Pod
Pod 是您可以在 Kubernetes 中创建和管理的最小可部署计算单元。
Pod(就像鲸鱼荚或豌豆荚)是一组一个或多个容器,它们共享存储和网络资源,并指定如何运行容器。Pod 的内容始终位于同一位置并共同调度,并在共享上下文中运行。Pod 对特定于应用程序的“逻辑主机”进行建模:它包含一个或多个相对紧密耦合的应用程序容器。在非云环境中,在同一物理机或虚拟机上执行的应用程序类似于在同一逻辑主机上执行的云应用程序。
除了应用程序容器之外,Pod 还可以包含初始化容器,这些容器在 Pod 启动期间运行。您还可以注入临时容器来调试正在运行的 Pod。
什么是 Pod?
注意
您需要在集群中的每个节点上安装容器运行时,以便 Pod 可以在那里运行。Pod 的共享上下文是一组 Linux 命名空间、cgroup 以及可能的其他隔离方面 - 与隔离容器相同。在 Pod 的上下文中,各个应用程序可能会应用进一步的子隔离。
Pod 类似于一组具有共享命名空间和共享文件系统卷的容器。
Kubernetes 集群中的 Pod 主要用于以下两种方式
运行单个容器的 Pod。“每个 Pod 一个容器”模型是最常见的 Kubernetes 用例;在这种情况下,您可以将 Pod 视为单个容器的包装器;Kubernetes 管理 Pod 而不是直接管理容器。
运行需要协同工作的多个容器的 Pod。Pod 可以封装由多个位于同一位置的容器组成的应用程序,这些容器紧密耦合并需要共享资源。这些位于同一位置的容器构成一个 cohesive 单元。
在单个 Pod 中对多个位于同一位置且共同管理的容器进行分组是一个相对高级的用例。您应该仅在容器紧密耦合的特定情况下使用此模式。
您不需要运行多个容器来提供复制(为了弹性或容量);如果您需要多个副本,请参阅工作负载管理。
使用 Pod
以下是一个 Pod 的示例,该 Pod 由运行映像 nginx:1.14.2
的容器组成。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
要创建上面显示的 Pod,请运行以下命令
kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml
Pod 通常不会直接创建,而是使用工作负载资源创建。有关如何将 Pod 与工作负载资源一起使用的更多信息,请参阅使用 Pod。
用于管理 Pod 的工作负载资源
通常,您不需要直接创建 Pod,即使是单例 Pod 也是如此。相反,请使用工作负载资源创建它们,例如Deployment 或Job。如果您的 Pod 需要跟踪状态,请考虑使用StatefulSet 资源。
每个 Pod 都旨在运行给定应用程序的单个实例。如果要水平扩展应用程序(通过运行更多实例来提供更多总体资源),则应使用多个 Pod,每个实例一个。在 Kubernetes 中,这通常称为复制。复制的 Pod 通常由工作负载资源及其控制器创建和管理为一个组。
有关 Kubernetes 如何使用工作负载资源及其控制器来实现应用程序扩展和自动修复的更多信息,请参阅Pod 和控制器。
使用 Pod
您很少会在 Kubernetes 中直接创建单个 Pod,即使是单例 Pod 也是如此。这是因为 Pod 被设计为相对短暂的、可丢弃的实体。当 Pod 被创建时(由您直接创建,或由控制器间接创建),新的 Pod 会被调度到集群中的节点上运行。Pod 会一直保留在该节点上,直到 Pod 执行完成、Pod 对象被删除、Pod 因缺乏资源而被驱逐,或者节点发生故障。
注意
重新启动 Pod 中的容器不应与重新启动 Pod 混淆。Pod 不是进程,而是运行容器的环境。Pod 会一直存在,直到被删除。Pod 的名称必须是有效的DNS 子域名值,但这可能会导致 Pod 主机名出现意外结果。为了获得最佳兼容性,名称应遵循DNS 标签的更严格规则。
Pod 操作系统
Kubernetes v1.25 [稳定]
您应该将 .spec.os.name
字段设置为 windows
或 linux
,以指示您希望 Pod 在哪个操作系统上运行。目前,Kubernetes 仅支持这两种操作系统。将来,此列表可能会扩展。
在 Kubernetes v1.30 中,.spec.os.name
的值不会影响kube-scheduler 如何选择 Pod 来运行节点。在任何运行节点的操作系统不止一个的集群中,您都应该在每个节点上正确设置kubernetes.io/os 标签,并使用基于操作系统标签的 nodeSelector
定义 Pod,kube-scheduler 会根据其他条件将您的 Pod 分配给一个节点,并且可能会也可能不会成功地选择一个合适的节点位置,其中节点操作系统适合该 Pod 中的容器。Pod 安全标准也使用此字段来避免实施与操作系统无关的策略。
Pod 和控制器
您可以使用工作负载资源为您创建和管理多个 Pod。资源的控制器处理复制和推出,以及在 Pod 发生故障时的自动修复。例如,如果一个节点发生故障,控制器会注意到该节点上的 Pod 已停止工作,并创建一个替换 Pod。调度器会将替换 Pod 放置到一个健康的节点上。
以下是一些管理一个或多个 Pod 的工作负载资源的示例
Pod 模板
工作负载 资源的控制器从Pod 模板创建 Pod,并代表您管理这些 Pod。
PodTemplate 是用于创建 Pod 的规范,包含在工作负载资源中,例如Deployment、Job 和DaemonSet。
工作负载资源的每个控制器都使用工作负载对象内的 PodTemplate
来创建实际的 Pod。PodTemplate
是您用来运行应用程序的任何工作负载资源的所需状态的一部分。
创建 Pod 时,您可以在 Pod 模板中为 Pod 中运行的容器包含环境变量。
下面的示例是一个简单 Job 的清单,其中包含一个启动一个容器的 template
。该 Pod 中的容器打印一条消息,然后暂停。
apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
# This is the pod template
spec:
containers:
- name: hello
image: busybox:1.28
command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
restartPolicy: OnFailure
# The pod template ends here
修改 Pod 模板或切换到新的 Pod 模板不会对已存在的 Pod 产生直接影响。如果您更改了工作负载资源的 Pod 模板,则该资源需要创建使用更新后的模板的替换 Pod。
例如,StatefulSet 控制器会确保运行的 Pod 与每个 StatefulSet 对象的当前 Pod 模板相匹配。如果您编辑 StatefulSet 以更改其 Pod 模板,则 StatefulSet 会开始根据更新后的模板创建新的 Pod。最终,所有旧的 Pod 都将被新的 Pod 替换,更新完成。
每个工作负载资源都实现了自己的规则来处理对 Pod 模板的更改。如果您想详细了解 StatefulSet,请阅读 StatefulSet 基础教程中的更新策略。
在节点上,kubelet 不会直接观察或管理有关 Pod 模板和更新的任何细节;这些细节已被抽象化。这种抽象和关注点分离简化了系统语义,并使得在不更改现有代码的情况下扩展集群行为成为可能。
Pod 更新和替换
如上一节所述,当工作负载资源的 Pod 模板发生更改时,控制器会根据更新后的模板创建新的 Pod,而不是更新或修补现有的 Pod。
Kubernetes 不会阻止您直接管理 Pod。可以就地更新正在运行的 Pod 的某些字段。但是,Pod 更新操作(如 patch
和 replace
)有一些限制
有关 Pod 的大多数元数据都是不可变的。例如,您不能更改
namespace
、name
、uid
或creationTimestamp
字段;generation
字段是唯一的。它只接受增加字段当前值的更新。如果设置了
metadata.deletionTimestamp
,则无法在metadata.finalizers
列表中添加新条目。Pod 更新可能不会更改
spec.containers[*].image
、spec.initContainers[*].image
、spec.activeDeadlineSeconds
或spec.tolerations
以外的字段。对于spec.tolerations
,您只能添加新条目。更新
spec.activeDeadlineSeconds
字段时,允许两种类型的更新- 将未分配的字段设置为正数;
- 将字段从正数更新为较小的非负数。
资源共享和通信
Pod 支持其组成容器之间的数据共享和通信。
Pod 中的存储
Pod 可以指定一组共享存储 卷。Pod 中的所有容器都可以访问共享卷,从而允许这些容器共享数据。卷还允许 Pod 中的持久数据在其中一个容器需要重新启动的情况下得以保留。有关 Kubernetes 如何实现共享存储并将其提供给 Pod 的更多信息,请参阅存储。
Pod 网络
每个 Pod 都为每个地址系列分配了一个唯一的 IP 地址。Pod 中的每个容器都共享网络命名空间,包括 IP 地址和网络端口。在 Pod 内部(并且仅限在 Pod 内部),属于该 Pod 的容器可以使用 localhost
相互通信。当 Pod 中的容器与 Pod 外部的实体通信时,它们必须协调如何使用共享网络资源(例如端口)。在 Pod 中,容器共享 IP 地址和端口空间,并且可以通过 localhost
找到彼此。Pod 中的容器还可以使用标准进程间通信(例如 SystemV 信号量或 POSIX 共享内存)相互通信。不同 Pod 中的容器具有不同的 IP 地址,并且如果没有特殊配置,则无法通过操作系统级 IPC 进行通信。想要与在不同 Pod 中运行的容器进行交互的容器可以使用 IP 网络进行通信。
Pod 中的容器将系统主机名视为与为 Pod 配置的 name
相同。在网络部分中有更多相关信息。
Pod 安全设置
要设置 Pod 和容器的安全约束,请使用 Pod 规范中的 securityContext
字段。此字段使您可以对 Pod 或单个容器可以执行的操作进行粒度控制。例如
- 删除特定的 Linux 功能以避免 CVE 的影响。
- 强制 Pod 中的所有进程都以非 root 用户或特定的用户或组 ID 运行。
- 设置特定的 seccomp 配置文件。
- 设置 Windows 安全选项,例如容器是否以 HostProcess 身份运行。
注意
您还可以使用 Pod securityContext 在 Linux 容器中启用特权模式。特权模式会覆盖 securityContext 中的许多其他安全设置。除非您无法通过使用 securityContext 中的其他字段授予等效权限,否则请避免使用此设置。在 Kubernetes 1.26 及更高版本中,您可以通过在 Pod 规范的安全上下文中设置windowsOptions.hostProcess
标志,以类似的特权模式运行 Windows 容器。有关详细信息和说明,请参阅创建 Windows HostProcess Pod。- 要了解您可以使用的内核级安全约束,请参阅Pod 和容器的 Linux 内核安全约束。
- 要详细了解 Pod 安全上下文,请参阅为 Pod 或容器配置安全上下文。
静态 Pod
静态 Pod 由特定节点上的 kubelet 守护程序直接管理,API 服务器不会观察它们。大多数 Pod 由控制平面管理(例如,Deployment),而对于静态 Pod,kubelet 直接监督每个静态 Pod(并在其失败时重新启动它)。
静态 Pod 始终绑定到特定节点上的一个 Kubelet。静态 Pod 的主要用途是运行自托管控制平面:换句话说,使用 kubelet 来监督各个控制平面组件。
kubelet 会自动尝试为每个静态 Pod 在 Kubernetes API 服务器上创建一个镜像 Pod。这意味着节点上运行的 Pod 在 API 服务器上可见,但无法从那里控制。有关更多信息,请参阅指南创建静态 Pod。
具有多个容器的 Pod
Pod 旨在支持多个协作进程(作为容器),这些进程构成一个内聚的服务单元。Pod 中的容器会在集群中的同一物理或虚拟机上自动共置和共同调度。容器可以共享资源和依赖项,相互通信,并协调何时以及如何终止。
Kubernetes 集群中的 Pod 主要用于以下两种方式
- 运行单个容器的 Pod。“每个 Pod 一个容器”模型是最常见的 Kubernetes 用例;在这种情况下,您可以将 Pod 视为单个容器的包装器;Kubernetes 管理 Pod 而不是直接管理容器。
- 运行需要协同工作的多个容器的 Pod。Pod 可以封装由多个共置容器组成的应用程序,这些容器紧密耦合并需要共享资源。这些共置容器构成一个内聚的服务单元,例如,一个容器将共享卷中存储的数据提供给公众,而另一个单独的sidecar 容器刷新或更新这些文件。Pod 将这些容器、存储资源和临时网络身份打包在一起,作为一个单元。
例如,您可能有一个容器充当共享卷中文件的 Web 服务器,而另一个单独的sidecar 容器从远程源更新这些文件,如下图所示
一些 Pod 既有init 容器,也有应用程序容器。默认情况下,init 容器会在应用程序容器启动之前运行并完成。
您还可以拥有为主要应用程序 Pod 提供辅助服务的sidecar 容器(例如:服务网格)。
Kubernetes v1.29 [beta]
默认情况下启用 SidecarContainers
功能门允许您为 init 容器指定 restartPolicy: Always
。设置 Always
重启策略可确保将设置了该策略的容器视为在 Pod 的整个生命周期中保持运行的sidecar。您明确定义为 sidecar 容器的容器会在主应用程序 Pod 之前启动,并在 Pod 关闭之前一直运行。
容器探针
探针是由 kubelet 定期对容器执行的诊断程序。为了执行诊断,kubelet 可以调用不同的操作
ExecAction
(在容器运行时的帮助下执行)TCPSocketAction
(由 kubelet 直接检查)HTTPGetAction
(由 kubelet 直接检查)
您可以在 Pod 生命周期文档中阅读有关探针的更多信息。
下一步
- 了解Pod 的生命周期。
- 了解RuntimeClass以及如何使用它为不同的 Pod 配置不同的容器运行时配置。
- 阅读有关PodDisruptionBudget以及如何使用它在中断期间管理应用程序可用性的信息。
- Pod 是 Kubernetes REST API 中的顶级资源。Pod对象定义详细描述了该对象。
- 分布式系统工具包:组合容器的模式解释了包含多个容器的 Pod 的常见布局。
- 阅读有关Pod 拓扑扩展约束的信息
要了解 Kubernetes 为什么将通用的 Pod API 包装在其他资源(例如StatefulSets或Deployments)中的上下文,您可以阅读有关先前技术的文章,包括