【GKE】ConfigMapで環境変数を設定してGOで呼び出すtomlファイルを切り替える


前提

前提として、GKE上にコンテナをデプロイしているものとして話を進めます。

GKE上にコンテナをデプロイする方法はすっ飛ばしますので、以下の記事を参考にしてもらえると嬉しいです。

参考:https://cloud.google.com/kubernetes-engine/docs/tutorials/hello-app?hl=ja

また、そもそものDockerfileを作成する方法を知りたい人は、以下にまとめたので参考にしてもらえると嬉しいです。(GOのDockfileの作成方法というよりは、Nuxt.jsmulti-stage buildのやり方を解説してる内容ですが…。)

参考:https://qiita.com/arthur_foreign/items/fca369c1d9bde1701e38

環境変数ごとにGOで呼び出すtomlファイルを切り替える

GKEで環境変数ごとに呼び出すtomlファイルを切り替えていきたいと思います。

接続するDB(Aurora)を環境変数ごとに切り替える想定ですが、ConfigMapとはズレるお話なので色々省略しました。

database.go

// 省略

func init() {
    var config Config

    var filePath string

    env := os.Getenv("TEST")
    switch env {
      case "production":
        filePath = "prd.toml"
      case "staging":
        filePath = "stg.toml"
      case "development":
        filePath = "dev.toml"
      case "test":
        filePath = "test.toml"
      default:
        filePath = "dev.toml"
    }

// 省略

}

※パスワードはtomlに書き込まずに、Secretで管理しようと思いましたが、別の記事で対応しようと思います。

defaultの環境変数が呼び出されてGKE上PodがCrashしていた

以下のログを見るに、PodがCrashを繰り返しているようです。

$ kubectl get pods
NAME                                    READY   STATUS             RESTARTS   AGE
aiueo-1-xxxxxxxxxx-xxxxx                0/1     CrashLoopBackOff   8          19m
aiueo-1-xxxxxxxxxx-xxxxy                0/1     CrashLoopBackOff   8          19m
aiueo-1-xxxxxxxxxx-xxxxz                0/1     CrashLoopBackOff   8          19m

原因を調べるためにログを出してみましょう。

$ kubectl logs aiueo-1-xxxxxxxxxx-xxxxx
panic: dial tcp: lookup host.docker.internal on xx.x.x.xx:xx: no such host
※適当にぼかしてます。

GKE上でデプロイした時に環境変数が正しく設定されておらずに、switchdefaultcaseであるdev.toml(ローカル開発時に使用するファイル)が呼び出されていたようです。

以下がdev.tomlのソースコードになります。

dev.toml
[MySQL]

Host     = "host.docker.internal"
Username = "jojo"
Database = "dio"
Password = "wryyyyy"

そのため、GKE上にコンテナをデプロイする際に、ConfigMapで環境変数を設定してあげましょう。

ConfigMapとは

ConfigMap は、実行時に構成ファイル、コマンドライン引数、環境変数、ポート番号、およびその他の構成成果物をポッドのコンテナやシステム コンポーネントにバインドします。ConfigMap を使用すると、構成をポッドやコンポーネントから分離できます。これにより、ワークロードの移植性が維持され、構成の変更や管理が容易になり、構成データがポッド仕様に制約されなくなります。
引用:https://cloud.google.com/kubernetes-engine/docs/concepts/configmap?hl=ja

ConfigMapの説明は上記の引用ママで、特に補足とかは必要ないかなと思ってます。(GCPのドキュメントはめちゃくちゃ分かりやすい)

ただ、ConfigMapの注意点としては以下です。

ConfigMap は、機密性が低く、暗号化されていない構成情報を保存して共有するのに便利です。クラスタで機密情報を使用するには、シークレットを使用する必要があります。
引用:https://cloud.google.com/kubernetes-engine/docs/concepts/configmap?hl=ja

引用通り、パスワードやSSH認証鍵などの機密性の高い情報を管理する際にはConfigMapではなく、Secretの方が適切かと思ってます。

ちなみに、GKE上ではConfigMapだとKey:ValueのValueが見えますが、Secretでは見えません。

GKE上のConfigMapの表示

また、Deploymentでは、ConfigMapについて以下のような記載がされています。

//省略
spec:
  containers:
  - env:
    - name: TEST
      valueFrom:
        configMapKeyRef:
          key: TEST
          name: nginx-1-config
//省略

GKE上のSecretの表示

デプロイするGOのコンテナに環境変数の設定をする

GKEのコンソール上でコンテナをデプロイする時に、ってところにKeyとValueを設定します。

適当にTestをKeyにtestをValueにしましょう。

作成されたPodを見ると、先ほど設定した環境変数がConfigMapに設定されているので確認します。

以下の画像のように、先ほど設定したKeyValueが確認できましたね。

これで、先ほどdefaultdev.tomlではなく、test.tomlが呼ばれるはずです。

test.tomlにちゃんとした設定を書いておけば、GKE上のPodはCrashせずに以下のようなログが出ました。

$ kubectl logs aiueo-1-xxxxxxxxxx-xxxxx

   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v3.3.10-dev
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:8080