3.4. 설정 데이터
어떨 때 쓰는가
- 개발·검증·운영에서 접속 주소나 설정값만 다르게 하고 싶을 때
- 비밀번호를 이미지 안에 넣지 않고 관리하고 싶을 때
- 설정을 바꿀 때마다 이미지를 다시 만들고 싶지 않을 때
설정을 이미지 밖에 두는 이유
컨테이너 이미지에 설정을 넣으면 환경마다 이미지를 새로 만들어야 합니다.
| 이미지에 넣으면 | 밖에 두면 | |
|---|---|---|
| 환경별 배포 | 개발용·운영용 이미지를 따로 만듭니다 | 같은 이미지를 씁니다 |
| 설정 변경 | 이미지를 다시 만들고 다시 배포합니다 | 값만 고칩니다 |
| 검증한 것과 운영에 뜨는 것 | 다른 이미지입니다 | 같은 이미지입니다 |
| 비밀번호 | 이미지에 박혀 누구나 볼 수 있습니다 | 권한이 있는 사람만 봅니다 |
"검증한 것과 운영에 뜨는 것이 같다" 는 점이 가장 중요합니다. 이미지가 다르면 검증에서 통과한 것이 운영에서 실패할 수 있습니다.
ConfigMap 이란
감출 필요 없는 설정값을 담는 자원 입니다.
키와 값의 쌍으로 저장하며, 값은 짧은 문자열일 수도 있고 설정 파일 전체일 수도 있습니다.
| 담는 예 | 형태 |
|---|---|
| 접속 주소 | DB_HOST=db.example.local |
| 로그 수준 | LOG_LEVEL=info |
| 기능 켬·끔 | FEATURE_NEW_UI=true |
| 설정 파일 통째로 | application.yml 의 내용 전체 |
Secret 이란
감춰야 하는 값을 담는 자원 입니다. 구조는 ConfigMap 과 같지만 다루는 방식이 다릅니다.
| ConfigMap | Secret | |
|---|---|---|
| 화면 표시 | 그대로 보입니다 | 가려져 있습니다. 눌러야 보입니다 |
| 조회 권한 | view 롤에 포함 | view 롤에서 제외 (7.1 장) |
| 저장 형식 | 평문 | base64 인코딩 |
| 유형 구분 | 없음 | 있습니다 (아래 참고) |
Secret 은 암호화가 아니다
Secret 은 암호화되어 저장되지 않습니다. base64 로 인코딩만 되어 있고, 인코딩은 누구나 되돌릴 수 있습니다.
Secret 이 제공하는 보호는 이런 것입니다.
| 있는 것 | 없는 것 |
|---|---|
| 조회 권한을 따로 관리할 수 있습니다 | 값 자체의 암호화 |
| 화면과 로그에 실수로 노출되는 것을 줄입니다 | 저장소가 뚫렸을 때의 보호 |
| 파드에 파일로 주입할 때 메모리에만 둡니다 |
따라서 Secret 조회 권한은 꼭 필요한 사람에게만 주십시오. 클러스터 저장소(etcd)의 암호화는 운영 담당자가 별도로 설정합니다.
ConfigMap 목록
워크로드 > 구성 맵 으로 들어갑니다.

| 열 | 설명 |
|---|---|
| 이름 | ConfigMap 이름 |
| 네임스페이스 | 속한 네임스페이스 |
| 데이터 | 담긴 키 개수 |
| 경과 시간 | 만든 뒤 지난 시간 |
ConfigMap 과 Secret 은 네임스페이스 단위 자원입니다. 다른 네임스페이스의 파드는 쓸 수 없습니다. 여러 네임스페이스에서 같은 설정이 필요하면 각각 만들어야 합니다.
ConfigMap 상세
이름을 누르면 담긴 키와 값을 봅니다.

- 값이 긴 설정 파일이면 전체 내용이 그대로 보입니다.
- 편집 버튼으로 값을 고칠 수 있습니다.
- 어떤 파드가 이 ConfigMap 을 쓰는지는 여기서 보이지 않습니다. 파드 상세의 환경 변수와 마운트에서 확인합니다(3.1 장).
Secret 목록
워크로드 > 시크릿 에서 봅니다.

목록 구성은 ConfigMap 과 같고 유형 열이 더 있습니다. 값은 기본으로 가려져 있어 눈 모양 버튼을 눌러야 보입니다.
Secret 유형
유형은 그 Secret 이 무엇에 쓰이는지 나타냅니다. 유형에 따라 담아야 할 키가 정해져 있습니다.
| 유형 | 담는 것 | 만들어지는 경로 |
|---|---|---|
Opaque | 일반 비밀값. 키 이름은 자유 | 직접 만듭니다 |
kubernetes.io/dockerconfigjson | 레지스트리 로그인 정보 | 이미지를 가져올 때 씁니다 |
kubernetes.io/tls | TLS 인증서(tls.crt)와 개인 키(tls.key) | cert-manager 가 자동 생성 (7.3 장) |
kubernetes.io/basic-auth | 사용자 이름과 비밀번호 | Git 저장소 인증 등 |
kubernetes.io/ssh-auth | SSH 개인 키 | Git SSH 접속 |
kubernetes.io/service-account-token | 서비스 어카운트 토큰 | 클러스터가 자동 생성 |
helm.sh/release.v1 | Helm 릴리즈 정보 | Helm 이 자동 생성 (9.1 장) |
helm.sh/release.v1 이 여러 개 보이는 것은 정상입니다. Helm 이 개정마다 하나씩 남깁니다.
빌드가 레지스트리에 이미지를 올리지 못할 때 는 dockerconfigjson 유형 Secret 의 계정과
비밀번호를 확인하십시오(4.2 장).
파드에 연결하는 두 가지 방식
| 방식 | 설명 | 적합한 경우 |
|---|---|---|
| 환경 변수 | 키를 환경 변수 이름으로 전달 | 값이 몇 개 안 될 때 |
| 볼륨 마운트 | 키를 파일로 만들어 디렉터리에 붙임 | 설정 파일이 통째로 필요할 때 |
환경 변수 방식은 두 가지로 나뉩니다.
| 방식 | 동작 |
|---|---|
| 키 하나씩 지정 | 원하는 키만 골라 이름을 바꿔 넣을 수 있습니다 |
| 통째로 주입 | ConfigMap 의 모든 키가 환경 변수가 됩니다 |
파드 상세 화면에서 어떤 ConfigMap·Secret 이 어떤 방식으로 연결되었는지 확인할 수 있습니다.
만들고 연결하기 — YAML
ConfigMap 만들기
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: my-app
data:
LOG_LEVEL: "info" # 값이 하나인 항목
MAX_CONNECTIONS: "50"
application.yaml: | # 파일 통째로 넣기
server:
port: 8080
logging:
level: info
값은 모두 문자열로 씁니다. 숫자 50 을 따옴표 없이 적으면 적용할 때 거부됩니다.
| 뒤에 여러 줄을 쓰면 그 전체가 파일 하나의 내용이 됩니다.
Secret 만들기
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
namespace: my-app
type: Opaque
stringData: # 평문으로 적으면 저장할 때 변환됩니다
username: appuser
password: "s3cr3t-p@ssw0rd"
stringData 를 쓰십시오. data 를 쓰면 값을 미리 인코딩해 넣어야 하는데, 잊고 평문을
넣으면 애플리케이션이 깨진 값을 받습니다. stringData 는 Kubernetes 가 대신 변환합니다.
Console 화면에서 만들 때는 이 변환이 자동으로 이뤄지므로 값만 입력하면 됩니다.
방식 1 — 환경 변수로 넣기
키를 골라 이름을 정해 넣습니다.
containers:
- name: app
image: registry.example.com/my-app:1.0
env:
- name: LOG_LEVEL # 컨테이너에서 쓸 이름
valueFrom:
configMapKeyRef:
name: app-config # ConfigMap 이름
key: LOG_LEVEL # 그 안의 키
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-credentials
key: password
키가 많으면 통째로 넣습니다. ConfigMap 의 키 이름이 그대로 환경 변수 이름이 됩니다.
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: db-credentials
통째로 넣을 때는 키 이름이 환경 변수로 쓸 수 있는 형태여야 합니다. application.yaml
처럼 점이 든 키는 환경 변수가 되지 못하고 조용히 빠집니다. 파일 성격의 값은 아래 볼륨
방식을 쓰십시오.
방식 2 — 파일로 붙이기
containers:
- name: app
image: registry.example.com/my-app:1.0
volumeMounts:
- name: config # 아래 volumes 의 이름과 같아야 합니다
mountPath: /etc/app # 이 디렉터리에 파일이 생깁니다
readOnly: true
volumes:
- name: config
configMap:
name: app-config
이렇게 하면 /etc/app/ 아래에 키 이름으로 파일이 하나씩 만들어집니다. 위 예에서는
LOG_LEVEL·MAX_CONNECTIONS·application.yaml 세 파일이 생깁니다.
필요한 키만 골라 파일 이름 을 바꿀 수도 있습니다.
volumes:
- name: config
configMap:
name: app-config
items:
- key: application.yaml
path: config.yaml # /etc/app/config.yaml 로 만들어집니다
Secret 도 같은 방식이며 configMap 대신 secret, name 대신 secretName 을 씁니다.
volumes:
- name: creds
secret:
secretName: db-credentials
defaultMode: 0400 # 소유자만 읽기
인증 정보를 파일로 붙일 때는 권한을 좁히십시오. 지정하지 않으면 0644 로 만들어져
소유자 외에도 읽을 수 있습니다.
마운트할 때 주의할 것
mountPath 에 지정한 디렉터리의 기존 내용은 가려집니다. 예를 들어 /etc/nginx 에
ConfigMap 을 붙이면 이미지에 들어 있던 /etc/nginx 아래 파일이 전부 보이지 않게 됩니다.
파일 하나만 바꾸려면 그 파일만 지정합니다.
- name: config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf # 이 파일 하나만 덮어씁니다
다만 subPath 로 붙인 파일은 ConfigMap 을 고쳐도 갱신되지 않습니다. 파드를 다시
시작해야 반영됩니다. 아래 "값을 고친 뒤 할 일" 과 함께 보십시오.
값을 고친 뒤 할 일
이 부분을 몰라 "설정을 바꿨는데 반영이 안 된다" 는 일이 자주 생깁니다.
| 연결 방식 | 값 변경 반영 |
|---|---|
| 환경 변수 | 반영되지 않습니다. 파드를 다시 시작해야 합니다 |
| 볼륨 마운트 | 파일 내용은 1분 안팎에 바뀝니다. 다만 애플리케이션이 파일을 다시 읽어야 실제로 적용됩니다 |
환경 변수가 반영되지 않는 이유는, 환경 변수가 프로세스를 시작할 때 한 번 전달되는 값 이기 때문입니다. 이미 도는 프로세스의 환경 변수는 밖에서 바꿀 수 없습니다.
확실하게 반영하려면 해당 Deployment 를 다시 시작 하십시오(3.2 장).
되돌릴 때 주의할 것
ConfigMap·Secret 은 버전 이력이 없습니다. 고치면 이전 값이 사라집니다.
Deployment 를 롤백해도 ConfigMap 내용은 되돌아가지 않습니다(3.2 장). 롤백은 파드 템플릿만 되돌리고, 템플릿에는 "어떤 ConfigMap 을 쓸지" 만 적혀 있기 때문입니다.
설정을 고치기 전에 다음 중 하나를 하십시오.
| 방법 | 설명 |
|---|---|
| 현재 내용 복사해 두기 | 상세 화면의 YAML 을 복사해 파일로 보관 |
| 이름에 버전 붙이기 | app-config-v2 로 새로 만들고 배포 정의에서 참조를 바꿉니다 |
두 번째 방법을 쓰면 롤백할 때 참조도 함께 되돌아가 설정까지 복구됩니다.