[Retry, k8s] 16. 서비스 API - 헤드리스 서비스
카테고리: KUBERNETES
태그: kubernetes
[Retry, k8s] 16. 서비스 API - 헤드리스 서비스
🔔 헤드리스 서비스
클러스터 IP가 없는 서비스
-
로드밸런싱이 필요없거나 단일 서비스 IP가 필요 없는 경우에 헤드리스 서비스를 사용한다.
-
예를 들어, DB와 같이 마스터/슬레이브 구조가 있는 서비스들의 경우 서비스를 통해 로드밸런싱을 하지 않고 개별 파드의 주소를 알고 접속해야 하는데, 이런 경우 헤드리스 서비스는 서비스의 이름으로 파드의 접근 위치를 알아내기 위해 사용되며 서비스의 이름과 파드의 이름을 통해서 파드에 직접 접근할 수 있다.
-
이러한 이유로 헤드리스 서비스를 스테이트풀셋에서 사용된다.
-
-
IP 주소가 없기 때문에 로드 밸런싱 또는 프록시가 제공되지 않으며, DNS 라운드 로빈을 사용한 엔드포인트를 제공한다.
- 목적지 파드 IP 주소가 클러스터 내부 DNS에서 반환되는 형태로 부하 분산을 하기 때문에 클라이언트에서 DNS 캐시를 주의해야 한다.

📜 헤드리스 서비스 생성
헤드리스 서비스를 생성하려면 (1), (2) 조건을 만족한다.
| 조건 | 설명 |
|---|---|
| (1) | 서비스의 spec.type이 ClusterIP일 것 |
| (2) | 서비스의 spec.clusterIP가 None일 것 |
| (3) | 스테이트풀셋으로 생성된 파드명으로 디스커버리하는 경우, metadata.name이 스테이트풀셋의 spec.serviceName과 같을 것 |
$ cat <<EOF > sample-headless.yaml
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
EOF
$ cat <<EOF > sample-statefulset-headless.yaml
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
EOF
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
sample-statefulset-headless-0 1/1 Running 0 34s 10.46.0.1 k8s-node02 <none> <none>
sample-statefulset-headless-1 1/1 Running 0 27s 10.40.0.2 k8s-node01 <none> <none>
sample-statefulset-headless-2 1/1 Running 0 19s 10.46.0.2 k8s-node02 <none> <none>
root@k8s-master:~/test#
# 서비스 이름 해석 - "서비스명.네임스페이스명.svc.cluster.local"
# 스테이트풀셋의 서비스 디스커버리에서 DNS 라운드 로빈으로 IP 주소를 반환
$ 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.40.0.2
sample-headless.default.svc.cluster.local. 30 IN A 10.46.0.2
sample-headless.default.svc.cluster.local. 30 IN A 10.46.0.1
클러스터 내부 DNS에서 파드명으로 이름을 해석을 할 수 없게 되어 있다.
- 서비스를 생성할 때 ClusterIP 등과 같은 여러 파드에 대해 엔드포인트가 할당되어 그 엔드포인트의 이름 해석은 제공되지만, 개별 파드명에서 이름 해석은 할 서 없다.
스테이트풀셋이 헤드리스 서비스를 사용하고 서비스의 metadata.name이 스테이트풀셋의 spec.serviceName과 같은 경우 추가로 다음과 같이 파드 단위의 이름을 해석할 수 있다.
- “파드명.서비스명.네임스페이스명.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.46.0.1
컨테이너 내부의 resolv.conf 등에는 search 지시자로 다음과 같은 엔트리가 들어 있어 “파드명.서비스명”, “파드명.서비스명.네임스페이스명”으로도 질의할 수 있다.
# 컨테이너 내부의 resolv.conf 확인
$ kubectl run --image=amsy810/tools:v2.0 --restart=Never --rm -i testpod --command -- cat /etc/resolv.conf
nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
pod "testpod" deleted
📜 스테이트풀셋 외의 파드명으로 이름 해석
스테이트풀셋의 경우만 파드명으로 이름 해석이 가능하다고 했지만, 파드에 설정을 추가하여 파드명으로 이름을 해석할 수 있다.
- 파드의 spec.hostname과 헤드리시 서비스명과 동일한 spec.subdomain 설정을 추가한다.(이때, spec.hostname은 파드명 아니여 된다.)
cat <<EOF > sample-subdomain.yaml
apiVersion: v1
kind: Pod
metadata:
name: sample-subdomain
labels:
app: sample-app
spec:
hostname: sample-hostname
subdomain: sample-subdomain
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
EOF
“Hostname명.subdomain/서비스명.네임스페이스명.svc.cluster.local”
-
디플로이먼트 등에서 설정을 할 경우, 매니페스트 구조상 여러 레플리카에서 같은 hostname만 설정할 수 있다.
-
또한, 같은 hostname이 지정된 경우는 하나의 A 레코드만 반환되기 때문에 디플로이먼트 등에는 개별 파드명으로 이름 해석이 가능하도록 설정할 수 없다.
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/sample-subdomain 1/1 Running 0 4m50s 10.40.0.3 k8s-node01 <none> <none>
# 파드명으로 서비스 디스커버리
$ kubectl run --image=amsy810/tools:v2.0 --restart=Never --rm -i testpod \
> --command -- dig sample-hostname.sample-subdomain.default.svc.cluster.local
(생략)
;; ANSWER SECTION:
sample-hostname.sample-subdomain.default.svc.cluster.local. 30 IN A 10.40.0.3
댓글 남기기