IT/Kubernets

Native sidecar 마이그레이션, 이거 하나만 조심하면 된다

gfrog 2026. 8. 20. 15:12

오늘 알게 된 건데, 아직도 Istio sidecar나 Vault agent를 그냥 containers[]에 박아넣고 쓰시는 분들 꽤 많더라. 우리 팀도 그랬다. 근데 최근 클러스터 1.33 올리면서 native sidecar (초기 컨테이너 restartPolicy: Always)로 싹 옮겼는데, 딱 하나 함정이 있어서 공유한다.

뭐가 좋아졌나

원래 sidecar 패턴의 고질병이 두 개였다. 하나는 앱 컨테이너보다 sidecar가 늦게 뜨면 초기 요청이 실패하는 거. 또 하나는 Job에서 sidecar가 안 죽어서 Pod가 Completed로 안 넘어가는 거. Vault agent injector 쓰는 팀이면 다들 겪어봤을 거다.

Kubernetes 1.33에서 native sidecar가 stable 됐고, 이제는 initContainers[]에 넣고 restartPolicy: Always만 붙이면 된다:

spec:
  initContainers:
  - name: vault-agent
    image: hashicorp/vault:1.17
    restartPolicy: Always   # 이 한 줄이 sidecar로 만든다
    # ...
  containers:
  - name: app
    image: myapp:latest

이러면 vault-agent가 먼저 뜨고, Ready 상태가 되어야 앱 컨테이너가 시작된다. 그리고 앱이 끝나면 sidecar도 SIGTERM 받고 알아서 종료된다. 진짜 깔끔하다.

근데 조심할 게 하나 있다

terminationGracePeriodSeconds 계산이 예전이랑 다르다. 우리는 이걸 놓쳐서 배포 하나 완전 말아먹었다.

Native sidecar는 앱 컨테이너가 먼저 SIGTERM 받고 종료된 후에야 sidecar에 SIGTERM이 간다. 즉, Pod 전체 grace period 안에서 앱 종료 시간 + sidecar 종료 시간이 모두 끝나야 한다는 뜻이다. 예전 sidecar 패턴처럼 병렬로 죴는 게 아니다.

우리 앱은 in-flight 요청 flush에 20초 걸리고, Vault agent는 토큰 lease revoke에 15초 정도 걸린다. 예전에는 grace period 30초로 잡아도 문제없었는데 (병렬로 처리되니까), native로 바꾸고 나서 gracefully 종료가 안 되고 강제 kill 당하는 케이스가 늘었다. kubectl get events 뒤져보니 FailedPreStopHook 로그가 잔뜩 찍혀 있더라.

결국 terminationGracePeriodSeconds: 60으로 늘렸다. 대충 (앱 종료 시간 + sidecar 종료 시간) * 1.5 정도 잡는 게 안전한 것 같다.

마이그레이션 순서

우리는 이렇게 했다:

  1. 스테이징에 native sidecar로 배포 → grace period 로그 관찰 (1주일)
  2. 낮은 트래픽 서비스부터 프로덕션 rollout
  3. Job/CronJob은 마지막에. Pod completion 동작 바뀌는 게 가장 크리티컬해서.

Job에서 특히 편해졌다. 예전에는 Vault agent 안 죽어서 Job이 Complete 안 되는 거 workaround 하려고 sidecar에 exit 0 트리거 파일 감시하는 스크립트까지 넣었었는데, 그거 다 지워버렸다. 코드 200줄 정도 줄었다.

정리하면

restartPolicy: Always 붙이는 건 쉬운데, grace period 재계산 안 하면 곤란해질 수 있다. 프로덕션 옮기기 전에 반드시 앱 shutdown + sidecar shutdown 시간 재고 여유 두고 잡자. 다른 팀에서 다른 함정 겪은 분 있으면 댓글로 알려주세요.