CKS — 쿠버네티스 보안 전문가 · 진짜 클러스터에서 확인하기 · 이론
막히는 시점이 다르면 고치는 곳도 다르다
한 줄 요약
설정을 쓰는 연습과 그 설정이 지켜지는 것을 확인하는 연습은 다릅니다. 사고는 언제나 후자에서 납니다.
왜 강제되는 곳에서 해야 하나
앞 모듈들에서 securityContext 와 Pod Security 를 여러 번 썼습니다. 그런데 그 실습들이 도는 곳에는 kubelet 도 컨테이너 런타임도 없어서, 위반한 파드도 그냥 Running 이 되었습니다.
설정을 쓰는 연습은 되었지만 그 설정이 지켜지는 것을 확인하는 연습은 되지 않았습니다. 그리고 실무에서 사고가 나는 자리는 후자입니다 — 설정을 다 써 놓고 적용되지 않은 상태가 정상처럼 보이기 때문입니다.
같은 "안 된다" 가 세 층에 흩어져 있다
| 층 | 무엇이 여기 있나 | 증상 | 언제 보이나 |
|---|---|---|---|
| 어드미션 | Pod Security Admission, 정책 엔진 | kubectl apply 가 거부됨 | 배포 전 (CI) |
| kubelet | runAsNonRoot, 이미지 USER 검사 | 파드는 생성, CreateContainerConfigError | 배포 직후 |
| 런타임 | 읽기 전용 루트, capability, seccomp | 파드는 Running, 앱만 실패 | 그 코드 경로를 탈 때 |
가장 좋은 것은 어드미션입니다. 피드백이 즉시 오고, 잘못된 것이 아예 클러스터에 들어오지 않습니다.
가장 나쁜 것은 런타임입니다. 파드는 멀쩡히 돌고 있어서, 증상이 애플리케이션 오류로 보입니다. 평소에는 괜찮다가 특정 코드 경로에서만 실패하는 일도 흔합니다.
그래서 순서가 있습니다. 앞 층에서 막을 수 있는 것을 뒤 층에 맡기지 않습니다.
Pod Security Admission 은 warn 부터
enforce 를 바로 걸면 이미 도는 워크로드가 다음 재배포에서 전부 막힙니다. 그것 자체가 장애입니다.
pod-security.kubernetes.io/warn: restricted # 먼저 이것만pod-security.kubernetes.io/enforce: restricted # 경고가 0 이 된 뒤에끊고 나서 세는 것이 아니라 세고 나서 끊는 순서입니다.
실무에서 진짜 중요한 것
앞 층에서 막을 수 있는 것을 뒤 층에 맡기지 않습니다. 어드미션에서 걸리면 CI 에서 즉시 알 수 있지만, 런타임에서 걸리면 파드가 멀쩡히 도는 채로 특정 코드 경로에서만 실패해 애플리케이션 오류처럼 보입니다. 같은 규칙이라도 어디서 강제하느냐가 대응 비용을 열 배 가릅니다.
enforce 는 경고가 0 이 된 뒤에 겁니다. 바로 걸면 이미 도는 워크로드가 다음 재배포에서 전부 막히고, 그것 자체가 장애입니다. warn 으로 먼저 세고 나서 끊는 순서를 지켜야 합니다.
runAsNonRoot 실패는 파드 생성 실패로 보이지 않습니다. 파드는 만들어지고 CreateContainerConfigError 만 남아서, 이미지의 USER 를 의심하기까지 시간이 걸립니다. 이미지를 만들 때 USER 를 명시해 두는 것이 가장 값싼 예방입니다.
다음 실습에서 이 셋을 진짜 클러스터 위에서 하나씩 확인합니다.