Kubernetes上のアプリケーションに外部から秘匿情報やパラメータを与える方法の一つとして、ConfigMap/Secretに情報を記載し、環境変数として渡すことができます。一方でこの方法を採用した場合、ConfigMap/Secretに記載する変数を更新すると、これをPodに反映するには、Podの再起動を実行する必要があります。
ここでReloaderというOSSを利用すると、ConfigMap/Secret更新時にPodの再起動を手動で行う手間を省くことができます。
Reloaderは、クラスター上にあるConfigMap/Secretを監視し、これらの更新を検知すると、特定のDeployment/DaemonSet/StatefulSetを更新します。これにより新規Podが作成され、自動的にPodに修正内容を反映してくれます。監視対象のConfigMap/Secret、更新対象のDeploymentなどは個別に指定することも可能なため、必要に応じて柔軟に設定することが可能です。
Reloaderの機能自体はとてもシンプルですが、ArgoCD/Argo Rollouts/Sealed SecretなどのOSSとも組み合わせて使えるようサポートされており、様々な場面で利用できることが期待できます。
なお、同じような機能を提供するOSSはいくつか存在しますが、今回は調べた時点で最もGitHubスター数の多いReloaderを使用しました。
Reloaderを動かす
ではReloaderを実際に使ってみます。今回はREADMEにも案内されている3通りの方法でPodに変更内容の反映を行います。
先に大まかな使い分け方を記載します。
Workloadへの指定 | ConfigMap/Secretへの指定 | 対象のConfigMap/Secret | |
---|---|---|---|
1 | reloader.stakater.com/auto: "true" |
- | Workloadの使用するすべてのConfigMap/Secretが対象 |
2 | reloader.stakater.com/search: "true" |
reloader.stakater.com/match: "true" |
Workloadが利用するうち、Annotationの付与されたもののみ |
3 | configmap.reloader.stakater.com/reload: "<ConfigMap名>" secret.reloader.stakater.com/reload: "Secret名" |
- | Workloadが利用しないものも含め、Annotationsで指定するConfigMap/Secretが対象 |
インストール
Reloaderをインストールする前に、Kubernetesクラスター上にテスト用のConfigMap/Secret/Deploymentリソースを作成しておきます。
# ConfigMap $ kubectl get configmap NAME DATA AGE kube-root-ca.crt 1 14m test-configmap 1 29s # Secret $ kubectl get secret NAME TYPE DATA AGE default-token-4cbzx kubernetes.io/service-account-token 3 14m test-secret Opaque 1 27s # Pod $ kubectl get pods NAME READY STATUS RESTARTS AGE reloader-test-7c55cb5568-6xqkf 1/1 Running 0 23s reloader-test-7c55cb5568-knf2z 1/1 Running 0 23s reloader-test-7c55cb5568-nb56f 1/1 Running 0 23s # Podに反映されている変数 $ kubectl exec -it reloader-test-7c55cb5568-6xqkf -- printenv PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=reloader-test-7c55cb5568-6xqkf TERM=xterm SECRET-ENV=secret1234 CONFIGMAP-ENV=configmap1234 (以降割愛)
Reloaderをインストールします。インストールには素のYamlファイルのほか、Kustomize・Helmチャートでの方法も案内されています。
$ kubectl apply -f https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml serviceaccount/reloader-reloader created clusterrole.rbac.authorization.k8s.io/reloader-reloader-role created clusterrolebinding.rbac.authorization.k8s.io/reloader-reloader-role-binding created deployment.apps/reloader-reloader created $ kubectl get pods NAME READY STATUS RESTARTS AGE reloader-reloader-69b9d44fc7-bq7b4 1/1 Running 0 103s reloader-test-7c55cb5568-6xqkf 1/1 Running 0 5m3s reloader-test-7c55cb5568-knf2z 1/1 Running 0 5m3s reloader-test-7c55cb5568-nb56f 1/1 Running 0 5m3s
1. Pod側にauto
を指定
Reloaderを利用する際は、対象のDeploymentやConfigmap/Secretに特定のAnnotationsを付与し、Reloaderによる処理を指定することができます。例えばDeploymentにreloader.stakater.com/auto: "true"
というAnnotationを付与すると、Reloaderが対象のDeploymentを検知し、Deploymentの参照するConfigMap/Secretが更新されれば、Deploymentの管理するPodを更新します。
apiVersion: apps/v1 kind: Deployment metadata: name: reloader-test labels: app: nginx annotations: reloader.stakater.com/auto: "true" (以降割愛)
Deploymentに上記Annotationを追加後、事前にアプライしておきます。
$ kubectl apply -f deployment.yaml
deployment.apps/reloader-test configured
ここではConfigMapの値を修正し、更新します。この時Podの状態を見ていると、新しいPodが作成されていることを確認できます。
# ConfigMapを修正 $ kubectl apply -f configmap.yaml configmap/test-configmap configured # Podが作成される $ kubectl get pods -w NAME READY STATUS RESTARTS AGE reloader-reloader-69b9d44fc7-bq7b4 1/1 Running 0 4m10s reloader-test-7c55cb5568-6xqkf 1/1 Running 0 7m30s reloader-test-7c55cb5568-knf2z 1/1 Running 0 7m30s reloader-test-7c55cb5568-nb56f 1/1 Running 0 7m30s reloader-test-74d4bfb55c-m75s9 0/1 Pending 0 0s reloader-test-74d4bfb55c-m75s9 0/1 Pending 0 0s reloader-test-74d4bfb55c-m75s9 0/1 ContainerCreating 0 0s reloader-test-74d4bfb55c-m75s9 1/1 Running 0 3s reloader-test-7c55cb5568-6xqkf 1/1 Terminating 0 8m32s reloader-test-74d4bfb55c-dhwr9 0/1 Pending 0 0s reloader-test-74d4bfb55c-dhwr9 0/1 Pending 0 0s reloader-test-74d4bfb55c-dhwr9 0/1 ContainerCreating 0 0s reloader-test-7c55cb5568-6xqkf 0/1 Terminating 0 8m33s reloader-test-7c55cb5568-6xqkf 0/1 Terminating 0 8m33s reloader-test-7c55cb5568-6xqkf 0/1 Terminating 0 8m33s reloader-test-74d4bfb55c-dhwr9 1/1 Running 0 3s reloader-test-7c55cb5568-nb56f 1/1 Terminating 0 8m35s reloader-test-74d4bfb55c-28ww7 0/1 Pending 0 0s reloader-test-74d4bfb55c-28ww7 0/1 Pending 0 0s reloader-test-74d4bfb55c-28ww7 0/1 ContainerCreating 0 0s reloader-test-7c55cb5568-nb56f 0/1 Terminating 0 8m36s reloader-test-7c55cb5568-nb56f 0/1 Terminating 0 8m36s reloader-test-7c55cb5568-nb56f 0/1 Terminating 0 8m36s reloader-test-74d4bfb55c-28ww7 1/1 Running 0 3s reloader-test-7c55cb5568-knf2z 1/1 Terminating 0 8m38s reloader-test-7c55cb5568-knf2z 0/1 Terminating 0 8m39s reloader-test-7c55cb5568-knf2z 0/1 Terminating 0 8m39s reloader-test-7c55cb5568-knf2z 0/1 Terminating 0 8m39s
また更新後にDeploymentの状態を見ると、 STAKATER_TEST_CONFIGMAP_CONFIGMAP
という変数が追加されていることがわかります。ReloaderはDeployment/DaemonSet/StatefulSetを更新するとき、デフォルトでは特定の環境変数を追加することで更新します。これ以外に、特定のAnnotationを追加することで更新する方法を選択することも可能で、ArgoCDなどを利用する場合はこちらが推奨されます。
$ kubectl exec -it reloader-test-74d4bfb55c-28ww7 -- printenv PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOSTNAME=reloader-test-74d4bfb55c-28ww7 TERM=xterm SECRET-ENV=secret1234 CONFIGMAP-ENV=configmap5678 STAKATER_TEST_CONFIGMAP_CONFIGMAP=9ff99bd578c45053d076640b122ec309c61d3b7e (以降割愛)
※参考: GitHub - stakater/Reloader: Reload Strategies
2. Pod側にsearch
, ConfigMap/Secret側にmatch
を指定
reloader.stakater.com/auto
というAnnotationはDeploymentの使用するConfigMap/Secretのいずれかが更新するとPodの作成を行いますが、監視対象とするConfigMap/Secretを特定することも可能です。ConfigMap/Secretを指定する方法の一つに、 reloader.stakater.com/match: "true"
というAnnotationをConfigMap/Secretに、 reloader.stakater.com/search: "true"
というAnnotationをDeploymentに付与する方法があります。
この設定は、search
と match
の両方が設定されており、かつConfigMap/SecretはDeploymentなどが利用しているものを指定しなければ動作しません。
apiVersion: apps/v1 kind: Deployment metadata: name: reloader-test labels: app: nginx annotations: reloader.stakater.com/search: "true" (以降割愛)
apiVersion: v1 kind: Secret metadata: name: test-secret annotations: reloader.stakater.com/match: "true" (以降割愛)
ここでは、SecretにのみAnnotationを付与し、ConfigMap/Secret両方を更新したときの挙動を見てみます。
# 事前にAnnotationの変更を反映しておく $ kubectl apply -f deployment.yaml deployment.apps/reloader-test configured $ kubectl apply -f secret.yaml secret/test-secret configured
すると、Configmapを更新したときは何の変化もないのに対し、Secretを更新したときはPodが作成される様子を確認できます。
# configmapを更新してもpodは再起動しない $ kubectl apply -f configmap.yaml configmap/test-configmap configured $ kubectl get pods -w NAME READY STATUS RESTARTS AGE reloader-reloader-69b9d44fc7-bq7b4 1/1 Running 0 12m reloader-test-74d4bfb55c-28ww7 1/1 Running 0 7m18s reloader-test-74d4bfb55c-dhwr9 1/1 Running 0 7m21s reloader-test-74d4bfb55c-m75s9 1/1 Running 0 7m24s # secretを更新するとpodは再起動する $ kubectl apply -f secret.yaml secret/test-secret configured $ kubectl get pods -w NAME READY STATUS RESTARTS AGE reloader-reloader-69b9d44fc7-bq7b4 1/1 Running 0 12m reloader-test-74d4bfb55c-28ww7 1/1 Running 0 7m18s reloader-test-74d4bfb55c-dhwr9 1/1 Running 0 7m21s reloader-test-74d4bfb55c-m75s9 1/1 Running 0 7m24s reloader-test-58d84bcfd7-9vdnf 0/1 Pending 0 0s reloader-test-58d84bcfd7-9vdnf 0/1 Pending 0 0s reloader-test-58d84bcfd7-9vdnf 0/1 ContainerCreating 0 0s reloader-test-58d84bcfd7-9vdnf 1/1 Running 0 3s (以降割愛)
3. Pod側にConfigMap/Secretを指定
ConfigMap/Secretを指定する2つ目の方法として、 configmap.reloader.stakater.com/reload
secret.reloader.stakater.com/reload
を使う例になります。こちらはDeploymnetなどに対象のConfigMap/Secretの名称を指定する形式になります。そのため、例えばDeploymentが利用するConfigMapの1つだけを指定することで、それ以外のConfigMap/Secretが更新されてもPodの作成は発生しません。
ここでは以下のようなAnnotationをDeploymentに付与した状態で、ConfigMap/Secretの更新を行います。ConfigMapのほうは正しい名称ですが、Secretのほうは誤った名称を指定しています。
apiVersion: apps/v1 kind: Deployment metadata: name: reloader-test labels: app: nginx annotations: secret.reloader.stakater.com/reload: "test-secret-dummy" configmap.reloader.stakater.com/reload: "test-configmap" (以降割愛)
# 事前にAnnotationの変更を反映しておく $ kubectl apply -f deployment.yaml deployment.apps/reloader-test configured $ kubectl apply -f secret.yaml secret/test-secret configured
この状態でConfigMap/Secretを更新します。すると、Secretを更新しても (Deployment Annotationで指定されていないため) Podの作成は発生しませんが、ConfigMapはPodの作成が発生します。
# secretは更新しても再起動しない $ kubectl apply -f secret.yaml secret/test-secret configured $ kubectl get pods -w NAME READY STATUS RESTARTS AGE reloader-reloader-69b9d44fc7-bq7b4 1/1 Running 0 30m reloader-test-58d84bcfd7-9vdnf 1/1 Running 0 14m reloader-test-58d84bcfd7-dlsvn 1/1 Running 0 14m reloader-test-58d84bcfd7-nn6bk 1/1 Running 0 14m # configmapを更新するとpodは再起動される $ kubectl apply -f configmap.yaml configmap/test-configmap configured $ kubectl get pods -w NAME READY STATUS RESTARTS AGE reloader-reloader-69b9d44fc7-bq7b4 1/1 Running 0 30m reloader-test-58d84bcfd7-9vdnf 1/1 Running 0 14m reloader-test-58d84bcfd7-dlsvn 1/1 Running 0 14m reloader-test-58d84bcfd7-nn6bk 1/1 Running 0 14m reloader-test-d48cfc84b-k5h5k 0/1 Pending 0 0s reloader-test-d48cfc84b-k5h5k 0/1 Pending 0 0s reloader-test-d48cfc84b-k5h5k 0/1 ContainerCreating 0 0s reloader-test-d48cfc84b-k5h5k 1/1 Running 0 3s (以降割愛)
なお、こちらの方法で指定できるのは、Deploymentから利用しているConfigMap/Secretだけに限らないようで、試しにDeploymentの使用していないSecretなどをAnnotationに指定したところ、指定のSecretの更新に合わせてPodが作成される様子を確認しました。
# 不要なSecretを作成 $ kubectl apply -f secret-2.yaml secret/test-secret-2 created # Deployment Annotationを修正 $ head -10 deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: reloader-test labels: app: nginx annotations: secret.reloader.stakater.com/reload: "test-secret-2" #configmap.reloader.stakater.com/reload: "test-configmap" spec: $ kubectl apply -f deployment.yaml deployment.apps/reloader-test configured $ kubectl get pods NAME READY STATUS RESTARTS AGE reloader-reloader-bf77955f4-2x7fp 1/1 Running 0 62s reloader-test-7c55cb5568-cfjqr 1/1 Running 0 10s reloader-test-7c55cb5568-fq9xv 1/1 Running 0 10s reloader-test-7c55cb5568-twwqh 1/1 Running 0 10s # secret-2を更新 $ kubectl apply -f secret-2.yaml secret/test-secret-2 configured # Podが作成される $ kubectl get pods -w NAME READY STATUS RESTARTS AGE reloader-reloader-bf77955f4-2x7fp 1/1 Running 0 90s reloader-test-7c55cb5568-cfjqr 1/1 Running 0 38s reloader-test-7c55cb5568-fq9xv 1/1 Running 0 38s reloader-test-c84db947-dhxlc 0/1 ContainerCreating 0 1s reloader-test-c84db947-lfh7k 1/1 Running 0 4s reloader-test-c84db947-dhxlc 1/1 Running 0 3s reloader-test-7c55cb5568-fq9xv 1/1 Terminating 0 40s reloader-test-c84db947-crc4l 0/1 Pending 0 0s reloader-test-c84db947-crc4l 0/1 Pending 0 0s reloader-test-c84db947-crc4l 0/1 ContainerCreating 0 0s (以降割愛)