후니의 IT인프라 사전

1주차 - 쿠버네티스 주요 리소스(statefulset, headless 서비스) 본문

프로젝트&&스터디/DOIK 스터디

1주차 - 쿠버네티스 주요 리소스(statefulset, headless 서비스)

james_janghun 2022. 6. 24. 09:36

1. stateless vs stateful

  - stateless는 쉽게 말해서 상태가 보존되지 않는 다고 생각하면 됩니다. 삭제되고 다시 살아나면서 hostname등의 기본적인 정보가 변경됩니다.

  - stateful의 경우 이와 반대로 동일한 형태가 유지되는 것이라고 할 수 있습니다.

  - 특히나 nginx와 같이 웹서버 등은 만약 하나의 pod가 죽어도, 생성되는 pod가 같은 nginx pod 이기만 하면됩니다. 그러나 DB와 같이 내부의 내용까지 보존되어야 하는경우 hostname이나 volume 연결정보 등 부터 모두 기존의 내용과 동일해야하므로 반드시 같은 내용의 pod가 등장해야 합니다.

 

2. stateful 및 headless 소개

  - 이처럼 stateful 상태에서는 변동되는 IP와 같이 유동적인 내용을 담아서는 언제든 소통이 엇갈릴 가능성이 존재합니다.

  - 이를 해결하기 위해서 headless 서비스를 이용하며, 대표적으로 DNS를 활용한 쿼리를 사용합니다.

  - 만약 pod1이 172.17.0.2 라는 IP를 사용하다가 죽은 경우, 동일한 pod1이 생성되면서 172.17.0.5로 IP가 변동될 수 있습니다. 이를 예방하기 위해서 pod1.service 라는 형식의 도메인을 만들게 되면 IP와 상관없이 쿼리가 가능하게 됩니다.

 

 

3. statefulset과 headless 서비스 실습

- 아래의 yaml을 통해서 실습을 진행하겠습니다.

- Service에서는 Cluster IP type으로 80포트로 nginx를 서비스하고 있습니다.

- Statefulset에서는 nginx를 2개 생성하도록 유지합니다.

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
            spec:
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

일단 먼저 statefulSet의 보존기능을 확인해 보겠습니다.

현재 만들어진 nginx pod 2개의 hostname은 web-0과 web-1 입니다. 이를 삭제하고 다시 생성된 pod 또한 hostname이 같습니다.

(🚴|DOIK-Lab:default) root@k8s-m:~/nodeport# for i in 0 1; do kubectl exec "web-$i" -- sh -c 'hostname'; done
web-0
web-1

(🚴|DOIK-Lab:default) root@k8s-m:~/nodeport# kubectl delete pod -l app=nginx
pod "web-0" deleted
pod "web-1" deleted

(🚴|DOIK-Lab:default) root@k8s-m:~/nodeport# for i in 0 1; do kubectl exec "web-$i" -- sh -c 'hostname'; done
web-0
web-1

하지만 IP는 변동됨을 확인할 수 있습니다.

NAME    READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
web-0   1/1     Running   0          63s   172.16.3.10   k8s-w3   <none>           <none>
web-1   1/1     Running   0          62s   172.16.2.16   k8s-w1   <none>           <none>

# 파드 삭제 이후 재 생성된 모습
NAME    READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
web-0   1/1     Running   0          5s    172.16.3.11   k8s-w3   <none>           <none>
web-1   1/1     Running   0          3s    172.16.2.17   k8s-w1   <none>           <none>

IP가 변동되 었지만 netshoot 상에서는 문제 없이 DNS 쿼리를 통해서 변동된 IP를 잘 확인하고 있습니다.

 netdebug  ~ nslookup nginx
Server:         10.200.1.10
Address:        10.200.1.10#53

Name:   nginx.default.svc.cluster.local
Address: 172.16.3.10
Name:   nginx.default.svc.cluster.local
Address: 172.16.2.16



# pod 재 생성이후
 netdebug  ~ nslookup nginx
Server:         10.200.1.10
Address:        10.200.1.10#53

Name:   nginx.default.svc.cluster.local
Address: 172.16.2.17
Name:   nginx.default.svc.cluster.local
Address: 172.16.3.11

위 실습 처럼 statefulset으로 pod를 유지할 때는 headless서비스를 통해서 배포하는 것이 효율적임을 알 수 있습니다.

 

이상으로 statefulset & headless 서비스 학습을 마치겠습니다.