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"