오퍼레이터가 파드를 만들려 할 때마다 실패하고 같은 메시지가 반복된다.
pods "sas-cas-server-default-controller" is forbidden:
violates PodSecurity "baseline:latest": hostPath volumes (volume "cas-cache-nvme0")
오퍼레이터는 재조정을 계속 시도하므로 로그가 몇 분 간격으로 같은 오류를 쌓는다. 파드는 아예 만들어지지 않으므로 kubectl get pod 에도 나타나지 않는다. 즉 파드 로그를 볼 수 없고, 오퍼레이터 로그나 워크로드 리소스의 이벤트에서만 원인이 보인다.
Pod Security Admission(PSA) 이 네임스페이스 라벨로 걸려 있다. baseline 과 restricted 프로파일은 hostPath 볼륨을 금지한다. 워크로드가 노드의 로컬 디스크(NVMe 캐시 등)를 hostPath 로 붙이려 하면 어드미션 단계에서 막힌다.
PSA 는 쿠버네티스 1.25 에서 PodSecurityPolicy 를 대체해 기본 내장된 어드미션 컨트롤러다. 세 가지 모드를 각각 다른 프로파일로 둘 수 있다.
| 라벨 | 동작 |
|---|---|
pod-security.kubernetes.io/enforce |
위반하면 생성을 거부한다 |
pod-security.kubernetes.io/audit |
감사 로그에만 남긴다 |
pod-security.kubernetes.io/warn |
요청한 사용자에게 경고만 보낸다 |
kubectl get ns <namespace> --show-labels
kubectl get ns <namespace> -o jsonpath='{.metadata.labels}' | tr ',' '\n'
어떤 리소스가 hostPath 를 쓰는지 찾는다.
kubectl get <kind> <name> -n <ns> -o yaml | grep -n -B3 -A3 hostPath
가장 근본적인 해결이다. 용도에 따라 선택지가 다르다.
| 용도 | 대안 |
|---|---|
| 임시 캐시 · 스크래치 | emptyDir. 메모리 기반이 필요하면 emptyDir.medium: Memory |
| 노드 로컬 디스크 성능이 필요 | Local PersistentVolume 또는 local-path 계열 프로비저너 |
| 여러 파드가 공유 | NFS · CephFS 등 RWX 볼륨 |
Local PV 는 노드에 묶이므로 파드가 그 노드로만 스케줄된다는 점을 감수해야 한다. 그래도 hostPath 와 달리 PVC 를 거치므로 PSA 가 막지 않는다.
제품이 hostPath 를 요구하고 대안이 없다면 그 네임스페이스만 완화한다. 클러스터 전체가 아니라 해당 네임스페이스로 범위를 좁히는 것이 핵심이다.
kubectl label ns <namespace> pod-security.kubernetes.io/enforce=privileged --overwrite
kubectl label ns <namespace> pod-security.kubernetes.io/warn=baseline --overwrite
kubectl label ns <namespace> pod-security.kubernetes.io/audit=baseline --overwrite
강제만 풀고 경고와 감사는 남겨 두면 어떤 워크로드가 기준을 벗어나는지 계속 볼 수 있다. 강제를 아예 떼려면 라벨을 지운다.
kubectl label ns <namespace> pod-security.kubernetes.io/enforce- --overwrite
라벨을 바꿔도 이미 실패한 요청이 자동으로 재시도되지 않는 경우가 있다. 오퍼레이터가 만드는 파드라면 상위 리소스를 건드려 재조정을 유발한다.
kubectl rollout restart deployment/<operator> -n <ns>
privileged 프로파일은 아무 제약도 걸지 않는다. hostPath 하나 때문에 hostNetwork, hostPID, 특권 컨테이너까지 전부 허용된다. 노드 파일 시스템의 임의 경로를 마운트할 수 있으면 컨테이너 탈출로 이어진다.
차선책으로는 강제 프로파일을 baseline 으로 두되, 예외가 필요한 워크로드만 별도 네임스페이스로 분리해 그 네임스페이스만 완화한다. 더 세밀한 제어가 필요하면 Kyverno 나 Gatekeeper 같은 정책 엔진으로 "이 서비스 계정이 만드는 파드의 이 경로만 hostPath 허용" 같은 규칙을 쓴다.
warn 과 audit 으로 먼저 영향 범위를 확인한다.:latest 는 버전 고정을 하지 않았다는 뜻이다. 클러스터를 올릴 때 기준이 강해질 수 있으므로 운영 환경에서는 baseline:v1.31 처럼 버전을 박아 두는 편이 안전하다.