이 글에서는 쿠버네티스 Secret을 활용하여 MinIO의 민감한 자격 증명 정보를 안전하게 관리하는 방법에 대해 알아보겠습니다. 보안 모범 사례와 함께 실제 구현 방법을 상세히 설명합니다.
📌 쿠버네티스 Secret 개념 이해하기
✅ Secret이란 무엇인가?
Secret은 비밀번호, API 키, 인증서와 같은 민감한 정보를 저장하기 위한 쿠버네티스 리소스입니다. ConfigMap과 유사하지만 보안에 중점을 둔 리소스입니다.
▶️ Secret의 주요 특징:
- 민감 데이터를 저장하도록 설계됨
- Base64 인코딩으로 저장 (암호화는 아님)
- etcd에 저장될 때 암호화 가능 (추가 구성 필요)
- 메모리에만 마운트 가능 (tmpfs)
- Pod 간 공유 제한 가능
apiVersion: v1 # 핵심 API 그룹의 v1 버전, Secret은 쿠버네티스 핵심 리소스이므로 v1 사용
kind: Secret # 리소스 종류는 Secret으로, 민감한 정보를 저장하기 위한 전용 리소스
metadata:
name: minio-creds # Secret 이름, Pod에서 이 이름으로 Secret을 참조하므로 명확하게 지정
namespace: minio-system # Secret이 속한 네임스페이스, MinIO가 배포된 네임스페이스와 동일하게 설정해야 접근 가능
type: Opaque # Secret 유형을 Opaque로 지정, 일반적인 키-값 쌍 데이터에 적합한 기본 유형
data:
# Base64 인코딩된 데이터 (echo -n "minio" | base64)
root-user: bWluaW8= # MinIO 루트 사용자명을 Base64로 인코딩한 값, 평문은 "minio"
# Base64 인코딩된 데이터 (echo -n "minio123" | base64)
root-password: bWluaW8xMjM= # MinIO 루트 비밀번호를 Base64로 인코딩한 값, 평문은 "minio123"
✅ Secret vs ConfigMap
Secret과 ConfigMap의 차이점과 각각의 사용 사례를 이해합시다.
특성 | Secret | ConfigMap |
용도 | 민감한 데이터 | 일반 구성 데이터 |
인코딩 | Base64 인코딩 | 평문 |
크기 제한 | 1MB | 1MB |
접근 제어 | 더 세밀하게 제어 가능 | 기본 RBAC |
암호화 | etcd 암호화 지원 | 암호화 없음 |
▶️ Secret 사용 사례:
- 비밀번호, API 키
- TLS 인증서 및 키
- OAuth 토큰
- SSH 키
▶️ ConfigMap 사용 사례:
- 애플리케이션 설정 파일
- 환경별 설정
- 명령줄 인수
- 포트 번호, 리소스 제한
📌 Secret 생성 방법
✅ 명령형 방식으로 Secret 생성
kubectl 명령어를 사용하여 Secret을 생성하는 방법입니다.
# 리터럴 값으로 Secret 생성
kubectl create secret generic minio-creds \
--from-literal=root-user=minio \
--from-literal=root-password=minio123 \
--namespace minio-system
# 파일에서 Secret 생성
echo -n "minio" > ./root-user.txt
echo -n "minio123" > ./root-password.txt
kubectl create secret generic minio-creds \
--from-file=root-user=./root-user.txt \
--from-file=root-password=./root-password.txt \
--namespace minio-system
✅ 선언형 방식으로 Secret 생성
YAML 파일로 Secret을 정의하고 적용하는 방법입니다.
apiVersion: v1 # 핵심 API 그룹의 v1 버전, Secret은 기본 리소스 타입
kind: Secret # 리소스 종류는 Secret
metadata:
name: minio-creds # Secret 이름, 나중에 이 이름으로 참조
namespace: minio-system # Secret이 속한 네임스페이스
type: Opaque # 일반적인 키-값 쌍에 사용되는 기본 Secret 타입
stringData: # stringData 필드는 자동으로 Base64 인코딩됨, 평문을 직접 입력할 때 사용
root-user: minio # MinIO 루트 사용자 이름, 평문으로 입력하면 쿠버네티스가 자동 인코딩
root-password: minio123 # MinIO 루트 비밀번호, 평문으로 입력하면 쿠버네티스가 자동 인코딩
# YAML 파일 적용
kubectl apply -f minio-secret.yaml
✅ 다양한 Secret 타입
쿠버네티스는 여러 유형의 Secret을 지원합니다.
- Opaque: 기본 유형, 임의의 키-값 쌍 저장
- kubernetes.io/tls: TLS 인증서 및 키 저장
- kubernetes.io/dockerconfigjson: Docker 레지스트리 자격 증명
- kubernetes.io/service-account-token: 서비스 어카운트 토큰
- kubernetes.io/ssh-auth: SSH 인증 키
# TLS Secret 예시
apiVersion: v1 # 핵심 API 그룹의 v1 버전
kind: Secret # 리소스 종류는 Secret
metadata:
name: minio-tls # TLS 인증서를 위한 Secret 이름
namespace: minio-system # Secret이 속한 네임스페이스
type: kubernetes.io/tls # TLS 타입 Secret, 인증서와 키를 저장하기 위한 특별한 형식
data:
tls.crt: base64_encoded_cert # TLS 인증서 데이터, Base64로 인코딩됨
tls.key: base64_encoded_key # TLS 개인 키 데이터, Base64로 인코딩됨
# TLS Secret 생성 (인증서 파일 사용)
kubectl create secret tls minio-tls \
--cert=path/to/cert.pem \
--key=path/to/key.pem \
--namespace minio-system
📌 MinIO에서 Secret 활용하기
✅ 환경 변수로 Secret 사용
MinIO Deployment에서 Secret을 환경 변수로 사용하는 방법입니다.
apiVersion: apps/v1 # 앱 API 그룹의 v1 버전, Deployment는 apps API 그룹에 속함
kind: Deployment # 리소스 종류는 Deployment, Pod의 복제본을 관리하는 컨트롤러
metadata:
name: minio # Deployment 이름
namespace: minio-system # Deployment가 속한 네임스페이스
spec:
selector:
matchLabels:
app: minio # Pod 선택자, 이 라벨을 가진 Pod를 관리
replicas: 1 # 복제본 수, MinIO 단일 인스턴스 배포
template:
metadata:
labels:
app: minio # Pod 라벨, selector의 matchLabels와 일치해야 함
spec:
containers:
- name: minio # 컨테이너 이름
image: minio/minio:RELEASE.2023-07-21T21-12-44Z # MinIO 이미지 버전, 안정적인 특정 버전 사용
args:
- server # MinIO 서버 모드로 실행
- /data # 데이터 저장 경로
env:
- name: MINIO_ROOT_USER # MinIO 루트 사용자 환경 변수 이름
valueFrom:
secretKeyRef:
name: minio-creds # 참조할 Secret 이름
key: root-user # Secret에서 가져올 키 이름
- name: MINIO_ROOT_PASSWORD # MinIO 루트 비밀번호 환경 변수 이름
valueFrom:
secretKeyRef:
name: minio-creds # 참조할 Secret 이름
key: root-password # Secret에서 가져올 키 이름
ports:
- containerPort: 9000 # MinIO API 포트
name: api # 포트 이름
- containerPort: 9001 # MinIO 콘솔 포트
name: console # 포트 이름
✅ 볼륨으로 Secret 마운트
Secret을 볼륨으로 마운트하여 파일 시스템을 통해 접근하는 방법입니다.
apiVersion: apps/v1 # 앱 API 그룹의 v1 버전, StatefulSet은 apps API 그룹에 속함
kind: StatefulSet # 리소스 종류는 StatefulSet, 상태 유지가 필요한 애플리케이션에 적합
metadata:
name: minio # StatefulSet 이름
namespace: minio-system # StatefulSet이 속한 네임스페이스
spec:
serviceName: minio-headless # 헤드리스 서비스 이름, StatefulSet에 필수 필드
replicas: 1 # 복제본 수
selector:
matchLabels:
app: minio # Pod 선택자
template:
metadata:
labels:
app: minio # Pod 라벨
spec:
containers:
- name: minio # 컨테이너 이름
image: minio/minio:RELEASE.2023-07-21T21-12-44Z # MinIO 이미지
args:
- server # 서버 모드
- /data # 데이터 경로
env:
- name: MINIO_ROOT_USER # 환경 변수로 사용자 이름 지정
valueFrom:
secretKeyRef:
name: minio-creds # Secret 이름
key: root-user # 키 이름
- name: MINIO_ROOT_PASSWORD # 환경 변수로 비밀번호 지정
valueFrom:
secretKeyRef:
name: minio-creds # Secret 이름
key: root-password # 키 이름
volumeMounts:
- name: data # 데이터 볼륨 이름
mountPath: /data # 마운트 경로
- name: minio-config # 설정 볼륨 이름
mountPath: /root/.minio/ # MinIO 설정 디렉토리
- name: credentials # 자격 증명 볼륨 이름
mountPath: /etc/credentials # 자격 증명 마운트 경로
readOnly: true # 읽기 전용으로 마운트, 보안 강화
volumes:
- name: credentials # 자격 증명 볼륨 정의
secret:
secretName: minio-creds # 사용할 Secret 이름
items: # Secret의 특정 키만 선택적으로 마운트
- key: root-user # Secret의 키
path: access-key # 마운트될 파일 이름
- key: root-password # Secret의 키
path: secret-key # 마운트될 파일 이름
- name: minio-config # 설정 볼륨 정의
emptyDir: {} # 임시 볼륨
volumeClaimTemplates: # 영구 볼륨 클레임 템플릿
- metadata:
name: data # 볼륨 이름
spec:
accessModes: [ "ReadWriteOnce" ] # 접근 모드
resources:
requests:
storage: 10Gi # 요청 스토리지 크기
✅ MinIO 액세스 키 관리
MinIO용 액세스 키와 시크릿 키를 Secret으로 관리하는 방법입니다.
apiVersion: v1 # 핵심 API 그룹의 v1 버전
kind: Secret # 리소스 종류는 Secret
metadata:
name: minio-user1-creds # 특정 사용자를 위한 Secret 이름
namespace: minio-system # Secret이 속한 네임스페이스
labels:
app: minio # Secret 라벨, 관리 용이성을 위한 라벨링
user: user1 # 사용자 식별 라벨
type: Opaque # 일반 Secret 타입
stringData: # 자동 Base64 인코딩되는 평문 데이터
access-key: user1 # 사용자 액세스 키
secret-key: user1password # 사용자 시크릿 키
MinIO의 액세스 키를 초기화하는 Job 예시:
apiVersion: batch/v1 # 배치 API 그룹의 v1 버전, Job은 배치 워크로드를 위한 리소스
kind: Job # 리소스 종류는 Job, 일회성 작업을 실행하는 컨트롤러
metadata:
name: minio-create-user # Job 이름
namespace: minio-system # Job이 속한 네임스페이스
spec:
template:
spec:
restartPolicy: OnFailure # 실패 시 재시작 정책
containers:
- name: mc # 컨테이너 이름
image: minio/mc:latest # MinIO 클라이언트 이미지
command: ["/bin/sh", "-c"] # 실행할 명령
args:
- |
# MinIO 서버에 연결
mc alias set myminio http://minio:9000 $MINIO_ROOT_USER $MINIO_ROOT_PASSWORD
# 새 사용자 생성
mc admin user add myminio $USER_ACCESS_KEY $USER_SECRET_KEY
# 정책 설정 (읽기 전용 예시)
mc admin policy set myminio readwrite user=$USER_ACCESS_KEY
env:
- name: MINIO_ROOT_USER # 루트 사용자 환경 변수
valueFrom:
secretKeyRef:
name: minio-creds # Secret 이름
key: root-user # 키 이름
- name: MINIO_ROOT_PASSWORD # 루트 비밀번호 환경 변수
valueFrom:
secretKeyRef:
name: minio-creds # Secret 이름
key: root-password # 키 이름
- name: USER_ACCESS_KEY # 새 사용자 액세스 키
valueFrom:
secretKeyRef:
name: minio-user1-creds # 사용자 Secret 이름
key: access-key # 키 이름
- name: USER_SECRET_KEY # 새 사용자 시크릿 키
valueFrom:
secretKeyRef:
name: minio-user1-creds # 사용자 Secret 이름
key: secret-key # 키 이름
📌 Secret 보안 강화 방법
✅ etcd 암호화 설정
쿠버네티스 etcd 데이터베이스에서 Secret 데이터를 암호화하는 방법입니다.
- 암호화 구성 파일 생성:
# encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1 # API 서버 구성 API 그룹 버전
kind: EncryptionConfiguration # 리소스 종류는 EncryptionConfiguration, API 서버 암호화 설정
resources:
- resources:
- secrets # 암호화할 리소스 유형, Secret만 암호화
providers:
- aescbc: # AES-CBC 암호화 프로바이더, 강력한 암호화 알고리즘
keys:
- name: key1 # 키 이름
secret: <base64-encoded-key> # Base64로 인코딩된 32바이트 암호화 키
- identity: {} # Identity 프로바이더, 암호화하지 않음 (fallback)
- kube-apiserver 구성 업데이트:
# API 서버에 암호화 설정 적용 (kubeadm 설치의 경우)
sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
# 다음 줄 추가 (spec.containers[].command 아래)
- --encryption-provider-config=/etc/kubernetes/encryption-config.yaml
# 볼륨 마운트 추가
volumeMounts:
- name: encryption-config
mountPath: /etc/kubernetes/encryption-config.yaml
readOnly: true
# 볼륨 정의 추가
volumes:
- name: encryption-config
hostPath:
path: /etc/kubernetes/encryption-config.yaml
type: File
- 기존 Secret 재암호화:
# 모든 Secret 목록 가져오기
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
✅ RBAC를 통한 Secret 접근 제어
RBAC(Role-Based Access Control)를 사용하여 Secret에 대한 접근을 제한하는 방법입니다.
apiVersion: rbac.authorization.k8s.io/v1 # RBAC API 그룹의 v1 버전
kind: Role # 리소스 종류는 Role, 네임스페이스 범위의 권한 집합
metadata:
name: minio-secrets-reader # Role 이름
namespace: minio-system # Role이 속한 네임스페이스
rules:
- apiGroups: [""] # 핵심 API 그룹
resources: ["secrets"] # Secret 리소스에 대한 권한
resourceNames: ["minio-creds"] # 특정 Secret 이름으로 범위 제한
verbs: ["get", "watch", "list"] # 허용할 동작, 읽기 전용 권한만 부여
---
apiVersion: rbac.authorization.k8s.io/v1 # RBAC API 그룹의 v1 버전
kind: RoleBinding # 리소스 종류는 RoleBinding, Role과 사용자/그룹/서비스어카운트 연결
metadata:
name: read-minio-secrets # RoleBinding 이름
namespace: minio-system # RoleBinding이 속한 네임스페이스
subjects:
- kind: ServiceAccount # 권한 부여 대상 종류
name: minio-operator # 권한을 부여할 ServiceAccount 이름
namespace: minio-system # ServiceAccount가 속한 네임스페이스
roleRef:
kind: Role # 참조할 권한 종류
name: minio-secrets-reader # 참조할 Role 이름
apiGroup: rbac.authorization.k8s.io # Role이 속한 API 그룹
✅ Secret 불변성 설정
불변 Secret을 사용하여 수정을 방지하는 방법입니다.
apiVersion: v1 # 핵심 API 그룹의 v1 버전
kind: Secret # 리소스 종류는 Secret
metadata:
name: minio-creds-immutable # Secret 이름
namespace: minio-system # Secret이 속한 네임스페이스
annotations:
reflector.v1.k8s.emberstack.com/reflection-allowed: "false" # 외부 도구를 통한 반영 방지
immutable: true # 불변성 설정, 생성 후 변경 불가능하게 만듦
type: Opaque # 일반 Secret 타입
data:
root-user: bWluaW8= # Base64로 인코딩된 루트 사용자 이름
root-password: bWluaW8xMjM= # Base64로 인코딩된 루트 비밀번호
📌 Sealed Secrets와 외부 시크릿 관리
✅ Sealed Secrets 소개
Bitnami Sealed Secrets를 사용하여 Git에 안전하게 Secret을 저장하는 방법입니다.
# Sealed Secrets 컨트롤러 설치
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.19.4/controller.yaml
# kubeseal CLI 설치 (Mac)
brew install kubeseal
# 기존 Secret을 Sealed Secret으로 변환
kubectl create secret generic minio-creds \
--from-literal=root-user=minio \
--from-literal=root-password=minio123 \
--namespace minio-system \
--dry-run=client -o yaml | \
kubeseal --format yaml > sealed-minio-creds.yaml
생성된 Sealed Secret 예시:
apiVersion: bitnami.com/v1alpha1 # Bitnami API 그룹, Sealed Secrets 전용 API
kind: SealedSecret # 리소스 종류는 SealedSecret, 암호화된 Secret
metadata:
name: minio-creds # SealedSecret 이름, 복호화 후 생성될 Secret 이름과 동일
namespace: minio-system # SealedSecret이 속한 네임스페이스
spec:
encryptedData: # 암호화된 데이터, 클러스터 내 Sealed Secrets 컨트롤러만 복호화 가능
root-password: AgBy8hCL... # 암호화된 비밀번호 데이터
root-user: AgBd42fX... # 암호화된 사용자 이름 데이터
template:
metadata:
name: minio-creds # 생성될 Secret 이름
namespace: minio-system # 생성될 Secret 네임스페이스
type: Opaque # Secret 타입
✅ 외부 시크릿 관리 도구
외부 시크릿 관리 도구를 쿠버네티스와 통합하는 방법입니다.
- External Secrets Operator:
apiVersion: external-secrets.io/v1beta1 # External Secrets API 그룹
kind: ExternalSecret # 리소스 종류는 ExternalSecret, 외부 시크릿 참조
metadata:
name: minio-external-secret # ExternalSecret 이름
namespace: minio-system # ExternalSecret이 속한 네임스페이스
spec:
refreshInterval: 1h # 새로고침 간격, 1시간마다 외부 소스에서 시크릿 가져옴
secretStoreRef:
name: aws-secretsmanager # SecretStore 참조, 외부 시크릿 제공자 정보
kind: ClusterSecretStore # SecretStore 종류, 클러스터 전체 범위
target:
name: minio-creds # 생성될 Secret 이름
creationPolicy: Owner # 생성 정책, 없으면 생성하고 있으면 관리
data:
- secretKey: root-user # Secret에 저장될 키 이름
remoteRef:
key: minio/credentials # 외부 시크릿 저장소의 키 경로
property: username # 해당 키의 특정 속성 (JSON 필드 등)
- secretKey: root-password # Secret에 저장될 키 이름
remoteRef:
key: minio/credentials # 외부 시크릿 저장소의 키 경로
property: password # 해당 키의 특정 속성
- HashiCorp Vault 통합:
apiVersion: secrets.hashicorp.com/v1beta1 # HashiCorp Secrets API 그룹
kind: VaultSecret # 리소스 종류는 VaultSecret, Vault 시크릿 참조
metadata:
name: minio-vault-secret # VaultSecret 이름
namespace: minio-system # VaultSecret이 속한 네임스페이스
spec:
vaultAuthRef: vault-auth # Vault 인증 참조
mount: secret # Vault 시크릿 엔진 마운트 경로
path: minio # Vault 내 시크릿 경로
destination:
name: minio-creds # 생성될 Secret 이름
create: true # Secret이 없으면 생성
type: Opaque # Secret 타입
refreshAfter: 1h # 새로고침 간격
data:
- key: credentials # Vault 내 키 이름
property: username # 해당 키의 특정 속성
secretKey: root-user # Secret에 저장될 키 이름
- key: credentials # Vault 내 키 이름
property: password # 해당 키의 특정 속성
secretKey: root-password # Secret에 저장될 키 이름
📌 MinIO 자격 증명 순환
✅ 자격 증명 순환 전략
MinIO 자격 증명을 안전하게 순환(변경)하는 전략입니다.
▶️ 자격 증명 순환 단계:
- 새 Secret 생성
- 새 자격 증명을 MinIO에 적용
- 애플리케이션 구성 업데이트
- 이전 자격 증명 비활성화
- 검증 후 이전 Secret 삭제
apiVersion: v1 # 핵심 API 그룹의 v1 버전
kind: Secret # 리소스 종류는 Secret
metadata:
name: minio-creds-new # 새 Secret 이름, 버전 또는 날짜 포함 가능
namespace: minio-system # Secret이 속한 네임스페이스
labels:
app: minio # 애플리케이션 라벨
version: "v2" # 버전 라벨, 자격 증명 버전 추적
type: Opaque # 일반 Secret 타입
stringData: # 자동 Base64 인코딩되는 평문 데이터
root-user: minio # 새 루트 사용자 이름 (또는 변경된 값)
root-password: minio123new # 새 루트 비밀번호, 보안 강화를 위해 복잡한 값 사용
자격 증명 순환을 위한 Job 예시:
apiVersion: batch/v1 # 배치 API 그룹의 v1 버전
kind: Job # 리소스 종류는 Job, 일회성 작업 실행
metadata:
name: minio-credential-rotation # Job 이름
namespace: minio-system # Job이 속한 네임스페이스
spec:
template:
spec:
restartPolicy: OnFailure # 실패 시 재시작 정책
containers:
- name: mc # 컨테이너 이름
image: minio/mc:latest # MinIO 클라이언트 이미지
command: ["/bin/sh", "-c"] # 실행할 명령
args:
- |
# 현재 자격 증명으로 MinIO 서버에 연결
mc alias set myminio http://minio:9000 $CURRENT_ROOT_USER $CURRENT_ROOT_PASSWORD
# 루트 사용자 비밀번호 변경
mc admin user add myminio $NEW_ROOT_USER $NEW_ROOT_PASSWORD --update
# 연결 테스트
sleep 5 # 변경사항이 적용될 시간 대기
mc alias set myminio-new http://minio:9000 $NEW_ROOT_USER $NEW_ROOT_PASSWORD
mc ls myminio-new
echo "Credential rotation completed successfully"
env:
- name: CURRENT_ROOT_USER # 현재 루트 사용자 환경 변수
valueFrom:
secretKeyRef:
name: minio-creds # 현재 Secret 이름
key: root-user # 키 이름
- name: CURRENT_ROOT_PASSWORD # 현재 루트 비밀번호 환경 변수
valueFrom:
secretKeyRef:
name: minio-creds # 현재 Secret 이름
key: root-password # 키 이름
- name: NEW_ROOT_USER # 새 루트 사용자 환경 변수
valueFrom:
secretKeyRef:
name: minio-creds-new # 새 Secret 이름
key: root-user # 키 이름
- name: NEW_ROOT_PASSWORD # 새 루트 비밀번호 환경 변수
valueFrom:
secretKeyRef:
name: minio-creds-new # 새 Secret 이름
key: root-password # 키 이름
✅ 애플리케이션 재구성 없는 자격 증명 순환
애플리케이션을 재시작하지 않고 자격 증명을 순환하는 방법입니다.
apiVersion: v1 # 핵심 API 그룹의 v1 버전
kind: ConfigMap # 리소스 종류는 ConfigMap, 비민감 구성 데이터 저장
metadata:
name: credential-updater # ConfigMap 이름
namespace: minio-system # ConfigMap이 속한 네임스페이스
data:
update-script.sh: | # 스크립트 파일 내용
#!/bin/sh
# 자격 증명 순환 스크립트
NEW_CREDS_DIR=/new-creds
CREDS_DIR=/credentials
# 새 자격 증명 파일 복사
cp $NEW_CREDS_DIR/* $CREDS_DIR/
# MinIO 프로세스에 SIGHUP 시그널 전송하여 설정 다시 로드
pkill -SIGHUP minio
echo "Credentials updated at $(date)"
apiVersion: batch/v1 # 배치 API 그룹의 v1 버전
kind: Job # 리소스 종류는 Job
metadata:
name: in-place-credential-update # Job 이름
namespace: minio-system # Job이 속한 네임스페이스
spec:
template:
spec:
restartPolicy: OnFailure # 실패 시 재시작 정책
serviceAccountName: minio-updater # 권한 있는 ServiceAccount 사용
containers:
- name: updater # 컨테이너 이름
image: busybox:latest # 경량 기본 이미지
command: ["/bin/sh", "/scripts/update-script.sh"] # 실행할 명령
volumeMounts:
- name: scripts # 스크립트 볼륨
mountPath: /scripts # 마운트 경로
- name: new-credentials # 새 자격 증명 볼륨
mountPath: /new-creds # 마운트 경로
- name: minio-credentials # MinIO 자격 증명 볼륨
mountPath: /credentials # 마운트 경로
volumes:
- name: scripts # 스크립트 볼륨 정의
configMap:
name: credential-updater # 사용할 ConfigMap
defaultMode: 0755 # 실행 권한 부여
- name: new-credentials # 새 자격 증명 볼륨 정의
secret:
secretName: minio-creds-new # 새 Secret 이름
- name: minio-credentials # MinIO 자격 증명 볼륨 정의
persistentVolumeClaim:
claimName: minio-credentials-pvc # MinIO가 사용하는 PVC
📌 최소 권한 원칙 적용
✅ 서비스 계정과 최소 권한
최소 권한 원칙을 적용하여 MinIO 관련 서비스 계정을 설정하는 방법입니다.
apiVersion: v1 # 핵심 API 그룹의 v1 버전
kind: ServiceAccount # 리소스 종류는 ServiceAccount, Pod가 사용할 신원
metadata:
name: minio-sa # ServiceAccount 이름
namespace: minio-system # ServiceAccount가 속한 네임스페이스
---
apiVersion: rbac.authorization.k8s.io/v1 # RBAC API 그룹의 v1 버전
kind: Role # 리소스 종류는 Role, 네임스페이스 범위의 권한 집합
metadata:
name: minio-role # Role 이름
namespace: minio-system # Role이 속한 네임스페이스
rules:
- apiGroups: [""] # 핵심 API 그룹
resources: ["secrets"] # Secret 리소스에 대한 권한
resourceNames: ["minio-creds"] # 특정 Secret으로 범위 제한
verbs: ["get"] # 허용할 동작, 읽기만 가능
- apiGroups: [""] # 핵심 API 그룹
resources: ["services"] # Service 리소스에 대한 권한
verbs: ["get", "list"] # 허용할 동작, 읽기만 가능
---
apiVersion: rbac.authorization.k8s.io/v1 # RBAC API 그룹의 v1 버전
kind: RoleBinding # 리소스 종류는 RoleBinding, Role과 ServiceAccount 연결
metadata:
name: minio-rolebinding # RoleBinding 이름
namespace: minio-system # RoleBinding이 속한 네임스페이스
subjects:
- kind: ServiceAccount # 권한 부여 대상 종류
name: minio-sa # 권한을 부여할 ServiceAccount 이름
namespace: minio-system # ServiceAccount가 속한 네임스페이스
roleRef:
kind: Role # 참조할 권한 종류
name: minio-role # 참조할 Role 이름
apiGroup: rbac.authorization.k8s.io # Role이 속한 API 그룹
MinIO Deployment에 서비스 계정 적용:
apiVersion: apps/v1 # 앱 API 그룹의 v1 버전
kind: Deployment # 리소스 종류는 Deployment
metadata:
name: minio # Deployment 이름
namespace: minio-system # Deployment가 속한 네임스페이스
spec:
# ... 다른 필드 생략 ...
template:
spec:
serviceAccountName: minio-sa # 사용할 ServiceAccount 지정, 최소 권한 원칙 적용
# ... 다른 필드 생략 ...
✅ Pod 보안 컨텍스트 설정
Secret을 사용하는 Pod의 보안을 강화하는 방법입니다.
apiVersion: apps/v1 # 앱 API 그룹의 v1 버전
kind: Deployment # 리소스 종류는 Deployment
metadata:
name: minio-secure # Deployment 이름
namespace: minio-system # Deployment가 속한 네임스페이스
spec:
# ... 다른 필드 생략 ...
template:
spec:
serviceAccountName: minio-sa # 사용할 ServiceAccount
securityContext: # Pod 수준 보안 컨텍스트
fsGroup: 1000 # 파일 시스템 그룹 ID, 볼륨 마운트 권한 설정
runAsNonRoot: true # 루트가 아닌 사용자로 실행
runAsUser: 1000 # 사용자 ID 1000으로 실행
containers:
- name: minio # 컨테이너 이름
# ... 다른 필드 생략 ...
securityContext: # 컨테이너 수준 보안 컨텍스트
allowPrivilegeEscalation: false # 권한 상승 방지
readOnlyRootFilesystem: true # 루트 파일시스템 읽기 전용
capabilities:
drop: ["ALL"] # 모든 Linux 기능 제거
volumeMounts:
- name: credentials # 자격 증명 볼륨
mountPath: /credentials # 마운트 경로
readOnly: true # 읽기 전용 마운트
- name: data # 데이터 볼륨
mountPath: /data # 마운트 경로
- name: tmp # 임시 디렉토리 볼륨
mountPath: /tmp # 마운트 경로
volumes:
- name: credentials # 자격 증명 볼륨 정의
secret:
secretName: minio-creds # Secret 이름
- name: data # 데이터 볼륨 정의
persistentVolumeClaim:
claimName: minio-data # PVC 이름
- name: tmp # 임시 디렉토리 볼륨 정의
emptyDir: {} # 임시 볼륨
📌 Summary
- Secret은 쿠버네티스에서 민감한 자격 증명을 관리하는 핵심 리소스
- 환경 변수 또는 볼륨 마운트를 통해 MinIO에 자격 증명 제공 가능
- etcd 암호화를 통해 저장 데이터 보안 강화 가능
- RBAC를 활용하여 Secret 접근을 최소 권한 원칙에 따라 제한
- Sealed Secrets 및 외부 시크릿 관리 도구로 GitOps 워크플로우 보안 강화
- 자격 증명 순환 전략으로 정기적인 보안 강화 가능
- 서비스 계정과 보안 컨텍스트를 통해 추가적인 보안 레이어 구축