쿠버네티스 Job을 지우지 않고 기다리게 하는 법: suspend와 리소스 재조정
배치 작업이 바로 실행될 수 없을 때, 우리는 실패로 처리해야 할까 아니면 실행 직전에 조건을 다시 맞춰야 할까?
쿠버네티스 Job을 지우지 않고 기다리게 하는 법: suspend와 리소스 재조정
- 카테고리: infra_dev
- 예상 읽기 시간: 10분
- 오늘의 질문: 배치 작업이 바로 실행될 수 없을 때, 우리는 실패로 처리해야 할까 아니면 실행 직전에 조건을 다시 맞춰야 할까?
- 핵심 출처:
- Kubernetes v1.36: Mutable Pod Resources for Suspended Jobs (beta) - 게시일 2026-04-27, 확인일 2026-06-08
- Kubernetes v1.36: In-Place Vertical Scaling for Pod-Level Resources Graduates to Beta - 게시일 2026-04-30, 확인일 2026-06-08
- Kubernetes v1.35: New level of efficiency with in-place Pod restart - 게시일 2026-01-02, 확인일 2026-06-08
- GKE release notes (Stable channel) - 최신 Stable 채널 문서, 확인일 2026-06-08
1. 왜 지금 봐야 하나
Kubernetes 배치 작업은 그동안 꽤 단순하게 생각하기 쉬웠다. Job을 만들고, 리소스를 요청하고, 스케줄러가 자리를 찾으면 실행한다. 자리가 없거나 조건이 맞지 않으면 대기하거나 실패한다. 작은 서비스의 야간 배치라면 이 모델로 충분하다.
하지만 2026년의 인프라 상황은 조금 다르다. GPU 학습 작업, 대량 데이터 처리, 비용을 낮추기 위한 spot/preemptible 노드, CronJob으로 반복되는 백그라운드 작업이 같은 클러스터를 나눠 쓴다. 작업을 처음 만들 때 정한 CPU, 메모리, GPU 요청이 실제 실행 시점의 최적값이 아닐 수 있다. 클러스터 큐가 “지금은 4 GPU가 아니라 2 GPU만 가능하다”고 판단할 수도 있고, CronJob 하나는 리소스를 줄여서라도 늦게 실행하는 편이 완전히 실패하는 것보다 나을 수 있다.
Kubernetes v1.36의 MutablePodResourcesForSuspendedJobs beta는 이 지점을 겨냥한다. suspended Job의 Pod template 안에 있는 컨테이너 리소스 요청과 제한을 실행 전 또는 재개 전 바꿀 수 있게 했다. 즉, Job을 삭제하고 다시 만들지 않고도 “기다리는 작업”의 실행 조건을 조정할 수 있다.
이 변화는 단순 편의 기능이 아니다. 운영 관점에서는 Job의 identity, metadata, history를 보존하면서 큐잉, 비용 최적화, 실패 회피를 설계할 수 있다는 뜻이다.
2. 핵심 개념
핵심은 Job을 “생성 즉시 실행되는 객체”가 아니라 “실행 전 조정 가능한 작업 요청”으로 보는 것이다.
Kubernetes v1.36 블로그에 따르면 suspended Job에서는 다음 리소스 필드를 바꿀 수 있다.
spec.template.spec.containers[*].resources.requestsspec.template.spec.containers[*].resources.limitsspec.template.spec.initContainers[*].resources.requestsspec.template.spec.initContainers[*].resources.limits
조건은 명확하다.
- Job의
spec.suspend가true여야 한다. - 이미 실행됐다가 suspend된 Job이라면 active Pod가 모두 종료되어
status.active == 0이어야 한다. - 일반적인 리소스 검증은 그대로 적용된다. 예를 들어 limit은 request보다 작을 수 없고, GPU 같은 extended resource는 요구 형식을 지켜야 한다.
이 기능은 새 API 타입을 추가하는 방식이 아니다. 기존 Job과 Pod template 구조를 유지하되, suspended 상태에서 특정 리소스 필드의 immutability 제약을 완화한다. 그래서 운영자가 배워야 할 새 추상화는 많지 않지만, 상태 전이 규칙을 잘못 이해하면 “왜 수정이 거부되지?”라는 문제가 생긴다.
짧게 말하면 이렇다.
실행 중인 Pod를 마음대로 바꾸는 기능이 아니라, 아직 실행되지 않았거나 완전히 멈춘 Job의 실행 조건을 재협상하는 기능이다.
3. 최신 이슈와 연결
Kubernetes 커뮤니티가 최근 다루는 방향은 “삭제 후 재생성”을 줄이는 쪽이다.
첫 번째 흐름은 v1.36의 suspended Job 리소스 변경이다. 기존에는 큐 컨트롤러가 4 GPU Job을 2 GPU로 낮춰 실행하고 싶어도 Job을 삭제하고 다시 만들어야 했다. 이때 metadata, status, history, 외부 시스템에서 잡고 있던 Job identity가 흔들릴 수 있었다. v1.36에서는 suspend 상태에서 리소스를 바꾼 뒤 spec.suspend=false로 재개할 수 있다.
두 번째 흐름은 같은 v1.36의 In-Place Pod-Level Resources Vertical Scaling beta다. 이 기능은 실행 중인 Pod의 aggregate resource budget인 .spec.resources를 조정할 수 있게 한다. 특히 sidecar가 있는 복합 Pod에서 여러 컨테이너가 공유하는 리소스 envelope를 키우거나 줄이는 모델을 제공한다. 단, kubelet은 노드의 allocatable capacity를 확인하고, 불가능하면 PodResizePending 같은 condition으로 상태를 드러낸다.
세 번째 흐름은 v1.35의 RestartAllContainers alpha다. Pod를 삭제하지 않고 전체 컨테이너와 init container를 다시 시작하는 방식이다. 공식 글은 대규모 AI/ML workload에서 Pod 재생성으로 인한 스케줄링 병목과 비용 낭비를 줄일 수 있다고 설명한다. 다만 alpha이고 feature gate가 필요하며, preStop hook에 의존하는 graceful shutdown 가정도 조심해야 한다.
여기에 GKE Stable 채널 릴리스 노트를 보면, 2026년 6월 초 Stable 채널은 1.33, 1.34 계열 패치 타깃을 계속 갱신하고 있으며 5월에는 1.35 패치 타깃도 등장했다. 즉 upstream 블로그의 v1.36 기능을 읽을 때도 “내 managed Kubernetes에서 언제, 어떤 채널로 쓸 수 있는가”는 별도로 확인해야 한다. 새로운 기능이 upstream에 있다고 해서 오늘 운영 클러스터에서 바로 켜도 된다는 뜻은 아니다.
4. 개발자 관점 해석
이 주제의 실전 의미는 “백그라운드 작업을 얼마나 유연하게 실패시키지 않을 것인가”다.
예를 들어 다음과 같은 작업이 있다고 하자.
- 매일 새벽 실행되는 embedding 재생성 CronJob
- 고객별 리포트 생성 worker
- GPU가 있으면 빠르게 돌고, 없으면 작은 배치로 느리게 돌 수 있는 학습 Job
- queue depth가 높을 때만 CPU request를 키우고 싶은 데이터 처리 Job
기존 설계에서는 Job 생성 시점에 리소스를 확정해야 했다. 클러스터 상황이 맞지 않으면 pending이 길어지거나, 별도 컨트롤러가 Job을 삭제하고 다시 만들어야 했다. 이때 idempotency, 외부 DB의 job state, 알림, retry count가 꼬일 수 있다.
suspended Job 리소스 변경은 이 문제를 조금 더 안전한 상태 기계로 바꾼다.
create suspended Job
→ queue/admission controller가 현재 용량과 우선순위 확인
→ resources.requests/limits 조정
→ suspend=false로 실행
→ 실패 시 retry 정책과 외부 idempotency key로 처리
여기서 중요한 tradeoff가 있다.
- 신뢰성: Job을 삭제하지 않으니 identity와 기록이 보존된다. 하지만 리소스를 낮춰 실행하면 처리 시간이 길어지고 timeout이 더 잘 날 수 있다.
- 비용: 비싼 GPU나 큰 메모리 노드를 기다리는 대신 작은 리소스로 진행할 수 있다. 하지만 작은 리소스로 오래 돌면 총 비용이 오히려 늘 수 있다.
- 보안/격리: 큐 컨트롤러가 리소스 필드를 바꿀 권한을 갖는다. 이 권한은 곧 비용과 성능을 바꾸는 권한이므로 RBAC와 audit log가 필요하다.
- 관측성: “Job이 느리다”와 “Job이 낮은 리소스로 재조정되어 실행됐다”는 전혀 다른 사건이다. 리소스 변경 이벤트를 로그와 메트릭에 남기지 않으면 장애 분석 때 원인을 놓친다.
즉 이 기능은 마법 같은 autoscaling이 아니다. 실행 전 협상 지점을 Kubernetes API 안에 공식적으로 마련해주는 기능에 가깝다.
5. 내 프로젝트에 적용할 체크포인트
작은 팀이라도 다음 질문을 던져볼 만하다.
- 지금 우리 CronJob이나 Job 중 “리소스가 부족하면 실패보다 지연 실행이 나은 작업”이 있는가?
- Job을 삭제하고 다시 만들 때 외부 DB의 job id, retry count, 알림 상태가 꼬인 적이 있는가?
- 리소스 request/limit을 낮춰도 correctness가 유지되는 작업과 그렇지 않은 작업을 구분했는가?
- queue controller나 운영 스크립트가 리소스를 바꿀 때 audit log가 남는가?
status.active > 0인 Job을 suspend한 뒤 바로 리소스를 바꾸려고 하는 흐름은 없는가?- managed Kubernetes를 쓴다면 해당 기능이 실제 클러스터 버전과 release channel에서 지원되는지 확인했는가?
- 리소스 하향 조정 시 timeout, batch size, checkpoint interval, retry backoff도 같이 바뀌어야 하는가?
특히 AI 시대의 개발팀은 embedding, eval, batch inference, 데이터 동기화처럼 “서비스 요청 경로 밖에서 돌지만 제품 품질에 중요한 작업”이 늘어난다. 이런 작업은 실패하면 사용자에게 바로 500을 주지는 않지만, 누적되면 검색 품질 저하, 리포트 지연, 비용 폭증으로 이어진다. 그래서 Job 운영 모델은 점점 더 애플리케이션 설계의 일부가 된다.
6. 오늘 10분 액션
오늘은 클러스터를 바꾸지 말고, 내 프로젝트의 Job 하나를 골라 아래 표만 채워보자.
작업 이름:
실패해도 되는가, 늦게라도 끝나야 하는가:
현재 requests/limits:
리소스를 50%로 낮추면 correctness가 유지되는가:
느려질 때 조정해야 할 timeout/batch size:
외부 idempotency key 위치:
Job을 삭제/재생성하면 잃는 metadata 또는 history:
관측해야 할 이벤트: suspended, resource_changed, resumed, failed, retried
그리고 manifests나 Helm chart에서 suspend: true로 시작해도 되는 작업인지 표시만 해둔다. 실제 적용은 클러스터 버전, feature gate, managed service 지원 여부를 확인한 뒤에 한다.
10분 안에 얻어야 할 결론은 하나다.
이 Job은 “바로 실행”이 아니라 “실행 전 조정”이 필요한 작업인가?
그 답이 yes라면, 앞으로 큐 컨트롤러나 운영 스크립트가 리소스와 실행 시점을 협상하는 구조를 설계할 가치가 있다.
7. 더 볼 자료
- Kubernetes v1.36: Mutable Pod Resources for Suspended Jobs (beta)
- Kubernetes v1.36: In-Place Vertical Scaling for Pod-Level Resources Graduates to Beta
- Kubernetes v1.35: New level of efficiency with in-place Pod restart
- GKE release notes (Stable channel)
중복 회피 메모
로컬 content/generated에는 2026-06-08 기준 AI 컨텍스트 관리, Next.js 디버깅, Ethereum PeerDAS 글이 있었고, Supabase의 infra_dev 최근 조회 결과는 0건이었다. 기존 로컬 글 중 Cloudflare Workers tracing, Next.js 보안, Supabase/Postgres deprecation 같은 운영 주제가 있었지만, 이번 글은 Kubernetes batch Job의 suspend 상태, 리소스 재조정, 큐/비용/신뢰성 tradeoff에 집중해 관점을 분리했다.
핵심 출처
로그인하면 이 글을 북마크하고, 나만 보는 한 줄 메모를 남길 수 있어요.
댓글 0
최신순 ▾혹시 이 글을 읽는 동료 개발자가 있다면, GitHub으로 로그인하고 한 줄 흔적을 남겨줘요. (스팸 방지용 로그인이에요)