LabHub

사이드카와 컨테이너 조합 패턴 · 세 가지 패턴 · 이론

무엇을 옆에 두는가

LabHub 에서 이어서 보기

한 줄 요약

파드 안의 컨테이너들은 네트워크 네임스페이스와 볼륨을 공유한다. 그 두 가지를 공유하고 싶을 때만 컨테이너를 붙인다. 그 외에는 붙이지 않는다.

왜 이게 필요했나

"기능을 하나 더 붙이자" 는 이유로 사이드카를 늘리면 파드가 무거워지고, 배포 단위가 커지고, 하나가 죽으면 전체가 재시작된다. 사이드카는 공짜가 아니다.

붙일 만한 이유는 결국 셋 중 하나다.

| 패턴 | 무엇을 하나 | 예 |
|---|---|---|
| 사이드카 | 본체를 건드리지 않고 기능을 더한다 | 로그 수집, 지표 변환, 인증서 갱신 |
| 앰배서더 | 본체 대신 바깥과 통신한다 | 서비스 메시 프록시, DB 커넥션 풀 |
| 어댑터 | 본체의 출력을 표준 형식으로 바꾼다 | 앱 고유 지표 → 프로메테우스 형식 |

셋을 가르는 기준은 트래픽의 방향이다. 사이드카는 옆에서 거들고, 앰배서더는 나가는 길목에 서고, 어댑터는 들어오는 요청에 답할 형식을 바꾼다.

어떻게 동작하나

공유되는 것과 안 되는 것을 정확히 알아야 설계가 된다.

| 공유됨 | 공유 안 됨 |
|---|---|
| 네트워크(같은 localhost, 같은 IP) | 파일시스템 루트(각자 자기 이미지) |
| IPC, 볼륨(마운트한 것만) | 프로세스 목록(기본값 — shareProcessNamespace: true 로 켤 수 있다) |

그래서 사이드카가 본체의 로그를 읽으려면 같은 볼륨을 양쪽에 마운트해야 한다. emptyDir 하나를 본체는 /var/log/app 에, 수집기는 /logs 에 마운트하는 식이다.

1.29 가 고친 오래된 문제

예전에는 사이드카가 그냥 "컨테이너 하나 더" 였다. 그래서 두 가지가 어긋났다.

1. 기동 순서를 보장할 수 없었다. 본체가 프록시보다 먼저 뜨면 첫 요청들이 실패한다.
2. Job 이 끝나지 않았다. 본체가 끝나도 사이드카가 계속 살아 있어 Job 이 영원히 Running 이었다.

1.29 부터 initContainersrestartPolicy: Always 를 주면 정식 사이드카가 된다. 초기화 컨테이너처럼 본체보다 먼저 시작하고, 본체가 끝나면 함께 종료된다.

spec:  initContainers:    - name: proxy      image: envoyproxy/envoy:v1.31-latest      restartPolicy: Always      # ← 이 한 줄이 사이드카로 만든다  containers:    - name: app      image: myapp:1.0

흔한 착각

리소스 요청이 더해진다는 것. 파드의 요청량은 컨테이너들의 합이다. 사이드카에 requests.cpu: 100m 를 주면 파드 100개에 10코어가 예약된다. 스케줄러는 그 합을 보고 자리를 찾으므로, 사이드카 하나가 클러스터 밀도를 크게 떨어뜨릴 수 있다.

로그 사이드카가 항상 옳다는 것. 노드마다 하나 도는 DaemonSet 수집기가 대개 더 싸다. 파드마다 수집기를 붙이면 그 수만큼 프로세스가 는다. 사이드카 수집기는 다른 파드와 격리해야 할 때(멀티테넌시)나 파일 경로가 특이할 때만 쓴다.

실무에서 진짜 중요한 것

사이드카는 본체와 생명주기를 공유한다. 사이드카가 OOM 으로 죽으면 그 컨테이너가 다시 뜨는 동안 본체가 기대던 기능이 멈추고, 재시작이 반복되면 파드가 CrashLoopBackOff 로 빠져 통째로 못 쓰게 된다. 그래서 사이드카의 메모리 한도는 넉넉하게, 그리고 본체보다 먼저 죽지 않도록 잡아야 한다. 로그 수집기가 버퍼를 메모리에 쌓는 설정이면 특히 그렇다.