Vault

Vault Secrets Operatorで実現するKubernetes×GitOpsの秘匿情報運用

2026-04-19
NicheeLab編集部

Kubernetesにおけるシークレットの最小権限・自動ローテーション・監査可能性を両立するなら、VaultとGitOpsの組み合わせが有力です。Vault Secrets Operator (VSO) はCRDを通してVaultの値をKubernetes Secretとして調達し、Gitで意図を宣言できます。

本稿では、VSOのCRD設計、Argo CD/Fluxによる同期順序、最小権限・ローテーション設計、障害時のふるまいまでを、Ops実務と資格対策の両面から解説します。

VSOとGitOpsの全体像

VSOは、Vaultへの接続・認証・シークレット取得をKubernetesのCRDとして宣言し、最終的にKubernetes Secretを生成します。GitOpsでは、これらCRDマニフェストをGitに保存し、Argo CDやFluxが同期してオペレーターの調和処理を呼び出します。結果として、秘匿情報の配布は「意図の宣言=Gitの変更」に集約され、変更理由やレビュー履歴を監査できます。

典型フローは次の通りです。1) GitにVaultConnection/VaultAuth/VaultStaticSecret/VaultDynamicSecretを定義 2) Argo CD/Fluxが同期 3) VSOがVaultに認証しシークレットを取得・更新 4) アプリPodはKubernetes Secretを参照。

  • Gitには意図(どのVaultパスをどのNamespaceに供給するか)のみを置き、値そのものは置かない。
  • Argo CD/Fluxの同期順序で、VaultConnection/VaultAuth → VaultStatic/DynamicSecret → Workloadの順に適用する。
  • 動的シークレットはTTL/ローテーションをVSOに任せ、アプリの再読込(ローリング再起動やファイルウォッチ)戦略を併用する。

GitOps×VSO×Vaultのデータフロー

pushreconcileauth (Kubernetes/AppRole)read/issue secretsmount/use (env/vol)Git (manif)Argo CD / FluxVault Secrets OperatorHashiCorp VaultKubernetes SecretWorkloads (Deployment/Job)

最小セットのCRD例(Gitに置く宣言)

apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultConnection
metadata:
  name: vc-default
  namespace: app
spec:
  address: https://vault.example.com:8200
  # Enterprise利用時はnamespace等を指定可。TLS/CABundleもここで指定。
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
  name: va-k8s
  namespace: app
spec:
  vaultConnectionRef: vc-default
  method: kubernetes
  mount: kubernetes
  kubernetes:
    role: app-role
    serviceAccount: app-sa
    audiences:
      - vault
---
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
  name: app-kv
  namespace: app
spec:
  vaultAuthRef: va-k8s
  mount: kv
  type: kv-v2
  path: app/config
  refreshAfter: 1m
  destination:
    create: true
    name: app-config
  # 必要なキーのみ抽出
  data:
    - secretKey: DB_USER
      remoteRef:
        key: username
    - secretKey: DB_PASS
      remoteRef:
        key: password

CRDと最小権限設計

VSOの主なCRDは、接続情報を定義するVaultConnection、認証方式と紐付くVaultAuth、静的値(KVなど)を取得するVaultStaticSecret、動的値(DBやクラウド一時認証など)を扱うVaultDynamicSecretです。これらをNamespace単位で分けると、チーム境界や責務分離が明確になります。

Vault側のポリシーは「必要なパスだけ許可」が基本です。VaultAuthが指すロール(Kubernetes AuthのroleやAppRole)は、対象パスのread/issue/renewに限定します。Kubernetes側ではVSOのServiceAccountに対して、対象Namespace内のSecret作成・更新の最小権限のみを与えます。

  • VaultAuthは認証方式(kubernetes/approle/jwtなど)を選べる。Kubernetes AuthならServiceAccountトークンで認証可能。
  • VaultStaticSecretはrefreshAfter等で再取得の周期を宣言できる。DynamicはTTLに応じて更新・再発行される。
  • Namespace分割とラベルで、どのArgo CD/FluxがどのCRDを同期するかを明確化する。
観点Vault Secrets Operator (VSO)Vault CSI/Agent InjectorExternal Secrets Operator (ESO)
配布単位CRD(K8s Secretを生成)Pod注入/CSIボリューム(Secretを生成しない構成も多い)CRD(K8s Secretを生成)
動的シークレット対応(TTL更新・再発行)基本はランタイム注入(再読込/再起動で更新)対応(プロバイダ経由で取得)
テンプレート化一部サポート(キー抽出/変換)限定的(注入中心)サポート(テンプレート/マッピング)
GitOps適合高い(CRDで意図を宣言)中(注入設定はPod側アノテーション中心)高い(CRDで意図を宣言)
Vault認証Kubernetes/AuthRole/JWT等をVaultAuthで宣言Agent側で設定(Kubernetes/AuthRole等)プロバイダ設定(Vault AppRole/K8s等)

VaultポリシーとKubernetes Authロールの最小例(概念)

# Vaultポリシー(HCL): app-policy
path "kv/data/app/config" {
  capabilities = ["read"]
}

# Kubernetes Authロール作成(概念的なCLI例)
# 実際のパラメータ名は環境に合わせて調整してください
vault write auth/kubernetes/role/app-role \
  bound_service_account_names=app-sa \
  bound_service_account_namespaces=app \
  policies=app-policy \
  ttl=1h

GitOps適用パターン(Argo CD/Flux)

同期順序は重要です。Argo CDならsync-waveアノテーション、FluxならKustomizationのdependsOnで、VaultConnection/VaultAuth → VaultStatic/DynamicSecret → Workloadの順に整列させます。これにより、アプリ適用時にはすでにSecretが存在します。

リポジトリ構成は、baseにVSO CRDと共通ポリシー、overlayに環境固有(パスやロール名、宛先Secret名)を置く形がわかりやすいです。マルチクラスターではクラスター毎のKustomization/Argo Applicationで分離します。

  • Argo CD: メタデータにargocd.argoproj.io/sync-waveを付与し、負の値→小→大の順に同期。
  • Flux: Kustomization.dependsOnで依存関係を明示。失敗時の再試行はコントローラに任せる。
  • Secret生成後にDeploymentを同期させると、起動失敗を避けやすい。

Argo CDでの同期順序(例)

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: app-secrets
  annotations:
    argocd.argoproj.io/sync-wave: "0"
spec:
  source:
    repoURL: https://git.example.com/org/app-config.git
    path: k8s/overlays/prod/secrets
    targetRevision: main
  destination:
    server: https://kubernetes.default.svc
    namespace: app
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: app-workload
  annotations:
    argocd.argoproj.io/sync-wave: "1"
spec:
  source:
    repoURL: https://git.example.com/org/app-config.git
    path: k8s/overlays/prod/workload
    targetRevision: main
  destination:
    server: https://kubernetes.default.svc
    namespace: app

セキュリティとコンプライアンスの要点

GitにはVaultパスや宛先Secret名などのメタデータだけを保存し、値はVaultだけに保持します。VSOのServiceAccountにはSecretのcreate/update権限のみを付与し、list/getを不要にしないか検討します(監査ポリシーに応じて決定)。

ネットワーク的には、VSO PodからVaultへのEgressを許容するNetworkPolicyを設定し、VaultにはmTLS/適切なCAを設定します。バックアップ面では、Kubernetes Secretのバックアップはあくまでキャッシュと捉え、復元はVaultから再調達する設計に寄せます。

  • 責務分離: VSO CRDのレビューはプラットフォーム/SRE、Vaultパス・ポリシーはセキュリティチームが管理など、役割境界を明確に。
  • 秘匿情報の露出経路を洗い出し、kubectl get secretの権限を最小化する。
  • 動的シークレットは短TTL+アプリの自動再接続で被害時間を短縮。

RBAC最小例(VSOがSecretを作るための権限)

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: vso-secrets-writer
  namespace: app
rules:
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: vso-secrets-writer-binding
  namespace: app
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: vso-secrets-writer
subjects:
  - kind: ServiceAccount
    name: vault-secrets-operator
    namespace: vso-system

運用・ローテーションと障害時のふるまい

静的シークレットはrefreshAfter等の周期やSpec変更で再取得されます。動的シークレットはTTLに合わせて更新/再発行され、最大TTL到達で再発行へ移行します。いずれも、更新されたKubernetes Secretをアプリがどう取り込むか(ローリング再起動、SIGHUP、ファイル監視など)は別途設計が必要です。

Vault到達不能時や認証失敗時は、VSOがステータス条件とイベントで失敗を通知し、以前に生成済みのKubernetes Secretは即座に削除されないのが一般的です。復旧後に再調和されます。挙動はエンジンやバージョン設定に依存するため、本番適用前に意図通りかを検証してください。

  • Secret更新に合わせたアプリ再起動は、kubectl rollout restartやReconcilerを使って自動化可能。
  • 監視: VSOコントローラのメトリクス/イベント、アプリの認証失敗ログを相関させる。
  • 失敗時のバックオフと再試行はオペレーターに任せ、手動での再同期はArgo CD/Fluxの機能で実行。

運用時のコマンド例

# Argo CDで強制再同期
aio argocd app sync app-secrets

# Secret更新に伴うDeploymentのローリング再起動
kubectl -n app rollout restart deploy/myapp

# 失敗イベントの確認
kubectl -n app describe vaultstaticsecret app-kv
kubectl -n vso-system logs deploy/vault-secrets-operator

資格対策チェックリスト(Ops向け)

出題では、どのリソースをGitで管理し、Vault側で何を定義するか、依存順序をどう保証するか、という運用設計が問われがちです。VSOのCRD役割、Kubernetes AuthロールとVaultポリシーの最小化、Argo CD/Fluxの同期制御は押さえておきましょう。

障害時のふるまい(Vault不達や認証失敗時の挙動、Secretの残存、動的シークレットのTTL更新ロジック)も理解しておくと、実務と試験の両方で有利です。

  • Gitに置く: VaultConnection/VaultAuth/VaultStatic/DynamicSecret、Argo/Fluxの定義。Vaultの値は絶対に置かない。
  • 順序制御: Argoのsync-wave、FluxのdependsOnでSecret→Workloadの順に。
  • 最小権限: Vaultポリシーは必要パスのみ。K8s RBACはSecretのcreate/update中心。
  • 更新伝播: Secret更新がPod環境変数に自動反映されない点(再起動が必要)を押さえる。

Kustomizeレイアウト(概念)

# ディレクトリ構成(例)
# k8s/
# ├─ base/
# │   ├─ vso/                # VSO CRDインスタンス(Connection/Auth/Static/Dynamic)
# │   └─ rbac/               # 最小RBAC
# └─ overlays/
#     ├─ dev/
#     │   ├─ kustomization.yaml
#     │   └─ patches/        # Vaultパスや宛先Secret名の調整
#     └─ prod/
#         ├─ kustomization.yaml
#         └─ patches/
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base/vso
  - ../../base/rbac
namespace: app
namePrefix: prod-
# 必要に応じてpatchesでVaultパスやロール名を変える

問題で確認

Ops

問題 1

GitOpsでVSOを用いてアプリにシークレットを供給する。起動失敗を避け、最小権限を満たす構成として最も適切なのはどれか。

  1. Argo CDでVaultConnection/VaultAuthをsync-wave 0、VaultStaticSecretを1、Deploymentを2に設定。Vaultポリシーは必要なパスのみread許可。
  2. Argo CDでDeploymentをsync-wave 0、VaultStaticSecretを1にし、起動後にSecretが無ければ再起動で対応。Vaultポリシーは*で全許可。
  3. Fluxで全Kustomizationを同一にまとめ、順序は未指定。VSOのServiceAccountにClusterRoleでsecretsの*権限を付与。
  4. Argo CDとFluxを併用し、両方から同じNamespaceに適用して衝突時は手動で調整。VaultはrootトークンをGitに保存。

正解: A

Secret→Workloadの順序制御(sync-waveで0→1→2)と、Vaultポリシーの必要最小権限(対象パスのみread)が原則。Bは順序が逆でポリシーが過剰、Cは順序未定義と過剰権限、Dは競合と重大なセキュリティ違反がある。

よくある質問

VSOとVault Agent Injector/CSIはどちらを選べばよいですか?

GitOpsで「Kubernetes Secretを成果物として残す」運用ならVSOが適します。Podへの直接注入やファイルとしてのエフェメラル提供を重視し、Secretリソースを作りたくない場合はAgent Injector/CSIが適します。両者の混在は可能ですが、パターンは明確に分けて運用してください。

Secretが更新されたらPodは自動で再起動されますか?

Kubernetes Secretを環境変数で参照している場合は自動再起動されません。ボリュームでマウントしている場合はファイルは更新されますが、アプリ側の再読込が必要です。ローリング再起動の自動化(例: Argo CDのhooksや専用コントローラの利用)を検討してください。

マルチテナント環境ではどう分割すべきですか?

NamespaceごとにVaultConnection/VaultAuthを分離し、VaultのKubernetes AuthロールもNamespaceとServiceAccountでバインドします。Argo CD/FluxのスコープもNamespaceまたはアプリ単位で分け、RBACはSecretのcreate/updateのみを付与する最小権限で運用します。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
Vault

Vault のコア概念を最短距離で理解する:Secret / Auth / Policy / Token

HashiCorp Vault Associate レベルで押さえるべきコア概念(Secret Engine、Auth ...

Vault

Vault Operations Professional: 上位資格としての範囲を実務目線で押さえる

HashiCorp Vault Operations Professional(Ops Pro)の出題範囲を、Assoc...

Vault

Vaultにおけるパスベースのルーティング: マウントとAPI構造を読み解く

HashiCorp Vaultのパスベースのルーティングを、マウント設計とAPIパスの観点から整理。Associateレ...

Vault

Vault Tokens の基礎: 認証の起点となる概念

HashiCorp Vault におけるトークンの役割、種類、ライフサイクル、ポリシー連携、設計パターンをAssocia...

Vault

Vault のトークン種類を正しく使い分ける: service / batch 実践

HashiCorp Vault Associate 向けの試験対策と実務運用を両立させた、service トークンと b...

Vaultの記事一覧 (101件)
© 2026 NicheeLab All rights reserved.