Secrets 와 ConfigMaps

KubernetesBeginner
지금 연습하기

소개

소프트웨어에서 데이터베이스 URL 이나 비밀번호 같은 설정을 애플리케이션 코드에 직접 입력하는 것은 좋지 않은 방법입니다. 이렇게 하면 변경이 어려워지고 보안 위험도 커집니다.

Kubernetes 는 다음 두 객체로 이 문제를 해결합니다.

  1. ConfigMap: 공용 게시판이라고 생각하면 됩니다. 여기에 "배경색은 파란색입니다" 또는 "데이터베이스 주소는 10.0.0.1입니다" 같은 정보를 게시합니다. 사무실의 누구나 (Pod) 이 내용을 읽을 수 있습니다.
  2. Secret: 비밀번호나 토큰처럼 민감한 값을 저장할 때 사용합니다.

애플리케이션 코드와 실행 시 구성을 분리하는 것은 단순한 Kubernetes 기능이 아니라, 플랫폼 설계의 중요한 원칙입니다.

이 실습에서는 다음 작업을 수행합니다.

  • 게시판 (ConfigMap) 에 메모를 작성합니다.
  • 금고 (Secret) 에 비밀번호를 넣습니다.
  • Pod 가 두 객체를 읽도록 구성합니다.

ConfigMap 생성

웹 서버용 구성 파일을 만들어 보겠습니다. 이 파일을 이미지에 포함하는 대신 ConfigMap에 저장합니다.

이 방식은 더 큰 컨테이너 설계 원칙의 일부입니다. 재사용할 수 있는 이미지 하나를 빌드한 다음, 실행 시 환경별 구성을 제공합니다. 그러면 개발, 스테이징, 프로덕션 환경에서 서로 다른 설정을 사용하면서도 같은 컨테이너를 사용할 수 있으므로 이미지의 이식성이 높아집니다.

먼저 nginx.conf라는 간단한 Nginx 구성 파일을 만듭니다.

echo 'events {} http { server { listen 80; location / { return 200 "Hello from ConfigMap!"; } } }' > nginx.conf

이제 이 파일에서 nginx-config라는 ConfigMap 을 만듭니다. 이렇게 하면 파일이 Kubernetes 클러스터의 게시판에 게시됩니다.

kubectl create configmap nginx-config --from-file=nginx.conf

ConfigMap 이 생성되었는지 확인합니다.

kubectl describe configmap nginx-config

Data 섹션 아래에 nginx.conf의 내용이 표시되어야 합니다.

Secret 생성

이제 민감한 값을 저장해 보겠습니다. Secret은 ConfigMap 과 비슷하게 작동하지만, Kubernetes 가 Secret 을 더 신중하게 처리하며 저장된 데이터를 난독화합니다.

여기서는 정확히 이해해야 할 점이 있습니다. Secret 은 매니페스트나 이미지에 비밀번호를 직접 입력하는 것보다 안전하지만, base64 인코딩은 실제 암호화가 아닙니다. 프로덕션 환경에서는 Secret 을 저장할 때 저장 데이터 암호화, 더 엄격한 RBAC, 외부 Secret 관리 시스템을 함께 사용하는 경우가 많습니다.

더미 비밀번호를 저장할 app-secret이라는 Secret 을 만듭니다.

kubectl create secret generic app-secret --from-literal=password=SuperSecretPass123

Secret 이 생성되었는지 확인합니다.

kubectl get secret app-secret

세부 내용을 확인해도 비밀번호가 그대로 표시되지는 않습니다. 비밀번호는 숨겨진 상태로 인코딩되어 있습니다.

kubectl get secret app-secret -o yaml

password 필드가 여러 문자가 뒤섞인 형태로 표시되는지 확인합니다. 이것은 base64 인코딩이며, 옆에서 내용을 훔쳐보거나 로그에 실수로 값이 표시되는 것을 방지하기 위한 방식입니다.

ConfigMap 을 파일로 마운트

이제 Pod 가 게시판의 내용을 읽도록 구성해 보겠습니다.

ConfigMap 을 사용하는 가장 일반적인 방법은 ConfigMap 을 파일로 마운트하는 것입니다. 그러면 컨테이너 안에서 일반 디스크 파일처럼 보입니다.

이 파일 기반 방식은 애플리케이션이 특정 경로에 있는 구성 파일을 이미 사용하도록 설계된 경우에 유용합니다. Kubernetes 는 ConfigMap 의 데이터를 컨테이너 파일 시스템에 배치하므로, 애플리케이션은 기존과 같은 방식으로 파일을 읽을 수 있습니다.

pod-config.yaml이라는 파일을 만듭니다.

nano pod-config.yaml

다음 내용을 붙여 넣습니다. 이 Pod 는 nginx-config ConfigMap 을 /etc/nginx/nginx.conf에 마운트합니다.

apiVersion: v1
kind: Pod
metadata:
  name: config-pod
spec:
  containers:
    - name: nginx
      image: nginx:alpine
      volumeMounts:
        - name: config-volume
          mountPath: /etc/nginx/nginx.conf
          subPath: nginx.conf
  volumes:
    - name: config-volume
      configMap:
        name: nginx-config

저장하고 종료합니다 (Ctrl+X, Y, Enter).

다음 명령으로 적용합니다.

kubectl apply -f pod-config.yaml

Pod 가 시작될 때까지 몇 초 기다립니다. 이제 컨테이너 내부에 파일이 있는지 확인합니다.

kubectl exec config-pod -- cat /etc/nginx/nginx.conf

직접 만든 구성이 표시되어야 합니다. Pod 가 게시판의 내용을 읽고 해당 파일을 사용한 것입니다.

Secret 을 환경 변수로 주입

이제 Secret 을 사용해 보겠습니다. 비밀번호를 전달하는 일반적인 방법은 환경 변수를 사용하는 것입니다.

이 방법은 편리하지만, 동시에 고려해야 할 점도 있습니다. 애플리케이션은 환경 변수를 쉽게 읽을 수 있지만, 진단 명령이나 프로세스 검사 과정에서 환경 변수가 노출될 수 있습니다. 애플리케이션마다 필요한 방식과 위험 수준이 다르므로 Kubernetes 는 파일 기반 주입과 환경 변수 주입을 모두 지원합니다.

pod-secret.yaml이라는 파일을 만듭니다.

nano pod-secret.yaml

다음 내용을 붙여 넣습니다. 이 Pod 는 app-secret에서 password 값을 가져와 APP_PASSWORD라는 환경 변수에 할당합니다.

apiVersion: v1
kind: Pod
metadata:
  name: secret-pod
spec:
  containers:
    - name: busybox
      image: busybox
      command: ["sleep", "3600"]
      env:
        - name: APP_PASSWORD
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: password

저장하고 종료합니다 (Ctrl+X, Y, Enter).

다음 명령으로 적용합니다.

kubectl apply -f pod-secret.yaml

Pod 가 실행되면 컨테이너 내부의 환경 변수를 확인합니다.

kubectl exec secret-pod -- env | grep APP_PASSWORD

APP_PASSWORD=SuperSecretPass123가 표시되어야 합니다.

여기서 중요한 점은 Pod 정의에 비밀번호가 포함되어 있지 않다는 것입니다. 비밀번호는 금고 (Secret) 에 저장되어 있고, Pod 는 실행 시 금고를 열 수 있는 키만 사용합니다.

요약

이 실습에서는 코드와 구성을 분리하는 방법을 연습했습니다.

다음 작업을 성공적으로 수행했습니다.

  1. ConfigMap(게시판) 을 사용하여 서버에 구성 파일을 주입했습니다.
  2. Secret(금고) 을 사용하여 애플리케이션에 숨겨진 비밀번호를 주입했습니다.

이제 Docker 이미지를 다시 빌드하지 않고도 구성을 업데이트하거나 비밀번호를 교체할 수 있습니다.