External Secrets Operator
次に、External Secrets operatorを使用したAWS Secrets Managerとの統合を探ってみましょう。これは既にEKSクラスタにインストールされています:
NAME READY STATUS RESTARTS AGE
external-secrets-6d95d66dc8-5trlv 1/1 Running 0 7m
external-secrets-cert-controller-774dff987b-krnp7 1/1 Running 0 7m
external-secrets-webhook-6565844f8f-jxst8 1/1 Running 0 7m
NAME SECRETS AGE
default 0 7m
external-secrets-sa 0 7m
オペレーターはexternal-secrets-saという名前のServiceAccountを使用しており、これはIRSAを介してIAMロールに関連付けられ、AWS Secrets Managerへのアクセス権を提供しています:
Annotations: eks.amazonaws.com/role-arn: arn:aws:iam::1234567890:role/eks-workshop-external-secrets-sa-irsa
ClusterSecretStoreリソースを作成する必要があります - これは任意の名前空間からExternalSecretsが参照できるクラスター全体のSecretStoreです。このClusterSecretStoreを作成するために使用するファイルを確認してみましょう:
apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
name: "cluster-secret-store"
spec:
provider:
aws:
service: SecretsManager
region: $AWS_REGION
auth:
jwt:
serviceAccountRef:
name: "external-secrets-sa"
namespace: "external-secrets"
シークレットソースとしてAWS Secrets Managerを使用するためにservice: SecretsManagerを設定
シークレットが保存されているAWSリージョンを指定するために$AWS_REGION環境変数を使用
auth.jwtはIRSAを使用してexternal-secrets名前空間のexternal-secrets-saサービスアカウントで認証し、これはAWS Secrets Managerへのアクセス権を持つIAMロールにリンクされています
このファイルを使用してClusterSecretStoreリソースを作成しましょう。
次に、AWS Secrets Managerからどのデータを取得し、それをKubernetesシークレットにどのように変換するかを定義するExternalSecretを作成します。その後、これらの認証情報を使用するようにcatalogデプロイメントを更新します:
- Kustomize Patch
- Deployment/catalog
- Diff
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../../../base-application/catalog
- external-secret.yaml
patches:
- path: deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/created-by: eks-workshop
app.kubernetes.io/type: app
name: catalog
namespace: catalog
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/component: service
app.kubernetes.io/instance: catalog
app.kubernetes.io/name: catalog
template:
metadata:
annotations:
prometheus.io/path: /metrics
prometheus.io/port: "8080"
prometheus.io/scrape: "true"
labels:
app.kubernetes.io/component: service
app.kubernetes.io/created-by: eks-workshop
app.kubernetes.io/instance: catalog
app.kubernetes.io/name: catalog
spec:
containers:
- env:
- name: RETAIL_CATALOG_PERSISTENCE_USER
valueFrom:
secretKeyRef:
key: username
name: catalog-external-secret
- name: RETAIL_CATALOG_PERSISTENCE_PASSWORD
valueFrom:
secretKeyRef:
key: password
name: catalog-external-secret
envFrom:
- configMapRef:
name: catalog
image: public.ecr.aws/aws-containers/retail-store-sample-catalog:1.2.1
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 3
name: catalog
ports:
- containerPort: 8080
name: http
protocol: TCP
readinessProbe:
httpGet:
path: /health
port: 8080
periodSeconds: 5
successThreshold: 3
resources:
limits:
memory: 512Mi
requests:
cpu: 250m
memory: 512Mi
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
volumeMounts:
- mountPath: /tmp
name: tmp-volume
securityContext:
fsGroup: 1000
serviceAccountName: catalog
volumes:
- emptyDir:
medium: Memory
name: tmp-volume
app.kubernetes.io/instance: catalog
app.kubernetes.io/name: catalog
spec:
containers:
- - envFrom:
+ - env:
+ - name: RETAIL_CATALOG_PERSISTENCE_USER
+ valueFrom:
+ secretKeyRef:
+ key: username
+ name: catalog-external-secret
+ - name: RETAIL_CATALOG_PERSISTENCE_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ key: password
+ name: catalog-external-secret
+ envFrom:
- configMapRef:
name: catalog
- - secretRef:
- name: catalog-db
image: public.ecr.aws/aws-containers/retail-store-sample-catalog:1.2.1
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
新しいExternalSecretリソースを確認してみましょう:
NAME STORE REFRESH INTERVAL STATUS READY
catalog-external-secret cluster-secret-store 1h SecretSynced True
SecretSyncedステータスはAWS Secrets Managerからの同期が成功したことを示しています。リソースの仕様を見てみましょう:
dataFrom:
- extract:
conversionStrategy: Default
decodingStrategy: None
key: eks-workshop-catalog-secret-WDD8yS
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: cluster-secret-store
target:
creationPolicy: Owner
deletionPolicy: Retain
この設定は、keyパラメータと先ほど作成したClusterSecretStoreを通じてAWS Secrets Managerのシークレットを参照しています。1時間のrefreshIntervalは、シークレット値がどの頻度で同期されるかを決定します。
ExternalSecretを作成すると、自動的に対応するKubernetesシークレットが作成されます:
NAME TYPE DATA AGE
catalog-db Opaque 2 21h
catalog-external-secret Opaque 2 1m
catalog-secret Opaque 2 5h40m
このシークレットはExternal Secrets Operatorによって所有されています:
- apiVersion: external-secrets.io/v1beta1
blockOwnerDeletion: true
controller: true
kind: ExternalSecret
name: catalog-external-secret
uid: b8710001-366c-44c2-8e8d-462d85b1b8d7
私たちのcatalogポッドが新しいシークレット値を使用していることを確認できます:
NAME READY STATUS RESTARTS AGE
catalog-777c4d5dc8-lmf6v 1/1 Running 0 1m
catalog-mysql-0 1/1 Running 0 24h
- name: RETAIL_CATALOG_PERSISTENCE_USER
valueFrom:
secretKeyRef:
key: username
name: catalog-external-secret
- name: RETAIL_CATALOG_PERSISTENCE_PASSWORD
valueFrom:
secretKeyRef:
key: password
name: catalog-external-secret
まとめ
**AWS Secrets and Configuration Provider(ASCP)とExternal Secrets Operator(ESO)**の間には、AWS Secrets Managerのシークレットを管理するための「最良」な選択肢はありません。
それぞれのツールには異なる利点があります:
-
ASCPはAWS Secrets Managerからシークレットを直接ボリュームとしてマウントでき、環境変数として公開されることを避けることができますが、ボリューム管理が必要です。
-
ESOはKubernetesシークレットのライフサイクル管理を簡素化し、クラスター全体のSecretStore機能を提供しますが、ボリュームマウントはサポートしていません。
あなたの具体的なユースケースに基づいて決定すべきであり、両方のツールを使用することでシークレット管理における最大限の柔軟性とセキュリティを提供することができます。