Kubernetes:Pod总结(一)
官方文档详尽介绍了Pod的概念。
概念
Pods are the smallest deployable units of computing that you can create and manage in Kubernetes.
简单来讲,Pod 是一组(也可以为一个)container 的集合,这些 container 一起调度,视为一个基本单元。
可以通过示例test-pod.yml
,简单了解Pod:
1 | apiVersion: v1 |
创建:
1 | kubectl create -f test-pod.yml |
查看日志:
1 | [root@master-1 ~]# kubectl logs myapp-pod |
这是一个非常简单的 Pod 样例。它的主要字段解释如下:
- apiVersion/kind:这是所有资源共有的基本字段,表示 api 版本号以及类型。
- apiVersion:表示资源所属于的 group 以及 version。结构一般为
<group/<version>
,其中 v1 是特例,其 group 为 “”, 省去了中间的/
。一般核心的资源都是 v1,比如Namespace / Pod / ConfigMap
等。其它的资源各有各自的 group 以及 version。 - kind:资源类型,开头大写。
- apiVersion:表示资源所属于的 group 以及 version。结构一般为
- metadata
- name:该 pod 的名字。
- labels:pod 的标签。
- namespace:可选字段。Kubernetes 中的资源分为两类,一类属于 namespace,一类不属于。Pod 属于 namespace,如果 yaml 里没有写 namespace,表示属于
default namespace
。
- spec:pod 的主要信息部分。
- containers:一个列表,因为可以有包含多个 container。
- name:这个 container 的名字,一个 pod 下面的多个 container 名字不能冲突。
- image:这个 container 的镜像信息。
- command:启动命令。是可选项,因为一般镜像都有默认值。
You can use workload resources to create and manage multiple Pods for you. A controller for the resource handles replication and rollout and automatic healing in case of Pod failure. For example, if a Node fails, a controller notices that Pods on that Node have stopped working and creates a replacement Pod. The scheduler places the replacement Pod onto a healthy Node.
当然,很少在 Kubernetes 中直接创建一个个的 Pod,甚至是单实例(Singleton)的 Pod。 这是因为 Pod 被设计成了相对临时性的、用后即抛的一次性实体。 当 Pod 由你或者间接地由 控制器 创建时,它被调度在集群中的节点上运行。 Pod 会保持在该节点上运行,直到 Pod 结束执行、Pod 对象被删除、Pod 因资源不足而被 驱逐 或者节点失效为止。
重启 Pod 中的容器不应与重启 Pod 混淆。 Pod 不是进程,而是容器运行的环境。 在被删除之前,Pod 会一直存在。
在实际的使用中,直接用 Pod 是不适合的,因为必然会产生单点故障。我们需要有一种方法来方便地创建、管理同一个服务的多个实例 Pod。Kubernetes 中引入了 Workload 的概念,它可以理解为 Pod 的父资源,主要的作用就是来管理多个 Pod 的生命周期。
Workload 主要分为以下几类:
- Deployment 和 ReplicaSet:最常见的类型。广泛适用于多种业务场景。
- DaemonSet:在集群的每个节点上部署一个 Pod,适用于各种 agent 业务的场景。
- StatefulSet:适用于各种有状态服务的场景。
- Job 和 CronJob: 用于一些自动化任务。
有状态服务:需要数据存储功能的服务,例如MySQL。
Pod基础结构
必选参数
1 | # pod的最基础的yaml文件最少需要以下的几个参数 |
标签和注释
1 | # 放在metadata中 |
容器
常用参数
1 | spec: |
资源配合
如果一个容器只指明limit而未设定request,则request的值等于limit值
requests申请范围是0到node节点的最大配置,而limits申请范围是requests到无限,即0 <= requests <=Node Allocatable, requests <= limits <= Infinity。CPU超过limits时,pod不会被kill,只会被限制。但是内存超过时,就会被kernel视为内存溢出(OOM)kill掉。
1 | # 资源和请求的设置 |
健康检查
健康检查有三种方式分别是
- 脚本或命令
- httpGet
- tcp检测
1 | livenessProbe: # 如果探测失败会重启容器 |
存储卷
1 | spec: |
重启调度
1 | spec: |
Pod生命周期
Pod 遵循一个预定义的生命周期,起始于 Pending
阶段,如果至少 其中有一个主要容器正常启动,则进入 Running
,之后取决于 Pod 中是否有容器以 失败状态结束而进入 Succeeded
或者 Failed
阶段。
Pod 的 status
字段是一个 PodStatus对象,其中包含一个 phase
字段。
Pod 的阶段(Phase)是 Pod 在其生命周期中所处位置的简单宏观概述。 该阶段并不是对容器或 Pod 状态的综合汇总,也不是为了成为完整的状态机。
Pod 阶段的数量和含义是严格定义的。 除了本文档中列举的内容外,不应该再假定 Pod 有其他的 phase
值。
下面是 phase
可能的值:
取值 | 描述 |
---|---|
Pending (悬决) |
Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间。若一直处于pending 状态,可参考之前的文章排查。 |
Running (运行中) |
Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。 |
Succeeded (成功) |
Pod 中的所有容器都已成功终止,并且不会再重启。 |
Failed (失败) |
Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。 |
Unknown (未知) |
因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。 |
如果某节点死掉或者与集群中其他节点失联,Kubernetes 会实施一种策略,将失去的节点上运行的所有 Pod 的 phase
设置为 Failed
。
一旦调度器将 Pod 分派给某个节点,kubelet
就通过 容器运行时开始为 Pod 创建容器。 容器的状态有三种:Waiting
(等待)、Running
(运行中)和 Terminated
(已终止)。
Pod 拓扑分布约束
在 v1.18 之前的 Kubernetes 版本中,如果要使用 Pod 拓扑扩展约束,必须在 API 服务器 和调度器 中启用
EvenPodsSpread
特性门控。EvenPodsSpread
:使 Pod 能够在拓扑域之间平衡调度。
通过拓扑分布约束(Topology Spread Constraints),可控制在集群内故障域之间的分布,例如区域(Region)、可用区(Zone)、节点和其他用户自定义拓扑域,以实现高可用并提升资源利用率。
示例
查看并配置节点标签:
1 | [root@master-1 tmp]# kubectl get nodes --show-labels |
新建Deployment:
1 | apiVersion: apps/v1 |
创建:
1 | [root@master-1 test]# kubectl create -f nginx.yml |
可见两个Pod分布到同一个节点。
配置分布约束:
1 | apiVersion: apps/v1 |
说明:
- maxSkew 描述 Pod 分布不均的程度。这是给定拓扑类型中任意两个拓扑域中 匹配的 pod 之间的最大允许差值。它必须大于零。取决于 whenUnsatisfiable 的 取值,其语义会有不同。
- 当 whenUnsatisfiable 等于 “DoNotSchedule” 时,maxSkew 是目标拓扑域 中匹配的 Pod 数与全局最小值之间可存在的差异。
- 当 whenUnsatisfiable 等于 “ScheduleAnyway” 时,调度器会更为偏向能够降低 偏差值的拓扑域。
- topologyKey 是节点标签的键。如果两个节点使用此键标记并且具有相同的标签值, 则调度器会将这两个节点视为处于同一拓扑域中。调度器试图在每个拓扑域中放置数量 均衡的 Pod。
- whenUnsatisfiable 指示如果 Pod 不满足分布约束时如何处理:
- DoNotSchedule(默认)告诉调度器不要调度。
- ScheduleAnyway 告诉调度器仍然继续调度,只是根据如何能将偏差最小化来对 节点进行排序。
- labelSelector 用于查找匹配的 pod。匹配此标签的 Pod 将被统计,以确定相应 拓扑域中 Pod 的数量。
查看pod已分别调度到不同的node:
1 | [root@master-1 test]# kubectl get pod -o wide |