KubernetesのPodからVaultへ安全に認証する王道は、Service Accountトークンを用いたKubernetes Auth Methodです。本稿では、RBACとロール設計の勘所、Sidecar(Vault Agent Injector)による秘密情報配布の実装ポイントを、試験観点と運用観点の両方から解説します。
Associate試験では、auth/kubernetesの構成要素、Service AccountとVaultロールの対応付け、Agent Injectorの注釈と動作、トークン更新やTTLの考え方が頻出です。設定例と比較表、ASCII図でイメージを固定しましょう。
Kubernetes Auth Methodは、Podに自動マウントされるService Account(SA)JWTを用い、Vault側でその正当性をKubernetes API経由で検証し、Vaultトークンを払い出す仕組みです。Sidecarパターンでは、Vault AgentがPod内で自動認証・シークレット取得・テンプレート展開を行い、アプリはファイル経由で秘密情報を参照します。
実務では、アプリをVaultに直接接続させるよりも、Sidecar(またはInit)経由のファイル配布が管理しやすく、ローテーションや再読み込みの制御も行いやすい傾向があります。以下の図で、認証からシークレット注入までの流れを確認します。
| パターン | 長所 | 注意点 |
|---|---|---|
| アプリがVaultへ直接login(SDK/HTTP) | 依存コンポーネントが少ない。柔軟な制御が可能。 | アプリ側で認証・更新・リトライ実装が必要。言語毎の実装差。 |
| Sidecar(Vault Agent Injector) | Pod注釈で簡易導入。自動認証・テンプレート・自動更新が一体化。 | 追加コンテナ分のリソース消費。注釈と権限設計の理解が必要。 |
| Initコンテナで一括注入 | 起動時に完結。アプリは単純なファイル読込のみ。 | 起動後のローテーションに弱い。更新にはPod再起動が必要。 |
| CSIドライバ(Secrets Store CSI + Vaultプロバイダ) | K8s標準ボリューム経由で参照。Secret未経由でファイル展開可。 | クラスタ側の追加運用が必要。機能差・同期挙動の理解が鍵。 |
Kubernetes Auth + Sidecarの典型フロー
最小構成の概念(抜粋)
# Pod内のService Accountトークンを使い、VaultのKubernetes Authでlogin。
# SidecarのVault Agentがテンプレートでシークレットをファイル出力し、
# アプリはread-onlyでマウントされたボリュームから読み取る。Vaultサーバー側では、Kubernetes Auth Methodを有効化し、Kubernetes APIへのTokenReviewが可能なService Accountを用意して、auth/kubernetes/configに必要情報を登録します。これにより、VaultはPodのJWTを正規のKubernetes発行トークンとして検証できます。
RBACは最小権限で十分です。TokenReviewと、該当するNamespaceのService Accountトークン検証に必要な権限のみを付与します。
| パラメータ | 目的 | 設定ヒント |
|---|---|---|
| kubernetes_host | Vaultが問い合わせるKubernetes APIエンドポイント | クラスタ内部からはhttps://$KUBERNETES_PORT_443_TCP_ADDR:443などを使用 |
| token_reviewer_jwt | Kubernetes APIでTokenReviewを行うためのJWT | 専用Service Accountのトークンを使用。Projected Token推奨 |
| kubernetes_ca_cert | APIサーバーのCA証明書 | クラスタのCAをConfigMapからマウントして渡す。SYSTEM CERTでも可(環境依存) |
設定コンポーネントの関係
Kubernetes Authの有効化とRBAC(例)
# 1) Vault側: Kubernetes Authを有効化
vault auth enable kubernetes
# 2) Reviewer用のService Account/RBAC(kube側)
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: vault-token-reviewer
namespace: vault
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:token-reviewer
rules:
- apiGroups: ["authentication.k8s.io"]
resources: ["tokenreviews"]
verbs: ["create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: vault-token-reviewer-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:token-reviewer
subjects:
- kind: ServiceAccount
name: vault-token-reviewer
namespace: vault
# 3) VaultにK8sクラスタ情報を登録
# 環境に合わせて$K8S_HOST, $REVIEWER_JWT, $CA_CERTを用意
vault write auth/kubernetes/config \
kubernetes_host="$K8S_HOST" \
token_reviewer_jwt="$REVIEWER_JWT" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crtVaultのKubernetesロールは、特定のService Account名とNamespaceの組み合わせに対してVaultポリシーを関連付け、許可されたPodからのloginにトークンを発行します。bound_service_account_names、bound_service_account_namespaces、必要に応じてbound_audiencesでJWTのaudienceを絞り込みます。
TTLやトークンタイプ(service, batch)もロールで制御可能です。アプリの更新間隔や再起動コストを踏まえ、短すぎないTTLと自動更新可否を決めます。
| ロール設計パターン | 適用シナリオ | リスク/留意点 |
|---|---|---|
| SA単位(細粒度) | マイクロサービスごとに最小権限を付与 | ロール数が増える。命名規則と管理の一貫性が重要 |
| Namespace単位(中粒度) | 同一Namespace内の複数Podで同一権限を共有 | 越権の可能性。Namespaceの境界運用が前提 |
| 複数SAを1ロールに集約 | 機能が近いサービス群をまとめて管理 | 差分要件に弱い。将来的な分離コストが上がる |
ロールとポリシーのひも付けイメージ
ロール作成とポリシー例
# ポリシー: kv v2の特定パスのみ許可
tee kv-app.hcl <<'EOF'
path "kv/data/app/*" {
capabilities = ["read"]
}
EOF
vault policy write kv-app kv-app.hcl
# ロール: app Namespaceのweb SAにバインド
aud="vault"
vault write auth/kubernetes/role/app-web \
bound_service_account_names=web \
bound_service_account_namespaces=app \
bound_audiences="$aud" \
policies=kv-app \
ttl=1h \
token_type=defaultVault Agent Injectorは、Podに注釈を付与するだけでSidecarと共有ボリュームを自動注入し、Kubernetes Authで認証・テンプレートを評価してファイルを生成します。アプリは環境変数ファイルや設定ファイルとして読み取るだけで済みます。
ローテーションが必要な証明書や短命トークンは、Agentの自動更新とSIGHUPリロード等を組み合わせると安定します。
| 注釈キー | 設定例 | 効果 |
|---|---|---|
| vault.hashicorp.com/agent-inject | "true" | Sidecarと共有ボリュームを注入 |
| vault.hashicorp.com/role | "app-web" | Kubernetes Authで使用するVaultロール |
| vault.hashicorp.com/agent-inject-secret-config | "kv/data/app/config" | テンプレートのデータソースとなるシークレットパス |
| vault.hashicorp.com/agent-inject-template-config | "{{ with secret \\"kv/data/app/config\\" }}{{ .Data.data | toJSON }}{{ end }}" | ファイル内容のテンプレート(Go template) |
InjectorのPod内レイアウト
Deployment注釈の最小例(kv v2からconfig.json生成)
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: app
spec:
replicas: 1
selector:
matchLabels: { app: web }
template:
metadata:
labels: { app: web }
annotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/role: "app-web"
# 出力ファイル名は注釈の末尾と一致
vault.hashicorp.com/agent-inject-secret-config: "kv/data/app/config"
vault.hashicorp.com/agent-inject-template-config: |
{{- with secret "kv/data/app/config" -}}{{ .Data.data | toJSON }}{{- end -}}
spec:
serviceAccountName: web
containers:
- name: app
image: ghcr.io/example/web:1.0
volumeMounts:
- name: vault-secrets
mountPath: /vault/secrets
readOnly: true
volumes:
- name: vault-secrets
emptyDir:
medium: MemoryKubernetes Authで払い出されたVaultトークンは、ロールのttlおよびmax_ttlの範囲で自動更新可能です。SidecarのAgentは期限前に更新し、失敗時には再試行します。更新不可が続く場合、テンプレートの再評価が止まり、アプリは最後に出力されたファイルを参照し続けます。
安定運用には、監視(トークン残存TTL、テンプレート更新時刻)、Pod再起動戦略、SIGHUP等での設定再読み込みを組み合わせ、万一の認証断でも影響範囲を限定します。
| 障害シナリオ | 典型的な症状 | 対策 |
|---|---|---|
| Kubernetes APIへの到達不可 | auth失敗、TokenReviewエラー、再試行が継続 | ネットワーク/Firewall確認、APIエンドポイント/CA更新、冗長経路 |
| SAトークンaudience不一致 | Invalid audienceでlogin失敗 | bound_audiencesとPodのProjected Tokenのaudを一致させる |
| ポリシー誤設定 | テンプレート評価でpermission denied | 必要pathのread/listを見直し、kv v2の/dataと/metadataの違いに注意 |
更新ループの簡略図
テンプレート例(環境変数ファイル)と再読込
# テンプレート例: .env 形式
{{- with secret "kv/data/app/db" -}}
DB_USER={{ .Data.data.username }}
DB_PASS={{ .Data.data.password }}
{{- end -}}
# アプリ側: ファイル変更検知でSIGHUP
# inotifywait等で /vault/secrets/.env の更新を監視し、プロセスにSIGHUP送出Associate試験では、用語と流れが問われます。Reviewerトークンの役割、ロールのバインド条件、Injector注釈の意味、kv v2のパス指定など基本を確実に。
また、audienceやNamespace/SA名の不一致によるログイン失敗、kv v2での/dataと/metadataの混同は頻出の落とし穴です。
| トピック | 要点 | よくあるミス |
|---|---|---|
| TokenReviewの意味 | VaultがK8s発行JWTを正当性確認 | Reviewerトークンをアプリに渡してしまう |
| ロールの条件付け | SA名とNamespaceを両方指定 | Namespaceワイルドカードの乱用で越権 |
| Injector注釈 | role/secret/templateの3点セット | kv v2でパス階層を誤る |
用語対応のミニ図
CLIでの手動login確認(トラブルシュート)
# Pod内での手動テスト例(デバッグ用途)
SA_JWT=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
vault write auth/kubernetes/login role=app-web jwt="$SA_JWT"
# auth成功後に VAULT_TOKEN を使って読み取り
echo $VAULT_TOKEN | vault kv get -format=json kv/app/configAssociate
問題 1
Kubernetes上のアプリをVaultに接続するにあたり、Vault Agent Injectorを用いたSidecarパターンを採用する。セキュリティと運用の観点から、正しい設計はどれか。
正解: B
ReviewerトークンはVaultがKubernetes APIへTokenReviewするために使用するもので、アプリやSidecarが使うものではありません。SidecarはPodのSA JWTでauth/kubernetesにloginし、Vaultロールはbound_service_account_namesとbound_service_account_namespacesで紐付けます。kv v2は/data/...で参照します。
Reviewer用Service Accountは必ず必要ですか?
はい。VaultはKubernetes APIのTokenReviewでPodのJWTを検証するため、最小権限のReviewer用SA(およびRBAC)が必要です。これをauth/kubernetes/configのtoken_reviewer_jwtとして設定します。
InjectorとInitコンテナはどちらを選ぶべきですか?
起動後のローテーションや自動更新が必要ならInjector(Sidecar)が適しています。起動時にのみ取得すればよい固定設定で、更新はPod再起動で許容できるならInitコンテナも選択肢です。
kv v1とv2の見分け方と注意点は?
マウント時のオプションで判断します。kv v2はバージョニング機能があり、APIパスが/data/と/metadata/に分かれます。Injector注釈やCLIでの取得時は、kv v2ならsecret/data/...のように/dataを含める点に注意してください。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Vault のコア概念を最短距離で理解する:Secret / Auth / Policy / Token
HashiCorp Vault Associate レベルで押さえるべきコア概念(Secret Engine、Auth ...
Vault Operations Professional: 上位資格としての範囲を実務目線で押さえる
HashiCorp Vault Operations Professional(Ops Pro)の出題範囲を、Assoc...
Vaultにおけるパスベースのルーティング: マウントとAPI構造を読み解く
HashiCorp Vaultのパスベースのルーティングを、マウント設計とAPIパスの観点から整理。Associateレ...
Vault Tokens の基礎: 認証の起点となる概念
HashiCorp Vault におけるトークンの役割、種類、ライフサイクル、ポリシー連携、設計パターンをAssocia...
Vault のトークン種類を正しく使い分ける: service / batch 実践
HashiCorp Vault Associate 向けの試験対策と実務運用を両立させた、service トークンと b...