[Kubernetes]External Secrets Operator入門
これは何?
Kubernetes External Secrets(KES)がメンテナンス期に移行する(新機能の追加などが対応されなくなる)というアナウンスが出たため(以下ISSUE)、External Secrets Operator(ESO)へ移行するために調査したことをまとめました。
*KESがESOへの移行を推奨していたこともあり、今回は他のSecret管理ツールは検討せずESOについてのみ調べました。
External Secrets Operatorとは
ESOはAWSなどの外部providerに保存された機密情報を取得してKubernetesのSecretリソースとして利用できるようにするためのCRDです。
KESと比べてドキュメントの充実度や設定の柔軟さが良いらしいです。ちなみにKESはJavaScriptで作られており、ESOはGolangで作られています。
2021年12月時点での各種外部providerのメンテナンス状況は以下のとおりです。
基本的にはalpha版なので利用する場合にはアップデート時の破壊的更新に特に注意が必要そうです(Kubernetesのエコシステムではalpha版の利用は割と仕方ないですね..)。
Provider | Stability | maintenance |
---|---|---|
AWS Secrets Manager | alpha | Internally maintained |
AWS Parameter Store | alpha | Internally maintained |
Hashicorp Vault | stable | Internally maintained |
Google Cloud Secrets Manager | alpha | Internally maintained |
Azure Key Vault | alpha | Community maintained |
IBM Cloud Secrets Manager | alpha | Community maintained |
Yandex Lockbox | stable | Community maintained |
Gitlab Project Variables | alpha | Community maintained |
Alibaba Cloud KMS | alpha | Community maintained |
Oracle Vault | alpha | Community maintained |
Akeyless | alpha | Community maintained |
エコシステム
ESOは SecretStore
(or ClusterSecretStore
) と ExternalSecret
というCRDを使うことで機密情報を外部providerから取得します。SecretStore
(or ClusterSecretStore
) は外部providerに対する認証を行い、ExternalSecret
は参照したい機密情報の指定を行います。
KESでは以下のように ExternalSecret
を用意すればよかったのでこの点では設計思想に違いがあり、ESOでは役割(認証とリソースの指定)毎にCRDを分けた形をとっています。
# KESではこれだけ定義すればよかった
apiVersion: 'kubernetes-client.io/v1'
kind: ExternalSecret
metadata:
name: hoge-secret
spec:
backendType: systemManager
roleArn: IAM_ROLE_ARN
data:
- name: name
key: key
ESOの各リソースの役割は以下の図の通りです(External Secrets Operator API Overviewより拝借)。
AWSのParameter Storeなどを利用する場合には以下のようなイメージです(External Secrets Operator AWS Parameter Storeより拝借)。
SecretStore
SecretStoreでは取得したいリソースに対してどのように(どのproviderのどの認証方式で)アクセスするのかを定義します。
AWSのParameter Storeに対するアクセスを行いたい場合にはおよそ以下の設定が必要です。
認証にはIRSAを利用できるので基本的にはKESで利用していたリソースをそのまま転用できそうです。
apiVersion: external-secrets.io/v1alpha1
kind: SecretStore
metadata:
name: secretstore-sample
spec:
# 機密情報を保管しているproviderに対する設定を記載する
provider:
aws:
# `ParameterStore` or `SecretsManager` が指定可能
service: ParameterStore
# Parameter Storeに対してアクセス時にAssumeRoleするためのIAM Role。
# IRSAを経由して認証する場合には
# IRSAのIAM Roleに必要な権限を指定することでこちらは無指定でも良さそう?(要検証)
role: iam-role
region: ap-northeast-1
# AWSに対する認証を行うためのリソースを指定する
auth:
# IRSAを経由して認証する場合にはこれを使う
jwt:
serviceAccountRef:
name: my-serviceaccount
# Access Key ID, Secret Access Keyを経由して認証する場合にはこれを使う
secretRef:
accessKeyIDSecretRef:
name: awssm-secret
key: access-key
secretAccessKeySecretRef:
name: awssm-secret
key: secret-access-key
---
# ServiceAccount経由での認証の場合にはServiceAccountを作成
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
# IAM Role側で `ssm:GetParameter` などの権限を付与しておくと良さそう
eks.amazonaws.com/role-arn: <IAM_ROLE_ARN>
name: my-serviceaccount
namespace: xxxxx
ExternalSecret
取得したいリソースを定義することでKubernetesのSecretリソースとして機密情報が保存されます。
ExternalSecretは以下のタイミングでデータの更新(SecretStoreに問い合わせて機密情報を取得し、差分があれば更新)を行います。
-
.spec.refreshInterval
の指定を経過した場合 -
.metadata.labels
または.metadata.annotations
に差分がある場合 -
.spec
に差分がある場合
AWSのParameter Storeに対するアクセスを行いたい場合にはおよそ以下の設定が必要です。
apiVersion: external-secrets.io/v1alpha1
kind: ExternalSecret
metadata:
name: example
# `labels` と `annotations` は作成されるSecretにも引き継がれる
labels:
acme.org/owned-by: "q-team"
annotations:
foo: bar
spec:
# 外部providerに対してデータ参照を行いSecretの値を更新する頻度
refreshInterval: 1h
# 該当データをどのように取得するかを定義したSecretStoreを指定する
secretStoreRef:
name: secretstore-sample
kind: SecretStore
# ExternalSecretから作成される `kind: Secret` リソースの情報を定義する
# ExternalSecretにつき1つだけ定義できる
target:
# `kind: Secret` として作成されたリソースの名前であり、無指定の場合には `.metadata.name` が指定される。
name: secret-to-be-created
# `Owner`, `Merge`, `None` から指定する。デフォルトは `Owner`
# `Owner` は Secretリソースを作成し、 `.metadata.ownerReferences` をセットする。
# `Merge` は Secretリソースを作成しないが `.spec.data` の値をSecretリソースに反映させる
# `None` は Secretリソースを作成しない(将来的にはinjectorとして利用可能になる想定)
creationPolicy: Owner
# key/valueで何のデータがほしいかを明示的に指定する
data:
- secretKey: secret-key-to-be-managed
remoteRef:
# parameter storeの場合にはpathを指定
key: provider-key
# 指定したものを一括で取得することもできる
dataFrom:
- key: remote-key-in-the-provider
Helm Chart
ESOのHelm Chartは以下で公開されています(ESOのGitHubのrootには charts
系のディレクトリが見当たらなかったので、以下を見るのが手っ取り早そうです)。
設定値はKESと同じようなものが多いため、KESで利用していたもの(ServiceAccountなど)をある程度そのままこちらに移行できそうな雰囲気はあります。
その他
External Secrets
のProjectを見ていると、KESからESOにマイグレーションしてくれるRepositoryがありました。現状ではまだ開発中とのことで今後に期待ですね。
まとめ
私にとっては初めてのライブラリ乗り換えのため戦々恐々としていましたが、調べたところESOに対する学習コストやリソースの作り直しは思ったよりは少なそうで安心しました(大本のProjectが同じというのも影響していると思います)。
みなさんも素敵なKubernetesライフをお過ごしください!
参考
ESO公式ドキュメント
Discussion