配置高磁盘占用Pod自动更新

ACS集群的Pod临时存储空间不足时,为保障业务连续性,可利用 acs-instance-helper 组件配置自动监控策略,平滑轮转高磁盘占用 Pod,从而维持集群稳定性。

工作原理

ACS 实例默认提供 30 GiB 的免费临时存储空间(EphemeralStorage)。当临时存储空间被写满时,会导致业务受损。可部署acs-instance-helper组件,实现对达到磁盘存储阈值(98%)的 Pod 进行自动驱逐与轮转,尽量避免磁盘耗尽导致的业务损失。

  • 磁盘压力监控acs-instance-helper 持续监控 Pod 状况。当 Pod 的临时存储空间使用率超过阈值时,Pod的磁盘充足状态(ContainerHasSufficientDisk) 会更新为 False

  • 触发轮转更新:当该状况标记改变时,组件会自动结合无状态应用(如 Deployment)的在线扩容策略(先扩容,后销毁)和 PodDisruptionBudget(PDB) 的调度策略,实现 Pod 的平滑轮转。

适用范围

  • ACS集群版本为1.28及以上。

安装组件

  1. ACS控制台页面,单击目标集群名称,在集群详情页左侧导航栏,选择应用 > Helm

  2. Helm页面,单击创建

    1. 基本信息:在Chart中搜索acs-instance-helper,勾选搜索结果。

    2. 参数配置:Chart版本选择最新版。

acs-instance-helper组件进行全局配置

控制台

  1. 在目标集群详情页左侧导航栏,选择配置管理 > 配置项

  2. 配置项页面,单击使用YAML创建资源,然后将以下内容复制到模板区域,单击创建

kubectl

  1. 获取集群kubeconfig并通过kubectl工具连接集群

  2. 将以下YAML内容保存为acs-instance-helper-global-configmap.yaml文件,然后执行kubectl apply -f acs-instance-helper-global-configmap.yaml命令。

kind: ConfigMap
apiVersion: v1
metadata:
  namespace: kube-system
  name: acs-instance-helper-global-config
data:
  insufficientDiskEvictionSeconds: "300"
  customOnlineWorkloads: foo.io/SomeWorkload,bar.io/AnotherWorkload
  • insufficientDiskEvictionSeconds:从检测到磁盘压力到强制优雅下线的等待时间,单位为秒。默认值为 "300"(5分钟)。

  • customOnlineWorkloads:组件默认支持Deployment类型工作负载,可配置此项为组件添加额外支持的自定义工作负载类型。

    重要
    • 请确保自定义的工作负载控制器能够通过伸缩维持 Pod 的副本数(当副本数不足时,可以自动补充)。

    • 无法保证所有自定义工作负载都能实现磁盘达到压力阈值时的无损轮转,为自定义工作负载启用该功能时,请务必进行充分测试。

创建并配置工作负载

  • 为使 acs-instance-helper 能够管理应用,需为工作负载添加注解(annotations): ops.alibabacloud.com/enable-insufficient-disk-helper: "true"

  • 创建PDB,规定任何时候至少有 100% 的副本可用,如以下示例所示,轮转过程至少保证有2个副本可用。

控制台

  1. 在目标集群左侧导航栏,选择工作负载 > 无状态

  2. 无状态页面,单击使用YAML创建资源,然后将以下内容复制到模板区域,单击创建

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: app
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: app
      template:
        metadata:
          labels:
            app: app
          annotations:
            # 关键注解:为该工作负载启用功能
            ops.alibabacloud.com/enable-insufficient-disk-helper: "true"
        spec:
          containers:
            - image: registry-cn-hangzhou.ack.aliyuncs.com/dev/hello-world:v1
              name: main-container
              resources:
                limits:
                  cpu: "4"
                  memory: 8Gi
          restartPolicy: Always
    ---
    apiVersion: policy/v1
    kind: PodDisruptionBudget
    metadata:
      name: app-pdb
    spec:
      minAvailable: 100%
      selector:
        matchLabels:
          app: app
  3. 在弹窗中找到目标无状态应用,单击查看,确认Pod状态为Running。 

kubectl

  1. 将以下YAML内容保存为app.yaml文件,然后执行kubectl apply -f app.yaml命令。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: app
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: app
      template:
        metadata:
          labels:
            app: app
          annotations:
            # 关键注解:为该工作负载启用功能
            ops.alibabacloud.com/enable-insufficient-disk-helper: "true"
        spec:
          containers:
            - image: registry-cn-hangzhou.ack.aliyuncs.com/dev/hello-world:v1
              name: main-container
              resources:
                limits:
                  cpu: "4"
                  memory: 8Gi
          restartPolicy: Always
    ---
    apiVersion: policy/v1
    kind: PodDisruptionBudget
    metadata:
      name: app-pdb
    spec:
      minAvailable: 100%
      selector:
        matchLabels:
          app: app
  2. 确认目标应用Pod状态为Running

    kubectl get pods -l app=app

验证出现磁盘压力时的Pod自动轮转

  1. 将以下app-xxxapp-yyy替换成实际的Pod名称,在两个终端中分别向两个Pod写入数据,以模拟多个副本同时出现磁盘压力。

    # 终端 1
    kubectl exec app-xxx -- sh -c 'dd if=/dev/zero of=/largefile bs=1G count=30'
    # 终端 2
    kubectl exec app-yyy -- sh -c 'dd if=/dev/zero of=/largefile bs=1G count=30'
  2. 持续观察数分钟,可以看到当达到磁盘压力阈值时,两个Pod会依次被驱逐替换,且替换过程,始终有两个 Pod 保持 Running 状态:

    $ kubectl get po
    NAME         READY   STATUS        RESTARTS   AGE
    app-xxx      1/1     Terminating   0          12m
    app-yyy      1/1     Running       0          12m
    app-xxx-new  1/1     Running       0          11s

    app-xxx被驱逐替换后,app-yyy也开始被驱逐替换,最终出现两个新的Pod。

    $ kubectl get po
    NAME          READY   STATUS        RESTARTS   AGE
    app-yyy       1/1     Terminating   0          13m
    app-xxx-new   1/1     Running       0          1m
    app-yyy-new   1/1     Running       0          11s

应用于生产环境

  • 合理规划磁盘使用:此功能是应对磁盘压力的最后防线。最佳实践是优化应用,例如配置合理的ACS容器日志轮转或增大临时存储空间。

  • 监控与告警:配置针对 Pod 事件 NewInstanceCreationTriggeredInstanceEvictedGracefully 的告警,以便及时了解由磁盘压力引发的自动恢复操作。请参考使用阿里云Prometheus监控ACS集群状态

计费说明

安装 acs-instance-helper 组件将在您的集群中部署一个包含两个副本的 Deployment。每个副本的资源规格为 1 vCPU 和 2 GiB 内存,这将占用集群资源并产生相应费用。详细计费,请参考ACS算力计费说明

常见问题

此功能与 Kubelet 原生的磁盘压力驱逐(Disk Pressure Eviction)有何不同?

Kubelet 原生的强制驱逐发生在磁盘写满后,该过程不受 PDB 等机制保护。此外,由于磁盘已经完全写满,Pod 的优雅下线逻辑也可能执行失败。本功能通过提前执行驱逐,可以有效避免以上问题。