はじめに

ソフトウェアでは、データベースの URL やパスワードなどの設定をアプリケーションコードにハードコードするのは適切ではありません。変更が難しくなり、セキュリティ上のリスクも高まります。

Kubernetes では、次の 2 つのオブジェクトを使用してこの問題に対応します。

  1. ConfigMap:公開掲示板のようなものです。ここに「背景色は青」や「データベースのアドレスは 10.0.0.1」といった情報を掲示します。オフィス内の誰でも(Pod)その情報を読み取れます。
  2. Secret:パスワードやトークンなど、機密性の高い値に使用します。

アプリケーションコードと実行時設定を分離することは、単なる Kubernetes の機能ではなく、プラットフォーム設計における重要な原則です。

この実験では、次の操作を行います。

  • 掲示板(ConfigMap)にメモを書き込みます。
  • 金庫(Secret)にパスワードを保管します。
  • Pod がその両方を読み取れるように設定します。

ConfigMap を作成する

まず、Web サーバー用の設定ファイルを作成します。設定をイメージに組み込む代わりに、ConfigMap に保存します。

この方法は、コンテナ設計におけるより大きな原則の一部です。つまり、再利用可能なイメージを 1 つ作成し、実行時に環境ごとの設定を渡します。これにより、開発環境、ステージング環境、本番環境で同じコンテナを使用しながら、それぞれ異なる設定を適用できるため、イメージの移植性が高まります。

まず、nginx.conf という名前の簡単な Nginx 設定ファイルを作成します。

echo 'events {} http { server { listen 80; location / { return 200 "Hello from ConfigMap!"; } } }' > nginx.conf

次に、このファイルから nginx-config という名前の ConfigMap を作成します。これにより、ファイルが Kubernetes クラスターの掲示板に「掲示」されます。

kubectl create configmap nginx-config --from-file=nginx.conf

作成されたことを確認します。

kubectl describe configmap nginx-config

Data セクションに nginx.conf の内容が表示されます。

Secret を作成する

次に、機密情報を保存します。Secret は ConfigMap と似ていますが、Kubernetes は Secret をより慎重に扱い、保存時にデータを難読化します。

ここでは正確に理解しておくことが重要です。Secret は、マニフェストやイメージにパスワードをハードコードするより安全ですが、base64 エンコードは本当の暗号化ではありません。本番環境では、Secret の管理に保存時の暗号化、より厳格な RBAC、外部の Secret 管理システムを組み合わせることがよくあります。

ダミーのパスワードを保存する app-secret という名前の Secret を作成します。

kubectl create secret generic app-secret --from-literal=password=SuperSecretPass123

作成されたことを確認します。

kubectl get secret app-secret

詳細を表示しても、パスワードがそのまま表示されることはありません。パスワードは隠された状態(エンコードされた状態)で表示されます。

kubectl get secret app-secret -o yaml

password フィールドには、文字が複雑に並んだ値が表示されます。これは、肩越しの覗き見やログへの誤表示を防ぐことを目的とした base64 エンコードです。

ConfigMap をファイルとしてマウントする

次に、Pod が掲示板の内容を読み取れるようにします。

ConfigMap を使用する最も一般的な方法は、ファイルとしてマウントすることです。マウントされたデータは、ディスク上の通常のファイルと同じようにコンテナ内に現れます。

このファイル方式は、アプリケーションが特定のパスにある設定ファイルをもともと必要としている場合に便利です。Kubernetes は ConfigMap のデータをコンテナのファイルシステムに展開するため、アプリケーションは通常どおりファイルを読み取れます。

pod-config.yaml という名前のファイルを作成します。

nano pod-config.yaml

次の内容を貼り付けます。この Pod は nginx-config ConfigMap を /etc/nginx/nginx.conf にマウントします。

apiVersion: v1
kind: Pod
metadata:
  name: config-pod
spec:
  containers:
    - name: nginx
      image: nginx:alpine
      volumeMounts:
        - name: config-volume
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
  volumes:
    - name: config-volume
      configMap:
        name: nginx-config

保存して終了します(Ctrl+X、Y、Enter)。

適用します。

kubectl apply -f pod-config.yaml

起動するまで数秒待ちます。次に、コンテナ内を確認してファイルが存在するか確認します。

kubectl exec config-pod -- cat /etc/nginx/nginx.conf

作成した設定内容が表示されます。Pod が掲示板の内容を読み取り、そのファイルを使用できたことを確認できます。

Secret を環境変数として注入する

次は Secret です。パスワードを渡す一般的な方法の 1 つは、環境変数を使用することです。

この方法は便利ですが、同時にトレードオフもあります。環境変数はアプリケーションから簡単に読み取れる一方で、診断コマンドやプロセスの確認によって公開される可能性があります。Kubernetes がファイル方式と環境変数方式の両方をサポートしているのは、アプリケーションやリスクの特性によって適した方法が異なるためです。

pod-secret.yaml という名前のファイルを作成します。

nano pod-secret.yaml

次の内容を貼り付けます。この Pod は app-secret から password の値を取得し、APP_PASSWORD という環境変数に設定します。

apiVersion: v1
kind: Pod
metadata:
  name: secret-pod
spec:
  containers:
    - name: busybox
      image: busybox
      command: ["sleep", "3600"]
      env:
        - name: APP_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: password

保存して終了します(Ctrl+X、Y、Enter)。

適用します。

kubectl apply -f pod-secret.yaml

Pod が起動したら、コンテナ内の環境変数を確認します。

kubectl exec secret-pod -- env | grep APP_PASSWORD

APP_PASSWORD=SuperSecretPass123 と表示されます。

ここで重要なのは、Pod の定義そのものにパスワードが含まれていないことです。パスワードは「金庫」(Secret)に保存され、Pod は実行時に金庫を開くためのキーだけを持ちます。

まとめ

この実験では、コードと設定を分離する練習をしました。

次の操作を実行しました。

  1. ConfigMap(掲示板)を使用して、設定ファイルをサーバーに注入しました。
  2. Secret(金庫)を使用して、隠されたパスワードをアプリケーションに注入しました。

これで、Docker イメージを再ビルドしなくても、設定を更新したりパスワードをローテーションしたりできるようになりました。