OCI KubernetesとOCI VaultでExternal Secrets Operatorを使用 (2022/06/01)
OCI KubernetesとOCI VaultでExternal Secrets Operatorを使用 (2022/06/01)
投稿者:Ali Mukadam
最近、お客様からExternal Secrets Operator (ESO)プロジェクトを紹介され、すでにOCI Vaultと統合されていることを知り、嬉しく思いました。この記事では、ESOを試してみて、OKEでどのように使用できるかを見ていきます。
OKEへのExternal Secrets Operatorのインストール
まず、OCIコンソールのクイック作成か、https://github.com/oracle-terraform-modules/terraform-oci-oke を使って、OKEクラスタを作成します。これでCloud Shellやterraform-oci-okeモジュールのoperator hostを使って、kubectlやhelmコマンドを実行できるようになります。
helm チャートで ESO をインストールしてみましょう。
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets \
external-secrets/external-secrets \
-n external-secrets \
--create-namespace
OCI Vaultで使用するためのESOの設定
instance_principalを使用しない場合、秘密鍵とFingerprintを保持するためにyamlファイルにKubernetes secretを作成します。
apiVersion: v1
kind: Secret
metadata:
name: pk-fp
labels:
type: oracle
type: Opaque
stringData:
privateKey: |
-----BEGIN RSA PRIVATE KEY-----
abcdefg1234567890/+-
-----END RSA PRIVATE KEY-----
fingerprint: ab:cd:ef:gh:12:34
シークレットの作成
kubectl create -f pk-fp.yaml
これでSecretStoreを作成することができます。
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: alivault
spec:
provider:
oracle:
vault: # The vault OCID
region: # The vault region
auth:
user: # A user OCID
tenancy: # A user's tenancy
secretRef:
privatekey:
name: pk-fp
key: privateKey
fingerprint:
name: pk-fp
key: fingerprint
N.B. instance_principalsを使う場合は、authから最後までを削除してください。また、動的グループを作成し、ワーカー・ノードを追加する必要があります。最後に、OCI Vaultで作成するキーを動的グループに使用させるためのポリシーも作成する必要があります。
kubectl create -f oci-secret-store.yaml
ExternalSecret の作成
では、ESO を使って ExternalSecret を作成してみましょう。
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: oci-secret
spec:
refreshInterval: 0.03m
secretStoreRef:
kind: SecretStore
name: alivault # Must match SecretStore on the cluster
target:
name: my-oke-secret # Name for the secret on the cluster
creationPolicy: Owner
data:
- secretKey: key
remoteRef:
key: my-eso-secret
my-eso-secretは、Vault内のOCIシークレットの名前です。
この場合、単にプレーンな内容("aSecretInSiV")を持つだけなので、上記のようにデータを使用すれば、ExternalSecretを作成することができます。
kubectl create -f ext-secret.yaml
ExternalSecretの入手
kubectl get es
NAME STORE REFRESH INTERVAL STATUS
oci-secret alivault 0.03m SecretSynced
シークレットが同期されたことが確認できます。このネームスペースのシークレットを一覧にしてみましょう。
kubectl get secrets
NAME TYPE DATA AGE
default-token-mnpsm kubernetes.io/service-account-token 3 41m
my-oke-secret Opaque 1 108s
pk-fp Opaque 2 10m
my-oke-secretが作成されたことが確認できます。それでは、シークレットの中を覗いてみましょう。
kubectl get secret my-oke-secret -o yaml
apiVersion: v1
data:
key: YVNlY3JldEluU2lW
immutable: false
kind: Secret
metadata:
annotations:
reconcile.external-secrets.io/data-hash: cff53a4bddfc2d04ea50e6d0da2c2868
creationTimestamp: "2022-06-01T02:11:43Z"
name: my-oke-secret
namespace: default
ownerReferences:
- apiVersion: external-secrets.io/v1beta1
blockOwnerDeletion: true
controller: true
kind: ExternalSecret
name: oci-secret
uid: 0039c7ab-91c2-4e15-acc7-f8de87ba1254
resourceVersion: "9117"
uid: 3074d172-078f-4214-9f21-a6bc69aae182
type: Opaque
キーが作成されたことが確認できます。これを抽出して、OCI Secretで作成したものと一致するかどうか確認してみましょう。
kubectl get secret my-oke-secret -o json | jq -r ."data.key" | base64 -d
aSecretInSiV
素晴らしい これは一致します!
シークレットを更新
では、更新を扱えるかどうか見てみましょう。OCI Secretで、新しいバージョンを作ってみましょう。
バージョン2がアクティブになり、現在の状態になるのを待って、もう一度上記のコマンドを実行し、シークレットを抽出します。
kubectl get secret my-oke-secret -o json | jq -r ."data.key" | base64 -d
SecretVersion2
Kubernetes Secret の値が更新されました。
クラスタ内の他のアプリケーションでESOを使用
ESO を使って、クラスタ内で動作している他のアプリケーションにシークレットを注入する方法を見てみましょう。今回は、Grafanaにパスワードを注入してみます。
Grafanaのhelmレポを追加します。
helm repo add grafana https://grafana.github.io/helm-charts
helm show values grafana/grafana > grafana.yaml
grafana.yamlを編集し、Administrator credentialsセクションを見つけます。
admin:
## Name of the secret. Can be templated.
existingSecret: "grafana-in-eso"
userKey: admin-user
passwordKey: admin-password
既存のSecretを上記のように変更します(または、任意の値に変更します)。
次に、OCI Vaultで以下のようにシークレットを作成します。
以上でExternalSecretを作成することができました。
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: oci-secret
spec:
refreshInterval: 0.03m
secretStoreRef:
kind: SecretStore
name: alivault
target:
name: grafana-in-eso
creationPolicy: Owner
dataFrom:
- extract:
key: grafana
それでは、Grafanaをデプロイしてみましょう。
helm install grafana grafana/grafana -f grafana.yaml
Grafanaポッドにポートフォワード
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=grafana,app.kubernetes.io/instance=grafana" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace default port-forward $POD_NAME 3000
OCI Vaultで作成した値が代わりに使用されていることに注意してください。ログインできるようになりました。
ここで、管理者のユーザー名とパスワードを変更したいとします。OCI Secretで新しいバージョンを作成します。
アクティブになったら、再度ログインしてください。
これは失敗します。理由は、Grafanaのポッドを作成する際に、シークレットを読み込んで、シークレットからadmin-usernameとadmin-passwordの値を使用し、設定ファイルに保存しているからです。そのため、今はまだOCI SecretとKubernetes secretの値が変更されていても、Grafanaはそのことを認識していないのです。
新しい値を使用するためには、このファイルを更新する必要があります。GrafanaのREST APIを使うこともできますが、Grafanaにシークレットの変更を監視するリスニングメカニズムがあるかどうかはわかりません(将来的に調査する必要があります)。今のところ、ユーザー名とパスワードの再読み込みを強制する最も簡単な方法は、Grafanaポッドを削除してKubernetesによる再作成を強制することです。
kubectl delete pod $POD_NAME
新しいポッドが作成されているのがわかると思います。
kubectl get pods
NAME READY STATUS RESTARTS AGE
grafana-788976bc4c-q2swm 0/1 ContainerCreating 0 8s
READYになるのを待って、バージョン2のシークレットで使用した値でポートフォワードしてください。これで、Grafanaにログインできるようになります。
注意:これはGrafanaのユーザー名とパスワードの更新方法として推奨されるものではありません。この例のポイントは、アプリケーションでESOを介してOCI Vaultからシークレットを再読み込みすることを示すことです。
まとめ
External Secrets Operatorは、OCI OKEをOCI Vaultと統合して使用するための優れた方法です。OKEとOKEで動作するアプリケーションの両方が、ESOを使用してOCI Vaultから機密データを取得することができます。
この投稿がお役に立てれば幸いです。
議論したいですか?私たちの公開Slackチャンネルに参加してください。
コメント
コメントを投稿