← 스터디 홈
6편 · 약 9분

ConfigMap/Secret과 설정

코드에서 설정을 분리한다

12-Factor App 원칙의 세 번째 항목은 "설정(Config)을 환경에 저장하라"이다. DB 접속 URL·로그 레벨·피처 플래그가 코드에 하드코딩되어 있으면, 운영/개발/테스트 환경마다 이미지를 다시 빌드해야 한다. 쿠버네티스는 이 문제를 두 오브젝트로 해결한다.

ConfigMapSecret
용도비민감 설정값비밀번호·토큰·인증서 등 민감 값
저장 형식평문base64 인코딩 (기본)
etcd 암호화 여부✗ 기본 꺼짐✗ 기본 꺼짐 — 따로 설정 필요
크기 제한1 MiB1 MiB

ConfigMap

ConfigMap은 키-값 쌍 또는 파일 내용을 클러스터 오브젝트로 저장한다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  LOG_LEVEL: "info"
  config.yaml: |
    port: 8080
    timeout: 30s

Pod에 주입하는 두 가지 방법

환경 변수 (envFrom / env) — 빠르게 주입할 수 있지만 ConfigMap이 바뀌어도 Pod를 재시작해야 반영된다.

envFrom:
  - configMapRef:
      name: app-config

볼륨 마운트 — 파일로 마운트된다. kubelet이 주기적으로(기본 약 60초) 파일을 갱신하므로, 앱이 파일 변경을 감시(watch)한다면 Pod 재시작 없이 설정을 반영할 수 있다.

volumes:
  - name: config
    configMap:
      name: app-config
volumeMounts:
  - name: config
    mountPath: /etc/config
    readOnly: true

주의: subPath로 마운트한 파일은 자동 갱신이 되지 않는다. 디렉터리 전체를 마운트해야 hot-reload가 동작한다.

Secret

Secret은 ConfigMap과 구조가 거의 같지만 민감 데이터를 위해 설계되었다.

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  DB_PASSWORD: cGFzc3dvcmQxMjM=   # base64("password123")

base64는 암호화가 아니다

Secret의 값은 base64로 인코딩되어 있다. base64 -d 한 줄이면 누구나 원문을 복원할 수 있다. base64는 바이너리 데이터를 YAML에 담기 위한 표현 형식일 뿐이다.

Secret이 ConfigMap보다 안전한 실질적인 이유는 두 가지다.

  1. RBAC 분리 — ConfigMap과 별도 리소스이므로 접근 권한을 다르게 설정할 수 있다.
  2. Encryption at Rest — 클러스터 관리자가 EncryptionConfiguration을 설정하면 etcd에 쓰기 전 AES-GCM 등으로 암호화된다. 기본값은 비활성이다.

Secret 타입

타입설명
Opaque범용 (기본값)
kubernetes.io/tlsTLS 인증서/키 (tls.crt, tls.key)
kubernetes.io/dockerconfigjson레지스트리 인증 정보 (이미지 풀)
kubernetes.io/service-account-tokenServiceAccount 토큰 (자동 생성)

주입 경로 한눈에 보기

설정 소스 ConfigMap Secret
주입 방식 envFrom / env volumeMount
Pod 내부 $ENV_VAR (재시작 시 반영) /etc/config/* (kubelet ~60s 갱신)
ConfigMap/Secret을 Pod에 주입하는 두 경로와 갱신 특성

환경 변수는 기동 시 한 번 복사된다. 볼륨 마운트는 kubelet이 주기적으로 심링크를 교체해 파일을 갱신한다. 어떤 앱은 SIGHUP이나 파일 watch로 재로드를 지원하기도 한다.

불변(Immutable) 설정

ConfigMap/Secret에 immutable: true를 지정하면 데이터 수정이 차단된다. 변경이 필요하면 새 이름으로 다시 만들고 Pod의 참조를 교체해야 한다. 그 대신 kube-apiserver의 watch 비용이 줄어 대규모 클러스터에서 API 서버 부하를 낮추는 효과가 있다.

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config-v2
immutable: true
data:
  LOG_LEVEL: "warn"

프로덕션 보안 체크리스트

  1. etcd 암호화 활성화EncryptionConfiguration으로 AES-GCM 또는 KMS 공급자 설정.
  2. RBAC 최소 권한 — 앱별 ServiceAccount에 필요한 Secret만 get 허용.
  3. 소스 저장소에 Secret 커밋 금지.gitignore 또는 SOPS/git-crypt 활용.
  4. 볼륨 마운트 + readOnly: true 선호 — 환경 변수는 kubectl describe pod에서 키 이름이 노출된다.
  5. 외부 시크릿 관리자 연동 고려 — HashiCorp Vault, AWS Secrets Manager 등을 External Secrets Operator로 연동하면 자동 순환(rotation)과 감사 로그를 얻을 수 있다.

References

  • https://kubernetes.io/docs/concepts/configuration/configmap/
  • https://kubernetes.io/docs/concepts/configuration/secret/
  • https://kubernetes.io/docs/concepts/security/secrets-good-practices/
  • https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/
  • https://blog.alphabravo.io/part-5-managing-applications-with-kubernetes-configmaps-and-secrets-configuration-without-tears/
  • https://www.wiz.io/academy/kubernetes-secrets
  • https://external-secrets.io/