k8s

BroadcastJob + Advanced CronJob 定期清理节点磁盘

背景

节点磁盘是一种单调递减资源,虽然节点有监控,但是也只是个监控没法清理。所以需要一个定时任务来执行清理磁盘。crontab 可以实现,只适合于本地脚本和命令的定时执行。

在k8s中 CronJob 也可以实现,并且提供了内置的失败处理和重试机制,也可以配置失败后重试的次数。同时可以通过 Prometheus 来监控任务的执行状态。而且 Job 只需要临时地占用一些节点资源,任务执行完毕后会自动释放。

但 CronJob 也有一些限制:

  • 默认的调度规则是随机的,一个节点上可能创建多个 Pod,造成重复作业的问题;
  • 无法自适应集群节点的规模,当集群中添加/删除一个节点时,需要手动调整 Job 的配置。

OpenKruise BroadcastJob 则很好地克服了原生 Job 在节点运维场景中的不足之处。它允许用户以类似 DaemonSet 调度的方式来编排 Pod,当用户创建 BroadcastJob 后,它会默认在集群的每一个 worker 节点创建一个 Pod,执行完成之后会自动对 Pod 进行清理。同时,搭配 Advanced CronJob,可以将 BroadcastJob 进行定时发下,从而实现定时清理节点磁盘的能力。

环境

当前磁盘空间情况如下:

file

查看镜像有很多升级版本遗留的镜像。

file

构建镜像

cat Dockerfile

FROM registry.cn-hangzhou.aliyuncs.com/wgh9626/debian:latest

COPY crictl /bin/
COPY clean.sh /bin/
RUN chmod +x /bin/clean.sh && chmod +x /bin/crictl

CMD ["sh", "/bin/clean.sh"]

docker build -t registry.cn-hangzhou.aliyuncs.com/wgh9626/clean:latest .
docker push registry.cn-hangzhou.aliyuncs.com/wgh9626/clean:latest

注意这里不能用alpine镜像,因为alpine镜像中没有bash命令。容器会报这个错:Error: failed to create containerd task: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "bash": executable file not found in $PATH: unknown

这样构建镜像pod启动后仍然会报这个错,因为下面的脚本中使用了[ $? -eq 0 ],这个需要bash。所以这里有两种方案,一种是使用其他镜像比如debian,ubuntu等,第二种是安装bash。
RUN apk add --no-cache bash。我这使用debian了。

清理脚本

cat clean.sh

#!/bin/sh

echo "container runtime endpoint:" $CONTAINER_RUNTIME_ENDPOINT

# 检查是否有启动的容器
crictl ps > /dev/null
if [ $? -eq 0 ]
then
    crictl ps | awk '{if(NR>1){print $2}}' > used-images.txt
    crictl images | grep registry.aliyuncs.com | awk '{print $3}' > target-images.txt

    # # 删除带有registry.aliyuncs.com的未使用的镜像。
    sort target-images.txt used-images.txt used-images.txt | uniq -u | xargs -r crictl rmi
else
    echo "crictl does not exist"
fi

exit 0

创建Advanced CronJob

apiVersion: apps.kruise.io/v1alpha1
kind: AdvancedCronJob
metadata:
  name: acj-test
spec:
  schedule: "*/1 * * * *"
  startingDeadlineSeconds: 60
  template:
    broadcastJobTemplate:
      spec:
        template:
          spec:
            containers:
              - name: node-cleaner
                image: registry.cn-hangzhou.aliyuncs.com/wgh9626/clean:latest
                imagePullPolicy: IfNotPresent
                env:
                - name: CONTAINER_RUNTIME_ENDPOINT
                  value: unix:///var/run/containerd/containerd.sock
                volumeMounts:
                - name: containerd
                  mountPath: /var/run/containerd
                terminationMessagePath: /tmp/termination-log
                terminationMessagePolicy: File
            volumes:
            - name: containerd
              hostPath:
                path: /var/run/containerd
            restartPolicy: OnFailure
            dnsPolicy: ClusterFirst
        completionPolicy:
          type: Always
          ttlSecondsAfterFinished: 90
        failurePolicy:
          type: Continue
          restartLimit: 3

以hostPath的方式将该 containerd.sock 挂载到容器中以执行crictl命令。CronJob 定义成每隔1分钟执行一次清除动作方便测试,真实的场景中,我们可以每隔几天甚至几周清理一次。

file

k apply -f job.yaml

job执行成功。

file

查看kruise-controller-manager的日志可以看到job下次执行时间。

k logs -n kruise-system kruise-controller-manager-555d7f7959-ngb6w --tail 1000 | grep "No upcoming scheduled times"

file

删除了几个镜像后,磁盘空间也释放了一点。

file

分类: k8s
0 0 投票数
文章评分
订阅评论
提醒
guest

0 评论
最旧
最新 最多投票
内联反馈
查看所有评论

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部
0
希望看到您的想法,请您发表评论x