CKA 实战实验
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,降低错误率。 |
后续步骤: 试验不同的探针类型(httpGet、exec),并根据应用的启动特性调节 initialDelaySeconds、periodSeconds 和 failureThreshold。
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(基于角色的访问控制)
- 定义
Role或ClusterRole对象,仅授予工作负载真正需要的权限。 - 绑定 这些角色到用户、组或服务账户,使用
RoleBinding或ClusterRoleBinding。 - 绝不要 使用
cluster-admin权限运行工作负载。
摘要
- 启动探针:延迟活跃性检查,直到容器真正准备好,防止慢启动应用出现无限重启。
- 就绪探针:控制 Pod 是否接收流量,实现零停机时间的更新。
- 存活探针:通过重启不健康的容器实现自我修复。
- ConfigMap 对环境变量的更改需要重新启动 Pod;文件挂载会自动更新,但应用程序必须重新加载数据。
- Secrets 是 base64 编码的;请谨慎处理并强制执行 RBAC。
故障排查技巧
- 使用
kubectl describe检查 Pod 和探针配置。 - 使用
kubectl logs查看容器输出。 - 使用
kubectl exec在运行中的容器内执行命令。