GKEで機密情報を扱うときは、秘密値の正本を Secret Manager に置き、Podには必要な時だけ最小権限で渡します。「Secret Managerを使う」だけでなく、アプリケーションへどの形で渡すかを選ぶことが重要です。

4つの方式
| 方式 | Podから見える形 | Kubernetes Secretへの複製 | 向いている場面 |
|---|---|---|---|
| クライアントライブラリ | API応答 | なし | アプリを変更できる。まず検討 |
| GKE Secret Manager add-on | 読み取り専用Volume | なし | ファイル読込に対応できる |
| GKEのSecret同期 | Kubernetes Secret | あり | 環境変数・既存Secret参照が必要 |
| External Secrets Operator | Kubernetes Secret | あり | マルチクラウド、既存ESO運用、柔軟な同期が必要 |
Google Cloudは、可能ならクライアントライブラリによる直接取得、次にマネージドadd-onによるVolumeマウントを推奨しています。既存アプリがKubernetes Secretしか読めない場合に同期方式を選びます。
共通前提:キーではなくWorkload Identityを使う
どの方式でも、サービスアカウントJSONキーをSecretやイメージへ置きません。第10回のWorkload Identity Federation for GKEを使い、KSA主体または必要最小限のIAM service accountへ対象Secretの参照権限を付与します。
プロジェクト全体へ roles/secretmanager.secretAccessor を付けるより、個別SecretのIAMポリシーへ付ける方が安全です。アプリAがアプリBの秘密値まで読める構成にしません。
方式1:アプリから直接取得する
Google Cloud公式クライアントライブラリはApplication Default Credentialsを使えます。アプリはSecretのリソース名を指定し、起動時または必要時に取得します。
利点は、秘密値をKubernetes APIへ複製せず、監査経路をSecret Managerへ集約できることです。一方、取得失敗時の再試行、キャッシュ、バージョン切替、ローテーション後の再読込をアプリ側で設計します。
環境変数はプロセス起動時に固定されやすいため、頻繁なローテーションが必要ならメモリ上の更新方法も検討します。
方式2:GKE Secret Manager add-onでVolumeへマウントする
GKEのマネージドadd-onは、Secrets Store CSI Driverの仕組みでSecretをPodの読み取り専用Volumeへマウントします。概念的な SecretProviderClass は次の形です。利用前にクラスタでadd-onを有効化し、公式手順の現行APIを確認してください。
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: example-secret-provider
namespace: YOUR_NAMESPACE
spec:
provider: gke
parameters:
secrets: |
- resourceName: "projects/YOUR_PROJECT_ID/secrets/YOUR_SECRET_ID/versions/latest"
path: "database-password"
Pod側ではCSI Volumeをマウントします。
spec:
serviceAccountName: YOUR_KSA_NAME
containers:
- name: app
image: registry.gitlab.com/GROUP/PROJECT/IMAGE:TAG
volumeMounts:
- name: secrets
mountPath: /var/run/secrets/app
readOnly: true
volumes:
- name: secrets
csi:
driver: secrets-store-gke.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: example-secret-provider
アプリは /var/run/secrets/app/database-password を読みます。秘密値をログへ出したり、エラーメッセージへ含めたりしないようにします。
方式3:GKEのSecret同期を使う
GKEにはSecret Managerの値をKubernetes Secretへ同期する統合機能もあります。既存アプリが secretKeyRef や通常のSecret Volumeしか使えない場合に、マネージドな選択肢になります。
ただし同期後は、秘密値がKubernetes Secretとしてクラスタ内にも存在します。NamespaceのRBAC、Secret閲覧権限、バックアップやログへの混入、同期停止時の挙動まで保護対象が増えます。アプリがVolumeを読めるなら、複製しないadd-onを先に検討します。
方式4:External Secrets Operatorを使う
既存の運用方式に合わせる場合、External Secrets Operator(ESO) をHelmで導入し、Secret ManagerからKubernetes Secretへ同期できます。ESOはGoogle Cloud以外の外部ストアも同じ考え方で扱えるため、マルチクラウドや既存資産との整合に向きます。
SecretStore
次はNamespace内だけで使える SecretStore の構造例です。導入したESOのCRDバージョンと公式provider仕様を確認してください。
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
name: google-secret-manager
namespace: YOUR_NAMESPACE
spec:
provider:
gcpsm:
projectID: YOUR_PROJECT_ID
auth:
workloadIdentity:
clusterLocation: YOUR_REGION
clusterName: YOUR_CLUSTER_NAME
serviceAccountRef:
name: YOUR_KSA_NAME
ExternalSecret
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: example-app-secret
namespace: YOUR_NAMESPACE
spec:
refreshInterval: 1h
secretStoreRef:
kind: SecretStore
name: google-secret-manager
target:
name: example-app-secret
creationPolicy: Owner
data:
- secretKey: DATABASE_PASSWORD
remoteRef:
key: YOUR_SECRET_ID
version: latest
実際の秘密値はマニフェストに現れません。生成されたSecretをアプリの secretKeyRef から参照します。
ESOの確認順
kubectl get secretstore,externalsecret -n YOUR_NAMESPACE
kubectl describe secretstore google-secret-manager -n YOUR_NAMESPACE
kubectl describe externalsecret example-app-secret -n YOUR_NAMESPACE
kubectl get secret example-app-secret -n YOUR_NAMESPACE
kubectl logs -n external-secrets \
deployment/external-secrets --tail=100
kubectl get secret ... -o yaml で data を表示してもBase64であり、機密情報の露出につながります。値そのものではなく、Ready condition、イベント、キー名の存在を確認します。
選定フロー
- アプリを変更できる → クライアントライブラリで直接取得
- ファイルを読める → GKE Secret Manager add-on
- Kubernetes Secretが必須でGKE統合を使える → GKEのSecret同期
- 既存ESO運用、複数provider、高い移植性が必要 → ESO
ESOは有力ですが「Secret Managerに必須」ではありません。運用するコントローラーと複製先を増やす価値がある場合に選びます。
ローテーション設計
latestを使うか、バージョンを固定して段階切替するか決める- 取得・同期間隔とアプリの再読込タイミングを合わせる
- 旧バージョンを無効化する前に新バージョンの利用を確認する
- 監査ログとアラートで異常なSecret参照を検出する
- 障害時も秘密値をログや画面へ表示しない