둘 다 파드를 여러 개 유지하는 컨트롤러다. 차이는 파드에 정체성을 주는가 하나로 정리된다.
| 항목 | Deployment | StatefulSet |
|---|---|---|
| 파드 이름 | 임의 접미사 | <이름>-0, <이름>-1 고정 |
| 기동·종료 순서 | 동시 | 0 번부터 차례로, 종료는 역순 |
| 저장소 | 모든 복제본이 같은 PVC 를 공유하거나 없음 | volumeClaimTemplates 로 복제본마다 전용 PVC |
| 네트워크 이름 | Service 이름으로만 | headless Service 를 통해 파드마다 고유 DNS 이름 |
| 파드 교체 | 새것을 띄우고 옛것을 내림 | 같은 이름으로 다시 뜨고 같은 PVC 를 다시 잡음 |
상태가 없는 애플리케이션을 StatefulSet 으로 올려도 동작은 한다. 그래서 "굳이 안 되는 이유가 있느냐" 는 질문이 나온다. 실무에서 걸리는 것은 다음이다.
-3 이 CrashLoopBackOff 면 -4 이후는 손도 대지 못한다. Deployment 라면 나머지가 먼저 올라와 서비스는 유지된다.volumeClaimTemplates 로 만들어진 PVC 는 StatefulSet 을 줄여도 자동으로 사라지지 않는다. 쓰지 않는 볼륨이 계속 쌓인다.정리하면, 정체성이 필요 없는데 StatefulSet 을 쓰면 얻는 것 없이 제약만 진다.
"StatefulSet 이 메모리를 더 쓰는가" 는 자주 나오는 오해다. 컨트롤러는 파드를 만들고 순서를 관리할 뿐이고, 메모리를 쓰는 것은 컨테이너 안의 프로세스다. 같은 이미지와 같은 resources 로 띄우면 사용량은 같다.
차이가 보인다면 실제 원인은 다른 데 있다.
실제 사용량은 파드 단위로 확인한다.
kubectl top pod -n <네임스페이스> --containers
StatefulSet 을 수정하다 다음 오류를 만난다.
The StatefulSet "my-app" is invalid: spec: Forbidden:
updates to statefulset spec for fields other than 'replicas', 'ordinals',
'template', 'updateStrategy', 'persistentVolumeClaimRetentionPolicy'
and 'minReadySeconds' are forbidden
메시지에 나열된 것만 바꿀 수 있다. 자주 걸리는 것은 다음 둘이다.
serviceName — headless Service 이름. 파드의 DNS 이름을 결정하므로 바꿀 수 없다.volumeClaimTemplates — PVC 이름과 크기, StorageClass. 이미 만들어진 PVC 와 어긋나므로 막혀 있다.selector 도 마찬가지로 바꿀 수 없다.
오브젝트를 다시 만드는 수밖에 없다. 데이터를 지키려면 파드만 내리고 PVC 는 남긴다.
kubectl -n <네임스페이스> delete statefulset my-app --cascade=orphan
--cascade=orphan 은 StatefulSet 오브젝트만 지우고 파드와 PVC 를 남긴다. 이어서 고친 매니페스트를 적용하면 같은 이름의 파드를 그대로 인수한다.
kubectl -n <네임스페이스> apply -f statefulset.yaml
파드까지 내려도 되는 상황이면 복제본을 0 으로 줄인 뒤 지우고 다시 만든다. PVC 는 명시적으로 지우지 않는 한 남는다.
kubectl -n <네임스페이스> scale statefulset my-app --replicas=0
kubectl -n <네임스페이스> delete statefulset my-app
kubectl -n <네임스페이스> apply -f statefulset.yaml
Helm 이나 kustomize 로 관리 중이라면 위 삭제를 도구 밖에서 하고 다시 적용한다. 도구가 직접 수정하려 들면 같은 오류로 막힌다.
volumeClaimTemplates 의 크기는 바꿀 수 없지만, 이미 만들어진 PVC 자체는 StorageClass 가 allowVolumeExpansion: true 이면 늘릴 수 있다.
kubectl -n <네임스페이스> patch pvc data-my-app-0 \
-p '{"spec":{"resources":{"requests":{"storage":"100Gi"}}}}'
복제본마다 따로 해야 한다. 이후에 만들어질 복제본까지 큰 크기로 받게 하려면 템플릿도 고쳐야 하므로 위의 재생성이 필요하다.