Kubernetes에서 애플리케이션을 배포할 때, 실행 환경에 따라 다양한 설정 값을 주입할 필요가 있다.

이를 위해 k8s는 ConfigMapSecret이라는 리소스를 제공하고 있다.

이 리소스로 외부에서 환경 변수 등을 관리할 수 있어 매번 새로 앱 빌드를 할 필요 없게 한다.

 

1. ConfigMap

비밀번호처럼 민감하지 않은 설정 정보 저장용 리소스.

특징

  • 키-값 형식의 데이터를 저장
  • 환경변수, 명령줄 인자, 설정 파일 등 비민감 설정 정보 주입 가능
  • 파드에 환경변수, 명령줄 인자, 볼륨 마운트 방식으로 주입

주요 개념 정리

  • 명령줄 인자 (command-line arguments)
    예: python app.py --env=prod
    --env=prod 부분을 외부에서 주입 가능
  • 설정 파일 경로
    /etc/config/app.conf 같은 경로로 파일을 마운트
    해당 경로에 ConfigMap 내용을 파일로 저장 가능
  • 주입 방식
    • 환경변수: env 필드 사용
    • 명령줄 인자: args, command 필드에 주입
    • 볼륨 마운트: ConfigMap 내용을 파일 형태로 제공

2. Secret

비밀번호, 토큰 등 민감한 정보를 저장하는 리소스.

특징

  • ConfigMap과 유사하지만 base64 인코딩 필요
  • base64는 보안이 아님 → etcd 암호화(Encryption at Rest)가 필요
  • RBAC, NetworkPolicy 등으로 접근 제어 가능
  • 환경변수, 파일 마운트 방식으로 파드에 주입

주요 개념 정리

  • etcd
    Kubernetes의 모든 상태 정보를 저장하는 핵심 저장소
  • Encryption at Rest
    디스크에 저장되기 전 데이터를 암호화
    Secret 사용 시 필수 보안 설정 중 하나
  • RBAC
    리소스 접근 제어 정책. Secret 열람 권한 제한 가능

3. 주입 예시

ConfigMap 예시

### ▶ ConfigMap, Secret
apiVersion: v1  # Kubernetes core API 그룹의 버전 v1 사용
kind: ConfigMap  # ConfigMap은 환경 변수나 설정 파일을 저장하는 용도
metadata:
  namespace: anotherclass-123  # 이 ConfigMap이 속한 네임스페이스
  name: api-tester-1231-properties  # 이 ConfigMap의 이름 (Pod에서 참조 가능)
  labels:  # 리소스를 식별하기 위한 라벨들
    part-of: k8s-anotherclass  # 프로젝트 그룹
    component: backend-server  # 역할 구분: 백엔드 서버
    name: api-tester  # 서비스 이름
    instance: api-tester-1231  # 인스턴스 식별용 라벨
    version: 1.0.0  # 버전 정보
    managed-by: dashboard  # 생성/관리 주체

# 실제 저장되는 key-value 형식 데이터들
# 이 값들은 컨테이너의 환경변수로 쓰이거나 파일로 마운트 가능
data:
  spring_profiles_active: "dev"  # Spring 프로파일 설정: dev 환경 사용
  application_role: "ALL"  # 애플리케이션 내부에서 사용할 권한 또는 역할
  postgresql_filepath: "/usr/src/myapp/datasource/postgresql-info.yaml"  # DB 접속 정보를 마운트한 파일 경로

 

 

Secret 예시

apiVersion: v1
kind: Secret  # Secret은 DB 비밀번호 같은 민감한 정보를 저장하는 리소스
metadata:
  namespace: anotherclass-123  # Secret이 속한 네임스페이스
  name: api-tester-1231-postgresql  # Secret 이름 (Pod에서 참조 가능)
  labels:  # 라벨을 통해 리소스를 구분하거나 관리할 수 있음
    part-of: k8s-anotherclass
    component: backend-server
    name: api-tester
    instance: api-tester-1231
    version: 1.0.0
    managed-by: dashboard

# stringData는 Kubernetes가 내부적으로 base64로 변환해 저장함
# 이 내용은 파일처럼 컨테이너에 마운트되며, 애플리케이션에서 읽을 수 있음
stringData:
  postgresql-info.yaml: |  # 이 키 이름은 컨테이너에 마운트될 파일명으로 사용됨
    driver-class-name: "org.postgresql.Driver"  # JDBC 드라이버 설정
    url: "jdbc:postgresql://postgresql:5431"  # DB 접속 URL
    username: "dev"  # DB 사용자명
    password: "dev123"  # DB 비밀번호

 

이때 stringData는 평문으로 작성하면 자동 base64 인코딩
반면 data 필드는 직접 base64 인코딩한 값을 넣어야 함

 

4. 마운트 예시 (Deployment.yaml)

volumeMounts:
  - name: secret-datasource
    mountPath: /usr/src/myapp/datasource
volumes:
  - name: secret-datasource
    secret:
      secretName: db-secret

5. 실습

ConfigMap Data

 

Secret Data

 

ConfigMap&Secret 데이터 조회 명령어

// Configmap 확인
kubectl describe -n anotherclass-123 configmaps api-tester-1231-properties
kubectl get -n anotherclass-123 configmaps api-tester-1231-properties -o yaml
kubectl get -n anotherclass-123 configmaps api-tester-1231-properties -o jsonpath='{.data}'

// Secret 확인
kubectl get -n anotherclass-123 secret api-tester-1231-postgresql -o yaml
kubectl get -n anotherclass-123 secret api-tester-1231-postgresql -o jsonpath='{.data}'

// Secret data에서 postgresql-info가 Key인 Value값만 조회 하기
kubectl get -n anotherclass-123 secret api-tester-1231-postgresql -o jsonpath='{.data.postgresql-info\\.yaml}'

// Secret data에서 postgresql-info가 Key인 Value값을 Base64 디코딩해서 보기
kubectl get -n anotherclass-123 secret api-tester-1231-postgresql -o jsonpath='{.data.postgresql-info\\.yaml}' | base64 -d

 

YAML 형식으로 ConfigMap 조회

 

YAML 형식으로 Secret 조회

 

파드 내부 들어와서 환경변수를 보면 ConfigMap의 내용이 들어가 있음

 

 

Secret이 이렇게 파일로 만들어지고 내용도 잘 들어가 있음

여기서 파드가 다 생성 후에 ConfigMap을 수정해도 파드의 환경변수는 바뀌지 않음

파드가 처음 만들어 졌을때 주입되기 때문에

하지만 Secret은 변경 후 바로 바뀌는데 이건 주입 방법 중 볼륨마운트로 주입하기 때문에 바로 바뀌는 것이다.

 

 

dev에서 test로 바로 변경되는 모습

 

6. ConfigMap, Secret 작동 흐름

  1. kubectl apply → API Server가 리소스(etcd)에 저장
  2. controller-manager가 필요한 리소스를 생성
  3. kubelet이 파드 정의 수신
  4. 컨테이너 시작 시 ConfigMap/Secret 주입

7. CI/CD와 ConfigMap 활용

출처: 일프로 인프런 강의[쿠버네티스 어나더 클래스 (지상편) - Sprint 1, 2 ]

  • 동일한 이미지로 개발(dev), 테스트(qa), 운영(prod) 환경 분리 가능
  • 환경별 ConfigMap만 변경하여 운영 가능
  • ConfigMap 외부화 덕분에 이미지 빌드 없이 설정만 교체 가능

8. 단점

  • ConfigMap 내용만 보고는 어떤 설정이 주입되었는지 알기 어려움
  • Spring에서 환경변수 주입 방식은 컴파일 오류가 아닌 런타임 오류로 바뀔 수 있음 → 디버깅 어려움
  • 팀 간 명확한 설정 기준이 없으면 혼란 발생 가능

9. Secret의 타입

Secret에는 용도에 따라 여러 type이 존재한다.

타입에 따라 쿠버네티스가 그 내용을 특정 방식으로 해석하거나 자동 활용할 수 있게 해줌

type: Opaque 이렇게 넣으면 된다 생략도 가능하고 기본값이 이것이다.

apiVersion: v1
kind: Secret  # Secret은 DB 비밀번호 같은 민감한 정보를 저장하는 리소스
type: Opaque <- 생략하면 자동으로 Opaque
metadata:

10. 주요 Secret 타입 설명

타입  용도  설명
Opaque 일반적인 key-value 형태 가장 일반적이며 대부분의 설정에 사용됨 (DB 비번, 토큰 등)
kubernetes.io/dockerconfigjson Docker 레지스트리 인증 비공개 이미지 pull을 위한 로그인 정보 저장
kubernetes.io/tls TLS 인증서 저장 HTTPS 통신을 위한 tls.crt, tls.key 저장
kubernetes.io/service-account-token 자동 생성됨 ServiceAccount에 바인딩된 JWT 토큰 저장 (자동관리용)
  • 이 모든 타입은 Secret이라고 해도 암호화 해주는 건 없음
  • 접근 제어를 통해서 보안을 하던가 별도의 암호화 로직을 만들어야함
  • 만약 암호화 로직을 구현했다면 ConfigMap으로 주고 받아도 됨
  • 이동 중에도 암호화 되어있어서 가능

 

❗️[중요]ConfigMap과 Secret은 파드가 아니다

ConfigMap이나 Secret은 파드(Pod)가 아니다. 이들은 쿠버네티스에 존재하는 리소스 객체(Resource Object) 중 하나이며, 쿠버네티스의 중앙 저장소인 etcd에 저장된다.

리소스 객체란?

  • 쿠버네티스에서 관리되는 모든 구성 요소는 리소스 객체로 취급된다.
  • 대표적인 예: Deployment, Service, ConfigMap, Secret, Pod 등
  • 이 객체들은 쿠버네티스 클러스터가 어떻게 동작해야 하는지에 대한 규칙 또는 선언문이다.

선언적 관리 방식

이렇게 선언적으로 동작들을 설정하는 것이 쿠버네티스이다.

  • 사용자는 리소스를 선언만 한다. (예: "파드를 3개 띄워라", "DB 비밀번호는 이 값이다" 등)
  • 이후 kube-apiserver를 통해 해당 선언이 etcd에 저장된다.
  • 쿠버네티스의 컨트롤러 컴포넌트(controller-manager, scheduler, kubelet 등)는
    이 선언을 바탕으로 실제 상태를 만들어내거나 유지한다.

예:

  • Deployment를 선언하면 controller-manager가 이를 감지하고 파드(Pod)를 생성함
  • ConfigMap이나 Secret을 선언하면, 해당 설정이 파드에 전달되도록 kubelet이 처리함

 

 

마무리

이번 글에서는 쿠버네티스에서 키-값 설정을 외부화하여 관리할 수 있는 ConfigMap과 Secret 리소스에 대해 알아보고, 실제로 이를 주입하여 애플리케이션에서 활용하는 실습을 진행했다.

 

이 두 리소스는 민감도에 따라 구분되며, 모두 etcd에 저장되어 쿠버네티스의 선언적 관리 방식 하에 동작한다.
특히, ConfigMap과 Secret을 미리 정의하고 필요한 시점에 주입받는 구조는 Spring의 Bean 등록 및 주입 방식과 유사하다는 점을 느겼다.

이처럼 자주 사용하는 설정값들을 별도로 관리하고 주입하는 방식은 유지보수성과 재사용성을 높이는 데 매우 효과적이다.

 

다음 글에서는 쿠버네티스의 핵심 특징 중 하나인 컨테이너의 생성과 소멸이 반복되는 환경에서 발생할 수 있는 데이터 손실 문제를 어떻게 해결하는지, 즉 영속적인 저장(Persistent Storage)을 가능하게 해주는 리소스인 PersistentVolumePersistentVolumeClaim에 대해 공부해보겠다.

+ Recent posts