Kubernetes Podの”command”や”args”で環境変数を参照する方法いろいろ

Bash,Docker,Kubernetes

はじめに

KubernetesでPod(もしくはReplicaSet、Deployment)のマニフェストにて、 commandargs 属性を使って実行コマンドを指定する事ができます。

commandargs に指定する実行コマンドで環境変数を利用する場合の注意点と対処法について紹介します。

検証環境

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"19", GitVersion:"v1.19.4", GitCommit:"d360454c9bcd1634cf4cc52d1867af5491dc9c5f", GitTreeState:"clean", BuildDate:"2020-11-12T01:09:16Z", GoVersion:"go1.15.4", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"16+", GitVersion:"v1.16.15-gke.4300", GitCommit:"7ed5ddc0e67cb68296994f0b754cec45450d6a64", GitTreeState:"clean", BuildDate:"2020-10-28T09:23:22Z", GoVersion:"go1.13.15b4", Compiler:"gc", Platform:"linux/amd64"}

commandargs に環境変数をベタ書きした場合、うまく参照できない

環境変数を出力するだけのPodを作成してみます。
まずはPodのマニフェストファイルを作成します。

env 属性で NAME という環境変数を設定し、それを出力させてみます。

# test-pod.yaml というマニフェストファイルを作成
$ cat <<'EOF' >test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
    - name: test-pod
      image: bash
      command: ["echo"]
      args:
        - "${NAME}"
      env:
        - name: NAME
          value: "genzouw"
EOF

マニフェストファイルを元にPodを作成します。

# test-pod.yaml を使って、Kubernetes上にPodを作成
$ kubectl apply -f test-pod.yaml

applyが正常にできたら、ログを確認してみます。

# Podの実行ログを確認
$ kubectl logs -f test-pod
${NAME}

env 属性で設定した環境変数が展開されませんでした。

このように、Kubernetesマニフェストの commandargs で環境変数を参照する場合、
シェルの感覚で $NAME${NAME} と記述してもうまく展開されないことがあります。

環境変数を参照するにはどうしたら良いでしょう?

対処法1:$(...) 形式で参照

先程の環境変数を参照していた ${NAME} という記述を $(NAME) のように 丸括弧 に書き換えます。

$ cat <<'EOF' >test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
    - name: test-pod
      image: bash
      command: ["echo"]
      args:
        - "$(NAME)"
      env:
        - name: NAME
          value: "genzouw"
EOF

では、このマニフェストファイルをapplyしてみます。

$ kubectl apply -f test-pod.yaml
pod/test-pod created

applyが正常にできたら、ログを確認してみます。

$ kubectl logs -f test-pod
genzouw

環境変数の値が正しく出力されるようになりました。

対処法2:bash -c 形式で参照

こちらの方法が見やすくて個人的には好きですが、利用のためにいくつかの条件をクリアしなければなりません。
commandbash -c を指定し、 args にスクリプト文字列を埋め込んでやるとなぜか ${NAME} が参照できるようになります。

$ cat <<'EOF' >test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
    - name: test-pod
      image: bash
      command: ["bash", "-c"]
      args:
        - |
          echo "${NAME}"
      env:
        - name: NAME
          value: "genzouw"
EOF

マニフェストファイルをapplyします。

$ kubectl apply -f test-pod.yaml
pod/test-pod created

applyが正常にできたら、ログを確認してみます。

$ kubectl logs -f test-pod
genzouw

環境変数の値が正しく出力されるようになりました。

ひとこと

個人的には通常のシェルと同じ感覚で記述できる 対処法2 の方が好きではありますが、利用できる条件が揃っている場合しか利用できません。
対処法1 の方法はどんな記法を採用していても利用できます。