kubernetes
Kubernetes Secrets Store CSI Driver
misankim
2023. 3. 7. 00:57
Kubernetes Secrets Store CSI Driver
-> k8s CSI(Container Storage Interface) 볼륨을 통해 secrets stores 와 k8s 를 통합하는 플러그인
-> secrets stores 의 시크릿을 k8s secret 으로 동기화도 가능(반드시 파드에 볼륨으로 마운트를 해줘야 sercet 리소스가 생성됨)
# gcp secret manager 와 gke 클러스터를 통합하여 사용 가능
# 설치
helm repo add secrets-store-csi-driver https://kubernetes-sigs.github.io/secrets-store-csi-driver/charts
helm upgrade -i csi-secrets-store secrets-store-csi-driver/secrets-store-csi-driver --namespace kube-system --set syncSecret.enabled=true
# gcp provider 를 위한 별도의 플러그인 배포
git clone https://github.com/GoogleCloudPlatform/secrets-store-csi-driver-provider-gcp.git
cd secrets-store-csi-driver-provider-gcp
kubectl apply -f deploy/provider-gcp-plugin.yaml
# 사용법
## gcp 서비스 어카운트 생성 및 워크로드 아이덴티티 설정
export PROJECT_ID=<your gcp project>
gcloud iam service-accounts create gke-workload
gcloud iam service-accounts add-iam-policy-binding \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:$PROJECT_ID.svc.id.goog[default/mypodserviceaccount]" \
gke-workload@$PROJECT_ID.iam.gserviceaccount.com
## gcp secret manager 에 시크릿 생성
echo -n "foo" > secret.data
gcloud secrets create testsecret --replication-policy=user-managed --data-file=secret.data --locations="asia-northeast3"
rm secret.data
## gcp 서비스 어카운트에 시크릿 단위의 권한 부여
-> testsecret 시크릿에만 액세스 가능
gcloud secrets add-iam-policy-binding testsecret \
--member=serviceAccount:gke-workload@$PROJECT_ID.iam.gserviceaccount.com \
--role=roles/secretmanager.secretAccessor
## 테스트 리소스 배포
./scripts/example.sh
## 확인
kubectl exec -it mypod -- ls -al /var/secrets
kubectl exec -it mypod -- cat /var/secrets/good1.txt
kubectl exec -it mypod -- cat /var/secrets/good2.txt
# gcp secret manager 의 시크릿을 파드에 파일로 마운트
➜ [secrets-store-csi-driver-provider-gcp] git:(main) ✗ cat examples/app-secrets.yaml.tmpl
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: app-secrets
spec:
provider: gcp
parameters:
secrets: |
- resourceName: "projects/$PROJECT_ID/secrets/testsecret/versions/latest"
path: "good1.txt"
- resourceName: "projects/$PROJECT_ID/secrets/testsecret/versions/latest"
path: "good2.txt"
➜ [secrets-store-csi-driver-provider-gcp] git:(main) ✗ cat examples/mypod.yaml.tmpl
apiVersion: v1
kind: ServiceAccount
metadata:
name: mypodserviceaccount
namespace: default
annotations:
iam.gke.io/gcp-service-account: gke-workload@$PROJECT_ID.iam.gserviceaccount.com
---
apiVersion: v1
kind: Pod
metadata:
name: mypod
namespace: default
spec:
serviceAccountName: mypodserviceaccount
containers:
- image: gcr.io/google.com/cloudsdktool/cloud-sdk:slim
imagePullPolicy: IfNotPresent
name: mypod
resources:
requests:
cpu: 100m
stdin: true
stdinOnce: true
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
tty: true
volumeMounts:
- mountPath: "/var/secrets"
name: mysecret
volumes:
- name: mysecret
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "app-secrets"
# gcp secret manager 의 시크릿을 파드에 환경 변수로 사용
-> 환경 변수로 사용하는 경우에도 반드시 파드에 secrets-store.csi.k8s.io 드라이버를 통해 볼륨을 마운트해줘야 k8s secret 리소스가 생성됨
https://secrets-store-csi-driver.sigs.k8s.io/topics/set-as-env-var.html
➜ [secrets-store-csi-driver-provider-gcp] git:(main) ✗ cat examples/app-secrets2.yaml.tmpl
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: app-secrets2
spec:
provider: gcp
secretObjects:
- secretName: foosecret
type: Opaque
data:
- objectName: good1.txt
key: username
- objectName: good2.txt
key: password
parameters:
secrets: |
- resourceName: "projects/$PROJECT_ID/secrets/testsecret/versions/latest"
path: "good1.txt"
- resourceName: "projects/$PROJECT_ID/secrets/testsecret/versions/latest"
path: "good2.txt"
➜ [secrets-store-csi-driver-provider-gcp] git:(main) ✗ cat examples/mypod2.yaml.tmpl
apiVersion: v1
kind: ServiceAccount
metadata:
name: mypodserviceaccount
namespace: default
annotations:
iam.gke.io/gcp-service-account: gke-workload@$PROJECT_ID.iam.gserviceaccount.com
---
apiVersion: v1
kind: Pod
metadata:
name: mypod2
namespace: default
spec:
serviceAccountName: mypodserviceaccount
containers:
- image: gcr.io/google.com/cloudsdktool/cloud-sdk:slim
imagePullPolicy: IfNotPresent
name: mypod
resources:
requests:
cpu: 100m
stdin: true
stdinOnce: true
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
tty: true
env:
- name: SECRET_USERNAME
valueFrom:
secretKeyRef:
name: foosecret
key: username
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: foosecret
key: password
volumeMounts:
- mountPath: "/var/secrets"
name: mysecret
volumes:
- name: mysecret
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "app-secrets2"