k8s/concept

service/ headless service

부엉이사장 2023. 12. 7. 10:52

# 개념

얘는 서비스타입이라곤 뭐한데.. 실제 한가지 서비스처럼 사용하는거다.

일단 clusterIP타입 service이지만, clusterIP를 None으로 해놔서 단일진입점이 없다.

그럼 얘는 어따가 쓰는걸까?

 

 

# yaml양식

apiVersion: v1
kind: Service
metadata:
  name: headless-service
spec:
  type: ClusterIP
  clusterIP: None
  selector:
    pod-service: muzzi
    #clusterIP: 10.96.1.1
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

기초적인 clusterIP타입인 yaml양식과 같지만 저기 clusterIP필드에 None으로 명시적으로 적어줬다.

만약 clusterIP를 명시적으로 한가지 아이피를 적어준다면 그 아이피가 단일진입점인 clusterIP가 된다.

또한 만약 저 필드를 적어주지 않으면, 랜덤으로 하나 정해주고 이게 더 네트워크 충돌이 안되어서 권장된다고 하였다.

하지만 headless 서비스는 이 clusterIP필드를 None으로 명시적으로 정해줬다. 그러면 어떻게 되는것일까?

 

 

 


# 일단 만들어보자.

- statefulSet생성

강의에서는 deployment로 만들었지만 난 statefulSet으로 만들었다.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: statefulset
spec:
  replicas: 3
  selector:
    matchLabels:
      pod-controller: dori
  serviceName: stateful
  template:
    metadata:
      labels:
        pod-controller: dori
        pod-service: muzzi
    spec:
      containers:
      - name: multitool
        image: praqma/network-multitool
        ports:
        - containerPort: 80

pod-controller : dori라는 라벨링으로 컨트롤러와 pod를 연결해주었고,

pod-service : muzzi라는 라벨링으로 서비스와 pod를 연결해주었다.

다시한번 말하지만 난 컨트롤러와 서비스의 라벨링을 눈에보이게 구분하고싶어서 이렇게 컨트롤러와 서비스별로 라벨링을 했지만, 보통은 다 통일을 한다. app: muzzi이런식으로..

kubectl create -f test-head-stf.yaml

 

 

- headless controller생성

apiVersion: v1
kind: Service
metadata:
  name: headless-service
spec:
  type: ClusterIP
  clusterIP: None
  selector:
    pod-service: muzzi
    #clusterIP: 10.96.1.1
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

 

kubectl create -f test-headless.yaml

 

 

# 응?

statefulSet으로 pod들이 잘 만들어졌고

headless서비스도 잘 만들어졌다. CLUSTER-IP컬럼이 None으로 되어있다.

그럼 이걸 어따 써먹을까?

kubectl describe service headless-service

자세하게 이 headless서비스를 describe로 봤더니 EndPoints에 pod들이 묶이긴 헀다.

 

 

 

 

# pod에 들어가 보자.

kubectl exec -it statefulset-0 -- /bin/bash

 

그리고 nslookup커맨드로 헤드레스 서비스에 대한 도메인과 아이피정보를 보자.

nslookup headless-service

신기하게 headless-service에 대한 도메인이 세개와 각각 세개의 아이피가 나오게 된다.

 

참고로 도메인에 관해서 좀 이해가 안되면 이전 포스팅을 보면 된다.

 

service/ k8s의 dns구성, service type> externalName

## 쿠버네티스 환경에서 도메인서버 # 일단 뜯어볼까? 쿠버네티스 환경에서는 도메인으로 서로 통신 할 수 있다. 도메인 서버를 확인하려면, kubectl get pods --all-namespace -o wide 모든 네임스페이스에

jacobowl.tistory.com

 

 

일반적인 단일진입점을 만들어주는 서비스에 대해서 nslookup커맨드를 치면, 서비스 도메인과 단일진입점인 clusterIP주소 하나만 나오게 된다. 그러나 headless service는 각 pod에서 서비스 네임을 안다면 해당 서비스가 만든 pod들의 아이피를 알 수 있게 된다.

 

 

 

 

# pod들을 scale조절해보고 nslookup해보자

kubectl scale statefulset statefulset --replicas=5

아까 세개였던 pod들이 scale명령어로 인해 5개로 바뀌었다.

 

그럼 다시 pod 안에서 nslookup해보자

nslookup headless-service

자동으로 해당 서비스에 연결된 pod들의 아이피가 추가되서 보여지게 된다.

물론 문제있는 pod들 몇개를 지우고 새로운 pod들이 태어나고 하더라도 pod가 해당 headless service에 속해있는 pod들의 아이피를 알수 있다. 

 

 

 

# 도메인은 모두 같은데?

그렇다. 만약 도메인으로 통신을 하게된다면, 도메인자체가 단일진입점처럼되서 우리가 알고있는 clusterIP타입 서비스처럼 로드벨런서역할을 하게된다.

ping headless-service.muzzi-house.svc.cluster.local

핑을 도메인으로 쳐보면

매번 핑던질때마다 다른 ip로 요청하게되는데, 

이렇게 pod들의 아이피다.

 

 

# 어따 써먹을까?(뇌피셜)

예를들어 daemonSet컨트롤러로 각각 pod들의 log를 기록하는 pod를 만들었을때, 다른 pod에서 이 각각의 pod의 log쪽 api요청을 보내서 작업을 수행해야할때, 만약 pod가 생성되고 삭제되고 아이피가 바뀌고 이런식으로 될떄마다 해당 작업의 ip를 하나하나 수정해주는게 매번 부족할 것이다.

그러나 이 headless service를 운영하게 된다면 프로그래밍해서 각각 pod들에서 이 headless 서비스 도메인을 통해 각각 pod들의 아이피를 정리하고 관리할 수 있게 될 것같다. 물론 내 뇌피셜..

핵심기능은 pod가 이 서비스를 통해 다른 pod들의 직접적인 아이피를 알아낼 수 있다는것이다.\

 

 

 

# dns resolving 

도메인을 ip주소로 변환하는 과정이라고하는데 그냥 dns서비스 말하는거 아닌가..?

암튼 뭐.. 

참고로 서비스에 속하지 않는 pod들도 ip주소롸 name space이름을 안다면 도메인으로 접속가능하다.

curl 10-244-2-253.muzzi-house.pod.cluster.local

요런식

'k8s > concept' 카테고리의 다른 글

ingress/ test  (0) 2023.12.11
ingress/ 설치 & 개념  (0) 2023.12.11
service/ k8s의 dns구성, service type> externalName  (0) 2023.12.06
service/ service type > ClueterIP & NodePort & LoadBalancer  (0) 2023.12.05
service/ 개념 & test  (0) 2023.12.04