字面含义是如图所示的豌豆,在 k8s 中用这个名字形象的表示若干个关系紧密的、共享一定资源的容器集合(1个或者多个)。
pod 在 k8s 中的示意图:
关于 pod 有如下理解:
- pod 是 k8s 项目的原子调度单位,也就是说 k8s 的调度器是按照 pod 而不是容器的资源需求来进行调度的
- pod 只是一个逻辑概念,并不存在所谓的 pod 的边界或者隔离环境(虽然在概念上我们可以认为存在)
- k8s 引入 pod 的概念目的是:
- 通过成“组”的概念能比较好的表达真实世界里的进程之间的亲密关系,并且在这种情况下资源调度也会成“组”调度
- 容器设计模式,典型的比如 sidecar 模式(可以在一个 Pod 中,启动一个辅助容器,来完成一些独立于主进程(主容器)之外的工作)
- pod 里的所有容器,共享同一个 Network Namespace,并且可以共享同一个 Volume
- 在 k8s 中,pod 中会先创建一个 Infra 容器,而用户定义的其他的容器 Join 到 Infra 容器的 Network Namepace
- pod 里的容器可直接使用 localhost 通信
- 一个 pod 只有一个 IP 地址
- pod 的生命周期只和 Infra 容器一致,与用户容器无关
- 某种角度看,pod 实际是类似传统基础设施里“虚拟机”的角色;而容器则是这个虚拟机里运行的用户程序(这种理解对于迁移基于传统虚拟机的应用非常重要,要摒弃同一个容器里放多个进程,仔细分析应用程序的关系,来决定是否/哪些容器放到哪些 pod 里)
- pod 中的所有 Init Container 定义的容器会按顺序逐一启动,而直到它们都启动并且退出了,用户容器才会启动
pod 的资源配置(cpu & memory)
在 k8s 中,资源分为两类:
- 可压缩资源(compressible resources):当可压缩资源不足时,Pod 只会“饥饿”,但不会退出。比如 cpu
- 不可压缩资源(incompressible resources):当不可压缩资源不足时,Pod 会被迫退出。比如 memory,当不足时就会因为 OOM(Out-Of-Memory)被内核杀掉
pod 是 k8s 的最小的原子调度单元,其中包含的一个或者多个 container 可以分别设置 resource,比如:
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
pod 整体的资源配置,就由这些 Container 的配置值累加得到。k8s 在调度时根据这个累加值中的 request 部分决定,在最终执行时由 kubelet 根据 limit 值设置 cgroup。
几个注意小项:
- cpu 建议使用单位 m,比如:500m 表示半个 cpu 的能力,不建议写成 0.5,因为 k8s 内部通用就是这种整数表达方式。
- memory 的单位,建议带 i,因为带 i 的是表示基于 1024 计算的,不带 i 是基于 1000 计算的,比如:1Mi=10241024;1M=10001000
关于资源 QoS
Guaranteed: 当 pod 里的每个 container 都同时设置了资源的 request 和 limit,并且 request 值等于 limit 值
// 每个 container 都符合这种配置模式时 resources: limits: memory: "500Mi" cpu: "700m" requests: memory: "500Mi" cpu: "700m"
Burstable:当 Pod 不满足 Guaranteed 的条件,但至少有一个 Container 设置了 requests 时
resources: limits memory: "200Mi" requests: memory: "100Mi"
Besteffort:当 Pod 既没有设置 requests,也没有设置 limits 时
QoS 的目的,是当宿主机资源紧张的时候,kubelet 对 Pod 进行 Eviction(即资源回收)时需要用到的。
k8s 设置了 Eviction 的默认值,也可以通过 kubelet 进行显式的设置,比如:
kubelet --eviction-hard=imagefs.available<10%,memory.available<500Mi,nodefs.available<5%,nodefs.inodesFree<5% --eviction-soft=imagefs.available<30%,nodefs.available<10% --eviction-soft-grace-period=imagefs.available=2m,nodefs.available=2m --eviction-max-pod-grace-period=600
注意 Eviction 在 k8s 里其实分为 Soft 和 Hard 两种模式。
- Soft Eviction:可以为 Eviction 设置一段“优雅时间”,表示达到阈值不立即驱逐,而是经过“优雅时间”后才驱逐
- Hard Eviction:达到阈值了就开始驱逐
驱逐 pod 的顺序是:优先 Qos Besteffort,然后 Burstable 的,最后才是 Guaranteed。
当宿主机的 Eviction 阈值达到后,就会进入 MemoryPressure 或者 DiskPressure 状态,从而避免新的 Pod 被调度到这台宿主机上。
cpuset
通过设置 cpuset 可以把容器绑定到某个 CPU 的核上,而不是像 cpushare 那样共享 CPU 的计算能力,这样可以减少 cpu 上下文切换,提升性能。只需要同时满足下面两个条件,就能设置使用 cpuset:
- pod 的 QoS 是 Guaranteed 的
- Pod 的 CPU 资源的 requests 和 limits 设置为同一个相等的整数值
resources: limits: memory: "500Mi" cpu: "2" requests: memory: "500Mi" cpu: "2"
该 Pod 会被绑定在 2 个独占的 CPU 核上。由 kubelet 决定到底是哪两个 CPU 核。