전에 이 위키의 백업이 어떤 식으로 이루어지는지를 적은 적이 있었는데 쿠버네티스 위에서는 어떻게 바꿨는지 적어 보자.

Job의 생성

다음과 같은 Job을 기술하였다. 잡이란 것도 결국 컨테이너가 실행되는 것이므로 .spec.template.spec 아래 containers에 간단히 Pod을 기술하면 된다.

apiVersion: batch/v1
kind: Job
metadata:
  name: dropbox-backup-to-wiki
spec:
  template:
    spec:
      containers:
      - name: backup
        image: cublr/dropbox-uploader
        command: ["/tmp/backup_docs.sh"]
        volumeMounts:
        - name: backup-docs
          mountPath: /tmp/backup_docs.sh
          subPath: backup_docs.sh
        - name: dropbox-auth
          mountPath: /root/.dropbox_uploader
          subPath: .dropbox_uploader
        - name: wiki-data
          mountPath: /mnt
      volumes:
      - name: backup-docs
        configMap:
          name: backup-docs
          defaultMode: 0777
      - name: dropbox-auth
        configMap:
          name: dropbox-auth
      - name: wiki-data
        persistentVolumeClaim:
          claimName: wiki-volumes
      restartPolicy: Never

전에도 이야기했지만 간단한 백업을 위해 andreafabrizi/Dropbox-Uploader의 스크립트를 사용하는데, 쿠버네티스 위에서 동작하여야 하므로 컨테이너를 생성하였다. 단, 라즈베리 파이가 아닌 오드로이드 위에서 그대로 사용하기엔, 저장소의 Dockerfile이 문제가 있는 것 같아서 도커파일을 매우 간단하게 다시 구성해서 이미지화하고 이를 cublr/dropbox-uploader에 업로드하였다. 그래서 이 잡이 실행되면 cublr/dropbox-uploader 이미지가 실행된다.

이 도커 이미지는 ENTRYPOINT가 이미 지정되어 있다. 이전에 구성했던 백업 스크립트를 그대로 사용하고 싶기 때문에 이를 컨테이너에 넣어 다시 실행해야 한다. 하지만 퍼블릭하게 공개되는 이미지에 그런 스크립트를 넣기가 그래서 ConfigMap을 사용하였다. 도커 이미지가 실행될 때 파일로 마운트되고, 위 yaml의 command를 사용해서 이미지의 ENTRYPOINT를 오버라이드한다.

마찬가지로 dropbox_uploader.sh 스크립트는 드롭박스의 억세스 키가 필요하므로, 이 또한 ConfigMap에 저장한다. 백업 대상이 되는 PersistentVolumeClaim도 마찬가지로 마운트한다.

이 잡이 실행되면 다음과 같은 결과를 확인할 수 있다.

$ kubectl create -f backup.yaml 
job.batch/dropbox-backup-to-wiki created

$ kubectl get pod
NAME                                      READY   STATUS    RESTARTS   AGE
dropbox-backup-to-wiki-ss686              1/1     Running   0          18s

$ kubectl logs dropbox-backup-to-wiki-ss686
./
./linux/
./linux/article/
...
./playground/openvswitch-virtualbox.txt
 > Uploading "/tmp/2019-12-13T10:33:55-w.cublr.com.tar.gz" to "/docs/2019/12/13/2019-12-13T10:33:55-w.cublr.com.tar.gz"... DONE

잡이 무사히 실행된 것을 봤으니 이번엔 CronJob을 만들어 보자. 크론잡은 잡의 상위 객체 정도 되므로, 크론잡의 정의는 잡을 포함한다. 잡은 팟을 포함하는 것처럼. 따라서 yaml의 정의는 이런 식으로 구성된다.

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: wiki-backup-periodically
spec:
  schedule: "0 * * * *"
  successfulJobsHistoryLimit: 48
  failedJobsHistoryLimit: 48
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: cublr/dropbox-uploader
            command: ["/tmp/backup_docs.sh"]
            volumeMounts:
            - name: backup-docs
              mountPath: /tmp/backup_docs.sh
              subPath: backup_docs.sh
            - name: dropbox-auth
              mountPath: /root/.dropbox_uploader
              subPath: .dropbox_uploader
            - name: wiki-data
              mountPath: /mnt
          volumes:
          - name: backup-docs
            configMap:
              name: backup-docs
              defaultMode: 0777
          - name: dropbox-auth
            configMap:
              name: dropbox-auth
          - name: wiki-data
            persistentVolumeClaim:
              claimName: wiki-volumes
          restartPolicy: Never

이를 등록하면 쿠버네티스에서 spec.schedule에 따라 알아서 잡을 실행할 것이다.

$ kubectl get pod
NAME                                        READY   STATUS      RESTARTS   AGE
wiki-backup-periodically-1576234800-slkt9   0/1     Completed   0          121m
wiki-backup-periodically-1576238400-mfklp   0/1     Completed   0          60m
wiki-backup-periodically-1576242000-jzl8h   0/1     Completed   0          58s

한 시간마다 한 번씩 실행된 것을 확인할 수 있다.