1-Kubernetes基本概念
K8S概述
Kubernetes 是一个可移植、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。
部署演进
容器类似于 VM,但是更宽松的隔离特性,使容器之间可以共享操作系统(OS)。 因此,容器比起 VM 被认为是更轻量级的。且与 VM 类似,每个容器都具有自己的文件系统、CPU、内存、进程空间等。 由于它们与基础架构分离,因此可以跨云和 OS 发行版本进行移植。
K8s优点:
- 敏捷应用程序的创建和部署:与使用 VM 镜像相比,提高了容器镜像创建的简便性和效率。
- 持续开发、集成和部署:通过快速简单的回滚(由于镜像不可变性), 提供可靠且频繁的容器镜像构建和部署。
- 关注开发与运维的分离:在构建、发布时创建应用程序容器镜像,而不是在部署时, 从而将应用程序与基础架构分离。
- 可观察性:不仅可以显示 OS 级别的信息和指标,还可以显示应用程序的运行状况和其他指标信号。
- 跨开发、测试和生产的环境一致性:在笔记本计算机上也可以和在云中运行一样的应用程序。
- 跨云和操作系统发行版本的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、 Google Kubernetes Engine 和其他任何地方运行。
- 以应用程序为中心的管理:提高抽象级别,从在虚拟硬件上运行 OS 到使用逻辑资源在 OS 上运行应用程序。
- 松散耦合、分布式、弹性、解放的微服务:应用程序被分解成较小的独立部分, 并且可以动态部署和管理 - 而不是在一台大型单机上整体运行。
- 资源隔离:可预测的应用程序性能。
- 资源利用:高效率和高密度。
k8s可以提供什么
- 服务发现和负载均衡
Kubernetes 可以使用 DNS 名称或自己的 IP 地址来暴露容器。 如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定 - 存储编排
Kubernetes 允许自动挂载你选择的存储系统,例如本地存储、公共云提供商等。 - 自动部署和回滚
使用 Kubernetes 描述已部署容器的所需状态, 它可以以受控的速率将实际状态更改为期望状态。 例如,你可以自动化 Kubernetes 来为你的部署创建新容器, 删除现有容器并将它们的所有资源用于新容器。 - 自动完成装箱计算
为 Kubernetes 提供许多节点组成的集群,在这个集群上运行容器化的任务。 你告诉 Kubernetes 每个容器需要多少 CPU 和内存 (RAM)。 Kubernetes 可以将这些容器按实际情况调度到你的节点上,以最佳方式利用你的资源。 - 自我修复
Kubernetes 将重新启动失败的容器、替换容器、杀死不响应用户定义的运行状况检查的容器, 并且在准备好服务之前不将其通告给客户端。 - 密钥与配置管理
Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 SSH 密钥。 你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。 - 批处理执行
除了服务外,Kubernetes 还可以管理你的批处理和 CI(持续集成)工作负载,如有需要,可以替换失败的容器。 - 水平扩缩
使用简单的命令、用户界面或根据 CPU 使用率自动对你的应用进行扩缩。 - IPv4/IPv6 双栈
为 Pod(容器组)和 Service(服务)分配 IPv4 和 IPv6 地址。 - 为可扩展性设计
在不改变上游源代码的情况下为你的 Kubernetes 集群添加功能。
k8s核心组件
k8s是由控制平面和一个或者多个工作节点组成。
控制面组件
- kube-apiserver:提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制。
- etcd:存储系统,APIserver将请求的数据存储到etcd中
- kube-scheduler:负责资源的调度,按照预定的调度策略将 Pod 调度到相应的节点上。
- kube-controller-manager:运行控制器来实现k8s API的行为,例如故障检测、自动扩展和滚动更新。
- cloud-controller-manager:通过云提供商的 API 管理云平台上的集群。
工作节点组件
- kubelet:是工作节点上运行的代理,它确保容器在 Pod 中运行。kubelet 接收一组通过各类机制提供给它的 PodSpecs,并确保这些 PodSpecs 中描述的容器处于运行状态且健康。
- kube-proxy:在节点上运行的网络代理,实现 Kubernetes 服务(Service) 概念的一部分。kube-proxy 维护节点上的一些网络规则,这些网络规则允许从集群内部或外部访问 Pod 中运行的服务。
- 容器运行时:负责运行容器。
k8s对象
Kubernetes 对象就像是你在 Kubernetes 集群中写的一张“任务清单”。你通过创建这些对象来告诉 Kubernetes:
- 你想运行什么应用(比如一个网站或数据库)。
- 这些应用需要多少资源(比如 CPU 和内存)。
- 这些应用应该怎么运行(比如出错时自动重启,或者如何更新)。
当创建了一个对象时,Kubernetes 会记住你写的“任务清单”(也就是你期望的状态)。然后,Kubernetes 会不断检查集群的实际状态,确保它和你写的“任务清单”一致。任务清单中包含spec(规约,希望对象所具有的期望状态)。status描述了对象的当前状态,k8s会不断检查实际情况,并更新status,使其与spec一致。
清单中的必须字段:
- apiVersion - 创建该对象所使用的 Kubernetes API 的版本
- kind - 想要创建的对象的类别
- metadata - 帮助唯一标识对象的一些数据,包括一个 name 字符串、UID 和可选的 namespace
- spec - 你所期望的该对象的状态
对于不同的对象,spec 部分的内容会有所不同。详细查看官网Kubernetes API 参考
对象管理
特性 | 指令式命令 | 指令式对象配置 | 声明式对象配置 |
---|---|---|---|
操作方式 | 直接运行命令操作资源。 | 通过 YAML 文件明确指定操作(创建、更新、删除)。 | 通过 YAML 文件描述期望状态,Kubernetes 自动处理。 |
命令示例 | kubectl run/create/delete | kubectl create/replace/delete -f | kubectl apply -f |
是否需要 | YAML 文件 | 不需要。 | 需要。 |
适用场景 | 快速测试、临时操作。 | 简单操作、临时测试。 | 生产环境、持续管理。 |
幂等性 | 不是幂等的(多次运行可能导致错误)。 | 不是幂等的(多次运行可能导致错误)。 | 幂等的(多次运行结果一致)。 |
变更管理 | 需要手动处理变更。 | 需要手动处理变更。 | Kubernetes 自动处理变更。 |
对象名称和ID
名称: 在同一个命名空间中,每一个对象都有一个名称来标识在同类资源中的唯一性,不同类型的资源可以同名。
UID: 在集群中全局唯一,用来区分同一个命名空间中的不同对象。
- Kubernetes 资源的唯一性由 API 组、资源类型、名字空间 和 名称 决定。
- API 版本 不会影响资源的唯一性。
- 删除资源后,可以创建同名的新对象。
- 在同一资源类型和名字空间中,名称必须是唯一的。
namespace
Namespace 是 Kubernetes 中用于将资源逻辑分组和隔离的机制。它可以将一个物理集群划分为多个虚拟集群,每个 Namespace 中的资源名称是唯一的,但不同 Namespace 中的资源可以重名。Kubernetes 控制面会为所有名字空间设置一个不可变更的标签 kubernetes.io/metadata.name
。 标签的值是名字空间的名称。
Namespace 的作用:
- 资源隔离:将不同的项目、团队或环境(如开发、测试、生产)的资源隔离开。
- 权限控制:通过 RBAC(基于角色的访问控制)为不同的 Namespace 设置不同的权限。
- 资源管理:可以为每个 Namespace 设置资源配额(Resource Quota),限制其资源使用量。
default | 如果没有指定 Namespace,资源会默认创建到这里。 |
kube-system | 存放 Kubernetes 系统组件的资源(如 kube-proxy、CoreDNS 等)。 |
kube-public | 存放公共资源,通常对所有用户可见。 |
kube-node-lease | 用于节点心跳机制,与节点健康检查相关。 |
1 | # 列出所有命名空间 |
标签与注解
标签是附加到 Kubernetes 对象(如 Pod、Service、Node 等)上的键值对(key-value pairs)。用于标识和选择对象,通常用于筛选、分组或关联资源。
1 | # 标签示例 |
注解也是附加到 Kubernetes 对象上的键值对,但它用于存储非标识性的元数据,注解通常用于存储额外的信息,如配置、说明、工具链信息等。
1 | metadata: |
特性 | 标签(Labels) | 注解(Annotations) |
---|---|---|
用途 | 用于标识和选择资源。 | 用于存储非标识性的元数据。 |
键值对长度 | 较短,通常用于快速识别。 | 可以较长,适合存储详细信息。 |
是否可用于选择器 | 是,可以通过选择器筛选资源。 | 否,不能用于筛选资源。 |
示例 | app: my-app, env: prod | description: “Production frontend” |
使用场景 | 资源分组、服务选择、节点调度。 | 存储构建信息、工具链集成、说明文档。 |
字段选择器
字段选择器(Field Selector)是 Kubernetes 中用于根据资源的字段值筛选资源的一种机制。它允许你通过指定资源的特定字段值来过滤资源。
1 | #使用字段选择器筛选资源 |
finalizers终结器
- Finalizers 是 Kubernetes 中一种用于控制资源删除行为的机制。存储在资源的 metadata.finalizers 字段中。本质上就是一个 标记,用于告诉 Kubernetes:“这个资源还不能删除,需要先完成某些操作”。这个标记的添加和移除是由你自定义的逻辑控制的,通常通过编写控制器或外部系统来完成。逻辑上就是在删除这个资源时暂时不能删除,要等完成一些自定义的操作后,删除finalizers标记,然后才能删除资源。
- Finalizers 的主要作用是确保在删除资源之前,完成一些必要的清理操作。
- 什么是属主和附属?
在 Kubernetes 中,属主(Owner) 和 附属(Dependent) 是一种资源之间的从属关系。属主资源拥有一个或多个附属资源,Kubernetes 通过这种关系来管理资源的生命周期。
- 属主(Owner):通常是更高级别的资源,例如 Deployment、StatefulSet、ReplicaSet 等。
- 附属(Dependent):通常是由属主创建或管理的资源,例如 Pod。
- 属主和附属的关系
属主和附属之间的关系通过资源的 metadata.ownerReferences 字段来定义。每个附属资源都会在其metadata.ownerReferences
字段中记录其属主资源的信息。
示例:一个由 Deployment 创建的 Pod 的 metadata.ownerReferences 字段可能如下所示:1
2
3
4
5
6
7
8复制
metadata:
ownerReferences:
- apiVersion: apps/v1
kind: Deployment
name: my-deployment
uid: 12345678-1234-1234-1234-123456789012
controller: true - 属主和附属的作用
属主和附属的关系在 Kubernetes 中有以下作用:
- 生命周期管理
当属主资源被删除时,Kubernetes 会自动删除其所有附属资源。
例如,删除一个 Deployment 时,Kubernetes 会自动删除由该 Deployment 创建的所有 Pod。 - 垃圾回收
Kubernetes 的垃圾回收器(Garbage Collector)会检查资源的 metadata.ownerReferences 字段。如果属主资源被删除,垃圾回收器会自动删除所有附属资源。 - 资源关联
通过属主和附属的关系,可以清晰地表示资源之间的依赖关系。
例如,一个 Service 可以通过标签选择器关联到由 Deployment 创建的 Pod。\
属主关系与 Finalizer
属主关系与 Finalizer 的作用
属主关系和 Finalizer 都是 Kubernetes 中用于管理资源生命周期的机制,但它们的作用不同:
属主关系:用于表示资源之间的从属关系(如 Deployment 和 Pod),并控制资源的级联删除。
Finalizer:用于在删除资源之前执行清理操作,防止资源被意外删除。级联删除与 Finalizer
Kubernetes 支持两种级联删除策略:前台删除(Foreground) 和 后台删除(Background)。在前台删除中,Kubernetes 会为属主资源添加 Finalizer,以确保删除顺序。
前台删除(Foreground):先删除附属资源,再删除属主资源。
Kubernetes 会为属主资源添加foreground
Finalizer。
控制器必须删除所有ownerReferences.blockOwnerDeletion=true
的附属资源后,才能删除属主资源。
这种策略确保属主资源在删除之前,所有依赖它的附属资源都被清理。kubectl delete deployment my-deployment --cascade=foreground
后台删除(Background):立即删除属主资源,然后异步删除附属资源。默认的删除方式
Kubernetes 会立即删除属主资源,然后由垃圾回收器异步删除附属资源。
这种策略不会为属主资源添加 Finalizer。孤立删除(Orphan)
Kubernetes 会为属主资源添加orphan
Finalizer。
删除属主资源后,附属资源会被保留,不再被属主资源管理。kubectl delete deployment my-deployment --cascade=orphan
至于为什么属主添加了orphan
Finalizer还是会被删除,是因为这个 Finalizer 的作用是告诉 Kubernetes:“在删除属主资源之前,先解除它与附属资源(如 Pod)的属主关系”。也就是执行这条命令的流程:属主添加 orphan Finalizer–>解除属主关系(将附属metadata.ownerReferences
字段中指向属主资源的条目移除)–>删除属主资源。