⑱１日１０分で理解するコンテナ技術入門 - 環境変数の設定 -

Kubernetesにおいて、Podに環境変数を設定する（設定値を渡す）方法は
1. マニフェストファイルにハードコード
1. ConfigMapを使う
1. Secretを使う

の３つの方法があります。
今回は、ハードコードの方法と、ConfigMapを使う方法について紹介します。

# マニフェストファイルにハードコード
`spec.containers.env`に、環境変数のkey-valueを記述します。
```yaml:hardcode.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
    - name: nginx
      image: nginx:latest
      env:
        - name: EXPOSE_PORT
          value: "80"
      ports:
        - containerPort: 80
```
上記の例では、`EXPOSE_PORT`という環境変数に`80`を設定しています。
このPodを起動して、環境変数を確認してみます。
```bash
$ kubectl apply -f hardcode.yaml
$ kubectl exec -it nginx -- /bin/bash
root@nginx:/# echo $EXPOSE_PORT
80
```
正しく設定できていることが分かります。

# ConfigMapを使う
マニフェストファイルにハードコードする場合では、同じ設定を他のPodにも適用したい場合に、同じ内容を何回も書く必要があり不便です。ConfigMapは、key-valueの集合をオブジェクトとして持つため、複数Podで同じ設定を共有する場合などに一元管理できて便利です。

ConfigMapを使うモチベーションについて、[公式ドキュメント](https://kubernetes.io/ja/docs/concepts/configuration/configmap/)では、
>たとえば、アプリケーションを開発していて、(開発用時には)自分のコンピューター上と、(実際のトラフィックをハンドルするときは)クラウド上とで実行することを想像してみてください。あなたは、DATABASE_HOSTという名前の環境変数を使用するコードを書きます。ローカルでは、この変数をlocalhostに設定します。クラウド上では、データベースコンポーネントをクラスター内に公開するKubernetesのServiceを指すように設定します。
こうすることで、必要であればクラウド上で実行しているコンテナイメージを取得することで、ローカルでも完全に同じコードを使ってデバッグができるようになります。

と書かれています。環境による差異はConfigMapに集約することで、コードは同じものを利用できて便利ということでしょう。

## ConfigMapの作成
ConfigMapは、利用方法に応じて作成時に記述する内容が少し異なります。利用方法は、
1. Podに環境変数として設定する
1. ボリュームとしてマウントする

の2つの方法があります。

Podに環境変数として設定する場合は、Pod側では環境変数として値にアクセスできます。
ボリュームとしてマウントする場合は、Pod側ではマウント先にあるファイルを見に行くことで値にアクセスできます。
### Podに環境変数として設定する場合
Podに環境変数として設定する、つまりハードコードする場合と同じようにPod側が利用できるパターンだと、ConfigMapは以下のように記述します。
```yaml:podenv_configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: example-config
data:
  APP_COLOR: "blue"
  APP_MODE: "production"
```
クラスターに適用します。
```bash
$ kubectl apply -f podenv_configmap.yaml 
configmap/example-config created
```
このConfigMapを利用するPod側のマニフェストは、以下のようになります。
```yaml:podenv_pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
    - name: example-container
      image: nginx
      env:
        - name: APP_COLOR
          valueFrom:
            configMapKeyRef:
              name: example-config
              key: APP_COLOR
        - name: APP_MODE2 # ConfigMapでの名前とは異なる名前
          valueFrom:
            configMapKeyRef:
              name: example-config
              key: APP_MODE
```
`spec.containers.env`の中に、環境変数名(`name`)と、その値の参照先(`valueFrom`)を設定します。`configMapKeyRef`には、参照するConfigMapの名前と、そのConfigMap内のどのキーを参照するかを記述します。ですので、ConfigMapで定義した名前と別の名前として環境変数に設定することもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532202/3979dabc-8bd0-a784-2235-c106dca455e3.png)

:::note info
`envFrom`を使う場合
上記の例では`valueFrom`を使って値を設定していますが、環境変数が多い場合に各環境変数に対して`valueFrom`を使うのは大変です。そこで、ConfigMapのすべてのキーと値を設定できる、`envFrom`という方法があります。
```yaml:envFromを使う場合
apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
    - name: example-container
      image: nginx
      envFrom:
        - configMapRef:
            name: example-config
```
上記のように、Pod側のマニフェストでConfigMapを指定することで一気に環境変数を設定することができます。ただし、`valueFrom`で行ったようなConfigMapと異なるキー名で値を参照するようなことはできなくなるので注意してください。
:::

Podをクラスターに作成します。
```bash
$ kubectl apply -f podenv_pod.yaml 
pod/example-pod created
```

値を確認します。
```bash
$ kubectl exec -it example-pod -- /bin/bash
root@example-pod:/# echo $APP_COLOR
blue
root@example-pod:/# echo $APP_MODE2
production
```
このように、`spec.containers.env.name`に指定した名前がPodの環境変数として設定されています。

### ボリュームとしてマウントする場合
ボリュームとしてマウントする場合、ConfigMapは以下のように記述します。`config.txt`の部分には、好きなファイル名を記述できます。
```yaml:volume_configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: example-config
data:
  config.txt: |
    color=blue
    mode=production
```
クラスターに作成します。
```bash
$ kubectl apply -f volume_configmap.yaml
```
ConfigMapを利用するPodは、以下のようにボリュームをマウントするときと同じ書き方で記述します。
```yaml:volume_pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
  - name: example-container
    image: nginx
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap:
      name: example-config
```
クラスターにPodを作成します。
```bash
$ kubectl apply -f volume_pod.yaml
```

:::note warn
エラーが出る場合
Pod作成時にエラーが出る場合は、以前作成したPodを削除してください（同じ名前のPodのため）
:::

PodからConfigMapの内容を確認してみます。
```bash
$ kubectl exec -it example-pod -- /bin/bash
root@example-pod:/# ls /etc/config
config.txt
root@example-pod:/# cat /etc/config/config.txt 
color=blue
mode=production
```
このように、`config.txt`という名前のファイルに設定値が書き込まれています。

# まとめ
今回はPodに環境変数や設定を渡す方法として、マニフェストファイルにハードコードする方法と、ConfigMapを使う方法について説明しました。
次回は機密情報などをPodに渡すためのリソースである、Secretについて紹介します。