Files
cs-note/hhs/MS/05-部署运维/02-Kubernetes/04-扩缩容与有状态应用.md
T
2026-05-24 11:42:38 +08:00

6.5 KiB
Raw Blame History

tags, create time
tags create time
kubernetes
hpa
autoscaling
statefulset
horizontal-pod-autoscaler
2026-05-18 00:30

K8s 扩缩容与有状态应用 — HPA & StatefulSet

概述

K8s 提供多种扩缩容机制。HPA 基于 CPU/Memory 或其他自定义指标实现 Pod 级别的弹性伸缩,适用于无状态服务。StatefulSet 则是数据库、消息队列等有状态组件的理想选择。两者各有适用场景。

HPA 弹性伸缩

基础示例

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: order-service-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: order-service
  minReplicas: 3
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70   # CPU > 70% 时扩容
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60   # 扩容稳定期
      policies:
      - type: Pods
        value: 2
        periodSeconds: 60             # 每分钟最多扩 2 个
    scaleDown:
      stabilizationWindowSeconds: 300  # 缩容稳定期 5min(防抖动)

扩展指标:基于自定义 Metric 扩缩容

  metrics:
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: "100"           # 每个 Pod 平均 100 QPS 时扩容
  - type: Object
    object:
      metric:
        name: active_users
      describedObject:
        apiVersion: apps/v1
        kind: Deployment
        name: web-app
      target:
        type: Value
        value: "500"                  # 每 500 活跃用户触发一次扩容

[!info] HPA 的工作机制

HPA 控制器每 15 秒查询 Metrics Server(CPU/Memory)或自定义 Metrics Adapter(QPS 等),计算所需 Replica 数。公式:ceil(当前指标值 / 目标指标值 × 当前副本数)。为了防止抖动,scaleDown 的稳定窗口通常比 scaleUp 长很多。

HPA 调优最佳实践

参数 推荐值 说明
averageUtilization (CPU) 60~70% 低于 60% 浪费资源,高于 80% 延迟风险大
scaleUp.stabilizationWindow 0~60s 突发流量快速响应
scaleDown.stabilizationWindow 300~600s 防止抖动导致的频繁扩缩
pods[].periodSeconds 60s 限制扩容频率,避免雪崩

StatefulSet — 有状态应用

Deployment 适合无状态服务,而有状态服务(数据库、分布式协调器等)需要 稳定的网络标识 + 有序的启停。StatefulSet 就是为此而生的控制器。

完整示例

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql-cluster
spec:
  serviceName: mysql           # 绑定 Headless Service
  replicas: 3
  podManagementPolicy: Parallel  # 并行启动(生产建议 OrderedReady 逐步启动)
  
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      partition: 0             # 从最后一个 Pod 开始逐步滚动
  
  selector:
    matchLabels:
      app: mysql
  
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        ports:
        - containerPort: 3306
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
  
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 20Gi

StatefulSet 的核心特性

特性 说明
稳定名称 Pod 名为 {statefulset-name}-{ordinal},如 mysql-cluster-0
有序部署 默认依次启动:0 → 1 → 2(设置 Parallel 可并行)
有序删除 反向删除:2 → 1 → 0(保证主从切换安全)
持久化存储 volumeClaimTemplates 为每个 Pod 独立创建 PVC,Pod 重建后数据不丢失
Headless Service 需搭配 ClusterIP: None 的 Service,每个 Pod 有独立的 DNS 记录

StatefulSet vs Deployment 对比

维度 Deployment StatefulSet
Pod 命名 随机后缀 {name}-{0,1,2,...}
存储 共享 PVC 或不持久 每个 Pod 独立 PVC
启动顺序 并发 串行(默认)
删除顺序 随机 逆序
DNS 稳定性 每次重建 IP 变 域名不变
适用场景 Web/API 无状态服务 DB、ZooKeeper、Kafka

[!note] 为什么有状态应用不适合 Deployment?

Deployment 会随机销毁和重建 Pod——这意味着 PVC 会被重新绑定到不同的 Pod,存储卷中的数据和节点 ID 完全错位。StatefulSet 保证同一个 Pod 始终使用同一片存储,这对数据库、Kafka、ZooKeeper 等组件至关重要。

Headless Service — StatefulSet 的灵魂搭档

apiVersion: v1
kind: Service
metadata:
  name: mysql-headless
spec:
  clusterIP: None                # 关键:不分配 ClusterIP
  selector:
    app: mysql
  ports:
  - port: 3306

通过 DNS 可以直接访问单个 Pod:

  • mysql-cluster-0.mysql-headless.production.svc.cluster.local:3306
  • mysql-cluster-1.mysql-headless.production.svc.cluster.local:3306

补充:Vertical Pod Autoscaler (VPA)

HPA 只管 Pod 数量,不管单 Pod 的资源配置。如果你经常遇到 OOMKill 或 CPU Throttling,可以尝试 VPA:

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: order-service-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: order-service
  updatePolicy:
    updateMode: "Auto"       # Auto / Initial / Off
  resourcePolicy:
    containerPolicy:
      minAllowed:
        cpu: 100m
        memory: 128Mi
      maxAllowed:
        cpu: "2"
        memory: 4Gi

[!warning] VPA 的限制

VPA 在调整资源时会驱逐并重建 Pod。与 HPA 不同,VPA 不能无缝运行——建议在开发/测试环境中先用 Initial 模式观察推荐值,确定合理后再切到 Auto。生产环境通常结合 HPA(管数量)+ 手动调优 Resources(管质量)。

关联笔记