容器组

Pod 是您可以在 Kubernetes 中创建和管理的、可部署的最小计算单元。

一个 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 的示例,它包含一个运行镜像 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 也不例外。相反,可以使用工作负载资源(例如 DeploymentJob)来创建它们。如果你的 Pod 需要跟踪状态,请考虑使用 StatefulSet 资源。

每个 Pod 都旨在运行给定应用程序的单个实例。如果你想横向伸缩应用程序(通过运行更多实例来提供更多总体资源),你应该使用多个 Pod,每个实例一个。在 Kubernetes 中,这通常被称为 replication(副本)。复制的 Pod 通常由工作负载资源及其控制器作为一个组来创建和管理。

有关 Kubernetes 如何使用工作负载资源及其控制器来实现应用程序伸缩和自动修复的更多信息,请参阅Pod 和控制器

Pod 原生为构成它们的容器提供两种共享资源:网络存储

使用 Pod

在 Kubernetes 中,你很少会直接创建单个 Pod,即使是单例 Pod 也是如此。这是因为 Pod 被设计为相对短暂、可一次性使用的实体。当创建 Pod 时(由你直接创建,或由控制器间接创建),新的 Pod 会被调度到集群中的一个Node 上运行。Pod 会一直保留在该节点上,直到 Pod 执行完毕、Pod 对象被删除、Pod 因资源不足被 驱逐(evicted),或者节点发生故障。

Pod 的名称必须是有效的DNS 子域名值,但这可能会对 Pod 主机名产生意外结果。为了获得最佳兼容性,名称应遵循更严格的DNS 标签规则。

Pod 操作系统

特性状态: Kubernetes v1.25 [stable]

你应该将 .spec.os.name 字段设置为 windowslinux,以指明 Pod 期望运行在哪个操作系统上。目前 Kubernetes 只支持这两种操作系统。将来,此列表可能会扩展。

在 Kubernetes v1.33 中,.spec.os.name 的值不影响kube-scheduler 为 Pod 选择运行节点的机制。在任何存在多个运行节点操作系统的集群中,你应该在每个节点上正确设置 kubernetes.io/os 标签,并使用基于操作系统标签的 nodeSelector 来定义 Pod。kube-scheduler 会根据其他标准为你的 Pod 分配节点,可能成功也可能无法选择一个适合该 Pod 中容器的节点操作系统位置。Pod 安全标准也使用此字段来避免强制执行与特定操作系统无关的策略。

Pod 和控制器

你可以使用工作负载资源来为你创建和管理多个 Pod。资源的控制器负责处理 Pod 失败时的副本、发布和自动修复。例如,如果一个 Node 发生故障,控制器会注意到该 Node 上的 Pod 已停止工作,并创建一个替代的 Pod。调度器会将替代 Pod 放置到健康的 Node 上。

以下是一些管理一个或多个 Pod 的工作负载资源的示例

Pod 模板

工作负载资源的控制器会根据 pod 模板创建 Pod,并代表你管理这些 Pod。

Pod 模板是创建 Pod 的规范,它们包含在工作负载资源中,例如DeploymentsJobsDaemonSets

每个工作负载资源的控制器都使用工作负载对象中的 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 基础教程中的更新策略

在 Node 上,kubelet 不会直接观察或管理与 Pod 模板和更新相关的任何细节;这些细节都被抽象化了。这种抽象和关注点分离简化了系统语义,使得在不更改现有代码的情况下扩展集群行为成为可能。

Pod 更新和替换

正如前文所述,当工作负载资源的 Pod 模板发生更改时,控制器会根据更新后的模板创建新的 Pod,而不是更新或修补现有 Pod。

Kubernetes 并不阻止你直接管理 Pod。可以原地更新运行中 Pod 的一些字段。但是,诸如 patchreplace 之类的 Pod 更新操作存在一些限制

  • 关于 Pod 的大部分元数据是不可变的。例如,你不能更改 namespacenameuidcreationTimestamp 字段。

    • generation 字段是唯一的。系统会自动设置它,新 Pod 的 generation 为 1,并且 Pod 规约中可变字段的每次更新都会使 generation 增加 1。如果 Alpha 特性门控 PodObservedGenerationTracking 已设置,则 Pod 的 status.observedGeneration 将反映 Pod 状态被报告时的 metadata.generation
  • 如果设置了 metadata.deletionTimestamp,则不能向 metadata.finalizers 列表中添加新条目。

  • Pod 更新不能更改 spec.containers[*].imagespec.initContainers[*].imagespec.activeDeadlineSecondsspec.tolerations 以外的字段。对于 spec.tolerations,只能添加新条目。

  • 更新 spec.activeDeadlineSeconds 字段时,允许进行两种类型的更新

    1. 将未赋值的字段设置为正数;
    2. 将字段从正数更新为较小的非负数。

Pod 子资源

上述更新规则适用于常规的 Pod 更新,但其他 Pod 字段可以通过 子资源进行更新。

  • Resize(伸缩): resize 子资源允许更新容器资源(spec.containers[*].resources)。有关详细信息,请参阅伸缩容器资源
  • Ephemeral Containers(临时容器): ephemeralContainers 子资源允许向 Pod 添加临时容器。有关详细信息,请参阅临时容器
  • Status(状态): status 子资源允许更新 Pod 状态。这通常仅由 Kubelet 和其他系统控制器使用。
  • Binding(绑定): binding 子资源允许通过 Binding 请求设置 Pod 的 spec.nodeName。这通常仅由调度器使用。

资源共享和通信

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 运行。

Static Pod

Static Pod 由特定节点上的 kubelet 守护进程直接管理,而API server 不会观察它们。大多数 Pod 由控制平面管理(例如,Deployment),而对于 Static Pod,kubelet 会直接监管每个 Static Pod(并在其失败时重启)。

Static Pod 总是绑定到特定节点上的一个Kubelet。Static Pod 的主要用途是运行自托管的控制平面:换句话说,使用 kubelet 来监管单个控制平面组件

kubelet 会自动尝试在 Kubernetes API Server 上为每个 Static Pod 创建一个镜像 Pod。这意味着在节点上运行的 Pod 在 API Server 上可见,但无法从那里控制。有关更多信息,请参阅指南创建 Static Pod

具有多个容器的 Pod

Pod 被设计为支持多个协作进程(作为容器),这些进程构成了一个内聚的服务单元。Pod 中的容器会自动共同位于集群中同一物理机或虚拟机上,并共同调度。容器可以共享资源和依赖关系,相互通信,并协调它们的终止时间和方式。

Kubernetes 集群中的 Pod 主要以两种方式使用

  • 运行单个容器的 Pod。“每个 Pod 一个容器”的模型是 Kubernetes 最常见的用例;在这种情况下,你可以将 Pod 视为单个容器的包装;Kubernetes 管理 Pod,而不是直接管理容器。
  • 运行多个需要协同工作的容器的 Pod。Pod 可以封装一个由多个共同位于同一位置的容器组成的应用程序,这些容器紧密耦合并且需要共享资源。这些共同位于同一位置的容器构成一个单一的内聚服务单元——例如,一个容器向公众提供存储在共享卷中的数据,而另一个独立的sidecar 容器负责刷新或更新这些文件。Pod 将这些容器、存储资源和临时网络身份一起包装成一个单一单元。

例如,你可能有一个容器作为共享卷中文件的 Web 服务器,还有一个单独的sidecar 容器负责从远程源更新这些文件,如下图所示

Pod creation diagram

一些 Pod 包含初始化容器应用容器。默认情况下,初始化容器在应用容器启动之前运行并完成。

你还可以拥有sidecar 容器,它们为主应用程序 Pod 提供辅助服务(例如:服务网格)。

特性状态: Kubernetes v1.33 [stable] (默认启用:true)

SidecarContainers 特性门控默认启用,它允许你为初始化容器指定 restartPolicy: Always。将重启策略设置为 Always 可确保你设置为此值的容器被视为在 Pod 的整个生命周期内保持运行的 sidecars。你显式定义为 sidecar 容器的容器会在主应用程序 Pod 启动之前启动,并一直运行直到 Pod 关闭。

容器探针

探针(probe) 是 kubelet 定期对容器执行的诊断。为了执行诊断,kubelet 可以调用不同的动作

  • ExecAction(在容器运行时帮助下执行)
  • TCPSocketAction(由 kubelet 直接检查)
  • HTTPGetAction(由 kubelet 直接检查)

你可以在 Pod 生命周期文档中阅读有关探针的更多信息。

接下来

要理解 Kubernetes 为何将通用的 Pod API 封装在其他资源中(例如 StatefulSetsDeployments)的背景,你可以阅读相关的先行技术,包括

最后修改于 2025 年 4 月 7 日 上午 9:46 PST: Update InPlacePodVerticalScaling docs for v1.33 beta (#50290) (c014f72fbb)