1. 왜 설정과 코드를 분리해야 할까
애플리케이션 개발 시 설정 정보(데이터베이스 URL, API 키 등)를 코드 안에 직접 작성(하드코딩)하는 경우가 있습니다. 하지만 이는 다음과 같은 문제를 야기합니다.
- 환경별 변경의 어려움: 개발, 테스트, 운영 환경마다 DB 주소나 로깅 레벨이 다르다면, 환경을 바꿀 때마다 코드를 수정하고 다시 빌드해야 합니다.
- 보안 취약점: 민감한 정보(비밀번호)가 코드에 포함되면 Git 리포지토리나 이미지에 노출될 위험이 있습니다.
- 재사용성 저하: 동일한 애플리케이션이지만 설정만 다른 여러 인스턴스를 띄우기 어렵습니다.
쿠버네티스의 ConfigMap과 Secret은 이러한 문제를 해결하고 "설정과 코드의 분리(Separation of Concerns)"라는 모범 사례를 따르게 해줍니다.
기존에 진행하던 deployment.yaml 은 다음과 같이 설정 데이터를 직접 하드 코딩해주었습니다. 이 내용을 분리하는 실습을 진행해보겠습니다.
<이전 코드>
env:
- name: SPRING_DATASOURCE_URL
value: jdbc:mysql://mysql:3306/test
- name: SPRING_DATASOURCE_USERNAME
value: root
- name: SPRING_DATASOURCE_PASSWORD
value: password
- name: SPRING_DATA_MONGODB_URI
value: mongodb://mongodb:27017/testdb
2. ConfigMap: 민감하지 않은 설정 데이터 관리
ConfigMap은 민감하지 않은 설정 데이터를 키-값(Key-Value) 쌍으로 저장하는 데 사용됩니다. 애플리케이션 환경 변수, 설정 파일 내용 등을 관리할 때 적합합니다.
2.1 ConfigMap 생성하기
# my-app-db-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-app-db-config # 이 ConfigMap의 이름
data:
# 환경 변수로 주입될 설정 키-값 쌍
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/test
SPRING_DATASOURCE_USERNAME: root
SPRING_DATA_MONGODB_URI: mongodb://mongodb:27017/testdb
# 파일로 주입될 설정 내용 (key가 파일 이름이 됨)
app_custom_settings.txt: |
# My Custom App Settings
server.port=8080
debug.mode=true
2.2 적용하기
kubectl apply -f my-app-db-config.yaml
명령어로 ConfigMap 생성하기 간단한 키-값 쌍은 명령어로도 빠르게 생성할 수 있습니다.
# 리터럴(literal) 값으로 생성
kubectl create configmap my-app-env-config --from-literal=APP_ENV=dev --from-literal=LOG_LEVEL=DEBUG
# 파일 내용으로 생성 (먼저 my_file.txt 파일 생성: echo "TEST_VALUE=Hello" > my_file.txt)
kubectl create configmap my-app-file-config --from-file=config.txt=my_file.txt
2.2 ConfigMap을 파드에 주입하기
이제 생성한 ConfigMap의 데이터를 my-java-app 파드에 주입해 보겠습니다. 디플로이먼트(Deployment)의 YAML 파일을 수정해야 합니다.
방법 A: 환경 변수로 주입 (개별 키-값)
my-java-app 디플로이먼트의 컨테이너 정의 부분에 env 섹션을 추가하여 ConfigMap의 특정 키를 파드의 환경 변수로 매핑합니다.
# deployment.yaml
# ...
containers:
- name: my-java-app
image: dockerhubid/test:2.0 # 당신의 애플리케이션 이미지
ports:
- containerPort: 8080
env: # <--- 이 부분 추가/수정
- name: SPRING_DATASOURCE_URL # 파드 내에서 사용할 환경 변수 이름
valueFrom:
configMapKeyRef:
name: my-app-db-config # 사용할 ConfigMap 이름
key: SPRING_DATASOURCE_URL # ConfigMap 내의 키
- name: SPRING_DATASOURCE_USERNAME
valueFrom:
configMapKeyRef:
name: my-app-db-config
key: SPRING_DATASOURCE_USERNAME
- name: SPRING_DATA_MONGODB_URI
valueFrom:
configMapKeyRef:
name: my-app-db-config
key: SPRING_DATA_MONGODB_URI
# ...
방법 B: 볼륨(파일)으로 주입
ConfigMap에 정의된 app_custom_settings.txt 같은 설정 파일을 파드 내 특정 경로에 마운트하여 사용할 수 있습니다.
# my-java-app-deployment.yaml (수정된 부분)
# ...
containers:
- name: my-java-app
image: qws1566/test:2.0
ports:
- containerPort: 8080
volumeMounts: # <--- 컨테이너 내부에 볼륨 마운트
- name: app-config-volume # 아래 volumes 섹션과 이름 일치
mountPath: "/etc/app-settings" # 파드 내에서 ConfigMap 파일들이 마운트될 경로
readOnly: true # 읽기 전용으로 마운트
# ...
volumes: # <--- spec: 바로 아래에 볼륨 정의
- name: app-config-volume
configMap:
name: my-app-db-config # 마운트할 ConfigMap의 이름
# items: # (선택 사항) 특정 파일만 마운트하려면 사용
# - key: app_custom_settings.txt
# path: custom.conf # 파드 내 파일 이름 변경 가능
디플로이먼트 YAML 파일 수정 후 클러스터에 적용하여 롤링 업데이트를 시작합니다.
kubectl apply -f <deployment.yaml_파일>
2.3 주입된 ConfigMap 정보 확인하기
새로운 파드들이 실행되면, 파드 내부 셸에 접속하여 환경 변수와 파일 내용을 확인합니다.
- 파드 이름 확인:
kubectl get pods -l app=my-java-app
- 파드 셸 접속: (새로 생성된 파드 중 아무거나 선택)
kubectl exec -it <파드_이름> -- bash
- 정보 확인 (파드 내부 셸에서):
- 환경 변수 확인:
echo $SPRING_DATASOURCE_URL echo $SPRING_DATASOURCE_USERNAME echo $SPRING_DATA_MONGODB_URI
- 파일 내용 확인 (볼륨으로 주입했다면):
ls /etc/app-settings/ cat /etc/app-settings/app_custom_settings.txt
- 환경 변수 확인:
- 파드 셸 종료:
exit
다음과 같이 잘 저장된 것을 확인 가능합니다.
Secret: 민감한 데이터 안전하게 관리하기
Secret은 비밀번호, API 토큰, 인증서와 같은 민감한 정보를 저장하는 데 사용됩니다. ConfigMap과 유사하지만, 데이터가 Base64로 인코딩되어 저장되며, etcd에 저장 시 암호화될 수 있다는 차이점이 있습니다.
3.1 Secret 생성하기
MySQL 데이터베이스 비밀번호 (ex: dsjflksefj) 을 Secret으로 관리해 봅시다. 주의: Secret의 data 필드 값은 반드시 Base64로 인코딩되어야 합니다.
# 비밀번호를 Base64로 인코딩 (터미널에서 실행):
echo -n "바꾸려는 비밀번호 값" | base64
# 출력되는 값을 아래 YAML에 사용합니다.
# my-app-db-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: my-app-db-secret # 이 Secret의 이름
type: Opaque # 일반적인 키-값 Secret 타입
data:
SPRING_DATASOURCE_PASSWORD: <위에서_인코딩한_비밀번호의_Base64_값>
kubectl apply -f my-app-db-secret.yaml
명령어로 Secret 생성하기 간단한 Secret은 명령어로도 생성할 수 있습니다. 이 경우 쿠버네티스가 자동으로 Base64 인코딩을 처리해 줍니다.
# 리터럴(literal) 값으로 생성
kubectl create secret generic my-app-credential-secret --from-literal=API_KEY=your_super_secret_key
# 파일 내용으로 생성 (예: my_cert.pem 파일의 내용을 cert.pem 키로)
# kubectl create secret generic my-app-cert-secret --from-file=cert.pem=my_cert
deployment.yaml 파일을 수정해줍니다.
# Secret에서 비밀번호 가져오기 (새로 추가)
- name: SPRING_DATASOURCE_PASSWORD # 파드 내에서 사용할 환경 변수 이름
valueFrom:
secretKeyRef:
name: my-app-db-secret # 사용할 Secret 이름
key: SPRING_DATASOURCE_PASSWORD # Secret 내의 키
방법 B: 볼륨(파일)으로 주입
Secret의 내용을 파드 내 특정 경로에 파일로 마운트할 수 있습니다.
deployment.yaml
# ...
containers:
- name: my-java-app
image: qws1566/test:2.0
ports:
- containerPort: 8080
volumeMounts:
# 기존 ConfigMap 볼륨 마운트 (유지)
- name: app-config-volume
mountPath: "/etc/app-settings"
readOnly: true
# Secret 볼륨 마운트 (새로 추가)
- name: app-secret-volume
mountPath: "/etc/app-secrets" # 파드 내에서 Secret 파일들이 마운트될 경로
readOnly: true
# ...
volumes:
# 기존 ConfigMap 볼륨 정의 (유지)
- name: app-config-volume
configMap:
name: my-app-db-config
# Secret 볼륨 정의 (새로 추가)
- name: app-secret-volume
secret:
secretName: my-app-db-secret # 마운트할 Secret의 이름
# items: # (선택 사항) 특정 파일만 마운트하려면 사용
# - key: SPRING_DATASOURCE_PASSWORD
# path: db_password.txt # 파드 내 파일 이름 변경 가능
kubectl apply -f <deployment.yaml_파일>
3.3 주입된 Secret 정보 확인하기
새로운 파드들이 실행되면, 파드 내부 셸에 접속하여 환경 변수와 파일 내용을 확인합니다.
- 파드 이름 확인:
kubectl get pods -l app=my-java-app
- 파드 셸 접속:
kubectl exec -it <파드_이름> -- bash
- 정보 확인 (파드 내부 셸에서):
- 환경 변수 확인:결과: kimsoyun1! (Base64 인코딩된 값이 아닌 원래 값으로 출력됩니다!)
echo $SPRING_DATASOURCE_PASSWORD
- 파일 내용 확인 (볼륨으로 주입했다면):결과: kimsoyun1! (파일 내용도 자동으로 디코딩되어 보입니다.)
ls /etc/app-secrets/ cat /etc/app-secrets/SPRING_DATASOURCE_PASSWORD
- 환경 변수 확인:결과: kimsoyun1! (Base64 인코딩된 값이 아닌 원래 값으로 출력됩니다!)
- 파드 셸 종료:
exit
4. ConfigMap과 Secret 비교
구분 | ConfigMap | Secret |
목적 | 민감하지 않은 설정 데이터 저장 (예: DB URL, API 키, 로깅 레벨) | 민감한 데이터 저장 (예: 비밀번호, 인증서, 토큰) |
데이터 형식 | 일반 텍스트 (Base64 인코딩 불필요) | Base64 인코딩 (저장 시 필수, 파드 주입 시 자동 디코딩) |
보안 수준 | 일반 텍스트로 저장 및 전송되므로, kubectl get configmap 시 내용이 바로 노출 | etcd에 저장 시 암호화 가능 (클러스터 설정에 따라 다름). kubectl get secret 시 Base64로 인코딩된 형태로만 보임. |
주입 방식 | 환경 변수, 볼륨(파일) | 환경 변수, 볼륨(파일) |
용례 | 애플리케이션의 일반 설정, 환경 설정, 커스텀 파일 | 데이터베이스 비밀번호, 클라우드 API 키, TLS/SSL 인증서 |
'Cloud' 카테고리의 다른 글
Kubernetes PV(PersistentVolume), PVC(PersistentVolumeClaim) 실습 (4) | 2025.07.11 |
---|---|
Kubernetes RollingUpdate, Rollback 실습 (3) | 2025.07.11 |
kubernetes 배포 외부 접속 - NodePort, Kind (1) | 2025.07.10 |
Spring boot Docker와 Kubernetes 활용하여 배포하기 (3) | 2025.07.09 |