k8s通过OpenKruise实现精准缩容(三)

引言

        在前面的两个章节中,我们介绍了Kubernetes的调度策略、HPA的工作原理和实现Pos极致弹性伸的核心组件Openkruise,接下来将进入实践分享环节,看到最后相信你会收获更多精彩,也烦请大家关注一下我们的公众号哈。

背景

        最近,我和几位同行朋友探讨了一个关于渲染农场资源管理的实际挑战。我们讨论的焦点是如何有效地缩减渲染农场中的闲置资源,以降低成本。在当前的作业负载(Workload)管理过程中,我们遇到了一个具体的问题:在执行容器副本的缩容操作时,系统无法优先终止那些处于闲置状态的Pod,而那些正在运行的非闲置Pod在优雅退出(Graceful Termination)过程中耗时较长。

        特别是在使用云服务提供商的Serverless产品进行容器化部署时,这一问题变得尤为突出。因为在这种场景下,Pod的数量和它们的运行时间直接影响到成本--运行的Pod越多,累计的运行时间越长,产生的成本也就越高。因此,能否快速且精确地让那些闲置的Pod优先退出,成为了有效管理资源和控制成本的关键。

方案

        在Kubernetes 1.22版本开始,默认开启了pod-deletion-cost特性,允许用户设置Pod的删除成本,它是一个整数值,可以为正数、零或负数,分值越低在缩容时的优先级越高。我在网上翻过很多资料,大多都是通过手动修改,亦或编写脚本进行批量修改,但似乎都不是很理想,在我的不懈努力下,终于找到一个最佳实践方案,我们可以借助Openkruise的自定义探针PodProbeMarker自动给Pods注入pod-deletion-cost的分值,将CPU使用率较低的删除成本设置为5,将CPU使用率较高的设置为10,当然也可以根据任务的空闲和繁忙状态进行定义,接下来我将分享具体的实现过程。

实践分享(满满干货)

实验环境

Kubernetes 1.24

Openkruise 1.6

 

安装

PodProbeMarker能力默认是关闭的, 你可以通过 feature-gate PodProbeMarkerGate 

打开,如下: 

helm install kruise openkruise/kruise --version 1.6.3 --set featureGates="PodProbeMarkerGate=true"

创建nginx演示服务,命名为nginx.yaml

apiVersion: apps/v1 
kind: Deployment
metadata:
  name: nginx
  namespace: hpa
  labels:
    app: nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx  
  template:
    metadata:
      labels:
        app: nginx
        nginx-idle: 'xxx'   # 如果是闲置的时候会显示为ture
      annotations:
        controller.kubernetes.io/pod-deletion-cost: '100'  # 初始删除成本我们设置为100
    spec:
      containers:
      - name: nginx
        image: nginx:1.16.1
        ports:
        - containerPort: 80
        resources:
          requests:       # 必须设置,否则HPA无法运行
            cpu: 100m     # 设置容器运行时所需CPU资源
            memory: 200Mi # 设置容器运行时所需内存资源
          limits:         # 不是必须设置,但是设置后可以避免压测时占用过多资源
            cpu: 200m      # 限制容器CPU资源为200m,m 是毫核(milli-cores)的缩写,因此200m表示0.2核
            memory: 400Mi   # 限制容器内存资源为400Mi 
---
kind: Service
apiVersion: v1
metadata:
  name: nginx
  namespace: hpa
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

然后执行kubectl apply -f nginx.yaml完成部署

 

21671446798f56443b4a8480118a7e4e.png

接着我们创建一个HPA控制器,当CPU使用率均值达到50%,则触发弹性扩缩容,我们把稳定窗口设置为300s,避免使用率波动导致Pods频繁伸缩,想要更深入了解HPA的同学可以看下我们的第一章节哈,接着,我们将如下内容保存为hpa.yaml

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nginx-hpa
  namespace: hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx
  minReplicas: 2  # Deployment可缩容的容器数量下限,需设置为大于等于1的整数
  maxReplicas: 10  # 该Deployment可扩容的容器数量上限,需大于minReplicas
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50 # 目标资源的平均使用率,即资源使用量的平均值与其请求量之间的比例
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
    scaleUp:
      stabilizationWindowSeconds: 300

同样也是执行kubectl apply -f hpa.yaml完成部署,创建完成后我们可以通过kubectl get hpa -n hpa查看HPA是否创建成功,成功则有如下显示

 

02b476e5f192103051cee86915b3ccb3.png

好了,最后就是我们的重头戏,创建PodProbeMarker控制器,我们利用自定义探测脚本idle.sh来判断Pods的CPU是否处于空闲,如果空闲则将删除成本设置为5,如果繁忙则设置为10。我们将下面的内容保存为probe.yaml

apiVersion: apps.kruise.io/v1alpha1
kind: PodProbeMarker
metadata:
  name: nginx-probe
  namespace: hpa
spec:
  selector:
    matchLabels:
      app: nginx
  probes:
  - name: Idle
    containerName: nginx
    probe:
      exec:
        command:
        - /home/nginx/idle.sh
      initialDelaySeconds: 10
      timeoutSeconds: 3
      periodSeconds: 10
      successThreshold: 1
      failureThreshold: 3
    markerPolicy:
    - state: Succeeded
      labels:
        nginx-idle: 'true'
      annotations:
        controller.kubernetes.io/pod-deletion-cost: '5'
    - state: Failed
      labels:
        nginx-idle: 'false'
      annotations:
        controller.kubernetes.io/pod-deletion-cost: '10'
    podConditionType: nginx.io/idle

 对的,也是通过执行kubectl apply -f probe.yaml完成部署,在完成部署后,我们可以通过如下指令查看当前Pods的删除成本,如下是繁忙状态,所有的容器删除成本均从100自动修改为10,现在确实有点小激动,毕竟是全网唯一讲解如何自动注入pod-deletion-cost的分享。

kubectl get pods -l app=nginx -n hpa -o json | jq '.items[] | {POD_NAME: .metadata.name, POD_DELETION_COST: .metadata.annotations["controller.kubernetes.io/pod-deletion-cost"]}'

0a3e4d2869f047bcb167773c1148e3ba.png

我们还要验证下,当空闲的时候是否会将删除成本修改为5呢?好的,我们让其中一个Pod的CPU冷静下,然后再执行上述pod-deletion-cost分值查看指令,果不其然,在CPU冷静后,这个Pod的删除成本变成了5。

abbd9a6e16a748fc8e7e97ea3cadc7cf.png别急,还没结束,我们来减少其中一个副本,看看是否删除成本分值低的优先被删除,执行如下指令缩减副本

kubectl scale deployment nginx -n hpa --replicas=1

407f8006e67c430796c6a3a5575de0a1.png

查看缩容后的情况,我们发现真的是分值较小的Pod被删除了,很好,我们做到了。 

8042570b143d4f538d34d081926c8631.png 

总结 

        这是一个很惊喜的案例,我们可以精准地将闲置的Pods进行缩容,可以更快地结束容器,从而节省更多的成本,当然实际的场景可能更复杂,但是都可以举一反三,相信这篇文章对于容器副本数量较多的资源管理场景会有帮助,大家如果有什么需要了解,或者需要我分享的内容,也可以在下面留言,谢谢! 

欢迎订阅我的公众号「SRE运维手记」,可扫下方二维码,或者微信搜“SRE运维手记”

e45dc07b6fd04114a9f5fe6f4772a886.jpeg

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值