“연결만 되면 끝?”이 아닌 쿠버네티스 핵심 개념: Ingress/Service부터 Probe·관측까지

도입부: 쿠버네티스를 운영하다 보면 “트래픽은 들어오는데 왜 장애지?” 같은 순간을 자주 만납니다. 이 글에서는 네트워킹 구성요소(Ingress/Service/DNS/NetworkPolicy)와 상태검증(Probe)·관측을 한 흐름으로 묶어, 안정성·보안·가용성 관점에서 책임 경계를 어떻게 나눌지 정리합니다.

1) 쿠버네티스 네트워킹을 “음식 배달 앱”으로 이해하기

제가 본 자료(음식 배달 앱 비유)는 쿠버네티스 네트워킹을 “요청이 들어오고, 내부에서 목적지를 찾고, 허용된 경로로만 통신하게 만드는” 구조로 설명합니다. 핵심 구성요소는 아래처럼 역할이 분리됩니다.

  • Ingress / LoadBalancer: 클러스터 “바깥”에서 “안”으로 들어오는 진입점입니다. (도메인/경로 기반 라우팅, TLS 종료 등 L7 기능이 주로 여기에 붙습니다.)
  • Service: Pod는 스케일링/재시작으로 IP가 바뀌지만, Service는 고정된 접근 지점(가상 IP/이름) + 로드밸런싱을 제공합니다.
  • Pod: 실제 애플리케이션이 실행되는 단위입니다.
  • DNS(CoreDNS): “이름으로 찾기”를 담당합니다. 보통 my-svc.my-ns.svc.cluster.local 같은 형태로 서비스 디스커버리가 이뤄집니다.
  • NetworkPolicy: “누가 누구와 통신할 수 있는지”를 정의하는 네트워크 보안 규칙입니다. 쿠버네티스 네트워크는 기본적으로 “잘 열려있기” 때문에, 운영 환경에서는 필요한 만큼 닫아 격리를 만들어야 합니다.

정리하면, 운영 관점의 메시지는 딱 한 문장으로 귀결됩니다.

Ingress로 들어오고, Service로 분산되고, DNS로 발견하고, NetworkPolicy로 통제한다.

2) Service가 “안정적인 엔드포인트”라는 말의 진짜 의미

Service의 본질은 “Pod가 바뀌어도 클라이언트가 같은 방법으로 접근하게 해준다”입니다. 즉 Pod의 불안정성을 Service가 흡수합니다.

  • Pod 교체/스케일링으로 IP가 바뀌어도 Service는 동일
  • Service 뒤에 있는 엔드포인트는 동적으로 변하지만 로드밸런싱으로 흡수
  • 서비스 간 호출은 DNS 이름으로 단순화

다만 실무에서는 Service만으로 부족해지는 순간도 있습니다. 예를 들어:

  • L7 라우팅(경로/호스트 기반), TLS, 인증/인가가 필요해지면 Ingress(또는 Gateway/API Gateway) 계층이 필수가 됩니다.
  • 클라이언트 IP 보존, 세션 유지(sticky session) 같은 요구사항이 생기면 설계 포인트가 늘어납니다.

즉, “Service가 안정적이다”는 말은 **네트워크 레벨에서의 안정적 ‘접근 지점’**을 의미하지, 애플리케이션이 정상이라는 의미는 아닙니다. 그 다음 이야기가 바로 Probe와 관측입니다.

3) Pod가 Running이어도 서비스는 고장일 수 있습니다

운영을 하다 보면 흔히 이런 상황을 봅니다.

  • Pod 상태: Running
  • Service 라우팅: 정상 (트래픽은 계속 들어옴)
  • 실제 사용자 경험: 오류/타임아웃/데이터 불일치

자료에서는 특히 이런 포인트를 강조합니다.

  • liveness probe는 “프로세스가 살아있냐”를 확인하는데 가깝고,
  • 저장소 I/O, 데이터 경로 장애(예: 디스크 문제, 파일시스템 hang, 특정 의존성의 부분 장애)는 놓칠 수 있습니다.
  • 그래서 “Probe만 잘 설정하면 된다”가 아니라, 별도 알림/관측 체계가 반드시 필요합니다.

즉, 네트워킹이 “연결”을 만든다면, Probe/관측은 “정상 동작을 증명”합니다.

4) readiness / liveness / startupProbe: 책임이 다릅니다

쿠버네티스의 Probe는 비슷해 보이지만 의도가 다릅니다.

  • readinessProbe: “지금 이 Pod가 트래픽을 받아도 되는가?”
    • 실패하면: Service 엔드포인트에서 제외(트래픽 차단)
  • livenessProbe: “이 Pod는 재시작이 필요한가?”
    • 실패하면: 컨테이너 재시작
  • startupProbe: “초기 기동 중에는 느려도 봐주자(오탐 방지)”
    • 느린 초기화/웜업이 있는 앱에서 liveness/readiness 오탐을 줄이는 안전장치

여기서 제가 특히 공감한 경고는 이 부분입니다.

liveness를 DB 같은 외부 의존성에 연결하면 장애를 ‘치료’가 아니라 ‘증폭’시킬 수 있습니다.

예를 들어 DB가 일시적으로 느려졌을 때 liveness가 실패하도록 해두면, 앱은 재시작을 반복하며 더 많은 커넥션/부하를 만들고 장애가 길어질 수 있습니다. 외부 의존성 문제는 보통 “재시작”이 답이 아니기 때문입니다.

예시: “트래픽 차단(readiness)”과 “프로세스 생존(liveness)”를 분리하기

아래 예시는 전형적인 방향성을 보여줍니다(핵심은 readiness는 ‘서빙 가능 여부’, liveness는 **‘프로세스가 정상 루프를 도는지’**에 가깝게 둔다는 점입니다).

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-api
  template:
    metadata:
      labels:
        app: my-api
    spec:
      containers:
        - name: app
          image: my-api:1.0.0
          ports:
            - containerPort: 8080
          startupProbe:
            httpGet:
              path: /healthz/startup
              port: 8080
            failureThreshold: 30
            periodSeconds: 2
          readinessProbe:
            httpGet:
              path: /healthz/ready
              port: 8080
            periodSeconds: 5
            failureThreshold: 2
          livenessProbe:
            httpGet:
              path: /healthz/live
              port: 8080
            periodSeconds: 10
            failureThreshold: 3
  • /healthz/ready: 캐시/워커/필수 초기화가 끝났는지 등 “서빙 준비”를 체크(실패 시 트래픽만 막음)
  • /healthz/live: 이벤트 루프/스레드 데드락 같은 “프로세스 자체 생존”에 집중(실패 시 재시작)
  • /healthz/startup: 초기 구간은 넉넉하게 보호

(각 엔드포인트의 구현은 조직/서비스 특성에 따라 달라지지만, 외부 의존성(예: DB down)을 liveness로 바로 연결하지 않기는 강력한 기본값이라고 생각합니다.)

5) NetworkPolicy: “AI 시대라서 더 중요해진 기본기”

대화에서 “AI로 인해 보안을 많이 신경써야 할 것 같다”는 이야기가 나왔는데, 쿠버네티스 관점에서는 이 우려가 특히 NetworkPolicy로 연결되기 쉽습니다.

AI/LLM 기능이 들어가면 보통 다음이 늘어납니다.

  • 외부 API 호출(egress) 증가 (모델 API, 벡터DB, 서드파티)
  • 비밀정보(API 키)·민감 데이터 접근 경로 증가
  • 서비스 간 통신 관계가 복잡해짐

이때 NetworkPolicy의 운영 철학은 간단합니다.

  • 기본적으로 네트워크는 열려있다
  • 운영에서는 가능하면 필요한 것만 열어라(least privilege)

다만 트레이드오프도 분명합니다.

  • 보안↑ 대신 운영 복잡도↑ (정책 관리, 장애 시 “왜 막혔지?” 추적)
  • 특히 AI 워크로드는 egress가 많아 “차단”이 가용성 리스크가 되기 쉬움

그래서 저는 NetworkPolicy를 “한 번에 완벽히”보다는,

  1. 핵심 네임스페이스/핵심 데이터 경로부터 격리하고
  2. 관측(Flow log, 네트워크 모니터링)과 함께 점진적으로 조이는 방식이 현실적이라고 봅니다.

6) 운영에서의 책임 경계: 라우팅 vs 상태검증/알림

마지막으로, 자료들을 종합했을 때 제가 정리한 “책임 경계”는 이렇습니다.

  • Ingress/Service/DNS:
    • “요청을 어디로 보낼지”를 책임집니다. (라우팅/디스커버리/분산)
  • NetworkPolicy:
    • “보내도 되는지”를 책임집니다. (허용/차단/격리)
  • Probe(readiness/liveness/startup):
    • “지금 서빙해도 되는지 / 재시작이 필요한지”를 책임집니다. (트래픽 차단 vs 재시작)
  • 관측(메트릭/로그/트레이싱) + 알림:
    • “Pod가 Running인데도 왜 장애인지”를 밝혀내는 최후의 보루입니다.
    • 특히 liveness가 잡아내지 못하는 데이터 경로/스토리지/I/O 문제는 관측 없이는 놓치기 쉽습니다.

결국 “연결(네트워킹)”과 “정상성(프로브·관측)”은 따로가 아니라, 같이 설계해야 운영 품질이 올라갑니다.

마무리

쿠버네티스의 핵심은 컴포넌트 이름을 외우는 게 아니라, 트래픽 경로(Ingress/Service/DNS)와 통신 통제(NetworkPolicy), 그리고 상태 판단(Probe)·관측을 어떻게 분리하고 연결할지를 운영 관점에서 설계하는 데 있습니다. 여러분 팀에서는 “라우팅”과 “상태검증/알림”의 경계를 어디까지로 두고 있는지 한 번 점검해보시면 좋겠습니다.

참고 자료

1개의 좋아요