第一部分:Deployment资源对象的理论基础与架构剖析

1.1 为什么需要Deployment

        在Kubernetes生态中,用户从不直接管理单个Pod——Pod在节点宕机、资源不足、被驱逐时会消失,Kubernetes也不会自动将其重生。因此,Kubernetes引入了“控制器”(Controller)这一核心抽象。控制器通过“声明式期望状态”与“实际状态”之间的持续比对(即调谐循环,Reconcile Loop),驱动集群不断向用户期望的目标收敛。Deployment正是Kubernetes中最常用的工作负载控制器之一,专注于管理无状态应用(Stateless Applications)的Pod副本集。

Deployment的核心价值可以概括为五大能力:

能力维度具体说明
副本管理始终维持指定数量的Pod副本(如 replicas: 3)
自愈能力Pod崩溃或节点故障时,控制器自动重建新Pod
滚动更新无缝升级镜像或配置,服务零停机
版本回滚一键回退到上一个稳定版本
暂停/恢复支持分阶段发布与金丝雀部署

        适用场景包括Web服务、API网关、微服务应用、缓存代理等无状态负载;不适用于数据库、ZooKeeper、Kafka等有状态应用,后者应使用StatefulSet。

1.2 Deployment控制器的两层架构

        Deployment的核心设计理念是分层控制——它并不直接管理Pod,而是通过一个中间层ReplicaSet来实现间接管控。整个控制链条如下:

Deployment(用户声明期望状态)
  ↕ 控制
ReplicaSet(版本管理与副本保障)
  ↕ 管理
Pod(实际运行实例)

Deployment层的职责包括:接收用户的更新指令(如修改镜像版本)、决定滚动更新的速率(通过maxSurge与maxUnavailable参数)、维护版本历史链(每个更新操作创建一个新的ReplicaSet),以及在必要时执行回滚操作。当用户执行kubectl rollout undo时,Deployment将重新激活上一个历史ReplicaSet,而不需要保存任何Pod快照。

ReplicaSet层的职责则更加聚焦:它通过标签选择器(Label Selector)匹配Pod,持续监控符合标签的Pod数量,若实际数量少于期望,则通过Pod模板创建新Pod;若实际数量多于期望,则删除多余的Pod。

每次更新Deployment的Pod模板(例如变更镜像或环境变量)时,Deployment控制器都会创建一个新的ReplicaSet,旧ReplicaSet保留但不缩放至零,以便用户随时回滚。通过kubectl rollout history deployment/<deployment名>可查看所有历史版本(Revision)的完整列表。

1.3 控制器模式与调谐循环

        Deployment(以及其他所有Kubernetes控制器)的运行基于控制器模式(Controller Pattern)。这个模式可用以下伪代码精确描述:

for {
    实际状态 := 获取集群中对象 X 的实际状态
    期望状态 := 获取集群中对象 X 的期望状态(来自用户提交的YAML)
    if 实际状态 == 期望状态 {
        什么都不做
    } else {
        执行编排动作,将实际状态调整为期望状态
    }
}

具体而言,Deployment控制器从etcd中获取所有携带指定标签(如app: nginx)的Pod,统计其数量作为实际状态;而Deployment对象的spec.replicas字段值即为期望状态。控制器对二者进行比较,确定是需要创建新Pod还是删除多余Pod。

这一比对过程在Kubernetes中称为调谐(Reconcile),而循环本身称为调谐循环(Reconcile Loop)或同步循环(Sync Loop)。调谐的最终结果总是对被控制对象的某种读写操作——增加Pod、删除Pod、更新Pod配置等,这也是Kubernetes“面向API对象编程”理念的直观体现。

从事件驱动的实现角度看,Deployment Controller通过Informer机制同时监听Deployment、ReplicaSet和Pod三种资源的变化事件,任一事件触发即进入syncLoop进行状态同步。

第二部分:Deployment配置清单(Manifest)字段详解

        在深入YAML配置之前,有必要明确一个概念:Kubernetes配置清单(Manifest)是以YAML格式编写的声明式配置文件,用于定义集群中资源的期望状态。Kubernetes通过kubectl apply命令读取Manifest,将其写入API Server,再由各控制器驱动集群状态向该声明收敛。

2.1 基础框架与必须字段

        每个部署到Kubernetes的YAML文件都必须包含四个必须字段:

字段说明本教程取值
apiVersion指定使用的Kubernetes API版本apps/v1
kind声明的Kubernetes对象类型Deployment
metadata资源的元数据(名称、标签、命名空间等)见下方详细解析
spec资源的期望状态规格见下方详细解析

2.2 Deployment核心YAML完整示例与逐字段解析

        本章将给出一个包含Liveness、Readiness、Startup三种探针的生产级Nginx Deployment配置,然后对每一个字段展开深度解释。请注意本教程基于openEuler 24.03 SP3系统,因此containerd作为默认的容器运行时,CRI交互方式与Docker有所不同,但用户几乎感知不到,所有kubectl命令行为完全一致。

生产环境提示:在生产级别部署中,建议将容器镜像标签固定为精确版本(如nginx:1.25.3)而非latest,以确保部署的可重复性、审计能力与回滚精准性。

创建文件nginx-production-deployment.yaml,内容如下:

---
# 文档分隔符:YAML支持多个文档合并,此符号将同一文件中的多个资源定义分开
# 以下为Deployment资源定义
apiVersion: apps/v1            # Kubernetes API的apps组v1稳定版本
kind: Deployment               # 资源类型为Deployment
metadata:
  name: nginx-production       # Deployment的名称,集群内唯一标识
  namespace: default           # 命名空间,逻辑隔离单位
  labels:                      # 标签:用于组织、筛选和关联资源
    app: nginx-production      # 应用标签(kv键值对,下同)
    tier: frontend             # 层级标签
    version: v1                # 版本标签
  annotations:                 # 注解:记录非标识性元数据(如描述、维护人等)
    description: "Production-grade Nginx Deployment with health probes"
    maintainer: "devops-team"

# --- spec开始:Deployment的期望状态定义 ---
spec:
  replicas: 3                  # (重要)期望的Pod副本数量
  revisionHistoryLimit: 10     # 保留的历史ReplicaSet数量上限,用于回滚
  minReadySeconds: 30          # Pod就绪后等待30秒才标记为Available

  # --- selector:选择器,用于建立Deployment与Pod的关联关系 ---
  selector:
    matchLabels:               # 等值匹配:必须选择标签
      app: nginx-production    # 此处的键值必须与template中定义的标签一致
      tier: frontend

  # --- strategy:更新策略配置 ---
  strategy:
    type: RollingUpdate        # 滚动更新策略(默认值),另一种为Recreate
    rollingUpdate:
      maxSurge: 1              # 更新期间允许超出期望副本数的最大Pod数
      maxUnavailable: 1        # 更新期间允许不可用的最大Pod数

  # --- template:Pod模板定义(核心字段)---
  template:
    metadata:
      labels:                  # Pod模板的标签,必须包含selector.matchLabels的所有键值
        app: nginx-production
        tier: frontend
        version: v1
    spec:                      # Pod规格
      terminationGracePeriodSeconds: 60   # 优雅终止等待时间

      # --- containers:容器列表定义 (数组类型)---
      containers:
        - name: nginx                        # 容器名称
          image: nginx:1.25.3                # 容器镜像及具体版本标签
          imagePullPolicy: IfNotPresent      # 镜像拉取策略

          # ---- 端口定义 ----
          ports:
            - name: http                     # 端口名称(用于Service引用)
              containerPort: 80              # 容器内监听的端口号
              protocol: TCP                  # 传输层协议

          # ---- 资源请求与限制 ----
          resources:
            requests:                        # 调度器保证分配的最小资源
              cpu: "100m"                    # 100毫核CPU (0.1核)
              memory: "128Mi"                # 128兆字节内存
            limits:                          # 容器能使用的最大资源上限
              cpu: "500m"                    # 500毫核CPU (0.5核)
              memory: "512Mi"                # 512兆字节内存

          # ---- 启动探针 ----
          # 作用:检测应用是否已完成启动。配置了startupProbe后,
          #        liveness和readiness探针将被禁用,
          #        直到startupProbe首次成功为止
          startupProbe:
            httpGet:                         # 检查方式:HTTP GET请求
              path: /healthz                 # 健康检查的URI路径
              port: 80                       # 目标端口
              scheme: HTTP                   # HTTP协议
            initialDelaySeconds: 10          # 容器启动后等待10秒再执行第一次探测
            periodSeconds: 10                # 探测间隔:每10秒执行一次
            timeoutSeconds: 3                # 单次探测超时时间3秒
            failureThreshold: 30             # 连续失败30次(即30×10=300秒)才判定失败
            successThreshold: 1              # 成功1次即视为启动成功

          # ---- 存活探针 ----
          # 作用:检测容器是否正常运行,失败则触发容器重启
          livenessProbe:
            httpGet:
              path: /healthz                 # 存活检测路径
              port: 80
              scheme: HTTP
            initialDelaySeconds: 15          # 启动后首次探测延迟
            periodSeconds: 20                # 探测间隔:每20秒一次
            timeoutSeconds: 5                # 超时时间5秒
            failureThreshold: 3              # 连续3次失败触发重启
            successThreshold: 1              # 成功1次即视为存活

          # ---- 就绪探针 ----
          # 作用:检测容器是否准备好接收客户端流量,失败则从Service端点移除
          readinessProbe:
            httpGet:
              path: /ready                   # 就绪检测路径
              port: 80
              scheme: HTTP
            initialDelaySeconds: 5           # 启动后5秒首次探测
            periodSeconds: 5                 # 探测间隔:每5秒一次
            timeoutSeconds: 3                # 超时时间3秒
            failureThreshold: 3              # 连续失败3次标记为未就绪
            successThreshold: 1              # 成功1次即视为就绪

          # ---- 生命周期钩子 ----
          lifecycle:
            preStop:                         # 容器终止前执行的命令
              exec:
                command:
                  - "/bin/sh"
                  - "-c"
                  - "sleep 15"              # 等待15秒让Service卸载端点

2.3 各字段深度解析

2.3.1 apiVersion与kind

apiVersion: apps/v1指定了使用Apps API组的v1稳定版本。Kubernetes的API按照以下成熟度组织:

  • Alpha:可能包含bug,不保证未来兼容,示例格式为object/v1alpha1

  • Beta:仍有些不稳定,但很可能进入稳定版,示例格式为object/v1beta1

  • Stable:建议生产使用,示例格式为apps/v1

Deployment自Kubernetes 1.9起使用apps/v1稳定版API,是生产环境唯一推荐使用的版本。

kind: Deployment声明了YAML文件描述的是Deployment类型的Kubernetes对象。Kubernetes支持数十种kind类型,包括但不限于Deployment、Service、ConfigMap、DaemonSet、StatefulSet、Job等。

2.3.2 metadata字段

metadata.name是Deployment在集群中的唯一标识符,同一命名空间内不可重复。命名建议:采用小写字母、数字和连字符组合,如nginx-production。

metadata.namespace用于逻辑隔离资源。若不指定,默认使用default命名空间。

metadata.labels是键值对格式的标签,用于组织和筛选资源。标签是Kubernetes中最为核心的关联机制——Deployment通过spec.selector.matchLabels筛选与管理Pod,Pod通过标签匹配所属的Service。labels可以包含多个键值对,在组织上与Selector配合使用。

metadata.annotations与标签类似(也是键值对),但用于记录非标识性元数据,如描述文字、维护者信息、构建版本号等。注解不支持选择器查询。

关键约束:template.metadata.labels定义的标签,必须包含spec.selector.matchLabels中定义的全部标签键值对,否则API Server将在创建时直接拒绝该配置。这是因为Deployment必须能够通过选择器精确定位它所管理的Pod,任何标签不匹配都将破坏这一关联。

2.3.3 spec.replicas

replicas: 3声明期望的Pod副本数量为3。Deployment控制器将持续确保集群中有且仅有3个符合选择器匹配条件的Pod在运行。

副本数的选择须考虑以下因素:

  • 高可用性:至少2个副本可承受单Pod故障;3个副本可承受单节点宕机

  • 资源约束:每个Pod的资源请求量 × 副本数 < 集群可用资源

  • 负载分散:副本数越多,单个Pod承受的负载越低

2.3.4 spec.revisionHistoryLimit

revisionHistoryLimit: 10限制Deployment保留的历史ReplicaSet数量为10。每次更新Deployment时都会创建一个新的ReplicaSet,旧的ReplicaSet保留用于回滚操作。该字段的值直接控制了可回滚的版本总数。

如果将此值设置为0,Deployment将清理所有历史ReplicaSet,从而无法执行回滚操作。生产环境中通常保留5~10个版本,以在存储开销与回滚灵活性之间取得平衡。

2.3.5 spec.minReadySeconds

minReadySeconds: 30指定新创建的Pod在变为“就绪”状态后,必须持续就绪至少30秒,才能被Deployment标记为“可用”(Available)。这个字段的主要价值在于缓冲——避免Pod短时间内就绪又变为未就绪的“抖动”问题(快速就绪-未就绪交替),减少流量波动。

2.3.6 spec.selector

selector定义了Deployment用于识别其所管理Pod的标签选择器。matchLabels使用等值匹配方式——Pod的标签键值必须完全匹配此处定义的键值,才能被该Deployment管理。Kubernetes还支持matchExpressions进行集合式选择,但matchLabels的等值匹配是最常用模式。

2.3.7 spec.strategy

strategy控制Deployment的更新行为。Kubernetes支持两种策略:

策略类型行为描述适用场景
RollingUpdate(默认)逐步创建新Pod再删除旧Pod,保证服务不中断绝大多数Web服务、API应用
Recreate先删除所有旧Pod,再重新创建新Pod不支持多版本的数据库应用、一次性批量任务
滚动更新参数详解

maxSurge:更新期间允许超过期望副本数的最大Pod数量。取值可以是绝对值(如maxSurge: 1)或百分比(如maxSurge: 25%)。当期望副本数为3、maxSurge为1时,更新过程中最多允许4个Pod同时存在;若maxSurge为25%,计算方式为3 × 25% = 0.75,向上取整得1(但严格数学公式因实现而异)。

maxUnavailable:更新期间允许不可用的最大Pod数量。取值同样可以是绝对值或百分比。例如maxUnavailable: 1表示更新过程中最多允许1个Pod处于不可用状态。

这两个参数共同构成了滚动更新的速率窗口:

  • maxSurge控制“能超前创建多少新Pod”

  • maxUnavailable控制“能超前删除多少旧Pod”

Kubernetes默认值均为25%,已足够满足绝大多数集群的需求。

滚动更新数学演示(期望副本=3):

参数组合含义更新步进
maxSurge:1, maxUnavailable:0允许1个额外Pod,不允许任何Pod不可用先创建1个新Pod→就绪后删除1个旧Pod→重复3次
maxSurge:1, maxUnavailable:1允许1个额外Pod和1个Pod不可用创建1新→删除1旧→创建1新→删除1旧→创建1新→完成
maxSurge:0, maxUnavailable:1不允许额外Pod,允许1个不可用删除1旧→创建1新→就绪→删除1旧→创建1新→就绪→删除1旧→创建1新
maxSurge:25%, maxUnavailable:25%(默认)3×25%=0.75→向上取整≈1个额外与1个不可用相当于1和1,创建1新→删除1旧→重复

简单说:surge大→速度快但耗资源多,unavailable大→速度快但可用副本少,策略选取本质是在部署速度 vs 服务质量之间做权衡。

2.3.8 spec.template

template是Deployment中最重要的字段——它定义了待创建的Pod的完整规格。template本身是一个Pod模板对象,包含metadata和spec两个子字段。

Pod模板的metadata通常只包含labels字段。需要注意的是,Pod模板的metadata不应包含name或namespace字段——Pod的名称由ReplicaSet自动生成(格式为<Deployment名>-<ReplicaSet哈希>-<Pod随机后缀>),命名空间也必须与Deployment保持一致,不能跨命名空间管理Pod。

2.3.9 spec.template.spec.terminationGracePeriodSeconds

terminationGracePeriodSeconds: 60定义Pod收到SIGTERM信号后,在被强制SIGKILL终止之前等待的秒数,默认值为30秒。对于需要优雅关闭的应用程序(如正在处理HTTP长连接或事务的Web服务),应适当增大该值,以确保容器有足够时间完成正在处理的请求。

2.3.10 containers详解

containers字段是Pod模板的核心,定义了Pod中运行的容器列表。每个容器支持以下关键子字段:

  • name:容器的唯一标识名,在Pod内唯一

  • image:容器使用的基础镜像,建议指定精确版本标签

  • imagePullPolicy:镜像拉取策略

    策略值行为
    Always每次启动容器时都尝试拉取镜像
    IfNotPresent仅当本地不存在镜像时才拉取
    Never从不拉取镜像,必须本地存在

    openEuler 24.03 SP3环境推荐IfNotPresent,以加快Pod启动速度并避免网络依赖。

  • ports:声明容器监听的端口(数组)。各字段含义:

    • name:端口名称,供Service通过名称引用

    • containerPort:容器内实际监听的端口号

    • protocol:传输层协议(TCP/UDP/SCTP)

  • resources:CPU与内存的请求和限制。requests是调度器进行Pod调度时保证分配的最小量;limits是容器允许使用的最大量。容器运行后实际占用资源随负载波动干两者之间。合理设置这两个值有助于Kubernetes做出最优的调度决策并防止单个容器耗尽节点资源。

第三部分:Pod探针体系——存活·就绪·启动三种探针详解

3.1 探针存在的必要性

在不配置任何健康检查的情况下,Kubernetes仅能判断Pod是否存在以及容器进程是否在运行,但这远远不够:

  • 应用启动缓慢,但容器状态已为Running——此时若接入流量,请求将失败

  • 应用线程死锁或陷入死循环,但进程依然存在——Kubernetes完全感知不到异常

  • 依赖的数据库/Redis/消息队列不可用,但服务仍在接收外部请求——客户端将收到大量错误响应

探针正是为解决上述诊断盲区而设计的健康检查机制。

3.2 三种探针的核心定位与差异

Kubernetes通过kubelet组件对Pod中的每个容器执行探针检查。当前提供了三种探针,它们在触发时机、行为后果和适用场景上存在本质区别:

维度存活探针(livenessProbe)就绪探针(readinessProbe)启动探针(startupProbe)
核心问题“容器是否正常运行?”“容器是否准备好接收流量?”“应用是否已启动完成?”
探测失败后果kubelet杀死容器并触发重启(受restartPolicy影响)从所有关联Service的端点列表中移除该Pod IPkubelet杀死容器并触发重启
探测成功后持续监控容器健康状态将Pod IP重新加入Service端点激活liveness和readiness探针
典型使用场景线程死锁、内存泄漏、JVM卡死启动预热、依赖不可用、负载过高启动时间超过60秒的慢启动应用
是否导致重启是(失败后重启容器)否(仅控制流量路由)是(失败后重启容器)
不配置默认值SuccessSuccessSuccess

关键认知:readinessProbe失败只影响流量分发,并不重启容器,依赖服务恢复后探针重新成功,Pod自动回到Service端点。反之,livenessProbe失败会导致容器被直接杀死并重建——这是一个破坏性操作,必须谨慎配置,确保探针只捕获真正的不可恢复错误。

3.3 启动探针的特殊地位

startupProbe与其他两种探针之间存在关键的互斥/抑制关系:如果配置了startupProbe,那么livenessProbe和readinessProbe都将被禁用,直到startupProbe首次成功执行完毕。这一特性至关重要,因为它解决了“慢启动应用被存活探针误杀”的经典问题:

  • 无startupProbe时:应用正在启动(可能需要60~120秒),但livenessProbe已在不断探测、积累失败次数,一旦达到failureThreshold,kubelet就会将容器杀死

  • 有startupProbe时:在startupProbe成功之前,livenessProbe和readinessProbe被完全禁用;startupProbe可配置较长的failureThreshold,给予慢启动应用充足的初始化时间

因此,对于启动时间较长的应用(如大型Java Spring Boot服务、需要加载机器学习模型的服务),强烈建议同时配置三种探针,其中startupProbe的failureThreshold×periodSeconds应大于应用的最长启动时间。

3.4 三种检查方式深度对比

Kubernetes为每种探针提供了四种检查机制,本章聚焦于最常用的三种:

检查方式原理描述健康判定条件适用场景
httpGet向容器指定端口和路径发送HTTP/HTTPS GET请求响应HTTP状态码在200~399范围内Web服务、REST API、带健康检查端点的应用
tcpSocket尝试与容器指定端口建立TCP连接三次握手成功建立连接数据库、Redis、gRPC服务、自定义TCP协议的服务
exec在容器内执行指定命令并检查退出状态码命令退出状态码为0所有类型应用,需要自定义复杂健康检查逻辑的场景

⚠️ exec探针的成本警告:exec探针的实现在每次探测时都需要在容器内创建/复制进程。在高Pod密度的集群中,如果periodSeconds设置过短,exec探针可能显著增加节点的CPU负载。建议在高负载场景优先使用httpGet或tcpSocket。

httpGet探针还支持额外的可选字段,其含义如下:

字段类型默认值说明
schemestringHTTP连接方案(HTTP或HTTPS)
hoststringPod IP请求的主机名,默认使用Pod IP
pathstring/HTTP请求的URL路径
httpHeaders[]Object无自定义HTTP请求头(列表)

3.5 探针公共参数详解

所有三种探针和三种检查方式均共享以下公共参数:

参数类型默认值说明最小/最大值
initialDelaySecondsint320容器启动后等待多少秒再发起第一次探测≥0
periodSecondsint3210两次探测之间的间隔秒数≥1
timeoutSecondsint321单次探测的超时秒数≥1
failureThresholdint323连续失败多少次才判定为失败≥1
successThresholdint321连续成功多少次才判定为成功≥1(liveness/startup必须为1)

失效时间窗口推导:可以推导容器被视为不健康的总耗时窗口如下:

失效确认时间 = failureThreshold × periodSeconds + timeoutSeconds×(failureThreshold)

参数调优建议:

  • initialDelaySeconds:应设置为大于应用的实际启动时间。对于快速启动应用(如Nginx),可设置为5~15秒;对于Java服务,建议设置为30~60秒

  • periodSeconds:生产环境中建议不低于5秒。过低会增加API Server和kubelet的负载

  • timeoutSeconds:建议小于periodSeconds,避免探测请求堆积

  • failureThreshold:存活探针建议3~5次,避免偶发网络抖动触发重启;启动探针可设置较高值(如30)以适应慢启动应用

3.6 httpGet探针示例详解

回到本章YAML示例中的配置:

startupProbe:
  httpGet:
    path: /healthz              # 向容器发送 GET /healthz 请求
    port: 80                    # 目标端口80
    scheme: HTTP                # 使用HTTP协议
  initialDelaySeconds: 10       # 容器启动后等10秒
  periodSeconds: 10             # 每10秒探测一次
  timeoutSeconds: 3             # 单次探测超时3秒
  failureThreshold: 30          # 连续失败30次才判定失败
  successThreshold: 1           # 成功1次即视为启动完成

此配置的含义为:容器启动10秒后,kubelet开始每10秒向Pod的80端口发送GET /healthz请求;如果HTTP响应的状态码在200~399之间(即2xx或3xx),记为一次成功;只要成功1次,即视为启动完成,随后liveness和readiness探针被激活;如果连续30次(即30×10秒=300秒窗口)探测均失败,则kubelet判定容器启动失败,杀死容器并根据重启策略重启。

该设计适用于启动时间较长但非极端的应用(例如启动时间在60~240秒区间内)。

3.7 tcpSocket探针示例

        对于不暴露HTTP接口的数据库类服务(如PostgreSQL、MySQL、Redis),tcpSocket是最自然的选择:

livenessProbe:
  tcpSocket:
    port: 5432                  # 尝试在端口5432建立TCP连接
  initialDelaySeconds: 30
  periodSeconds: 10
  failureThreshold: 3
readinessProbe:
  tcpSocket:
    port: 5432                  # 就绪探测使用相同的TCP端口检查
  initialDelaySeconds: 5
  periodSeconds: 5

        kubelet将尝试与Pod IP的端口5432进行TCP三次握手。只要TCP连接建立成功(即服务器端口开放并监听),即判定为健康。

3.8 exec探针示例

        exec探针是灵活度最高的检查方式,适合需要复杂业务逻辑的健康检查(代码摘选自Kubernetes官方文档示例):

livenessProbe:
  exec:
    command:
      - cat
      - /tmp/healthy            # 检查/tmp/healthy文件是否存在
  initialDelaySeconds: 5
  periodSeconds: 5
  failureThreshold: 3

        该探针在容器内执行cat /tmp/healthy命令。若文件存在且读取成功,命令退出码为0,判定为健康;若文件被删除(如某些健康检测脚本会在异常时清除状态文件),命令返回非零码,判定为失败。系统内可通过配合启动脚本控制该文件的存在与否,从而间接控制探针结果。

⚠️ 请注意:若执行的探测命令是Shell脚本,必须显式指定Shell解析器,例如sh /data/scripts/health_check.sh,而不能直接指定脚本路径。

第四部分:openEuler 24.03 SP3环境下的实战部署

4.1 系统环境说明

        参考openEuler官方文档及社区实践所述,本教程的部署环境基于openEuler 24.03 LTS SP3操作系统,Kubernetes v1.28,容器运行时为containerd。openEuler 24.03 LTS SP3是华为主导的开源Linux发行版,“24.03 LTS SP3”代表2024年3月发布的长期支持版第3次服务包更新,适配x86与鲲鹏等国产硬件架构,稳定性强,适合企业级部署与学习场景。

4.2 环境前置条件(checklist)

在部署之前,确保已经完成以下所有前置步骤(详见本系列第二篇文章):

[ ] 关闭防火墙(systemctl disable --now firewalld)
[ ] 关闭SELinux(setenforce 0,并修改/etc/selinux/config永久关闭)
[ ] 关闭Swap交换空间(swapoff -a,并注释/etc/fstab中的swap行)
[ ] 配置主机名和/etc/hosts文件
[ ] 启用内核IP转发参数(net.ipv4.ip_forward=1)
[ ] 安装并启动containerd容器运行时
[ ] 安装kubeadm、kubelet、kubectl组件
[ ] 使用kubeadm完成集群初始化
[ ] 部署CNI网络插件(Calico或Flannel)
[ ] Worker节点已加入集群

验证集群状态:

# 检查所有节点是否均已处于Ready状态
kubectl get nodes

# 检查kube-system命名空间下所有系统Pod是否正常运行
kubectl get pods -n kube-system

预期输出中所有节点STATUS应为Ready,所有系统Pod的READY应为1/1且STATUS为Running。

4.3 部署第一个Deployment

将本章第二部分给出的完整YAML保存为nginx-production-deployment.yaml,然后执行以下命令:

kubectl apply -f nginx-production-deployment.yaml

命令行说明:kubectl apply -f命令读取指定的YAML文件,通过API Server将资源定义写入etcd。若该资源已存在,则以声明式方式更新现有配置;若尚未创建,则新建资源。这是Kubernetes推荐的标准管理方式。

预期输出:

deployment.apps/nginx-production created

4.4 验证部署状态

4条命令即可快速检查Deployment全貌,各条命令用途如下:

1) 查看Deployment状态:

kubectl get deployment nginx-production

输出解读:

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-production   3/3     3            3           45s
  • READY 3/3:3个期望副本全部就绪

  • UP-TO-DATE 3:3个Pod已更新到最新版本

  • AVAILABLE 3:3个Pod已就绪超过minReadySeconds时间

2) 查看ReplicaSet:

kubectl get rs -l app=nginx-production

此命令通过标签筛选输出,可确认Deployment创建的ReplicaSet及其副本数状态。

3) 查看所有Pod及探针计时器初始化情况:

kubectl get pods -l app=nginx-production

注意Pod名称格式为nginx-production-<ReplicaSet哈希>-<随机后缀>,这是由ReplicaSet自动生成的唯一标识符。

4) 查看某个Pod的详细描述(含探针配置及其当前状态):

kubectl describe pod <pod-name>

在输出的Containers.nginx部分,可看到探针配置的完整回显及各探针的延迟参数、失败计数等信息。

# 便捷写法——直接获取Pod名并传入describe:
kubectl describe pod "$(kubectl get pods -l app=nginx-production -o jsonpath='{.items[0].metadata.name}')"

4.5 查看Pod内部健康检查端点

对于httpGet探针,可以直接在所有节点上使用curl测试健康检查端点是否正常响应(注意Pod内不一定安装curl,以下命令在其所在节点上执行):

# 获取Pod IP
kubectl get pod <pod-name> -o wide

# 在集群节点上测试存活探针端点
curl -v http://<Pod-IP>/healthz

# 测试就绪探针端点
curl -v http://<Pod-IP>/ready

Nginx默认不提供/healthz和/ready端点,因此在生产环境中需要配置Nginx返回这些路径。对于学习和测试,可通过进入Pod添加自定义配置,或使用支持内置健康检查端点的镜像(如各类微服务框架的应用镜像)。

4.6 验证探针行为

场景一——就绪探针测试:如果/ready端点返回非2xx/3xx状态码,Pod的READY列将显示0/1,且Service将不再向该Pod发送流量(Pod仍然Running,仅接收流量的条件被关闭):

# 就绪探针失败后查看Pod状态
kubectl get pods -l app=nginx-production -w

场景二——存活探针重启测试:如果/healthz端点返回失败,连续失败次数达到failureThreshold后,Pod的RESTARTS计数将增加,且STATUS会经历短暂的Error→Running状态变迁:

kubectl get pods -l app=nginx-production
# 观察RESTARTS列的变化

4.7 滚动更新实战

更新镜像版本为nginx:1.25.4:

kubectl set image deployment/nginx-production nginx=nginx:1.25.4

命令解析:kubectl set image deployment/<Deployment名称> <容器名称>=<新镜像>直接更新指定Deployment中指定容器的镜像版本,无需手动编辑YAML文件。此命令会触发Deployment控制器的滚动更新流程。

监控滚动更新进度:

kubectl rollout status deployment/nginx-production

预期输出:

Waiting for deployment "nginx-production" rollout to finish: 1 out of 3 new replicas have been updated...
Waiting for deployment "nginx-production" rollout to finish: 2 out of 3 new replicas have been updated...
deployment "nginx-production" successfully rolled out

查看更新历史版本:

kubectl rollout history deployment/nginx-production

此命令列出Deployment的所有历史REVISION及其对应的镜像变更记录。

4.8 版本回滚操作

回滚到上一稳定版本:

kubectl rollout undo deployment/nginx-production

命令解析:kubectl rollout undo deployment/<Deployment名>自动将Deployment恢复到上一个历史ReplicaSet的配置状态,包括镜像版本、环境变量等所有Pod模板内容。

回滚到指定的历史版本(先查看历史记录,获取REVISION编号):

kubectl rollout undo deployment/nginx-production --to-revision=2

4.9 查看实时日志

kubectl logs -f deployment/nginx-production

命令解析:kubectl logs -f deployment/<Deployment名>以follow模式实时查看该Deployment下所有Pod的日志流(控制台合并输出)。若Deployment有多个副本,此命令会从其中一个Pod流式输出。

若Pod中不存在curl但需要执行临时网络调试,可启动一个临时容器:

kubectl run debug-pod --image=busybox:1.28 --rm -it --restart=Never -- sh

第五部分:Deployment进阶话题

5.1 资源限制优化(Guaranteed/ Burstable/Best-Effort QoS类)

        Kubernetes根据Pod中容器设置的resources.requests和resources.limits为Pod分配三种QoS(Quality of Service)等级:

  • Guaranteed:每个容器的CPU和内存都设置了requests和limits,且两者数值相等(requests == limits)。Guaranteed Pod具有最高优先级,在节点资源紧张时最不容易被驱逐。

  • Burstable:至少一个容器设置了requests,但requests与limits不完全相等。Burstable Pod具有中等优先级。

  • Best-Effort:未设置任何requests和limits。Best-Effort Pod优先级最低,节点资源紧张时会被首先驱逐。

生产环境中建议使用Burstable或Guaranteed,以实现更稳定的服务质量。

5.2 revisionHistoryLimit的运维意义

        revisionHistoryLimit控制了历史ReplicaSet的保留数量,直接影响可回滚的版本数。如果该值设为0,所有历史ReplicaSet将被清理,kubectl rollout undo将彻底失效。在频繁更新的CI/CD流水线中,建议将revisionHistoryLimit设置为10~20,以在存储开销与回滚能力之间取得平衡。

5.3 批量重启Pod(使用rollout restart)

        在某些场景下(如ConfigMap更新后需要重新加载配置,或在开发/测试环境中快速测试),可能需要在不修改任何YAML内容的前提下统一重启Deployment管理的所有Pod。

传统做法需要首先触发滚动更新(如修改环境变量),而这会在Deployment历史中留下一条无意义的变更记录。自Kubernetes v1.15起,引入了一条更干净的指令:

kubectl rollout restart deployment/nginx-production

命令解析:kubectl rollout restart deployment/<Deployment名>通过为Pod模板注入一个时间戳注解,触发一次滚动更新,所有Pod将按顺序被重建。该操作会引起短暂的服务中断(视maxUnavailable参数而定),但只需一条命令、不影响回滚历史,在运维中极为常用。

5.4 水平自动扩缩容(HPA)简介

        Deployment支持通过Horizontal Pod Autoscaler(HPA)实现基于CPU/内存利用率的自动扩缩容。以下命令创建一个HPA,使Deployment在CPU达到50%时在3~10个副本之间动态扩展:

kubectl autoscale deployment nginx-production --min=3 --max=10 --cpu-percent=50

命令解析:kubectl autoscale deployment命令根据指定的最小/最大副本数和目标CPU使用率,自动创建HorizontalPodAutoscaler资源。HPA控制器会定期查询Metrics API获取Pod的CPU指标,并据此计算期望副本数。

5.5 生产环境探针最佳实践总结

  1. 务必配置三种探针:生产环境中所有Pod均应配置健康检查。至少配置readinessProbe和livenessProbe;启动时间较长的应用还需添加startupProbe。

  2. 就绪探针应包含依赖检查:如果应用依赖数据库、Redis、消息队列等外部服务,readinessProbe应能真实反映这些依赖的可用性——依赖不可用时标记为未就绪,等待依赖恢复后流量自动恢复,而非重启容器。

  3. 存活探针应仅检查自身状态:livenessProbe只应检查容器自身的内部状态(如死锁、死循环等不可恢复错误)。不要将外部依赖的可用性纳入livenessProbe——外部依赖不可用不应导致容器重启。

  4. 启动探针应足够宽松:startupProbe的failureThreshold×periodSeconds必须大于应用的最长启动时间。对于启动时间不确定的应用,宁可配置更长的窗口,也不要冒险误杀。

  5. 为探针设置合理的资源开销:periodSeconds不宜低于5秒;exec探针在高密度集群中应谨慎使用。

  6. 配合preStop钩子实现优雅下线:terminationGracePeriodSeconds应大于preStop钩子的执行时间,确保容器有足够时间完成清理工作(如关闭数据库连接、完成正在处理的请求等)。

结语

        本文以openEuler 24.03 LTS SP3为运行环境,从Deployment的控制器模式原理出发,深入讲解了Deployment YAML清单的全部核心字段(包括apiVersion/kind/metadata/spec/strategy/template及其子字段),同时结合三种Pod探针的类型区分、检查机制与参数调优,给出了可直接应用于生产环境的完整配置示例。通过将理论原理与逐字段注释相结合,读者应当能够扎实掌握Deployment与Pod探针的核心概念,并构建起从环境初始化到应用部署、探针验证、实时监控、滚动更新与版本回滚的完整操作闭环。

        Kubernetes的Deployment控制器与Pod探针机制是构建云原生应用的基石。掌握这些知识后,读者将有能力在生产环境中自信地部署、监控和维护无状态应用,为后续学习Service流量调度、Ingress路由规则、ConfigMap/Secret配置注入、StatefulSet有状态编排等更深层次的云原生技术打下坚实基础。

更多推荐