はじめに
今回はKubernetesのCronJob
リソースでkubectl
コマンドを実行し、定期的にリソースを更新する方法について、メモを残しておきます。
やりたいことは以下の通りです。
今回はgit
kubectl
それぞれのコマンドを実行することのできるコンテナイメージを利用し、2つのコンテナ間でEmptyDir
Volumeを共有することで、マニフェストファイルのデプロイを実行しました。
CronJobの利用方法
CronJob
からkubectl
コマンドを実行するには、CronJob
がkubectl
コマンドを実行できるよう権限を付与する必要があります。そのため、まずはService AccountとRole/Rolebindingを作成します。今回はDeployment
リソースの作成を目的としていたため、以下のようなRoleを付与しました。
apiVersion: v1 kind: ServiceAccount metadata: name: internal-kubectl --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: modify-deployments rules: - apiGroups: ["apps"] resources: - deployments verbs: - get - create - update - patch - list - delete --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: modify-pods-to-sa subjects: - kind: ServiceAccount name: internal-kubectl roleRef: kind: Role name: modify-deployments apiGroup: rbac.authorization.k8s.io
また、利用するGitHubのリポジトリがプライベートリポジトリの場合は、以下のようなSecret
リソースをあらかじめ作成しておきます。
apiVersion: v1 kind: Secret metadata: name: forgithubaccess type: Opaque data: username: <base64-GItHub account> password: <base64-GitHub access token>
これでCronJob
を利用する準備ができたので、次にCronJob
を作成します。今回は、以下のような定義ファイルを利用しました。
apiVersion: batch/v1beta1 kind: CronJob metadata: name: cronjob-git-kubectl spec: schedule: "*/1 * * * *" # 毎分実行する jobTemplate: spec: template: spec: serviceAccountName: internal-kubectl # 事前に作成したService Accountを指定 containers: - name: git image: alpine/git:latest env: - name: SECRET_USERNAME valueFrom: secretKeyRef: name: forgithubaccess key: username - name: SECRET_PASSWORD valueFrom: secretKeyRef: name: forgithubaccess key: password command: ["git", "clone"] args: ["https://$(SECRET_USERNAME):$(SECRET_PASSWORD)@github.com/<Account>/<Repository>.git", "/cache"] volumeMounts: - mountPath: /cache name: git-volume - name: kubectl image: bitnami/kubectl command: ["/bin/sh", "-c"] args: - | sleep 10; # 上のgit cloneが終了するまで待機 kubectl apply -f /cache/sample-app.yaml # GitHubリポジトリのディレクトリ・ファイル構成に応じて変更 volumeMounts: - mountPath: /cache name: git-volume volumes: - name: git-volume emptyDir: {} restartPolicy: Never backoffLimit: 4
実行内容としては、①対象の定義ファイルを格納したGitリポジトリからファイルを取得する、②取得したファイルを指定してkubectl apply
コマンドを実行する、という流れになります。①の処理が完了する前に②を実行すると、「指定したファイルが存在しない」というエラーが発生するため、sleep
で一定時間待機してからkubectl
コマンドを実行するようにしています。
CronJob
中で2つのコンテナを実行し、取得したリポジトリのデータを共有できるようemptyDir
リソースを利用しています。
CronJob
のスケジューリングはひとまず1分ごとに実行するよう設定し、1分ごとに①②の操作を繰り返すことになります。
これを利用してCronJob
を作成します。
$ kubectl apply -f cronjob-git-kubectl.yml cronjob.batch/cronjob-git-kubectl created $ kubectl get cronjob NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE cronjob-git-kubectl */1 * * * * False 0 <none> 6s
作成後にPodの状態を確認すると、1分ごとにJobが起動し、動作している様子が確認できます。
# CronJobの様子 # “sample-app”がkubectlコマンドで作成したPod $ kubectl get pods -w NAME READY STATUS RESTARTS AGE cronjob-git-kubectl-1607865300-ff4q6 0/2 Pending 0 0s cronjob-git-kubectl-1607865300-ff4q6 0/2 Pending 0 0s cronjob-git-kubectl-1607865300-ff4q6 0/2 ContainerCreating 0 0s # (1回目のJob実行) cronjob-git-kubectl-1607865300-ff4q6 1/2 Running 0 13s sample-app-75ff8897f5-rgmgt 0/1 Pending 0 0s sample-app-75ff8897f5-rgmgt 0/1 Pending 0 0s sample-app-75ff8897f5-rgmgt 0/1 ContainerCreating 0 0s cronjob-git-kubectl-1607865300-ff4q6 0/2 Completed 0 23s sample-app-75ff8897f5-rgmgt 1/1 Running 0 9s # (2回目以降のJob実行) cronjob-git-kubectl-1607865360-9h7ds 0/2 Pending 0 0s cronjob-git-kubectl-1607865360-9h7ds 0/2 Pending 0 0s cronjob-git-kubectl-1607865360-9h7ds 0/2 ContainerCreating 0 0s cronjob-git-kubectl-1607865360-9h7ds 1/2 Running 0 7s cronjob-git-kubectl-1607865360-9h7ds 0/2 Completed 0 17s cronjob-git-kubectl-1607865420-6ncqj 0/2 Pending 0 0s cronjob-git-kubectl-1607865420-6ncqj 0/2 Pending 0 0s cronjob-git-kubectl-1607865420-6ncqj 0/2 ContainerCreating 0 1s cronjob-git-kubectl-1607865420-6ncqj 1/2 Running 0 8s cronjob-git-kubectl-1607865420-6ncqj 0/2 Completed 0 18s # 実行結果 $ kubectl get pods NAME READY STATUS RESTARTS AGE cronjob-git-kubectl-1607865300-ff4q6 0/2 Completed 0 2m26s cronjob-git-kubectl-1607865360-9h7ds 0/2 Completed 0 86s cronjob-git-kubectl-1607865420-6ncqj 0/2 Completed 0 26s sample-app-75ff8897f5-rgmgt 1/1 Running 0 2m4s # 1回目のJobのログ $ kubectl logs cronjob-git-kubectl-1607865300-ff4q6 -c git Cloning into '/cache'... $ kubectl logs cronjob-git-kubectl-1607865300-ff4q6 -c kubectl deployment.apps/sample-app created # 2回目以降のJobのログ $ kubectl logs cronjob-git-kubectl-1607865420-6ncqj -c git Cloning into '/cache'... $ kubectl logs cronjob-git-kubectl-1607865420-6ncqj -c kubectl deployment.apps/sample-app unchanged