当前位置: 首页 > 文档资料 > Kubernetes 指南 >

2.2 主要概念 - Pod

优质
小牛编辑
128浏览
2023-12-01

Pod 是一组紧密关联的容器集合,它们共享 IPC、Network 和 UTS namespace,是 Kubernetes 调度的基本单位。Pod 的设计理念是支持多个容器在一个 Pod 中共享网络和文件系统,可以通过进程间通信和文件共享这种简单高效的方式组合完成服务。

pod

Pod 的特征

  • 包含多个共享 IPC、Network 和 UTC namespace 的容器,可直接通过 localhost 通信
  • 所有 Pod 内容器都可以访问共享的 Volume,可以访问共享数据
  • 无容错性:直接创建的 Pod 一旦被调度后就跟 Node 绑定,即使 Node 挂掉也不会被重新调度(而是被自动删除),因此推荐使用 Deployment、Daemonset 等控制器来容错
  • 优雅终止:Pod 删除的时候先给其内的进程发送 SIGTERM,等待一段时间(grace period)后才强制停止依然还在运行的进程
  • 特权容器(通过 SecurityContext 配置)具有改变系统配置的权限(在网络插件中大量应用)

Kubernetes v1.8 还支持容器间共享 PID namespace,需要 docker >= 1.13.1,并配置 kubelet --docker-disable-shared-pid=false

Pod 定义

通过 yaml 或 json 描述 Pod 和其内 Container 的运行环境以及期望状态,比如一个最简单的 nginx pod 可以定义为

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: nginx
  5. labels:
  6. app: nginx
  7. spec:
  8. containers:
  9. - name: nginx
  10. image: nginx
  11. ports:
  12. - containerPort: 80

API 版本对照表

Kubernetes 版本Core API 版本默认开启
v1.5+core/v1

使用 Volume

Volume 可以为容器提供持久化存储,比如

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: redis
  5. spec:
  6. containers:
  7. - name: redis
  8. image: redis
  9. volumeMounts:
  10. - name: redis-storage
  11. mountPath: /data/redis
  12. volumes:
  13. - name: redis-storage
  14. emptyDir: {}

更多挂载存储卷的方法参考 Volume。

私有镜像

在使用私有镜像时,需要创建一个 docker registry secret,并在容器中引用。

创建 docker registry secret:

  1. kubectl create secret docker-registry regsecret --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>

容器中引用该 secret:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: private-reg
  5. spec:
  6. containers:
  7. - name: private-reg-container
  8. image: <your-private-image>
  9. imagePullSecrets:
  10. - name: regsecret

RestartPolicy

支持三种 RestartPolicy

  • Always:只要退出就重启
  • OnFailure:失败退出(exit code 不等于 0)时重启
  • Never:只要退出就不再重启

注意,这里的重启是指在 Pod 所在 Node 上面本地重启,并不会调度到其他 Node 上去。

环境变量

环境变量为容器提供了一些重要的资源,包括容器和 Pod 的基本信息以及集群中服务的信息等:

(1) hostname

HOSTNAME 环境变量保存了该 Pod 的 hostname。

(2)容器和 Pod 的基本信息

Pod 的名字、命名空间、IP 以及容器的计算资源限制等可以以 Downward API 的方式获取并存储到环境变量中。

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: test
  5. spec:
  6. containers:
  7. - name: test-container
  8. image: gcr.io/google_containers/busybox
  9. command: ["sh", "-c"]
  10. args:
  11. - env
  12. resources:
  13. requests:
  14. memory: "32Mi"
  15. cpu: "125m"
  16. limits:
  17. memory: "64Mi"
  18. cpu: "250m"
  19. env:
  20. - name: MY_NODE_NAME
  21. valueFrom:
  22. fieldRef:
  23. fieldPath: spec.nodeName
  24. - name: MY_POD_NAME
  25. valueFrom:
  26. fieldRef:
  27. fieldPath: metadata.name
  28. - name: MY_POD_NAMESPACE
  29. valueFrom:
  30. fieldRef:
  31. fieldPath: metadata.namespace
  32. - name: MY_POD_IP
  33. valueFrom:
  34. fieldRef:
  35. fieldPath: status.podIP
  36. - name: MY_POD_SERVICE_ACCOUNT
  37. valueFrom:
  38. fieldRef:
  39. fieldPath: spec.serviceAccountName
  40. - name: MY_CPU_REQUEST
  41. valueFrom:
  42. resourceFieldRef:
  43. containerName: test-container
  44. resource: requests.cpu
  45. - name: MY_CPU_LIMIT
  46. valueFrom:
  47. resourceFieldRef:
  48. containerName: test-container
  49. resource: limits.cpu
  50. - name: MY_MEM_REQUEST
  51. valueFrom:
  52. resourceFieldRef:
  53. containerName: test-container
  54. resource: requests.memory
  55. - name: MY_MEM_LIMIT
  56. valueFrom:
  57. resourceFieldRef:
  58. containerName: test-container
  59. resource: limits.memory
  60. restartPolicy: Never

(3) 集群中服务的信息

容器的环境变量中还可以引用容器运行前创建的所有服务的信息,比如默认的 kubernetes 服务对应以下环境变量:

  1. KUBERNETES_PORT_443_TCP_ADDR=10.0.0.1
  2. KUBERNETES_SERVICE_HOST=10.0.0.1
  3. KUBERNETES_SERVICE_PORT=443
  4. KUBERNETES_SERVICE_PORT_HTTPS=443
  5. KUBERNETES_PORT=tcp://10.0.0.1:443
  6. KUBERNETES_PORT_443_TCP=tcp://10.0.0.1:443
  7. KUBERNETES_PORT_443_TCP_PROTO=tcp
  8. KUBERNETES_PORT_443_TCP_PORT=443

由于环境变量存在创建顺序的局限性(环境变量中不包含后来创建的服务),推荐使用 DNS 来解析服务。

ImagePullPolicy

支持三种 ImagePullPolicy

  • Always:不管镜像是否存在都会进行一次拉取
  • Never:不管镜像是否存在都不会进行拉取
  • IfNotPresent:只有镜像不存在时,才会进行镜像拉取

注意:

  • 默认为 IfNotPresent,但 :latest 标签的镜像默认为 Always
  • 拉取镜像时 docker 会进行校验,如果镜像中的 MD5 码没有变,则不会拉取镜像数据。
  • 生产环境中应该尽量避免使用 :latest 标签,而开发环境中可以借助 :latest 标签自动拉取最新的镜像。

访问 DNS 的策略

通过设置 dnsPolicy 参数,设置 Pod 中容器访问 DNS 的策略

  • ClusterFirst:优先基于 cluster domain 后缀,通过 kube-dns 查询 (默认策略)
  • Default:优先从 kubelet 中配置的 DNS 查询

使用主机的 IPC 命名空间

通过设置 spec.hostIPC 参数为 true,使用主机的 IPC 命名空间,默认为 false。

使用主机的网络命名空间

通过设置 spec.hostNetwork 参数为 true,使用主机的网络命名空间,默认为 false。

使用主机的 PID 空间

通过设置 spec.hostPID 参数为 true,使用主机的 PID 命名空间,默认为 false。

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: busybox1
  5. labels:
  6. name: busybox
  7. spec:
  8. hostIPC: true
  9. hostPID: true
  10. hostNetwork: true
  11. containers:
  12. - image: busybox
  13. command:
  14. - sleep
  15. - "3600"
  16. name: busybox

设置 Pod 的 hostname

通过 spec.hostname 参数实现,如果未设置默认使用 metadata.name 参数的值作为 Pod 的 hostname。

设置 Pod 的子域名

通过 spec.subdomain 参数设置 Pod 的子域名,默认为空。

比如,指定 hostname 为 busybox-2 和 subdomain 为 default-subdomain,完整域名为 busybox-2.default-subdomain.default.svc.cluster.local,也可以简写为 busybox-2.default-subdomain.default

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: busybox2
  5. labels:
  6. name: busybox
  7. spec:
  8. hostname: busybox-2
  9. subdomain: default-subdomain
  10. containers:
  11. - image: busybox
  12. command:
  13. - sleep
  14. - "3600"
  15. name: busybox

注意:

  • 默认情况下,DNS 为 Pod 生成的 A 记录格式为 pod-ip-address.my-namespace.pod.cluster.local,如 1-2-3-4.default.pod.cluster.local
  • 上面的示例还需要在 default namespace 中创建一个名为 default-subdomain(即 subdomain)的 headless service,否则其他 Pod 无法通过完整域名访问到该 Pod(只能自己访问到自己)
  1. kind: Service
  2. apiVersion: v1
  3. metadata:
  4. name: default-subdomain
  5. spec:
  6. clusterIP: None
  7. selector:
  8. name: busybox
  9. ports:
  10. - name: foo # Actually, no port is needed.
  11. port: 1234
  12. targetPort: 1234

注意,必须为 headless service 设置至少一个服务端口(spec.ports,即便它看起来并不需要),否则 Pod 与 Pod 之间依然无法通过完整域名来访问。

资源限制

Kubernetes 通过 cgroups 限制容器的 CPU 和内存等计算资源,包括 requests(请求, 调度器保证调度到资源充足的 Node 上,如果无法满足会调度失败 )和 limits(上限)等:

  • spec.containers[].resources.limits.cpu:CPU 上限,可以短暂超过,容器也不会被停止
  • spec.containers[].resources.limits.memory:内存上限,不可以超过;如果超过,容器可能会被终止或调度到其他资源充足的机器上
  • spec.containers[].resources.requests.cpu:CPU 请求,也是调度 CPU 资源的依据,可以超过
  • spec.containers[].resources.requests.memory:内存请求,也是调度内存资源的依据,可以超过;但如果超过,容器可能会在 Node 内存不足时清理
  • spec.containers[].resources.limits.ephemeral-storage:临时存储的请求,调度容器存储的依据
  • spec.containers[].resources.requests.ephemeral-storage:临时存储的上限,超过后 Pod 会被驱逐

比如 nginx 容器请求 30% 的 CPU 和 56MB 的内存,但限制最多只用 50% 的 CPU 和 128MB 的内存:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. labels:
  5. app: nginx
  6. name: nginx
  7. spec:
  8. containers:
  9. - image: nginx
  10. name: nginx
  11. resources:
  12. requests:
  13. cpu: "300m"
  14. memory: "56Mi"
  15. limits:
  16. cpu: "1"
  17. memory: "128Mi"

注意

  • CPU 的单位是 CPU 个数,可以用 millicpu (m) 表示少于 1 个 CPU 的情况,如 500m = 500millicpu = 0.5cpu,而一个 CPU 相当于
    • AWS 上的一个 vCPU
    • GCP 上的一个 Core
    • Azure 上的一个 vCore
    • 物理机上开启超线程时的一个超线程
  • 内存的单位则包括 E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki 等。

健康检查

为了确保容器在部署后确实处在正常运行状态,Kubernetes 提供了两种探针(Probe)来探测容器的状态:

  • LivenessProbe:探测应用是否处于健康状态,如果不健康则删除并重新创建容器
  • ReadinessProbe:探测应用是否启动完成并且处于正常服务状态,如果不正常则不会接收来自 Kubernetes Service 的流量

Kubernetes 支持三种方式来执行探针:

  • exec:在容器中执行一个命令,如果 命令退出码 返回 0 则表示探测成功,否则表示失败
  • tcpSocket:对指定的容器 IP 及端口执行一个 TCP 检查,如果端口是开放的则表示探测成功,否则表示失败
  • httpGet:对指定的容器 IP、端口及路径执行一个 HTTP Get 请求,如果返回的 状态码[200,400) 之间则表示探测成功,否则表示失败
  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. labels:
  5. app: nginx
  6. name: nginx
  7. spec:
  8. containers:
  9. - image: nginx
  10. imagePullPolicy: Always
  11. name: http
  12. livenessProbe:
  13. httpGet:
  14. path: /
  15. port: 80
  16. httpHeaders:
  17. - name: X-Custom-Header
  18. value: Awesome
  19. initialDelaySeconds: 15
  20. timeoutSeconds: 1
  21. readinessProbe:
  22. exec:
  23. command:
  24. - cat
  25. - /usr/share/nginx/html/index.html
  26. initialDelaySeconds: 5
  27. timeoutSeconds: 1
  28. - name: goproxy
  29. image: gcr.io/google_containers/goproxy:0.1
  30. ports:
  31. - containerPort: 8080
  32. readinessProbe:
  33. tcpSocket:
  34. port: 8080
  35. initialDelaySeconds: 5
  36. periodSeconds: 10
  37. livenessProbe:
  38. tcpSocket:
  39. port: 8080
  40. initialDelaySeconds: 15
  41. periodSeconds: 20

Init Container

Pod 能够具有多个容器,应用运行在容器里面,但是它也可能有一个或多个先于应用容器启动的 Init 容器。Init 容器在所有容器运行之前执行(run-to-completion),常用来初始化配置。

如果为一个 Pod 指定了多个 Init 容器,那些容器会按顺序一次运行一个。 每个 Init 容器必须运行成功,下一个才能够运行。 当所有的 Init 容器运行完成时,Kubernetes 初始化 Pod 并像平常一样运行应用容器。

下面是一个 Init 容器的示例:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: init-demo
  5. spec:
  6. containers:
  7. - name: nginx
  8. image: nginx
  9. ports:
  10. - containerPort: 80
  11. volumeMounts:
  12. - name: workdir
  13. mountPath: /usr/share/nginx/html
  14. # These containers are run during pod initialization
  15. initContainers:
  16. - name: install
  17. image: busybox
  18. command:
  19. - wget
  20. - "-O"
  21. - "/work-dir/index.html"
  22. - http://kubernetes.io
  23. volumeMounts:
  24. - name: workdir
  25. mountPath: "/work-dir"
  26. dnsPolicy: Default
  27. volumes:
  28. - name: workdir
  29. emptyDir: {}

因为 Init 容器具有与应用容器分离的单独镜像,使用 init 容器启动相关代码具有如下优势:

  • 它们可以包含并运行实用工具,处于安全考虑,是不建议在应用容器镜像中包含这些实用工具的。
  • 它们可以包含使用工具和定制化代码来安装,但是不能出现在应用镜像中。例如,创建镜像没必要 FROM 另一个镜像,只需要在安装过程中使用类似 sed、 awk、 python 或 dig 这样的工具。
  • 应用镜像可以分离出创建和部署的角色,而没有必要联合它们构建一个单独的镜像。
  • 它们使用 Linux Namespace,所以对应用容器具有不同的文件系统视图。因此,它们能够具有访问 Secret 的权限,而应用容器不能够访问。
  • 它们在应用容器启动之前运行完成,然而应用容器并行运行,所以 Init 容器提供了一种简单的方式来阻塞或延迟应用容器的启动,直到满足了一组先决条件。

Init 容器的资源计算,选择一下两者的较大值:

  • 所有 Init 容器中的资源使用的最大值
  • Pod 中所有容器资源使用的总和

Init 容器的重启策略:

  • 如果 Init 容器执行失败,Pod 设置的 restartPolicy 为 Never,则 pod 将处于 fail 状态。否则 Pod 将一直重新执行每一个 Init 容器直到所有的 Init 容器都成功。
  • 如果 Pod 异常退出,重新拉取 Pod 后,Init 容器也会被重新执行。所以在 Init 容器中执行的任务,需要保证是幂等的。

容器生命周期钩子

容器生命周期钩子(Container Lifecycle Hooks)监听容器生命周期的特定事件,并在事件发生时执行已注册的回调函数。支持两种钩子:

  • postStart: 容器创建后立即执行,注意由于是异步执行,它无法保证一定在 ENTRYPOINT 之前运行。如果失败,容器会被杀死,并根据 RestartPolicy 决定是否重启
  • preStop:容器终止前执行,常用于资源清理。如果失败,容器同样也会被杀死

而钩子的回调函数支持两种方式:

  • exec:在容器内执行命令,如果命令的退出状态码是 0 表示执行成功,否则表示失败
  • httpGet:向指定 URL 发起 GET 请求,如果返回的 HTTP 状态码在 [200, 400) 之间表示请求成功,否则表示失败

postStart 和 preStop 钩子示例:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: lifecycle-demo
  5. spec:
  6. containers:
  7. - name: lifecycle-demo-container
  8. image: nginx
  9. lifecycle:
  10. postStart:
  11. httpGet:
  12. path: /
  13. port: 80
  14. preStop:
  15. exec:
  16. command: ["/usr/sbin/nginx","-s","quit"]

使用 Capabilities

默认情况下,容器都是以非特权容器的方式运行。比如,不能在容器中创建虚拟网卡、配置虚拟网络。

Kubernetes 提供了修改 Capabilities 的机制,可以按需要给容器增加或删除。比如下面的配置给容器增加了 CAP_NET_ADMIN 并删除了 CAP_KILL

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: cap-pod
  5. spec:
  6. containers:
  7. - name: friendly-container
  8. image: "alpine:3.4"
  9. command: ["/bin/sleep", "3600"]
  10. securityContext:
  11. capabilities:
  12. add:
  13. - NET_ADMIN
  14. drop:
  15. - KILL

限制网络带宽

可以通过给 Pod 增加 kubernetes.io/ingress-bandwidthkubernetes.io/egress-bandwidth 这两个 annotation 来限制 Pod 的网络带宽

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: qos
  5. annotations:
  6. kubernetes.io/ingress-bandwidth: 3M
  7. kubernetes.io/egress-bandwidth: 4M
  8. spec:
  9. containers:
  10. - name: iperf3
  11. image: networkstatic/iperf3
  12. command:
  13. - iperf3
  14. - -s

[warning] 仅 kubenet 支持限制带宽

目前只有 kubenet 网络插件支持限制网络带宽,其他 CNI 网络插件暂不支持这个功能。

kubenet 的网络带宽限制其实是通过 tc 来实现的

  1. # setup qdisc (only once)
  2. tc qdisc add dev cbr0 root handle 1: htb default 30
  3. # download rate
  4. tc class add dev cbr0 parent 1: classid 1:2 htb rate 3Mbit
  5. tc filter add dev cbr0 protocol ip parent 1:0 prio 1 u32 match ip dst 10.1.0.3/32 flowid 1:2
  6. # upload rate
  7. tc class add dev cbr0 parent 1: classid 1:3 htb rate 4Mbit
  8. tc filter add dev cbr0 protocol ip parent 1:0 prio 1 u32 match ip src 10.1.0.3/32 flowid 1:3

调度到指定的 Node 上

可以通过 nodeSelector、nodeAffinity、podAffinity 以及 Taints 和 tolerations 等来将 Pod 调度到需要的 Node 上。

也可以通过设置 nodeName 参数,将 Pod 调度到指定 node 节点上。

比如,使用 nodeSelector,首先给 Node 加上标签:

  1. kubectl label nodes <your-node-name> disktype=ssd

接着,指定该 Pod 只想运行在带有 disktype=ssd 标签的 Node 上:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: nginx
  5. labels:
  6. env: test
  7. spec:
  8. containers:
  9. - name: nginx
  10. image: nginx
  11. imagePullPolicy: IfNotPresent
  12. nodeSelector:
  13. disktype: ssd

nodeAffinity、podAffinity 以及 Taints 和 tolerations 等的使用方法请参考 调度器章节。

自定义 hosts

默认情况下,容器的 /etc/hosts 是 kubelet 自动生成的,并且仅包含 localhost 和 podName 等。不建议在容器内直接修改 /etc/hosts 文件,因为在 Pod 启动或重启时会被覆盖。

默认的 /etc/hosts 文件格式如下,其中 nginx-4217019353-fb2c5 是 podName:

  1. $ kubectl exec nginx-4217019353-fb2c5 -- cat /etc/hosts
  2. # Kubernetes-managed hosts file.
  3. 127.0.0.1 localhost
  4. ::1 localhost ip6-localhost ip6-loopback
  5. fe00::0 ip6-localnet
  6. fe00::0 ip6-mcastprefix
  7. fe00::1 ip6-allnodes
  8. fe00::2 ip6-allrouters
  9. 10.244.1.4 nginx-4217019353-fb2c5

从 v1.7 开始,可以通过 pod.Spec.HostAliases 来增加 hosts 内容,如

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: hostaliases-pod
  5. spec:
  6. hostAliases:
  7. - ip: "127.0.0.1"
  8. hostnames:
  9. - "foo.local"
  10. - "bar.local"
  11. - ip: "10.1.2.3"
  12. hostnames:
  13. - "foo.remote"
  14. - "bar.remote"
  15. containers:
  16. - name: cat-hosts
  17. image: busybox
  18. command:
  19. - cat
  20. args:
  21. - "/etc/hosts"
  1. $ kubectl logs hostaliases-pod
  2. # Kubernetes-managed hosts file.
  3. 127.0.0.1 localhost
  4. ::1 localhost ip6-localhost ip6-loopback
  5. fe00::0 ip6-localnet
  6. fe00::0 ip6-mcastprefix
  7. fe00::1 ip6-allnodes
  8. fe00::2 ip6-allrouters
  9. 10.244.1.5 hostaliases-pod
  10. 127.0.0.1 foo.local
  11. 127.0.0.1 bar.local
  12. 10.1.2.3 foo.remote
  13. 10.1.2.3 bar.remote

HugePages

v1.8 + 支持给容器分配 HugePages,资源格式为 hugepages-<size>(如 hugepages-2Mi)。使用前要配置

  • 开启 --feature-gates="HugePages=true"
  • 在所有 Node 上面预分配好 HugePage ,以便 Kubelet 统计所在 Node 的 HugePage 容量

使用示例

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. generateName: hugepages-volume-
  5. spec:
  6. containers:
  7. - image: fedora:latest
  8. command:
  9. - sleep
  10. - inf
  11. name: example
  12. volumeMounts:
  13. - mountPath: /hugepages
  14. name: hugepage
  15. resources:
  16. limits:
  17. hugepages-2Mi: 100Mi
  18. volumes:
  19. - name: hugepage
  20. emptyDir:
  21. medium: HugePages

注意事项

  • HugePage 资源的请求和限制必须相同
  • HugePage 以 Pod 级别隔离,未来可能会支持容器级的隔离
  • 基于 HugePage 的 EmptyDir 存储卷最多只能使用请求的 HugePage 内存
  • 使用 shmget()SHM_HUGETLB 选项时,应用必须运行在匹配 proc/sys/vm/hugetlb_shm_group 的用户组(supplemental group)中

优先级

从 v1.9 开始,可以为 Pod 设置一个优先级(alpha),保证高优先级的 Pod 优先调度。

优先级调度功能还在 Alpha 版,使用前需要开启:

  • --feature-gates=PodPriority=true
  • --runtime-config=scheduling.k8s.io/v1alpha1=true --admission-control=Controller-Foo,Controller-Bar,...,Priority

为 Pod 设置优先级前,先创建一个 PriorityClass,并设置优先级(数值越大优先级越高):

  1. apiVersion: scheduling.k8s.io/v1alpha1
  2. kind: PriorityClass
  3. metadata:
  4. name: high-priority
  5. value: 1000000
  6. globalDefault: false
  7. description: "This priority class should be used for XYZ service pods only."

为 Pod 指定优先级

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: nginx
  5. labels:
  6. env: test
  7. spec:
  8. containers:
  9. - name: nginx
  10. image: nginx
  11. imagePullPolicy: IfNotPresent
  12. priorityClassName: high-priority

当调度队列有多个 Pod 需要调度时,优先调度高优先级的 Pod。而当高优先级的 Pod 无法调度时,Kubernetes 会尝试先删除低优先级的 Pod 再将其调度到对应 Node 上(Preemption)。

注意:受限于 Kubernetes 的调度策略,抢占并不总是成功。

PodDisruptionBudget

PodDisruptionBudget (PDB) 用来保证一组 Pod 同时运行的数量,这些 Pod 需要使用 Deployment、ReplicationController、ReplicaSet 或者 StatefulSet 管理。

  1. apiVersion: policy/v1beta1
  2. kind: PodDisruptionBudget
  3. metadata:
  4. name: zk-pdb
  5. spec:
  6. maxUnavailable: 1
  7. selector:
  8. matchLabels:
  9. app: zookeeper

参考文档