Hot For Coding

简单场景下k8s的CronJob与容器内Crontab计划任务对比

full k8s docker crontab

背景

需求是这样的,需要部署一批静态站点在Kubernetes上,这批静态站点的所有静态资源全都推送在Git仓库的某个固定分支下,比如master分支下。对部署的要求特别简单,只需要把仓库克隆到本地,然后Nginx的root参数值修改到仓库目录位置即可,例子如下

rm -rf /var/www/html
git clone --depth=1 https://github.com/lizhongit/static.git /var/www/html

默认Nginx的default server的root路径就在/var/www/html下,注意必须先删除/var/www/html,否则克隆会失败提示你目录已存在。另外,建议添加上--depth=1参数只克隆第一层,因为作为部署资源来说,没有必要clone整个仓库,那会造成下载资源众多导致部署周期变长。

初次部署的方案搞定了,接下来就是更新,更新其实并不复杂,只需要隔一段时间执行以下命令即可,比如每隔五分钟执行一下更新命令

cd /var/www/html
git pull

接下来要实现这个计划任务面临以下两个方案选择了

方案一:依赖k8s CronJob

这种方案,比较贴合k8s的环境,k8s提供了CronJob方案解决所有计划任务的需求,例子如下

deployment.yaml


apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: html
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: html
  resources:
    requests:
      storage: 100Mi

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web

spec:
  replicas: 1
  selector:
    matchLabels:
      app: web

  template:
    metadata:
      labels:
        app: web

    spec:
      containers:
      - name: web
        image: ubuntu

        env:
        - name: DEBIAN_FRONTEND
          value: noninteractive

        ports:
        - containerPort: 80

        command: 
        - /bin/sh
        - -c
        - |
            apt update
            apt install -y git nginx
            rm -rf /var/www/html
            git clone --depth=1 https://github.com/lizhongit/static.git /var/www/html
            /usr/sbin/nginx -g 'daemon off;'

        volumeMounts:
        - name: html
          mountPath: /var/www/html

      volumes:
      - name: html
        persistentVolumeClaim:
          claimName: "html"

---

apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
  - name: web
    port: 80
    targetPort: 80

---

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: update
spec:
  schedule: "*/5 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: crontab
            image: ubuntu
            
            env:
            - name: DEBIAN_FRONTEND
              value: noninteractive

            command:
            - /bin/sh
            - -c
            - |
                cd /html
                apt update
                apt install -y git
                git pull

            volumeMounts:
            - name: html
              mountPath: /html

          volumes:
          - name: html
            persistentVolumeClaim:
              claimName: "html"

以上YAML配置文件主要创建了一个Deployment和CronJob,Deployment负责运行Web静态服务器,CronJob负责每五分钟使用git pull命令更新内容。虽说能工作,但这种方案有以下缺点

  • 需要额外创建一个可支持多个Pod读写的PVC
  • 需要创建CronJob

方案二:依赖容器内的Crontab程序

接下来,我们来介绍这种依赖容器内的Crontab程序达到更新的目的,先上YAML配置

deployment.yaml


apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web

spec:
  replicas: 1
  selector:
    matchLabels:
      app: web

  template:
    metadata:
      labels:
        app: web

    spec:
      containers:
      - name: web
        image: ubuntu

        env:
        - name: DEBIAN_FRONTEND
          value: noninteractive

        ports:
        - containerPort: 80

        command: 
        - /bin/sh
        - -c
        - |
            apt update
            apt install -y git cron nginx
            rm -rf /var/www/html
            git clone --depth=1 https://github.com/lizhongit/static.git /var/www/html
            cat <<EOF | tee /etc/cron.d/web-cron
            */5 * * * * cd /var/www/html && /usr/bin/git pull

            EOF
            chmod 0644 /etc/cron.d/web-cron
            crontab /etc/cron.d/web-cron
            cron
            /usr/sbin/nginx -g 'daemon off;'

---

apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
  - name: web
    port: 80
    targetPort: 80

测试一下

$ kubectl apply -f deployment.yaml
deployment.apps/web created

$ kubectl get svc
NAME      TYPE         CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
web       ClusterIP    10.110.192.135   <none>        80/TCP    4m27s

$ curl 10.110.192.135
<!DOCTYPE html>
<html lang="zh-hans">
  <head>
    <meta charset="UTF-8" />
    <title>琼台博客</title>
  </head>
  <body>
    <h1>Hello World</h1>
    <a href="https://www.qttc.net">琼台博客</a>
  </body>
</html>

以上方案相比第一种有以下优点

  • 不需要PVC做存储支持
  • 不需要额外部署CronJob
  • 由于不依赖PVC,所以可以横向扩展大量副本用于高并发

以上YAML文件均测试可用,大家也可以在自己的环境上试试!

分享

TITLE: 简单场景下k8s的CronJob与容器内Crontab计划任务对比

LINK: https://www.qttc.net/533-k8s-cronjob-and-container-crontab.html

NOTE: 原创内容,转载请注明出自琼台博客