TECHSTEP

ITインフラ関連の記事を公開してます。

Reloaderを試す

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に付与する方法があります。

この設定は、searchmatch の両方が設定されており、かつ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

(以降割愛)