K8s详细学习笔记 第八章:应用的扩缩容与更新策略
第八章:应用的扩缩容与更新策略
在云原生时代,应用的生命周期远不止于“部署”这一步。一个成功的应用需要能够优雅地应对流量的波峰波谷,并能以最小的风险、最快的速度迭代更新。Kubernetes为此提供了一整套强大且自动化的工具,让应用的**弹性(Elasticity)和敏捷性(Agility)**不再是难题。
本章将深入探讨两大核心主题:
- 应用的扩缩容:如何根据实际需求,动态地增加或减少应用的Pod副本数量,以达到资源利用和性能表现的最佳平衡。
- 应用的更新策略:如何将应用从一个版本升级到另一个版本,同时确保服务的连续性和稳定性,实现真正的零停机发布。
8.1 手动扩缩容: kubectl scale命令的使用
在深入了解自动化机制之前,我们先从最直接、最简单的手动扩缩容开始。Kubernetes提供了kubectl scale命令,允许你快速地修改Deployment、ReplicaSet、StatefulSet等可伸缩资源的副本数量。
这是一种命令式的操作,当你明确知道需要多少个副本时,它非常有用。
使用场景:
- 计划内活动:在进行市场推广活动或预期有流量高峰之前,手动扩容。
- 紧急应对:发现服务负载过高,作为应急措施快速增加副本。
- 资源节省:在业务低谷期(如深夜),手动缩容以节省成本。
- 测试与调试:在测试环境中快速调整副本数以模拟不同场景。
命令语法:
kubectl scale [--replicas=COUNT] <resource_type>/<resource_name>
实践示例:
假设我们有一个在前面章节创建的名为nginx-deployment的Deployment,初始replicas为3。
-
扩容(Scale Out):将Nginx应用的副本数从3个增加到5个。
kubectl scale --replicas=5 deployment/nginx-deployment执行命令后,你会看到输出
deployment.apps/nginx-deployment scaled。此时,Deployment控制器会立即开始工作,创建2个新的Pod,直到总数达到5个。你可以通过kubectl get pods来观察这个过程。 -
缩容(Scale In):将Nginx应用的副本数从5个减少到2个。
kubectl scale --replicas=2 deployment/nginx-deployment同样,Deployment控制器会优雅地终止3个Pod,直到总数剩下2个。
背后原理:kubectl scale命令本质上只是一个快捷方式,它所做的就是修改Deployment资源对象在etcd中存储的YAML定义,将其spec.replicas字段的值更新为你指定的数字。Deployment控制器监测到这个“期望状态”的变化后,便会采取行动(增加或减少Pod),使“实际状态”与“期望状态”保持一致。
局限性:
手动扩缩容虽然简单,但其局限性也非常明显:它依赖于人的判断和干预,无法实时响应不可预测的负载变化。要实现真正的弹性,我们必须依赖自动化机制。
8.2 水平Pod自动扩缩容(HPA)
Horizontal Pod Autoscaler (HPA)是Kubernetes中实现应用自动化弹性的核心组件。它能够自动地根据观察到的CPU利用率、内存使用量或其他自定义指标,来调整Pod的副本数量。
“水平”扩缩容指的是通过增减Pod的数量来调整应用的整体处理能力,与之对应的是“垂直”扩缩容(Vertical Pod Autoscaling, VPA),即调整单个Pod的CPU或内存大小。HPA是无状态应用扩缩容最常用的方式。
HPA工作的前提条件
为了让HPA能够正常工作,必须满足两个关键前提:
-
Metrics Server的部署: HPA需要一个数据来源来获取Pod的资源使用指标。Metrics Server是Kubernetes集群中的一个核心插件,它从每个节点的
kubelet收集资源使用数据(CPU、内存),并通过Kubernetes API聚合起来,以metrics.k8s.ioAPI的形式暴露给其他组件使用。没有Metrics Server,HPA就如同一个没有眼睛的司机,无法做出任何决策。- 在大多数托管的K8s服务(如GKE, EKS, AKS)和一些本地工具(如Docker Desktop)中,Metrics Server是默认安装的。你可以通过
kubectl top pods和kubectl top nodes命令来检查它是否正常工作。
- 在大多数托管的K8s服务(如GKE, EKS, AKS)和一些本地工具(如Docker Desktop)中,Metrics Server是默认安装的。你可以通过
-
为Pod设置资源请求(Requests): 这是最容易被忽略但至关重要的前提。HPA在计算CPU利用率时,使用的公式是:
当前CPU利用率 = Pod当前实际CPU使用量 / Pod的CPU请求值(Requests)
如果你没有在Pod的容器定义中设置resources.requests.cpu,那么HPA就无法计算利用率百分比,也就无法工作。这再次强调了第七章中为Pod设置requests的重要性。
HPA的工作原理:一个持续的控制循环
HPA由Master节点上的Controller Manager中的一个专用控制器(HPA Controller)实现。其工作流程是一个经典的控制循环:
- 用户定义HPA: 用户创建一个HPA资源对象,指定要监控的目标(如一个Deployment)、扩缩容的副本数范围(
minReplicas和maxReplicas),以及触发扩缩容的指标阈值(例如,CPU平均利用率达到80%)。 - 周期性检查: HPA控制器以一个可配置的周期(默认为15秒)运行。
- 获取指标: 在每个周期,HPA控制器通过
metrics.k8s.ioAPI从Metrics Server查询目标(如Deployment)下所有Pod的当前指标值(例如,每个Pod的CPU使用量)。 - 计算期望副本数: 控制器将所有Pod的指标值进行平均,得到一个当前的平均指标值。然后,它使用一个核心算法来计算期望的副本数:
期望副本数 = ceil [ 当前副本数 * ( 当前平均指标值 / 期望指标值 ) ]ceil是向上取整函数。- 例如:当前有3个副本,期望CPU利用率为50%,当前实际平均利用率为75%。那么期望副本数 =
ceil [ 3 * ( 75% / 50% ) ]=ceil [ 3 * 1.5 ]=ceil [ 4.5 ]= 5个。
- 执行扩缩容: 如果计算出的期望副本数与当前副本数不同,HPA控制器就会更新目标Deployment的
spec.replicas字段。 - Deployment响应: Deployment控制器接管后续工作,根据新的
replicas值来创建或删除Pod。 - 冷却时间: 为了防止因指标值的瞬时抖动而导致频繁的扩缩容(称为“抖动”或“颠簸”),HPA在执行一次扩容后,会进入一个冷却期(默认为3分钟),在此期间不会再次执行扩容。缩容的冷却期则更长(默认为5分钟)。
实践示例:为Deployment配置HPA
让我们为一个PHP-Apache应用创建一个Deployment,并为其配置HPA。
步骤1:创建Deployment和Service
这个Deployment运行一个会消耗CPU的PHP页面。
# php-apache.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-apache
spec:
selector:
matchLabels:
run: php-apache
replicas: 1
template:
metadata:
labels:
run: php-apache
spec:
containers:
- name: php-apache
image: k8s.gcr.io/hpa-example
ports:
- containerPort: 80
# !!!必须设置requests!!!
resources:
requests:
cpu: 200m
---
apiVersion: v1
kind: Service
metadata:
name: php-apache
spec:
selector:
run: php-apache
ports:
- port: 80
````kubectl apply -f php-apache.yaml`
**步骤2:创建HPA资源**
* **使用`kubectl autoscale`命令(快捷方式)**:
```bash
kubectl autoscale deployment php-apache \
--cpu-percent=50 \
--min=1 \
--max=10
```
这条命令会创建一个HPA,目标是`php-apache`这个Deployment,当其Pod的平均CPU利用率超过50%时触发扩容,副本数范围在1到10之间。
* **使用YAML文件(声明式)**:
```yaml
# hpa.yaml
apiVersion: autoscaling/v2beta2 # 使用v2beta2可以支持更多类型的指标
kind: HorizontalPodAutoscaler
metadata:
name: php-apache-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache # 指向要扩缩容的目标
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50 # 目标CPU利用率
```
`kubectl apply -f hpa.yaml`
**步骤3:施加负载并观察HPA工作**
1. **监控HPA状态**: 打开一个新的终端,持续观察HPA的状态。
```bash
kubectl get hpa -w
```
初始状态下,`TARGETS`应该显示一个较低的百分比,例如 `<unknown>/50%` 或 `2%/50%`。
2. **施加负载**: 打开另一个终端,创建一个临时的Pod来向`php-apache`服务发送大量请求。
```bash
kubectl run -it --rm load-generator --image=busybox -- /bin/sh
# 在load-generator的shell中,执行无限循环的wget
# while true; do wget -q -O- http://php-apache; done
```
3. **观察扩容**: 回到第一个终端,你会看到HPA的状态开始变化:
* `TARGETS`列的CPU利用率会迅速飙升,远超50%。
* `REPLICAS`列的数字会从1开始,逐渐增加到2, 3, 4... 直到CPU利用率稳定在50%左右。
* 你可以通过`kubectl get pods`看到新的Pod被创建出来。
4. **撤销负载并观察缩容**:
* 在`load-generator`的终端中,按`Ctrl+C`停止循环,然后`exit`退出Pod。
* 再次观察HPA的状态。`TARGETS`列的CPU利用率会下降到接近0%。
* 等待缩容的冷却时间(默认为5分钟)过后,你会看到`REPLICAS`的数量会逐渐减少,最终回到`minReplicas`所设定的1个。
这个实验完整地展示了HPA如何自动化地维护应用的性能和资源使用。
### 8.3 Deployment的更新策略
在敏捷开发和DevOps实践中,频繁地发布新版本的应用是常态。Deployment资源通过其`spec.strategy`字段,提供了两种内置的更新策略来管理这个过程。
#### 1. Recreate(重新创建)
* **机制**: 这是一种简单粗暴的“先删后建”策略。当触发更新时,Deployment控制器会**首先终止所有**正在运行的旧版本Pod。当所有旧Pod都被完全删除后,它才会开始创建新版本的Pod。
* **优点**: 策略简单,逻辑清晰。可以确保在任何时候,集群中都不会同时存在新旧两个版本的应用实例,这对于某些无法兼容新旧版本共存的应用(例如,数据库schema发生重大不兼容变更)是必要的。
* **缺点**: **会导致服务中断**。在旧Pod被删除和新Pod启动并准备好接收流量之间,会有一段明显的服务不可用时间窗口。
* **适用场景**: 极少用于生产环境的在线服务。适用于开发环境、一次性任务,或可以接受停机窗口的维护场景。
```yaml
# deployment-recreate.yaml
spec:
replicas: 3
strategy:
type: Recreate # 明确指定策略类型
2. RollingUpdate(滚动更新) - 默认策略
- 机制: 这是一种平滑、优雅的“渐进式替换”策略。当触发更新时,Deployment控制器会逐个地用新版本的Pod替换旧版本的Pod,同时确保在整个更新过程中,始终有一定数量的Pod在对外提供服务。
- 优点: 实现零停机发布。用户的流量会被平滑地从旧版本迁移到新版本,对用户完全无感。
- 缺点: 更新过程比
Recreate慢。在更新期间,集群中会同时存在新旧两个版本的Pod,需要应用自身能够处理这种情况(向后兼容)。 - 适用场景: 绝大多数生产环境应用更新的标准选择。
滚动更新的行为可以通过两个非常重要的参数进行精细化控制:maxSurge 和 maxUnavailable。
【重难点】 理解HPA的工作原理和指标选择,掌握滚动更新中的maxSurge和maxUnavailable参数以实现精细化发布控制
HPA的工作原理与指标选择深度解析
-
HPA的核心是期望状态与实际状态的比较:再次强调,HPA是Kubernetes声明式API哲学的完美体现。它不断地将用户定义的“期望指标”(如CPU 50%)与从Metrics Server获取的“实际指标”进行比较,并计算出一个“期望副本数”,然后通过修改Deployment的
replicas字段来驱动整个系统趋向于这个新的期望状态。 -
指标选择的艺术:
- CPU利用率: 最常用、最直观的指标,适用于CPU密集型应用(如视频转码、复杂计算)。它的优点是响应灵敏。
- 内存使用量: 这是一个非常棘手的指标,通常不建议作为HPA的主要触发条件。原因是,很多应用(尤其是Java等带垃圾回收机制的语言)在内存使用量上升后,并不会轻易地将其归还给操作系统,即使负载下降。这会导致Pod数量只增不减,无法有效缩容。内存指标更适合用于垂直Pod自动扩缩容(VPA)。
- 自定义指标(Custom Metrics): 对于业务应用来说,CPU利用率往往不能直接反映业务负载。例如,一个I/O密集型的Web应用,其瓶颈可能在于并发连接数或请求处理队列。通过适配器(如Prometheus Adapter),HPA可以基于从Prometheus等监控系统采集的任何自定义指标进行扩缩容,例如:
requests_per_second(每秒请求数)queue_length(消息队列长度)active_sessions(活跃用户会话数)
使用自定义指标通常能更准确、更及时地反映真实业务压力,是构建高级弹性系统的关键。
精细化发布控制:maxSurge与maxUnavailable的策略艺术
这两个参数定义了滚动更新过程中的“步调”和“边界”,共同决定了更新的速度、风险和资源消耗。它们可以被设置为一个绝对数字(如1)或一个百分比(如25%)。
假设我们有一个replicas: 10的Deployment。
-
maxUnavailable(最大不可用):- 含义: 在滚动更新期间,最多允许有多少个Pod处于不可用状态。不可用的Pod包括正在被删除的旧Pod和尚未完全就绪的新Pod。
- 作用: 控制了服务的最低可用容量。
- 示例:
maxUnavailable: 20%(即2个Pod)。这意味着在任何时刻,Kubernetes都必须保证至少有 10 - 2 = 8 个Pod是健康且可用的。它会先删除2个旧Pod,然后创建2个新Pod,等待新Pod就绪后,再进行下一轮替换。
-
maxSurge(最大峰值):- 含义: 在滚动更新期间,最多允许比期望的
replicas数量多出多少个Pod。 - 作用: 控制了更新的速度和资源消耗。
- 示例:
maxSurge: 25%(即2.5,向上取整为3个Pod)。这意味着在任何时刻,Pod的总数最多不能超过 10 + 3 = 13 个。Kubernetes可以先创建3个新Pod,然后再删除3个旧Pod,从而加快更新速度。
- 含义: 在滚动更新期间,最多允许比期望的
这两个参数是协同工作的,Kubernetes会在不违反任何一个约束的前提下执行更新。
不同策略配置下的行为分析:
| 策略组合 (replicas: 10) | 行为 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
默认值 maxSurge: 25% maxUnavailable: 25% |
一边创建2-3个新Pod,一边删除2-3个旧Pod。总副本数在8到13之间波动。 | 均衡了速度、资源和可用性。 | 无明显缺点,是通用选择。 | 大多数常规应用发布。 |
高可用优先 (金丝雀/蓝绿) maxSurge: 100% maxUnavailable: 0 |
先创建10个新Pod。当所有新Pod都Ready后,再瞬间将流量切换过去,并删除所有10个旧Pod。 |
绝对的零服务容量损失。更新期间总容量会翻倍,切换速度快。 | 需要双倍的节点资源来容纳新旧两套Pod。 | 对可用性要求极高的核心服务,发布窗口期的资源充足。 |
资源受限环境 maxSurge: 0 maxUnavailable: 1 (或 10%) |
必须先删除1个旧Pod,释放出资源后,才能创建1个新Pod。总副本数不会超过10。 | 不占用任何额外资源。 | 更新速度最慢,并且服务容量会暂时下降。 | 节点资源极其紧张,可以接受较慢更新和轻微容量波动的环境。 |
快速发布 maxSurge: 50% maxUnavailable: 50% |
同时创建5个新Pod,并删除5个旧Pod,以非常快的速度进行替换。 | 发布速度极快。 | 风险较高,如果新版本有问题,会快速影响到一半的服务实例。 | 测试环境或对发布速度要求极高、且回滚机制非常完善的场景。 |
YAML示例:配置一个高可用优先的更新策略
apiVersion: apps/v1
kind: Deployment
metadata:
name: critical-service
spec:
replicas: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0 # 保证服务容量不低于10
maxSurge: "100%" # 允许额外创建10个Pod
通过灵活地组合maxSurge和maxUnavailable,你可以根据应用的特性、资源状况和风险偏好,设计出最适合你的发布策略,从而在敏捷迭代和系统稳定性之间找到完美的平衡点。这正是Kubernetes声明式配置强大能力的体现。
K8s 详细学习笔记 目录
以下是整个系列的10章目录,点击章节标题即可跳转阅读:
- K8s详细学习笔记 第一章:K8s入门与核心概念
- K8s详细学习笔记 第二章:部署你的第一个应用:Pod与Deployment
- K8s详细学习笔记 第三章:应用访问与服务发现:Service与Ingress
- K8s详细学习笔记 第四章:应用配置管理:ConfigMap与Secret
- K8s详细学习笔记 第五章:数据持久化:Volume与Persistent Storage
- K8s详细学习笔记 第六章:应用的健康检查与自愈能力
- K8s详细学习笔记 第七章:资源的限制与调度
- K8s详细学习笔记 第八章:应用的扩缩容与更新策略
- K8s详细学习笔记 第九章:K8s安全机制:认证、授权与准入控制
- K8s详细学习笔记 第十章:集群运维与故障排查
更多推荐
所有评论(0)