K8S-Pod(下)

发布于:2025-09-09 ⋅ 阅读:(12) ⋅ 点赞:(0)

Pod 的本质

Pod 是 Kubernetes 中最小的可部署的计算单元。它本质上是一个不可变的实体。一旦被创建,其核心定义(如镜像、命令、环境变量、卷等)就是不可变的。基本上(非全部)对 Pod 定义的修改都需要通过替换来实现,即创建一个新的 Pod 来替代旧的 Pod。

Pod 的创建流程

Pod 的创建是一个由多个组件协同完成的过程

  1. 提交请求
    kubectl 等客户端工具将 Pod 的配置信息(YAML/JSON)发送给 Kubernetes API Server。

  2. 验证与存储
    API Server 会验证请求的合法性和权限,然后将 Pod 的配置信息作为一条期望状态 (Desired State) 的记录写入到集群的持久化存储中心(通常是 etcd)。大部分对 Pod 定义的修改都需要通过替换来实现,即创建一个新的 Pod 来替代旧的 Pod。

  3. 调度 (Scheduling)
    Scheduler 持续监听 API Server,发现有一个新 Pod 被创建,且它的 nodeName 字段为空,这意味着它需要被调度。

    • 调度器根据 Pod 的资源请求、亲和性、污点容忍度等策略,从集群中选择一个最合适的 Node。
    • 选择完成后,调度器将绑定信息(将这个 Pod 绑定到某个 Node)写回 API Server。
    • API Server 再次更新 etcd 中的数据,将 Pod 的 nodeName 字段填上。
  4. 执行与启动
    目标 Node 上的 kubelet 组件监听到有新的 Pod 被调度到它所在的节点。

    • kubelet 从 API Server 获取 Pod 的详细配置。
    • kubelet 根据配置,调用本地的容器运行时(如 containerd, CRI-O),下载所需镜像,并启动容器。
    • kubelet 还会根据配置执行容器探针(Liveness, Readiness, Startup)进行健康检查。
  5. 状态上报
    kubelet 将 Pod 和容器的实际状态 (Actual State)(如 Running, Pending, Failed)持续报告给 API Server,最终写入 etcd。

至此,一个 Pod 完成创建并运行。

Pod 的更新机制

正如 Pod 的本质是不可变的一样,Pod 的更新操作本质上都是替换,即“删除旧 Pod,创建新 Pod”。

在生产环境中,我们通常通过 Deployment 等控制器来管理 Pod 的更新,实现无缝的滚动更新 (Rolling Update)

滚动更新流程

  1. 触发更新
    用户修改 Deployment 的配置(如镜像版本)并提交。API Server 将新的 Deployment 期望状态写入 etcd。

  2. 创建新 ReplicaSet
    Deployment 控制器注意到期望状态的变化。它会创建一个新的 ReplicaSet,其 Pod 模板指向新的配置(如新镜像)。

  3. 逐步替换

    • 新的 ReplicaSet 的副本数从 0 开始逐步增加(例如,先增加到 1)。
    • 同时,旧的 ReplicaSet 的副本数从 N 开始逐步减少(例如,先减少到 N-1)。
    • Kubernetes 会保证在更新过程中,可用的 Pod 总数始终不低于期望副本数的一定比例(默认 75%,可通过 maxUnavailable 配置),以确保服务不中断。
  4. 完成与回滚

    • 过程持续进行:(旧:N, 新:0) -> (旧:N-1, 新:1) -> … -> (旧:0, 新:N)
    • 旧的 ReplicaSet 会被保留(但其副本数缩容为 0),以便于需要时快速回滚。

Pod 的部分修改

虽然 Pod 的核心定义不可变,但部分元数据 (Metadata)状态字段是可以直接更新的:

字段类型 可更新字段示例 说明
元数据 (Metadata) labels 动态添加/修改标签,不会触发 Pod 重启,但可能影响 Service 端点选择。
annotations 动态更新注解,常用于工具(监控、链路追踪)动态注入配置信息。
Spec (部分字段) spec.activeDeadlineSeconds 更新 Pod 的活动截止时间。
spec.tolerations (不推荐) 理论上可添加容忍度,但行为不确定,因为调度已完成。
Status 所有状态字段 (如 phase, conditions, podIP) 由 Kubernetes 系统组件(kubelet)自动更新,反映 Pod 的实际状态。用户不能手动修改

不可变的字段containers[](镜像、命令、端口等)、volumesinitContainers[] 以及调度相关配置。

Init 容器

Init 容器是一种特殊的Pod容器,在应用容器启动之前运行,用于执行初始化任务。

特点

  • Init 容器会按顺序逐个运行。每个都必须成功完成(退出码为 0),下一个才能开始。
  • 在所有 Init 容器成功完成之前,Pod 的 status.initContainerStatuses 字段会显示状态,并且应用容器不会启动
  • 拥有自己的镜像,通常包含应用镜像中不存在的工具(如 curl, nslookup, dig)。
  • 与应用容器共享 Volume,可用于传递配置或数据。

示例与操作

# myapp.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: myapp-container
    image: myapp:1.0
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
# 部署 Pod
kubectl apply -f myapp.yaml
# 查看状态
kubectl get pod myapp-pod
# 查看详细信息(观察 Init 容器状态)
kubectl describe pod myapp-pod

边车容器 (Sidecar Container)

  • 边车容器是与主应用容器并行运行的辅助容器,旨在增强或扩展主容器的功能。
  • K8S将边车容器作为一个特殊的Init容器

特点

  • 与主容器同时启动、同时运行、同时终止,生命周期完全一致。
  • 与主容器共享相同的网络命名空间(同一 IP)、Volume(共享文件)等。
  • 为主容器提供额外能力(如日志收集、代理、监控),但主容器可能对其无感知。

官方文档勘误

官方文档错误地将边车容器配置为 initContainers
在这里插入图片描述

正确示例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  template:
    spec:
      containers:
        # 主应用容器
        - name: myapp
          image: alpine:latest
          command: ['sh', '-c', 'while true; do echo "$(date): Log entry" >> /opt/logs.txt; sleep 1; done']
          volumeMounts:
            - name: data
              mountPath: /opt
        # 边车容器 
        - name: logshipper-sidecar
          image: alpine:latest
          command: ['sh', '-c', 'tail -n+1 -f /opt/logs.txt'] # 持续跟踪日志
          volumeMounts:
            - name: data
              mountPath: /opt
      volumes:
        - name: data
          emptyDir: {}

主容器和边车容器的区分

在 Kubernetes 中,Pod 内的所有容器在技术上是平等的。“主容器”和“边车容器”的区分完全是一种基于设计和意图的逻辑概念

  • 主容器 (Main Container):承载 Pod 主要业务功能的容器。如果删除它,Pod 就失去了核心价值。
  • 边车容器 (Sidecar Container)辅助或增强主容器功能的容器。删除它,主容器依然能工作,但会失去一些增强特性(如日志外发、高级网络功能)。
    • 例如:日志收集器 (Fluentd)、服务网格代理 (Envoy)、监控导出器。

容器的“主”“从”角色是由其功能决定的,而不是由它们在 YAML 文件中的声明顺序决定的。 交换 containers 列表中的顺序不会改变它们的角色,但可能会影响启动时序和依赖关系。

总结

特性 应用容器 (Main Container) 边车容器 (Sidecar Container) Init 容器 (Init Container)
目的 实现 Pod 的主要业务逻辑 辅助、增强应用容器的功能 为应用容器做初始化准备
生命周期 与 Pod 生命周期一致 与 Pod 生命周期一致 在应用容器之前运行
运行方式 与其它容器并行运行 与主容器并行运行 严格顺序执行,必须成功退出
启动次数 持续运行,可能重启 持续运行,可能重启 一次性运行,完成后即终止
典型用例 Web 服务器、数据库、计算任务 日志收集器、服务网格代理、监控导出器 等待依赖服务、拉取密钥/配置、数据库迁移
在 Job 中的行为 任务主体,其成功退出决定 Job 完成 需配合主容器退出,否则会阻塞 Job 完成 正常执行,不影响 Job 完成判定

网站公告

今日签到

点亮在社区的每一天
去签到