- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 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를 적용하지 않습니다.