Pod の YAML ファイルに env を追加して再度 YAML ファイルを出力したい

今回はタイトルにあるように Pod が定義された YAML ファイルに任意の環境変数を追加して再度 YAML ファイルとして出力する。

満たしたい要件は

  • Pod に env が定義されてなくても環境変数を追加できる
  • すでに定義されている環境変数に対しては上書きをする
  • 複数のコンテナがある場合は絞ることができる

今回は下記の YAML を使用する。

# pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: apps
spec:
  containers:
  - name: app-1
    image: busybox
  - name: app-2
    image: busybox

ゴールとしては下記のファイルが出力されることを目指す。

apiVersion: v1
kind: Pod
metadata:
  name: apps
spec:
  containers:
  - name: app-1
    image: busybox
  - name: app-2
    image: busybox
    env:
    - name: FOO
       value: BAR

yq

YAML ファイルの操作になるので真っ先に思いついたのが yq を使うことでした。

github.com

公式サイトを見ると Multiply (Merge) に今回のように環境変数を追加したい時に使える例が書いてあるので、これをベースに今回の要件を満たすように変更したコマンドが下記になります。

idPath=".name"  originalPath=".spec.containers[] | select(.name == \"app-2\") | .env"  otherPath=".env" yq eval-all '
(
  (( ((eval(strenv(originalPath)) // []) + eval(strenv(otherPath)))  | .[] | {(eval(strenv(idPath))):  .}) as $item ireduce ({}; . * $item )) as $uniqueMap
  | ( $uniqueMap  | to_entries | .[]) as $item ireduce([]; . + $item.value)
) as $mergedArray
| select(fi == 0) | (eval(strenv(originalPath))) = $mergedArray
' pod.yaml <(echo '{"env": [{"name": "FOO", "value": "BAR"}]}' | yq -P)

むずかしいですね。。。yq 慣れしてない私はパッと見ただけでは何が起きているのか分かりませんでした。

kubectl

次に試したのが kubectl です。今回は Kubernetes のリソースを扱うので kubectl で実現できないかと試しました。結果としてできたコマンドは下記になります。

cat pod.yaml | \
  kubectl patch \
    -f - \
    --local \
    -o yaml \
    -p '
      {
        "spec": {
          "containers": [
            {
              "name": "app-2",
              "env": [
                {
                  "name": "FOO",
                  "value": "BAR"
                }
              ]
            }
          ]
        }
      }'

今回は yq の時よりは分かりやすくなったのではないでしょうか。-p で指定している JSON を使用して patch が行われ、spec.containers 内で name を指定することによって特定のコンテナに環境変数が追加されます。

環境変数を追加するという目的であれば kubectl set env も使えるのですが、これは変更がない場合には YAML ファイルを出力してくれなかったので、kubectl patch を使用しています。

最後に

今回は Pod の YAML ファイルに env を追加して YAML ファイルを出力するために yqkubectl を試し最終的にシンプルさから kubectl を選択しました。 Kubernetes 周りの操作をする時は、まずは kubectl で実現できないかをしていくと良さそう。