대표적인 서비스들의 IP 는 모두 부하 분산을 위해 발급된 가상 IP 이다. 파드의 IP를 직접 노출하는것이 아니라 가상의 IP를 통해 여러 파드에 로드밸런싱 하는 것이다.
| 서비스 종류 | IP 엔드포인트의 역할 |
| ClusterIP | 쿠버네티스 클러스터 내부에서만 통신이 가능한 가상 IP |
| ClusterIP - ExternalIPs | 지정한 쿠버네티스 노드의 IP(들) |
| NodePort | 모든 쿠버네티스 노드의 IP(들) |
| LoadBalancer | 클러스터 외부 로드 밸런서의 가상 IP |
반면, 헤드리스(Headless) 서비스는 목적지 파드의 IP 주소를 직접 반환하는 서비스이다. DNS 라운드 로빈 방식을 사용한 엔드포인트를 제공한다. 클러스터 내부 DNS에서 목적지 파드의 IP 주소를 반환하는 것이다.
sample-headless.default.svc.cluster.local 도메인으로 요청 -> 클러스터 내부 DNS 에서 라운드 로빈 방식으로 특정 파드의 IP 를 매핑
스테이트풀셋이 헤드리스 서비스를 사용하여 제공되는 경우에 파드명으로 IP 주소를 디스커버리할 수 있다. 예를 들어 sample-statefulset-headless-0 스테이트풀셋 파드의 IP 로 호출하고 싶은 경우
sample-statefulset-headless-0.sample-headless.default.svc.cluster.local 도메인으로 호출하면 "sample-statefulset-headless-0" 파드명으로 특정 파드를 호출할 수 있는 것이다.(매니페스트는 아래에서 다룸)
1. 생성
아래와 같이 spec.type: ClusterIP 와 spec.clusterIP: None 을 지정하여 생성한다.
apiVersion: v1
kind: Service
metadata:
name: sample-headless
spec:
type: ClusterIP
clusterIP: None
ports:
- name: "http-port"
protocol: "TCP"
port: 80
targetPort: 80
selector:
app: sample-app
이렇게만 서비스를 생성하면 DNS 라운드 로빈 방식으로 서비스 디스커버리된다. 이 서비스를 통해 스테이트풀셋을 파드명으로 질의 가능하도록 구성하려면, 아래와 같이 스테이트풀셋 매니페스트의 spec.serviceName 에 사용할 헤드리스 서비스명을 지정하면 된다.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: sample-statefulset-headless
spec:
serviceName: sample-headless
replicas: 3
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: nginx-container
image: amsy810/echo-nginx:v2.0
여기서는 volumeClaimTemplates 를 지정하지 않아서 PV, PVC 가 생성되지 않는데, 자세한 스테이트풀셋 구성 방법은 스테이트풀셋 포스트를 참고하기 바란다.
2. 헤드리스 서비스 질의해보기
아래의 커맨드로 FQDN 으로 클러스터 내부 DNS에 질의해보면 ClusterIP 의 IP 주소가 아닌, 여러 파드의 IP 주소가 반환되는 것을 볼 수 있다. 따라서 클라이언트에서는 DNS 캐시에 주의하여야 한다.
# 스테이트풀셋으로 관리되는 파드들의 IP 주소 확인
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
sample-statefulset-headless-0 1/1 Running 0 13m 10.244.1.179 desktop-worker <none> <none>
sample-statefulset-headless-1 1/1 Running 0 13m 10.244.1.180 desktop-worker <none> <none>
sample-statefulset-headless-2 1/1 Running 0 13m 10.244.2.119 desktop-worker2 <none> <none>
# 클러스터 내부에서 FQDN 질의
$ kubectl run --image=amsy810/tools:v2.0 --restart=Never --rm -i testpod --command -- dig sample-headless.default.svc.cluster.local
...
;; QUESTION SECTION:
;sample-headless.default.svc.cluster.local. IN A
;; ANSWER SECTION:
sample-headless.default.svc.cluster.local. 30 IN A 10.244.1.179
sample-headless.default.svc.cluster.local. 30 IN A 10.244.2.119
sample-headless.default.svc.cluster.local. 30 IN A 10.244.1.180
...
pod "testpod" deleted
3. 스테이트풀셋 파드명으로 헤드리스 서비스 질의해보기
위에서 생성한 스테이트풀셋의 경우는 spec.serviceName 으로 헤드리스 서비스를 지정했다. 이렇게 서비스로 노출된 파드는 파드명을 FQDN 에 포함하여 다음 규칙으로 DNS 에 질의할 수 있게 된다.
<파드명>.<서비스명>.<네임스페이스명>.svc.cluster.local
아래처럼 질의해보면 특정 파드의 IP 로 해석되는 것을 볼 수 있다.
# <파드명>.<서비스명>.<네임스페이스명>.svc.cluster.local 로 질의
$ kubectl run --image=amsy810/tools:v2.0 --restart=Never --rm -i testpod --command -- dig sample-statefulset-headless-0.sample-headless.default.svc.cluster.local
;; QUESTION SECTION:
;sample-statefulset-headless-0.sample-headless.default.svc.cluster.local. IN A
;; ANSWER SECTION:
sample-statefulset-headless-0.sample-headless.default.svc.cluster.local. 30 IN A 10.244.1.179
...
pod "testpod" deleted
4. 스테이트풀셋 외의 리소스 hostname 으로 도메인 해석하기
스테이트풀셋으로 관리되지 않는 파드의 경우에도 Pod 의 매니페스트 설정을 통해 파드단위로 질의(이름해석)할 수는 있긴 하다. 다음과 같이 Pod 의 spec.hostname, spec.subdomain 을 지정하되, subdomain 에는 헤드리스 서비스(ClusterIP: None)의 이름을 지정한다.
---
apiVersion: v1
kind: Pod
metadata:
name: subdomain-pod
labels:
app: sample-app
spec:
hostname: sample-hostname
subdomain: sample-subdomain # 사용할 헤드리스 Service 의 이름을 설정
containers:
- name: nginx-container
image: amsy810/tools:v2.0
---
apiVersion: v1
kind: Service
metadata:
name: sample-subdomain
spec:
type: ClusterIP
clusterIP: None
ports: []
selector:
app: sample-app
| 항목 | |
| spec.hostname | 파드의 host명(임의) |
| spec.subdomain | 파드를 노출하고자 하는 헤드리스 서비스명 |
이렇게 설정하고 나면 아래와 같은 규칙으로 특정 파드에 질의할 수 있다.
<hostname>.<서비스명>.<네임스페이스명>.svc.cluster.local
하지만, 일반적으로 파드는 deployment 를 통해서 관리하게 되는데, 디플로이먼트의 매니페스트에서는 구조상 여러 파드에 각각의 hostname 을 설정할 수 없다. 이렇게 hostname 이 같게 되면 하나의 A 레코드만 반환되기 때문에 개별 파드명으로 이름 해석이 불가능하다. 쿠버네티스에서는 일반적인 파드 각각에 대해서 의식하지 않고도 서비스를 통해 사용할 수 있게 구성하도록 권장하고 있고, 추후 확장성이나 관리용이성을 위해서라도 파드명으로 이름 해석을 사용하는 것은 최대한 지양하여야 한다.
'Kubernetes' 카테고리의 다른 글
| [Kubernetes] None-Selector 서비스(외부 서비스로의 로드 밸런싱) (0) | 2025.12.05 |
|---|---|
| [Kubernetes] ExternalName 서비스(클러스터 내부에서 외부 도메인의 CNAME 사용하기) (0) | 2025.12.05 |
| [Kubernetes] Multi Region 서비스에서 최소한의 latency 를 위한 Topology Aware Hint (0) | 2025.11.23 |
| [Kubernetes] 클러스터 외부 트래픽에 대해 노드에서의 로드 밸런싱 제외 (0) | 2025.11.23 |
| [Kubernetes] 서비스 Session Affinity 설정 (0) | 2025.11.22 |
