VaultとExternal Secrets Operatorを連携する
External Secrets Operator
は
HashiCorp Vault
など
様々なシークレット管理システム上のシークレットから
Kubernetesの
Secret
を作成してくれるソフトウェアです。
Gitにsecretをアップしたくない時に使えるものですね。
前回
手元のラズパイk8sにvault serverをインストールしたので、
それとExternal Secrets Operatorと連携したいと思います。
環境
確認環境はこちら
ubuntu@k8s1:~$ k get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8s1 Ready control-plane,etcd,master 326d v1.28.10+rke2r1 192.168.0.51 <none> Ubuntu 24.04 LTS 6.8.0-1028-raspi containerd://1.7.11-k3s2
k8s2 Ready worker 203d v1.28.10+rke2r1 192.168.0.52 <none> Ubuntu 24.04.1 LTS 6.8.0-1013-raspi containerd://1.7.11-k3s2
k8s3 Ready worker 326d v1.28.10+rke2r1 192.168.0.53 <none> Ubuntu 24.04 LTS 6.8.0-1013-raspi containerd://1.7.11-k3s2
vaultとExternal Secrets Operatorは同じクラスタで起動しますが、
vaultはingressで外部公開しているのでそちらを通してアクセスします。
ubuntu@k8s1:~$ k get pod,ingress -n vault
NAME READY STATUS RESTARTS AGE
pod/vault-0 1/1 Running 0 5d11h
pod/vault-1 1/1 Running 0 5d11h
pod/vault-agent-injector-6665f9cbc6-8k8sh 1/1 Running 0 5d11h
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/vault <none> vault.tsuchinokometal.com 192.168.0.52,192.168.0.53 80 5d11h
helmでExternal Secrets Operatorをインストール
こちら を参考にExternal Secrets Operatorをインストールします。
ubuntu@k8s1:~$ helm repo add external-secrets https://charts.external-secrets.io
ubuntu@k8s1:~$ helm repo update
ubuntu@k8s1:~$ helm install external-secrets external-secrets/external-secrets -n external-secrets --create-namespace
NAME: external-secrets
LAST DEPLOYED: Thu Jun 5 20:54:48 2025
NAMESPACE: external-secrets
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
external-secrets has been deployed successfully in namespace external-secrets!
In order to begin using ExternalSecrets, you will need to set up a SecretStore
or ClusterSecretStore resource (for example, by creating a 'vault' SecretStore).
More information on the different types of SecretStores and how to configure them
can be found in our Github: https://github.com/external-secrets/external-secrets
ubuntu@k8s1:~$ helm list -n external-secrets
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
external-secrets external-secrets 1 2025-06-05 20:54:48.13443726 +0900 JST deployed external-secrets-0.17.0 v0.17.0
ubuntu@k8s1:~$ k get pod -n external-secrets
NAME READY STATUS RESTARTS AGE
external-secrets-75ccf7ffd-xh9lw 1/1 Running 0 86s
external-secrets-cert-controller-6cdbf89fff-l7dbr 1/1 Running 0 86s
external-secrets-webhook-db4d9b557-rp9rf 1/1 Running 0 86s
特に設定を変更することなく問題なく起動しました。
vaultと連携
vaultとの連携は こちら を参考に進めます。
まずはvaultと認証するためのリソースを作成します。
認証方法は
こちら
で試したkubernetes認証を流用します。
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
name: vault-backend
spec:
provider:
vault:
server: "http://vault.tsuchinokometal.com"
path: "secret"
version: "v2"
auth:
kubernetes:
mountPath: "kubernetes"
role: "my-role"
serviceAccountRef:
name: "my-sa"
secretRef:
name: "my-app"
key: "password"
vault側の設定は以下の通りですので、そちらに合わせてSecretStoreを作成しました。
ubuntu@k8s1:~$ vault kv get secret/my-app
=== Secret Path ===
secret/data/my-app
======= Metadata =======
Key Value
--- -----
created_time 2025-05-31T09:14:45.104709193Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 1
====== Data ======
Key Value
--- -----
password supersecret!
ubuntu@k8s1:~$ vault read auth/kubernetes/role/my-role
Key Value
--- -----
alias_name_source serviceaccount_uid
bound_service_account_names [my-sa]
bound_service_account_namespace_selector n/a
bound_service_account_namespaces [default]
policies [my-policy]
token_bound_cidrs []
token_explicit_max_ttl 0s
token_max_ttl 0s
token_no_default_policy false
token_num_uses 0
token_period 0s
token_policies [my-policy]
token_ttl 20m
token_type default
ttl 20m
作成すると以下の状態になりました。
ubuntu@k8s1:~$ k get SecretStore
NAME AGE STATUS CAPABILITIES READY
vault-backend 23s Valid ReadWrite True
次にこのSecretStoreを使ってkubernetes secretを作成します。
マニフェストは以下のように作成してみました。
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: vault-example
spec:
refreshInterval: "15s"
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: my-secret
data:
- secretKey: password
remoteRef:
key: my-app
property: password
target.nameでsecretの名前が指定できるようですね。
secretが作成できたら確認してみます。
ubuntu@k8s1:~$ k get secret my-secret -o jsonpath={.data.password} | base64 -d
supersecret!
連携できたようですね!
シークレットの更新
新規追加した時と同じコマンドで上書きしちゃえばいいようです。
ubuntu@k8s1:~$ vault kv put secret/my-app password=ultrasecret!
=== Secret Path ===
secret/data/my-app
======= Metadata =======
Key Value
--- -----
created_time 2025-06-07T03:41:41.705997865Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 2
ubuntu@k8s1:~$ vault kv get secret/my-app
=== Secret Path ===
secret/data/my-app
======= Metadata =======
Key Value
--- -----
created_time 2025-06-07T03:41:41.705997865Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 2
====== Data ======
Key Value
--- -----
password ultrasecret!
自動でsecretが更新されました。
ubuntu@k8s1:~$ k get secret my-secret -o jsonpath={.data.password} | base64 -d
ultrasecret!
シークレットのロールバック
ロールバックコマンド で更新したシークレットを復元できます。
ubuntu@k8s1:~$ vault kv rollback -version=1 secret/my-app
Key Value
--- -----
created_time 2025-06-07T04:03:59.520397652Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 3
ubuntu@k8s1:~$ vault kv get secret/my-app
=== Secret Path ===
secret/data/my-app
======= Metadata =======
Key Value
--- -----
created_time 2025-06-07T04:03:59.520397652Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 3
====== Data ======
Key Value
--- -----
password supersecret!
バージョンが加算されて復元されるようですね。
問題なくsecret側もロールバックしています。
ubuntu@k8s1:~$ k get secret my-secret -o jsonpath={.data.password} | base64 -d
supersecret!