LabHub
배우기 러닝패스 코스

Istio 서비스 메시 · 사이드카의 수명주기와 자원 · 이론

사이드카는 붙는 순간이 아니라 사는 동안이 문제다

LabHub 에서 이어서 보기

한 줄 요약

주입된 프록시의 자원·시작 순서·종료 방식은 파드 주석 몇 개로 정해지고, 그 주석이 실제로 어떤 필드가 되는지는
istioctl kube-inject 로 클러스터에 올리기 전에 확인할 수 있다.

왜 붙인 다음이 더 어려운가

사이드카 주입은 배우기 쉽다. 네임스페이스에 라벨을 걸면 파드마다 컨테이너가 하나 더 생긴다. 문제는
그 다음이다. 프록시는 공짜가 아니고, 앱과 함께 뜨고 함께 죽어야 하며, 어떤 워크로드에는 방해가 된다.

자원부터 보자. 기본 프록시는 CPU 100m, 메모리 128Mi 를 요청하고 상한은 CPU 2코어, 메모리 1Gi 다.
파드 하나로 보면 작지만 파드 2천 개면 요청만으로 CPU 200 코어를 예약한다. 반대로 요청을 너무 낮추면
트래픽이 몰릴 때 프록시가 먼저 느려져 애플리케이션 지연으로 보이는 장애가 난다. 이 손잡이는 워크로드마다
달라야 하고, 그래서 파드 주석으로 조정한다.

두 번째는 시작 순서다. 컨테이너는 원칙적으로 동시에 시작한다. 앱이 빠르고 프록시가 느리면 앱의 첫 몇 초
동안 나가는 요청이 프록시 없이 iptables 규칙에만 걸려 그냥 실패한다. 배포 직후에만 나타나는 5xx 가
이 모양이다. holdApplicationUntilProxyStarts 를 켜면 주입기가 프록시를 컨테이너 목록의 맨 앞에
놓고 postStart 훅을 붙여, 프록시가 준비될 때까지 다음 컨테이너 시작을 붙잡는다.

세 번째가 가장 오래된 함정이다. Job 파드에 프록시가 일반 컨테이너로 들어가면, 본체 작업이 끝나도
프록시는 계속 살아 있다. 파드는 완료로 넘어가지 못하고 배치 파이프라인이 그 자리에 선다. 예전에는
작업 스크립트 마지막에 프록시의 종료 엔드포인트를 호출하는 방식으로 우회했다 — 작업이 실패하면 그 줄이
실행되지 않는다는 결함을 안고. 지금은 쿠버네티스가 재시작 정책을 가진 초기화 컨테이너를 지원하므로
프록시를 그쪽으로 옮긴다. 먼저 시작하고, 파드가 사는 동안 살아 있고, 본체가 끝나면 함께 정리된다.

주석이 어떤 필드가 되는가

| 주석 | 주입 결과에서 바뀌는 곳 |
| --- | --- |
| sidecar.istio.io/proxyCPU, proxyMemory | istio-proxy 의 resources.requests |
| sidecar.istio.io/proxyCPULimit, proxyMemoryLimit | istio-proxy 의 resources.limits |
| proxy.istio.io/config | istio-proxy 의 환경변수 PROXY_CONFIG (JSON 으로 변환된다) |
| proxy.istio.io/configholdApplicationUntilProxyStarts | 컨테이너 순서 + lifecycle.postStart 훅 |
| traffic.sidecar.istio.io/excludeOutboundPorts | istio-init 의 명령줄 인자 |
| sidecar.istio.io/inject: "false" | 프록시와 초기화 컨테이너가 아예 들어가지 않는다 |
| sidecar.istio.io/nativeSidecar: "true" | 프록시가 initContainers 로 옮겨 가고 restartPolicy: Always 를 받는다 |

여기서 중요한 성질 하나 — proxy.istio.io/config 는 값이 문자열인데 그 안에 YAML 을 담는다. 사람이 쓰는
형식과 프록시가 읽는 형식이 다르다는 뜻이라, 오타가 나도 매니페스트 문법은 통과한다. 결과의 환경변수를
직접 열어 보는 습관이 필요한 이유다.

주석을 붙이는 자리도 자주 틀린다. 주입은 파드를 대상으로 하므로 주석은 파드 템플릿에 붙어야 한다.
Deployment 의 메타데이터에 붙이면 문법은 맞고 아무 일도 일어나지 않는다.

현장에서 만나는 모습

가장 자주 보는 것은 "배포한 직후 몇 초만 오류가 난다" 는 신고다. 로그에는 연결 거부만 남고 재현이 안 된다.
시작 순서 보장을 켜면 사라진다. 이 설정이 기본값이 아닌 이유는 파드 시작이 그만큼 느려지기 때문이라,
어디에 켤지는 서비스 성격에 따라 정한다.

두 번째는 "야간 배치가 어제부터 안 끝난다" 이다. 파드는 Running 이고 애플리케이션 로그는 정상 종료를
찍었다. 프록시만 살아 있다. 이런 파드가 쌓이면 배치 큐가 막히고, 원인을 모르면 사람이 파드를 손으로
지우는 운영이 굳어진다.

세 번째는 데이터베이스 연결이다. 프록시가 프로토콜을 잘못 알아보면(포트 이름이 없거나 규칙에 맞지 않으면)
연결이 끊기거나 이상하게 느려진다. 그럴 때 임시로 쓰는 손잡이가 나갈 포트 제외다 — 근본 해법은 포트 이름을
프로토콜에 맞게 붙이는 것이지만, 장애 중에는 이 주석 하나가 시간을 벌어 준다.

이 실습 환경의 한계

실습 파드에서는 진짜 프록시를 띄울 수 없다. 그래서 시작 순서 보장이 실제로 첫 요청을 구해 주는 장면,
Job 파드가 완료로 넘어가지 못하는 장면, 프록시가 메모리를 얼마나 쓰는지는 볼 수 없다. 이 실습이 다루는 것은
선언이 어떤 파드 명세가 되는가이다. 다행히 이 단계에서 잡을 수 있는 실수가 현장 사고의 큰 몫을
차지한다 — 주석을 엉뚱한 자리에 붙였거나, 값의 형식이 틀렸거나, 켰다고 생각한 것이 켜지지 않은 경우다.

다음 실습에서 할 것

아무 주석도 없는 기본 주입 결과를 먼저 읽고, 주석을 하나씩 더해 가며 결과 매니페스트의 어느 필드가
바뀌는지 확인한다. 자원, 프록시 설정, 시작 순서 보장, 나갈 포트 제외, 주입 제외를 차례로 보고,
Job 을 두 가지 방식으로 주입해 프록시가 어느 목록으로 가는지 비교한다. 마지막에는 여덟 장을 한 번에
다시 주입해 결과를 표로 굳히는 스크립트를 만든다.