사이드카 컨테이너
사이드카 컨테이너 (Sidecar Containers)
이 기능은 쿠버네티스에서 안정(stable) 기능이에요. v1.33부터 그랬으며, 처음에는 v1.28 릴리스에서 제공됐어요. 이 기능이나 동작을 더 이상 비활성화하거나 선택 해제할 수 없어요(잠겨 있음). 관련 기능 게이트인 SidecarContainers에 값을 명시적으로 설정하면 쿠버네티스는 이를 무시하지만 오류를 보고하지는 않아요.
사이드카 컨테이너는 같은 파드 안에서 기본 애플리케이션 컨테이너와 함께 실행되는 보조 컨테이너예요. 이 컨테이너들은 기본 애플리케이션 코드를 직접 수정하지 않으면서 로깅, 모니터링, 보안, 데이터 동기화 같은 추가 서비스나 기능을 제공해 기본 앱 컨테이너의 기능을 향상하거나 확장하는 데 사용돼요.
보통 파드에는 앱 컨테이너가 하나만 있어요. 예를 들어 로컬 웹서버가 필요한 웹 애플리케이션이 있다면, 로컬 웹서버는 사이드카이고 웹 애플리케이션 자체가 앱 컨테이너예요.
출처: 문서
본문
쿠버네티스의 사이드카 컨테이너
쿠버네티스는 사이드카 컨테이너를 init 컨테이너의 특수한 경우로 구현해요. 사이드카 컨테이너는 파드 시작 후에도 계속 실행돼요. 이 문서는 파드 시작 중에만 실행되는 컨테이너를 명확히 가리키기 위해 '일반 init 컨테이너(regular init containers)'라는 용어를 사용해요.
클러스터에 SidecarContainers 기능 게이트가 활성화되어 있다면(이 기능은 쿠버네티스 v1.29부터 기본으로 활성화), 파드의 initContainers 필드에 나열된 컨테이너에 restartPolicy를 지정할 수 있어요. 이러한 재시작 가능한 사이드카 컨테이너는 다른 init 컨테이너와 같은 파드 안의 기본 애플리케이션 컨테이너와 독립적이에요. 이들은 기본 애플리케이션 컨테이너와 다른 init 컨테이너에 영향을 주지 않고 시작, 중지, 재시작될 수 있어요.
init이나 사이드카 컨테이너로 표시되지 않은 여러 컨테이너로 파드를 실행할 수도 있어요. 이것은 파드 안의 컨테이너들이 파드가 전반적으로 동작하는 데 필요할 때 적절하지만, 어떤 컨테이너를 먼저 시작하거나 중지할지 제어할 필요는 없을 때 그렇죠. 컨테이너 수준의 restartPolicy 필드를 지원하지 않는 더 오래된 쿠버네티스 버전을 지원해야 할 때도 이렇게 할 수 있어요.
예시 애플리케이션
두 컨테이너(그중 하나가 사이드카)가 있는 Deployment의 예시는 다음과 같아요.
참고:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
labels:
app: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: alpine:latest
command: ['sh', '-c', 'while true; do echo "logging" >> /opt/logs.txt; sleep 1; done']
volumeMounts:
- name: data
mountPath: /opt
initContainers:
- name: logshipper
image: alpine:latest
# restartPolicy: Always 로 설정하면 이 컨테이너는 사이드카 컨테이너가 됩니다.
restartPolicy: Always
command: ['sh', '-c', 'tail -F /opt/logs.txt']
volumeMounts:
- name: data
mountPath: /opt
volumes:
- name: data
emptyDir: {}
사이드카 컨테이너와 파드 수명주기
init 컨테이너가 restartPolicy를 Always로 설정해 생성되면, 그 컨테이너는 시작되어 파드의 전체 수명 동안 실행을 유지해요. 이는 보조 서비스를 기본 애플리케이션 컨테이너와 분리해서 실행하는 데 도움이 될 수 있어요.
이 init 컨테이너에 readinessProbe가 지정되면, 그 결과는 파드의 준비(ready) 상태를 결정하는 데 사용돼요.
이 컨테이너들은 init 컨테이너로 정의되므로 일반 init 컨테이너와 같은 순서 및 순차 보장의 이점을 받아, 복잡한 파드 초기화 흐름을 위해 사이드카 컨테이너를 일반 init 컨테이너와 섞을 수 있어요.
일반 init 컨테이너와 비교해, initContainers 안에 정의된 사이드카는 시작된 후에도 계속 실행돼요. 이것은 파드의 .spec.initContainers 안에 항목이 둘 이상 있을 때 중요해요. 사이드카 스타일의 init 컨테이너가 실행 중이 되면(kubelet이 그 init 컨테이너의 started 상태를 true로 설정하면), kubelet은 순서가 있는 .spec.initContainers 목록에서 다음 init 컨테이너를 시작해요. 그 상태는 컨테이너에 실행 중인 프로세스가 있고 시작 프로브(startup probe)가 정의되어 있지 않아서 true가 되거나, startupProbe가 성공한 결과로 true가 돼요.
파드 종료 시, kubelet은 기본 애플리케이션 컨테이너가 완전히 멈출 때까지 사이드카 컨테이너의 종료를 연기해요. 그런 다음 사이드카 컨테이너는 파드 스펙에 나타난 순서의 반대 순서로 종료돼요. 이 접근 방식은 사이드카가 더 이상 필요하지 않을 때까지 파드 안의 다른 컨테이너를 지원하며 계속 동작하도록 보장해요.
사이드카 컨테이너가 있는 Job
쿠버네티스 스타일의 init 컨테이너를 사용해 사이드카를 사용하는 Job을 정의한다면, 각 파드의 사이드카 컨테이너는 기본 컨테이너가 끝난 후에도 Job이 완료되는 것을 방해하지 않아요.
두 컨테이너(그중 하나가 사이드카)가 있는 Job의 예시는 다음과 같아요.
apiVersion: batch/v1
kind: Job
metadata:
name: myjob
spec:
template:
spec:
containers:
- name: myjob
image: alpine:latest
command: ['sh', '-c', 'echo "logging" > /opt/logs.txt']
volumeMounts:
- name: data
mountPath: /opt
initContainers:
- name: logshipper
image: alpine:latest
# restartPolicy: Always 로 설정하면 이 컨테이너는 사이드카 컨테이너가 됩니다.
restartPolicy: Always
command: ['sh', '-c', 'tail -F /opt/logs.txt']
volumeMounts:
- name: data
mountPath: /opt
restartPolicy: Never
volumes:
- name: data
emptyDir: {}
애플리케이션 컨테이너와의 차이
사이드카 컨테이너는 같은 파드에서 앱 컨테이너와 함께 실행돼요. 하지만 기본 애플리케이션 로직을 실행하지 않고, 대신 기본 애플리케이션에 지원 기능을 제공해요.
사이드카 컨테이너는 독립적인 수명주기를 가져요. 앱 컨테이너와 독립적으로 시작, 중지, 재시작될 수 있어요. 즉, 기본 애플리케이션에 영향을 주지 않고 사이드카 컨테이너를 업데이트, 스케일링, 유지보수할 수 있어요.
사이드카 컨테이너는 기본 컨테이너와 같은 네트워크와 저장소 네임스페이스를 공유해요. 이 같은 위치 배치(co-location)로 서로 밀접하게 상호작용하고 리소스를 공유할 수 있어요.
쿠버네티스 관점에서 사이드카 컨테이너의 정상 종료(graceful termination)는 덜 중요해요. 다른 컨테이너가 할당된 전체 정상 종료 시간을 사용하면, 사이드카 컨테이너는 정상적으로 종료할 시간을 갖기 전에 SIGTERM 신호를 받고 이어서 SIGKILL 신호를 받아요. 그래서 파드 종료 시 사이드카 컨테이너의 0이 아닌 종료 코드(0은 성공적인 종료를 나타냄)는 정상적이며 외부 도구가 일반적으로 무시해야 해요.
init 컨테이너와의 차이
사이드카 컨테이너는 기본 컨테이너 옆에서 작동해, 그 기능을 확장하고 추가 서비스를 제공해요.
사이드카 컨테이너는 기본 애플리케이션 컨테이너와 동시에 실행돼요. 이들은 파드의 수명주기 동안 활성이며 기본 컨테이너와 독립적으로 시작·중지될 수 있어요. init 컨테이너와 달리 사이드카 컨테이너는 자신의 수명주기를 제어하는 프로브(probes)를 지원해요.
사이드카 컨테이너는 init 컨테이너처럼 항상 같은 네트워크를 공유하고, 선택적으로 볼륨(파일시스템)도 공유할 수 있기 때문에 기본 애플리케이션 컨테이너와 직접 상호작용할 수 있어요.
init 컨테이너는 기본 컨테이너가 시작되기 전에 중지되므로, 파드의 앱 컨테이너와 메시지를 교환할 수 없어요. 어떤 데이터 전달도 단방향이에요(예: init 컨테이너는 정보를 emptyDir 볼륨 안에 넣을 수 있어요).
사이드카 컨테이너의 이미지를 변경해도 파드가 재시작되지는 않지만, 컨테이너 재시작은 촉발돼요.
컨테이너 간 리소스 공유
init, 사이드카, 앱 컨테이너의 실행 순서를 감안하면 리소스 사용에 대해 다음 규칙이 적용돼요.
- 모든 init 컨테이너에 정의된 특정 리소스 요청·한도 중 가장 큰 값이 유효 init 요청/한도(effective init request/limit)예요. 어떤 리소스에 리소스 한도가 지정되지 않았으면 가장 큰 한도로 간주돼요.
- 파드의 리소스에 대한 유효 요청/한도는 파드 오버헤드와 다음 중 더 큰 값의 합이에요.
- 리소스에 대한 모든 비-init 컨테이너(앱 및 사이드카 컨테이너) 요청/한도의 합
- 리소스에 대한 유효 init 요청/한도
- 스케줄링은 유효 요청/한도에 기반해 수행돼요. 즉, init 컨테이너는 파드 수명 동안 사용되지 않는 초기화용 리소스를 예약할 수 있어요.
- 파드의 유효 QoS 계층의 QoS(서비스 품질) 계층은 모든 init, 사이드카, 앱 컨테이너에 대해 동일한 QoS 계층이에요.
할당량과 한도는 유효 파드 요청과 한도에 기반해 적용돼요.
사이드카 컨테이너와 Linux cgroups
Linux에서 파드 수준 제어 그룹(cgroups)에 대한 리소스 할당은 스케줄러와 같은 유효 파드 요청과 한도에 기반해요.
더 알아보기 (Learn more)
- 사이드카 컨테이너 도입 방법을 배워 보세요.
- 네이티브 사이드카 컨테이너에 대한 블로그 게시물을 읽어 보세요.
- init 컨테이너가 있는 파드 만들기에 대해 읽어 보세요.
- 프로브 유형(liveness, readiness, startup probe)에 대해 배워 보세요.
- 파드 오버헤드에 대해 배워 보세요.