Kubernetes 系列【7】Pod(容器组)

📅 发布时间:2026/7/12 20:03:59
Kubernetes 系列【7】Pod(容器组) 文章目录1. 基本介绍1.1 是什么1.2 容器运行时1.3 共享上下文1.4 两种使用场景1.4.1 单容器1.4.2 多容器1.5 Pod 整体阶段五种状态1.6 容器的三种状态2. 基础使用2.1 创建2.2 指定操作系统2.3 使用控制器2.4 模板3. 进阶使用3.1 更新与重建3.1.1 可更新字段3.1.2 子资源专项变更3.1.3 版本计数3.2 资源共享与进程通信3.2.1 存储3.2.2 网络3.3 安全配置3.4 资源配额请求与限制3.5 静态 Pod3.6 容器探针1. 基本介绍Pod容器组是Kubernetes中最小的可调度计算单元一个Pod代表一组紧密耦合的容器。国内官方汉化统一译作容器组1.1 是什么英文单词Pod本义1豆荚一个豆荚里包裹好几颗豆子本义2鲸群一群鲸鱼结伴同行。K8s借用这个词来做比喻 一个Pod 一个封闭的荚壳内部包裹多个容器。Pod由一个或多个容器组成这些容器共享存储与网络资源同时拥有统一的运行配置。同一个Pod内的所有容器始终被调度到同一节点、协同运行处在同一个隔离上下文环境中。传统虚拟机场景中我们在一台Linux虚拟机上同时运行Nginx、日志采集程序、监控代理多个进程。这些进程共用同一IP、同一磁盘目录互相可以用localhost通信整机一起启停无法把其中某一个进程单独拆分到另一台机器。K8s云场景中Pod就等价于这一整台虚拟机称为逻辑主机。Pod内部多个容器对应虚拟机里的多个进程。它们共用一套网络、一套存储整体作为调度整体不能把容器拆开调度到不同节点。在Kuboard中的容器组菜单1.2 容器运行时集群内每个节点都必须预先安装容器运行时Pod 才能正常运行。Pod只是Kubernetes的API对象仅仅是一段配置描述本身不能直接运行程序。真正拉起镜像、创建隔离环境的是容器运行时containerd、CRI-O、docker。kubelet调用CRI接口依靠容器运行时去创建容器没有运行时Pod只会停留在Pending状态无法启动。1.3 共享上下文Pod的共享上下文由一组Linux命名空间、cgroups以及其他隔离机制构成和容器自身的隔离技术完全一致。在Pod的整体隔离环境内单个业务容器还可以再做一层子隔离。共享命名空间整个Pod共用网络命名空间、UTS主机名命名空间。所以多个容器共用同一个IP能够用localhost互相访问。PID、挂载、用户命名空间默认不共享每个容器内部依然相互隔离。CgroupsControl Groups控制组是Linux内核提供的资源管控技术用来把一组进程捆在一起限制它们最多能用多少CPU、内存、磁盘IO。Cgroups资源组同一个Pod下所有容器归属同一套CPU、内存限额可以整体限制资源。可以把Pod理解为一组共享命名空间与存储卷的容器集合。多个容器被打包进同一个网络环境并且共用数据卷。1.4 两种使用场景Kubernetes集群内的Pod主要有两种使用场景。只有互相强依赖、必须部署在一起的程序才放进同一个Pod。松耦合服务前端、后端、数据库必须分成多个独立Pod。1.4.1 单容器一个Pod只运行一个容器是最常用的部署模式。绝大多数微服务网关、后端服务、Redis、MySQL都采用该模式一个业务实例 一个 Pod 一个容器。1.4.2 多容器Pod可以封装一套由多个紧耦合容器组成的应用容器之间需要共享资源。同一Pod内的多个容器共同构成一个完整的服务单元。多个组件必须满足三个条件才能放到同一个Pod必须运行在同一台节点不能分开部署用网络与存储需要localhost互相调用生命周期完全绑定同时启动、同时销毁。多容器Pod仅用于紧耦合组件多用于主容器加边车辅助容器多个容器共享网络与存储整体不可拆分调度。例如你可能有一个容器为共享卷中的文件提供Web服务器支持以及一个单独的 边车Sidecar 容器负责从远端更新这些文件开启SidecarContainers特性门控后可以给初始化容器设置restartPolicy: Always。这类容器会作为常驻边车在Pod 整个生命周期持续运行先于主应用启动直到Pod销毁才退出常用于服务网格、日志采集等辅助组件。Pod内部多容器不能用来做水平扩容业务扩副本要新建多个独立Pod借助工作负载控制器完成伸缩与自愈。1.5 Pod 整体阶段五种状态每个Pod都有一个status状态对象里面有个phase字段用来简单标记Pod当前处在生命周期哪个阶段。这个阶段只是一个粗略大分类不会把容器所有细微状态都写进去也不是一套完整精细的状态流转规则。Pod整体阶段phase五种状态表Pod阶段通俗解释典型场景Pending 待启动集群已经接收Pod但容器还没准备好运行正在分配节点、拉取镜像、加载配置Running 运行中Pod已分配到机器容器全部创建完成至少一个容器正在工作业务正常对外提供服务、容器重启过程中Succeeded 执行成功所有容器全部正常跑完退出不会自动重启一次性定时任务、执行完就销毁的PodFailed 运行失败所有容器都停止至少一个容器异常退出且不自动重启程序报错崩溃、启动参数错误、资源不足无法运行Unknown 状态未知集群无法获取Pod状态信息Pod所在节点宕机、节点和集群断开通信平时敲kubectl看到的STATUS列比如CrashLoopBackOff、Terminating只是给人看的提示不等于 phase 阶段。phase是集群底层API标准字段二者要分清。示例NAMESPACE NAME READY STATUS RESTARTS AGE alessandras-namespace alessandras-pod 0/1 CrashLoopBackOff 200 2d9hCrashLoopBackOff容器反复启动失败不停崩溃重启TerminatingPod正在删除中Pod删除相关说明默认删除Pod会预留30秒优雅关闭时间加--force参数可强制立刻删除K8s 1.27规则删除Pod前会先标记为Succeeded/Failed再清理两种例外静态Pod、无finalizer强制删除的Pod节点失联宕机后该节点上所有Pod都会被标记为Failed。1.6 容器的三种状态除了Pod整体大阶段集群还会单独记录Pod里每一个容器的实时状态。可以配置容器生命周期钩子在容器启动、关闭前后执行自定义脚本。调度器把Pod分配到机器后kubelet会创建容器容器只有三种状态等待中、运行中、已终止。查看命令kubectl describe pod容器名。内部容器状态对照表容器状态通俗解释常见行为Waiting 等待中容器还没正式启动在做准备工作拉镜像、加载密钥Secret、等待资源Running 运行中容器正常稳定运行若配置postStart启动钩子钩子已执行完毕Terminated 已终止容器启动过之后正常结束或异常退出可查看退出码、终止原因、启停时间配置preStop停止钩子会先执行再终止2. 基础使用2.1 创建下面是一个Pod示例仅运行nginx:latest镜像apiVersion:v1kind:Podmetadata:name:nginxspec:containers:-name:nginximage:nginx:latestports:-containerPort:80执行创建命令kubectl apply-fsimple-pod.yaml查看集群内所有Pod确认是否运行kubectl get pods# 输出简化版显示名称、状态、重启次数、运行时长kubectl get pod nginx# 只看这个 nginx podkubectl get pod nginx-owide# -o wide 额外输出节点IP、PodIP、镜像绝大多数场景都不需要直接创建Pod哪怕是单实例Pod。推荐通过Deployment、Job这类工作负载资源来创建。如果Pod需要持久化状态则使用StatefulSet。一个Pod对应应用的单个实例。如果你需要横向扩容启动更多实例提升整体算力应当创建多个独立Pod一个实例对应一个Pod。在Kubernetes里这种多副本机制被称为副本管理。多副本Pod通常由控制器统一创建、批量管理。无论由你手动创建还是由控制器自动创建新Pod都会被调度到集群某个节点上。Pod会一直驻留在该节点直到运行结束、对象被删除、因资源不足被驱逐或是所在节点故障。注意重启Pod内部的容器 ≠ 重启整个Pod。Pod不是进程而是容器的运行环境。只要不被删除Pod对象会一直存在。Pod名称必须是合法的DNS子域名但这可能导致主机名出现异常。为保证最大兼容性Pod名称建议遵守更严格的DNS标签命名规则。2.2 指定操作系统可以通过.spec.os.name字段填写windows或linux声明Pod期望运行的操作系统。目前Kubernetes仅支持这两种操作系统未来会继续扩展。示例Pod配置apiVersion:v1kind:Podmetadata:name:linux-podspec:os:name:linux# 声明为Linux容器containers:-name:nginximage:nginx在Kubernetes v1.36版本中该字段不会影响调度器选择节点。spec.os.name只是标记字段不参与调度过滤。调度器不会自动根据该字段筛选同系统节点可能会出现Linux Pod被调度到Windows节点镜像直接启动失败。正确配套方案所有节点自动自带标签kubernetes.io/oslinux/kubernetes.io/oswindowsPod增加nodeSelector强制匹配系统节点示例spec:os:name:linuxnodeSelector:kubernetes.io/os:linux同时Pod的安全策略也会读取此字段避免对不匹配的系统执行无关策略。2.3 使用控制器直接手动创建Pod有巨大缺陷Pod是临时资源节点宕机、Pod崩溃后不会自动重建也不支持批量扩容、滚动更新。借助工作负载资源可以批量创建并管理Pod。资源对应的控制器负责处理副本扩缩、版本发布以及Pod异常时的自动恢复。例如某个节点宕机控制器会检测到该节点上的Pod全部失效并新建替代Pod调度器会把新Pod分配到健康节点。以下是可以管理Pod的常用工作负载资源资源适用场景核心特点Deployment无状态服务Nginx、后端 API、微服务普通无状态应用支持滚动更新、扩缩容Pod 无固定身份、无稳定网络标识StatefulSet有状态服务MySQL、Redis、ZookeeperPod 有序创建 / 删除每个 Pod 固定主机名、稳定存储适配需要持久身份的中间件 / 数据库DaemonSet节点级代理日志收集、监控、网络代理集群每个节点自动运行 1 个 Pod新增节点自动部署删除节点自动回收示例1Deployment最常用无状态工作负载apiVersion:apps/v1kind:Deployment# 工作负载资源metadata:name:nginx-deployspec:replicas:3# 期望3个Pod副本控制器维持数量始终为3selector:matchLabels:app:nginxtemplate:# Pod模板控制器根据模板批量创建Podmetadata:labels:app:nginxspec:containers:-name:nginximage:nginx:latestports:-containerPort:80默认情况下Kubernetes逐个调度每一个Pod。但部分紧耦合应用要求一组Pod同时被调度才能正常运行。你可以通过spec.schedulingGroup调度组字段将多个Pod归入同一个PodGroup。调度器会识别分组对整组Pod统一执行协同调度策略。控制组功能状态Kubernetes v1.35内测版默认关闭2.4 模板工作负载控制器会依据Pod模板批量创建Pod并全权接管生命周期管理。如果手动创建Pod要逐个写yaml、逐个管理工作负载Deployment/Job/DaemonSet把Pod的统一配置抽成spec.template只写一份模板控制器自动批量生成多个Pod统一管控。PodTemplate不是独立API资源嵌套在工作负载spec下是工作负载「期望运行什么Pod」的标准描述。创建Pod时可以在模板内为容器配置环境变量所有Pod统一的配置镜像、端口、环境变量、资源限制、探针、存储挂载全部写在template里批量生效。Job模板示例apiVersion:batch/v1kind:Job# Job 控制器根据这份模板生成一次性任务 Podmetadata:name:hellospec:# 关键template 就是 PodTemplatetemplate:spec:containers:-name:helloimage:busybox:1.28command:[sh,-c,echo Hello, Kubernetes! sleep 3600]restartPolicy:OnFailurePod创建完成后大部分核心字段镜像、命令、挂载等无法直接就地修改。K8s更新模板统一策略用新模板生成全新Pod逐步替换旧Pod不改动正在运行的旧Pod。举个例子StatefulSet控制器会保证所有运行中的Pod严格匹配当前模板。一旦你修改了模板控制器就会逐步新建Pod最终把所有旧实例全部替换完成。每一种工作负载都有独立的模板更新策略。不同控制器实现更新逻辑不一样不能一概而论比如StatefulSet默认不自动滚动更新需要手动触发更新。上层控制器管理模板更新底层kubelet只负责运行Pod二者互不感知架构易扩展。3. 进阶使用3.1 更新与重建3.1.1 可更新字段在Kubernetes生态中所有常规业务Pod均由工作负载控制器通过Pod模板统一创建与管理。Pod模板变更不会修改存量运行Pod只会新建新版Pod完成替换更新。Pod是不可变主体绝大多数核心配置一经创建便无法修改以此保障集群调度稳定性、运行一致性与故障可追溯性。K8s并未完全禁止直接修改Pod对象支持通过kubectl patch、kubectl replace等命令就地修改运行中Pod。但官方做了极强的权限限制仅开放极少数字段更新绝大多数核心配置、元数据均为永久不可变。以下元数据字段永久锁定任何更新操作都会直接报错是K8s底层强约束命名空间metadata.namespacePod名称metadata.name资源唯一标识metadata.uid创建时间戳metadata.creationTimestamp补充特殊约束若Pod已设置删除时间戳进入Terminating终止状态禁止新增终结器finalizers条目防止删除流程阻塞、资源死锁。仅开放6类字段支持运行中原地更新spec.containers[*].image业务容器镜像版本spec.initContainers[*].image初始化容器镜像版本spec.activeDeadlineSecondsPod最大运行时长spec.terminationGracePeriodSeconds优雅终止等待时长spec.tolerations节点容忍度配置仅允许新增禁止删除/修改旧规则spec.schedulingGates调度网关配置针对spec.activeDeadlineSeconds仅支持两种修改将空值改为正数将已有正数改得更小非负数。3.1.2 子资源专项变更常规更新只支持上述字段其余配置需要通过子资源来变更Resize资源调整更新容器CPU、内存配额参考容器资源扩容文档。Ephemeral Containers临时容器向运行中的Pod注入调试容器。Status状态更新Pod状态仅由kubelet和系统控制器使用。Binding绑定通过绑定请求指定节点仅调度器使用。3.1.3 版本计数metadata.generation是版本号字段由系统自动维护新创建Pod版本号为1每修改一次可变更的spec配置版本号自动1。status.observedGeneration记录当前Pod状态对应的配置版本由kubelet维护外部控制器禁止修改。不同状态字段会关联不同版本直接状态更新对应当前版本N间接状态更新对应上一轮版本N-1直接状态更新时配置变更会直接体现在状态中资源扩容状态扩容后已分配资源新增临时容器且处于等待阶段间接状态更新时配置变更需要一段时间才能生效状态会滞后一个版本容器镜像ID要等到镜像拉取完成才会更新扩容过程中实际占用资源依旧是旧配额需要重启的容器在扩容期间仍然沿用旧资源超时时长、优雅终止时长、删除时间戳状态生效会滞后一轮同步3.2 资源共享与进程通信同一个Pod内的容器可以共享数据、互相通信。3.2.1 存储Pod可以定义一组共享存储卷所有容器都能读写这份存储空间实现数据互通。即便其中某个容器重启卷内的数据依然可以保留。3.2.2 网络每个IP协议族都会给Pod分配唯一IP。Pod内所有容器共享同一个网络命名空间共用IP和端口。在Pod内部容器之间可以直接通过localhost互相访问访问外部服务时多个容器需要协调端口占用避免冲突除了网络调用还可以使用SystemV信号量、POSIX共享内存这类本机进程通信方式不同Pod拥有独立IP不做特殊配置就无法使用本机IPC通信跨Pod调用必须走网络IP。Pod内所有容器看到的主机名都等于Pod的名称详情见网络章节。3.3 安全配置通过Pod配置中的securityContext字段来约束容器权限可以精细化管控Pod或单个容器的行为。基础安全规范建议遵循基线安全标准以非root用户运行容器。简单安全上下文示例apiVersion:v1kind:Podmetadata:name:security-context-demospec:securityContext:runAsUser:1000runAsGroup:3000fsGroup:2000containers:-name:sec-ctx-demoimage:busyboxcommand:[sh,-c,sleep 1h]有关更多详细信息请参阅 Pod 高级配置。如需配置内核权限、seccomp等高级策略请阅读安全概念章节。3.4 资源配额请求与限制定义Pod时可以为容器声明资源配额最常用的是CPU和内存。requests请求调度器依靠该值判断节点资源是否充足决定把Pod调度到哪台机器limits上限kubelet强制限制资源用量容器不得超出该数值。CPU超限会被内核限流内存超出限制会触发OOM杀死进程。说明设置CPU上限需要权衡利弊。配额可以防止单个业务耗尽节点资源避免租户之间互相抢占资源多租户环境必不可少。但即便节点还有空闲算力CPU限流依然会触发可能拉高延迟敏感型业务的耗时。是否开启CPU上限要结合集群环境、业务特征和隔离要求综合判断。资源单位、限流规则与配置示例参考 Pod 与容器资源管理文档。3.5 静态 Pod静态Pod直接由节点本地的kubelet托管不受apiserver管控。普通Pod由控制平面管理而静态Pod完全由kubelet自主拉起、异常自动重启。静态Pod只能绑定到某一台节点的kubelet。最典型的用途是搭建自托管控制平面用kubelet直接管理apiserver、etcd等控制面组件。详情查看静态 Pod 文档。说明静态Pod的spec不能引用其他的API对象例如ServiceAccount、ConfigMap、Secret等。3.6 容器探针探针是kubelet 周期性对容器执行的健康检测支持三种检测方式ExecAction在容器内执行命令TCPSocketAction端口连通性检测HTTPGetActionHTTP接口健康检查更多内容请查阅 Pod 生命周期文档。