CKAD — 쿠버네티스 애플리케이션 개발자 · 애플리케이션 환경·설정·보안 · 실습
ConfigMap 과 Secret 으로 설정 주입하기
목표
같은 이미지를 환경마다 다르게 동작시키는 네 가지 주입 경로(전체 환경변수, 개별 환경변수, 파일 볼륨, subPath 파일)를 구분해서 쓰고, Secret 과 ConfigMap 의 차이를 필드 수준에서 다룰 수 있게 된다.
왜 중요한가
설정 주입에서 실무 사고가 나는 지점은 대부분 "갱신이 반영되는가"이다. 환경변수로 넣은 값은 프로세스가 시작할 때 한 번 읽히고 끝이라, ConfigMap 을 고쳐도 파드를 다시 만들기 전에는 절대 바뀌지 않는다. 볼륨으로 넣은 파일은 kubelet 이 주기적으로 갱신해 주지만, subPath 로 얹은 파일만은 예외라 갱신되지 않는다. 이 세 가지 동작 차이를 모르면 "설정을 바꿨는데 왜 안 먹지"에서 시간을 다 쓴다.
defaultMode 도 실무에서 자주 걸린다. Secret 을 마운트하면 기본 권한이 0644 라 같은 노드의 다른 프로세스가 읽을 수 있다. TLS 키처럼 민감한 파일은 0400 으로 좁힌다. YAML 에서 0400 을 따옴표 없이 쓰면 8진수로 해석되지만, 400 만 쓰면 10진수 400 으로 읽혀 엉뚱한 권한이 된다.
immutable: true 는 보안 기능이 아니라 성능 기능이다. kubelet 은 마운트된 ConfigMap/Secret 의 변경을 감시하려고 API 서버를 계속 두드리는데, immutable 이면 감시를 멈춘다. 수천 파드 규모에서 apiserver 부하가 눈에 띄게 줄어든다.
단계
1. 네임스페이스 ckad-config 를 만들고, 그 안에 ConfigMap app-config 를 리터럴로 만든다. 키는 APP_MODE=production, LOG_LEVEL=info.
2. 디렉터리 /root/ckad-config 를 만들고 파일 /root/ckad-config/app.properties 에 timeout=30 한 줄을 쓴 뒤, 그 파일로 ConfigMap app-props 를 만든다(키 이름은 app.properties).
3. 파드 cfg-env 를 만든다. 이미지 busybox:1.36, command: ["/bin/sh","-c","sleep 3600"]. envFrom 으로 app-config 전체를 주입하고, 추가로 env 에 LOG 라는 이름으로 app-config 의 LOG_LEVEL 키를 참조한다.
4. Secret db-secret 을 만든다. 타입은 generic(Opaque), 키는 DB_USER=appuser, DB_PASSWORD=s3cr3t.
5. 파드 secret-consumer 를 만든다. 이미지 busybox:1.36, command: ["/bin/sh","-c","sleep 3600"]. 환경변수 DB_PASSWORD 를 db-secret 의 DB_PASSWORD 키에서 가져오고, 같은 Secret 을 볼륨 dbcreds 로 /etc/db 에 마운트하되 defaultMode 를 0400 으로 준다.
6. 파드 cfg-vol 을 만든다. 이미지 nginx:1.27. ConfigMap app-props 를 볼륨 props 로 두 번 마운트한다 — 하나는 /etc/app 에 디렉터리째, 다른 하나는 subPath: app.properties 로 /opt/app/app.properties 에.
7. ConfigMap feature-flags 를 만든다. 키 NEW_UI=on, 그리고 immutable: true. 파드 optional-cm 을 만들어(이미지 busybox:1.36, command: ["/bin/sh","-c","sleep 3600"]) 존재하지 않는 ConfigMap maybe-config 를 envFrom 으로 참조하되 optional: true 를 준다.
8. Deployment web-config 를 만든다. 레플리카 2, 라벨 app=web-config, 이미지 nginx:1.27. envFrom 에 app-config(configMapRef)와 db-secret(secretRef)을 모두 넣고, ConfigMap app-props 를 볼륨 props 로 /etc/app 에 마운트한다.
참고
kubectl create configmap app-config -n ckad-config --from-literal=APP_MODE=production --from-literal=LOG_LEVEL=infokubectl create secret generic db-secret -n ckad-config --from-literal=DB_USER=appuser --from-literal=DB_PASSWORD=s3cr3t- YAML 로 직접 쓸 때 평문을 넣으려면
data가 아니라stringData를 쓴다. 저장되면 자동으로data로 바뀐다. - 흔한 실수 1:
defaultMode를 컨테이너의volumeMounts밑에 쓰는 것. 볼륨 정의(spec.volumes[].secret.defaultMode) 쪽이다. - 흔한 실수 2:
immutable을data안에 넣는 것. ConfigMap 최상위 필드다. - 확인:
kubectl get secret db-secret -n ckad-config -o jsonpath='{.data.DB_USER}' | base64 -d
단계 8개
- 리터럴로 ConfigMap 만들기
- 파일에서 ConfigMap 만들기
- envFrom 과 configMapKeyRef 를 같이 쓰기
- Secret 만들기와 인코딩 확인
- Secret 을 환경변수와 파일로 함께 주입
- ConfigMap 볼륨과 subPath
- optional 참조와 immutable ConfigMap
- Deployment 에 세 가지를 한꺼번에 (종합)