K8s_Cloudwave: 네트워크 서비스

k8s 서비스

  1. 장애 전
    • 여러 Pod가 각자 IP를 가지고 트래픽을 받음
    • 로드밸런서가 Pod IP들로 분산
  2. 노드 다운 / Pod 장애 발생
    • 특정 Pod(10.2.10.2)가 사라짐
  3. 장애 후
    • Kubernetes가 Pod를 다른 노드에 새로 생성
    • 새 Pod는 IP가 바뀜 (10.2.10.5)

문제점

  • 기존에 정적으로 Pod IP를 바라보던 설정은 전부 깨짐 
  • 그래서 정적 라우팅은 문제가 있음
  • 그래서 Service가 필요

AWS + Kubernetes

  • EKS 노드는 Private Subnet에 배치
  • 외부 접근은 Public Subnet의 ALB/NLB를 통해 접근

ClusterIP

  • 고정된 내부 IP 만들어주고, 그 뒤에 여러 pod로 트래픽을 알아서 분산
  • kube-proxy 기반으로 동작 (Iptables/IPVS 모드)
  • iptables 모드: 랜덤하게 분산
  • IPVS 모드: 아래 표에서 로드밸런싱 방법 선택 가능


NodePort

  • 모든 노드에 같은 포트 하나가 열림
  • 외부 트래픽은 아무 노드로 들어와도 됨
  • 노트포트는 그냥 입구임. 위 그림처럼 실제 연결은 ClousterIP가 담당
  • NodePort는 여러 포트에서 들어온 트래픽을 내부로 분산은 잘하지만, 결국 외부 진입점이 통합되지 않아서 운영이 힘들다
  • L7 지원 안한다
  • 테스트나 로컬에서 주로 사용

LoadBalancer

Internet
  ↓
[Cloud LoadBalancer]  ← 서비스 1개당 1개
  ↓
[ClusterIP]
  ↓
Pods
  • Cluster IP + Loadbalancer
  • 서비스 하나당 외부 LB 하나 (L4)
  • Cluster IP가 외부 통신이 불가능하기 때문에 앞단에 LoadBalancer를 연결하여 외부 트래픽을 받음

Ingress

Internet
  ↓
[External LoadBalancer]
  ↓
[NodePort Service]  ← Ingress Controller용
  ↓
[Ingress Controller Pod]
  ↓
[ClusterIP Services]
  ↓
Application Pods
  • NodePort + 외부 로드벨런서
  • 외부 진입점 하나로 여러 서비스를 라우팅 (L7)
  • 반드시 Ingress 컨트롤러가 필요

Headless Service

  • clusterIP: None = 이 Service는 로드밸런싱하지 말고, Pod들을 그대로 드러내라
  • 가상 IP 생성 X
# 일반 Service DNS
my-service.default.svc.cluster.local
 → 10.96.123.45 (Service IP 하나)

# Headless Service DNS
my-service.default.svc.cluster.local
 → 10.10.1.2
 → 10.10.1.3
 → 10.10.1.4

 

Clouster IP 서비스와 Headless 서비스 차이


Telepresence

  • 로컬에서 실행 중인 애플리케이션을 쿠버네티스 클러스터 내부에 있는 것처럼 연결해주는 도구
  • Client + Server 구조

왜 Telepresence를 쓰냐?

- 기존 개발 방식

  • 로컬에서 개발
  • → 이미지 빌드
  • → push
  • → 배포
  • → 테스트
    👉 느림 / 반복 많음 / 귀찮음

- Telepresence 사용

  • 로컬에서 코드 실행
  • 그대로 클러스터 네트워크에 “잠입”
  • 실제 Service / DB / ConfigMap / Secret 사용 가능

👉 “로컬 = 클러스터 내부”처럼 동작


Telepresence 핵심 개념

 
[내 로컬 PC]
   ↕ (터널/프록시)
[Telepresence Traffic Manager]  ← K8s 안
   ↕
[ClusterIP / Service / Pod / DB]

 

핵심 구성요소 2개

  • Telepresence CLI (Client)
    • 내 로컬 PC에 설치
    • 로컬 앱을 클러스터에 연결
  • Telepresence Traffic Manager (Server)
    • 쿠버네티스 클러스터 안에 설치
    • 네트워크 프록시 + 트래픽 중계 역할

Telepresence가 해주는 일

네트워크 관점

  • 로컬 PC가 ClusterIP, Service, Pod IP 접근 가능
  • → 마치 Pod 안에서 실행하는 것처럼 동작

개발 관점

  • 실제 쿠버네티스 리소스 사용
  • 로컬 코드 수정 → 즉시 반영
  • 이미지 재빌드 ❌
  • 배포 ❌

Telepresence 핵심 명령어

# 내 로컬 PC를 쿠버네티스 클러스터 네트워크에 연결
telepresence connect

# 현재 Telepresence 연결 상태 확인
telepresence status

# Helm을 사용해 쿠버네티스 클러스터에 Traffic Manager(Server) 설치
telepresence helm install

LoadBalancer 실습

Deployment 생성 .yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nodeapp-deployment
  labels:
    app: nodeapp
# ─────────────────────────────
# Deployment 기본 정보
# - 이 리소스는 Pod를 직접 만들지 않고
#   Pod를 관리하는 상위 컨트롤러 역할
# ─────────────────────────────

spec:
  replicas: 3
  # ─────────────────────────────
  # 항상 Pod를 3개 유지
  # 하나 죽으면 자동으로 새로 생성
  # ─────────────────────────────

  selector:
    matchLabels:
      app: nodeapp-pod
  # ─────────────────────────────
  # 이 Deployment가 관리할 Pod를
  # 라벨 기준으로 식별
  # ─────────────────────────────

  template:
    metadata:
      labels:
        app: nodeapp-pod
    # ─────────────────────────────
    # 실제 생성될 Pod의 라벨 정의
    # Service와 연결될 핵심 부분
    # ─────────────────────────────

    spec:
      containers:
      - name: nodeapp-container
        image: dangtong/nodeapp
        ports:
        - containerPort: 8080
        # ─────────────────────────────
        # Pod 안에서 실행되는 컨테이너 정의
        # 실제 애플리케이션이 리슨하는 포트
        # ─────────────────────────────

 

LoadBalancer Service 생성 .yml (AWS)

apiVersion: v1
kind: Service
metadata:
  name: nodeapp-lb

  annotations:
    # ─────────────────────────────
    # AWS에 실제 LoadBalancer를 생성하기 위한 설정
    # - external: 외부 로드밸런서
    # - internet-facing: 인터넷 공개
    # - ip: Pod IP를 직접 타겟으로 사용
    # ─────────────────────────────
    service.beta.kubernetes.io/aws-load-balancer-type: external
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing

spec:
  type: LoadBalancer
  # ─────────────────────────────
  # Service 타입을 LoadBalancer로 지정
  # → AWS LoadBalancer 자동 생성
  # ─────────────────────────────

  ports:
  - port: 80
    targetPort: 8080
  # ─────────────────────────────
  # 외부 사용자 포트(80)를
  # Pod 내부 애플리케이션 포트(8080)로 연결
  # ─────────────────────────────

  selector:
    app: nodeapp-pod
  # ─────────────────────────────
  # 트래픽을 받을 Pod 선택 (라벨 기반)
  # ─────────────────────────────

Deployment 

  • Stateless (웹 서버에 주로 사용)
  • Pod 간 구분 X
  • 디스크 하나를 여러 pod들이 공유하는 방식을 주로 사용
  • Pod 동시에 생성/삭제 가능

Stateful

  • Stateful (DB, Redis에 주로 사용)
  • Pod 마다 고유한 이름 존재
  • Pod 마다 고유한 디스크 1개씩 연결
  • Pod 순차적으로 생성/삭제 
  • 동시에 같이 생성/삭제 안됨

StatefulSet은 왜 이렇게 만들었을까?

  • 분산시스템은 기준 노드가 중요하다 (데이터 유지를 위해)
  • DB는 각 노드가 자기 데이터를 가짐
  • Pod ↔ 디스크 관계가 절대 바뀌면 안 됨
  • 노드 디스크 순서가 깨지면 데이터가 망가짐
  • StatefulSet을 활용하면 디스크는 아래처럼 구성
노드 A 볼륨 원본
└─노드 B 볼륨 복제본
└─노드 C 볼륨  복제본

# 복제 개수 설정 가능 (예: 2 replicas)

Eventually Consistency

  • 즉시 모든 곳에서 같은 데이터가 보장되지는 않지만, 시간이 지나면 결국 모든 복제본이 같은 값을 가지게 되는 일관성 모델
  • 즉 데이터 일관성을 위한 모델
  • 예시
    1. 한국 사용자 → 글 작성
    2. 가까운 Redis / DB에 먼저 저장
    3. 이후 다른 지역(미국, 일본 등) DB로 비동기 복제
    4. 복제가 끝나기 전까지는: 사용자 이외에 외부 사용자는 글을 못 봄
    5. 👉 잠깐 동안 데이터가 다를 수 있음

복제본 수와 저장 완료 조건

  • 데이터는 여러 복제본(replica)에 저장
  • 복제본을 만드는 순간에는 그 글을 수정할 수 없음
  • 지정한 최소 복제본 수가 다 저장되었을 때, 글이 저장 완료 문구가 뜨는 원리