- Published on
Pod Security Standards(PSA/PSS) 실전 가이드
- Authors
- Name
- 1. Pod Security Standards란?
- 2. 3가지 보안 프로파일
- 3. PSA 동작 모드
- 4. Restricted 프로파일 호환 Pod 작성
- 5. 마이그레이션 전략
- 6. Namespace별 예외 처리
- 7. AdmissionConfiguration으로 클러스터 기본값 설정
- 8. 실전 트러블슈팅
- 9. 퀴즈

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의 세 가지 동작 모드는 무엇이며, 각각의 역할은?
- enforce: 정책을 위반하는 Pod의 생성을 거부합니다.
- audit: 위반 사항을 감사 로그에 기록하지만 Pod 생성은 허용합니다.
- warn: kubectl 사용자에게 경고 메시지를 표시하지만 Pod 생성은 허용합니다.
마이그레이션 시에는 warn/audit를 먼저 적용하고, 충분한 검증 후 enforce를 활성화하는 것이 안전합니다.
Q2: Restricted 프로파일에서 반드시 설정해야 하는 securityContext 항목 4가지는?
- runAsNonRoot: true — root 사용자로 실행 금지
- allowPrivilegeEscalation: false — 권한 상승 금지
- capabilities.drop: ["ALL"] — 모든 Linux capabilities 제거
- seccompProfile.type: RuntimeDefault — Seccomp 프로파일 설정
이 4가지를 모두 설정하지 않으면 Restricted namespace에서 Pod 생성이 거부됩니다.
Q3: 기존 클러스터를 PSA로 마이그레이션할 때 권장되는 단계는?
- 현재 상태 감사: dry-run으로 위반 사항 파악
- warn/audit 적용: 실제 차단 없이 모니터링
- 위반 워크로드 수정: securityContext 추가, 권한 최소화
- enforce 활성화: 충분한 테스트 후 실제 정책 적용
- 클러스터 기본값 설정: AdmissionConfiguration으로 신규 namespace에 자동 적용
점진적 접근이 핵심이며, 절대 한 번에 enforce를 적용하지 않습니다.