Application Lifecycle Management - 멀티 컨테이터 파드

2025. 12. 30. 19:15·CKA

마이크로서비스 아키텍처의 핵심은 “큰 모놀리스를 잘게 쪼개 독립적으로 개발·배포·확장”하는 것입니다. 이렇게 하면 전체 애플리케이션을 통째로 손대지 않고, 필요한 서비스만 변경하거나 스케일링할 수 있습니다.

그런데 실무에서는 “서비스를 분리하되, 항상 함께 붙어 다녀야 하는 컴포넌트”가 자주 등장합니다. 대표적으로:

  • 메인 애플리케이션 + 웹서버(프록시)
  • 메인 애플리케이션 + 로그 수집기
  • 메인 애플리케이션 + 설정/인증 토큰 갱신 에이전트
  • 메인 애플리케이션 + 로컬 캐시/프록시

이때 두 컴포넌트를 하나로 합쳐서 코드가 부풀어 오르는 것은 피하고 싶고, 그렇다고 서로 완전히 분리된 파드로 만들면 “항상 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가지 패턴으로 설명합니다.

  1. 코로케이티드(Co-located) 컨테이너
  2. 초기화(Init) 컨테이너
  3. 사이드카(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가지:
    1. Co-located: 함께 계속 실행, 시작 순서 보장 없음
    2. Init: 메인 앱 전에 실행되고 끝남(순차 실행 보장)
    3. 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
'CKA' 카테고리의 다른 글
  • Application Lifecycle Management - VPA
  • Application Lifecycle Management - 오토스케일링과 HPA
  • Application Lifecycle Management - etcd에 저장되는 secret 암호화하기
  • Application Lifecycle Management - Secret
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (243)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (119)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      WAS
      @within
      JPQL
      requset scope
      조회 성능 최적화
      gesingleresult
      Thread
      typequery
      @discriminatorcolumn
      고급
      양방향 맵핑
      jdk 동적 프록시
      프록시
      jpq
      김영한
      @args
      스레드
      log trace
      자바
      페치 조인
      락
      빈 후처리기
      cglib
      버퍼
      hibernate5module
      Target
      @discriminatorvalue
      단방향 맵핑
      reentarantlock
      프록시 팩토리
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    Application Lifecycle Management - 멀티 컨테이터 파드
    상단으로

    티스토리툴바