Flux CD Flux CD

SOPS と age で Git のシークレットを管理する

commit する前に Kubernetes の Secret を暗号化し、クラスター内で Flux に復号させます。

12 min learn.level.中級

GitOps は、クラスターの設定を Git に置き、それには Secret も含まれます。プレーンな Kubernetes の Secret を commit すると、Secret のデータは base64 でエンコードされているだけなので、リポジトリを読める人全員にその値が露出します。Flux の kustomize-controller は、Mozilla SOPS で暗号化されたファイルを復号できるため、暗号化された Secret を commit して、システム全体を Git に保つことができます。このガイドでは、最もシンプルな選択肢である age の鍵を使います。

ツールをインストールして鍵を作成する

age と sops をインストールし(たとえば brew install age sops)、鍵のペアを生成します。

age-keygen -o age.agekey

出力ファイルには秘密鍵が入り、コマンドは公開鍵(age1 で始まります)を出力します。秘密鍵を Git に入れないでください。安全な場所にバックアップしてください。失うと、シークレットを復号できなくなります。Flux 2.9 は、ポリシーが必要とする場合のために、age のポスト量子暗号のサポートも追加しています。

クラスターに秘密鍵を渡す

秘密鍵を、それを使う Flux の Kustomization と同じ namespace の Secret として保存します。

kubectl create secret generic sops-age \
  --namespace=flux-system \
  --from-file=age.agekey=/dev/stdin < age.agekey

Secret の中のキーは、.agekey で終わる必要があります。ローカルの age.agekey ファイルは、別の場所に安全に保存した後で、削除するか、パスワードマネージャーに移動します。

リポジトリで SOPS を設定する

リポジトリのルートに .sops.yaml を作成して、全員が同じ方法で暗号化するようにします。キーを、自分の公開鍵に置き換えます。

creation_rules:
  - path_regex: .*\.yaml
    encrypted_regex: ^(data|stringData)$
    age: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

encrypted_regex は data と stringData のフィールドだけを暗号化するため、マニフェストの他の部分は、レビューや Flux による処理のために、読める状態のままになります。複数の age の受信者(カンマ区切り)を列挙して、チームメイトとクラスターの鍵が、すべて復号できるようにできます。

Secret を暗号化する

Secret のマニフェストをローカルで書きます。たとえば apps/webapp/db-credentials.yaml です。

apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
  namespace: webapp
stringData:
  username: webapp
  password: s3cr3t-value

その場で暗号化します。

sops --encrypt --in-place apps/webapp/db-credentials.yaml

ファイルを開くと、username と password の値は暗号文になり、メタデータを含む sops: ブロックが追加されています。commit しても安全です。後で編集するには、sops apps/webapp/db-credentials.yaml を実行します。エディターで復号され、保存時に再暗号化されます。commit しようとしているものを確認するには、値がもう読めないことを確かめてください。

復号するよう Flux に伝える

フォルダーを適用する Flux の Kustomization に、decryption ブロックを追加します。

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: webapp
  namespace: flux-system
spec:
  interval: 10m
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./apps/webapp
  prune: true
  decryption:
    provider: sops
    secretRef:
      name: sops-age

commit して push します。調整の間に、kustomize-controller はメモリ内でファイルを復号し、通常の Secret をクラスターに適用します。確認します。

flux reconcile kustomization webapp --with-source
kubectl get secret db-credentials -n webapp

トラブルシューティングと良い習慣

Kustomization が復号エラーを報告する場合は、sops-age の Secret が Kustomization と同じ namespace に存在すること、そのキー名が .agekey で終わること、ファイルが対応する公開鍵で暗号化されたことを確認してください。kubectl describe kustomization webapp -n flux-system がエラーを表示します。

  • 環境ごとに異なる鍵を使い、dev の鍵が本番のシークレットを読めないようにします。
  • 鍵をローテーションするには、新しい受信者を追加し、再暗号化し(sops updatekeys)、その後で古いものを削除します。
  • クラウドの KMS キー(AWS KMS、Azure Key Vault、Google Cloud KMS)や、HashiCorp Vault、OpenBao も機能し、鍵ファイルの配布を避けられます。workload identity で設定し、プラットフォームが認証情報を提供する場合は secretRef を省略します。
  • シークレットを Git の外に完全に置きたい場合は、External Secrets Operator を使って、シークレットを vault から同期し、Flux には ExternalSecret オブジェクトだけを管理させます。

人気のガイド