Pod
Pod 是在 Kubernetes 中可以创建和管理的最小的可部署计算单元。
Pod(如鲸鱼荚或豌豆荚)是一组一个或多个容器,它们共享存储和网络资源,以及如何运行容器的规范。Pod 的内容始终位于同一位置并协同调度,并在共享上下文中运行。Pod 模拟特定于应用程序的“逻辑主机”:它包含一个或多个应用程序容器,这些容器相对紧密耦合。在非云环境中,在同一台物理或虚拟机上执行的应用程序类似于在同一台逻辑主机上执行的云应用程序。
除了应用程序容器之外,Pod 还包含初始化容器,这些容器在 Pod 启动期间运行。您还可以注入临时容器 来调试正在运行的 Pod。
什么是 Pod?
注意
您需要在集群中的每个节点上安装容器运行时,以便 Pod 可以在那里运行。Pod 的共享上下文是一组 Linux 命名空间、cgroups,以及可能的其他隔离方面——与隔离容器 相同的事物。在 Pod 的上下文中,各个应用程序可能已应用了进一步的子隔离。
Pod 类似于一组具有共享命名空间和共享文件系统卷的容器。
Kubernetes 集群中的 Pod 主要用于以下两种方式
运行单个容器的 Pod。 “每个 Pod 一个容器”模型是最常见的 Kubernetes 使用案例;在这种情况下,您可以将 Pod 视为单个容器的包装器;Kubernetes 管理 Pod 而不是直接管理容器。
运行多个需要协同工作的容器的 Pod。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 也是如此。相反,请使用工作负载资源(例如部署 或作业)来创建它们。如果您的 Pod 需要跟踪状态,请考虑StatefulSet 资源。
每个 Pod 旨在运行给定应用程序的单个实例。如果您想水平扩展您的应用程序(通过运行更多实例来提供更多整体资源),您应该使用多个 Pod,每个实例一个。在 Kubernetes 中,这通常被称为复制。复制的 Pod 通常由工作负载资源及其控制器作为一个组创建和管理。
有关 Kubernetes 如何使用工作负载资源及其控制器来实现应用程序扩展和自动修复的更多信息,请参见Pod 和控制器。
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.31 中,.spec.os.name
的值不会影响kube-scheduler 如何为 Pod 选择一个节点运行。在任何存在多个操作系统用于运行节点的集群中,您应该在每个节点上正确设置kubernetes.io/os 标签,并根据操作系统标签定义 Pod 带有 nodeSelector
。kube-scheduler 根据其他条件将您的 pod 分配到节点,并且可能成功或可能不成功地选择合适的节点放置,其中节点操作系统适合该 Pod 中的容器。 Pod 安全标准 也使用此字段来避免执行与操作系统无关的策略。
Pod 和控制器
您可以使用工作负载资源为您创建和管理多个 Pod。该资源的控制器负责在 Pod 发生故障时处理复制、推出和自动修复。例如,如果节点发生故障,控制器会注意到该节点上的 Pod 已停止工作,并创建一个替换 Pod。调度程序将替换 Pod 放置到健康节点上。
以下是管理一个或多个 Pod 的工作负载资源的一些示例
Pod 模板
用于工作负载 资源的控制器从Pod 模板创建 Pod,并代表您管理这些 Pod。
PodTemplate 是用于创建 Pod 的规范,包含在工作负载资源中,例如部署、作业 和守护程序集。
用于工作负载资源的每个控制器都使用工作负载对象中的 PodTemplate
来创建实际的 Pod。PodTemplate
是您用于运行应用程序的任何工作负载资源的所需状态的一部分。
当您创建 Pod 时,您可以在 Pod 模板中包含环境变量,用于在 Pod 中运行的容器。
以下示例是一个简单作业的清单,其中包含一个启动一个容器的 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 的容器可以使用 localhost
相互通信。当 Pod 中的容器与 Pod **外部** 的实体通信时,它们必须协调如何使用共享网络资源(例如端口)。在 Pod 内,容器共享一个 IP 地址和端口空间,并且可以通过 localhost
互相找到。Pod 中的容器还可以使用标准的进程间通信(如 SystemV 信号量或 POSIX 共享内存)相互通信。不同 Pod 中的容器具有不同的 IP 地址,并且如果没有特殊配置,则无法通过 OS 级别的 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 由控制平面管理(例如,部署),而对于静态 Pod,kubelet 直接监督每个静态 Pod(如果它失败则重新启动它)。
静态 Pod 始终绑定到特定节点上的一个 Kubelet。静态 Pod 的主要用途是运行自托管控制平面:换句话说,使用 kubelet 监督各个 控制平面组件。
kubelet 会自动尝试在 Kubernetes API 服务器上为每个静态 Pod 创建一个 镜像 Pod。这意味着在节点上运行的 Pod 在 API 服务器上可见,但无法从那里控制。有关更多信息,请参阅指南 创建静态 Pod。
包含多个容器的 Pod
Pod 旨在支持多个协作进程(作为容器),这些进程构成一个连贯的服务单元。Pod 中的容器会自动位于群集中的同一台物理机或虚拟机上,并进行共同调度。容器可以共享资源和依赖项、相互通信以及协调何时以及如何终止。
Kubernetes 集群中的 Pod 主要用于以下两种方式
- 运行单个容器的 Pod。 “每个 Pod 一个容器”模型是最常见的 Kubernetes 使用案例;在这种情况下,您可以将 Pod 视为单个容器的包装器;Kubernetes 管理 Pod 而不是直接管理容器。
- 运行多个需要协同工作的容器的 Pod。Pod 可以封装一个由多个紧密耦合且需要共享资源的协同定位容器组成的应用程序。这些协同定位容器构成一个连贯的服务单元,例如,一个容器为存储在共享卷中的数据提供公共服务,而另一个单独的 边车容器 刷新或更新这些文件。Pod 将这些容器、存储资源和短暂的网络身份包装在一起,形成一个单一单元。
例如,您可能有一个充当共享卷中文件的 Web 服务器的容器,以及一个单独的 边车容器 从远程源更新这些文件,如下图所示
一些 Pod 除了 初始化容器 之外,还具有 应用程序容器。默认情况下,初始化容器在应用程序容器启动之前运行并完成。
您还可以拥有 边车容器,这些容器为主要应用程序 Pod 提供辅助服务(例如:服务网格)。
Kubernetes v1.29 [beta]
默认情况下启用,SidecarContainers
功能网关 允许您为初始化容器指定 restartPolicy: Always
。设置 Always
重启策略确保将您设置了它的容器视为在 Pod 的整个生命周期内保持运行的边车。您显式定义为边车容器的容器会在主应用程序 Pod 启动之前启动,并一直运行到 Pod 关闭为止。
容器探测
探测 是 kubelet 定期对容器执行的诊断。要执行诊断,kubelet 可以调用不同的操作
ExecAction
(在容器运行时的帮助下执行)TCPSocketAction
(由 kubelet 直接检查)HTTPGetAction
(由 kubelet 直接检查)
您可以在 Pod 生命周期文档中阅读有关 探测 的更多信息。
下一步
- 了解有关 Pod 生命周期 的信息。
- 了解有关 RuntimeClass 的信息,以及如何使用它为不同的 Pod 配置不同的容器运行时配置。
- 阅读有关 PodDisruptionBudget 的信息,以及如何使用它在中断期间管理应用程序可用性。
- Pod 是 Kubernetes REST API 中的顶级资源。 Pod 对象定义详细描述了该对象。
- 分布式系统工具包:复合容器模式 解释了包含多个容器的 Pod 的常见布局。
- 阅读有关 Pod 拓扑传播约束 的信息
要了解 Kubernetes 将常见的 Pod API 封装在其他资源(例如 StatefulSet 或 Deployment)中的原因,您可以阅读有关先前技术的相关信息,包括