본문 바로가기

About/Kubernetes

[k8s] Service - 헤드리스 서비스(Headless Service)

헤드리스 서비스(Headless Service)

쿠버네티스 서비스 생성 시 .spec.clusterIP 필드 값을 None으로 설정하면 클러스터 IP가 없는 서비스를 만들 수 있습니다. 이런 서비스를 '헤드리스 서비스(Headless Service)'라고 합니다. 헤드리스 서비스의 경우 클러스터 IP가 할당되지 않고, kube-proxy가 이렇나 서비스를 처리하지 않으며, 로드 밸런싱 또는 프록시 동작을 수행하지 않습니다. DNS가 자동으로 구성되는 방법은 서비스에 셀렉터가 정의되어 있는지 여부에 달려있습니다.

헤드리스 서비스에 셀렉터(.spec.selector) 필드를 설정하면 쿠버네티스 API로 확인할 수 있는 엔드포인트(endpoint)가 만들어집니다. 서비스와 연결된 파드를 직접 가리키는 DNA A 레코드도 만들어집니다.

만약 셀렉터가 없는 경우 엔드포인트가 만들어지지 않습니다. 단, 셀렉터가 없더라도 DNS 시스템은 ExternalName 타입의 서비스에서 사용할 CNAME 레코드가 만들어집니다.


헤드리스 서비스(Headless Service) 사용해보기

nginx 파드 생성

우선 다음과 같이 app: nginx-for-svc 라는 레이블을 가지는 nginx pod를 하나 생성합니다.

1
kubectl run my-nginx --image=nginx --port=80 --labels="app=nginx-for-svc"
cs

파드가 정상적으로 실행됐는지 다음과 같이 확인합니다.

1
2
3
[root@k8s-master jh]$ kubectl get pods
NAME       READY   STATUS    RESTARTS        AGE
my-nginx   1/1     Running   0               110s
cs

 


그리고 my-nginx 파드의 자세한 정보를 다음과 같이 확인합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@k8s-master jh]# kubectl describe pod my-nginx
Name:         my-nginx
Namespace:    default
Priority:     0
Node:         k8s-node2/192.168.56.32
Start Time:   Wed, 26 Jan 2022 07:03:51 +0000
Labels:       app=nginx-for-svc
Annotations:  cni.projectcalico.org/containerID: 3e05dc45362a550ae6eff220032e60b1199fe5b2b301acdf5a2fec9769b3010c
              cni.projectcalico.org/podIP: 20.109.131.3/32
              cni.projectcalico.org/podIPs: 20.109.131.3/32
Status:       Running
IP:           20.109.131.3
 
...생략
cs

7번줄에서 해당 파드의 label이 정상적으로 적용된 것을 확인할 수 있으며, 12번 줄에서 Pod의 IP가 20.109.131.3으로 할당된 것을 알 수 있습니다.(해당 IP를 기억해주세요.)

Headless Service 생성

그 후 다음과 같이 매니페스트 파일을 작성합니니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# headless.yaml
apiVersion: v1
kind: Service
metadata:
  name: headless-service
spec:
  # type : ClusterIP이지만 clusterIP 필드: None으로 생성
  type: ClusterIP
  clusterIP: None
  # 셀렉터 설정
  selector:
    app: nginx-for-svc
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
cs

.spec.type 필드 값은 ClusterIP 이지만 spec.clusterIP 필드 값은 None으로 설정하였습니다. 위의 코드를 headless.yaml 파일로 저장하고 kubectl apply 명령어를 이용하여 클러스터에 적용합니다.

1
2
[root@k8s-master jh]$ kubectl apply -f headless.yaml 
service/headless-service created
cs

그리고 kubectl get svc 명령어로  서비스 상태를 확인합니다. 

1
2
3
4
5
[root@k8s-master jh]# kubectl get svc
NAME               TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
... 생략 
headless-service   ClusterIP      None         <none>        80/TCP    2m56s
... 생략 
 
cs

TYPE 항목이 ClusterIP이지만 CLUSTER-IP와 EXTERNAL-IP 항목이 <none> 입니다.

좀 더 자세한 정보를 확인하기 위해 kubectl describe 명령어를 다음과 같이 입력합니다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@k8s-master jh]# kubectl describe svc headless-service
Name:              headless-service
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx-for-svc
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                None
IPs:               None
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         20.109.131.3:80
Session Affinity:  None
Events:            <none>
 
cs

IP항목은 None이므로 실제 값이 없지만, EndPoint 항목은 .spec.selector 필드에서 선택한 조건에 맞는 파드(위의 my-nginx)의 IP와 Port 정보를 확인할 수 있습니다. EndPoints의 IP가 위의 my-nginx 파드의 IP와 동일한 것을 알 수 있습니다.

Headless Service 확인

헤드리스 서비스에 셀렉터를 설정하면 엔드포인트가 생성되는 것을 확인하였습니다.  DNS A 레코드도 만들어진다고 했는데 이를 확인해보겠습니다. 

우선 파드를 하나 생성합니다. nicolaka/netshoot 이미지를 이용하는데 이는 다양한 네트워크 진단 툴을 제공하는 도커 이미지 입니다.

1
 kubectl run -it --image nicolaka/netshoot testnet bash
cs

컨테이너가 실행되었으면그리고 dig <도메인 이름> 명령을 실행합니다. 위의 예시에서 도메인은  FQDN(Fully Qualified Domain Name)에 따라 headless-service.default.svc.cluster.local 입니다.

FQDN 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
bash-5.1$ dig headless-service.default.svc.cluster.local
 
<<>> DiG 9.16.22 <<>> headless-service.default.svc.cluster.local
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 31286
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
 
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 8e33fe94bc62132d (echoed)
;; QUESTION SECTION:
;headless-service.default.svc.cluster.local. IN A
 
;; ANSWER SECTION:
headless-service.default.svc.cluster.local30 IN A 20.109.131.3
 
;; Query time: 1 msec
;; SERVER: 10.96.0.10#53(10.96.0.10)
;; WHEN: Wed Jan 26 07:43:05 UTC 2022
;; MSG SIZE  rcvd: 141
 
cs

19번 줄의 ANSWER SECTION을 살펴보면  A 레코드가 생성된 것을 확인할 수 있습니다.

 


kubernetes의 헤드리스 서비스에 대하여 알아보았습니다.

참고

http://www.yes24.com/Product/Goods/85578606

 

쿠버네티스 입문 - YES24

현업의 운영 경험을 바탕으로 엄선한 쿠버네티스 입문 A~Z현재 다양한 인프라 구축의 핵심 기술은 컨테이너이다. 운영체제, 데이터베이스, 웹 서버 등 인프라 구축에 필요한 컨테이너 이미지 각

www.yes24.com

https://kubetm.github.io/k8s/07-intermediate-basic-resource/service/

 

Service

Headless, Endpoint, ExternalName

kubetm.github.io