1. 개요
Service는 여러 Pod 앞에 두는 고정 주소다. 공식 문서는 “Pod 로 실행 중인 네트워크 애플리케이션을 노출하는 방법"이라고 정의한다.
Pod 는 죽고 다시 뜰 때마다 IP 가 바뀐다. 앱이 다른 앱의 IP 를 직접 알고 있으면 그 앱이 재시작하는 순간 연결이 끊긴다. Service 는 그 앞에 안 바뀌는 이름과 IP 를 하나 세워둔다.
앱은 http://backend:8080 으로 부르면 된다. 뒤에서 Pod 가 몇 개 뜨고 지든 모른다.
2. 타입별 도달 범위
네 종류가 있고, 앞의 셋은 위에 얹히는 구조다.
| 타입 | 어디서 닿나 | 만들면 함께 생기는 것 |
|---|---|---|
ClusterIP (기본) | 클러스터 안에서만 | — |
NodePort | 노드 IP + 고정 포트 | ClusterIP |
LoadBalancer | 외부 IP (클라우드가 발급) | NodePort + ClusterIP |
ExternalName | — (DNS CNAME 만 반환) | 프록시 없음 |
표를 위 그림과 겹쳐 읽으면 이렇게 된다. NodePort 를 만들면 ClusterIP 가 자동으로 함께 생기고, LoadBalancer 를 만들면 NodePort 와 ClusterIP 가 둘 다 함께 생긴다. 없애는 게 아니라 앞에 입구를 하나씩 더 세우는 것이다.
type: ClusterIP → [ClusterIP]
type: NodePort → [NodePort] → [ClusterIP]
type: LoadBalancer → [LB] → [NodePort] → [ClusterIP]
↑ 새로 생기는 입구 ↑ 항상 있다
ExternalName 만 성격이 다르다. 트래픽을 넘기는 게 아니라 DNS 로 다른 이름을 알려줄 뿐이라 프록시도 ClusterIP 도 없다. 외부 DB 를 클러스터 안 이름처럼 부르고 싶을 때 쓴다.
3. 셀렉터와 EndpointSlice
Service 는 IP 목록을 직접 들고 있지 않다. 라벨 셀렉터로 조건만 적어두면 컨트롤러가 맞는 Pod 를 계속 찾아 채운다.
spec:
selector:
app: backend # 이 라벨을 가진 Pod 전부
ports:
- port: 80 # Service 가 받는 포트
targetPort: 9376 # Pod 가 듣는 포트
공식 문서의 설명대로 컨트롤러가 “셀렉터에 맞는 Pod 를 계속 스캔해 EndpointSlice 를 갱신"한다. Pod 가 늘거나 죽으면 그 목록이 자동으로 바뀐다.
port 와 targetPort 가 다를 수 있다는 점이 자주 걸린다. 앞은 부르는 쪽이 쓰는 번호, 뒤는 컨테이너가 실제로 듣는 번호다.
4. Headless Service
clusterIP: None 을 주면 가상 IP 를 만들지 않는다. DNS 를 물으면 Service IP 하나가 아니라 Pod IP 들이 그대로 돌아온다.
일반 Service backend → 10.96.0.12 (하나. 뒤에서 분배)
Headless Service backend → 10.1.3.7, 10.1.8.2 (전부. 직접 고른다)
부하 분산을 포기하는 대신 개별 Pod 를 지목할 수 있게 된다. StatefulSet 과 함께 쓰이는 이유다 — 데이터베이스 복제본에서 “0번이 리더"처럼 특정 Pod 를 찍어야 하는 경우가 있다.
5. 타입 선택
클러스터 안에서만 쓴다 → ClusterIP
개발 중 잠깐 밖에서 확인한다 → NodePort
운영 환경에서 외부에 연다 → LoadBalancer (또는 Ingress)
Pod 를 개별로 지목해야 한다 → Headless
외부 주소에 클러스터 안 이름을 붙인다 → ExternalName
HTTP 서비스를 여러 개 외부에 연다면 LoadBalancer 를 서비스마다 만드는 것보다 Ingress 가 낫다. LoadBalancer 는 클라우드에서 개당 과금되므로, 하나의 진입점에서 경로로 나누는 편이 저렴하고 관리하기 쉽다.
6. 관련 문서
- Label / Selector — Service 가 Pod 를 고르는 방법 (예정)
- StatefulSet — Headless Service 와 함께 쓰이는 워크로드 (예정)
- Ingress — HTTP 경로 기반 외부 노출 (예정)
7. 출처
정의, 타입별 동작, 계층 관계, EndpointSlice 갱신은 공식 문서 “Service” 에 근거한다.
“In Kubernetes, a Service is a method for exposing a network application that is running as one or more Pods in your cluster.”
“NodePort: Exposes the Service on each Node’s IP at a static port (the NodePort). A ClusterIP Service, to which the NodePort Service routes, is automatically created.”
“LoadBalancer: Exposes the Service externally using a cloud provider’s load balancer. NodePort and ClusterIP Services, to which the external load balancer routes, are automatically created.”
“The controller for that Service continuously scans for Pods that match its selector, and then makes any necessary updates to the set of EndpointSlices for the Service.”