CNPE — 클라우드 네이티브 플랫폼 엔지니어 (전문가) · 생성 버튼을 넘어 변경과 회수까지 · 이론
변경과 삭제까지 책임지는 셀프서비스 API
한 줄 요약
좋은 셀프서비스는 생성 이후에도 요청과 실제 상태의 차이를 수렴시키고, 삭제 요청과 실제 회수 완료를 구분하며 다른 팀의 자원을 보존합니다.
왜 이게 필요했나
플랫폼 데모에서는 앱이 한 번 생성되면 박수를 받습니다. 운영에서는 그 뒤가 더 깁니다. 복제수를 늘리고, 새 설정을 반영하고, 사용하지 않는 환경을 지웁니다. 사용자는 “변경했습니다”라는 응답을 보지만 일부 파드는 이전 설정으로 응답할 수 있습니다. 삭제 요청은 성공했는데 비용을 발생시키는 자원이 남을 수도 있습니다. 생성만 자동화하고 나머지를 사람에게 맡기면 운영 부담은 다른 이름으로 돌아옵니다.
개발자가 하위 Deployment를 직접 고친 상황도 생각해 봅시다. App 요청은 2개인데 Deployment를 3개로 바꾸면 무엇이 원본일까요? 이 실습에서는 App이 원본입니다. 컨트롤러는 차이를 관측해 하위 자원을 다시 2개로 돌립니다. 복귀 자체가 버그가 아니라 선언한 계약의 결과입니다. 지속하려는 변경은 원본 요청에 해야 합니다.
어떻게 동작하나
변경 검증은 이전과 같은 UID의 요청인지부터 시작합니다. Kubernetes의 이름은 재사용할 수 있습니다. parcel을 삭제하고 같은 이름으로 새로 만들면 URL과 이름은 같아 보여도 UID가 다릅니다. 이전 앱의 성공 기록을 새 앱의 증거로 사용하면 안 되는 이유입니다. 하위 Deployment의 UID도 함께 연결하면 자원을 지우고 다시 만든 우회를 구분할 수 있습니다.
다음은 세대입니다. Deployment의 metadata.generation은 원하는 설정의 변경을 표현하고 status.observedGeneration은 컨트롤러가 관측한 세대를 나타냅니다. 이전 세대에서 Ready였던 상태가 새 선언 직후에도 잠시 보일 수 있습니다. 그래서 관측 세대가 현재 세대인지, 새 복제본과 가용 복제본 수가 목표와 같은지, 종료 중인 이전 파드가 남아 있는지, 현재 파드가 실제 preview 응답을 내는지를 함께 확인합니다.
실험으로 하위 자원을 3개로 바꾼 뒤 최종 결과가 2개인 것만 제출하면 실제로 차이를 만들었는지 알 수 없습니다. 처음부터 2개였어도 같은 결과이기 때문입니다. 이번 실습의 실험 도우미는 API가 저장한 3개 상태의 패치 응답을 보관합니다. 그 세대보다 뒤의 세대에서 2개로 복귀했는지 확인하여 변화의 앞뒤를 연결합니다. 상태 하나와 사건의 흐름은 다른 종류의 증거입니다.
삭제에도 단계가 있습니다. 삭제 요청을 받은 API 서버는 deletionTimestamp를 표시할 수 있습니다. finalizer가 남아 있으면 객체는 곧바로 사라지지 않습니다. 이 표식은 해당 컨트롤러가 정리 절차를 마칠 기회를 주기 위한 장치입니다. 장애 대응 중 finalizer를 전부 지우면 눈앞의 객체는 없어질 수 있지만, 소유자가 책임져야 할 외부 자원이 남을 수 있습니다.
실습에서는 교육용 보류 표식 하나를 넣어 삭제 중 상태를 관찰합니다. 이 표식은 상위 요청의 부재를 늦출 뿐, 모든 하위 자원이 살아 있다고 보장하지 않습니다. 컨트롤러가 하위 자원을 먼저 회수할 수도 있으므로 매번 실제 상태를 봐야 합니다. 해제할 때는 해당 표식 하나만 제거하고, UID와 resourceVersion을 대조해 사이에 일어난 변경을 덮어쓰지 않습니다.
현장에서 만나는 모습
“조회 결과가 없다”에도 두 뜻이 있습니다. 목록 API가 정상 응답했고 대상이 없는 경우와, 인증·통신 문제로 목록을 얻지 못한 경우입니다. 후자를 빈 목록으로 바꾸면 삭제 검사기가 장애를 성공으로 보고합니다. 실습은 App·Deployment·ReplicaSet·Service·Pod 각각의 목록 조회가 성공하고 대상이 없을 때만 부재를 인정합니다.
범위도 확인해야 합니다. team-a를 정리하면서 team-b까지 삭제하면 내 앱은 확실히 사라집니다. 그러나 그것은 성공한 정리가 아닙니다. 다른 팀 sentinel의 UID와 실제 응답이 그대로인지 대조하여 필요한 자원만 회수했는지 확인합니다. 이 실습은 개인 VM 안의 팀 권한 분리를 다루며, 네임스페이스만으로 모든 네트워크·자원 격리가 완성됐다고 주장하지 않습니다.
다음 실습에서 할 것
같은 요청을 preview·2복제로 변경하고, 하위 자원의 수동 변경이 원본으로 복귀하는 것을 관측합니다. 이어서 삭제 중 상태와 실제 회수를 나누어 기록하고 다른 팀이 보존됐는지 확인합니다. 마지막에는 관측 실패와 모순을 unknown으로 남기는 작은 진단기를 작성합니다. 없는 정보에서 성공을 추정하지 않는 습관이 목표입니다.
공식 문서
- [Crossplane Composite Resources](https://docs.crossplane.io/v2.4/composition/composite-resources/)
- [Kubernetes 객체 소유 관계](https://kubernetes.io/docs/concepts/overview/working-with-objects/owners-dependents/)
- [Kubernetes Finalizers](https://kubernetes.io/docs/concepts/overview/working-with-objects/finalizers/)