쿠버네티스 마스터 — Security·RBAC·NetworkPolicy

2026-05-03확률과 통계 마스터 노트

쿠버네티스 마스터 노트 시리즈 8편. RBAC 4 객체(Role/ClusterRole/RoleBinding/ClusterRoleBinding)의 권한 모델, ServiceAccount가 Pod 인증 주체가 되는 메커니즘, NetworkPolicy로 Pod 사이 방화벽, SecurityContext로 컨테이너 권한 제어(runAsNonRoot·readOnlyRootFilesystem), Pod Security Standards 3 단계, 이미지 스캔까지.

이 글은 쿠버네티스 마스터 노트 시리즈의 여덟 번째 편입니다. 1~7편이 기능이었다면, 이번엔 운영 환경의 보안 — RBAC·NetworkPolicy·SecurityContext.

K8s는 강력한 도구라 권한 관리 안 하면 사고 폭발. RBAC으로 누구·뭘·어디서, NetworkPolicy로 Pod 방화벽, SecurityContext로 컨테이너 권한.

처음 K8s Security가 어렵게 느껴지는 이유

처음 이 단원이 어렵게 느껴지는 이유는 두 가지예요. 첫째, RBAC 4 객체가 한 번에 등장합니다. Role·ClusterRole·RoleBinding·ClusterRoleBinding. 둘째, NetworkPolicy 문법이 직관적이지 않습니다.

해결법은 한 가지예요. "Role = 권한 묶음 / Binding = 사용자에게 부여" 한 줄. ClusterRole·ClusterRoleBinding은 클러스터 전체 버전. 둘 곱하기로 4개. 이 그림이 잡히면 끝.

RBAC — Role-Based Access Control

K8s 보안의 토대. 4 객체로 권한 부여.

[Role / ClusterRole]   = 권한 묶음
       ↑
[RoleBinding / ClusterRoleBinding]
       ↓
[Subject = User / Group / ServiceAccount]

Role vs ClusterRole

종류 범위
Role 특정 namespace
ClusterRole 클러스터 전체 (또는 namespace 자원에도)

Role 예시

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: dev
  name: pod-reader
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]

dev namespace 안 Pod을 읽기만 가능.

RoleBinding — 사용자에게 부여

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: alice-pod-reader
  namespace: dev
subjects:
  - kind: User
    name: alice
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

alice에게 dev namespace의 pod-reader Role 부여.

ClusterRoleBinding — 전역

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: alice-cluster-admin
subjects:
  - kind: User
    name: alice
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

alice에게 클러스터 전체 admin.

Verbs — 작업 종류

get, list, watch     # 읽기
create, update, patch # 쓰기
delete, deletecollection # 삭제

apiGroups·resources

rules:
  - apiGroups: [""]              # core API (Pod·Service 등)
    resources: ["pods"]
  - apiGroups: ["apps"]          # apps API (Deployment·StatefulSet)
    resources: ["deployments"]
  - apiGroups: [""]
    resources: ["pods/log"]      # 하위 리소스
    verbs: ["get"]

여기서 정말 중요한 시험 함정 — apiGroups: [""] = core API (Pod·Service·Node·Namespace 등 K8s 1.0부터). 그 외엔 그룹 명시 (apps·batch·networking.k8s.io 등).

ServiceAccount — Pod의 인증 주체

각 Pod은 ServiceAccount(SA)로 API Server 인증.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-sa
  namespace: dev
spec:
  serviceAccountName: my-sa
  containers:
    - name: app
      image: my-app

기본은 default SA (namespace당 자동 생성). 권한 거의 없음.

여기서 시험 함정이 하나 있어요. default SA는 너무 약함. 운영 권장 = 각 앱별 전용 SA + 최소 권한 RoleBinding.

SA 토큰 자동 마운트

/var/run/secrets/kubernetes.io/serviceaccount/
  ├── token       # JWT 토큰
  ├── ca.crt
  └── namespace

K8s API 호출 시 이 토큰으로 인증. 클러스터 안 자동.

토큰 자동 마운트 비활성

spec:
  serviceAccountName: my-sa
  automountServiceAccountToken: false   # API 안 호출하는 Pod

실전 RBAC 패턴

개발자 — namespace 안 모든 권한

kind: ClusterRole
metadata:
  name: developer
rules:
  - apiGroups: ["", "apps", "batch", "networking.k8s.io"]
    resources: ["*"]
    verbs: ["*"]
kind: RoleBinding
metadata:
  name: dev-team
  namespace: dev
subjects:
  - kind: Group
    name: developers
roleRef:
  kind: ClusterRole
  name: developer

CI/CD — 특정 Deployment만 업데이트

kind: Role
rules:
  - apiGroups: ["apps"]
    resources: ["deployments"]
    resourceNames: ["my-app"]
    verbs: ["get", "patch", "update"]

특정 리소스만 (resourceNames).

NetworkPolicy — Pod 방화벽

기본은 모든 Pod끼리 통신 가능. NetworkPolicy로 제한.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-policy
  namespace: prod
spec:
  podSelector:
    matchLabels:
      app: db
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: api
      ports:
        - protocol: TCP
          port: 5432
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              name: kube-system
      ports:
        - protocol: UDP
          port: 53

해석:

  • 대상 — app: db Pod
  • Ingress — app: api Pod에서 5432만
  • Egress — kube-system DNS 53만

여기서 정말 중요한 시험 함정 — NetworkPolicy 적용 시 명시 안 된 트래픽 모두 차단. 처음 적용 시 정상 통신 끊김 위험. 점진적 적용·테스트 필수.

Default Deny

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
spec:
  podSelector: {}              # 모든 Pod
  policyTypes:
    - Ingress
    - Egress

namespace의 모든 트래픽 차단 (allow 명시 안 한 것). 보안 강한 환경.

여기서 시험 함정이 하나 있어요. NetworkPolicy는 CNI 지원 필요. Calico·Cilium 지원, Flannel 기본 X. 클러스터 생성 시 결정.

SecurityContext — 컨테이너 권한

Pod 레벨

spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
    runAsNonRoot: true

Container 레벨

containers:
  - name: app
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: [ALL]
        add: [NET_BIND_SERVICE]
      privileged: false

핵심 옵션

옵션 권장
runAsNonRoot: true Root 실행 X
runAsUser 명시적 사용자 ID
readOnlyRootFilesystem: true 루트 파일시스템 읽기 전용
allowPrivilegeEscalation: false sudo 같은 권한 상승 X
capabilities.drop: [ALL] 모든 Linux capability 제거
privileged: false 호스트 권한 X

여기서 정말 중요한 시험 함정 — 운영 환경 SecurityContext 표준:

securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  readOnlyRootFilesystem: true
  allowPrivilegeEscalation: false
  capabilities:
    drop: [ALL]

이미지가 root로 실행되면 위 설정 충돌 → 컨테이너 실패. 이미지 측에서 non-root 사용자 설정 필요.

Pod Security Standards — PSS (1.25+)

이전 PodSecurityPolicy 대체. 3 레벨:

레벨 의미
Privileged 제한 없음
Baseline 알려진 위협 차단
Restricted 강력한 제한 (운영 권장)

namespace 라벨로 적용:

apiVersion: v1
kind: Namespace
metadata:
  name: prod
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: latest

enforce (강제) / audit (로그) / warn (경고).

이미지 보안

이미지 출처 검증

spec:
  containers:
    - name: app
      image: my-registry.com/my-app:v1.2.3   # 명시적 태그
      # latest 절대 X
      imagePullPolicy: IfNotPresent

Admission Controller로 강제

- ImagePolicyWebhook
- OPA Gatekeeper
- Kyverno

특정 레지스트리만 허용·서명 검증·취약점 스캔 통과한 것만.

이미지 스캔

도구:

  • Trivy — 오픈소스
  • Snyk
  • Aqua Security
  • Clair

CI 파이프라인에서 이미지 빌드 후 스캔.

Secret 보안 (5편 보충)

# Secret을 etcd에 평문 저장 X
EncryptionConfiguration 필수 (5편)

# 운영 = External Secrets + Vault

Audit Log

# /etc/kubernetes/audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  - level: Metadata
    resources:
      - group: ""
        resources: ["secrets"]

API Server에서 audit log 활성화. 모든 작업 추적.

보안 체크리스트

✓ RBAC 활성·최소 권한
✓ 각 앱별 ServiceAccount
✓ default SA 사용 X
✓ NetworkPolicy default deny + 명시 allow
✓ SecurityContext — runAsNonRoot·readOnlyRoot·dropAll
✓ Pod Security Standards (restricted)
✓ 이미지 명시 태그 (latest X)
✓ 이미지 스캔 (Trivy 등)
✓ Secret 외부 관리 (Vault·Sealed)
✓ etcd 암호화
✓ Audit Log
✓ 노드 OS 업데이트

시험 직전 한 번 더 — 자주 헷갈리는 함정 모음

여기까지가 8편의 핵심입니다. 시험 직전 또는 실무에서 헷갈릴 때 다시 펼쳐 볼 수 있게 압축 노트로 마무리할게요.

  • RBAC = K8s 보안 토대
  • 4 객체 — Role / ClusterRole / RoleBinding / ClusterRoleBinding
  • Role = namespace / ClusterRole = 클러스터
  • Binding = Subject(User·Group·SA)에게 Role 부여
  • Verbs — get·list·watch (읽기) / create·update·patch (쓰기) / delete
  • apiGroups: [""] = core API
  • ServiceAccount = Pod의 인증 주체
  • 토큰 자동 마운트 (/var/run/secrets/.../token)
  • default SA = 너무 약함, 운영 = 앱별 전용 SA
  • NetworkPolicy = Pod 방화벽
  • 기본은 모두 통신 → NetworkPolicy로 제한
  • CNI 지원 필요 (Calico·Cilium / Flannel X)
  • Default Deny + 명시 Allow 패턴
  • SecurityContext — Pod / Container 레벨
  • 운영 표준 — runAsNonRoot·readOnlyRootFilesystem·dropAll·allowPrivilegeEscalation false
  • 이미지가 root면 충돌
  • Pod Security Standards (1.25+) — 3 레벨 (Privileged·Baseline·Restricted)
  • namespace 라벨로 적용
  • 이미지 — 명시 태그 (latest X) / 이미지 스캔 (Trivy)
  • Admission Controller — OPA Gatekeeper·Kyverno
  • etcd 암호화 + Audit Log
  • 보안 체크리스트 12개 항목

시리즈 다른 편

공식 문서: Kubernetes RBAC / NetworkPolicy / Pod Security Standards 에서 더 깊이.

다음 글(9편)에서는 Helm — 패키지 매니저, Chart 구조, 템플릿, 운영 배포 패턴까지 풀어 갑니다.

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!