본문 바로가기

CKA

[k8s] Secret 정리 (ConfigMap 차이)

728x90
반응형

개요

Kubernetes를 쓰다 보면 "설정값을 Pod에 어떻게 안전하게 전달하지?"라는 상황이 자주 생긴다.

이때 사용하는 대표 리소스가 ConfigMap과 Secret인데, 둘은 주입 방식(Env/Volume)이 거의 동일하지만 저장하는 데이터 성격과 보안 관점에서 중요한 차이가 있다.

1. Secret이란?

Secret은 비밀번호, 토큰, 인증서 같은 "민감한 값"을 Kubernetes 리소스로 저장하고 Pod에 주입하는 방식이다.

 

예를 들어 아래 같은 값들이 Secret으로 관리된다.

  • DB 계정/비밀번호
  • API Key / Access Token
  • TLS 인증서 / 개인키
  • Docker Registry 로그인 정보

즉, Secret의 역할은 간단히 말해:

"민감한 설정값을 클러스터에 저장해두고, 필요한 Pod에만 전달해서 사용하게 한다."

2. Secret vs ConfigMap, 같은 원리인가?

  • Pod에 주입하는 방식은 거의 동일하다
    • 환경변수(env)
    • envFrom(여러 키를 한번에)
    • 볼륨(volume) 마운트

하지만 차이가 있다.

(1) 용도 차이

  • ConfigMap: 비민감 설정값(URL, 로그레벨, feature flag 등)
  • Secret: 민감 정보 (비번, 토큰, 키, 인증서 등)

(2) data 저장 방식

  • ConfigMap은 문자열 그대로 저장
  • Secret은 data: 에 base64 인코딩된 값으로 저장하는 경우가 많다.

⚠️ 여기서 중요한 포인트:

→ base64는 "암호화"가 아니다. 단순 인코딩이라 복호화가 매우 쉽다.

따라서 Secret이 "자동으로 안전해지는 것"은 아니고, 운영 환경에서는 보안 설정이 함께 따라와야 한다.

 

(3) 보안 관점 차이

Secret을 제대로 쓰려면 아래를 함께 고려해야 한다.

  • RBAC로 Secret 접근 최소화
    • 불필요한 사용자/서비스계정에 secret get/list 권한 주지 않기
  • 가능하면 etcd Encryption at rest 적용 (클러스터 설정)
  • Pod에 필요한 Secret만 주입하기

3.  Secret 종류 (자주 쓰는 타입)

  • Opaque: 일반 Key-Value Secret (가장 흔함)
  • kubernetes.io/tls: TLS 인증서/키 (tls.crt, tls.key)
  • kubernetes.io/dockerconfigjson: Docker registry 인증 정보

4. 실습: Secret 생성 & Pod에 주입하기

실습은 아래 4단계로 진행한다.

1. Namespace 생성

2. Opaque Secret 생성

3. 환경변수로 주입

4. 볼륨으로 마운트

 

4.1 Namespace 생성

kubectl create ns secret-lab
kubectl config set-context --current --namespace=secret-lab

 

4.2 Secret 생성 (Opaque)

방법 A) YAML로 생성

먼저 base64 만들기(macOS):

echo -n 'hrlab' | base64
echo -n 'P@ssw0rd-123' | base64

 

그 결과를 data에 넣기:

apiVersion: v1
kind: Secret
metadata:
  name: app-secret
  namespace: secret-lab
type: Opaque
data:
  db_user: aHJsYWI=
  db_password: UEBzc3cwcmQtMTIz

 

방법 B) 명령어로 생성

리터럴 값으로 Secret을 생성한다.

kubectl create secret generic app-secret \
  --from-literal=db_user=hrlab \
  --from-literal=db_password='P@ssw0rd-123'

 

확인:

kubectl get secret
kubectl describe secret app-secret
  • describe에서 실제 값이 안나오고 key 목록/크기만 출력된다.

학습용으로 실제 값을 확인해보면:

kubectl get secret app-secret -o jsonpath='{.data.db_user}' | base64 --decode; echo
kubectl get secret app-secret -o jsonpath='{.data.db_password}' | base64 --decode; echo

 

4.3 Pod에 Secret 주입: 환경변수 방식

secretKeyRef로 특정 key를 환경변수로 주입한다.

apiVersion: v1
kind: Pod
metadata:
  name: env-secret-pod
spec:
  containers:
  - name: app
    image: busybox:1.36
    command: ["sh", "-c", "env | sort; sleep 3600"]
    env:
    - name: DB_USER
      valueFrom:
        secretKeyRef:
          name: app-secret
          key: db_user
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: app-secret
          key: db_password

 

적용:

kubectl apply -f pod-env-secret.yaml
kubectl get pod env-secret-pod -w
kubectl logs env-secret-pod | grep -E 'DB_USER|DB_PASSWORD'

✅ 로그에 DB_USER, DB_PASSWORD가 보이면 성공.

참고: 환경변수는 편하지만, 디버깅/덤프/로그 등으로 노출될 여지가 있어
보안이 특히 중요한 값은 볼륨 마운트(파일) 방식을 선호하기도 한다.

 

4.4 Pod에 Secret 주입: 볼륨(파일) 마운트 방식

Secret을 볼륨으로 마운트하면 /etc/secret 아래에 key 이름 그대로 파일이 생성된다.

apiVersion: v1
kind: Pod
metadata:
  name: vol-secret-pod
spec:
  containers:
  - name: app
    image: busybox:1.36
    command: ["sh", "-c", "ls -l /etc/secret && sleep 3600"]
    volumeMounts:
    - name: secret-vol
      mountPath: /etc/secret
      readOnly: true
  volumes:
  - name: secret-vol
    secret:
      secretName: app-secret

 

적용 및 확인:

kubectl apply -f pod-vol-secret.yaml
kubectl get pod vol-secret-pod -w
kubectl exec -it vol-secret-pod -- sh
# inside container
ls -l /etc/secret
cat /etc/secret/db_user
cat /etc/secret/db_password

✅ 파일이 생성되고 값이 읽히면 성공.

728x90
반응형