본문 바로가기

About/Kubernetes

[k8s] StatefulSet(스테이트풀셋)

Stateless Application vs Stateful Application

Stateless Application

클라이언트와 서버 관계에서, 서버가 클라이언트의 상태를 보존하지 않는 형태의 서비스입니다. 말 그대로 상태가 없는 애플리케이션으로 대표적으로 Apache, Nginx와 같은 Web server가 있습니다.

Stateless Application

Stateless 애플리케이션은 쿠버네티스에서 삭제/생성 시 같은 역할을 하는 애플리케이션을 생성하면됩니다. 이 때 앱의 이름은 중요하지 않습니다. Stateless 애플리케이션은 Volume이 반드시 필요하진 않지만 하나의 볼륨에 모든 애플리케이션이 연결되어 사용할 수 있습니다.

쿠버네티스에서는 Replication Controller, Replicaset, Deployment와 같은 컨트롤러를 이용하여 Stateless 파드들을 관리하였습니다. 

Stateful Application

클라이언트와 서버 관계에서, 서버가 클라이언트의 상태를 보존하는 형태의 서비스입니다. 말 그대로 상태를 저장하는 형태의 애플리케이션으로 대표적으로 Mongodb, redis와 같은 Database가 있습니다.

Stateful Application

Stateful 애플리케이션은 쿠버네티스에서 삭제/생성 시 역할에 따라 다르게 애플리케이션을 생성해야합니다. 위의 그림에서 Arbiter 역할을 하는 애플리케이션이 다운될 경우 Arbier 애플리케이션을 생성해야합니다. 따라서 애플리케이션의 이름으로 어떤 역할을 하는 애플리케이션인지 식별해야하므로 이름이 변경되면 안됩니다. Stateful은 각각의 애플리케이션이 역할이 다른만큼 각각의 애플리케이션이 다른 Volume을 사용합니다. 보통 내부 시스템이 데이터베이스 저장을 위해 연결합니다.

쿠버네티스에서는 스테이트풀셋(StatefulSet)이라는 컨트롤러로 상태가 있는 파드(Stateful Application)들을 관리합니다.

 StatefulSet

스테이트풀셋을 사용하면 볼륨을 사용해서 특정 데이터를 저장한 후 파드를 재시작했을 때 해당 데이터를 유지합니다. 여러 개의 파드 사이에 순서를 지정해서 실행되도록 할 수도 있습니다. 이런 방식으로 애플리케이션에 어떠한 상태가 있어야할 때 사용합니다.

예제를 살펴보며 스테이트풀셋의 특징을 알아보겠습니다.

다음과 강티 Nginx를 사용하는 StatefulSet과 Service를 생성하는 매니페스트 파일을 작성합니다.

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
## nginx-statefulset.yaml
 
### Service 생성 
apiVersion: v1
kind: Service
metadata:
  name: nginx-statefulset-service
  labels:
    app: nginx-statefulset-service
spec:
  ports:
  - port: 80
    name: web
  type: ClusterIP # CluserIP
  clusterIP: None # IP=None -> Headless Service, 파드 이름을 도메인으로 사용하기 위함 
  selector:
    app: nginx-statefulset-service
---
### StatefulSet 생성
apiVersion: apps/v1
kind: StatefulSet # kind: StatefulSet
metadata:
  name: web # StatefulSet 이름
spec:
  selector:
    matchLabels:
      app: nginx-statefulset  # .spec.template.metadata.labels와 동일한 app 선택
  serviceName: "nginx-statefulset-service" # 위에서 생성한 Service 지정
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx-statefulset # .spec.selector.matchLabels에서 선택되도록 Label 생성
    spec:
      terminationGracePeriodSeconds: 10 # 종료 시간 10초로 설정
      containers:
      - name: nginx-statefulset 
        image: nginx 
        ports:
        - containerPort: 80
          name: web
cs

 

그리고 kubectl apply -f nginx-statefulset.yaml 명령어를 실행하면 파드가 순서대로 하나씩 생성됩니다.(리플리카셋은 한 번에 모든 파드가 생성)

1
2
3
4
5
[root@k8s-master ~]# kubectl get pods
NAME    READY   STATUS              RESTARTS   AGE
web-0   1/1     Running             0          8s
web-1   1/1     Running             0          4s
web-2   0/1     ContainerCreating   0          0s
cs

 

파드가 순서대로 생성되기 때문에 web-0 파드가 만들어지면 web-1이 생성되고, web-1이 생성되면, web-2가 생성됩니다.

또한 기존과는 다르게 파드 이름에 UUID 형식의 접미사가 아니라 web- 이라는 이름 뒤에 0, 1, 2... 처럼 숫자가 순서대로 붙습니다. 파드가 실행될 때는 작은 숫자부터 순서대로 실행됩니다. 만약 0번이 실행되지 않았다면 1번은 실행되지 않고, 1번이 실행되지 않았다면 2번은 실행되지 않습니다.

파드가 삭제될 때는 반대로 큰 숫자가 붙은 파드부터 순서(2, 1, 0)대로 삭제됩니다. 실행중인 스테이트풀 셋의 replicas 필드 값을 줄이는 경우에도 큰 숫자가 붙은 파드 붙어 삭제합니다. 

실행중인 스테이트풀셋의 replicas를 2로 변경하고 다시 kubernetes get pods를 실행하면 2번 파드가 삭제된 것을 확인할 수 있습니다.

1
2
3
4
5
[root@k8s-master ~]# kubernetes get pods
NAME    READY   STATUS    RESTARTS   AGE
web-0   1/1     Running   0          53s
web-1   1/1     Running   0          49s
 
cs

쿠버네티스의 StatefulSet에 대하여 알아보았습니다.

참고