목차
- 1. 왜 쿠버네티스 보안이 이렇게 중요한가요?
- 2. RBAC 기본 개념 다시 잡기
- 3. RBAC 실전 설정: 최소 권한 원칙 적용하기
- 3-1. 개발자용 네임스페이스 제한 Role 만들기
- 3-2. 서비스 어카운트(Service Account) 권한 최소화
- 4. 쿠버네티스 시크릿 관리: 이게 진짜 골치 아픕니다
- 4-1. External Secrets Operator (ESO) 활용하기
- 4-2. Sealed Secrets으로 GitOps 환경 구성하기
- 4-3. etcd 암호화 설정 (꼭 하세요!)
- 5. ⚠️ 실제 겪은 트러블슈팅
- 문제 1: RBAC 설정 후 애플리케이션이 갑자기 동작 안 함
- 문제 2: ExternalSecret이 계속 Pending 상태
- 문제 3: Sealed Secrets 컨트롤러 재설치 후 복호화 실패
- 6. 추가 보안 강화: 꼭 챙겨야 할 것들
- Pod Security Standards (PSS) 적용
- 네트워크 정책(Network Policy)으로 Pod 간 통신 제한
- 감시 로그(Audit Log) 설정
- 7. 쿠버네티스 보안 베스트 프랙티스 정리
- 8. 자주 묻는 질문 (FAQ)
- Q. 기본 Secret 오브젝트는 정말 안전하지 않나요?
- Q. RBAC 설정이 너무 복잡한데 관리 도구가 있나요?
- Q. 개발 환경에서도 이렇게 엄격하게 해야 하나요?
- 마무리: 보안은 한 번에 끝나지 않습니다
쿠버네티스 보안 2026: RBAC와 시크릿 관리 베스트 프랙티스
안녕하세요, 13년차 인프라 엔지니어입니다. 요즘 제일 많이 받는 질문이 쿠버네티스 보안이에요. 특히 RBAC(Role-Based Access Control, 역할 기반 접근 제어)과 시크릿(Secret) 관리 쪽으로요.
솔직히 말씀드리면, 처음 k8s 클러스터를 운영할 때 "일단 돌아가면 되지"라는 생각으로 보안 설정을 미뤘다가 크게 혼난 적이 있거든요. 개발 클러스터에서 cluster-admin 권한을 남발하다가 실수로 프로덕션 네임스페이스 전체를 날릴 뻔 했던 그 날의 식은땀이 아직도 기억납니다 ㅎㅎ. 그 이후로는 k8s 보안 설정만큼은 제대로 잡고 가자는 주의가 됐어요.
2026년 현재, 쿠버네티스 보안 환경은 많이 달라졌습니다. External Secrets Operator, Sealed Secrets 같은 도구들이 성숙해졌고, RBAC 정책도 훨씬 정교하게 설계할 수 있게 됐죠. 이 글에서는 제가 실제 홈랩과 업무 환경에서 적용해본 내용을 바탕으로 현실적인 베스트 프랙티스를 공유해 드릴게요.
▲ 쿠버네티스 보안의 핵심 레이어: RBAC, 네트워크 정책, 시크릿 관리, Pod 보안이 유기적으로 연결되는 구조
1. 왜 쿠버네티스 보안이 이렇게 중요한가요?
쿠버네티스는 기본적으로 "편리함"을 위해 설계된 시스템이라서, 기본값(default) 설정만으로는 보안이 허술합니다. 이런 경험 있으신가요?
- 새로 합류한 팀원에게 임시로
cluster-admin권한을 줬다가 그냥 쭉 유지되는 상황 - ConfigMap에 DB 비밀번호를 평문으로 넣어둔 코드를 발견한 공포
- 개발자가 실수로
kubectl delete namespace production을 입력하는 악몽
실제로 2025년 CNCF 보고서에 따르면 k8s 보안 사고의 60% 이상이 잘못된 RBAC 설정과 시크릿 노출에서 시작된다고 합니다. 무서운 수치죠. 그래서 오늘 이 두 가지를 집중적으로 파봅니다.
2. RBAC 기본 개념 다시 잡기
쉽게 말해서 RBAC는 "누가 무엇을 할 수 있는가"를 정의하는 시스템입니다. 크게 4가지 오브젝트로 구성돼요.
| 오브젝트 | 범위 | 역할 | 예시 |
|---|---|---|---|
| Role | 네임스페이스 | 특정 네임스페이스 내 권한 정의 | dev 네임스페이스 Pod 조회 권한 |
| ClusterRole | 클러스터 전체 | 클러스터 수준 권한 정의 | 노드 조회, PV 관리 권한 |
| RoleBinding | 네임스페이스 | Role을 사용자/그룹에 연결 | kim@company.com에게 dev Role 부여 |
| ClusterRoleBinding | 클러스터 전체 | ClusterRole을 전체 범위로 연결 | ops팀에게 ClusterRole 부여 |
여기서 중요한 포인트! ClusterRoleBinding은 진짜 신중하게 써야 합니다. 처음엔 편하다고 ClusterRoleBinding을 남발했는데, 이게 나중에 감사(audit) 할 때 얼마나 골치 아픈지 직접 겪어봤거든요.
3. RBAC 실전 설정: 최소 권한 원칙 적용하기
핵심은 최소 권한 원칙(Principle of Least Privilege)입니다. 필요한 것만, 필요한 범위만 주는 거예요. 말은 쉬운데 실전에서 적용하려면 손이 많이 가더라고요. 단계별로 살펴볼게요.
3-1. 개발자용 네임스페이스 제한 Role 만들기
# developer-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: development
name: developer-role
rules:
# Pod 조회/로그 확인은 허용, 삭제는 금지
- apiGroups: [""]
resources: ["pods", "pods/log", "pods/exec"]
verbs: ["get", "list", "watch"]
# Deployment는 읽기 + 재시작만 허용
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "patch"]
# ConfigMap은 읽기만
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list"]
# Secret은 절대 접근 불가 (명시하지 않으면 기본 거부)
# developer-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: developer-rolebinding
namespace: development
subjects:
- kind: User
name: "developer@company.com"
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: "dev-team"
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: developer-role
apiGroup: rbac.authorization.k8s.io
여기서 눈치채셨나요? Secret에 대한 권한을 아예 명시하지 않았습니다. k8s RBAC는 화이트리스트 방식이라서 명시하지 않으면 자동으로 거부됩니다. 이게 쿠버네티스 보안 설계의 핵심이에요.
3-2. 서비스 어카운트(Service Account) 권한 최소화
애플리케이션 Pod에 자동으로 마운트되는 서비스 어카운트도 꼭 챙겨야 합니다. 기본 서비스 어카운트를 그냥 쓰면 클러스터 API에 불필요한 접근이 가능해지거든요.
# 기본 서비스 어카운트 토큰 자동 마운트 비활성화
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-app-sa
namespace: production
automountServiceAccountToken: false # 이게 핵심!
---
# Pod에서 명시적으로 SA 지정
apiVersion: v1
kind: Pod
metadata:
name: my-app
namespace: production
spec:
serviceAccountName: my-app-sa
automountServiceAccountToken: false # Pod 레벨에서도 한 번 더!
containers:
- name: app
image: my-app:latest
💡 팁: kubectl auth can-i 명령어로 특정 사용자의 권한을 빠르게 확인할 수 있습니다.
# developer@company.com이 production 네임스페이스에서 secret을 볼 수 있는지 확인
kubectl auth can-i get secrets \
--namespace=production \
--as=developer@company.com
# 출력: no (잘 막혀 있는 거 확인!)
▲ RBAC 권한 흐름: User/ServiceAccount → RoleBinding → Role → API 리소스 접근 제어 구조도
4. 쿠버네티스 시크릿 관리: 이게 진짜 골치 아픕니다
솔직히 말씀드리면, 시크릿 관리는 제가 가장 많이 삽질한 영역입니다. 기본 Secret 오브젝트는 그냥 base64 인코딩이라서, 사실상 평문이나 마찬가지거든요. etcd에도 기본적으로 암호화 없이 저장되고요.
2026년 현재 제가 권장하는 쿠버네티스 시크릿 관리 방식은 크게 두 가지입니다.
4-1. External Secrets Operator (ESO) 활용하기
External Secrets Operator(외부 시크릿 오퍼레이터)는 AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager 같은 외부 시크릿 저장소와 k8s를 연결해주는 오퍼레이터입니다. 제가 홈랩에서는 Vault를 연동해서 쓰고 있는데, 한 번 세팅해두면 진짜 편하더라고요.
# ESO 설치 (Helm 사용)
helm repo add external-secrets https://charts.external-secrets.io
helm install external-secrets \
external-secrets/external-secrets \
-n external-secrets \
--create-namespace
# SecretStore - AWS Secrets Manager 연동 예시
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: aws-secretsmanager
namespace: production
spec:
provider:
aws:
service: SecretsManager
region: ap-northeast-2
auth:
secretRef:
accessKeyIDSecretRef:
name: aws-credentials
key: access-key-id
secretAccessKeySecretRef:
name: aws-credentials
key: secret-access-key
# ExternalSecret - 실제 시크릿 동기화 정의
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: database-credentials
namespace: production
spec:
refreshInterval: 1h # 1시간마다 갱신
secretStoreRef:
name: aws-secretsmanager
kind: SecretStore
target:
name: db-secret # 생성될 k8s Secret 이름
creationPolicy: Owner
data:
- secretKey: DB_PASSWORD
remoteRef:
key: production/database
property: password
- secretKey: DB_USERNAME
remoteRef:
key: production/database
property: username
이렇게 하면 실제 비밀번호는 AWS Secrets Manager에만 있고, k8s Secret은 그걸 참조하는 구조가 됩니다. Git에 시크릿 값이 올라갈 일이 없어지는 거죠!
4-2. Sealed Secrets으로 GitOps 환경 구성하기
외부 저장소를 쓰기 어려운 환경이라면 Sealed Secrets(봉인된 시크릿)도 좋은 선택입니다. 공개키로 암호화한 SealedSecret을 Git에 저장하고, 클러스터 내 컨트롤러가 복호화하는 방식이에요.
# kubeseal CLI 설치 및 시크릿 봉인
# 1. 기존 Secret을 SealedSecret으로 변환
kubectl create secret generic db-secret \
--from-literal=password='super-secret-password' \
--dry-run=client \
-o yaml | \
kubeseal \
--controller-name=sealed-secrets-controller \
--controller-namespace=kube-system \
--format yaml > sealed-db-secret.yaml
# 2. 생성된 sealed-db-secret.yaml은 Git에 안전하게 커밋 가능!
# 암호화된 값이 들어있어서 클러스터 컨트롤러만 복호화 가능
4-3. etcd 암호화 설정 (꼭 하세요!)
이건 정말 많이들 놓치는 부분인데, etcd 저장 암호화(Encryption at Rest)도 반드시 설정해야 합니다.
# /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
- configmaps # configmap도 같이 암호화!
providers:
- aescbc:
keys:
- name: key1
secret: <base64로 인코딩된 32바이트 키>
- identity: {} # 암호화 안 된 기존 데이터 읽기용
# kube-apiserver에 암호화 설정 적용 (kubeadm 환경)
# /etc/kubernetes/manifests/kube-apiserver.yaml에 추가
spec:
containers:
- command:
- kube-apiserver
- --encryption-provider-config=/etc/kubernetes/encryption-config.yaml
# ... 기타 옵션들
5. ⚠️ 실제 겪은 트러블슈팅
실전에서 마주쳤던 문제들을 솔직하게 공유해 드릴게요.
문제 1: RBAC 설정 후 애플리케이션이 갑자기 동작 안 함
서비스 어카운트 토큰 자동 마운트를 끄고 나서 일부 앱이 k8s API를 내부적으로 호출하는 경우 죽어버리는 일이 생겼어요. 이럴 땐 kubectl logs로 에러를 확인하고, 해당 SA에 필요한 최소 권한을 다시 부여해야 합니다.
# RBAC 관련 감사 로그 확인
kubectl get events --field-selector reason=Forbidden -n production
# 특정 SA의 권한 확인
kubectl auth can-i --list \
--as=system:serviceaccount:production:my-app-sa
문제 2: ExternalSecret이 계속 Pending 상태
ESO를 처음 설치했을 때 SecretStore 상태가 계속 Pending이었는데, 알고 보니 IAM 권한 문제였어요. AWS의 경우 Secrets Manager에 대한 GetSecretValue, DescribeSecret 권한이 반드시 있어야 합니다.
# ESO 상태 확인
kubectl get secretstore -n production
kubectl describe secretstore aws-secretsmanager -n production
# ExternalSecret 상태 확인
kubectl get externalsecret -n production
kubectl describe externalsecret database-credentials -n production
문제 3: Sealed Secrets 컨트롤러 재설치 후 복호화 실패
이건 진짜 당황스러웠는데요. Sealed Secrets 컨트롤러를 재설치하면 키 쌍이 새로 생성돼서 기존 SealedSecret을 복호화 못 하는 상황이 발생합니다. 반드시 기존 키를 백업해두세요!
# Sealed Secrets 키 백업 (반드시 안전한 곳에 보관!)
kubectl get secret \
-n kube-system \
-l sealedsecrets.bitnami.com/sealed-secrets-key \
-o yaml > sealed-secrets-key-backup.yaml
# 컨트롤러 재설치 후 키 복원
kubectl apply -f sealed-secrets-key-backup.yaml
kubectl rollout restart deployment sealed-secrets-controller -n kube-system
▲ External Secrets Operator 대시보드: 시크릿 동기화 상태와 갱신 주기를 한눈에 확인하는 모니터링 화면
6. 추가 보안 강화: 꼭 챙겨야 할 것들
RBAC와 시크릿 관리 외에도 쿠버네티스 보안을 위해 꼭 챙겨야 할 것들이 있습니다.
Pod Security Standards (PSS) 적용
2022년부터 PodSecurityPolicy(PSP)가 deprecated되고 Pod Security Standards(파드 보안 표준)가 그 자리를 대신하고 있습니다.
# 네임스페이스에 보안 표준 레이블 적용
kubectl label namespace production \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted
네트워크 정책(Network Policy)으로 Pod 간 통신 제한
# 기본 deny-all 정책 + 필요한 것만 허용
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {} # 모든 Pod에 적용
policyTypes:
- Ingress
- Egress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
감시 로그(Audit Log) 설정
보안 사고가 났을 때 "누가 뭘 했는지" 추적하려면 감시 로그가 필수입니다.
# /etc/kubernetes/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# Secret 접근은 모두 기록
- level: Metadata
resources:
- group: ""
resources: ["secrets"]
# 삭제 작업은 RequestResponse 레벨로 상세 기록
- level: RequestResponse
verbs: ["delete", "deletecollection"]
# 나머지는 최소한만
- level: None
users: ["system:kube-proxy"]
verbs: ["watch"]
resources:
- group: ""
resources: ["endpoints", "services"]
7. 쿠버네티스 보안 베스트 프랙티스 정리
▲ 2026년 쿠버네티스 보안 베스트 프랙티스 한눈에 보기: RBAC, 시크릿 관리, 네트워크 정책, Pod 보안 체크리스트
| 영역 | 베스트 프랙티스 | 우선순위 |
|---|---|---|
| RBAC | 최소 권한 원칙, ClusterRoleBinding 최소화, SA 토큰 자동 마운트 비활성화 | 🔴 높음 |
| 시크릿 관리 | ESO 또는 Sealed Secrets 사용, etcd 암호화, Git에 평문 시크릿 금지 | 🔴 높음 |
| Pod 보안 | Pod Security Standards restricted 모드, 루트 컨테이너 금지 | 🟠 중간 |
| 네트워크 | 기본 deny-all 네트워크 정책, 필요한 통신만 허용 | 🟠 중간 |
| 감시/모니터링 | 감시 로그 활성화, Falco로 런타임 보안 모니터링 | 🟡 권장 |
| 이미지 보안 | 취약점 스캔(Trivy), 서명된 이미지만 허용(Cosign) | 🟡 권장 |
8. 자주 묻는 질문 (FAQ)
Q. 기본 Secret 오브젝트는 정말 안전하지 않나요?
base64 인코딩은 암호화가 아닙니다. etcd 암호화를 추가로 설정하고, RBAC로 Secret 접근을 엄격히 제한하면 어느 정도 안전하게 쓸 수 있어요. 하지만 가능하면 ESO나 Sealed Secrets 같은 전용 도구를 쓰는 걸 강력히 권장합니다.
Q. RBAC 설정이 너무 복잡한데 관리 도구가 있나요?
네, rbac-manager나 permission-manager 같은 도구들이 있습니다. 팀 규모가 커지면 이런 도구를 도입하는 게 좋더라고요. 저도 팀원이 10명 넘어가면서부터 rbac-manager를 도입했는데 관리가 훨씬 편해졌어요.
Q. 개발 환경에서도 이렇게 엄격하게 해야 하나요?
개발 환경이라도 최소한 시크릿 관리와 기본 RBAC는 적용하는 게 좋습니다. 개발 환경 설정이 그대로 프로덕션으로 복사되는 경우가 생각보다 많거든요 ㅎㅎ.
마무리: 보안은 한 번에 끝나지 않습니다
오늘 다룬 내용을 정리해보면, 쿠버네티스 보안의 핵심은 결국 두 가지입니다. 최소 권한 원칙을 철저히 지키는 RBAC 설정과 시크릿을 코드/Git에서 완전히 분리하는 시크릿 관리. 이 두 가지만 제대로 해도 대부분의 보안 사고를 예방할 수 있어요.
처음엔 설정이 복잡하고 귀찮게 느껴질 수 있어요. 저도 그랬으니까요. 근데 한 번 제대로 잡아두면 나중에 감시(audit)할 때나 보안 사고 대응할 때 얼마나 편한지 몰라요. 드디어 됐다! 싶은 그 순간이 반드시 옵니다 🎉
다음 글에서는 Falco를 이용한 쿠버네티스 런타임 보안 모니터링과 OPA(Open Policy Agent)를 활용한 정책 자동화를 다룰 예정입니다. 이미지 보안(Cosign, Trivy 연동)도 함께 다룰 예정이니 기대해 주세요!
✅ 오늘 바로 적용해볼 수 있는 것들:
kubectl auth can-i --list로 현재 권한 상태 점검하기- 불필요한 ClusterRoleBinding 목록 확인하기:
kubectl get clusterrolebindings - Secret 오브젝트에 RBAC가 제대로 적용되어 있는지 확인하기
- etcd 암호화 설정 여부 확인하기
궁금한 점이나 다른 경험이 있으시면 댓글로 남겨주세요. 저도 아직 배우는 중이라 같이 이야기 나누면 좋겠습니다 😊
'IT > k8s' 카테고리의 다른 글
| [k8s] Longhorn 쿠버네티스 영구 스토리지 완벽 가이드: 설치부터 PV/PVC까지 (1) | 2026.04.18 |
|---|---|
| [k8s] k3s vs MicroK8s: 경량 쿠버네티스 비교 분석 및 선택 가이드 (1) | 2026.04.16 |
| [k8s] k3s 최신 버전: 경량 쿠버네티스 설치 및 운영 실전 가이드 (1) | 2026.04.16 |
| [k8s] Kubernetes 네트워크 정책 완벽 가이드: 보안 강화 및 트래픽 제어 (2) | 2026.04.12 |
| [k8s] Pod Security Standards(PSS) 완벽 적용 가이드 (1) | 2026.04.12 |
| [k8s] Helm 4.0 차트 관리 완벽 가이드: OCI 정식 지원과 실전 배포 (0) | 2026.04.09 |