【Kubernetes】ConfigMap/SecretでPodの環境変数設定
はじめに
ConfigMapとSecretそれぞれを利用して、環境変数を簡単な例で実際に設定してみたいと思います。
ConfigMapとSecret
ConfigMapとは、機密性のない設定データを保存するオブジェクトです。
ConfigMap
ConfigMapは、 機密性のないデータをキーと値のペアで保存するために使用されるAPIオブジェクトです。Podは、環境変数、コマンドライン引数、またはボリューム内の設定ファイルとしてConfigMapを使用できます。 ConfigMapを使用すると、環境固有の設定をコンテナイメージから分離できるため、アプリケーションを簡単に移植できるようになります。 注意:ConfigMapは機密性や暗号化を提供しません。保存したいデータが機密情報である場合は、ConfigMapの代わりにSecretを使用するか、追加の(サードパーティー)ツールを使用してデータが非公開になるようにしてください。 動機 アプリケーションのコードとは別に設定データを設定するには、ConfigMapを使用します。 たとえば、アプリケーションを開発していて、(開発用時には)自分のコンピューター上と、(実際のトラフィックをハンドルするときは)クラウド上とで実行することを想像してみてください。あなたは、DATABASE_HOSTという名前の環境変数を使用するコードを書きます。ローカルでは、この変数をlocalhostに設定します。クラウド上では、データベースコンポーネントをクラスター内に公開するKubernetesのServiceを指すように設定します。 こうすることで、必要であればクラウド上で実行しているコンテナイメージを取得することで、ローカルでも完全に同じコードを使ってデバッグができるようになります。 ConfigMapは、大量のデータを保持するようには設計されていません。ConfigMapに保存されるデータは1MiBを超えることはできません。この制限を超える設定を保存する必要がある場合は、ボリュームのマウントを検討するか、別のデータベースまたはファイルサービスを使用することを検討してください。 ConfigMapオブジェクト ConfigMapは、他のオブジェクトが使うための設定を保存できるAPIオブジェクトです。ほとんどのKubernetesオブジェクトにspecセクションがあるのとは違い、ConfigMapにはdataおよびbinaryDataフィールドがあります。これらのフィールドは、キーとバリューのペアを値として受け入れます。dataフィールドとbinaryDataフィールドはどちらもオプションです。dataフィールドはUTF-8バイトシーケンスを含むように設計されていますが、binaryDataフィールドはバイナリデータを含むように設計されています。 ConfigMapの名前は、有効なDNSのサブドメイン名でなければなりません。 dataまたはbinaryDataフィールドの各キーは、英数字、-、_、または.で構成されている必要があります。dataに格納されているキーは、binaryDataフィールドのキーと重複することはできません。 v1.19以降、ConfigMapの定義にimmutableフィールドを追加して、イミュータブルなConfigMapを作成できます。 ConfigMapとPod ConfigMapを参照して、ConfigMap内のデータを元にしてPod内のコンテナの設定をするPodのspecを書くことができます。このとき、PodとConfigMapは同じ名前空間内に存在する必要があります。 以下に、ConfigMapの例を示します。単一の値を持つキーと、Configuration形式のデータ片のような値を持つキーがあります。 apiVersion: v1 kind: ConfigMap metadata: name: game-demo data: # プロパティーに似たキー。各キーは単純な値にマッピングされている player_initial_lives: "3" ui_properties_file_name: "user-interface.properties" # ファイルに似たキー game.properties: | enemy.types=aliens,monsters player.maximum-lives=5 user-interface.properties: | color.good=purple color.bad=yellow allow.textmode=true ConfigMapを利用してPod内のコンテナを設定する方法には、次の4種類があります。 コンテナ内のコマンドと引数 環境変数をコンテナに渡す 読み取り専用のボリューム内にファイルを追加し、アプリケーションがそのファイルを読み取る Kubernetes APIを使用してConfigMapを読み込むコードを書き、そのコードをPod内で実行する これらのさまざまな方法は、利用するデータをモデル化するのに役立ちます。最初の3つの方法では、kubeletがPodのコンテナを起動する時にConfigMapのデータを使用します。 4番目の方法では、ConfigMapとそのデータを読み込むためのコードを自分自身で書く必要があります。しかし、Kubernetes APIを直接使用するため、アプリケーションはConfigMapがいつ変更されても更新イベントを受信でき、変更が発生したときにすぐに反応できます。この手法では、Kubernetes APIに直接アクセスすることで、別の名前空間にあるConfigMapにもアクセスできます。 以下に、Podを設定するためにgame-demoから値を使用するPodの例を示します。 apiVersion: v1 kind: Pod metadata: name: configmap-demo-pod spec: containers: - name: demo image: alpine command: ["sleep", "3600"] env: # 環境変数を定義します。 - name: PLAYER_INITIAL_LIVES # ここではConfigMap内のキーの名前とは違い # 大文字が使われていることに着目してください。 valueFrom: configMapKeyRef: name: game-demo # この値を取得するConfigMap。 key: player_initial_lives # 取得するキー。 - name: UI_PROPERTIES_FILE_NAME valueFrom: configMapKeyRef: name: game-demo key: ui_properties_file_name volumeMounts: - name: config mountPath: "/config" readOnly: true volumes: # Podレベルでボリュームを設定し、Pod内のコンテナにマウントします。 - name: config configMap: # マウントしたいConfigMapの名前を指定します。 name: game-demo # ファイルとして作成するConfigMapのキーの配列 items: - key: "game.
Secretとは、機密データを保存するためのオブジェクトです。
Secret
Secretとは、パスワードやトークン、キーなどの少量の機密データを含むオブジェクトのことです。 このような情報は、Secretを用いないとPodの定義やコンテナイメージに直接記載することになってしまうかもしれません。 Secretを使用すれば、アプリケーションコードに機密データを含める必要がなくなります。 なぜなら、Secretは、それを使用するPodとは独立して作成することができ、 Podの作成、閲覧、編集といったワークフローの中でSecret(およびそのデータ)が漏洩する危険性が低くなるためです。 また、Kubernetesやクラスター内で動作するアプリケーションは、不揮発性ストレージに機密データを書き込まないようにするなど、Secretで追加の予防措置を取ることができます。 Secretsは、ConfigMapsに似ていますが、機密データを保持するために用います。 注意:KubernetesのSecretは、デフォルトでは、APIサーバーの基礎となるデータストア(etcd)に暗号化されずに保存されます。APIにアクセスできる人は誰でもSecretを取得または変更でき、etcdにアクセスできる人も同様です。 さらに、名前空間でPodを作成する権限を持つ人は、そのアクセスを使用して、その名前空間のあらゆるSecretを読むことができます。これには、Deploymentを作成する能力などの間接的なアクセスも含まれます。 Secretsを安全に使用するには、以下の手順を推奨します。 Secretsを安全に暗号化する Secretsのデータの読み取りを制限するRBACルールの有効化または設定 適切な場合には、RBACなどのメカニズムを使用して、どの原則が新しいSecretの作成や既存のSecretの置き換えを許可されるかを制限します。 Secretの概要 Secretを使うには、PodはSecretを参照することが必要です。 PodがSecretを使う方法は3種類あります。 ボリューム内のファイルとして、Podの単一または複数のコンテナにマウントする コンテナの環境変数として利用する Podを生成するためにkubeletがイメージをpullするときに使用する KubernetesのコントロールプレーンでもSecretsは使われています。例えば、bootstrap token Secretsは、ノード登録を自動化するための仕組みです。 Secretオブジェクトの名称は正当なDNSサブドメイン名である必要があります。 シークレットの構成ファイルを作成するときに、dataおよび/またはstringDataフィールドを指定できます。dataフィールドとstringDataフィールドはオプションです。 dataフィールドのすべてのキーの値は、base64でエンコードされた文字列である必要があります。 base64文字列への変換が望ましくない場合は、代わりにstringDataフィールドを指定することを選択できます。これは任意の文字列を値として受け入れます。 dataとstringDataのキーは、英数字、-、_、または.で構成されている必要があります。 stringDataフィールドのすべてのキーと値のペアは、内部でdataフィールドにマージされます。 キーがdataフィールドとstringDataフィールドの両方に表示される場合、stringDataフィールドで指定された値が優先されます。 Secretの種類 Secretを作成するときは、Secretのtypeフィールド、または特定の同等のkubectlコマンドラインフラグ(使用可能な場合)を使用して、その型を指定できます。 Secret型は、Secret dataのプログラムによる処理を容易にするために使用されます。 Kubernetesは、いくつかの一般的な使用シナリオに対応するいくつかの組み込み型を提供します。 これらの型は、実行される検証とKubernetesが課す制約の点で異なります。 Builtin Type Usage Opaque arbitrary user-defined data kubernetes.io/service-account-token service account token kubernetes.io/dockercfg serialized ~/.dockercfg file kubernetes.io/dockerconfigjson serialized ~/.docker/config.json file kubernetes.io/basic-auth credentials for basic authentication kubernetes.io/ssh-auth credentials for SSH authentication kubernetes.io/tls data for a TLS client or server bootstrap.
どちらもPodから設定データにアクセスすることができ、Podから設定データを分離することができます。
Secretの詳しいセキュリティ特性については下記のドキュメントを確認してください。
Secret
Secretとは、パスワードやトークン、キーなどの少量の機密データを含むオブジェクトのことです。 このような情報は、Secretを用いないとPodの定義やコンテナイメージに直接記載することになってしまうかもしれません。 Secretを使用すれば、アプリケーションコードに機密データを含める必要がなくなります。 なぜなら、Secretは、それを使用するPodとは独立して作成することができ、 Podの作成、閲覧、編集といったワークフローの中でSecret(およびそのデータ)が漏洩する危険性が低くなるためです。 また、Kubernetesやクラスター内で動作するアプリケーションは、不揮発性ストレージに機密データを書き込まないようにするなど、Secretで追加の予防措置を取ることができます。 Secretsは、ConfigMapsに似ていますが、機密データを保持するために用います。 注意:KubernetesのSecretは、デフォルトでは、APIサーバーの基礎となるデータストア(etcd)に暗号化されずに保存されます。APIにアクセスできる人は誰でもSecretを取得または変更でき、etcdにアクセスできる人も同様です。 さらに、名前空間でPodを作成する権限を持つ人は、そのアクセスを使用して、その名前空間のあらゆるSecretを読むことができます。これには、Deploymentを作成する能力などの間接的なアクセスも含まれます。 Secretsを安全に使用するには、以下の手順を推奨します。 Secretsを安全に暗号化する Secretsのデータの読み取りを制限するRBACルールの有効化または設定 適切な場合には、RBACなどのメカニズムを使用して、どの原則が新しいSecretの作成や既存のSecretの置き換えを許可されるかを制限します。 Secretの概要 Secretを使うには、PodはSecretを参照することが必要です。 PodがSecretを使う方法は3種類あります。 ボリューム内のファイルとして、Podの単一または複数のコンテナにマウントする コンテナの環境変数として利用する Podを生成するためにkubeletがイメージをpullするときに使用する KubernetesのコントロールプレーンでもSecretsは使われています。例えば、bootstrap token Secretsは、ノード登録を自動化するための仕組みです。 Secretオブジェクトの名称は正当なDNSサブドメイン名である必要があります。 シークレットの構成ファイルを作成するときに、dataおよび/またはstringDataフィールドを指定できます。dataフィールドとstringDataフィールドはオプションです。 dataフィールドのすべてのキーの値は、base64でエンコードされた文字列である必要があります。 base64文字列への変換が望ましくない場合は、代わりにstringDataフィールドを指定することを選択できます。これは任意の文字列を値として受け入れます。 dataとstringDataのキーは、英数字、-、_、または.で構成されている必要があります。 stringDataフィールドのすべてのキーと値のペアは、内部でdataフィールドにマージされます。 キーがdataフィールドとstringDataフィールドの両方に表示される場合、stringDataフィールドで指定された値が優先されます。 Secretの種類 Secretを作成するときは、Secretのtypeフィールド、または特定の同等のkubectlコマンドラインフラグ(使用可能な場合)を使用して、その型を指定できます。 Secret型は、Secret dataのプログラムによる処理を容易にするために使用されます。 Kubernetesは、いくつかの一般的な使用シナリオに対応するいくつかの組み込み型を提供します。 これらの型は、実行される検証とKubernetesが課す制約の点で異なります。 Builtin Type Usage Opaque arbitrary user-defined data kubernetes.io/service-account-token service account token kubernetes.io/dockercfg serialized ~/.dockercfg file kubernetes.io/dockerconfigjson serialized ~/.docker/config.json file kubernetes.io/basic-auth credentials for basic authentication kubernetes.io/ssh-auth credentials for SSH authentication kubernetes.io/tls data for a TLS client or server bootstrap.
ConfigMapで環境変数
まずはConfigMapを使って環境変数の設定をしていきます。
ConfigMap
最初にConfigMapを作成します。
環境変数の値を格納するConfigMapのマニフェストconfigmap.yaml
は下記の通りです。
1apiVersion: v1
2kind: ConfigMap
3metadata:
4 name: env-config
5 namespace: default
6data:
7 HELLO: Hello
8 WORLD: World!!
ConfigMapを作成します。
1kubectl apply -f configmap.yaml
作成したConfigMapを確認してみると環境変数の値が確認できます。
1❯ kubectl describe configmap env-config
2Name: env-config
3Namespace: default
4Labels: <none>
5Annotations: <none>
6
7Data
8====
9HELLO:
10----
11Hello
12WORLD:
13----
14World!!
15
16BinaryData
17====
18
19Events: <none>
個別に環境変数を設定
作成したConfigMapから個別に環境変数を設定するPodを作成します。
configMapKeyRef
を使って環境変数の値を設定しています。configmap-keyref-pod.yaml
は下記の通りです。
1apiVersion: v1
2kind: Pod
3metadata:
4 name: configmap-keyref-pod
5spec:
6 containers:
7 - name: env-container
8 image: k8s.gcr.io/busybox
9 command: [ "/bin/sh", "-c", "echo $HELLO $WORLD" ]
10 env:
11 - name: HELLO
12 valueFrom:
13 configMapKeyRef:
14 name: env-config
15 key: HELLO
16 - name: WORLD
17 valueFrom:
18 configMapKeyRef:
19 name: env-config
20 key: WORLD
21 restartPolicy: Never
Podを作成します。
1kubectl apply -f configmap-keyref-pod.yaml
ログを確認すると環境変数が設定されていることがわかります。
1❯ kubectl logs configmap-keyref-pod
2Hello World!!
一括で環境変数を設定
次にConfigMapの設定内容を一括で設定するPodを作成します。
configMapRef
でConfigMapの設定内容全体を環境変数として設定します。configmap-ref-pod.yaml
は下記の通りです。
1apiVersion: v1
2kind: Pod
3metadata:
4 name: configmap-ref-pod
5spec:
6 containers:
7 - name: env-container
8 image: k8s.gcr.io/busybox
9 command: [ "/bin/sh", "-c", "echo $HELLO $WORLD" ]
10 envFrom:
11 - configMapRef:
12 name: env-config
13 restartPolicy: Never
Podを作成します。
1kubectl apply -f configmap-ref-pod.yaml
ログを確認すると一括でも環境変数が設定されていることがわかります。
1❯ kubectl logs configmap-ref-pod
2Hello World!!
Secretで環境変数
次はSecretを使って環境変数を設定します。
Secret
まずはSecretを作成します。
環境変数の値を格納するSecretのマニフェストsecret.yaml
は下記の通りです。
1apiVersion: v1
2kind: Secret
3metadata:
4 name: password-secret
5stringData:
6 USER: Masa
7 PASSWORD: HOGEHOGE
Secretを作成します。
1kubectl apply -f secret.yaml
作成したSecretを確認してみるとデータがそのまま表示されていないことがわかります。
1❯ kubectl describe secret password-secret
2Name: password-secret
3Namespace: default
4Labels: <none>
5Annotations: <none>
6
7Type: Opaque
8
9Data
10====
11PASSWORD: 8 bytes
12USER: 4 bytes
下記のようにyaml形式で出力するとデータがエンコードされた文字列が確認できます。
1❯ k get secret/password-secret -o yaml
2apiVersion: v1
3data:
4 PASSWORD: SE9HRUhPR0U= # エンコードされた文字列
5 USER: TWFzYQ== # エンコードされた文字列
6kind: Secret
7metadata:
8 :
9 :
10type: Opaque
これをbase64でデコードすることで元の文字列に戻すことが可能です。
1❯ echo "SE9HRUhPR0U=" | base64 --decode
2HOGEHOGE
3
4❯ echo "TWFzYQ==" | base64 --decode
5Masa
個別に環境変数を設定
作成したSecretから個別に環境変数を設定するPodを作成します。
secretMapKeyRef
を使って環境変数の値を設定しています。secret-keyref-pod.yaml
は下記の通りです。
1apiVersion: v1
2kind: Pod
3metadata:
4 name: secret-keyref-pod
5spec:
6 containers:
7 - name: password-container
8 image: k8s.gcr.io/busybox
9 command: [ "/bin/sh", "-c", "echo $USER $PASSWORD" ]
10 env:
11 - name: USER
12 valueFrom:
13 secretKeyRef:
14 name: password-secret
15 key: USER
16 - name: PASSWORD
17 valueFrom:
18 secretKeyRef:
19 name: password-secret
20 key: PASSWORD
21 restartPolicy: Never
Podを作成します。
1kubectl apply -f secret-keyref-pod.yaml
ログを確認すると環境変数が設定されていることがわかります。
1❯ kubectl logs secret-keyref-pod
2Masa HOGEHOGE
一括で環境変数を設定
次にSecretの設定内容を一括で設定するPodを作成します。
secretRef
でSecretの設定内容全体を環境変数として設定します。secret-ref-pod.yaml
は下記の通りです。
1apiVersion: v1
2kind: Pod
3metadata:
4 name: secret-ref-pod
5spec:
6 containers:
7 - name: password-container
8 image: k8s.gcr.io/busybox
9 command: [ "/bin/sh", "-c", "echo $USER $PASSWORD" ]
10 envFrom:
11 - secretRef:
12 name: password-secret
13 restartPolicy: Never
Podを作成します。
1kubectl apply -f secret-ref-pod.yaml
ログを確認すると一括でも環境変数が設定されていることがわかります。
1❯ kubectl logs secret-ref-pod
2Masa HOGEHOGE