主题
更新网站内容
业务场景
云咖啡公司推出了新品咖啡,需要更新官网内容,展示新品信息。作为运维工程师,你需要在不影响用户访问的情况下完成网站更新。
需求:
- 更新网站内容,添加新品咖啡信息
- 确保更新过程中服务不中断
- 配置健康检查,确保服务可用性
- 设置资源限制,防止资源耗尽
学习目标
完成本课程后,你将掌握:
- Deployment 的滚动更新机制
- 如何实现零停机部署
- 健康检查(LivenessProbe 和 ReadinessProbe)
- 资源限制(requests 和 limits)
- 版本回滚操作
前置准备
1. 确认上一课程的环境
bash
# 检查命名空间是否存在
kubectl get namespace cloud-cafe
# 检查 Deployment 是否存在
kubectl get deployment -n cloud-cafe
# 检查 Service 是否存在
kubectl get svc -n cloud-cafe如果资源不存在,请先完成 01-云咖啡官网部署.md 课程。
2. 获取当前访问地址
bash
# 获取 NodePort 端口号
NODE_PORT=$(kubectl get svc cloud-cafe-nodeport -n cloud-cafe -o jsonpath='{.spec.ports[0].nodePort}')
# 获取节点 IP
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')
echo "当前访问地址: http://$NODE_IP:$NODE_PORT"实战步骤
Step 1: 理解滚动更新机制
概念: Deployment 的滚动更新会逐步替换旧版本的 Pod,确保在更新过程中始终有可用的 Pod 在运行。
让我们先查看当前的 Deployment 状态:
bash
# 查看 Deployment 详情
kubectl describe deployment cloud-cafe-web -n cloud-cafe
# 查看 ReplicaSet(每个版本对应一个 ReplicaSet)
kubectl get rs -n cloud-cafe
# 查看 Pod
kubectl get pods -n cloud-cafe观察要点:
- 当前有一个 ReplicaSet
- Pod 的标签包含
pod-template-hash,用于标识版本 - Deployment 的
REVISION字段显示当前版本号
Step 2: 准备新版本的网站内容
云咖啡公司推出了新品"焦糖玛奇朵",我们需要更新网站内容:
📌 ConfigMap 更新策略
生产环境中有两种更新 ConfigMap 的策略:
- 直接更新同名 ConfigMap - 更新配置后,重新加载 Pod(可能需要重启)
- 创建新的 ConfigMap 并更新 Deployment 引用 - 通过滚动更新实现零停机切换
本课程使用第二种策略,通过更新 Deployment 的 ConfigMap 引用来触发滚动更新。
首先,创建新的 index.html 文件(新品展示页面):
点击查看 index.html 内容(新品展示页面)
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>云咖啡公司 - 新品上市</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
padding: 50px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
h1 { font-size: 48px; margin-bottom: 20px; }
p { font-size: 24px; margin-bottom: 30px; }
.coffee { font-size: 80px; margin: 30px 0; }
.new-product {
background: rgba(255, 255, 255, 0.2);
border-radius: 15px;
padding: 30px;
margin: 30px auto;
max-width: 600px;
}
.badge {
background: #ff6b6b;
color: white;
padding: 5px 15px;
border-radius: 20px;
font-size: 14px;
display: inline-block;
margin-bottom: 15px;
}
</style>
</head>
<body>
<div class="coffee">☕</div>
<h1>欢迎来到云咖啡公司</h1>
<p>用心制作每一杯咖啡</p>
<div class="new-product">
<span class="badge">新品上市</span>
<h2>🍯 焦糖玛奇朵</h2>
<p>香浓焦糖与绵密奶泡的完美融合</p>
<p>限时特惠:¥28</p>
</div>
<p>我们的咖啡豆来自世界各地,经过精心烘焙</p>
<p>为您提供最优质的咖啡体验</p>
</body>
</html>然后,更新 ConfigMap:
bash
# 更新 ConfigMap(直接更新同名 ConfigMap)
kubectl create configmap cloud-cafe-html \
--from-file=index.html=index.html \
-n cloud-cafe \
--dry-run=client -o yaml | kubectl apply -f -
# 或者先删除再创建
# kubectl delete configmap cloud-cafe-html -n cloud-cafe
# kubectl create configmap cloud-cafe-html --from-file=index.html=index.html -n cloud-cafe
# 查看更新后的 ConfigMap
kubectl get configmap cloud-cafe-html -n cloud-cafe -o yamlStep 3: 执行滚动更新
现在我们使用新的 ConfigMap 更新 Deployment。
📌 关于
--dry-run=client参数的解释
--dry-run=client表示客户端干运行,只在本地验证配置,不实际发送到集群执行。作用:
- 验证 YAML 配置是否正确
- 预览将要创建/修改的资源
- 避免误操作导致生产事故
两种模式:
模式 说明 使用场景 --dry-run=client只在客户端验证 快速检查配置语法 --dry-run=server发送到 API Server 验证 验证资源是否符合集群策略
然后,更新 Deployment 触发滚动更新。由于 ConfigMap 更新后不会自动触发 Pod 重启,我们需要通过更新 Deployment 来触发滚动更新:
点击查看更新后的 deployment.yaml 内容
yaml
# 云咖啡官网 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloud-cafe-web
namespace: cloud-cafe
labels:
app: cloud-cafe-web
spec:
replicas: 3
selector:
matchLabels:
app: cloud-cafe-web
template:
metadata:
labels:
app: cloud-cafe-web
# 添加 annotation 来触发滚动更新
annotations:
configmap-version: "2026-02-26-v1"
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: html-content
mountPath: /usr/share/nginx/html
volumes:
- name: html-content
configMap:
name: cloud-cafe-html
items:
- key: index.html
path: index.htmlbash
# 方式一:使用独立的 YAML 文件(推荐)
kubectl apply -f deployment.yaml
# 方式二:使用 --dry-run 先验证
kubectl apply -f deployment.yaml --dry-run=client
kubectl apply -f deployment.yaml
# 方式三:通过更新 annotation 触发滚动更新
kubectl patch deployment cloud-cafe-web -n cloud-cafe -p \
'{"spec":{"template":{"metadata":{"annotations":{"configmap-version":"'$(date +%s)'"}}}}}'📌 为什么需要更新 Deployment 来触发滚动更新?
ConfigMap 更新后,已经运行的 Pod 不会自动获取新的配置。有两种方式让 Pod 使用新的 ConfigMap:
- 直接更新 Deployment - 修改 annotation 或配置,触发滚动更新
- 等待 Pod 重启 - 新创建的 Pod 会使用新的 ConfigMap
生产环境建议:
- 使用
kubectl rollout restart deployment/<name>触发滚动更新- 或在 Pod 模板中添加版本 annotation,更新 annotation 触发更新
- 或使用配置重载工具(如 Reloader)自动检测 ConfigMap 变化
观察滚动更新过程:
bash
# 在另一个终端窗口中实时查看 Pod 状态
kubectl get pods -n cloud-cafe -w
# 查看滚动更新状态
kubectl rollout status deployment/cloud-cafe-web -n cloud-cafe
# 查看 Deployment 的更新历史
kubectl rollout history deployment/cloud-cafe-web -n cloud-cafe观察要点:
- 旧的 Pod 逐个被终止
- 新的 Pod 逐个被创建
- 在更新过程中,始终有可用的 Pod
- ReplicaSet 会创建新的版本
Step 4: 验证更新结果
bash
# 查看新的 Pod
kubectl get pods -n cloud-cafe
# 查看新的 ReplicaSet
kubectl get rs -n cloud-cafe
# 访问网站,查看新内容
curl http://$NODE_IP:$NODE_PORT预期输出: 应该看到包含"焦糖玛奇朵"新品信息的新页面
测试服务连续性:
bash
# 在更新过程中持续访问服务,验证服务不中断
for i in {1..20}; do
curl -s http://$NODE_IP:$NODE_PORT | grep -o "云咖啡公司" && echo " - 请求 $i 成功"
sleep 0.5
doneStep 5: 配置健康检查
概念: 健康检查用于确保容器正常运行。Kubernetes 提供了三种探针:
- LivenessProbe: 检查容器是否存活,如果失败则重启容器
- ReadinessProbe: 检查容器是否准备好接收流量,如果失败则从 Service 中移除
- StartupProbe: 检查容器是否启动成功(用于启动慢的应用)
让我们为 Deployment 添加健康检查。
首先,编辑 deployment.yaml 文件,添加健康检查配置:
bash
# 编辑 deployment.yaml 文件
# 使用你喜欢的编辑器:vim、nano、或直接在IDE中编辑
vim deployment.yamldeployment.yaml 完整内容(包含健康检查配置):
点击查看 deployment.yaml 内容
yaml
# 云咖啡官网 Deployment
# 本次修改:添加健康检查配置(LivenessProbe 和 ReadinessProbe)
# 修改位置:在 containers[0] 下添加探针配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloud-cafe-web
namespace: cloud-cafe
labels:
app: cloud-cafe-web
spec:
replicas: 3
selector:
matchLabels:
app: cloud-cafe-web
template:
metadata:
labels:
app: cloud-cafe-web
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
# [新增开始] 健康检查配置
# LivenessProbe:检查容器是否存活,失败则重启容器
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10 # 容器启动后10秒开始检查,给应用启动时间
periodSeconds: 10 # 每10秒检查一次
timeoutSeconds: 5 # 超时时间5秒
failureThreshold: 3 # 连续失败3次才认为不健康,避免偶发波动
# ReadinessProbe:检查容器是否就绪,失败则从Service移除
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5 # 容器启动后5秒开始检查
periodSeconds: 5 # 每5秒检查一次
timeoutSeconds: 3 # 超时时间3秒
failureThreshold: 3 # 连续失败3次才认为不就绪
# [新增结束]
volumeMounts:
- name: html-content
mountPath: /usr/share/nginx/html
volumes:
- name: html-content
configMap:
name: cloud-cafe-html
items:
- key: index.html
path: index.html保存文件后,应用配置:
bash
# 应用更新后的 Deployment
kubectl apply -f deployment.yaml
# 等待更新完成
kubectl rollout status deployment/cloud-cafe-web -n cloud-cafe
# 查看 Pod 详情,确认健康检查已配置
kubectl describe pod -l app=cloud-cafe-web -n cloud-cafe | grep -A 10 "Liveness\|Readiness"观察要点:
- Pod 的 Events 中应该有健康检查的日志
- Pod 的状态应该是 Running 且 Ready
测试健康检查:
bash
# 查看健康检查事件
kubectl get events -n cloud-cafe --sort-by='.lastTimestamp'
# 模拟容器故障(进入 Pod 并停止 nginx)
> 📌 **关于 `--sort-by` 参数的解释**
>
> `--sort-by` 用于按指定字段对输出结果进行排序。
>
> **语法**:`--sort-by='.字段路径'`
>
> **常用示例**:
> ```bash
> # 按时间戳排序事件(最新的在最后)
> kubectl get events --sort-by='.lastTimestamp'
>
> # 按创建时间排序 Pod
> kubectl get pods --sort-by='.metadata.creationTimestamp'
>
> # 按重启次数排序(查看异常 Pod)
> kubectl get pods --sort-by='.status.containerStatuses[0].restartCount'
> ```
>
> **提示**:配合 `-o jsonpath` 可以查看可用的字段路径
```bash
kubectl exec -it $(kubectl get pod -l app=cloud-cafe-web -n cloud-cafe -o jsonpath='{.items[0].metadata.name}') -n cloud-cafe -- /bin/bash
# 在 Pod 内执行: nginx -s stop
# 退出 Pod,观察 Pod 是否被重启
exit
kubectl get pods -n cloud-cafe -w观察要点:
- LivenessProbe 检测到容器失败
- Pod 被自动重启
- 重启次数增加
Step 6: 设置资源限制
概念: 资源限制用于控制容器的资源使用,防止单个容器耗尽节点资源。
- requests: 容器需要的最小资源量(用于调度)
- limits: 容器可以使用的最大资源量(用于限制)
继续在 deployment.yaml 文件中添加资源限制配置:
bash
# 编辑 deployment.yaml 文件
vim deployment.yamldeployment.yaml 完整内容(在Step 5基础上添加资源限制):
点击查看 deployment.yaml 内容
yaml
# 云咖啡官网 Deployment
# 本次修改:添加资源限制(requests 和 limits)
# 修改位置:在 containers[0] 下添加 resources 配置
# 前置依赖:需要先完成 Step 5 的健康检查配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloud-cafe-web
namespace: cloud-cafe
labels:
app: cloud-cafe-web
spec:
replicas: 3
selector:
matchLabels:
app: cloud-cafe-web
template:
metadata:
labels:
app: cloud-cafe-web
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
# [新增开始] 资源限制配置
# requests:调度时保证的最小资源(用于节点筛选)
# limits:容器能使用的最大资源(硬性限制)
resources:
requests:
memory: "64Mi" # 请求64MB内存,确保节点有足够资源
cpu: "250m" # 请求0.25核CPU(1000m = 1核)
limits:
memory: "128Mi" # 最多使用128MB内存,超出会被OOMKilled
cpu: "500m" # 最多使用0.5核CPU,超出会被限制
# [新增结束]
# [Step 5已添加] 健康检查配置
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10 # 容器启动后10秒开始检查
periodSeconds: 10 # 每10秒检查一次
timeoutSeconds: 5 # 超时时间5秒
failureThreshold: 3 # 连续失败3次才认为不健康
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5 # 容器启动后5秒开始检查
periodSeconds: 5 # 每5秒检查一次
timeoutSeconds: 3 # 超时时间3秒
failureThreshold: 3 # 连续失败3次才认为不就绪
volumeMounts:
- name: html-content
mountPath: /usr/share/nginx/html
volumes:
- name: html-content
configMap:
name: cloud-cafe-html
items:
- key: index.html
path: index.html保存文件后,应用配置:
bash
# 应用更新后的 Deployment
kubectl apply -f deployment.yaml
# 等待更新完成
kubectl rollout status deployment/cloud-cafe-web -n cloud-cafe
# 查看 Pod 的资源使用情况
kubectl top pods -n cloud-cafe观察要点:
- Pod 的 QoS 类别(Burstable、Guaranteed、BestEffort)
- 实际资源使用情况
查看 QoS 类别:
bash
# 查看 Pod 的 QoS 类别
kubectl get pod -l app=cloud-cafe-web -n cloud-cafe -o jsonpath='{.items[0].status.qosClass}'
# 解释 QoS 类别:
# - Guaranteed: 同时设置了 requests 和 limits,且两者相等
# - Burstable: 设置了 requests,但 requests < limits
# - BestEffort: 没有设置 requests 和 limitsStep 7: 版本回滚
场景: 假设新版本出现了问题,我们需要快速回滚到旧版本。
bash
# 查看更新历史
kubectl rollout history deployment/cloud-cafe-web -n cloud-cafe
# 查看特定版本的详细信息
kubectl rollout history deployment/cloud-cafe-web -n cloud-cafe --revision=2
# 回滚到上一个版本
kubectl rollout undo deployment/cloud-cafe-web -n cloud-cafe
# 等待回滚完成
kubectl rollout status deployment/cloud-cafe-web -n cloud-cafe
# 验证回滚结果
curl http://$NODE_IP:$NODE_PORT预期输出: 应该看到旧版本的页面(没有"焦糖玛奇朵"新品信息)
回滚到指定版本:
bash
# 再次更新到新版本
kubectl set image deployment/cloud-cafe-web nginx=nginx:latest -n cloud-cafe
kubectl rollout status deployment/cloud-cafe-web -n cloud-cafe
# 回滚到指定版本(例如版本 2)
kubectl rollout undo deployment/cloud-cafe-web -n cloud-cafe --to-revision=2
# 等待回滚完成
kubectl rollout status deployment/cloud-cafe-web -n cloud-cafe验证和测试
1. 检查所有资源状态
bash
# 查看 Deployment
kubectl get deployment -n cloud-cafe
# 查看 Pod
kubectl get pods -n cloud-cafe
# 查看 Service
kubectl get svc -n cloud-cafe
# 查看 ConfigMap
kubectl get configmap -n cloud-cafe2. 测试滚动更新的连续性
bash
# 在一个终端中持续访问服务
while true; do
curl -s http://$NODE_IP:$NODE_PORT | grep -o "云咖啡公司" && echo " - $(date)"
sleep 1
done在另一个终端中执行更新:
bash
# 更新 Deployment
kubectl set image deployment/cloud-cafe-web nginx=nginx:1.21 -n cloud-cafe
# 观察第一个终端的输出,确认服务不中断3. 测试健康检查
bash
# 查看健康检查事件
kubectl get events -n cloud-cafe --sort-by='.lastTimestamp' | grep -i "probe"
# 查看最近的 Pod 事件
kubectl describe pod -l app=cloud-cafe-web -n cloud-cafe | tail -204. 测试资源限制
bash
# 查看 Pod 的资源使用情况
kubectl top pods -n cloud-cafe
# 查看 Pod 的资源限制配置
kubectl get pod -l app=cloud-cafe-web -n cloud-cafe -o jsonpath='{.items[0].spec.containers[0].resources}'📝 总结和思考
本课程学到的知识点
- 滚动更新: 逐步替换旧版本 Pod,确保服务连续性
- 健康检查: LivenessProbe 和 ReadinessProbe 确保服务可用性
- 资源限制: requests 和 limits 控制资源使用
- 版本回滚: 快速回退到之前的版本
- 更新历史: 查看和管理 Deployment 的版本历史
关键概念
- 零停机部署: 通过滚动更新实现服务不中断
- 自愈能力: 健康检查自动重启失败的容器
- 资源隔离: 资源限制防止单个容器影响其他容器
- 版本管理: Deployment 自动管理多个版本
思考题
- 滚动更新过程中,如果新版本的 Pod 启动失败,会发生什么?
- LivenessProbe 和 ReadinessProbe 有什么区别?分别在什么场景下使用?
- 如果只设置 limits 不设置 requests,会发生什么?
- 如何控制滚动更新的速度?(提示:maxSurge 和 maxUnavailable)
最佳实践
- 始终配置健康检查: 确保服务可用性
- 合理设置资源限制: 防止资源耗尽
- 测试回滚流程: 确保能够快速回退
- 监控更新过程: 及时发现问题
下一步
本课程学习了如何安全地更新应用,并配置健康检查和资源限制。
下一课程将学习如何添加数据库,实现数据持久化。
下一课程: 03-订单系统部署.md
清理环境
如果你想清理本课程创建的资源:
bash
# 删除 Deployment(会删除相关的 Pod 和 ReplicaSet)
kubectl delete deployment cloud-cafe-web -n cloud-cafe
# 删除 Service
kubectl delete svc cloud-cafe-svc cloud-cafe-nodeport -n cloud-cafe
# 删除 ConfigMap
kubectl delete configmap cloud-cafe-html -n cloud-cafe
# 删除命名空间
kubectl delete namespace cloud-cafe提示: 如果你要继续学习下一个课程,建议保留这些资源,因为下一个课程会在此基础上进行。