今回は、Kubernetes External SecretsからExternal Secrets Operatorへ移行する際のポイントを調査しました。
前回触れたExternal Secrets Operator (以降ESO) は、同様の機能を提供する Kubernetes External Secrets (以降KES) から移行先として推奨されているプロダクトです。そのため、すでにKESを使っているプロジェクトではESOへの移行を検討する必要があります。
今回は、KESからESOへ移行する際に注意するべき点や、実際の移行方法について調査・検証しました。なお、KESからESOへの移行は、すでにProduction環境で実施している例がいくつかあるため、そちらも参考にしてください。
※参考:
- Kubernetes External SecretsからExternal Secrets Operatorに移行した話 〜他ツールとの比較・移行戦略・工夫したポイント〜
- マルチテナントKubernetes環境のKubernetes External Secrets が非推奨になるので External Secrets Operatorへ移行した話
- Kubernetes External Secrets が非推奨になるので External Secrets Operator と Secret Storage CSI を比較する
移行時のポイント
今回調査してわかった結論を先に書いておきます。
- KESインストール時にリソース名を変更している場合、ESOのリソース名と重複する可能性があるため、必要に応じてESO側のリソース名を変更する
- KESとESOの扱う
ExternalSecret
はAPIが異なるため、同一クラスターにリソースを作成しても問題ない - KESとESOとで同じ名称のSecretを扱う場合、Secret中の
metadata.ownerReferences
を変更する必要がある。これを避けたい場合はKESとESOで異なるSecret名にする必要がある。
移行方法の概要
KESからESOへの移行を行う際のパターンはいくつかありそうですが、大きくは KESの管理する既存のSecretをESOが管理するよう移行する か、 ESO用の新しい名称のSecretリソースを使う かに分かれそうです。
ESOのドキュメントには、KESからESOへの移行をサポートする kes-to-eso というツールが紹介されています。このツールは、KES・ESOがどちらもインストールされていることを前提に、既存のKES ExternalSecret
の設定をもとに、ESO SecretStore
ExternalSecret
のテンプレートを生成・デプロイします。そのため、このツールによる移行は、KESの管理するSecretをESOが管理するように移行する方法となります。
上記ツールによるAutomatic migrationを実行すると、以下のような動きで移行を実行します。
- クラスター上のKES
ExternalSecrets
リソースの情報からマニフェストファイルを作成し、kes_files
フォルダに保存する - ESO replicasetのPod数をゼロにスケールインする
- KES
ExternalSecrets
ファイルからESOSecretStore
ExternalSecrets
を生成し、eso_files
フォルダに保存する - ESO
SecretStore
ExternalSecrets
リソースをクラスター上に作成する - KES replicasetのPod数をゼロにスケールインする
- KESの管理するSecretリソースからKESのownershipを削除する
- ESO replicasetのPod数を1にスケールアウトする
一方、ESOが管理するSecretは別名で用意し、アプリケーションは新しいSecretを見るように変更する方法もあります。こちらは最後のほうで少し触れます。
今回は kes-to-eso
ツールをもとにKESからESOへの移行方法を検討し、以下のような流れでの作業を実施します。また作業前にいくつか疑問点が生じたので、そちらの解消も行います。
- ESOをKESと同じクラスター上にインストールする
SecretStore
ExternalSecret
をデプロイする- KESの扱う既存SecretからKESのownershipを削除する
- KES関連リソースを削除する
前提条件
前提として、今回は 移行前後で同じ名称のSecretリソースを更新し、既存のPodの設定に変更が入らないようにする こととしました。
また、KES/ESOがそれぞれAWSリソースにアクセスするための権限ですが、KESはあらかじめEKSノードにSecrets Managerへのアクセス権を付与して、ESOはAWSアカウント情報を持つSecretリソースを別に用意する形で付与しました。なお、IRSAを使用した場合については後述します。
検証環境
KESからESOへの移行を試すため、あらかじめKESをインストールしたKubernetesクラスターを用意します。
使用する環境は Amazon EKS
ver 1.22になります。
$ kubectl version Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.0", GitCommit:"c2b5237ccd9c0f1d600d3072634ca66cefdf272f", GitTreeState:"clean", BuildDate:"2021-08-04T18:03:20Z", GoVersion:"go1.16.6", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"22+", GitVersion:"v1.22.16-eks-ffeb93d", GitCommit:"52e500d139bdef42fbc4540c357f0565c7867a81", GitTreeState:"clean", BuildDate:"2022-11-29T18:41:42Z", GoVersion:"go1.16.15", Compiler:"gc", Platform:"linux/amd64"}
また、KES/ESOが扱うAWS Secrets Managerは以下になります。
$ aws secretsmanager get-secret-value --secret-id test-secret { "ARN": "arn:aws:secretsmanager:ap-northeast-1:111111111111:secret:test-secret-Rn6ufG", "Name": "test-secret", "VersionId": "93ed3aed-6048-41da-afec-48da94566aec", "SecretString": "{\"password\":\"1234\"}", "VersionStages": [ "AWSCURRENT" ], "CreatedDate": "2023-01-07T20:54:39.190000+09:00" }
検証を始める前に、あらかじめKESをインストールしておきます。KESのインストールにはHelmパッケージを利用すればよいですが、今回は helm template
から生成したマニフェストファイル群を利用しました。
# templateファイルの生成 $ git clone https://github.com/external-secrets/kubernetes-external-secrets.git $ cd kubernetes-external-secrets $ helm template --output-dir ./testdir ./charts/kubernetes-external-secrets/ # KESのインストール $ kubectl apply -f ./charts/kubernetes-external-secrets/crds $ kubectl apply -f ./testdir/kubernetes-external-secrets/templates/ # インストール後の確認 $ kubectl get crd NAME CREATED AT eniconfigs.crd.k8s.amazonaws.com 2023-01-14T00:26:18Z externalsecrets.kubernetes-client.io 2023-01-14T00:39:36Z securitygrouppolicies.vpcresources.k8s.aws 2023-01-14T00:26:22Z $ kubectl get pods NAME READY STATUS RESTARTS AGE release-name-kubernetes-external-secrets-754cc56b8f-xg2dp 1/1 Running 0 13s
KESインストール後は ExternalSecret
リソースに加え、生成されるSecretを扱うDeploymentも作成しておきます。
# ExternalSecretリソースの作成 $ kubectl apply -f externalsecret-kes.yaml externalsecret.kubernetes-client.io/test-secret created $ kubectl get externalsecret NAME LAST SYNC STATUS AGE test-secret 3s SUCCESS 12m $ kubectl get secret NAME TYPE DATA AGE default-token-6fbtj kubernetes.io/service-account-token 3 44m release-name-kubernetes-external-secrets-token-wf77j kubernetes.io/service-account-token 3 31m test-secret Opaque 1 30m $ kubectl get secret test-secret -oyaml apiVersion: v1 data: password: MTIzNA== # "1234" kind: Secret metadata: creationTimestamp: "2023-01-14T00:40:16Z" name: test-secret namespace: default ownerReferences: - apiVersion: kubernetes-client.io/v1 controller: true kind: ExternalSecret name: test-secret uid: 3821d90f-02d2-454d-8fba-704efeab81f7 resourceVersion: "5639" uid: 7319187e-49fa-4436-9a6b-c42f6d67bea4 type: Opaque # 上記Secretを利用するDeploymentの作成 $ kubectl apply -f kes-to-eso-deploy.yaml deployment.apps/kes-to-eso-deploy created $ kubectl get pods NAME READY STATUS RESTARTS AGE kes-to-eso-deploy-5cfb75cd85-hrksm 1/1 Running 0 13s kes-to-eso-deploy-5cfb75cd85-mxlpl 1/1 Running 0 13s release-name-kubernetes-external-secrets-754cc56b8f-6q2gg 1/1 Running 0 30m $ kubectl exec -it kes-to-eso-deploy-5cfb75cd85-hrksm -- printenv | grep password password=1234
externalsecret-kes.yaml
apiVersion: kubernetes-client.io/v1 kind: ExternalSecret metadata: name: test-secret spec: backendType: secretsManager region: ap-northeast-1 dataFrom: - test-secret
kes-to-eso-deploy.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: kes-to-eso-deploy labels: app: nginx spec: replicas: 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: kes-to-eso-container image: nginx env: - name: password valueFrom: secretKeyRef: name: test-secret key: password
ESO SecretStore
ExternalSecret
マニフェストファイルを作成する
今回使用したマニフェストファイルは以下の通りです。KESとESOの ExternalSecret
は、リソース中で指定するパラメータが異なるため、移行前後で同じSecretの情報を扱うよう修正する必要があります。
※今回は試しませんでしたが、 kes-to-eso
ツールでのManual migrationの手順を参照し、 kestoeso generate
コマンドを使用すると、KESからESOに変換した SecretStore
ExternalSecrets
リソースが生成されるので、そちらを使うのもよさそうです。
secretstore-eso.yaml
apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: name: secretstore-eso spec: provider: aws: service: SecretsManager region: ap-northeast-1 auth: secretRef: accessKeyIDSecretRef: name: awssm-secret key: access-key secretAccessKeySecretRef: name: awssm-secret key: secret-access-key
externalsecret-eso.yaml
apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: test-secret spec: refreshInterval: 5m secretStoreRef: name: secretstore-eso kind: SecretStore target: name: test-secret creationPolicy: Owner data: - secretKey: password remoteRef: key: test-secret property: password
※参考:
ESOをKESと同じクラスター上にインストールする
次にESOのインストールを行います。インストールを行う前に、KESとESOのリソースについて比較をしたうえで、ESOのインストールを行いました。
# templateファイルを生成 $ helm repo add external-secrets https://charts.external-secrets.io $ helm template external-secrets external-secrets/external-secrets --output-dir . # ESOのインストール $ kubectl apply -f ./templates/crds/ $ kubectl apply -f ./templates/ # インストール後の確認 $ kubectl get pods NAME READY STATUS RESTARTS AGE external-secrets-66dbbc7b45-xvmnh 1/1 Running 2 5m59s external-secrets-cert-controller-6c95b96976-8rzvf 1/1 Running 0 5m59s external-secrets-webhook-647478f6dc-wkjq6 1/1 Running 2 (112s ago) 5m59s kes-to-eso-deploy-5cfb75cd85-hrksm 1/1 Running 0 9m27s kes-to-eso-deploy-5cfb75cd85-mxlpl 1/1 Running 0 9m27s release-name-kubernetes-external-secrets-754cc56b8f-6q2gg 1/1 Running 0 39m
疑問点: ESOとKESのリソース名は重複しないか
KESとESOをインストールするにはHelmパッケージが用意されています。 helm template
コマンドでそれぞれ使用するファイル群を生成すると、以下のようになります。
# KES $ tree . . ├── crds │ └── kubernetes-client.io_externalsecrets_crd.yaml ├── deployment.yaml ├── rbac.yaml ├── service.yaml └── serviceaccount.yaml # ESO $ tree . . ├── cert-controller-deployment.yaml ├── cert-controller-rbac.yaml ├── cert-controller-serviceaccount.yaml ├── crds │ ├── acraccesstoken.yaml │ ├── clusterexternalsecret.yaml │ ├── clustersecretstore.yaml │ ├── ecrauthorizationtoken.yaml │ ├── externalsecret.yaml │ ├── fake.yaml │ ├── gcraccesstoken.yaml │ ├── password.yaml │ ├── pushsecret.yaml │ └── secretstore.yaml ├── deployment.yaml ├── rbac.yaml ├── serviceaccount.yaml ├── validatingwebhook.yaml ├── webhook-deployment.yaml ├── webhook-secret.yaml ├── webhook-service.yaml └── webhook-serviceaccount.yaml
上記のようにESOのほうがKESよりも多くのファイルを使用し、作成されるリソースの数もESOのほうが多いです。
また各リソース名を見てみると、KESにはHelmパッケージ利用時に指定できる release-name
という文字列が含まれ、その後ろに kubernetes-external-secret
と続きます。
※例: deployment.yaml
# Source: kubernetes-external-secrets/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: release-name-kubernetes-external-secrets namespace: "default" labels: app.kubernetes.io/name: kubernetes-external-secrets helm.sh/chart: kubernetes-external-secrets-8.5.5 app.kubernetes.io/instance: release-name app.kubernetes.io/managed-by: Helm (以降割愛)
一方でESOのほうは release-name
のような文字列はなく、KESと比較するとリソース名が重複するものはありませんでした。
※KESとESOのリソース名の比較表
リソースの種別 | KESリソース名 | ESOリソース名 |
---|---|---|
Deployment | release-name-kubernetes-external-secrets | external-secrets |
external-secrets-cert-controller | ||
external-secrets-webhook | ||
Service | release-name-kubernetes-external-secrets | external-secrets-webhook |
Service Account | release-name-kubernetes-external-secrets | external-secrets |
external-secrets-cert-controller | ||
external-secrets-webhook | ||
Secret | external-secrets-webhook | |
Cluster Role | release-name-kubernetes-external-secrets | external-secrets-controller |
external-secrets-view | ||
external-secrets-edit | ||
external-secrets-cert-controller | ||
Cluster Role Binding | release-name-kubernetes-external-secrets | external-secrets-controller |
release-name-kubernetes-external-secrets-auth | external-secrets-cert-controller | |
Role | external-secrets-leaderelection | |
Role Binding | external-secrets-leaderelection | |
Validating Webhook Configuration | secretstore-validate | |
externalsecret-validate | ||
CRD | externalsecrets.kubernetes-client.io | externalsecrets.external-secrets.io |
secretstores.external-secrets.io |
このため、KESとESOを同じクラスター上にインストールする際、デフォルトではリソース名の重複などは気にする必要はなさそうです。ただKESのリソース名を修正している場合はこの限りではないため、必要に応じてESOのリソース名は修正が必要となります。
疑問点: ExternalSecret
CRDは共存可能か
KESとESOは ExternalSecret
という名称のCRDを使用します。実際にKESとESOを同じクラスター上にインストールすると、この2つのCRDが共存することは確認できます。
$ kubectl get crd NAME CREATED AT acraccesstokens.generators.external-secrets.io 2023-01-14T01:17:26Z clusterexternalsecrets.external-secrets.io 2023-01-14T01:17:26Z clustersecretstores.external-secrets.io 2023-01-14T01:17:26Z ecrauthorizationtokens.generators.external-secrets.io 2023-01-14T01:17:26Z eniconfigs.crd.k8s.amazonaws.com 2023-01-14T00:26:18Z externalsecrets.external-secrets.io 2023-01-14T01:17:26Z # ESO externalsecrets.kubernetes-client.io 2023-01-14T00:39:36Z # KES fakes.generators.external-secrets.io 2023-01-14T01:17:27Z gcraccesstokens.generators.external-secrets.io 2023-01-14T01:17:27Z passwords.generators.external-secrets.io 2023-01-14T01:17:27Z pushsecrets.external-secrets.io 2023-01-14T01:17:27Z secretstores.external-secrets.io 2023-01-14T01:17:27Z securitygrouppolicies.vpcresources.k8s.aws 2023-01-14T00:26:22Z
それぞれの ExternalSecret
リソースの定義を見ると、APIが異なっていることがわかります。このため、リソースの名称が同じでも、同時にCRDを作成することが可能となります。
なお、それぞれのリソースの状態を確認するコマンドは微妙に異なっているらしく、KES ExternalSecret
リソースを見るには kubectl get externalsecret
、ESO ExternalSecret
を確認するには kubectl get externalsecrets
コマンドを使用します。
SecretStore/ExternalSecretをデプロイする
続いてSecretStore/ExternalSecretをデプロイします。
# AWSリソースにアクセスするための権限を付与 $ kubectl apply -f awssm-secret.yaml secret/awssm-secret created # Secret Storeのデプロイ $ kubectl apply -f secretstore-eso.yaml secretstore.external-secrets.io/secretstore-eso created $ kubectl get secretstore NAME AGE STATUS CAPABILITIES READY secretstore-eso 7s Valid ReadWrite True # External Secretのデプロイ $ kubectl apply -f externalsecret-eso.yaml externalsecret.external-secrets.io/test-secret created $ kubectl get externalsecrets.external-secrets.io NAME STORE REFRESH INTERVAL STATUS READY test-secret secretstore-eso 5m SecretSyncedError False
デプロイ後の状態を見ると、ESO ExternalSecret
で以下のようなエラーが発生しています。これはKESが指定のSecretのownershipをすでに所有しており、ESOのownershipを追加できないために発生しています。
$ kubectl describe externalsecrets.external-secrets.io test-secret Name: test-secret Namespace: default Labels: <none> Annotations: <none> API Version: external-secrets.io/v1beta1 Kind: ExternalSecret Metadata: (一部割愛) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning UpdateFailed 0s (x15 over 83s) external-secrets could not set ExternalSecret controller reference: Object default/test-secret is already owned by another ExternalSecret controller test-secret
既存SecretからKESのownershipを削除する
ESO ExternalSecret
のエラーを解消するため、Secretリソースの metadata.ownerReferences
を修正します。今回はSecretリソース中の metadata.ownerReferences
を削除しました。
$ kubectl edit secret test-secret secret/test-secret edited # 以下のようにmetadata.ownerReferencesの箇所を削除 # Please edit the object below. Lines beginning with a '#' will be ignored, # and an empty file will abort the edit. If an error occurs while saving this file will be # reopened with the relevant failures. # apiVersion: v1 data: password: MTIzNA== kind: Secret metadata: creationTimestamp: "2023-01-14T00:40:16Z" name: test-secret namespace: default resourceVersion: "5639" uid: 7319187e-49fa-4436-9a6b-c42f6d67bea4 type: Opaque
ただし、KESが起動中に上記操作を行っても、KESがSyncすることで再び OwnerReferencesが追加されます。
# 上記操作からしばらく後に状態を確認 $ kubectl get externalsecrets.kubernetes-client.io NAME LAST SYNC STATUS AGE test-secret 1s SUCCESS 51m $ kubectl get externalsecrets.external-secrets.io NAME STORE REFRESH INTERVAL STATUS READY test-secret secretstore-eso 5m SecretSyncedError False # ownershipが追加されている $ kubectl get secret test-secret -oyaml apiVersion: v1 data: password: MTIzNA== kind: Secret metadata: creationTimestamp: "2023-01-14T00:40:16Z" name: test-secret namespace: default ownerReferences: - apiVersion: kubernetes-client.io/v1 controller: true kind: ExternalSecret name: test-secret uid: 3821d90f-02d2-454d-8fba-704efeab81f7 resourceVersion: "13635" uid: 7319187e-49fa-4436-9a6b-c42f6d67bea4 type: Opaque
これを避けるため、事前にKES Deploymentのレプリカ数をゼロにし、KESからSyncを行わないようにします。
$ kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE external-secrets 1/1 1 1 25m external-secrets-cert-controller 1/1 1 1 25m external-secrets-webhook 1/1 1 1 25m kes-to-eso-deploy 2/2 2 2 29m release-name-kubernetes-external-secrets 1/1 1 1 59m # KESのレプリカ数をゼロに $ kubectl scale deploy --replicas=0 release-name-kubernetes-external-secrets deployment.apps/release-name-kubernetes-external-secrets scaled $ kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE external-secrets 1/1 1 1 26m external-secrets-cert-controller 1/1 1 1 26m external-secrets-webhook 1/1 1 1 26m kes-to-eso-deploy 2/2 2 2 30m release-name-kubernetes-external-secrets 0/0 0 0 60m
再びSecretのownershipを修正します。これでしばらくすると、Secretリソースが更新され、ESOがOwnershipを持つようになります。ExternalSecretに発生していたエラーも解消されることが確認できます。
# Secretからmetadata.ownerReferencesを削除 $ kubectl edit secret test-secret secret/test-secret edited # Secretを修正してからしばらく後 $ kubectl get externalsecrets.external-secrets.io NAME STORE REFRESH INTERVAL STATUS READY test-secret secretstore-eso 5m SecretSynced True $ kubectl describe externalsecrets.external-secrets.io test-secret Name: test-secret Namespace: default Labels: <none> Annotations: <none> API Version: external-secrets.io/v1beta1 Kind: ExternalSecret Metadata: (一部割愛) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning UpdateFailed 6m33s (x33 over 17m) external-secrets could not set ExternalSecret controller reference: Object default/test-secret is already owned by another ExternalSecret controller test-secret Normal Updated 65s (x3 over 12m) external-secrets Updated Secret # SecretにはESOのownershipが記載されている $ kubectl get secret test-secret -oyaml apiVersion: v1 data: password: MTIzNA== kind: Secret metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"external-secrets.io/v1beta1","kind":"ExternalSecret","metadata":{"annotations":{},"name":"test-secret","namespace":"default"},"spec":{"data":[{"remoteRef":{"key":"test-secret","property":"password"},"secretKey":"password"}],"refreshInterval":"5m","secretStoreRef":{"kind":"SecretStore","name":"secretstore-eso"},"target":{"creationPolicy":"Owner","name":"test-secret"}}} reconcile.external-secrets.io/data-hash: aeb62059e67d377d0a0ff6afda1a82cf creationTimestamp: "2023-01-14T00:40:16Z" name: test-secret namespace: default ownerReferences: - apiVersion: external-secrets.io/v1beta1 blockOwnerDeletion: true controller: true kind: ExternalSecret name: test-secret uid: 714a3d12-8869-4033-ad55-588e5789eabe resourceVersion: "15809" uid: 7319187e-49fa-4436-9a6b-c42f6d67bea4 type: Opaque
ただし、ここで再度KESのレプリカ数を1に戻すと、今度はSecretリソースのownershipがKESに上書きされてしまうので、注意してください。
疑問点: ESOの creationPolicy: Merge
は利用できるか
ESOは ExternalSecret
リソースのパラメータで、Secretリソース作成時のポリシーを指定できます。このうち Merge
を選択すると、Secretの新規作成は行わず、既存のSecretに値を追加する形での更新が可能となります。
当初、creationPolicy: Merge
を利用すれば、KESとESOとが同じSecretリソースを管理する状態を実現できるのではないかと考えたのですが、ESOがデータを追加するのは異なるデータが存在する場合とのことだったので、残念ながら同じデータを参照している場合は利用できませんでした。
※参考: External Secrets Operator Doc - Lifecycle
creationPolicy: Merge
の検証ログ
# ExternalSecretリソースを以下のように修正 $ cat externalsecret-eso.yaml apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: test-secret spec: refreshInterval: 5m secretStoreRef: name: secretstore-eso kind: SecretStore target: name: test-secret #creationPolicy: Owner creationPolicy: Merge data: - secretKey: password remoteRef: key: test-secret property: password $ kubectl apply -f externalsecret-eso.yaml externalsecret.external-secrets.io/test-secret configured # ExternalSecretのStatusはSyncできたと表示される $ kubectl get externalsecrets.external-secrets.io NAME STORE REFRESH INTERVAL STATUS READY test-secret secretstore-eso 5m SecretSynced True # metadata.ownerReferencesは更新されない $ kubectl get secret test-secret -oyaml apiVersion: v1 data: password: MTIzNA== kind: Secret metadata: creationTimestamp: "2023-01-14T00:40:16Z" name: test-secret namespace: default ownerReferences: - apiVersion: kubernetes-client.io/v1 controller: true kind: ExternalSecret name: test-secret uid: 3821d90f-02d2-454d-8fba-704efeab81f7 resourceVersion: "17653" uid: 7319187e-49fa-4436-9a6b-c42f6d67bea4 type: Opaque
KES関連リソースを削除する
最後にKES関連のリソースを削除します。
$ kubectl delete -f ./testdir/kubernetes-external-secrets/templates/ $ kubectl delete -f ./charts/kubernetes-external-secrets/crds
削除後にESOの状態などを確認しますが、特に問題は発生していないように見えます。
KES削除後の状態確認ログ
$ kubectl get crd NAME CREATED AT acraccesstokens.generators.external-secrets.io 2023-01-14T01:17:26Z clusterexternalsecrets.external-secrets.io 2023-01-14T01:17:26Z clustersecretstores.external-secrets.io 2023-01-14T01:17:26Z ecrauthorizationtokens.generators.external-secrets.io 2023-01-14T01:17:26Z eniconfigs.crd.k8s.amazonaws.com 2023-01-14T00:26:18Z externalsecrets.external-secrets.io 2023-01-14T01:17:26Z fakes.generators.external-secrets.io 2023-01-14T01:17:27Z gcraccesstokens.generators.external-secrets.io 2023-01-14T01:17:27Z passwords.generators.external-secrets.io 2023-01-14T01:17:27Z pushsecrets.external-secrets.io 2023-01-14T01:17:27Z secretstores.external-secrets.io 2023-01-14T01:17:27Z securitygrouppolicies.vpcresources.k8s.aws 2023-01-14T00:26:22Z $ kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE external-secrets 1/1 1 1 53m external-secrets-cert-controller 1/1 1 1 53m external-secrets-webhook 1/1 1 1 53m kes-to-eso-deploy 2/2 2 2 56m $ kubectl get pods NAME READY STATUS RESTARTS AGE external-secrets-66dbbc7b45-xvmnh 1/1 Running 2 53m external-secrets-cert-controller-6c95b96976-8rzvf 1/1 Running 0 53m external-secrets-webhook-647478f6dc-wkjq6 1/1 Running 2 (49m ago) 53m kes-to-eso-deploy-5cfb75cd85-hrksm 1/1 Running 0 57m kes-to-eso-deploy-5cfb75cd85-mxlpl 1/1 Running 0 57m $ kubectl get externalsecret Error from server (NotFound): Unable to list "kubernetes-client.io/v1, Resource=externalsecrets": the server could not find the requested resource (get externalsecrets.kubernetes-client.io) $ kubectl get externalsecrets NAME STORE REFRESH INTERVAL STATUS READY externalsecret.external-secrets.io/test-secret secretstore-eso 5m SecretSynced True NAME AGE STATUS CAPABILITIES READY secretstore.external-secrets.io/secretstore-eso 42m Valid ReadWrite True $ kubectl get secret NAME TYPE DATA AGE awssm-secret Opaque 2 45m default-token-6fbtj kubernetes.io/service-account-token 3 104m external-secrets-cert-controller-token-nlt7d kubernetes.io/service-account-token 3 57m external-secrets-token-nltx6 kubernetes.io/service-account-token 3 57m external-secrets-webhook Opaque 4 57m external-secrets-webhook-token-kkx8s kubernetes.io/service-account-token 3 57m test-secret Opaque 1 90m $ kubectl get secret test-secret -oyaml apiVersion: v1 data: password: MTIzNA== kind: Secret metadata: annotations: kubectl.kubernetes.io/last-applied-configuration: | {"apiVersion":"external-secrets.io/v1beta1","kind":"ExternalSecret","metadata":{"annotations":{},"name":"test-secret","namespace":"default"},"spec":{"data":[{"remoteRef":{"key":"test-secret","property":"password"},"secretKey":"password"}],"refreshInterval":"5m","secretStoreRef":{"kind":"SecretStore","name":"secretstore-eso"},"target":{"creationPolicy":"Owner","name":"test-secret"}}} reconcile.external-secrets.io/data-hash: aeb62059e67d377d0a0ff6afda1a82cf creationTimestamp: "2023-01-14T00:40:16Z" name: test-secret namespace: default ownerReferences: - apiVersion: external-secrets.io/v1beta1 blockOwnerDeletion: true controller: true kind: ExternalSecret name: test-secret uid: 714a3d12-8869-4033-ad55-588e5789eabe resourceVersion: "20305" uid: 7319187e-49fa-4436-9a6b-c42f6d67bea4 type: Opaque
その他
別名のSecretを使う場合
今回はSecret名を同じと仮定しましたが、そもそもKESとESOで異なる名称のSecretを管理するようにすることも考えられます。
管理するSecret名を変更する場合は、今回発生したownershipの問題は発生せず、KESからESOへの切り替え自体はよりスムーズに実施できるはずです。冒頭に紹介した本番環境での例でも、別名のSecretに切り替える方法が紹介されています。
こちらの場合、ownershipの書き換えをする必要がない代わりに、Secretを利用するリソース側に変更が必要となります。具体的にはDeploymntなどが使用するSecret情報を更新する必要があります。
IRSAを使う場合
今回のAWSアカウントへのアクセス権限付与の方法は、KES・ESOともにセキュアとは言えない方法で行っており、本来はIRSAを使用することが推奨されます。
KES/ESOでIRSAを使用する方法は少し異なります。KESはExternal SecretコントローラーPodにIAM権限を付与したService Accountを紐づける必要があります。一方でESOはコントローラーに付与することもできますが、SecretStore
ごとにService Accountを指定することもできます。
このため、KESで使用していたのと同じService Accountを SecretStore
に指定したり、新しいService Accountを用意することもできます。