CKA 实战实验

发布: (2026年1月10日 GMT+8 07:40)
8 min read
原文: Dev.to

Source: Dev.to

主题覆盖

  • 启动 / 就绪 / 活跃探针
  • ConfigMaps
  • Secrets
  • 配置错误与修复

环境

  • Minikube
  • kubectl
  • 本地机器(macOS / Linux / Windows)
minikube start
kubectl get nodes

预期: STATUS: Ready

Source:

实验 1 – 启动探针(修复无限重启)

1️⃣ 损坏的清单 (lab1-broken.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: slow-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: slow
  template:
    metadata:
      labels:
        app: slow
    spec:
      containers:
        - name: app
          image: busybox
          command: ["sh", "-c"]
          args:
            - sleep 30; echo STARTED; sleep 3600
          livenessProbe:
            exec:
              command: ["sh", "-c", "echo ok"]
            initialDelaySeconds: 5
            periodSeconds: 5
# 应用损坏的清单
kubectl apply -f lab1-broken.yaml

# 验证 Pod 状态
kubectl get pods

结果 – Pod 进入 CrashLoopBackOff,因为存活探针在应用完成启动序列之前就已经开始执行。

# 检查 Pod 为何失败
kubectl describe pod <pod-name>

2️⃣ 修复后的清单 (lab1-fixed.yaml)

添加 startupProbe,使存活探针在容器准备好之前被阻塞。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: slow-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: slow
  template:
    metadata:
      labels:
        app: slow
    spec:
      containers:
        - name: app
          image: busybox
          command: ["sh", "-c"]
          args:
            - sleep 30; echo STARTED; sleep 3600
          startupProbe:
            exec:
              command: ["sh", "-c", "echo ok"]
            failureThreshold: 40   # 40 × 1 s = 40 s 总等待时间
            periodSeconds: 1
          livenessProbe:
            exec:
              command: ["sh", "-c", "echo ok"]
            initialDelaySeconds: 5
            periodSeconds: 5
# 应用修复后的清单
kubectl apply -f lab1-fixed.yaml

# 验证 Pod 正常启动
kubectl get pods

结果 – Pod 成功启动,没有重启。启动探针阻止了存活探针,直到容器报告已就绪。

📚 为什么这很重要

  • 启动缓慢的应用(例如 Java 服务、数据库、迁移任务)通常需要更多时间才能响应健康检查。
  • 若没有启动探针,过早的存活探针会导致 不必要的重启,并使 Pod 陷入崩溃循环。
  • 正确配置的启动探针 防止流量 被发送到不健康的 Pod,同时避免 反复重启。

Source:

实验 2 – 就绪探针(流量控制)

1. 损坏的清单

Deployment (lab2-broken.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ready-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ready
  template:
    metadata:
      labels:
        app: ready
    spec:
      containers:
        - name: app
          image: hashicorp/http-echo:0.2.3
          args:
            - "-listen=:8080"
            - "-text=HELLO"
          ports:
            - containerPort: 8080

Service (service.yaml)

apiVersion: v1
kind: Service
metadata:
  name: ready-svc
spec:
  selector:
    app: ready
  ports:
    - port: 80
      targetPort: 8080

应用清单

kubectl apply -f lab2-broken.yaml
kubectl apply -f service.yaml

观察

  • Pod 会 立即 接收流量,即使应用处于不健康状态。
  • 没有机制在 Pod 处于异常状态时阻止流量。
kubectl get endpoints ready-svc

2. 添加就绪探针

在 Deployment 中加入就绪探针:

readinessProbe:
  tcpSocket:
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 3

提示:readinessProbe 块插入到 lab2-broken.yaml 中容器定义下方,然后重新应用该文件。

应用更新后的 Deployment

kubectl apply -f lab2-broken.yaml   # 现在包含 readinessProbe

验证更改

kubectl get pods
kubectl get endpoints ready-svc

结果

  • 当就绪探针失败时,Pod 仍保持 Running 状态,但会 从 Service 的端点列表中移除
  • 因此,流量会自动停止路由到不健康的 Pod。

3. 为什么就绪探针很重要

好处说明
零停机部署只有在通过就绪检查后才会添加新 Pod,防止用户访问到故障实例。
自愈Kubernetes 可以重启或替换始终未就绪的 Pod,提高整体可靠性。
流量控制Service 只会将流量路由到已就绪的 Pod,降低错误率。

后续步骤: 试验不同的探针类型(httpGetexec),并根据应用的启动特性调节 initialDelaySecondsperiodSecondsfailureThreshold

Source:

实验 3 – 存活探针(自愈)

1. 损坏的清单(lab3-broken.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hang-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hang
  template:
    metadata:
      labels:
        app: hang
    spec:
      containers:
        - name: app
          image: nginx

应用清单:

kubectl apply -f lab3-broken.yaml

模拟容器挂起

# 获取 pod 名称(假设标签 `app=hang` 唯一)
POD=$(kubectl get pods -l app=hang -o jsonpath='{.items[0].metadata.name}')

# 停止容器内的 PID 1 以模拟挂起
kubectl exec -it "$POD" -- kill -STOP 1

# 验证 pod 状态
kubectl get pods

结果: 即使容器内部的应用已死,pod 仍保持 Running 状态。

2. 添加存活探针(lab3-fixed.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hang-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hang
  template:
    metadata:
      labels:
        app: hang
    spec:
      containers:
        - name: app
          image: nginx
          livenessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 10
            periodSeconds: 5

应用更新后的部署:

kubectl apply -f lab3-fixed.yaml
kubectl get pods

结果: 当探针失败时,Kubernetes 会自动重启 pod。存活探针提供自愈能力;没有它们时,Kubernetes 什么也不会做。

ConfigMap 行为

1. 创建 ConfigMap

kubectl create configmap app-config --from-literal=APP_COLOR=blue

2. 将 ConfigMap 用作环境变量

env:
  - name: APP_COLOR
    valueFrom:
      configMapKeyRef:
        name: app-config
        key: APP_COLOR

部署 Pod 后,编辑 ConfigMap:

kubectl edit configmap app-config   # 更改 APP_COLOR 的值

观察: 正在运行的 Pod 不会 自动获取新值。

kubectl rollout restart deployment <deployment-name>

关键点: 对于正在运行的容器,环境变量是不可变的;需要重启才能生效。

3. 将 ConfigMap 挂载为文件

volumes:
  - name: config
    configMap:
      name: app-config

volumeMounts:
  - name: config
    mountPath: /etc/config

编辑 ConfigMap 后,节点上的文件会更新,但应用程序必须手动重新加载该文件——Kubernetes 不会自动重启 Pod。

Secret Handling

创建一个密钥

kubectl create secret generic db-secret \
  --from-literal=DB_PASS=secret123

将密钥用作环境变量

env:
  - name: DB_PASS
    valueFrom:
      secretKeyRef:
        name: db-secret
        key: DB_PASS

检查密钥

kubectl describe pod <pod-name>

观察: Secrets 以 Base64 形式存储。当你运行 kubectl describe 时,解码后的值会以明文显示。

最佳实践

  • 将密钥视为敏感数据,绝不要将其提交到源码控制。
  • 使用 RBAC 限制对密钥的访问。
  • 如有可能,优先使用外部密钥管理解决方案。

RBAC(基于角色的访问控制)

  • 定义 RoleClusterRole 对象,仅授予工作负载真正需要的权限。
  • 绑定 这些角色到用户、组或服务账户,使用 RoleBindingClusterRoleBinding
  • 绝不要 使用 cluster-admin 权限运行工作负载。

摘要

  • 启动探针:延迟活跃性检查,直到容器真正准备好,防止慢启动应用出现无限重启。
  • 就绪探针:控制 Pod 是否接收流量,实现零停机时间的更新。
  • 存活探针:通过重启不健康的容器实现自我修复。
  • ConfigMap 对环境变量的更改需要重新启动 Pod;文件挂载会自动更新,但应用程序必须重新加载数据。
  • Secrets 是 base64 编码的;请谨慎处理并强制执行 RBAC。

故障排查技巧

  • 使用 kubectl describe 检查 Pod 和探针配置。
  • 使用 kubectl logs 查看容器输出。
  • 使用 kubectl exec 在运行中的容器内执行命令。
Back to Blog

相关文章

阅读更多 »

StatefulSet 项目

先决条件:StatefulSet 需要以下组件: - Headless Service —— 为每个 pod 提供稳定的 DNS。 - StatefulSet manifest —— 定义 pod……