ExternalSecretsでGKEのsecretをSecretManagerで管理してみた

4 min read読了の目安(約3700字

GKEでsecretを使いたいときに,その管理方法に悩む方は多いかと思います.
ここではExternalSecretsを使用したsecretの管理方法についてご紹介いたします.

ExternalSecretsとは

ExternalSecretsはkubernetes clusterにおけるsecretを外部で管理できるソフトウェアツールです.
具体的には,cluster上にExternalSecretsのコントローラを設置することで,外部プロバイダからsecretデータを取得しcluster上にupsertします.
これにより,cluster上のpodは自由にsecretにアクセスすることができます.

ExternalSecretsを使うメリット

secretを外部で管理することでセキュリティ面を考慮しつつバージョニングを行うことができます.
GitHubで管理してしまうと,secretが漏洩してしまう可能性があり,こちらは避けたいところです.
また,cloudサービス上で管理することでconsoleから自由に追加や消去を行うことができるので,利便性も良いのではないかと考えられます.

実際に使ってみる

筆者は,実際にGKEのcluster上にExternalSecretsのコントローラを設置し,同じくGCPサービスであるSecretManagerで管理するsecretをupsertする方法を試してみました.
以下に必要な設定を記載します.

1.Workload Identityの有効化

cluster内のnodeからSecretManagerにアクセスする必要があるため,kubernetesサービスアカウントをGCPサービスアカウントと紐付ける必要があります.
この際に必要になるのが「Workload Identity」という機能です.
clusterのWorkload Identityを有効化するために以下のコマンドを使用します.

gcloud container clusters update $CLUSTER_NAME --workload-pool $PROJECT_NAME.svc.id.goog

また,node poolに対しても修正が必要になります.

gcloud container node-pools update $NODEPOOL_NAME --cluster=$CLUSTER_NAME --workload-metadata=GKE_METADATA

terraformを使用している場合

GKEのresourceにおいて,workload_identity_config.idnetity_namespaceおよびnode_pool.node_config.workload_metadata_configを加えることで有効化することができます.

resource "google_container_cluster" "CLUSTER_NAME" {  
  workload_identity_config {
    identity_namespace = "<PROJECT_NAME>.svc.id.goog"
  }

  node_pool {
    node_config {
      workload_metadata_config {
        node_metadata = "GKE_METADATA_SERVER"
      }
    }
  }
}

2.manifestファイル生成

kubernetes-external-secretsをcloneします.
cloneしたリポジトリ内に移動し,helmを使用してkubernetesのmanifestファイルのtemplateを生成します.

helm template --output-dir <OUTPUT PATH> ./charts/kubernetes-external-secrets/

3.templateの修正

templateのmetadata等を修正していきます.
主にRELEASE-NAMEとなっている項目を修正します.
例えばdeployment.yamlmetadata.nameRELEASE-NAME-kubernetes-external-secretsとなっているので,RELEASE-NAMEの部分を修正します.
本記事ではmy-release-kubernetes-external-secretsとしますが,自由で問題ありません.
rbac.yamlserviceaccount.yamlservice.yamlも同様に修正します.

4.GSAとKSAの紐付け

GCPサービスアカウントとkubernetesサービスアカウントの紐付けを行います.
この際,1で説明したWorkload Identityの有効化が必要になりますのでご注意ください.
まず,2で生成したserviceaccount.yamlにおいてmetadata.annotationsの項目を追加します.

metadata:
  annotations:
    iam.gke.io/gcp-service-account: <SERVICEACCOUNT_NAME>@<PROJECT_NAME>.iam.gserviceaccount.com

このときのSERVICEACCOUNT_NAMEは紐付けしたいGCPサービスアカウントの名前です.
このGCPサービスアカウントのロールにはsecretmanager.secretAccessorが必要になります.

次に,serviceaccount.yamlをGKEへapplyします.
また,bindingを完了するためにgcloudで以下のコマンドを実行します.

gcloud iam service-accounts add-iam-policy-binding \
	--role roles/iam.workloadIdentityUser \
	--member "serviceAccount:<PROJECT_NAME>.svc.id.goog[default/my-release-kubernetes-external-secrets]" \
	<SERVICEACCOUNT_NAME>@<PROJECT_NAME>.iam.gserviceaccount.com

5.デプロイ

設定が終わったとこで他のmanifestファイルもapplyします.
これでExternalSecretsの設置は完了なので,実際にsecretをデプロイしてみます.
例えば以下のようなmanifestファイルを作成します.

apiVersion: kubernetes-client.io/v1
kind: ExternalSecret
metadata:
  name: example-secret
spec:
  backendType: gcpSecretsManager
  region: REGION-NAME
  projectId: PROJECT-NAME
  data:
    - key: example-secret
      name: example-secret

これにより,SecretManagerにおけるexample-secretがGKEのsecretとしてupsertされます.

終わりに

最後まで読んで頂きありがとうございました.
実装から時間が空いて記事を書いてしまったため,もし何か違うところがあれば教えていただけるとありがたいです.
また,READMEにAWS SecretManager等を使用する方法も書かれているので,ぜひ参考にしてみてください.

参考