happyso
study with happyso
happyso
전체 방문자
오늘
어제
  • 분류 전체보기 (302)
    • GIT (3)
    • 컴퓨터 기본 개념 (29)
    • 알고리즘 (125)
      • 알고리즘 문제 (115)
      • 알고리즘 개념 (10)
    • Go (2)
    • 클라우드 (54)
      • DevOps (4)
      • Kubernetes(쿠버네티스) (33)
      • AWS (6)
      • CKA (8)
    • 리눅스(Linux) (18)
      • 컨테이너(Container) (8)
    • Front (22)
      • JavaScript (2)
      • React (20)
    • Python (21)
      • Python 웹 크롤링 (11)
      • Django (7)
      • MachineLearning (3)
    • 데이터베이스 (6)
      • MariaDB (2)
      • MongoDB (4)
    • C언어 (5)
    • Trouble Shooting (2)
    • 네트워크 (8)
      • CCNA (5)
    • 보안 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 15
  • edit
  • apply
  • kubernetes
  • Patch
  • 18
  • replace

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
happyso

study with happyso

[kubernetes] Service (Headless Service, ExternalName), Endpoint
클라우드/Kubernetes(쿠버네티스)

[kubernetes] Service (Headless Service, ExternalName), Endpoint

2024. 8. 13. 22:02

Headless Service

Headless 서비스는 서비스를 이용한 로드밸런싱 기능이 지원되지 않는다. 서비스를 거치지 않고 파드에 직접 접근한다.

서비스 생성 시 .spec.clusterIP 필드 값을 None으로 설정하면 클러스터 IP가 없는 서비스를 만들 수 있다.

❯ cat headless-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-headless-service
  namespace: service-test
spec:
  clusterIP: None
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 80
❯ kubectl get svc
NAME                  TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
my-headless-service   ClusterIP      None         <none>        80/TCP    3s

그럼 이런 기능이 언제/왜 필요하냐?

  • 기본 서비스와 연결된 파드에는 서비스가 LB 역할을 한다. 만약 3개의 파드가 연결돼있으면 3개의 파드가 돌아가며 랜덤으로 통신한다
  • 그러나 데이터베이스와 같이 master, slave 구조가 존재하는 경우에는 랜덤으로 통신이 되면 안되고 모든 파드 주소를 알고 있거나 master를 알고있거나 해야하므로 특정 파드에 선택적으로 통신을 할 수 있게 해야한다.
  • 그렇기 때문에 주로 statefulset 리소스(스토리지와 관련된 서비스를 띄울 경우 사용하는 쿠버네티스 리소스 종류)를 사용해야하는 경우 함께 사용된다.

[replicaset 리소스 배포]

❯ cat myweb-rs.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myweb-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
      env: dev
  template:
    metadata:
      labels:
        app: web
        env: dev
    spec:
      containers:
        - name: myweb
          image: ghcr.io/c1t1d0s7/go-myweb
          ports:
            - containerPort: 8080
              protocol: TCP
 
❯ kubectl apply -f myweb-rs.yaml
replicaset/myweb-rs created
 
❯ kubectl get pods
NAME                    READY   STATUS    RESTARTS        AGE
myweb-rs-5ltrj          1/1     Running   0               7s
myweb-rs-fldm7          1/1     Running   0               7s
myweb-rs-jtdll          1/1     Running   0               7s

[service, headless service 배포]

❯ cat myweb-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: myweb-svc
spec:
  type: ClusterIP
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 8080
 
❯ cat myweb-svc-headless.yaml
apiVersion: v1
kind: Service
metadata:
  name: myweb-svc-headless
spec:
  type: ClusterIP
  clusterIP: None # <-- Headless Service
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 8080
 
❯ kubectl apply -f myweb-svc.yaml
service/myweb-svc created
 
❯ kubectl apply -f myweb-svc-headless.yaml
service/myweb-svc-headless created
 
❯ kubectl get svc
NAME                  TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
myweb-svc             ClusterIP      10.96.221.72   <none>        80/TCP    33s
myweb-svc-headless    ClusterIP      None           <none>        80/TCP    30s

[테스트를 위한 파드 생성 및 접속 후 DNS 질의]

쿠버네티스는 파드 IP 리스트를 알려주는 방법을 DNS Lookup을 통해 제공한다.

보통은 DNS Lookup을 수행하면 서비스의 ClusterIP 하나를 반환한다. 그러나 Headless 서비스의 경우 소속된 파드 IP 주소 목록을 전부 반환한다.

❯ kubectl run nettool -it --image ghcr.io/c1t1d0s7/network-multitool --rm
If you don't see a command prompt, try pressing enter.
 
/ # host myweb-svc
myweb-svc.service-test.svc.cluster.local has address 10.96.221.72
 
/ # host myweb-svc-headless
myweb-svc-headless.service-test.svc.cluster.local has address 10.244.0.20
myweb-svc-headless.service-test.svc.cluster.local has address 10.244.0.19
myweb-svc-headless.service-test.svc.cluster.local has address 10.244.0.21
 
/ # host myweb-rs-5ltrj.myweb-svc-headless
Host myweb-rs-5ltrj.myweb-svc-headless not found: 3(NXDOMAIN) # => replicaset으로 만들어진 pod의 경우 <pod이름>.<서비스이름> 으로 DNS 질의 불가능
 
/ # host 10-244-0-20.myweb-svc-headless
10-244-0-20.myweb-svc-headless.service-test.svc.cluster.local has address 10.244.0.20

[statefulset 리소스 배포]

❯ cat myweb-sts.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: myweb-sts
spec:
  replicas: 3
  serviceName: myweb-svc-headless
  selector:
    matchLabels:
      app: web
      env: dev
  template:
    metadata:
      labels:
        app: web
        env: dev
    spec:
      containers:
        - name: myweb
          image: ghcr.io/c1t1d0s7/go-myweb
          ports:
            - containerPort: 8080
              protocol: TCP
 
❯ kubectl apply -f myweb-sts.yaml
statefulset.apps/myweb-sts created

[테스트를 위한 파드 생성 및 접속 후 DNS 질의]

❯ kubectl run nettool -it --image ghcr.io/c1t1d0s7/network-multitool --rm
If you don't see a command prompt, try pressing enter.
 
/ # host myweb-sts-0.myweb-svc-headless
myweb-sts-0.myweb-svc-headless.service-test.svc.cluster.local has address 10.244.0.23 # => statefulset으로 만들어진 pod의 경우 <pod이름>.<서비스이름> 으로 DNS 질의 가능

 

ExternalName

외부에서 접근하기 위한 목적이 아닌 내부 파드가 외부 도메인에 쉽게 접근하기 위해 사용한다.

접속하기 위한 외부 도메인 주소가 바뀌더라도 coredns가 세팅해준 내부 접근 도메인은 그대로 유지할 수 있기 때문에 애플리케이션을 다시 작성하거나 빌드하지 않고 externalName에서 도메인만 변경해서 적용해주면 된다.

externalName 필드에 google.com을 넣을 후 서비스를 생성한다.

❯ cat external-name-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-external-service
  namespace: service-test
spec:
  type: ExternalName
  externalName: google.com
❯ kubectl get svc
NAME                  TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
my-external-service   ExternalName   <none>       google.com    <none>    69m

서비스 도메인에 curl을 보내기 위한 테스트용 파드를 생성한다.

❯ cat external-name-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-externalname-pod
  namespace: service-test
spec:
  containers:
  - name: curl-container
    image: curlimages/curl:7.87.0
    command: [ "sleep", "3600" ]

생성된 파드 내부에 들어가서 curl 명령어를 통해 서비스 도메인으로 curl을 날려주면 google에 대한 정보가 넘어오는 것을 확인할 수 있다.

❯ kubectl exec -it test-externalname-pod -- curl http://my-external-service.service-test.svc.cluster.local
<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 404 (Not Found)!!1</title>
  <style>
    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
  </style>
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
  <p><b>404.</b> <ins>That’s an error.</ins>
  <p>The requested URL <code>/</code> was not found on this server.  <ins>That’s all we know.</ins>

Endpoint

서비스가 트래픽을 전달할 수 있는 실제 IP 주소와 포트의 목록을 관리한다.

파드가 생성되거나 삭제될 때 쿠버네티스 컨트롤러는 자동으로 해당 서비스와 연결된 Endpoint 를 업데이트한다.

이를 통해 서비스는 항상 최신의 파드 목록과 연결된다.

예를들어, 특정 서비스의 레이블과 일치하는 파드가 새로 생성되면 해당 파드의 IP 주소가 자동으로 Endpoint리소스에 추가된다.

$ kubectl get endpoints mongodb-headless
NAME                      ENDPOINTS                                                   AGE
mongodb-headless   10.0.0.1:27017,10.0.0.2:27017,10.0.0.3:27017   12d
$ kubectl get pods mongodb-0 -o wide
NAME               READY   STATUS    RESTARTS   AGE   IP             NODE   NOMINATED NODE   READINESS GATES
mongodb-0   1/1     Running   0          12d   10.0.0.1   worker1   <none>           <none>
 
$ kubectl get pods mongodb-1 -o wide
NAME               READY   STATUS    RESTARTS   AGE   IP             NODE   NOMINATED NODE   READINESS GATES
mongodb-1   1/1     Running   0          12d   10.0.0.2   worker2   <none>           <none>                                                         
 
$ kubectl get pods mongodb-2 -o wide
NAME               READY   STATUS    RESTARTS   AGE   IP              NODE   NOMINATED NODE   READINESS GATES
mongodb-2   1/1     Running   0          12d   10.0.0.3   worker3   <none>           <none>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

저작자표시 비영리 (새창열림)

'클라우드 > Kubernetes(쿠버네티스)' 카테고리의 다른 글

[Kubernetes] Cilium  (2) 2024.09.17
[Kubernetes] ArgoCD  (0) 2024.07.30
kube-proxy, CNI, coreDNS  (0) 2024.07.16
[쿠버네티스] 클러스터 구축  (0) 2024.06.08
[kubernetes] kubernetes의 update 종류와 동작 방법 (apply, edit, patch, replace)  (0) 2023.08.18
    '클라우드/Kubernetes(쿠버네티스)' 카테고리의 다른 글
    • [Kubernetes] Cilium
    • [Kubernetes] ArgoCD
    • kube-proxy, CNI, coreDNS
    • [쿠버네티스] 클러스터 구축
    happyso
    happyso

    티스토리툴바