CNPE — 클라우드 네이티브 플랫폼 엔지니어 (전문가) · 플랫폼 API 와 셀프서비스 · 이론
셀프서비스의 담장은 무엇을 막는가
한 줄 요약
셀프서비스에서 중요한 것은 열어 준 것이 아니라 닫아 둔 것입니다. 그리고 닫혔는지는 문서를 읽어서가 아니라 판정으로만 확인할 수 있습니다.
왜 롤을 읽어서는 알 수 없나
인가는 Role 하나로 성립하지 않습니다. Role 과 RoleBinding 이 합쳐지고, 그 위에 ClusterRole 과 ClusterRoleBinding 이 더해지고, 그 결과가 합집합입니다. 그래서 Role 을 아무리 좁게 써도 어딘가에 붙은 다른 바인딩 하나가 그것을 무의미하게 만들 수 있습니다.
확인하는 방법은 하나뿐입니다.
kubectl auth can-i delete appclaims.platform.labhub.io \ -n tenant-blue --as=system:serviceaccount:tenant-blue:blue-dev이 명령은 합쳐진 최종 결과를 답합니다. 열어 준 것과 닫아 둔 것을 둘 다 이렇게 확인해야 합니다. 열린 쪽만 보면 담장이 없는 것을 발견하지 못합니다.
어떻게 동작하나
테넌트에게 주지 않을 것
| 주지 않는 것 | 주면 생기는 일 |
| --- | --- |
| resourcequotas 의 create·patch | 테넌트가 자기 몫을 스스로 늘립니다 |
| roles·rolebindings 의 create | 테넌트가 자기 권한을 스스로 넓힙니다 |
| secrets 의 get | 셀프서비스와 무관한 자격 증명이 열립니다 |
| 커스텀 리소스의 delete | 회수 절차 없이 자원이 사라집니다 |
앞의 두 줄이 특히 중요합니다. 담장을 옮길 권한을 담장 안에 두면 담장이 아닙니다.
삭제를 막는 것은 조금 다른 이유입니다. 삭제 자체가 위험해서가 아니라, 삭제에는 정리해야 할 것이 딸려 있기 때문입니다. 볼륨, DNS 레코드, 외부 계정 같은 것들이 그렇습니다. 그래서 삭제는 회수 절차를 거치게 하고, 그 절차를 플랫폼 팀이 갖습니다.
와일드카드 하나가 전부를 뒤집습니다
verbs: ["*"] 이나 resources: ["*"] 이 한 줄 들어가면 위의 표가 통째로 무효가 됩니다. 그래서 셀프서비스 롤은 필요한 것만 이름으로 적습니다. 편의를 위해 별표를 쓰고 싶어지는 순간이 반드시 오는데, 그때가 담장을 잃는 순간입니다.
개수 상한은 쿼터로만 걸립니다
RBAC 은 "할 수 있는가" 를 답하고 "몇 개까지" 는 답하지 않습니다. 개수는 ResourceQuota 가 셉니다.
spec: hard: count/appclaims.platform.labhub.io: "2"여기에 함정이 하나 있습니다. CRD 를 만든 직후에 그 리소스를 겨냥한 쿼터를 걸면, 쿼터 컨트롤러가 아직 그 리소스를 모르는 상태로 굳습니다. 이 상태의 쿼터는 사용량이 비어 있고, 그 네임스페이스에서 그 리소스를 만들려는 요청은 전부 거절됩니다. 화면에는 상태를 모르겠다는 말만 나옵니다. 고치는 방법은 쿼터를 지웠다가 다시 거는 것 하나뿐이라, 이 순서를 아는 것과 모르는 것의 차이가 큽니다.
현장에서 만나는 모습
한 조직에서 셀프서비스 API 를 연 지 두 달 만에 청구 객체가 400 개를 넘었습니다. 개수 상한을 안 걸었기 때문입니다. 문제는 400 개가 아니라, 그중 몇 개가 실제로 쓰이는지 아무도 몰랐다는 것입니다. 상한은 자원을 아끼려고 거는 것이 아니라, 누군가 한 번 더 생각하게 하려고 겁니다.
또 하나 자주 보는 것은 개발자에게 edit ClusterRole 을 통째로 붙여 주는 것입니다. 그 안에는 시크릿 읽기가 들어 있습니다. 이름이 온순해서 아무도 열어 보지 않습니다.
다음 실습에서 할 것
AppClaim CRD 를 설계해 적용하고, CEL 로 용량과 등급을 묶고, 테넌트 롤로 열 것과 닫을 것을 나눈 뒤, 발급 상한이 실제로 세 번째 요청을 막는지 확인합니다.