Kubernetes 보안 완벽 가이드 — 클러스터 보안 강화

Kubernetes 보안 완벽 가이드 — 클러스터 보안 강화

이 글의 핵심

RBAC·ServiceAccount, Pod Security Standards, Network Policy, Secrets(Vault·Sealed Secrets), 이미지 스캔·Admission Control, 감사 로그·모니터링까지 운영 환경에서 바로 적용할 수 있는 Kubernetes 보안 강화 로드맵입니다.

이 글의 핵심

Kubernetes는 강력한 오케스트레이션 기능을 제공하지만, 기본 설정만으로는 네트워크 경계·신원·비밀·런타임이 한꺼번에 노출될 수 있습니다. 본 문서는 운영 클러스터에서 반복적으로 마주치는 보안 요구사항을 정책·구성·관측 가능성의 세 축으로 정리하고, 각 영역에서 채택할 수 있는 실무 패턴과 함정을 설명합니다.

다루는 범위는 다음과 같습니다.

  • RBAC·ServiceAccount: 누가 무엇을 할 수 있는지를 명시적으로 제한
  • Pod Security Standards: 워크로드의 특권 상승·호스트 접근을 구조적으로 차단
  • Network Policy: 동·서향 트래픽을 라벨 기준으로 최소 연결만 허용
  • Secrets 관리: etcd 암호화, HashiCorp Vault, Sealed Secrets 등 비밀 수명주기
  • 이미지 스캔·Admission Control: 취약 이미지 차단, 정책 기반 배포 게이트
  • 감사 로그·모니터링: 감사 추적과 이상 징후 탐지
  • 실전 보안 체크리스트: 도입 순서와 검증 항목

1. 위협 모델과 설계 원칙

클러스터 보안은 단일 도구가 아니라 다층 방어(defense in depth)입니다. 일반적인 공격 경로는 (1) 취약한 컨테이너 이미지나 과도한 권한으로 워크로드에 침투하고, (2) ServiceAccount 토큰이나 Secret을 탈취해 API 서버에 접근하며, (3) 네트워크 정책 부재로 내부 이동(lateral movement)을 시도하는 흐름입니다. 따라서 최소 권한, 기본 거부(default deny) 네트워크, 비밀의 외부화·짧은 수명, 배포 전 정책 검증을 동시에 만족시키는 것이 목표입니다.

운영 관점에서는 “한 번에 완벽”보다 네임스페이스·환경(dev/stage/prod)별로 단계적 강화가 현실적입니다. 예를 들어 개발 클러스터에서는 PSS를 baseline으로 시작하고, 프로덕션에서는 restricted와 Network Policy 기본 거부를 조합하는 식입니다.


2. RBAC와 ServiceAccount

2.1 RBAC의 역할

Kubernetes는 Role/ClusterRole에 동사(verb)와 리소스 조합을 정의하고, RoleBinding/ClusterRoleBinding으로 사용자·그룹·ServiceAccount에 부여합니다. 보안 강화의 핵심은 cluster-admin 남용 금지네임스페이스 범위 권한 선호입니다.

아래는 특정 네임스페이스에서 Deployment와 Pod만 읽기·목록 수준으로 제한하는 예시입니다.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: payments
  name: deploy-reader
rules:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["pods", "pods/log"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: deploy-reader-binding
  namespace: payments
subjects:
  - kind: ServiceAccount
    name: cicd-deployer
    namespace: payments
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: deploy-reader

이 구성은 CI/CD 파이프라인이 해당 네임스페이스의 배포 상태와 로그만 확인할 수 있게 합니다. create, patch, delete를 열어두면 파이프라인이 필요 이상으로 워크로드를 변경할 수 있으므로, 실제 배포 자동화에는 별도 Role으로 동사를 쪼개고 파이프라인 단계별로 다른 ServiceAccount를 쓰는 편이 안전합니다.

2.2 ServiceAccount와 토큰

Pod는 기본 ServiceAccount와 마운트된 토큰(또는 bound token)으로 API 서버에 접근합니다. 불필요한 API 접근을 막으려면 (1) 워크로드별 전용 ServiceAccount를 만들고, (2) 해당 SA에 RoleBinding만 부여하며, (3) automountServiceAccountToken: false로 토큰 마운트를 끄는 방안을 검토합니다. 토큰이 필요 없는 애플리케이션 컨테이너에는 마운트를 비활성화해 공격 면을 줄입니다.

운영자 개인 접근은 그룹·OIDC 연동으로 식별자를 클러스터 외부 IdP에 두고, kubeconfig에 짧은 만료 시간impersonation을 조합하는 패턴이 권장됩니다. 정적 클라이언트 인증서는 회전 비용이 크므로 가능하면 지양합니다.


3. Pod Security Standards

Pod Security Standards(PSS)는 privileged, baseline, restricted 세 수준으로 Pod·컨테이너 스펙을 제한합니다. 네임스페이스에 pod-security.kubernetes.io/enforce 등의 레이블을 붙이면 admission 단계에서 위반 배포를 거부할 수 있습니다.

프로덕션 워크로드에는 일반적으로 restricted를 목표로 하되, 레거시 이미지가 runAsNonRoot나 읽기 전용 루트 파일시스템을 만족하지 못하면 단계적으로 baselinerestricted로 이행합니다.

apiVersion: v1
kind: Namespace
metadata:
  name: app-prod
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

auditwarn을 함께 두면 배포는 허용되지만 위반 사실이 감사 로그·경고로 남아, 이행 계획을 세우기 좋습니다. 핵심은 컨테이너가 root로 실행되거나 호스트 네임스페이스·특권 모드를 쓰지 않도록 이미지와 Helm 차트를 정리하는 것입니다. PSS는 “잘못된 Pod가 들어오지 못하게 막는 문지기”이며, 애플리케이션 자체의 취약점을 대체하지는 않습니다.


4. Network Policy

기본 Kubernetes 네트워킹은 파드 간 연결을 넓게 허용합니다. Network Policy는 레이블 셀렉터로 수신(ingress)·송신(egress) 트래픽을 정의하며, CNI가 해당 정책을 지원해야 합니다.

다음 예시는 app=frontend 파드가 같은 네임스페이스의 app=backend 8080만 향해 나가고, 백엔드는 DNS와 백엔드 포트만 받도록 제한하는 패턴의 축소입니다.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: frontend-to-backend
  namespace: shop
spec:
  podSelector:
    matchLabels:
      app: frontend
  policyTypes:
    - Ingress
    - Egress
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: backend
      ports:
        - protocol: TCP
          port: 8080
    - to:
        - namespaceSelector: {}
          podSelector:
            matchLabels:
              k8s-app: kube-dns
      ports:
        - protocol: UDP
          port: 53

운영 시에는 정책이 없을 때의 의미를 팀과 합의해야 합니다. 많은 환경에서 “정책 없음 = 전체 허용”이므로, 새 네임스페이스마다 기본 거부 템플릿을 두고 필요한 연결만 열어 주는 방식이 안전합니다. 정책 디버깅은 kubectl describe networkpolicy와 CNI별 로그, 그리고 임시로 허용 규칙을 넓혀 보며 원인을 좁히는 절차가 필요합니다.


5. Secrets 관리: etcd 암호화, Vault, Sealed Secrets

5.1 etcd와 Kubernetes Secret

Secret 리소스는 API를 통해 전달되지만 etcd에는 인코딩된 형태로 저장됩니다. 클러스터 백업·디스크 접근이 가능한 주체에게는 의미 있는 위험이 되므로, etcd 암호화 at rest를 켜는 것이 기본선입니다. 또한 RBAC으로 Secret의 get·list를 제한하고, 불필요한 네임스페이스 전역 읽기 권한을 없애야 합니다.

5.2 HashiCorp Vault

Vault는 동적 자격 증명, 짧은 TTL, 감사 로그, KV 시크릿 엔진 등으로 비밀 수명주기를 중앙에서 관리합니다. Kubernetes 통합 패턴으로는 Vault Agent Injector로 사이드카가 파일 또는 환경에 시크릿을 주입하거나, CSI 드라이버로 마운트하는 방식이 있습니다. 이 접근은 평문 Secret을 Git에 두지 않으면서 Pod 기동 시점에만 비밀을 노출할 수 있게 합니다.

도입 시에는 Vault 클러스터 자체의 고가용성·백업·unseal 절차Kubernetes 인증 방법(Role, ServiceAccount JWT)을 운영 문서화하는 것이 중요합니다.

5.3 Sealed Secrets

Bitnami Sealed Secrets는 클러스터에 컨트롤러를 두고, 공개 키로 암호화된 SealedSecret 매니페스트만 Git에 저장합니다. 클러스터 내부에서만 복호화되어 일반 Secret으로 동기화되므로, GitOps 흐름과 잘 맞습니다. 키 로테이션·재암호화 전략을 미리 정하지 않으면 장기 운영에서 발목을 잡을 수 있으므로, 조직 표준으로 절차를 정해 두는 것이 좋습니다.


6. 이미지 스캔과 Admission Control

6.1 이미지 스캔

컨테이너 이미지는 공급망의 일부입니다. 레지스트리 또는 CI에서 Trivy, Grype, Clair 등으로 CVE를 스캔하고, 심각도 임계값을 넘기면 빌드를 실패시키는 정책을 두는 것이 일반적입니다. 스캔은 베이스 이미지 태그 고정(digest pin)과 함께할 때 효과가 큽니다. latest 태그는 재현성과 감사 추적을 해칩니다.

6.2 Admission Control

OPA Gatekeeper, Kyverno 같은 정책 엔진은 요청이 API 서버에 의해 지속되기 전에 검증·변경(mutating)할 수 있습니다. 예를 들어 다음과 같은 규칙을 강제할 수 있습니다.

  • 모든 Pod에 resources.requests/limits 존재
  • 허용된 레지스트리 prefix만 사용
  • privileged: true 금지
  • 특정 레이블이 없으면 네임스페이스 생성 거부

Kyverno 예시는 클러스터 버전과 정책 문법에 따라 다르지만, 핵심은 PSS와 중복되더라도 조직 규칙을 코드로 고정하고, 배포 파이프라인에서 동일한 정책을 사전 검증하는 것입니다.

# 개념 예시: 특정 이미지 레지스트리만 허용 (Kyverno 스타일 의사 코드)
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: allowed-registries
spec:
  validationFailureAction: Enforce
  rules:
    - name: check-image-registry
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "허용된 레지스트리만 사용하세요."
        pattern:
          spec:
            containers:
              - image: "corp.registry.io/* | ghcr.io/myorg/*"

실제 적용 시에는 프로젝트 문서의 최신 필드명과 validate/mutate 구문을 따르십시오.


7. 감사 로그와 모니터링

7.1 Kubernetes Audit

Audit Policy로 API 서버 요청을 기록할 수 있습니다. 민감 리소스(Secret, RoleBinding)에 대해 RequestResponse 수준을 적용하면 페이로드까지 남아 디버깅에 유용하지만 저장소·개인정보 측면에서 부담이 됩니다. 단계적으로 Metadata 수준에서 시작해 필요한 리소스만 상세화하는 방식을 권장합니다. 감사 로그는 중앙 로그 스택(Elasticsearch, Loki, Cloud 로깅)으로 보내 보존 기간과 접근 통제를 명시해야 합니다.

7.2 런타임·클러스터 모니터링

Falco 같은 런타임 보안 도구는 시스템 콜·커널 이벤트 기반으로 비정상 행위를 탐지합니다. Prometheus·Grafana로 API 서버 지연, etcd 크기, 노드 상태를 모니터링하고, RBAC 변경·새 ClusterRoleBinding 같은 이벤트에 알림을 거는 것이 좋습니다. 서비스 메시를 쓰는 경우 mTLS와 세밀한 라우팅 정책이 추가 방어층이 됩니다.


8. 실전 보안 체크리스트

아래 목록은 도입 순서를 가늠할 수 있는 실무 점검표입니다. 환경마다 우선순위는 달라집니다.

구분점검 항목
신원·권한OIDC/OAuth 연동, RBAC 최소 권한, cluster-admin 사용 최소화, ServiceAccount별 Role
워크로드PSS restricted 또는 단계적 이행, 루트 비사용, 읽기 전용 루트 FS, 드롭 캐퍼빌리티
네트워크기본 거부 Network Policy, 네임스페이스 간 불필요 통신 차단, 노출 서비스 최소화
비밀etcd 암호화, Secret 접근 RBAC, Vault/Sealed Secrets 등 Git에 평문 금지
공급망이미지 스캔, 허용 레지스트리, digest 기반 배포, SBOM·서명(예: Cosign) 검토
정책Kyverno/Gatekeeper로 조직 표준 강제, CI에서 동일 정책 선검증
관측Audit Policy, 중앙 로그, RBAC 변경 알림, 런타임 탐지(Falco 등)
클러스터버전 업그레이드 계획, CIS Benchmark 점검, 노드 OS 패치, etcd 백업 암호화

검증 방법으로는 kubectl auth can-i, 정책 드라이런(dry-run), 스테이징에서 Network Policy 단위 테스트, 재해 복구 훈련(백업 복원·Vault seal)을 주기적으로 수행하는 것을 권장합니다.


9. 정리

Kubernetes 보안은 API 권한·Pod 격리·네트워크 분할·비밀 수명·배포 게이트·감사가 맞물려야 완성됩니다. 한 번에 모든 항목을 도입하기보다, 네임스페이스와 환경별로 통제 수준을 올리며 관측 지표와 감사 로그로 효과를 확인하는 접근이 지속 가능합니다. 이 문서의 패턴을 바탕으로 조직 표준을 코드와 정책으로 고정하면, 클러스터 규모가 커져도 보안 상태를 예측 가능하게 유지할 수 있습니다.

배포 전 git add, git commit, git pushnpm run deploy를 실행하는 워크플로를 유지하십시오.

내부 동작과 핵심 메커니즘

이 글의 주제는 「Kubernetes 보안 완벽 가이드 — 클러스터 보안 강화」입니다. 여기서는 앞선 설명을 구현·런타임 관점에서 한 번 더 압축합니다. 구성 요소 간 책임 분리와 관측 가능한 지점을 기준으로 생각하면, “입력이 어디서 검증되고, 핵심 연산이 어디서 일어나며, 부작용(I/O·네트워크·디스크)이 어디서 터지는가”가 한눈에 드러납니다.

처리 파이프라인(개념도)

flowchart TD
  A[입력·요청·이벤트] --> B[파싱·검증·디코딩]
  B --> C[핵심 연산·상태 전이]
  C --> D[부작용: I/O·네트워크·동시성]
  D --> E[결과·관측·저장]

알고리즘·프로토콜 관점에서의 체크포인트

  • 불변 조건(Invariant): 각 단계가 만족해야 하는 조건(예: 버퍼 경계, 프로토콜 상태, 트랜잭션 격리)을 문장으로 적어 두면 디버깅 비용이 줄어듭니다.
  • 결정성: 동일 입력에 동일 출력이 보장되는 순수한 층과, 시간·네트워크에 의해 달라질 수 있는 층을 분리해야 테스트와 장애 분석이 쉬워집니다.
  • 경계 비용: 직렬화/역직렬화, 문자 인코딩, syscall 횟수, 락 경합처럼 “한 번의 호출이 아니라 누적되는 비용”을 의심 목록에 넣습니다.

프로덕션 운영 패턴

실서비스에서는 기능 구현과 함께 관측·배포·보안·비용이 동시에 요구됩니다. 아래는 팀에서 자주 쓰는 최소 체크리스트입니다.

영역운영 관점에서의 질문
관측성요청 단위 상관 ID, 에러율/지연 분위수, 주요 의존성 타임아웃이 보이는가
안전성입력 검증·권한·비밀 관리가 코드 경로마다 일관적인가
신뢰성재시도는 멱등한 연산에만 적용되는가, 서킷 브레이커·백오프가 있는가
성능캐시 계층·배치 크기·풀링·백프레셔가 데이터 규모에 맞는가
배포롤백 룬북, 카나리, 마이그레이션 호환성이 문서화되어 있는가

운영 환경에서는 “개발자 PC에서는 재현되지 않던 문제”가 시간·부하·데이터 크기 때문에 드러납니다. 따라서 스테이징의 데이터 양·네트워크 지연을 가능한 한 현실에 가깝게 맞추는 것이 중요합니다.


문제 해결(Troubleshooting)

증상가능 원인조치
간헐적 실패레이스 컨디션, 타임아웃, 외부 의존성 불안정최소 재현 스크립트 작성, 분산 트레이스·로그 상관관계 확인
성능 저하N+1 쿼리, 동기 I/O, 잠금 경합, 과도한 직렬화프로파일러·APM으로 핫스팟 확인 후 한 가지씩 제거
메모리 증가캐시 무제한, 클로저/이벤트 구독 누수, 대용량 객체의 불필요한 복사상한·TTL·스냅샷 비교(힙 덤프/트레이스)
빌드·배포만 실패환경 변수·권한·플랫폼 차이CI 로그와 로컬 diff, 컨테이너/런타임 버전 핀(pin)

권장 디버깅 순서: (1) 최소 재현 만들기 (2) 최근 변경 범위 좁히기 (3) 의존성·환경 변수 차이 확인 (4) 관측 데이터로 가설 검증 (5) 수정 후 회귀·부하 테스트.