[Kubernetes/Vault]PodへのSecret注入をkv-v1でもやってみた
はじめに
以下のWebセミナーに参加してKubernetesとValutの連携について方法を色々試しているところ。
https://www.youtube.com/watch?v=b2iiZ16eI7A
まずはVaultに登録した認証情報(ユーザー/パスワード情報)をKubernetesのPodに注入する、といったチュートリアルを実施してみた。その中で自分が疑問に思ったことの検証メモ。
※Vaultは触り始めたばかりなので、用語などよくわかってないですが
pathの間に"/data"が入るのはなぜ
チュートリアルを実施するうえで少し疑問だったのが、
vault kv put internal/database/config username="db-readonly-username" password="db-secret-password"
上記ではinternal/database/config
にユーザー名/パスワードなどの情報を登録していたのに、
vault policy write internal-app - <<EOF
path "internal/data/database/config" {
capabilities = ["read"]
}
EOF
ポリシーの作成や、
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/role: 'internal-app'
vault.hashicorp.com/agent-inject-secret-database-config.txt: 'internal/data/database/config'
Podのyaml定義に記載するアノテーションに記載されているpathがinternal/data/database/config
となっている。さて/data
はどこから出てきたのか?
kvのv1とv2の違い
どうやら、この/data
はkvのversion1とversion2でのAPI利用方法の違いが影響しているみたい。
チュートリアルではversion2のKVで実施している。
version1では/secret/:path
だったのが、version2では/secret/data/:path?version=:version-number
に変更になっている。
検証①:v1でチュートリアルをやってみる
実際の動作を確認するために、以下のチュートリアルをkv-v1で実施してみる。基本的な流れは同じだが一部のコマンドを修正して実施する。
https://learn.hashicorp.com/tutorials/vault/kubernetes-sidecar
internal
というpathでsecretを有効化する箇所は以下のコマンドに置き換える。
/ $ vault secrets enable -path=internal kv-v1
Success! Enabled the kv-v1 secrets engine at: internal/
念のため、以下コマンドでinternal/
がversion1で有効化されていることを確認しておく。
/ $ vault secrets list -detailed | grep internal
internal/ kv kv_7122e2b5 system system false replicated false false
map[version:1] n/a da1cd7bd-bd8c-97a5-97b8-07f8500abf2b
policyは、/data
が含まれていないpathに置き換えて登録する。
/ $ vault policy write internal-app - <<EOF
> path "internal/database/config" {
> capabilities = ["read"]
> }
> EOF
Success! Uploaded policy: internal-app
Kubernetes側としては、yamlファイルのannotaionのうち、vault.hashicorp.com/agent-inject-secret-database-config.txt
の値も同様に修正しておく。
チュートリアルの手順ではgit上から取得した検証用のyamlファイルを利用しているが、今回は以下の定義ファイルで実施してみる。
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: alpine-test
name: alpine-test
spec:
replicas: 1
selector:
matchLabels:
app: alpine-test
template:
metadata:
labels:
app: alpine-test
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/role: 'internal-app'
vault.hashicorp.com/agent-inject-secret-database-config.txt: 'internal/database/config'
spec:
containers:
- image: alpine
name: alpine
command:
- "sleep"
- "3600"
serviceAccountName: internal-app
kubectl apply
でPodを起動させてから、kubectl exec
コマンドで/vault/secrets/database-config.txt
の中身を確認してみる。
$ kubectl get pod alpine-test-59b7456c6d-vsbqt
NAME READY STATUS RESTARTS AGE
alpine-test-59b7456c6d-vsbqt 2/2 Running 0 19s
$
$ kubectl exec alpine-test-59b7456c6d-vsbqt -c alpine -- cat /vault/secrets/database-config.txt
password: db-secret-password
username: db-readonly-username
internal/database/config
に登録されているユーザー/パスワードが出力されていることが確認できた。
検証②:v1のまま、pathに"/date"を追加してみる
kv-v1の状態のまま、pathに/data
を付ける形にするとどうなるか試してみる。
vault-0のコンソールにログインした状態で以下コマンドを実施してinternal-app
をアップデートする
vault policy write internal-app - <<EOF
path "internal/data/database/config" {
capabilities = ["read"]
}
EOF
またyamlファイルも修正する。以下コマンドでannotaitonを更新する。
kubectl patch deployment alpine-test -p metadata":{"annotations":{"vault.hashicorp.com/agent-inject-secret-database-config.txt": "internal/data/database/config"}}}}}'
annotationを更新すると新しくPodが作成されるが、新規作成されたPodの状態を確認してもInitが完了せず、Runステータスにはならない。
$ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
alpine-test-59b7456c6d-vsbqt 2/2 Running 0 3m24s
alpine-test-6554846995-tpb9v 0/2 Init:0/1 0 5s
kubectl logs
コマンドでInitコンテナのログを確認してみると、internal/data/database/config
というpathのシークレットは無いといったメッセージが出力されている。
どうやら、version1では/data
はpathの一部として認識されているみたい。
$ kubectl logs alpine-test-6554846995-tpb9v -c vault-agent-init
==> Vault agent started! Log data will stream in below:
==> Vault agent configuration:
Cgo: disabled
Log Level: info
Version: Vault v1.9.2
Version Sha: f4c6d873e2767c0d6853b5d9ffc77b0d297bfbdf
2022-03-21T05:38:03.105Z [INFO] sink.file: creating file sink
2022-03-21T05:38:03.105Z [INFO] sink.file: file sink configured: path=/home/vault/.vault-token mode=-rw-r-----
2022-03-21T05:38:03.105Z [INFO] template.server: starting template server
2022-03-21T05:38:03.105Z [INFO] auth.handler: starting auth handler
2022-03-21T05:38:03.105Z [INFO] sink.server: starting sink server
2022-03-21T05:38:03.105Z [INFO] (runner) creating new runner (dry: false, once: false)
2022-03-21T05:38:03.105Z [INFO] auth.handler: authenticating
2022-03-21T05:38:03.106Z [INFO] (runner) creating watcher
2022-03-21T05:38:03.118Z [INFO] auth.handler: authentication successful, sending token to sinks
2022-03-21T05:38:03.118Z [INFO] auth.handler: starting renewal process
2022-03-21T05:38:03.118Z [INFO] template.server: template server received new token
2022-03-21T05:38:03.118Z [INFO] (runner) stopping
2022-03-21T05:38:03.118Z [INFO] (runner) creating new runner (dry: false, once: false)
2022-03-21T05:38:03.118Z [INFO] sink.file: token written: path=/home/vault/.vault-token
2022-03-21T05:38:03.119Z [INFO] sink.server: sink server stopped
2022-03-21T05:38:03.119Z [INFO] sinks finished, exiting
2022-03-21T05:38:03.119Z [INFO] (runner) creating watcher
2022-03-21T05:38:03.119Z [INFO] (runner) starting
2022-03-21T05:38:03.121Z [INFO] auth.handler: renewed auth token
2022-03-21T05:38:03.124Z [WARN] (view) vault.read(internal/data/database/config): no secret exists at internal/data/database/config (retry at
tempt 1 after "250ms")
2022-03-21T05:38:03.377Z [WARN] (view) vault.read(internal/data/database/config): no secret exists at internal/data/database/config (retry at
tempt 2 after "500ms")
2022-03-21T05:38:03.879Z [WARN] (view) vault.read(internal/data/database/config): no secret exists at internal/data/database/config (retry at
tempt 3 after "1s")
2022-03-21T05:38:04.881Z [WARN] (view) vault.read(internal/data/database/config): no secret exists at internal/data/database/config (retry at
tempt 4 after "2s")
2022-03-21T05:38:06.884Z [WARN] (view) vault.read(internal/data/database/config): no secret exists at internal/data/database/config (retry at
tempt 5 after "4s")
2022-03-21T05:38:10.888Z [WARN] (view) vault.read(internal/data/database/config): no secret exists at internal/data/database/config (retry at
tempt 6 after "8s")
2022-03-21T05:38:18.892Z [WARN] (view) vault.read(internal/data/database/config): no secret exists at internal/data/database/config (retry at
tempt 7 after "16s")
2022-03-21T05:38:34.895Z [WARN] (view) vault.read(internal/data/database/config): no secret exists at internal/data/database/config (retry at
tempt 8 after "32s")
2022-03-21T05:39:06.897Z [WARN] (view) vault.read(internal/data/database/config): no secret exists at internal/data/database/config (retry at
tempt 9 after "1m0s")
検証③:kvをバージョンアップしてみる
これまでkv-v1だったものをkv-v2にアップデートしてみる。
vault-0コンテナへログインして、以下コマンドでkv-v2へアップデートする。
/ $ vault kv enable-versioning internal
Success! Tuned the secrets engine at: internal/
internal/
がversion2になっていることを確認しておく。
/ $ vault secrets list -detailed | grep internal
internal/ kv kv_7122e2b5 system system false replicated false false
map[version:2] n/a
先ほどのPodが"Running"ステータスになっており、internal/database/config
に登録されているユーザー/パスワードが出力されていることが確認できた。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
alpine-test-6554846995-tpb9v 2/2 Running 0 2m58s
$
$ kubectl exec alpine-test-6554846995-tpb9v -c alpine -- cat /vault/secrets/database-config.txt
data: map[password:db-secret-password username:db-readonly-username]
metadata: map[created_time:2022-03-21T05:39:57.3716551Z custom_metadata:<nil> deletion_time: destroyed:false version:1]
v2だとバージョン管理が可能
kv-v1とkv-v2の違いについては、kv-v2ではバージョン管理されており過去バージョンの値も参照可能らしい。
確かにAPIの説明でも末尾に/secret/data/:path?version=:version-number
とバージョンが指定できる。
これも動作検証してみる。
まずはinternal/database/config
に登録されている情報を上書きする。vault-0コンテナへログインして以下のようにusername/passwordを更新する。
$ kubectl exec -n vault -it vault-0 -- /bin/sh
/ $ vault kv put internal/database/config username="username!!" password="password!!"
Key Value
--- -----
created_time 2022-03-21T05:42:27.5826724Z
custom_metadata <nil>
deletion_time n/a
destroyed false
version 2
/ $ exit
再度、ポッドを削除、再起動させる。
/vault/secrets/database-config.txt
の中身に、先ほどアップデートした内容が反映されていることが確認できた。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
alpine-test-6554846995-lnf2r 2/2 Running 0 52s
$
$ kubectl exec alpine-test-6554846995-lnf2r -c alpine -- cat /vault/secrets/database-config.txt
data: map[password:password!! username:username!!]
metadata: map[created_time:2022-03-21T05:42:27.5826724Z custom_metadata:<nil> deletion_time: destroyed:false version:2]
では、annotaionのpathの末尾に?version=1
を追記して、修正前のinternal/database/config
の内容を参照するようにしてみる。
kubectl patch deployment alpine-test -p '{"spec": {"template":{"metadata":{"annotations":{"vault.hashicorp.com/agent-inject-secret-database-config.txt": "internal/data/database/config?version=1"}}}}}'
Podが自動的に再起動される。/vault/secrets/database-config.txt
の中身が修正前のinternal/database/config
の内容となっていることが確認できた。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
alpine-test-7f65559cb-srrwf 2/2 Running 0 42s
$
$ kubectl exec alpine-test-7f65559cb-srrwf -c alpine -- cat /vault/secrets/database-config.txt
data: map[password:db-secret-password username:db-readonly-username]
metadata: map[created_time:2022-03-21T05:39:57.3716551Z custom_metadata:<nil> deletion_time: destroyed:false version:1]
Author And Source
この問題について([Kubernetes/Vault]PodへのSecret注入をkv-v1でもやってみた), 我々は、より多くの情報をここで見つけました https://qiita.com/comwing65/items/13fe7d9be66667021ba0著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .