Chuyển đến nội dung chính

レッスン 20: Kubernetes 上の Vault - ヘルム、オペレーター、および CSI

Helm チャート、Vault Secrets Operator (VSO)、Vault CSI Provider、Vault Agent Injector を使用して、Kubernetes に Vault をデプロイします。 VSO、CSI、エージェント インジェクターを比較します。

🔒 D​​evSecOps — レッスン 20 レッスン 20: Kubernetes 上の Vault - Helm、 オペレーターとCSI

HashiCorp Vault の基本から上級まで

パート 5: Vault Agent、プロキシ、および Kubernetes の統合

xdev.asia

1。 Helm

を使用して Kubernetes に Vault をデプロイする

展開モード

モード説明ユースケース
DevSingle pod, in-memory storageDevelopment, testing
StandaloneSingle pod, persistent storageSmall deployments
HAMulti-pod, Integrated Storage (Raft)Production
外部Vault は K8 の外部で実行され、Agent Injector のみを展開します外部 Vault サーバー

Helm Install (HA Mode)

# Add Helm repo
helm repo add hashicorp https://helm.releases.hashicorp.com
helm repo update

# Install Vault HA với Integrated Storage
helm install vault hashicorp/vault \
  --namespace vault \
  --create-namespace \
  --set server.ha.enabled=true \
  --set server.ha.replicas=3 \
  --set server.ha.raft.enabled=true \
  --set server.dataStorage.size=10Gi \
  --set server.resources.requests.memory=256Mi \
  --set server.resources.requests.cpu=250m \
  --set server.resources.limits.memory=512Mi \
  --set server.resources.limits.cpu=500m \
  --set ui.enabled=true \
  --set ui.serviceType=ClusterIP

Custom Values

# values-production.yaml
server:
  ha:
    enabled: true
    replicas: 3
    raft:
      enabled: true
      config: |
        ui = true

        listener "tcp" {
          tls_disable = 0
          address = "[::]:8200"
          cluster_address = "[::]:8201"
          tls_cert_file = "/vault/userconfig/vault-tls/tls.crt"
          tls_key_file  = "/vault/userconfig/vault-tls/tls.key"
        }

        storage "raft" {
          path = "/vault/data"
          retry_join {
            leader_api_addr = "https://vault-0.vault-internal:8200"
            leader_ca_cert_file = "/vault/userconfig/vault-tls/ca.crt"
          }
          retry_join {
            leader_api_addr = "https://vault-1.vault-internal:8200"
            leader_ca_cert_file = "/vault/userconfig/vault-tls/ca.crt"
          }
          retry_join {
            leader_api_addr = "https://vault-2.vault-internal:8200"
            leader_ca_cert_file = "/vault/userconfig/vault-tls/ca.crt"
          }
        }

        service_registration "kubernetes" {}

  dataStorage:
    size: 20Gi
    storageClass: gp3

  extraVolumes:
    - type: secret
      name: vault-tls

  resources:
    requests:
      memory: 512Mi
      cpu: 500m
    limits:
      memory: 1Gi
      cpu: 1000m

  ingress:
    enabled: true
    hosts:
      - host: vault.company.com

ui:
  enabled: true

injector:
  enabled: true
  replicas: 2
# Install với custom values
helm install vault hashicorp/vault \
  --namespace vault \
  --create-namespace \
  -f values-production.yaml

初期化とシール解除

# Init trên vault-0
kubectl exec -n vault vault-0 -- vault operator init \
  -key-shares=5 \
  -key-threshold=3 \
  -format=json > vault-init.json

# Unseal vault-0
kubectl exec -n vault vault-0 -- vault operator unseal <key-1>
kubectl exec -n vault vault-0 -- vault operator unseal <key-2>
kubectl exec -n vault vault-0 -- vault operator unseal <key-3>

# Join vault-1 và vault-2 vào Raft cluster
kubectl exec -n vault vault-1 -- vault operator raft join \
  https://vault-0.vault-internal:8200

kubectl exec -n vault vault-2 -- vault operator raft join \
  https://vault-0.vault-internal:8200

# Unseal vault-1 và vault-2
kubectl exec -n vault vault-1 -- vault operator unseal <key-1>
# ... (repeat for each node)

2. Vault Secrets Operator (VSO)

VSO は公式の Kubernetes オペレーターであり、Vault から Kubernetes Secret にシークレットを自動的に同期します。これは、Kubernetes ネイティブのシークレット管理の 推奨 メソッドです。

Install VSO

helm install vault-secrets-operator hashicorp/vault-secrets-operator \
  --namespace vault-secrets-operator-system \
  --create-namespace

Custom Resources

# 1. VaultConnection — kết nối đến Vault server
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultConnection
metadata:
  name: vault-connection
  namespace: app
spec:
  address: https://vault.company.com:8200
  skipTLSVerify: false
  caCertSecretRef: vault-ca-cert

---
# 2. VaultAuth — xác thực với Vault
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
  name: vault-auth
  namespace: app
spec:
  vaultConnectionRef: vault-connection
  method: kubernetes
  mount: kubernetes
  kubernetes:
    role: webapp
    serviceAccount: webapp-sa

---
# 3. VaultStaticSecret — sync KV secret
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultStaticSecret
metadata:
  name: app-db-secret
  namespace: app
spec:
  vaultAuthRef: vault-auth
  mount: secret
  type: kv-v2
  path: production/db
  refreshAfter: 60s
  destination:
    name: app-db-credentials
    create: true
    labels:
      app: webapp
    transformation:
      excludeRaw: true
      templates:
        connection-string:
          text: "postgresql://{{ .Secrets.username }}:{{ .Secrets.password }}@{{ .Secrets.host }}:5432/{{ .Secrets.database }}"

---
# 4. VaultDynamicSecret — dynamic database credentials
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultDynamicSecret
metadata:
  name: app-dynamic-db
  namespace: app
spec:
  vaultAuthRef: vault-auth
  mount: database
  path: creds/app-role
  renewalPercent: 67
  destination:
    name: app-dynamic-db-credentials
    create: true

---
# 5. VaultPKISecret — auto-issue certificates
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultPKISecret
metadata:
  name: app-tls-cert
  namespace: app
spec:
  vaultAuthRef: vault-auth
  mount: pki
  role: app-cert
  commonName: app.company.com
  altNames:
    - app.internal.company.com
  ttl: 24h
  expiryOffset: 1h
  destination:
    name: app-tls
    create: true

ポッドで使用

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
  namespace: app
spec:
  template:
    spec:
      serviceAccountName: webapp-sa
      containers:
        - name: webapp
          image: myapp:latest
          envFrom:
            - secretRef:
                name: app-db-credentials
          volumeMounts:
            - name: tls
              mountPath: /etc/tls
              readOnly: true
      volumes:
        - name: tls
          secret:
            secretName: app-tls

3. Vault CSI Provider

Vault CSI プロバイダーは、Secrets Store CSI Driver を使用して、Kubernetes シークレットを作成せずに、シークレットを Pod ボリュームに直接マウントします。

# SecretProviderClass
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: vault-db-creds
  namespace: app
spec:
  provider: vault
  parameters:
    vaultAddress: "https://vault.company.com:8200"
    roleName: "webapp"
    objects: |
      - objectName: "db-username"
        secretPath: "secret/data/production/db"
        secretKey: "username"
      - objectName: "db-password"
        secretPath: "secret/data/production/db"
        secretKey: "password"
  # Optionally sync to K8s Secret
  secretObjects:
    - secretName: app-db-synced
      type: Opaque
      data:
        - objectName: db-username
          key: username
        - objectName: db-password
          key: password

---
# Pod sử dụng CSI volume
apiVersion: v1
kind: Pod
metadata:
  name: webapp
spec:
  serviceAccountName: webapp-sa
  containers:
    - name: webapp
      image: myapp:latest
      volumeMounts:
        - name: secrets
          mountPath: /mnt/secrets
          readOnly: true
  volumes:
    - name: secrets
      csi:
        driver: secrets-store.csi.k8s.io
        readOnly: true
        volumeAttributes:
          secretProviderClass: vault-db-creds

4. Vault Agent Injector

Agent Injector は、Kubernetes Mutating Webhook を使用して、アノテーションを使用して Vault Agent サイドカーを Pod に自動的に挿入します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
spec:
  template:
    metadata:
      annotations:
        vault.hashicorp.com/agent-inject: "true"
        vault.hashicorp.com/role: "webapp"
        vault.hashicorp.com/agent-inject-secret-db.txt: "secret/data/production/db"
        vault.hashicorp.com/agent-inject-template-db.txt: |
          {{- with secret "secret/data/production/db" -}}
          DB_HOST={{ .Data.data.host }}
          DB_USER={{ .Data.data.username }}
          DB_PASS={{ .Data.data.password }}
          {{- end }}
    spec:
      serviceAccountName: webapp-sa
      containers:
        - name: webapp
          image: myapp:latest
          # Secrets available at /vault/secrets/db.txt

5。 VSO、CSI、エージェント インジェクターの比較

基準VSOCSIプロバイダーエージェントインジェクター
MechanismOperator + CRDsCSI DriverMutating Webhook
K8s シークレットK8s シークレットの作成オプションの同期No
動的シークレット✅ (VaultDynamicSecret)制限✅(テンプレート)
PKI 証明書✅ (VaultPKIScret)制限✅ (テンプレート)
自動回転✅ (リフレッシュ後)個別構成✅ (サイドカー)
サイドカーが必要NoNoYes
リソース オーバーヘッドLow (一般オペレーター)LowHigh (1 サイドカー/ポッド)
Recommendation✅ RecommendedOK cho simpleLegacy

6. Best Practices cho Kubernetes

  • 新規導入の優先度 VSO — ネイティブ K8s エクスペリエンス、オーバーヘッドの削減

  • ワークロードごとに専用のServiceAccountを使用

  • 本番環境向けに Cloud KMS で Auto-unseal を有効にする

  • Vault ポッド (非ルート、読み取り専用ファイルシステム) の Pod セキュリティ を構成します

  • NetworkPolicy を使用して Vault

  • へのアクセスを制限します
  • 永続ボリューム

  • の代わりに emptyDir (メモリバックアップ) にシークレットをマウントします。

7。概要

  • Helm chart — K8s

  • に統合ストレージを備えた Vault HA を展開する
  • VSO — 推奨、CRD ベース、シークレットを K8s シークレットに自動的に同期

  • CSI Provider — シークレットを Pod ボリュームに直接マウント

  • Agent Injector — legacy, sidecar-based, annotation-driven

次のセクションでは、Vault と実際のアプリケーション (Spring Boot、Node.js、Terraform、Ansible、CI/CD パイプライン) の統合に焦点を当てます。