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 可以封装由多个协同定位的容器组成的应用程序,这些容器紧密耦合并且需要共享资源。这些协同定位的容器形成一个单一的凝聚单元。
在单个 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,每个实例一个 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.32 中,.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 的容器可以使用 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 规范的 securityContext 中的windowsOptions.hostProcess
标志,以类似的特权模式运行 Windows 容器。有关详细信息和说明,请参阅创建 Windows HostProcess Pod。- 要了解您可以使用的内核级安全约束,请参阅Pod 和容器的 Linux 内核安全约束。
- 要了解有关 Pod 安全上下文的更多信息,请参阅为 Pod 或容器配置安全上下文。
静态 Pod
静态 Pod 由特定节点上的 kubelet 守护程序直接管理,而API 服务器不会观察它们。大多数 Pod 由控制平面管理(例如,Deployment),而对于静态 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 包装在其他资源(例如StatefulSets 或 Deployments)中,你可以阅读之前的技术,包括