쿠버네티스 마스터 — Services·Networking·Ingress

2026-05-03확률과 통계 마스터 노트

쿠버네티스 마스터 노트 시리즈 4편. Pod IP가 변경되는 환경에서 Service가 안정적 진입점 역할을 하는 메커니즘, ClusterIP/NodePort/LoadBalancer/ExternalName 4 타입의 결정적 차이, Endpoints 자동 갱신, CoreDNS의 서비스 디스커버리, Ingress가 L7 라우팅으로 외부 노출의 표준이 된 이유, Service Mesh 등장 배경까지.

이 글은 쿠버네티스 마스터 노트 시리즈의 네 번째 편입니다. 3편(Workloads)까지 Pod 생성·관리였다면, 이번엔 그 Pod에 어떻게 접근하나 — Services·Networking·Ingress.

Pod IP는 항상 바뀝니다. 다음 Pod에 접속하려면 어떻게? Service가 그 답. 외부에서 들어오려면? NodePort·LoadBalancer·Ingress 3종.

처음 Services가 어렵게 느껴지는 이유

처음 이 단원이 어렵게 느껴지는 이유는 두 가지예요. 첫째, 타입이 4개라 헷갈립니다. ClusterIP·NodePort·LoadBalancer·ExternalName — 어느 게 어디? 둘째, Ingress와 Service의 관계가 막연합니다.

해결법은 한 가지예요. "Service = 안정적 IP·DNS / Ingress = HTTP 라우팅" 한 줄. Service는 Pod 다운돼도 IP 안 바뀜, Ingress는 도메인·경로별 라우팅. 둘 보완.

왜 Service가 필요한가

Pod nginx-1 → IP 10.244.0.5 (Pod 다운 시 사라짐)
Pod nginx-2 → IP 10.244.0.6
Pod nginx-3 → IP 10.244.0.7

다른 Pod에서 nginx 접근 — 어느 IP?

문제:

  • Pod IP는 일회용
  • Pod 수 변경 시 IP도 변경
  • 클라이언트가 모든 IP 추적 X

Service가 답

Service "nginx" → 안정적 IP (예: 10.96.10.5)
                → 셀렉터로 매칭된 Pod들에 자동 라우팅
                → Pod 다운·교체에도 Service IP 그대로

여기서 정말 중요한 시험 함정 — Service = 가상 IP + 자동 로드밸런서. 클라이언트는 Service IP만 알면 됨. Pod 변경 자동 추적.

ClusterIP — 클러스터 내부 (기본)

apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    app: nginx
  ports:
    - port: 80          # Service 포트
      targetPort: 80    # Pod 포트
  type: ClusterIP       # 기본값 (생략 가능)
kubectl get svc
# NAME        TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)
# nginx-svc   ClusterIP   10.96.10.5     <none>        80/TCP

# 클러스터 안 다른 Pod에서
curl http://nginx-svc/    # DNS 자동 (CoreDNS)
curl http://10.96.10.5/   # 직접 IP

특징:

  • 클러스터 내부에서만 접근 가능
  • 외부 노출 X
  • DNS 자동 (<svc>.<ns>.svc.cluster.local)

여기서 시험 함정이 하나 있어요. ClusterIP는 외부 접근 X. Pod에서 또는 kubectl port-forward로만. 외부 노출은 NodePort·LoadBalancer·Ingress.

NodePort — 외부 단순 노출

spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080    # 30000~32767 범위 (선택, 자동 할당도 가능)
# 모든 노드의 30080 포트로 접근
curl http://<node-ip>:30080

특징:

  • 모든 노드의 같은 포트 열림
  • 노드 IP를 알아야 함
  • 운영 환경엔 부적합 (노드 IP 노출)

용도 — 개발·테스트만. 운영은 LoadBalancer 또는 Ingress.

LoadBalancer — 클라우드 로드밸런서

spec:
  type: LoadBalancer
  ports:
    - port: 80
      targetPort: 80

클라우드 환경 (AWS·GCP·Azure)에서 자동 LB 프로비저닝.

kubectl get svc
# NAME        TYPE           EXTERNAL-IP        PORT(S)
# nginx-svc   LoadBalancer   34.123.45.67       80:30080/TCP

curl http://34.123.45.67/

특징:

  • 클라우드 LB 자동 생성 (AWS ELB·GCP Load Balancer)
  • 공개 IP 자동 할당
  • 하나의 LB = 1개 Service (비쌈)

여기서 정말 중요한 시험 함정 — LoadBalancer는 클라우드 환경에서만. 온프레미스·로컬은 MetalLB 같은 추가 도구 필요.

ExternalName — DNS 별칭

spec:
  type: ExternalName
  externalName: api.example.com

클러스터 내부 DNS 조회 → 외부 도메인으로 리다이렉트. 외부 서비스를 내부 이름으로.

Endpoints — Service의 비밀

각 Service에는 Endpoints 객체 자동 생성:

kubectl get endpoints nginx-svc
# NAME        ENDPOINTS                                  AGE
# nginx-svc   10.244.0.5:80,10.244.0.6:80,10.244.0.7:80

Endpoints = 셀렉터에 매칭된 Pod IP 목록. 컨트롤러가 자동 갱신.

여기서 시험 함정이 하나 있어요. Pod이 Ready 아니면 Endpoints에 X. Readiness Probe 실패 = Service 트래픽 X. 7편에서 자세히.

CoreDNS — 서비스 디스커버리

K8s 클러스터 안 자동 DNS:

Service: my-svc.my-namespace.svc.cluster.local
또는: my-svc (같은 namespace)
또는: my-svc.my-namespace
# Pod 안에서
nslookup nginx-svc
# Server:  10.96.0.10
# Address: 10.96.0.10#53
# 
# Name: nginx-svc.default.svc.cluster.local
# Address: 10.96.10.5

CoreDNS = kube-system namespace의 DaemonSet (또는 Deployment).

Ingress — L7 HTTP 라우팅

여러 Service를 도메인·경로별 라우팅.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  tls:
    - hosts: [example.com]
      secretName: example-tls
  rules:
    - host: example.com
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-svc
                port:
                  number: 80
          - path: /web
            pathType: Prefix
            backend:
              service:
                name: web-svc
                port:
                  number: 80

흐름:

example.com/api → api-svc → API Pod
example.com/web → web-svc → Web Pod

Ingress Controller — 실제 처리자

Ingress 리소스만 정의하면 안 동작. Ingress Controller가 트래픽 처리:

Controller 설명
NGINX Ingress 가장 일반적
Traefik 자동 설정, 모던
HAProxy 고성능
AWS ALB AWS 환경
Istio Gateway Service Mesh와 함께
# NGINX Ingress 설치 (Helm)
helm install ingress-nginx ingress-nginx/ingress-nginx

여기서 정말 중요한 시험 함정 — Ingress 리소스 ≠ Ingress Controller. 리소스만 정의해도 Controller 없으면 안 됨. EKS·GKE는 자체 Controller 자동 설치.

Ingress vs LoadBalancer

측면 LoadBalancer Ingress
계층 L4 (TCP·UDP) L7 (HTTP)
라우팅 단일 Service 여러 Service (path·host)
비용 1 Service = 1 LB (비쌈) 1 LB = 여러 Service
TLS 클라우드 LB Ingress 자체
사용처 TCP·gRPC HTTP API·웹

여기서 정말 중요한 시험 함정 — 다수 HTTP 서비스 = Ingress 권장 (비용·관리 효율). 단일 TCP·gRPC = LoadBalancer.

Pod 네트워크 — CNI

각 Pod이 자기 IP를 갖는 메커니즘.

[Node 1]
  Pod 10.244.1.5
  Pod 10.244.1.6
  
[Node 2]
  Pod 10.244.2.7
  Pod 10.244.2.8

각 Pod이 직접 통신 가능 (NAT X)

CNI 플러그인:

  • Calico — BGP 기반, NetworkPolicy 강력
  • Flannel — 단순, 입문용
  • Cilium — eBPF 기반, 최신
  • Weave — 자동 암호화
  • AWS VPC CNI — AWS 네이티브

여기서 시험 함정이 하나 있어요. CNI 선택은 클러스터 생성 시 결정. 나중에 변경 매우 어려움. 운영 환경 = Calico 또는 Cilium 권장.

NetworkPolicy — 방화벽 (8편 미리보기)

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-policy
spec:
  podSelector:
    matchLabels:
      app: db
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: api
      ports:
        - port: 5432

이 db Pod엔 api 라벨 Pod만 5432 포트 접근. 8편에서 자세히.

Service Mesh — 한 단계 더

복잡한 마이크로서비스 환경:

  • 서비스 간 mTLS
  • 정밀한 트래픽 제어 (canary·트래픽 미러링)
  • 분산 추적·모니터링
  • 회로 차단·재시도

도구:

  • Istio
  • Linkerd
  • Consul Connect
  • AWS App Mesh

여기서 시험 함정이 하나 있어요. Service Mesh는 복잡도 ↑. 작은 클러스터엔 over-engineering. 마이크로서비스 10+ 또는 보안 요구 강할 때.

디버깅

# Service 상태
kubectl get svc
kubectl describe svc <name>

# Endpoints 확인
kubectl get endpoints <name>

# Pod에서 Service 호출
kubectl run -it --rm debug --image=busybox -- wget -O- http://my-svc

# DNS 확인
kubectl run -it --rm debug --image=busybox -- nslookup my-svc

# Ingress 상태
kubectl get ingress
kubectl describe ingress <name>

# Ingress Controller 로그
kubectl logs -n ingress-nginx deploy/ingress-nginx-controller

시험 직전 한 번 더 — 자주 헷갈리는 함정 모음

여기까지가 4편의 핵심입니다. 시험 직전 또는 실무에서 헷갈릴 때 다시 펼쳐 볼 수 있게 압축 노트로 마무리할게요.

  • Service = 안정적 IP + 자동 LB
  • Pod IP는 일회용 → Service로 추상화
  • 4 타입 — ClusterIP (기본·내부) / NodePort (개발) / LoadBalancer (클라우드) / ExternalName (DNS 별칭)
  • ClusterIP = 클러스터 내부만
  • NodePort = 30000~32767, 개발만
  • LoadBalancer = 클라우드 LB 자동
  • 1 Service = 1 LB (비쌈)
  • 온프레미스 LoadBalancer = MetalLB
  • Endpoints = 매칭 Pod IP 목록 (자동 갱신)
  • Pod Ready 아니면 Endpoints 제외
  • CoreDNS = 서비스 디스커버리 (<svc>.<ns>.svc.cluster.local)
  • Ingress = L7 HTTP 라우팅
  • 도메인·경로별 → 여러 Service
  • TLS·rewrite·인증 등 부가 기능
  • Ingress 리소스 ≠ Ingress Controller
  • Controller — NGINX·Traefik·HAProxy·AWS ALB·Istio
  • 다수 HTTP = Ingress 권장
  • 단일 TCP·gRPC = LoadBalancer
  • CNI = Pod 네트워크 (Calico·Flannel·Cilium·AWS VPC)
  • 클러스터 생성 시 결정, 나중 변경 어려움
  • NetworkPolicy = Pod 방화벽 (8편)
  • Service Mesh = 마이크로서비스 통신 (Istio·Linkerd)
  • 복잡도 ↑ — 작은 클러스터 X

시리즈 다른 편

공식 문서: Kubernetes Service / Ingress 에서 더 깊이.

다음 글(5편)에서는 ConfigMap & Secret — 설정·민감 정보 분리, Pod 주입 방식, 비밀 관리 모범 사례까지 풀어 갑니다.

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!