type
status
date
slug
summary
tags
category
icon
password

1、Pod和Container概念介绍

在 Kubernetes 中,Pod 和 Container 是核心概念。
  • Container:是轻量级、可移植的运行时环境,封装了应用程序及其依赖(如代码、运行时、库等),基于 Docker、Containerd 等容器运行时技术实现。
  • PodKubernetes 的最小调度和管理单元,由一个或多个共享资源的 Container 组成。Pod 的特点:
    • 最小调度单元意味着 Pod 是扩缩容的基本单位,例如 Deployment 扩缩的是 Pod 数量。
    • 一个 Pod 内的容器共享相同的网络命名空间、存储卷(Volumes)和 IP 地址。这意味着 Pod 内的容器之间可以通过 localhost:port 直接通信,可以使用 Volumn 实现数据共享。
    • 一个 Pod 的所有容器始终运行在同一个节点上,不能跨节点。
    • Pod 是临时的,设计为可随时被销毁和重建(例如在扩缩容或节点故障时)。
可以这么理解:Container 是运行应用的底层实体,Pod 是 Container 的抽象层,用于管理一组共享命名空间、存储卷、IP地址和端口的 Container。每个 Pod 还包含一个 Pause 容器,Pause 容器是 Pod 的父容器,主要负责僵尸进程的回收、实现 Pod 的容器之间共享上下文。
如上所示,这个 Pod 包含两个容器:nginx(主服务)和 fluentd(日志收集)
  • 它们共享名为 logs 的 Volume,通过 localhost 直接通信。
  • Pod 内还有一个 Pause 容器,实现 nginx 容器和 fluentd 容器之间的资源共享,如果 nginx 容器的进程假死了,Pause 容器还负责回收假死的僵死进程。
notion image
既然单个容器就可以部署我们的应用,为什么 Kubernetes 不直接管理容器,还要设计一个 Pod 的概念呢?
  • 实现对容器的健康监测和横向扩容。如果只有裸容器,因为应用容器里面里面只有一个应用进程,很难实现对容器内的进程的健康检查和横向扩容,而 Pod 借助 Pause 容器可以轻松实现这个功能。
  • 方便一组需要紧密合作的容器共享上下文。有时候会出现需要多个容器共享资源的场景,例如:一个主业务容器 + 一个日志收集容器(如 Fluentd)共享日志 Volume。一个 Pod 可以包含多个容器,容器之间可以共享 Pod 内的网络、存储等资源,例如服务网格(Server Mesh)中的 Sidecar 代理。
  • 可以替换容器运行时的实现。容器和容器运行时实现技术(Docker、Containerd)紧密绑定,而 Pod 对容器进行抽象,可以在不修改容器的情况下,替换容器的底层运行时实现。

2、Pod的状态和生命周期

2.1 Pod的生命周期

  1. 初始化阶段
      • API Server 接收到创建 Pod 的请求
      • 调度器(Scheduler)为 Pod 选择合适的节点
      • Kubelet 在目标节点上接收到 Pod 定义
  1. 容器创建阶段
      • 拉取容器镜像(如果需要)
      • 创建容器运行时环境(使用 Docker 或者 Containerd)
      • 执行启动命令
  1. 运行阶段
      • 执行主进程
      • 运行就绪探针(Readiness Probe)和存活探针(Liveness Probe)
  1. 终止阶段
      • Pod 被删除,状态置为 Terminating。
      • kube-proxy 更新转发规则,将 Pod 从 Service 的 endpoint 列表中摘除掉,新的流量不再转发到该 Pod。
      • 如果 Pod 配置了 preStop Hook ,将会执行。
      • kubelet 对 Pod 中各个容器发送 SIGTERM 信号以通知容器进程开始优雅停止。
      • 等待容器进程完全停止,如果在 terminationGracePeriodSeconds 内 (默认 30s)还未完全停止,就发送 SIGKILL 信号强制杀死进程。
      • 所有容器进程终止,清理 Pod 资源。

2.2 Pod的状态

Pod 的状态在生命周期的不同阶段会有不同的变化。Pod 的状态保存在 PodStatus 对象,PodStatus 中有一个 phase 字段,用于描述 Pod 在生命周期中的状态。可以使用 kubectl 查看某个 Pod 的 phase 字段:
notion image
Pod 的 phase 字段有以下五种状态:
状态
原因
Pending(挂起)
Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。可能正在下载容器镜像、分配资源或等待其他调度条件。
Running(运行中)
Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。
Succeeded(成功)
Pod 中的所有容器都已成功结束,并且不会再重启。常见于Job、CronJob等一次性或周期性任务完成后。
Failed(失败)
Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止,且未被设置为自动重启。
Unknown(未知)
因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。
下图是 Pod 在生命周期中状态转换示意图:
notion image
以上是 Pod 的 phase 字段的取值,kubectl 命令返回的 status 字段的取值更加细化。例如当 Pod 反复启动失败时,kubectl 命令的 status 字段中可能会出现 CrashLoopBackOff。
kubectl 命令返回的 status 字段取值范围有:
notion image

2.3 容器探针

Kubernetes 提供了以下探针来确保应用容器的可靠性:
  • 存活探针 (Liveness Probe):用于检测容器是否处于运行状态。如果探测失败,kubelet 会杀死容器并根据重启策略决定是否重启。
  • 就绪探针 (Readiness Probe):用于检测容器是否准备好接收流量。如果探测失败,端点控制器会从 Service 中移除该 Pod 的 IP 地址。
  • 启动探针 (Startup Probe):用于保护慢启动容器。在启动探针成功之前,其他探针都会被禁用。
Kubernetes 支持三种探针探测方式:
  1. HTTP GET:向容器 IP 发送 HTTP GET 请求
  1. Exec:在容器内执行指定命令
  1. TCP Socket:尝试与容器建立 TCP 连接
如下所示,使用存活探针以 http 请求的方式探测容器的运行状态,延迟 3s 进行第一次探测,后续每 3s 探测一次。

2.4 容器重启策略

容器重启策略是指当容器中的进程终止时应该如何响应。这些策略通过 Pod 的 spec.restartPolicy 字段进行配置。支持以下三种重启策略:
  • Always:默认策略,只要容器退出(不论退出代码是什么),kubelet 就会自动重启容器,适用于需要持续运行的应用程序(如 Web 服务器)
  • OnFailure:只有当容器以非零状态退出时才会重启,适用于批处理作业或预期会完成的任务
  • Never:无论容器如何退出,都不会重启,适用于一次性任务或不需要重启的作业
注意:
  • 不同的工作负载控制器对重启策略有不同的要求:
    • Deployment/ReplicaSet/StatefulSet: 通常使用 Always(默认)
    • Job: 通常使用 OnFailure 或 Never
    • DaemonSet: 通常使用 Always
  • 频繁重启的容器会进入指数退避延迟(10秒、20秒、40秒...),最多 5 分钟

2.5 生命周期钩子

生命周期钩子(Lifecycle Hooks)机制是指容器在特定时刻(容器启动/关闭时)运行用户定义的代码,实现优雅的初始化、关闭和其他自定义行为。Kubernetes 提供两种生命周期钩子,支持 exec 和 http 两种使用方式。
  • PostStart 钩子:在容器创建后立即执行,用于容器启动后的初始化操作。
  • PreStop 钩子:在容器终止前执行,用于优雅关闭应用程序、保存状态等。
注意:
  • PostStart 钩子与容器的主进程并行执行,不能保证在容器 ENTRYPOINT 之前完成。如果某个操作需要确保在容器 ENTRYPOINT 之前完成,可以使用 Init 容器(下面介绍)。
  • Kubernetes 不保证钩子一定会执行成功(如节点崩溃时)。
  • PreStop 默认最长超时时间为 30s,如果超过 30s 进程还未完全停止,就发送 SIGKILL 信号强制杀死进程。可通过 spec.terminationGracePeriodSeconds 调整(terminationGracePeriodSeconds 一定大于 sleep 的时间)

    3、其他Pod容器

    3.1 Init容器

    Init 容器是 Kubernetes 中一种特殊类型的容器,它在 Pod 内的应用容器启动之前运行,用于执行初始化任务。特点:
    • 先于应用容器运行:Init 容器总是运行到完成,且必须全部成功完成后,Pod 的主容器才会启动
    • 顺序执行:多个 Init 容器按顺序依次执行,前一个成功后才运行下一个
    • 独立配置:每个 Init 容器可以有自己的镜像、命令、卷挂载等配置
    • 资源隔离:Init 容器的资源请求/限制与主容器分开计算
    常见用途:
    • 准备配置文件:从 ConfigMap 或 Secret 生成应用所需的配置文件
    • 等待依赖服务:检查数据库或其他服务是否就绪
    • 数据下载/解压:从远程源下载应用所需数据
    • 权限设置:设置文件系统权限或其它安全相关配置
    • 注册服务:在服务发现系统中注册当前 Pod
    示例:
    注意:
    • 如果 Init 容器失败,Pod 会根据 restartPolicy 决定是否重启(通常为 "Always" 时会重启)
    • Init 容器不支持就绪探针(Readiness Probe),因为它们必须在就绪前完成
    • Init 容器不能设置生命周期钩子(Lifecycle Hooks)

    3.2 边车(Sidecar)容器

    边车(Sidecar)是Kubernetes中一种容器设计模式,通过将一个辅助容器与主应用程序容器一起部署在同一个 Pod 中,来扩展或增强主容器的功能。
    边车容器与主容器共享 Pod 中的网络、存储卷、命名空间等资源。主容器专注于核心业务逻辑,边车处理辅助功能如:
    • 日志收集:如 Fluentd、Filebeat 等日志收集器
    • 服务网格:如 Istio 的 Envoy 代理
    • 监控导出:如 Prometheus Expoter 导出监控信息
    • 安全代理:如 Vault 代理
    • 配置管理:动态获取和更新配置
    • 数据同步:如数据库复制代理
    示例:

    3.3 临时容器

    临时容器是 Kubernetes 中一种特殊类型的容器,主要用于调试目的,它们可以在不重启 Pod 的情况下动态地添加到正在运行的 Pod 中。需要 Kubernetes 1.16 以上版本支持。特点:
    • 调试专用:主要用于故障排查和诊断,例如诊断运行中的容器问题、检查网络连接、检查文件系统状态等。
    • 无需重启:无需重建 Pod 即可调试,不会影响原有容器的运行
    • 资源限制:不能配置资源限制(CPU/内存)
    • 生命周期:与 Pod 相同,Pod 终止时临时容器也会终止
    • 不可修改:一旦添加到 Pod 中,就不能被移除或更改
    使用方式:
    1、使用 kubectl debug 命令添加。
    2、通过 yaml 配置文件添加。
    Kubernetes系列:核心组件简介Kubernetes系列:俯瞰Kubernetes全貌
    Loading...