Skip to content
Published on

Pod Security Standards(PSA/PSS) 실전 가이드

Authors
  • Name
    Twitter
Pod Security Standards Guide

1. Pod Security Standards란?

Kubernetes 1.25부터 PodSecurityPolicy(PSP)가 완전히 제거되고, **Pod Security Admission(PSA)**이 기본 보안 메커니즘이 되었습니다. PSA는 **Pod Security Standards(PSS)**라는 3단계 보안 프로파일을 기반으로 동작합니다.

PSP에서 PSA로의 전환 배경

PSP는 복잡한 RBAC 설정이 필요하고 디버깅이 어려웠습니다. PSA는 namespace 라벨만으로 간단하게 보안 정책을 적용할 수 있어 운영 부담이 크게 줄었습니다.

2. 3가지 보안 프로파일

Privileged (특권)

모든 것이 허용되는 프로파일입니다. 시스템 수준 워크로드(CNI, 스토리지 드라이버 등)에 사용합니다.

# kube-system namespace에 Privileged 적용
apiVersion: v1
kind: Namespace
metadata:
  name: kube-system
  labels:
    pod-security.kubernetes.io/enforce: privileged
    pod-security.kubernetes.io/audit: privileged
    pod-security.kubernetes.io/warn: privileged

Baseline (기본)

알려진 권한 상승을 방지하면서 대부분의 워크로드가 동작할 수 있는 프로파일입니다.

제한 항목:

  • hostNetwork, hostPID, hostIPC 사용 금지
  • privileged 컨테이너 금지
  • 위험한 capabilities 추가 금지 (NET_RAW 등)
  • hostPath 볼륨 금지
apiVersion: v1
kind: Namespace
metadata:
  name: app-staging
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/enforce-version: v1.30
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

Restricted (제한)

가장 엄격한 프로파일로, 보안 모범 사례를 강제합니다.

추가 제한 항목:

  • runAsNonRoot 필수
  • Seccomp 프로파일 설정 필수
  • 모든 capabilities drop 필수
  • allowPrivilegeEscalation: false 필수
apiVersion: v1
kind: Namespace
metadata:
  name: app-production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: v1.30
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

3. PSA 동작 모드

PSA는 세 가지 모드로 동작합니다:

모드동작용도
enforce위반 Pod 생성 거부실제 정책 적용
audit감사 로그 기록모니터링
warn사용자에게 경고 표시마이그레이션 준비
# namespace에 라벨 적용
kubectl label namespace my-app \
  pod-security.kubernetes.io/enforce=baseline \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted

4. Restricted 프로파일 호환 Pod 작성

Restricted를 만족하는 Pod spec 예제입니다:

apiVersion: v1
kind: Pod
metadata:
  name: secure-app
  namespace: app-production
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: nginx:1.27-alpine
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        runAsNonRoot: true
        runAsUser: 1000
        capabilities:
          drop:
            - ALL
      resources:
        limits:
          memory: '128Mi'
          cpu: '500m'
        requests:
          memory: '64Mi'
          cpu: '250m'
      volumeMounts:
        - name: tmp
          mountPath: /tmp
        - name: cache
          mountPath: /var/cache/nginx
        - name: run
          mountPath: /var/run
  volumes:
    - name: tmp
      emptyDir: {}
    - name: cache
      emptyDir: {}
    - name: run
      emptyDir: {}

5. 마이그레이션 전략

기존 클러스터를 PSA로 마이그레이션하는 단계별 접근법입니다.

Step 1: 현재 상태 감사

# 모든 namespace에 대해 dry-run 검사
kubectl label --dry-run=server --overwrite ns --all \
  pod-security.kubernetes.io/enforce=baseline

# 특정 namespace의 위반 사항 확인
kubectl get pods -n my-app -o json | \
  kubectl apply --dry-run=server -f - 2>&1 | grep -i "warning"

Step 2: warn/audit 모드로 시작

# 먼저 warn과 audit만 적용
kubectl label namespace my-app \
  pod-security.kubernetes.io/warn=baseline \
  pod-security.kubernetes.io/audit=baseline

Step 3: 위반 워크로드 수정

# audit 로그에서 위반 사항 확인
kubectl logs -n kube-system -l component=kube-apiserver | \
  grep "pod-security.kubernetes.io"

Step 4: enforce 모드 활성화

# 충분한 테스트 후 enforce 적용
kubectl label namespace my-app \
  pod-security.kubernetes.io/enforce=baseline \
  --overwrite

6. Namespace별 예외 처리

특정 워크로드가 상위 권한이 필요한 경우, namespace를 분리하는 것이 권장됩니다:

# 모니터링 에이전트용 별도 namespace
apiVersion: v1
kind: Namespace
metadata:
  name: monitoring-agents
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/audit: baseline
    pod-security.kubernetes.io/warn: restricted
---
# 일반 앱용 namespace
apiVersion: v1
kind: Namespace
metadata:
  name: production-apps
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

7. AdmissionConfiguration으로 클러스터 기본값 설정

API 서버 설정으로 클러스터 전체 기본 정책을 지정할 수 있습니다:

# /etc/kubernetes/psa-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
  - name: PodSecurity
    configuration:
      apiVersion: pod-security.admission.config.k8s.io/v1
      kind: PodSecurityConfiguration
      defaults:
        enforce: 'baseline'
        enforce-version: 'latest'
        audit: 'restricted'
        audit-version: 'latest'
        warn: 'restricted'
        warn-version: 'latest'
      exemptions:
        usernames: []
        runtimeClasses: []
        namespaces:
          - kube-system
          - kube-public
          - istio-system

8. 실전 트러블슈팅

흔한 오류와 해결법

# 오류: Pod 생성 거부
# Error: pods "my-pod" is forbidden: violates PodSecurity "restricted:v1.30"

# 1. 어떤 필드가 위반인지 확인
kubectl describe pod my-pod -n production-apps 2>&1

# 2. 임시로 warn 모드에서 상세 확인
kubectl label namespace production-apps \
  pod-security.kubernetes.io/enforce=baseline \
  pod-security.kubernetes.io/warn=restricted \
  --overwrite

자주 발생하는 위반 체크리스트

#!/bin/bash
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
  echo "=== Namespace: $ns ==="
  kubectl get pods -n "$ns" -o json | \
    jq -r '.items[] | select(
      .spec.containers[].securityContext == null or
      .spec.securityContext == null
    ) | .metadata.name'
done

9. 퀴즈

Q1: PSA의 세 가지 동작 모드는 무엇이며, 각각의 역할은?
  1. enforce: 정책을 위반하는 Pod의 생성을 거부합니다.
  2. audit: 위반 사항을 감사 로그에 기록하지만 Pod 생성은 허용합니다.
  3. warn: kubectl 사용자에게 경고 메시지를 표시하지만 Pod 생성은 허용합니다.

마이그레이션 시에는 warn/audit를 먼저 적용하고, 충분한 검증 후 enforce를 활성화하는 것이 안전합니다.

Q2: Restricted 프로파일에서 반드시 설정해야 하는 securityContext 항목 4가지는?
  1. runAsNonRoot: true — root 사용자로 실행 금지
  2. allowPrivilegeEscalation: false — 권한 상승 금지
  3. capabilities.drop: ["ALL"] — 모든 Linux capabilities 제거
  4. seccompProfile.type: RuntimeDefault — Seccomp 프로파일 설정

이 4가지를 모두 설정하지 않으면 Restricted namespace에서 Pod 생성이 거부됩니다.

Q3: 기존 클러스터를 PSA로 마이그레이션할 때 권장되는 단계는?
  1. 현재 상태 감사: dry-run으로 위반 사항 파악
  2. warn/audit 적용: 실제 차단 없이 모니터링
  3. 위반 워크로드 수정: securityContext 추가, 권한 최소화
  4. enforce 활성화: 충분한 테스트 후 실제 정책 적용
  5. 클러스터 기본값 설정: AdmissionConfiguration으로 신규 namespace에 자동 적용

점진적 접근이 핵심이며, 절대 한 번에 enforce를 적용하지 않습니다.