Pod

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

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

Pod 操作系统

特性状态: Kubernetes v1.25 [稳定]

您应该将 .spec.os.name 字段设置为 windowslinux,以指示您希望 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 更新操作,例如 patchreplace 有一些限制。

  • 关于 Pod 的大多数元数据是不可变的。例如,您不能更改 namespacenameuidcreationTimestamp 字段;generation 字段是唯一的。它只接受将字段的当前值递增的更新。

  • 如果设置了 metadata.deletionTimestamp,则不能在 metadata.finalizers 列表中添加新条目。

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

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

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

资源共享和通信

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

静态 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 creation diagram

一些 Pod 除了 初始化容器 之外,还具有 应用程序容器。默认情况下,初始化容器在应用程序容器启动之前运行并完成。

您还可以拥有 边车容器,这些容器为主要应用程序 Pod 提供辅助服务(例如:服务网格)。

功能状态: Kubernetes v1.29 [beta]

默认情况下启用,SidecarContainers 功能网关 允许您为初始化容器指定 restartPolicy: Always。设置 Always 重启策略确保将您设置了它的容器视为在 Pod 的整个生命周期内保持运行的边车。您显式定义为边车容器的容器会在主应用程序 Pod 启动之前启动,并一直运行到 Pod 关闭为止。

容器探测

探测 是 kubelet 定期对容器执行的诊断。要执行诊断,kubelet 可以调用不同的操作

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

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

下一步

要了解 Kubernetes 将常见的 Pod API 封装在其他资源(例如 StatefulSetDeployment)中的原因,您可以阅读有关先前技术的相关信息,包括

上次修改时间:2024 年 7 月 29 日下午 10:20 PST: 更新 _index.md - 修复了语法错误的句子 (493c0169ed)