kubectl 로 Secret 을 만들고 읽는 방법과, 컨테이너에 Secret 을 주입할 때 env + secretKeyRef 와 envFrom 중 무엇을 골라야 하는지를 정리한다. exporter 류처럼 특정 비밀 하나만 필요한 컨테이너는 env 로 키 하나만 매핑하는 것이 최소 권한 원칙에 맞다.
# 리터럴
kubectl create secret generic my-secret \
--from-literal=username=admin \
--from-literal=password='${PASSWORD}'
# 파일 · 디렉터리 · env 파일
kubectl create secret generic my-secret --from-file=./config.json
kubectl create secret generic my-secret --from-file=app-config=./config.json
kubectl create secret generic my-secret --from-file=./configs/
kubectl create secret generic my-secret --from-env-file=./.env
# TLS
kubectl create secret tls my-tls --cert=./tls.crt --key=./tls.key
# 이미지 레지스트리
kubectl create secret docker-registry regcred \
--docker-server=<REGISTRY_URL> --docker-username=<USER> \
--docker-password='${PASSWORD}' --docker-email=<EMAIL>
매니페스트로 만들 때 data 는 base64 값, stringData 는 평문을 그대로 쓴다.
apiVersion: v1
kind: Secret
metadata:
name: my-secret
namespace: default
type: Opaque
stringData:
username: admin
password: "${PASSWORD}"
kubectl get secret -n <namespace>
kubectl describe secret my-secret # 값은 표시되지 않음
kubectl get secret my-secret -o jsonpath='{.data}' | jq 'keys'
kubectl get secret my-secret -o jsonpath='{.data.password}' | base64 -d
kubectl get secret my-secret -o json \
| jq -r '.data | to_entries[] | "\(.key)=\(.value | @base64d)"'
Secret 값은 base64 인코딩일 뿐 암호화가 아니다. etcd 암호화(EncryptionConfiguration, EKS 는 KMS envelope encryption) 를 켜고, RBAC 으로 secrets 의 get/list/watch 를 최소화한다. 디코딩한 값을 로그 · 터미널 캡처 · CI 출력에 남기지 않는다.
envFrom 은 Secret 의 모든 키가 그대로 환경변수 이름이 되어 통째로 주입된다.
envFrom:
- secretRef:
name: db-credentials
env + secretKeyRef 는 특정 키 하나만 원하는 이름으로 매핑한다.
env:
- name: DATA_SOURCE_NAME
valueFrom:
secretKeyRef:
name: db-credentials
key: postgres-dsn
exporter 에서 env 를 쓰는 이유는 네 가지다.
DATA_SOURCE_NAME, mysqld_exporter 의 MYSQLD_EXPORTER_PASSWORD 등). Secret 키 이름이 다르면 envFrom 으로는 매핑할 수 없다.envFrom 은 전부 컨테이너에 떨어뜨린다. 컨테이너가 침해되면 피해 범위가 곧장 커진다.envFrom 으로 합칠 때 생기는 키 이름 충돌(덮어쓰기) 이 없다.앱 컨테이너처럼 설정 묶음을 통째로 넣을 때는 envFrom 이 편하고, 비밀 하나만 필요한 컨테이너는 env 가 적합하다.
실무에서는 AWS Secrets Manager(또는 SSM Parameter Store) 를 원천으로 두고 클러스터로 끌어온다.
secretsmanager:GetSecretValue · kms:Decrypt 권한을 주고, ExternalSecret CR 을 선언하면 네이티브 K8s Secret 으로 동기화된다. 회전(rotation) 은 Secrets Manager 에서 일어나고 pod 재시작 한 번이면 새 값을 받는다. GitOps 와 잘 맞는다.syncSecret 으로 K8s Secret 을 같이 만들어 env 로 주입하는 하이브리드가 필요하다.