k8s 서비스

- 장애 전
- 여러 Pod가 각자 IP를 가지고 트래픽을 받음
- 로드밸런서가 Pod IP들로 분산
- 노드 다운 / Pod 장애 발생
- 특정 Pod(10.2.10.2)가 사라짐
- 장애 후
- 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
- 즉시 모든 곳에서 같은 데이터가 보장되지는 않지만, 시간이 지나면 결국 모든 복제본이 같은 값을 가지게 되는 일관성 모델
- 즉 데이터 일관성을 위한 모델
- 예시
- 한국 사용자 → 글 작성
- 가까운 Redis / DB에 먼저 저장
- 이후 다른 지역(미국, 일본 등) DB로 비동기 복제
- 복제가 끝나기 전까지는: 사용자 이외에 외부 사용자는 글을 못 봄
- 👉 잠깐 동안 데이터가 다를 수 있음
복제본 수와 저장 완료 조건
- 데이터는 여러 복제본(replica)에 저장
- 복제본을 만드는 순간에는 그 글을 수정할 수 없음
- 지정한 최소 복제본 수가 다 저장되었을 때, 글이 저장 완료 문구가 뜨는 원리