핵심 한 줄

쿠버네티스는 파드(컨테이너 묶음)를 컨트롤러(디플로이먼트→레플리카셋)로 자동 관리하고, 서비스로 네트워크를 추상화한다. 키워드는 셀프힐링·오토스케일·무중단 배포.


1. 파드 (Pod)

쿠버네티스의 최소 배포 단위. 1개 이상의 컨테이너를 묶고, 네트워크(같은 IP)·볼륨을 공유한다.

사이드카 패턴 (Sidecar)

  • 한 파드에 메인 컨테이너 + 보조 컨테이너(로그 수집기, 프록시 등)를 함께 배치
  • 볼륨 공유로 메인이 쓴 로그를 사이드카가 읽어 수집·외부 전송
  • 메인 컨테이너 코드를 건드리지 않고 부가 기능(로깅·모니터링·통신)을 분리하는 게 목적

대표 사례

메인 앱 + 로그 컨테이너(Fluentd 등) → 공유 볼륨의 로그를 사이드카가 외부로 전송. 서비스 메시(Envoy 프록시 주입)도 같은 패턴.


2. 워크로드 컨트롤러

디플로이먼트 (Deployment)

  • 파드 셀프힐링 가능: 파드가 죽으면 자동 재생성
  • 정확한 구조: 디플로이먼트 → 레플리카셋 → 파드
    • 레플리카셋(ReplicaSet): 지정한 개수의 파드를 유지·관리 (실제로 파드를 직접 감시)
    • 디플로이먼트: 레플리카셋을 관리하며 배포(rollout)·롤백 담당
  • 즉, 셀프힐링은 레플리카셋이, 버전 관리는 디플로이먼트가 한다.
Deployment ──관리──▶ ReplicaSet ──관리──▶ Pod, Pod, Pod
   (배포/롤백)          (개수 유지/셀프힐링)

롤링 업데이트 (Rolling Update)

  • 새 버전 파드를 하나씩 만들면서 기존 파드를 하나씩 제거하는 과정을 반복
  • 서비스 중단 없이 점진 교체 → 무중단 배포
  • 문제 발생 시 디플로이먼트로 롤백 가능

HPA (Horizontal Pod Autoscaling)

  • 부하량(CPU·메모리·커스텀 지표)에 따라 파드 개수를 자동 조절
  • 수평 확장(파드 수 늘리기) — 트래픽 급증 시 자동 스케일아웃, 한산하면 스케일인
  • (cf. 수직 확장 VPA는 파드 자원 자체를 키움 — HPA와 구분)

3. 서비스 (Service)

파드는 죽고 살아나며 IP가 계속 바뀐다. 서비스는 고정 진입점(고정 IP/DNS) + 부하분산을 제공해 클라이언트가 파드에 쉽게 접근하게 한다.

타입접근 범위용도우리 케이스
ClusterIP클러스터 내부 파드 간 통신만내부 서비스 연결 (기본값)risk·merchant-limit·order·redis·kafka-bootstrap — 파드끼리 DNS로 호출
NodePort내부 + 외부에서 노드IP:포트 접근 (30000~32767)테스트·개발, 클러스터 밖 클라이언트merchant-limit-np:31574 — 클러스터 밖 k6 시드가 merchant 생성용으로 직접 호출
LoadBalancer외부 LB를 통해 노출클라우드 환경 외부 노출k3s 내장 **klipper-lb(svclb)**가 역할 담당 → Traefik이 이 타입으로 노드:80/443 개방
ExternalNameDNS CNAME 리다이렉트클러스터 외부 서비스에 내부 DNS명 부여미사용

Ingress — L7 라우팅 규칙

서비스가 L4(IP:Port) 분산이라면, 인그레스는 L7(경로·호스트 기반) 라우팅 규칙이다. 서비스 타입이 아니라 별도 오브젝트.

  • 인그레스 컨트롤러가 규칙을 실행함 — k3s 내장은 Traefik.
  • 우리: 경로 / → payment Service. Traefik이 LoadBalancer 타입 서비스로 노드에 바인딩.

외부 노출 전략

NodePort/LoadBalancer는 L4, 인그레스는 L7. 도메인·경로 기반 분기·TLS 종료까지 한 곳에서 처리하려면 인그레스를 쓴다.


4. 컨트롤 플레인 / 노드 컴포넌트

쿠버네티스(k3s 포함)는 **컨트롤 플레인(마스터)**과 워커 노드로 나뉜다.

컨트롤 플레인

컴포넌트역할우리 케이스
kube-apiserver (:6443)모든 요청의 정문 (kubectl·kubelet·컨트롤러 전부 여기로)agent join, kubectl 명령 전부 apiserver 경유
kube-scheduler파드를 어느 노드에 배치할지 결정 (nodeSelector·taint/toleration·anti-affinity 반영)payment를 전용 노드풀에 배치한 주체
controller-manager제어 루프 집합체 (Deployment→ReplicaSet→Pod 관리, 롤아웃 조정)레플리카셋 개수 유지, 롤링업데이트 실행
datastore클러스터 상태 저장. k3s 기본은 SQLite (단일 서버, etcd 아님)단일 서버 구성; HA 전환 시 etcd/외부 DB 필요

워커 노드 (전 노드에 존재)

컴포넌트역할우리 케이스
kubeletapiserver와 통신, containerd로 컨테이너 실행·상태 보고각 노드에서 파드 실행·헬스 보고
kube-proxyiptables/ipvs 프로그래밍 → ClusterIP·NodePort L4 분산payment Service → 3파드 분산이 이것
flannel (CNI)파드망 10.42.0.0/16, 노드 간 파드 트래픽 VXLAN 캡슐화멀티 노드 간 파드 직통 통신
CoreDNS서비스명 → ClusterIP DNS 해석payment-svc 같은 이름 → IP 변환
Traefik + klipper-lbk3s 내장 Ingress 컨트롤러 + 서비스 LB (노드:80/443)외부 트래픽 수신 → payment Service 전달

5. 한눈에 정리

  • 파드: 컨테이너 묶음, 네트워크·볼륨 공유 → 사이드카로 부가기능 분리
  • 레플리카셋: 파드 개수 유지(셀프힐링)
  • 디플로이먼트: 레플리카셋 관리 + 롤링업데이트/롤백
  • HPA: 부하 기반 파드 수 자동조절
  • 서비스: 고정 IP + 부하분산 (ClusterIP=내부, NodePort=외부직접:30000~32767, LoadBalancer=LB위임, Ingress=L7 경로기반)
  • 컨트롤 플레인: apiserver(정문:6443)·scheduler(배치결정)·controller-manager(제어루프)·datastore(k3s=SQLite)
  • 노드: kubelet(실행·보고)·kube-proxy(L4분산)·flannel(CNI 10.42.0.0/16)·CoreDNS(이름해석)

6. Strimzi — Kafka 오퍼레이터

Kubernetes Operator 패턴

  • CRD(Custom Resource Definition) 로 상태를 선언하면, 오퍼레이터가 실체(파드·서비스·스토리지)로 reconcile한다.
  • StatefulSet을 손으로 관리하는 대신 원하는 상태를 YAML로 선언하고, 오퍼레이터가 현재 상태와 차이를 지속 조정.

우리 케이스

CRD역할
Kafka클러스터 전체 선언 (KRaft 모드, 3-broker, RF3 / minISR2)
KafkaNodePool브로커·컨트롤러 노드 풀 분리 선언
KafkaTopic토픽별 파티션·RF 선언 (4토픽)
  • 3-broker 클러스터를 Strimzi로 선언 배포 — ZooKeeper 없이 KRaft, RF3/minISR2 설정.

Operator 패턴 핵심

“어떻게 만들지”가 아니라 “무엇이 있어야 하는지” 를 선언. 오퍼레이터가 나머지를 책임진다.



7. ConfigMap / Secret

  • ConfigMap = 비민감 설정(평문). Secret = 민감정보(base64 인코딩만 — 암호화 아님. RBAC + etcd 암호화로 보호).
구분ConfigMapSecret
저장 형식평문base64 인코딩
용도DB URL·Kafka bootstrap·Redis host 등비밀번호·토큰·인증서
보호 수단없음RBAC + etcd 암호화

주입 방법

방식설명
envFrom: configMapRefConfigMap의 모든 키를 환경변수로 한 번에 주입
env.valueFrom.secretKeyRefSecret의 특정 키 하나만 환경변수로 주입
볼륨 마운트파일로 마운트 — 값 변경 시 파드 재시작 없이 자동 반영

우리 케이스

  • ConfigMap app-config: DB URL, Kafka bootstrap, Redis host → envFrom: configMapRef로 일괄 주입
  • Secret db-cred: DB 크리덴셜 → SPRING_DATASOURCE_USERNAME/PASSWORD는 valueFrom: secretKeyRef로 개별 주입

함정

envFrom 주입값은 파드 시작 시 고정 → ConfigMap/Secret 값을 바꿔도 파드를 재시작해야 반영. 볼륨 마운트는 자동 반영.


8. 프로브와 셀프힐링

프로브실패 시 동작목적
readinessProbeService Endpoints에서 제외 (파드 유지)트래픽 받을 준비 확인
livenessProbekubelet이 컨테이너 재시작생사 확인
startupProbe성공 전까지 다른 프로브 보류느린 초기화 보호
  • 셀프힐링 관계: liveness 실패 → kubelet이 재시작. readiness 실패 → Endpoints에서 빠져 트래픽 차단(파드 자체는 유지).
  • startupProbe가 성공하기 전까지 liveness/readiness는 평가되지 않는다 — 느린 앱의 재시작 루프 방지.

우리 케이스

  • 엔드포인트: /actuator/health/readiness, /actuator/health/liveness
  • initialDelaySeconds: 20(readiness), 40(liveness)

함정

liveness와 readiness를 같은 조건·타이밍으로 설정하면 readiness 실패 → liveness도 같이 실패 → 재시작 루프. 역할을 분리해서 설정해야 한다.


9. StatefulSet vs Deployment

구분DeploymentStatefulSet
상태StatelessStateful
파드 이름랜덤(해시)고정(pod-0, pod-1, pod-2)
파드 순서순서 무관 생성/삭제순서 보장(0→1→2 생성, 역순 삭제)
스토리지공유 또는 없음파드별 전용 PVC (이동 안 됨)
네트워크 ID재시작마다 변할 수 있음안정적 DNS명(pod-0.svc-name)

우리 케이스

  • Deployment: payment·risk·merchant-limit·order 서비스 — stateless, 파드 교체 가능
  • StatefulSet (Strimzi 관리): Kafka broker — 각 broker가 자기 로그 디렉토리를 가진 identity. broker-0, broker-1, broker-2로 고정 식별 필요

10. taint/toleration · nodeSelector · anti-affinity

개념

메커니즘방향동작
taint노드 → 파드”이 조건 없으면 오지마” (effect: NoSchedule / PreferNoSchedule / NoExecute)
toleration파드 → 노드”그 taint 견딜 수 있음”
nodeSelector파드 → 노드라벨 매칭으로 특정 노드만 선택
podAntiAffinity파드 ↔ 파드같은 라벨 파드끼리 분산 (required=강제 / preferred=선호)

topologyKey: kubernetes.io/hostname = 노드 단위로 분산.

우리 케이스 (payment 전용 노드풀)

노드 taint:   role=payment:NoSchedule
파드 toleration: key=role, value=payment
nodeSelector: pool=payment
podAntiAffinity: required, topologyKey=hostname → 노드당 파드 1개

이 조합으로 payment 파드만 전용 노드에, 노드당 1개로 배치.

함정 — 롤아웃 데드락 04.배포가 조용히 터진다

전용 노드 N개 + required anti-affinity + maxSurge: 1이면 surge 파드가 올라갈 빈 노드가 없어 롤아웃이 멈춘다. maxSurge: 0 + maxUnavailable: 1로 교체.


11. PersistentVolume / PersistentVolumeClaim

  • PV (PersistentVolume): 실제 스토리지 조각 (클러스터 리소스)
  • PVC (PersistentVolumeClaim): 파드의 스토리지 요청. PV에 바인딩됨
  • StorageClass: 동적 프로비저닝 — PVC 생성 시 PV 자동 생성
구분역할
PV실제 스토리지 (관리자가 사전 생성하거나 동적 생성)
PVC파드가 원하는 스토리지 크기/접근 모드 요청
StorageClassPVC 요청 시 PV를 자동 생성하는 템플릿

우리 케이스

  • k3s 기본 StorageClass: local-path → PVC 생성 시 노드 로컬 디스크에 PV 자동 생성
  • Kafka broker의 persistent-claim PVC가 이 StorageClass를 사용 → 각 broker 노드 로컬에 로그 디렉토리 생성

함정

local-path는 노드 고정 — 파드가 다른 노드로 스케줄되면 데이터가 따라가지 않는다. StatefulSet + anti-affinity로 broker를 특정 노드에 묶어 두는 이유.


12. 더 채울 거리

  • HPA 오토스케일 실측 (CPU 지표 → 파드 개수 변화 관측)
  • NetworkPolicy (파드 간 통신 제어, 화이트리스트)
  • Ingress TLS 종료 설정
  • Helm / Kustomize (매니페스트 패키징·환경별 오버라이드)

관련 노트