Pod 是可以在 Kubernetes 中创建和管理的最小可部署计算单元。
Pod(就像鲸鱼群或豌豆荚一样)是一组一个或多个容器,具有共享存储和网络资源,以及运行容器的规约。Pod 的内容始终被共处(co-located)和共调度(co-scheduled),并在共享的上下文中运行。Pod 对特定于应用程序的“逻辑主机”进行建模:它包含一个或多个相对紧密耦合的应用容器。在非云环境中,在同一物理机或虚拟机上执行的应用程序类似于在同一逻辑主机上执行的云应用程序。
除了应用容器外,Pod 还可以包含在 Pod 启动期间运行的初始化容器。您还可以注入临时容器来调试正在运行的 Pod。
Pod 的共享上下文是一组 Linux 命名空间(namespaces)、cgroups 以及可能的其他隔离层面——这些也是隔离容器的内容。在 Pod 的上下文中,各个应用程序可能会应用进一步的子隔离。
Pod 类似于一组具有共享命名空间和共享文件系统卷的容器。
Kubernetes 集群中的 Pod 主要以两种方式使用
运行单个容器的 Pod。“每个 Pod 一个容器”模型是 Kubernetes 最常见的用例;在这种情况下,您可以将 Pod 视为单个容器的包装器;Kubernetes 管理 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 也是如此。相反,请使用Deployment 或 Job 等工作负载资源来创建它们。如果您的 Pod 需要跟踪状态,请考虑 StatefulSet 资源。
每个 Pod 都旨在运行给定应用程序的单个实例。如果您想水平扩展应用程序(通过运行更多实例来提供更多总体资源),您应该使用多个 Pod,每个实例一个。在 Kubernetes 中,这通常被称为副本(Replication)。副本 Pod 通常由工作负载资源及其控制器作为一个组创建和管理。
有关 Kubernetes 如何使用工作负载资源及其控制器来实现应用程序扩缩容和自动修复的更多信息,请参阅Pod 和控制器。
您在 Kubernetes 中几乎不会直接创建单个 Pod——即使是单例 Pod 也是如此。这是因为 Pod 设计为相对短暂、可丢弃的实体。当创建 Pod 时(由您直接创建,或由控制器间接创建),新的 Pod 会被调度到集群中的一个节点上运行。Pod 会一直留在该节点上,直到 Pod 执行完成、Pod 对象被删除、Pod 因资源不足被驱逐,或者节点失败。
Pod 的名称必须是有效的 DNS 子域名值,但这可能会为 Pod 主机名产生意外结果。为了获得最佳兼容性,名称应遵循更严格的 DNS 标签规则。
Kubernetes v1.25 [稳定]您应该将 .spec.os.name 字段设置为 windows 或 linux,以指明您希望 Pod 在其上运行的操作系统。这两种是目前 Kubernetes 支持的唯一操作系统。将来,此列表可能会扩展。
在 Kubernetes v1.36 中,.spec.os.name 的值不会影响 kube-scheduler 如何选择 Pod 运行的节点。在任何拥有多个操作系统节点运行的集群中,您都应该在每个节点上正确设置 kubernetes.io/os 标签,并使用基于操作系统标签的 nodeSelector 来定义 Pod。kube-scheduler 会根据其他标准将您的 Pod 分配给节点,可能无法成功选择一个节点操作系统适合 Pod 中容器的合适节点放置位置。Pod 安全标准也使用此字段来避免强制执行与操作系统无关的策略。
您可以使用工作负载资源为您创建和管理多个 Pod。该资源的控制器会处理副本、发布和自动修复(以防 Pod 失败)。例如,如果某个节点失败,控制器会注意到该节点上的 Pod 已停止工作,并创建替换 Pod。调度程序会将替换 Pod 放置到健康的节点上。
以下是一些管理一个或多个 Pod 的工作负载资源示例
Kubernetes v1.35 [alpha](默认禁用)默认情况下,Kubernetes 会单独调度每个 Pod。但是,一些紧密耦合的应用程序需要一组 Pod 同时被调度才能正常工作。
您可以使用调度组字段 (spec.schedulingGroup) 将 Pod 链接到 PodGroup。这告诉 kube-scheduler 该 Pod 属于特定组,使其能够一次性对整个组应用协调的组级放置决策。
工作负载资源的控制器从 Pod 模板创建 Pod,并代表您管理这些 Pod。
PodTemplates 是用于创建 Pod 的规约,包含在 Deployments、Jobs 和 DaemonSets 等工作负载资源中。
工作负载资源的每个控制器都使用工作负载对象内部的 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。
Kubernetes 不会阻止您直接管理 Pod。可以在原地更新正在运行的 Pod 的某些字段。但是,诸如 patch 和 replace 之类的 Pod 更新操作有一些限制
关于 Pod 的大多数元数据都是不可变的。例如,您不能更改 namespace、name、uid 或 creationTimestamp 字段。
如果设置了 metadata.deletionTimestamp,则不能向 metadata.finalizers 列表中添加新条目。
Pod 更新不能更改 spec.containers[*].image、spec.initContainers[*].image、spec.activeDeadlineSeconds、spec.terminationGracePeriodSeconds、spec.tolerations 或 spec.schedulingGates 以外的字段。对于 spec.tolerations,您只能添加新条目。
更新 spec.activeDeadlineSeconds 字段时,允许两种类型的更新
上述更新规则适用于常规 Pod 更新,但其他 Pod 字段可以通过子资源进行更新。
resize 子资源允许更新容器资源 (spec.containers[*].resources)。有关更多详细信息,请参阅调整容器资源大小。ephemeralContainers 子资源允许将临时容器添加到 Pod。有关更多详细信息,请参阅临时容器。status 子资源允许更新 Pod 状态。这通常仅由 Kubelet 和其他系统控制器使用。binding 子资源允许通过 Binding 请求设置 Pod 的 spec.nodeName。这通常仅由调度程序使用。metadata.generation 字段是唯一的。它将由系统自动设置,以便新 Pod 的 metadata.generation 为 1,并且对 Pod 规约中可变字段的每次更新都会使 metadata.generation 递增 1。Kubernetes v1.35 [stable](默认启用)observedGeneration 是 Pod 对象 status 部分中捕获的一个字段。Kubelet 将设置 status.observedGeneration 以跟踪 Pod 状态到当前的 Pod 状态。Pod 的 status.observedGeneration 将反映在报告 Pod 状态时该 Pod 的 metadata.generation。status.observedGeneration 字段由 Kubelet 管理,外部控制器不应修改此字段。不同的状态字段可能与当前同步循环的 metadata.generation 相关联,也可能与上一个同步循环的 metadata.generation 相关联。关键区别在于 spec 中的更改是直接反映在 status 中,还是运行过程的间接结果。
对于直接反映已分配规约的状态字段,observedGeneration 将与当前的 metadata.generation(第 N 代)相关联。
此行为适用于
Waiting 状态时。对于作为运行规约的间接结果的状态字段,observedGeneration 将与上一个同步循环的 metadata.generation(第 N-1 代)相关联。
此行为适用于
ContainerStatus.ImageID 反映的是前一代的镜像,直到新镜像被拉取且容器被更新。Pod 实现了其包含容器之间的数据共享和通信。
Pod 可以指定一组共享存储卷。Pod 中的所有容器都可以访问共享卷,从而允许这些容器共享数据。卷还允许 Pod 中的持久数据在其中一个容器需要重启时存活。有关 Kubernetes 如何实现共享存储并使其可供 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 规约中的 securityContext 字段。此字段使您可以精细控制 Pod 或单个容器可以执行的操作。有关更多详细信息,请参阅高级 Pod 配置。
对于基本的安全配置,您应该符合基线 Pod 安全标准,并以非 root 用户身份运行容器。您可以设置简单的安全上下文
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
containers:
- name: sec-ctx-demo
image: busybox
command: ["sh", "-c", "sleep 1h"]
有关包括能力(capabilities)、seccomp 配置文件和详细安全选项在内的高级安全上下文配置,请参阅安全概念部分。
指定 Pod 时,您可以选择指定容器需要多少每种资源。最常见的资源是 CPU 和内存(RAM)。
当您为 Pod 中的容器指定资源请求时,kube-scheduler 会使用此信息来决定将 Pod 放置在哪个节点上。当您为容器指定资源限制时,kubelet 会强制执行这些限制,以便运行中的容器不能使用超过您设置限制的资源。
CPU 限制由 CPU 节流强制执行。当容器接近其 CPU 限制时,内核会限制其对 CPU 的访问。内存限制由内核在容器超出其限制时执行内存不足 (OOM) 杀掉(kill)来强制执行。
有关资源单位、强制行为和配置示例的详细信息,请参阅针对 Pod 和容器的资源管理。
静态 Pod 直接由特定节点上的 kubelet 守护进程管理,而无需 API server 观察它们。虽然大多数 Pod 是由控制平面(例如,Deployment)管理的,但对于静态 Pod,kubelet 直接监督每个静态 Pod(并在其失败时重启它)。
静态 Pod 始终绑定到特定节点上的一个 Kubelet。静态 Pod 的主要用途是运行自托管的控制平面:换句话说,使用 kubelet 来监督各个控制平面组件。
kubelet 会自动尝试为每个静态 Pod 在 Kubernetes API server 上创建一个镜像 Pod。这意味着节点上运行的 Pod 在 API server 上是可见的,但不能从那里进行控制。有关更多信息,请参阅指南创建静态 Pod。
Pod 旨在支持作为内聚服务单元的多个协作进程(作为容器)。Pod 中的容器会自动在集群中的同一物理机或虚拟机上共处和共调度。容器可以共享资源和依赖项、相互通信,并协调终止的时间和方式。
Kubernetes 集群中的 Pod 主要以两种方式使用
例如,您可能拥有一个充当共享卷中文件 Web 服务器的容器,以及一个从远程源更新这些文件的单独边车容器,如下图所示
有些 Pod 既有初始化容器,也有应用容器。默认情况下,初始化容器在应用容器启动之前运行并完成。
您还可以拥有为主要应用程序 Pod 提供辅助服务的边车容器(例如:服务网格)。
Kubernetes v1.33 [stable](默认启用)默认启用的 SidecarContainers 功能门控允许您为初始化容器指定 restartPolicy: Always。设置 Always 重启策略可确保设置了该策略的容器被视为边车(Sidecars),并在 Pod 的整个生命周期内保持运行。您明确定义为边车容器的容器会在主应用程序 Pod 之前启动,并保持运行直到 Pod 关闭。
探针(Probe)是 kubelet 对容器定期执行的诊断。为了执行诊断,kubelet 可以调用不同的动作
ExecAction(在容器运行时帮助下执行)TCPSocketAction(由 kubelet 直接检查)HTTPGetAction(由 kubelet 直接检查)您可以在 Pod 生命周期文档中阅读有关探针的更多信息。
要了解 Kubernetes 为何在其他资源(如 StatefulSets 或 Deployments)中封装通用 Pod API 的背景,您可以阅读先验技术,包括