[MacOS 환경 #25] 쿠버네티스 Secret

도람·2025년 11월 27일
post-thumbnail

시크릿(Secret)이란?

쿠버네티스 시크릿(Secret)은
비밀번호, 토큰, 인증서 키처럼 민감한 데이터를 저장하기 위한 API 오브젝트이다.

컨테이너 이미지나 파드 매니페스트 안에 비밀번호를 그대로 적어두면,

  • 깃 저장소에 그대로 올라가고
  • CI/CD 로그나 kubectl describe 출력에도 노출되고
  • 여러 사람이 마음만 먹으면 쉽게 볼 수 있다는 문제가 있다.

시크릿을 쓰면 이런 민감한 값을 파드 스펙과 분리해서 별도 오브젝트로 관리할 수 있다.
파드는 시크릿을 환경 변수(env)나 볼륨(volume) 으로만 받아서 사용하고,
실제 값은 시크릿 오브젝트 안에만 들어 있는 구조이다.

기본적으로 시크릿의 data 필드는 Base64 인코딩 문자열로 저장된다.
(보안 암호화가 아니라 인코딩이기 때문에, etcd 암호화 같은 추가 보안 설정도 함께 고려해야 한다.)


왜 시크릿을 쓸까?

쿠버네티스 공식 문서 기준으로, 시크릿을 쓰는 이유는 대략 이렇게 정리할 수 있다.

  1. 코드/이미지에 비밀번호를 하드코딩하지 않기 위해
  • 파드 YAML, 깃 리포지토리, 도커 이미지 등 여러 곳에 비밀값이 섞이는 걸 막는다.
  1. 최소 권한(Least privilege) 적용이 쉬워진다
  • 특정 네임스페이스, 특정 서비스 계정만 시크릿을 읽게 RBAC로 제한할 수 있다.
  • 같은 클러스터라도, 이 시크릿이 필요한 파드만 접근 가능하다.
  1. 컨피그맵과 역할 분리
  • ConfigMap : 설정값, 옵션, 플래그 등 민감하지 않은 환경설정
  • Secret : 패스워드, API 토큰, TLS 키처럼 민감한 값
  • 두 개를 나눠 두면 운영할 때도 “절대 막 건드리면 안 되는 값”을 구분하기 쉽다.
  1. Immutable Secret 지원
  • immutable: true 를 켜두면 시크릿 내용을 수정할 수 없게 만들어서
    실수로 비밀번호를 갈아버리는 사고를 막을 수 있다.
  • immutable 시크릿은 워치 감시를 중단해서 kube-apiserver 부하도 줄여준다.

시크릿 타입 간단 정리

대표적인 타입은 다음과 같다. (공식 문서 기준 요약)

타입용도 (요약)
Opaque기본형. 임의의 키/값 데이터 저장
kubernetes.io/service-account-token서비스 어카운트 토큰
kubernetes.io/dockerconfigjson프라이빗 레지스트리 접속용 자격 증명
kubernetes.io/tlsTLS 인증서(tls.crt, tls.key) 저장

실습에서는 가장 흔한 Opaque 타입만 사용한다.


실습

이번 실습 흐름은 이렇게 3단계로 잡았다.

  1. 기본 시크릿 생성하기 (Opaque 타입)
  2. 시크릿을 env(환경 변수)로 주입해서 MySQL 컨테이너에 전달하기
  3. immutable 시크릿으로 바꿔서, 실수로 수정 못 하게 막아보기

1. 1단계. 기본 시크릿 생성 (Opaque)

먼저 MySQL 계정 정보를 담을 mysql-cred 시크릿을 만든다.

1) kubectl 로 시크릿 생성

kubectl create secret generic mysql-cred \
  --from-literal=username='db-user' \
  --from-literal=password='nh' \
  -n default

2) 생성 확인

kubectl get secret mysql-cred -n default
kubectl describe secret mysql-cred -n default

이렇게 mysql-cred로 시크릿이 생성된 것을 확인할 수 있다.


3) YAML 형태로 확인

kubectl get secret mysql-cred -n default -o yaml

필드 해석:

필드설명
typeOpaque = 기본 임의 데이터 시크릿
dataBase64 인코딩된 키-값 쌍
username키 이름. 값은 Base64 인코딩된 문자열

2. PVC 생성


kubectl get sc 해서 나오는 standard와 연결해주었다.

파일 명 : mysql-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi           
  storageClassName: standard 

pvc 적용

kubectl apply -f mysql-pvc.yaml
kubectl get pvc mysql-pvc


3. 시크릿을 env 로 주입해서 MySQL 컨테이너에 쓰기 (공식 이미지 사용)

이제 방금 만든 mysql-cred 시크릿을
Deployment 안 컨테이너 환경 변수로 주입해서 쓰는 실습이다.

시크릿 관련 부분만 핵심 위주로 정리했다.

파일명: mysql-deploy-with-secret.yaml

# 파일명: mysql-deploy-with-secret.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-with-secret
  labels:
    app: mysql-with-secret
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql-with-secret
  template:
    metadata:
      labels:
        app: mysql-with-secret
    spec:
      containers:
      - name: mysql
        image: mysql:8.0

        env:
        # 루트 계정 비밀번호 (예시라서 그냥 value 사용)
        - name: MYSQL_ROOT_PASSWORD
          value: rootpassword

        # 사용자 ID 를 Secret 에서 가져오기
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: mysql-cred    # 1단계에서 만든 Secret
              key: username       # db-user

        # 사용자 PW 를 Secret 에서 가져오기
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-cred    # 같은 Secret
              key: password       # nh

        # 자동으로 만들 DB 이름
        - name: MYSQL_DATABASE
          value: testdb

        ports:
        - containerPort: 3306

        volumeMounts:
        - name: mysql-pvc
          mountPath: /var/lib/mysql  # 데이터 파일 저장 위치

      volumes:
      - name: mysql-pvc
        persistentVolumeClaim:
          claimName: mysql-pvc       # 2단계에서 만든 pvc 이름

포인트 정리

  • env[*].valueFrom.secretKeyRef.name: mysql-cred
    → 1단계에서 만든 시크릿 객체 이름

  • key: username, key: password
    → 시크릿 안에 들어 있는 키 이름 (username=db-user, password=nh)

  • MySQL 공식 이미지는 아래 env 를 보고 초기 설정을 한다.

    • MYSQL_ROOT_PASSWORD
    • MYSQL_USER
    • MYSQL_PASSWORD
    • MYSQL_DATABASE

즉, 이 디플로이먼트를 생성하면

  • 루트 계정: root / rootpassword
  • 일반 계정: db-user / nh
  • DB: testdb

이런 조합으로 MySQL 이 한 번에 초기화된다.


적용&확인

# 디플로이 생성
kubectl apply -f mysql-deploy-with-secret.yaml

# 파드 상태 확인
kubectl get pods -l app=mysql-with-secret

이렇게 파드가 Running 이 되면 시크릿 + PVC 조합이 정상 동작 중인 것이다.


4.immutable 시크릿으로 바꿔보기

운영 환경에서는 실수로 시크릿 내용을 덮어쓰는 사고를 막고 싶을 때가 많다.
쿠버네티스는 이런 경우를 위해 immutable Secret 기능을 제공한다.

한 번 immutable 로 만들면, 내용을 수정할 수 없고 삭제 후 재생성만 가능하다.


4-1) 기존 시크릿을 immutable 로 변경

아래처럼 시크릿 정의에 immutable: true 를 추가해서 다시 적용할 수 있다.
(기존 시크릿을 kubectl apply 로 관리한다고 가정)

파일명: mysql-cred-immutable.yaml

# 파일명: mysql-cred-immutable.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysql-cred
  namespace: default
type: Opaque
immutable: true
data:
  username: ZGItdXNlcg==   # db-user (Base64)
  password: bmg=           # nh (Base64)

이미 kubectl create secret ... 로 만들어둔 시크릿이 있으니까,
위 YAML 을 저장한 다음 그대로 apply 하면 된다.

kubectl apply -f mysql-cred-immutable.yaml

배포를 하게 되면 이렇게 warning 메세지가 뜨게 된다.
메세지를 해석해보면 다음과 같다.

“이 시크릿은 immutable 이라서 내용(data)을 바꿀 수 없다.
바꾸고 싶으면 시크릿을 삭제하고 새로 만들어라.”

kubectl describe secret mysql-cred -n default

describe로 확인해보면,

비밀번호가 바뀌지 않은 것을 확인할 수 있다.

실제 운영에서는:

  • 비밀번호를 실수로 바꾸면 안 되는 시크릿
  • 여러 환경(운영/스테이징)에서 절대 값이 바뀌면 안 되는 토큰

등에 immutable 을 걸어두면, 사람 실수로 인한 장애를 줄이는 데 도움이 된다.


전체 정리

단계내용핵심 포인트
1mysql-cred 시크릿 생성Opaque 타입, username/password 저장
2mysql-pvc 생성MySQL 데이터 저장용 PVC, SC=standard
3mysql-with-secret 디플로이 생성Secret 을 env 로 주입, MySQL 초기화
4시크릿에 immutable: true 설정이후 내용 수정 불가, 삭제 후 재생성만 가능
  • ConfigMap : 민감하지 않은 설정 값
  • Secret : 비밀번호, 토큰, 인증서 등 민감한 값
  • Secret 은 env / volume 으로 파드에 전달할 수 있고,
    공식 MySQL 이미지처럼 “환경 변수 기반 설정”을 쓰는 컨테이너와 궁합이 좋다.
  • immutable: true 를 쓰면 중요한 시크릿을 보호할 수 있다.


참고자료:
[쿠버네티스 공식 문서 – Secret]
https://kubernetes.io/docs/concepts/configuration/secret/?utm_source=chatgpt.com
[쿠버네티스 공식 문서 – Distribute Credentials Securely Using Secrets]
https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials-secure/?utm_source=chatgpt.com

profile
정도를 걷는 엔지니어

0개의 댓글