주기적으로 실행되는 앱은 CronJob으로

Page content

만일 job을 일정 주기 혹은 특정 시간에 실행시키려면 CronJob resource를 만들어 사용하면 된다.

JobCronJob간의 관계는?

CronJob에 대한 설명에 따르면 CronJob정의에 기술한 특정 시간이 되면 CronJobJob을 실행한다고. 그리고 그 JobPod를 실행한다.

그럼 Job을 위한 resource 정의와 CronJob을 위한 resource 정의를 각각 정의해야 하나? 그렇지는 않은 듯. CronJob의 정의 파일을 보면 JobTemplate 항목이 Job에서 볼 수 있는 Template과 유사한 container spec 등을 가지고 있다. 물론 CronJob 에서만 유효한 schedule spec 등을 추가로 가지고 있긴 하지만.

job.yamlcronjob.yaml을 둘 다 가진 경우

실제로 job.yamlcron.yaml 을 모두 가지고 있는 mysqldump의 helm chart를 확인하면 다음과 같다. charts/stable/mysqldump at master · helm/charts · GitHub

$ head -n 4 cron.yaml
{{- if ne .Values.schedule "now" -}}
apiVersion: batch/v1beta1
kind: CronJob
metadata:

$ head -n 4 job.yaml
{{- if eq .Values.schedule "now" -}}
apiVersion: batch/v1
kind: Job
metadata:

즉, Value 파일에 정의한 schedule 값이 now인 경우에는 Job을 deploy하고, 그렇지 않으면 CronJob을 deploy한다. 그러므로 하나의 Helm chart 의 templates 디렉토리에서 한 시점에 deploy될 resource type이 Job이나 CronJob 중 하나만 있어야 하는 듯. 같은 맥락에서 Job/CronJob이 아닌 Deployment가 있어도 Helm install 명령이 어떤 resource를 deploy할 지 판단할 수 없으므로 YAML 파일의 if문 등을 적절히 이용해서 한 번에 하나의 resource 만 deploy되도록 해야 한다(아마도)

CronJob 배포

Helm을 이용한 deploy는 여느 Deployment, Job과 동일한 방법으로 진행한다.

$ helm install -f pocket-stat-value.yaml pocket-stat helm-chart/charts/pocket-stat
NAME: pocket-stat
LAST DEPLOYED: Fri Oct  9 22:57:09 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
  export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services pocket-stat)
  export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT

일단 Helm 명령으로 Helm install 명령 자체는 잘 처리되었는 지 확인해 본다. 아래 pocket-stat chart가 deployed로 나오므로 최소한의 단계는 넘어간 듯

$ helm list
NAME       	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART            	APP VERSION
grafana    	default  	1       	2020-10-04 23:01:12.99628996 +0900 KST 	deployed	grafana-5.7.0    	7.2.0
influxdb   	default  	1       	2020-10-03 10:22:32.033591453 +0900 KST	deployed	influxdb-4.8.5   	1.8.0
pocket-stat	default  	1       	2020-10-09 22:57:09.385381052 +0900 KST	deployed	pocket-stat-0.1.0	1.16.0
podcast    	default  	1       	2020-10-03 08:57:19.676194777 +0900 KST	deployed	nginx-0.2.0      	1.0
sosa0sa    	default  	1       	2020-10-03 08:48:33.124989027 +0900 KST	deployed	nginx-0.2.0      	1.0

Job이나 Deployment에서와 같이 Pod 상태를 확인해 보면 없다

$ kubectl get pods | grep pocket-stat

혹시나 하고 CronJob 항목을 확인해 보니 뭔가 있다. Value에서 지정한 Schedule대로 매일 00:10 AM에 동작하도록 정보(10 0 * * *)가 나오는 거 보면 정상적으로 배포가 된 듯

cychong@mini1:~/work/Helm$ kubectl get cronjob
NAME          SCHEDULE     SUSPEND   ACTIVE   LAST SCHEDULE   AGE
pocket-stat   10 0 * * *   False     0        <none>          4m10s

앞에서 적은 대로 CronJobDeploymentJob과 달리 일단 Pod를 생성하는 게 아니라 지정된 시간이 되면 Job을 만들고, 해당 Job에 의해 Pod가 배포되는 방식이므로 아직 Pod가 생성되지 않는 것이다. 내일 밤 00:10 이 지난 후에 다시 kubectl get cronjob 명령으로 LAST SCHEDULE, ‘ACTIVE` 등의 항목이 어떻게 변경되는 지 확인하면 실제로 동작했는 지 확인할 수 있을 듯.

CronJob 삭제

CronJob 삭제는 delete cronjob 명령을 사용한다.

$ kubectl delete cronjob pocket-stat
cronjob.batch "pocket-stat" deleted

$ kubectl get cronjob
No resources found in default namespace.

그런데 여전히 helm에는 남아있네

$ helm list
NAME       	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART            	APP VERSION
grafana    	default  	1       	2020-10-04 23:01:12.99628996 +0900 KST 	deployed	grafana-5.7.0    	7.2.0
influxdb   	default  	1       	2020-10-03 10:22:32.033591453 +0900 KST	deployed	influxdb-4.8.5   	1.8.0
pocket-stat	default  	1       	2020-10-09 22:57:09.385381052 +0900 KST	deployed	pocket-stat-0.1.0	1.16.0
podcast    	default  	1       	2020-10-03 08:57:19.676194777 +0900 KST	deployed	nginx-0.2.0      	1.0
sosa0sa    	default  	1       	2020-10-03 08:48:33.124989027 +0900 KST	deployed	nginx-0.2.0      	1.0

$ helm uninstall pocket-stat
release "pocket-stat" uninstalled

이제 helm repo에 반영.

이제 Cronjob으로 사용할 chart를 github에 만든 helm chart repo에 반영하고 다시 CronJob을 배포해 본다.

$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "influxdata" chart repository
...Successfully got an update from the "infracloudio" chart repository
...Successfully got an update from the "myhelmrepo" chart repository
...Successfully got an update from the "grafana" chart repository
Update Complete. ⎈Happy Helming!⎈

$ helm search repo pocket-stat
NAME                  	CHART VERSION	APP VERSION	DESCRIPTION
myhelmrepo/pocket-stat	0.1.0        	1.16.0     	A Helm chart for Kubernetes

이제 local filesystem에 있는 chart가 아니라 myhelmrepo에 있는 chart를 이용해서 deploy해 본다.

$ helm install -f pocket-stat-value.yaml pocket-stat myhelmrepo/pocket-stat
NAME: pocket-stat
LAST DEPLOYED: Fri Oct  9 23:38:15 2020
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
  export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services pocket-stat)
  export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT

helm 배포가 정상적으로 되었는 지 확인해 보고

$ helm list |grep pocket-stat
pocket-stat	default  	1       	2020-10-09 23:38:15.375862343 +0900 KST	deployed	pocket-stat-0.1.0	1.16.0

CronJob도 잘 배포 되었는 지 확인해 본다.

$ kubectl get cronjob
NAME          SCHEDULE     SUSPEND   ACTIVE   LAST SCHEDULE   AGE
pocket-stat   10 0 * * *   False     0        <none>          16s

아직 한번 도 실행이 되지 않은 상태라 LAST SCHEDULE 항목이 none으로 출력되는데 나중에 한번이라도 실행이 되면, 해당 시간과 현재 시각과의 차이를 보여줄 듯