사이드카(sidecar) 컨테이너
Kubernetes v1.33 [stable](enabled by default)사이드카(sidecar) 컨테이너는 동일한 파드 내에서 메인 애플리케이션 컨테이너와 함께 실행되는 보조 컨테이너이다. 이 컨테이너는 로깅, 모니터링, 보안, 데이터 동기화와 같은 부가적인 서비스나 기능을 제공하여 기본 앱 컨테이너 의 기능을 향상시키거나 확장하는 데 사용되며, 기본 애플리케이션 코드를 직접 변경하지 않는다.
일반적으로 파드 안에는 하나의 앱 컨테이너만이 존재한다. 예를 들어, 어떤 웹 애플리케이션이 로컬 웹서버를 필요로 한다면, 해당 로컬 웹서버가 사이드카이고 웹 애플리케이션 자체가 앱 컨테이너이다.
쿠버네티스의 사이드카 컨테이너
쿠버네티스는 사이드카 컨테이너를 초기화 컨테이너의 특별한 유형으로 구현한다. 사이드카 컨테이너는 파드가 시작된 후에도 계속 실행된다. 이 문서는 파드가 시작 중에만 실행되는 컨테이너를 명확하게 언급하기 위해 일반 초기화 컨테이너 라는 용어를 사용한다.
클러스터에 SidecarContainers 기능 게이트가
활성화되어 있다면(이 기능은 쿠버네티스 v1.29부터 기본적으로 활성화됨),
파드의 initContainers 필드에 나열된 컨테이너에 대해
restartPolicy를 지정할 수 있다.
이러한 재시작 가능한 사이드카 컨테이너는 다른 초기화 컨테이너와
같은 파드 내의 메인 애플리케이션 컨테이너로부터 독립적이다.
이러한 컨테이너는 메인 애플리케이션 컨테이너와
다른 초기화 컨테이너에 영향을 주지 않고 시작, 중지 또는 재시작할 수 있다.
또한 초기화 컨테이너나 사이드카 컨테이너로 표시되지 않은 여러 컨테이너가 있는 파드를 실행하는 것도 가능하다.
이는 파드 내 컨테이너가 전체적으로 파드 작동에 필요하지만,
어떤 컨테이너가 먼저 시작하거나 중지해야 하는지 제어할 필요가 없을 때 적합하다.
또한 컨테이너 수준의 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
command: ['sh', '-c', 'tail -F /opt/logs.txt']
volumeMounts:
- name: data
mountPath: /opt
volumes:
- name: data
emptyDir: {}사이드카 컨테이너와 파드 라이프사이클
restartPolicy가 Always로 설정된 초기화 컨테이너가 생성되면,
파드의 전체 수명 동안 시작되어 계속 실행된다.
이는 메인 애플리케이션 컨테이너와 분리된 보조 서비스를 실행하는 데 유용하다.
이 초기화 컨테이너에 readinessProbe가 지정되어 있다면,
그 결과가 파드의 ready 상태를 결정하는 데 사용된다.
이러한 컨테이너는 초기화 컨테이너로 정의되므로, 일반 초기화 컨테이너와 동일한 순서 및 순차 보장을 활용할 수 있어, 복잡한 파드 초기화 흐름에 대해 사이드카 컨테이너와 일반 초기화 컨테이너를 혼합하여 사용할 수 있다.
일반 초기화 컨테이너와 비교했을 때,
initContainers 내에 정의된 사이드카는 시작한 후에도 계속 실행된다.
이는 파드에서 .spec.initContainers 안에 두 개 이상의 항목이 있을 때 중요하다.
사이드카 스타일의 초기화 컨테이너가 실행 중이면(kubelet이 해당 초기화 컨테이너의 started 상태를 true로 설정함),
kubelet은 정렬된 .spec.initContainers 목록에서 다음 초기화 컨테이너를 시작한다.
이 상태는 컨테이너에 실행 중인 프로세스가 있고 시작(Startup) 프로브가 정의되지 않았을 때나,
혹은 startupProbe가 성공했을 때 true가 된다.
파드 종료 시, kubelet은 메인 애플리케이션 컨테이너가 완전히 중지될 때까지 사이드카 컨테이너 종료를 연기한다. 이후 사이드카 컨테이너는 파드 명세에 나타난 순서의 역순으로 종료된다. 이 접근 방식은 사이드카가 더 이상 필요하지 않을 때까지 파드 내의 다른 컨테이너를 지원하면서 작동 상태를 유지하도록 보장한다.
사이드카 컨테이너가 있는 잡(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
command: ['sh', '-c', 'tail -F /opt/logs.txt']
volumeMounts:
- name: data
mountPath: /opt
restartPolicy: Never
volumes:
- name: data
emptyDir: {}애플리케이션 컨테이너와의 차이점
사이드카 컨테이너는 동일한 파드 안에서 앱 컨테이너 와 함께 실행된다. 그러나, 기본 애플리케이션 로직을 실행하지 않으며, 대신 메인 애플리케이션을 보조하는 기능을 제공한다.
사이드카 컨테이너는 자체적으로 독립된 라이프사이클을 가진다. 앱 컨테이너와 독립적으로 시작, 중지 및 재시작될 수 있다. 이는 기본 애플리케이션에 영향을 주지 않고 사이드카 컨테이너를 업데이트, 스케일링 또는 유지 관리할 수 있다는 의미이다.
사이드카 컨테이너는 기본 컨테이너와 동일한 네트워크 및 스토리지 네임스페이스를 공유한다. 이러한 공동 배치를 통해 밀접하게 상호 작용하고 리소스를 공유할 수 있게 한다.
쿠버네티스 관점에서, 사이드카 컨테이너의 그레이스풀(graceful) 종료는 그리 중요하지 않다.
다른 컨테이너들이 그레이스풀 종료에 할당된 시간을 모두 사용하고 나면,
사이드카 컨테이너는 그레이스풀하게 종료를 수행할 시간을 받지 않고, 바로 SIGTERM 신호를 받은 뒤 SIGKILL 신호를 받게 된다.
따라서 종료 코드가 0(0은 성공적인 종료를 의미)이 아니더라도, 이는 파드 종료 시 사이드카 컨테이너에 대해서는 정상이므로,
외부 도구에서는 일반적으로 무시해야 한다.
초기화 컨테이너와의 차이점
사이드카 컨테이너는 메인 컨테이너와 함께 작동하여 기능을 확장하고 추가 서비스를 제공한다.
사이드카 컨테이너는 메인 애플리케이션 컨테이너와 동시에 실행된다. 파드의 라이프사이클 전체에 걸쳐 활성 상태이며, 메인 컨테이너와 독립적으로 시작하고 중지할 수 있다. 초기화 컨테이너와 달리, 사이드카 컨테이너는 라이프사이클을 제어하기 위한 프로브(Probe)를 지원한다.
사이드카 컨테이너는 초기화 컨테이너와 마찬가지로 항상 동일한 네트워크를 공유하고, 선택적으로 볼륨(파일시스템)도 공유할 수 있기 때문에 메인 애플리케이션 컨테이너와 직접 상호 작용할 수 있다.
초기화 컨테이너는 메인 컨테이너가 시작되기 전에 중지되므로,
초기화 컨테이너는 파드 내 앱 컨테이너와 메시지를 교환할 수 없다.
모든 데이터 전달은 단방향이다(예: 초기화 컨테이너는 emptyDir 볼륨 내부에 정보를 넣을 수 있음).
사이드카 컨테이너의 이미지를 변경하면 파드가 재시작되지는 않지만, 컨테이너 재시작에 대한 트리거가 된다.
컨테이너 내 리소스 공유
초기화, 사이드카 및 앱 컨테이너의 실행 순서를 고려할 때, 리소스 사용에 대한 다음 규칙이 적용된다.
- 모든 초기화 컨테이너에 정의된 특정 리소스 요청 또는 한도의 최댓값이 유효 초기화 요청/한도이다. 어떤 리소스에 리소스 한도가 지정되지 않은 경우, 이것이 최고 한도로 간주된다.
- 리소스에 대한 파드의 유효 요청/한도는
파드 오버헤드와 다음 중 더 높은 값의 합이다.
- 모든 비초기화 컨테이너(앱 및 사이드카 컨테이너)의 리소스에 대한 요청/한도의 합
- 리소스에 대한 유효 초기화 요청/한도
- 스케줄링은 유효 요청/한도를 기반으로 수행되며, 이는 초기화 컨테이너가 파드의 수명 동안 사용되지 않는 초기화를 위한 리소스를 예약할 수 있음을 의미한다.
- 파드의 유효 QoS 클래스의 QoS(서비스 품질) 계층은 모든 초기화, 사이드카 및 앱 컨테이너 모두에 대한 QoS 계층이다.
쿼터와 한도는 유효 파드 요청 및 한도를 기반으로 적용된다.
사이드카 컨테이너와 리눅스 cgroups
리눅스에서 파드 수준 제어 그룹(cgroups)에 대한 리소스 할당은 스케줄러와 동일하게 유효 파드 요청 및 한도를 기반으로 한다.
다음 내용
- 사이드카 컨테이너 채택 방법 배우기
- 네이티브 사이드카 컨테이너 블로그 게시물 읽기
- 초기화 컨테이너가 있는 파드 생성에 대해 읽기
- 프로브 종류 에 대해 알아보기: liveness, readiness, startup 프로브
- 파드 오버헤드에 대해 알아보기