마이크로서비스 아키텍처의 핵심은 “큰 모놀리스를 잘게 쪼개 독립적으로 개발·배포·확장”하는 것입니다. 이렇게 하면 전체 애플리케이션을 통째로 손대지 않고, 필요한 서비스만 변경하거나 스케일링할 수 있습니다.
그런데 실무에서는 “서비스를 분리하되, 항상 함께 붙어 다녀야 하는 컴포넌트”가 자주 등장합니다. 대표적으로:
- 메인 애플리케이션 + 웹서버(프록시)
- 메인 애플리케이션 + 로그 수집기
- 메인 애플리케이션 + 설정/인증 토큰 갱신 에이전트
- 메인 애플리케이션 + 로컬 캐시/프록시
이때 두 컴포넌트를 하나로 합쳐서 코드가 부풀어 오르는 것은 피하고 싶고, 그렇다고 서로 완전히 분리된 파드로 만들면 “항상 1:1로 함께 스케일”하기가 어렵습니다. 이 문제를 해결하는 기본 단위가 멀티 컨테이너 파드입니다.
1) 멀티 컨테이너 파드란?
멀티 컨테이너 파드는 말 그대로 하나의 Pod 안에 여러 컨테이너를 넣는 방식입니다. 중요한 특징은 다음 3가지입니다.
(1) 동일한 라이프사이클 공유
- Pod가 생성되면 컨테이너들이 함께 생성되고
- Pod가 삭제되면 컨테이너들도 함께 종료됩니다
즉, “메인 앱 인스턴스당 반드시 1개씩 붙어야 하는 컴포넌트”를 강제로 함께 묶을 수 있습니다.
(2) 동일한 네트워크 네임스페이스 공유
- 같은 Pod 안 컨테이너들은 같은 IP를 공유합니다.
- 서로를
localhost로 호출할 수 있습니다.
따라서 Pod 간 통신을 위해 별도의 Service를 만들 필요 없이, 컨테이너 간 통신이 훨씬 단순해집니다.
(3) 동일한 스토리지 볼륨 공유 가능
- Pod 단위로 볼륨을 정의하고
- 각 컨테이너에 마운트하면
- 컨테이너들이 같은 파일 시스템(공유 디렉터리)을 통해 데이터를 주고받을 수 있습니다.
2) 멀티 컨테이너 파드 생성 방법: containers는 원래 배열이다
Pod 정의 파일에서 spec.containers는 배열(array) 입니다. 단일 컨테이너 파드만 만들었다면 체감이 덜하지만, 이게 배열인 이유가 바로 한 Pod에 여러 컨테이너를 허용하기 위해서입니다.
예시(메인 앱 + 웹 앱 컨테이너 2개):
apiVersion: v1
kind: Pod
metadata:
name: multi-container-demo
spec:
containers:
- name: web-app
image: nginx:1.27
ports:
- containerPort: 80
- name: main-app
image: my-org/main-app:1.0
ports:
- containerPort: 8080
이 구성에서 두 컨테이너는 같은 Pod 안에서 함께 동작하며, main-app이 localhost:80으로 nginx를 호출하거나, nginx가 localhost:8080으로 main-app에 프록시할 수 있습니다.
3) 멀티 컨테이너 파드 디자인 패턴 3가지
강의에서 멀티 컨테이너는 크게 3가지 패턴으로 설명합니다.
- 코로케이티드(Co-located) 컨테이너
- 초기화(Init) 컨테이너
- 사이드카(Sidecar) 컨테이너
각각은 “언제 실행되고, 얼마나 오래 살아있고, 시작 순서를 보장할 수 있는가”가 핵심 차이입니다.
4) 패턴 1: 코로케이티드(Co-located) 컨테이너
개념
- 하나의 Pod에 컨테이너 2개 이상을 그냥 같이 배치
- Pod 라이프사이클 동안 모두 계속 실행되는 것을 전제로 함
- 주로 “서로 강하게 의존하는 두 서비스”를 한 몸처럼 묶을 때 사용
특징
- 컨테이너들이
containers:배열 안에 동일한 레벨로 정의됨 - 시작 순서(누가 먼저 뜨는지)를 보장할 수 없음
- 둘 다 동시에 시작된다고 보는 게 안전
예시
apiVersion: v1
kind: Pod
metadata:
name: colocated-demo
spec:
containers:
- name: web
image: nginx:1.27
ports:
- containerPort: 80
- name: app
image: my-org/app:1.0
ports:
- containerPort: 8080
5) 패턴 2: Init Container (초기화 컨테이너)
개념
- 메인 컨테이너가 뜨기 전에, 먼저 실행되어야 하는 작업이 있을 때 사용
- Init 컨테이너는 실행 후 종료되어야 하며, 모두 성공해야 메인 컨테이너가 시작됩니다.
대표 유즈케이스
- DB가 준비될 때까지 대기(health check loop)
- 초기 데이터/스키마 준비
- 설정 파일 생성/템플릿 렌더링
- 외부 API 준비 여부 확인
특징
initContainers:라는 별도 섹션에 정의- 여러 개를 나열하면 순차적으로 실행(순서 보장)
예시(DB 준비 대기 → 메인 앱 실행):
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
initContainers:
- name: wait-db
image: busybox:1.36
command: ["sh", "-c", "until nc -z mysql 3306; do echo waiting for db; sleep 2; done"]
containers:
- name: main-app
image: my-org/main-app:1.0
ports:
- containerPort: 8080
6) 패턴 3: Sidecar Container (사이드카)
개념
- 메인 앱이 시작되기 전에 먼저 준비되어야 할 수 있고,
- 메인 앱이 실행되는 동안 계속 함께 실행되며,
- 메인 앱이 종료되면 같이 종료되는 “보조 컨테이너” 패턴입니다.
대표적으로 로그 수집기, 프록시, 에이전트가 여기에 들어갑니다.
코로케이티드 vs 사이드카가 헷갈리는 지점
둘 다 Pod 수명 주기 동안 함께 실행된다는 점은 비슷합니다. 차이는 보통 “시작 순서/준비 의존성”에서 발생합니다.
- 코로케이티드: 시작 순서 보장 없음(동등한 컨테이너)
- 사이드카: “먼저 준비되어야 한다”는 요구가 있는 경우가 많음
기본적으로
containers:사이의 “시작 순서”는 보장되지 않으므로, 메인 컨테이너가 사이드카 준비를 기다리는 방식(재시도/헬스체크/파일 생성 대기 등)으로 설계하는 게 일반적입니다.
사이드카 YAML 예시 (로그 수집: app + filebeat)
앱이 파일로 로그를 쓰고, 사이드카(Filebeat)가 같은 볼륨을 마운트해서 로그를 읽어 외부로 전송하는 전형적인 패턴입니다.
apiVersion: v1
kind: Pod
metadata:
name: app-with-filebeat
spec:
volumes:
- name: logs
emptyDir: {}
containers:
- name: app
image: my-org/app:1.0
volumeMounts:
- name: logs
mountPath: /var/log/app
# 예시: 앱이 /var/log/app/app.log에 로그를 기록한다고 가정
- name: filebeat
image: elastic/filebeat:8.12.0
volumeMounts:
- name: logs
mountPath: /var/log/app
# 실제 운영에서는 filebeat.yml을 ConfigMap으로 주입하고,
# Elasticsearch/Logstash endpoint, 인증정보(Secret) 등을 설정합니다.
7) 현실적인 예시: Filebeat 사이드카 + Elasticsearch + Kibana(로그 스택)
강의의 “더 현실적인 예시”는 로그 수집/분석 스택입니다.
- Elasticsearch: 로그를 저장·검색하는 백엔드
- Kibana: 로그 시각화/대시보드
- Filebeat: 애플리케이션 로그를 읽어서 Elasticsearch로 전달하는 경량 수집기(사이드카로 붙이기 좋음)
요구사항:
- 앱이 시작하기 전부터 로그를 놓치지 않게 해야 함(시작 로그)
- 앱이 비정상 종료해도 종료 로그를 수집해야 함(크래시 진단)
- 그래서 Filebeat는 앱과 같은 Pod에서 함께 살아야 함
(아래 예시는 “공유 볼륨으로 로그 파일을 공유”하는 전형적인 구조를 좀 더 명확히 보여줍니다.)
apiVersion: v1
kind: Pod
metadata:
name: app-with-filebeat-and-config
spec:
volumes:
- name: app-logs
emptyDir: {}
- name: filebeat-config
configMap:
name: filebeat-config
containers:
- name: app
image: my-org/app:1.0
volumeMounts:
- name: app-logs
mountPath: /var/log/app
- name: filebeat
image: elastic/filebeat:8.12.0
args: ["-c", "/etc/filebeat/filebeat.yml", "-e"]
volumeMounts:
- name: app-logs
mountPath: /var/log/app
- name: filebeat-config
mountPath: /etc/filebeat
8) 핵심 정리
- 멀티 컨테이너 파드는 “항상 1:1로 함께 붙어야 하는 컴포넌트”를 Pod 단위로 묶는 방법
- 같은 Pod의 컨테이너들은:
- 네트워크 공간 공유 →
localhost통신 가능 - 볼륨 공유 가능
- 같은 라이프사이클로 생성/종료
- 네트워크 공간 공유 →
- 패턴 3가지:
- Co-located: 함께 계속 실행, 시작 순서 보장 없음
- Init: 메인 앱 전에 실행되고 끝남(순차 실행 보장)
- Sidecar: 메인 앱과 함께 오래 실행되는 보조 컨테이너(로그/프록시/에이전트 등)
**사실상 Co-located <-> Sidecar 거의 같은 말 아닌가?
yaml 파일상으로는 거의 같다고 볼 수 있지만 문맥상 Co-located는 메인 서비스가 두 개이고, Sidecar는 하나는 메인 하나는 보조 느낌이라고 보면 됨. 메인보다 먼저 떠야 하는 사이드카인 경우 initContainer를 사용하고 restartPolicy를 Always로 사용하면 되며, 이는 Native Sidecar라고 부르기도 함.
Link to Practice Test: https://uklabs.kodekloud.com/topic/practice-test-multi-container-pods-2/
'CKA' 카테고리의 다른 글
| Application Lifecycle Management - VPA (1) | 2025.12.30 |
|---|---|
| Application Lifecycle Management - 오토스케일링과 HPA (0) | 2025.12.30 |
| Application Lifecycle Management - etcd에 저장되는 secret 암호화하기 (0) | 2025.12.30 |
| Application Lifecycle Management - Secret (0) | 2025.12.30 |
| Application Lifecycle Management - ConfigMap (0) | 2025.12.30 |