2026年版 Kubernetesシークレット管理完全ガイド:External Secrets、Vault、面接対策

Kubernetesのシークレット管理について、External Secrets Operator、HashiCorp Vaultとの連携、本番環境でのベストプラクティス、および技術面接での頻出質問を解説します。

Kubernetes Secrets Management with External Secrets Operator and HashiCorp Vault architecture diagram

Kubernetesのシークレット管理は、コンテナオーケストレーションにおいて最も重要なセキュリティ課題の一つです。ネイティブのKubernetes Secretは機密データをbase64エンコードで保存しますが、デフォルトでは保存時の暗号化が提供されません。この脆弱性は、DevOps採用面接で頻繁に問われるセキュリティリスクを生み出します。

面接での即答ポイント

Kubernetesシークレットのセキュリティについて質問された場合:ネイティブSecretはbase64エンコードであり、暗号化ではありません。本番環境では、HashiCorp VaultやAWS Secrets Managerなどの外部シークレットマネージャーが必要で、External Secrets Operator(ESO)を介して同期します。この分離により、シークレットがGitリポジトリに存在することを防ぎます。

ネイティブKubernetes Secretの限界

組み込みのSecretリソースは、etcdにbase64エンコードでデータを保存します。このエンコードは単一コマンドで元に戻すことができます:

bash
# decoding-secret.sh
# Kubernetesシークレット値を即座にデコード
kubectl get secret db-credentials -o jsonpath='{.data.password}' | base64 -d

base64は暗号化ではありません。クラスターアクセス権を持つ者であれば、シークレット値を読み取ることができます。Kubernetesドキュメントでは、Secretは「デフォルトでは暗号化されていない」と明記されており、保存時の暗号化を有効にすることを推奨しています。

本番デプロイメントに影響する3つの主要な制限があります:

  1. 監査証跡がない:ネイティブSecretは、誰がいつどの値にアクセスしたかのログを提供しません
  2. ローテーション機構がない:シークレットの変更には手動介入とPodの再起動が必要です
  3. GitOpsとの非互換性:暗号化されたシークレットをGitに保存しても、暗号化キー管理の問題が残ります

External Secrets Operatorのアーキテクチャ

External Secrets Operator(ESO)は、Kubernetesと外部シークレット管理システムを橋渡しします。2023年にCNCF Sandboxプロジェクトとしてリリースされ、2026年にはv0.10に到達しました。ESOは、AWS Secrets Manager、HashiCorp Vault、Google Secret Manager、Azure Key Vault、その他15以上のバックエンドをサポートしています。

アーキテクチャは3つのカスタムリソースで構成されます:

yaml
# secret-store.yaml
# ClusterSecretStoreはVaultへの接続を定義
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: vault-backend
spec:
  provider:
    vault:
      server: "https://vault.internal:8200"
      path: "secret"
      version: "v2"
      auth:
        kubernetes:
          mountPath: "kubernetes"
          role: "external-secrets"
          serviceAccountRef:
            name: "external-secrets"
            namespace: "external-secrets"

このClusterSecretStoreは、Kubernetesサービスアカウントトークンを使用してVaultで認証するようESOを設定します。kubernetes認証メソッドは、クラスターのTokenReview APIに対してサービスアカウントJWTを検証します。

yaml
# external-secret.yaml
# ExternalSecretは実際のシークレットデータを取得して同期
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: database-credentials
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend
    kind: ClusterSecretStore
  target:
    name: db-secret
    creationPolicy: Owner
  data:
    - secretKey: username
      remoteRef:
        key: secret/data/production/database
        property: username
    - secretKey: password
      remoteRef:
        key: secret/data/production/database
        property: password

ESOは1時間ごとにVaultをポーリングし(refreshInterval: 1h)、Kubernetes Secretを自動的に更新します。creationPolicy: Ownerは、ExternalSecretが削除されたときにSecretも削除されることを保証します。

HashiCorp Vault連携パターン

Vaultは、動的シークレット、自動ローテーション、包括的な監査ログを提供します。Vault Kubernetes認証ドキュメントに記載されているKubernetes認証メソッドにより、長期間有効な認証情報を配布せずにPodが認証できます。

Vault認証のセットアップには3つのステップが必要です:

bash
# vault-k8s-auth.sh
# VaultでKubernetes認証メソッドを有効化
vault auth enable kubernetes

# Kubernetes APIに対してトークンを検証するようVaultを設定
vault write auth/kubernetes/config \
  kubernetes_host="https://kubernetes.default.svc:443" \
  kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt

# サービスアカウントをポリシーにバインドするロールを作成
vault write auth/kubernetes/role/external-secrets \
  bound_service_account_names=external-secrets \
  bound_service_account_namespaces=external-secrets \
  policies=readonly-secrets \
  ttl=1h

この設定は、external-secretsサービスアカウントをVaultポリシーにバインドします。TTLはトークンの有効期限を制限し、再認証を強制することで、侵害されたトークンの影響範囲を縮小します。

本番デプロイメントでは、最小権限の原則に従ったポリシーが必要です:

hcl
# readonly-secrets.hcl
# 特定パスへの読み取り専用アクセスを付与するVaultポリシー
path "secret/data/production/*" {
  capabilities = ["read"]
}

path "secret/metadata/production/*" {
  capabilities = ["list"]
}

このポリシーは、本番シークレットパスへの読み取りアクセスのみを付与します。異なる環境を管理するチームは、対応するパス制限を持つ別々のポリシーを受け取ります。

ダウンタイムなしのシークレットローテーション

自動ローテーションは、シークレットが陳腐化した攻撃ベクトルになることを防ぎます。ESOはKubernetes側を処理しますが、アプリケーションは再起動なしでシークレットをリロードする必要があります。

ゼロダウンタイムローテーションには2つのアプローチがあります:

ファイル監視付きボリュームマウントシークレット:

yaml
# deployment-volume-secrets.yaml
# 自動更新されるファイルとしてシークレットをマウント
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
spec:
  template:
    spec:
      containers:
        - name: api
          image: api:v2.1.0
          volumeMounts:
            - name: secrets
              mountPath: /etc/secrets
              readOnly: true
      volumes:
        - name: secrets
          secret:
            secretName: db-secret

Kubernetesは、kubelet同期期間内(デフォルト1分)にマウントされたシークレットファイルを更新します。アプリケーションは各データベース接続時に/etc/secrets/passwordから認証情報を読み取り、再起動なしで新しい値を取得します。

環境変数シークレット用のReloader:

環境変数を使用するアプリケーションにはPodの再起動が必要です。Stakater Reloaderはこれを自動化します:

yaml
# deployment-with-reloader.yaml
# アノテーションはシークレット変更時にローリング再起動をトリガー
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
  annotations:
    reloader.stakater.com/auto: "true"
spec:
  template:
    spec:
      containers:
        - name: api
          envFrom:
            - secretRef:
                name: db-secret

ReloaderはSecret更新を監視し、ローリング再起動を実行して、ローテーション中の可用性を維持します。

DevOpsの面接対策はできていますか?

インタラクティブなシミュレーター、flashcards、技術テストで練習しましょう。

Kubernetesシークレットに関する面接質問

DevOps面接では、シークレット管理の理解を一貫してテストします。これらの質問は、ジュニアからシニアレベルまで出題されます:

Q: Kubernetes Secretが使用するエンコーディングは何ですか?なぜこれはセキュリティに不十分ですか?

Secretはbase64エンコーディングを使用しますが、これは可逆変換であり、暗号化ではありません。Secretに対するget権限を持つユーザーは誰でも値をデコードできます。セキュリティには、保存時の暗号化(etcd暗号化の有効化)とRBAC権限の制限が必要です。より深いKubernetesの概念については、Kubernetes面接の基礎を参照してください。

Q: GitOpsを使用する際、シークレットがGitリポジトリに表示されないようにするにはどうしますか?

External Secrets Operatorは、値そのものではなく、シークレットへの参照のみをGitに保存します。ExternalSecretマニフェストにはVaultまたはAWS Secrets Manager内のシークレットへのパスが含まれており、実際のシークレットがリポジトリに触れることはありません。BitnamiのSealed Secretsは、非対称暗号化を使用した代替アプローチを提供します。

Q: SecretStoreとClusterSecretStoreの違いを説明してください。

SecretStoreは名前空間スコープです:同じ名前空間内のExternalSecretsがそれを参照できます。ClusterSecretStoreはクラスター全体のスコープです:任意の名前空間から参照できます。複数のチームが単一のVaultインスタンスを共有する場合はClusterSecretStoreを使用し、各名前空間が分離されたシークレットバックエンドを持つ場合はSecretStoreを使用します。

Q: デプロイ後にPodがシークレットにアクセスできません。どのようにトラブルシュートしますか?

ExternalSecretのステータスから始めます:

bash
# troubleshoot-secrets.sh
# ExternalSecretの同期ステータスと条件を確認
kubectl get externalsecret database-credentials -o yaml

# Secretが作成されたことを確認
kubectl get secret db-secret -o yaml

# 認証エラーについてESOコントローラーログを確認
kubectl logs -n external-secrets deployment/external-secrets

一般的な障害には、期限切れのVaultトークン、不正なシークレットパス、ClusterSecretStoreのRBAC設定ミスがあります。

Q: 本番環境でデータベース認証情報のシークレットローテーションをどのように処理しますか?

Vaultのデータベースシークレットエンジンは、動的で短命な認証情報を生成します。認証情報のTTLよりも短いrefreshIntervalでESOを設定します。ローテーションが必要な静的認証情報の場合、VaultのローテーションAPIとReloaderを組み合わせて、更新後にPodを再起動します。アプリケーションは、ローテーションウィンドウ中の接続失敗を適切に処理する必要があります。

AWS Secrets ManagerとESO

AWS Secrets Manager連携には、サービスアカウント用のIAMロール(IRSA)が必要です。このパターンは静的認証情報を完全に排除します:

yaml
# aws-secret-store.yaml
# IRSAを使用したAWS Secrets Manager用ClusterSecretStore
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: aws-secrets
spec:
  provider:
    aws:
      service: SecretsManager
      region: ap-northeast-1
      auth:
        jwt:
          serviceAccountRef:
            name: external-secrets-sa
            namespace: external-secrets

サービスアカウントのアノテーションはIAMロールにリンクします:

yaml
# service-account-irsa.yaml
# IAMロールアノテーション付きサービスアカウント
apiVersion: v1
kind: ServiceAccount
metadata:
  name: external-secrets-sa
  namespace: external-secrets
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789:role/external-secrets

AWSは、Lambda関数を使用してSecrets Managerで作成されたシークレットを自動的にローテーションします。ESOのリフレッシュ間隔と組み合わせることで、設定されたポーリング期間内にシークレットがKubernetesに伝播します。

マルチクラスターシークレット同期

複数のクラスターを運用する組織には、一貫したシークレット配布が必要です。この要件に対応する2つのパターンがあります:

ClusterSecretStoreを使用したハブアンドスポーク:

すべてのクラスターが中央のVaultインスタンスに接続します。各クラスターのESOインストールは同じシークレットを参照し、Vaultが名前空間ベースのポリシーを通じてアクセス制御を処理します。

Vault Enterpriseによるレプリケーション:

Vault Enterpriseはリージョン間のパフォーマンスレプリケーションをサポートします。各クラスターはローカルのVaultレプリカに接続し、一貫性を維持しながらレイテンシを削減します。Vaultレプリケーションドキュメントでは、ディザスタリカバリとパフォーマンスレプリケーションモードについて説明しています。

ArgoCDを使用するチームの場合、GitOpsデプロイメントパターンの記事では、複数のクラスターにExternalSecretsをデプロイするApplicationSetsについて説明しています。

シークレットアクセスのためのRBAC強化

デフォルトのクラスターロールは、過度なシークレットアクセスを付与します。最小限のロールを作成してRBACを強化します:

yaml
# restricted-role.yaml
# 特定の名前空間でのみシークレットアクセスを許可するロール
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: secret-reader
  namespace: production
rules:
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get"]
    resourceNames: ["db-secret", "api-key"]

resourceNamesフィールドは、明示的にリストされたシークレットへのアクセスを制限します。このフィールドがないと、ロールは名前空間内のすべてのシークレットへのアクセスを付与します。

結論

Kubernetesシークレット管理は、base64エンコーディングの制限を理解することから始まります。本番環境では、External Secrets Operatorを介したHashiCorp VaultまたはAWS Secrets Managerなどの外部シークレットマネージャーが必要です。

重要なポイントは次のとおりです:ネイティブSecretは暗号化を提供しない、ESOは外部バックエンドとの同期を自動化する、Vaultは動的シークレットと監査ログを提供する、そしてRBACは最小権限の原則に従って強化する必要があります。これらの概念は、DevOps面接で定期的にテストされ、クラウドネイティブ環境でのシークレット管理のベストプラクティスを形成します。

今日のチャレンジ

DevOps のバグを見つけられますか

実際のコード、隠れたバグ、1日1回。アカウントなしで試せます。

Anthony Fillion-Maillet

執筆

Anthony Fillion-Maillet

SharpSkill 創業者

10 年以上フルスタック開発に携わっています。SharpSkill を運営し、ここで公開される内容に責任を負っています。

2026年9月2日 更新

タグ

#kubernetes
#secrets
#vault
#devops
#security

共有

関連記事