Secret を使用したアプリケーションの設定

KubernetesBeginner
オンラインで実践に進む

はじめに

アプリケーションでは、パスワード、トークン、データベースの認証情報など、コンテナイメージやプレーンテキストのマニフェストに直接記述すべきではない値を扱うことがよくあります。Kubernetes の Secret は、こうした機密性の高い設定を独立したオブジェクトとして保存し、Pod の起動時にそれを利用できるようにします。

この実験では、Secret の作成、エンコードされたデータの慎重な確認、アプリケーション Pod への接続、Secret の更新、そしてアプリケーションが新しい値を読み込めるようにするための Pod の再作成を行います。この実験では、Secret の基本的なワークフローに焦点を当てます。後の実験では、環境変数の詳細な設定やファイルベースの設定マウントについて学習します。

Secret 実践用の名前空間を準備する

このステップでは、Secret の練習用にクリーンな名前空間を準備します。

/home/labex/project から開始します。このディレクトリ内に Pod のマニフェストを 1 つ作成します。

mkdir -p /home/labex/project
cd /home/labex/project

Kubernetes API サーバーに接続できるか確認します。VM が起動した直後でノードの準備ができていない場合は、数秒待ってから再度コマンドを実行してください。

kubectl get nodes --request-timeout=5s

期待される出力例:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

アプリケーションオブジェクトを作成する前に、クラスターのネットワーク Pod が「Ready」状態になるまで待ちます。

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

期待される出力:

pod/calico-node-... condition met

ckad-prep-secrets という名前の名前空間を作成します。

kubectl create namespace ckad-prep-secrets

この名前空間を現在のコンテキストの名前空間として設定します。

kubectl config set-context --current --namespace=ckad-prep-secrets

現在の名前空間を確認します。

kubectl config view --minify --output 'jsonpath={..namespace}'; echo

期待される出力:

ckad-prep-secrets

Secret の作成と確認

このステップでは、小規模なアプリケーション用のデータベース接続設定を保存する Secret を作成します。

kubectl create secret generic コマンドは、不透明(Opaque)な Secret を作成します。generic は、Kubernetes がキーに対して特別な組み込みの意味を割り当てないことを意味します。各 --from-literal フラグは、Secret に 1 つのキーと値のペアを追加します。

kubectl create secret generic db-credentials \
  --from-literal=DB_USER=orders-app \
  --from-literal=DB_PASSWORD=dev-password-123 \
  --from-literal=DB_NAME=orders

期待される出力:

secret/db-credentials created

Secret の概要を確認します。

kubectl get secret db-credentials

期待される出力:

NAME             TYPE     DATA   AGE
db-credentials   Opaque   3      ...

Secret を YAML 形式で表示します。Kubernetes は data フィールド内の値を base64 エンコードされた文字列として保存するため、この出力で元のパスワードがそのまま見えることはありません。

kubectl get secret db-credentials -o yaml

期待される出力例:

data:
  DB_NAME: b3JkZXJz
  DB_PASSWORD: ...
  DB_USER: b3JkZXJzLWFwcA==
type: Opaque

Base64 エンコーディングは暗号化ではありません。Secret オブジェクトを読み取れる権限を持つ人は誰でも値をデコードできます。ここでは、パスワードを表示せずに表現方法を確認するために、ユーザー名のみをデコードします。

kubectl get secret db-credentials -o 'jsonpath={.data.DB_USER}' | base64 --decode; echo

期待される出力:

orders-app

Secret を使用した Pod の設定

このステップでは、Secret を環境変数として読み込む Pod を起動します。

envFrom.secretRef フィールドは、Secret 内のすべてのキーをコンテナ環境にインポートします。これは前回の実験の ConfigMap パターンと似ていますが、値は Secret オブジェクトから取得されます。この Pod 内のコマンドは、ユーザー名とデータベース名を表示し、パスワードが読み込まれたことのみを確認します。パスワード自体は表示しません。

secret-reader-pod.yaml を作成します。

cat > secret-reader-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: secret-reader
  labels:
    app: secret-reader
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: reader
    image: busybox:1.36
    command:
    - /bin/sh
    - -c
    - 'echo user=${DB_USER}; echo database=${DB_NAME}; if [ -n "${DB_PASSWORD}" ]; then echo password-loaded; fi; sleep 3600'
    envFrom:
    - secretRef:
        name: db-credentials
EOF

Pod マニフェストを適用します。

kubectl apply -f secret-reader-pod.yaml

期待される出力:

pod/secret-reader created

Pod が「Ready」になるまで待ちます。

kubectl wait --for=condition=Ready pod/secret-reader --timeout=120s

期待される出力:

pod/secret-reader condition met

Pod のログを読み取ります。アプリケーションは Secret の値が利用可能であることを確認していますが、パスワードの値は表示されていません。

kubectl logs secret-reader -c reader

期待される出力:

user=orders-app
database=orders
password-loaded

Secret の更新と Pod の再作成

このステップでは、Secret を更新し、コンテナが新しい値を受け取れるように Pod を再作成します。

コンテナの環境変数は、コンテナ起動時に確定されます。Secret が環境変数として使用されている場合、Secret オブジェクトを更新しても、実行中のコンテナ内の環境変数は自動的に書き換わりません。アプリケーションが更新された Secret の値を読み込む必要がある場合は、新しい Pod を起動する必要があります。

新しいアプリケーションユーザーとパスワードで Secret にパッチを適用します。

kubectl patch secret db-credentials --type merge --patch '{"stringData":{"DB_USER":"orders-worker","DB_PASSWORD":"rotated-password-456","DB_NAME":"orders"}}'

期待される出力:

secret/db-credentials patched

DB_USER のみをデコードして、更新されたユーザー名を確認します。

kubectl get secret db-credentials -o 'jsonpath={.data.DB_USER}' | base64 --decode; echo

期待される出力:

orders-worker

古い Pod を削除します。

kubectl delete pod secret-reader

期待される出力例:

pod "secret-reader" deleted

同じマニフェストから Pod を再作成し、「Ready」になるまで待ちます。

kubectl apply -f secret-reader-pod.yaml
kubectl wait --for=condition=Ready pod/secret-reader --timeout=120s

期待される出力:

pod/secret-reader created
pod/secret-reader condition met

再度ログを読み取ります。新しい Pod は Secret から更新されたユーザー名を参照しており、パスワードの生値をログに出力することなく動作しています。

kubectl logs secret-reader -c reader

期待される出力:

user=orders-worker
database=orders
password-loaded

まとめ

Kubernetes Secret を作成し、エンコードされたデータを確認し、非機密キーをデコードして表現方法を理解しました。また、Secret をアプリケーション Pod に接続し、Secret 更新後に Pod を再作成する手順を学びました。さらに、機密設定を扱う際の重要な習慣として、パスワードの値をログに出力することなく、アプリケーションが正しくパスワードを受け取ったことを検証する方法を実践しました。