Statefulset
https://blog.naver.com/isc0304/221885403537
스테이트풀셋(Statefulset)이란?
애플리케이션의 상태를 저장하고 관리하는 데 사용되는 쿠버네티스 객체다
기존의 포드를 삭제하고 생성할 때 상태가 유지되지 않는 한계가 있다
때문에 포드를 삭제하고 생성하면 완전히 새로운 가상환경이 시작된다
하지만 필요에 따라 이러한 포드의 상태를 유지하고 싶을 수 있다
응용프로그램의 로그나 기타 다른 정보들을 함께 저장하고자 하는 경우 단순히 PV를 하나 마운트해 이를 유지하기는 어렵다
스테이트풀셋으로 생성되는 포드는 영구 식별자를 가지고 상태를 유지시킬 수 있다
스테이트풀셋를 사용하고 자하는 케이스 다음과 같다
- 안정적이고 고유한 네트워크 식별자가 필요한 경우
- 안정적이고 지속적인 스토리지를 사용해야 하는 경우
- 질서 정연한 포드의 배치와 확장을 원하는 경우
- 포드의 자동 롤링업데이트를 사용하기 원하는 경우
스테이트풀셋은 각 포드의 상태를 유지할 수 있는 장점과 함께 몇가지 문제를 해결해야 한다
- 스테이트풀셋과 관련된 볼륨이 삭제되지 않음 (관리 필요)
- 포드의 스토리지는 PV나 스토리지클래스로 프로비저닝 수행해야 함
- 롤링업데이트를 수행하는 경우 수동으로 복구해야 할 수 있음 (롤링업데이트 수행 시 기존의 스토리지와 충돌로 인해 애플리케이션이 오류가 발생할 수 있다는 의미다)
- 포드 네트워크 ID를 유지하기 위해 헤드레스(headless) 서비스 필요
상태를 유지할 수 있다는 장점도 있지만 이로 인해 포드를 각각 따로 관리해줘야 하는 문제도 함께 동반한다
따라서 스테이트풀셋을 사용할 건지 디플로이먼트를 사용할 것인지는 프로젝트의 상황에 따라 달라질 수 있다
스테이트풀 생성 및 관찰
nginx-statefulset.yaml 파일 작성
# nginx-statefulset.yaml
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:
selector:
matchLabels:
app: nginx
serviceName: "nginx" # 헤드레스 서비스를 지정한다.
replicas: 3 # by default is 1
template:
metadata:
labels:
app: nginx
spec:
terminationGracePeriodSeconds: 10 # 강제 종료까지 대기하는 시간
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: # PVC 설정을 저장하는 부분
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "standard"
resources:
requests:
storage: 1Gi
kubectl 로 생성 및 확인
statefulset 한번에 하나씩 만들어짐
$ kubectl create -f nginx-statefulset.yaml
service/nginx created
statefulset.apps/web created
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.36.0.1 <none> 443/TCP 18m
nginx ClusterIP None <none> 80/TCP 40s
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/web-0 1/1 Running 0 69s
pod/web-1 1/1 Running 0 39s
pod/web-2 1/1 Running 0 23s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.36.0.1 <none> 443/TCP 18m
service/nginx ClusterIP None <none> 80/TCP 70s
NAME READY AGE
statefulset.apps/web 3/3 70s
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound pvc-dd97b926-278d-48f0-ade2-e458949c227b 1Gi RWO standard 2m5s
www-web-1 Bound pvc-96da613a-1ff6-4afd-8bad-94cb17306db4 1Gi RWO standard 94s
www-web-2 Bound pvc-cc84c78a-318a-4d38-b514-f5ed80a237e8 1Gi RWO standard 78s
도메인 네임과 서비스 동작 확인
$ kubectl run -i --tty --image busybox:1.28 dns-test --restart=Never --rm /bin/sh
If you don't see a command prompt, try pressing enter.
# nslookup web-0.nginx.default.svc
Server: 10.36.0.10
Address 1: 10.36.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-0.nginx.default.svc
Address 1: 10.32.2.12 web-0.nginx.default.svc.cluster.local
# nslookup web-1.nginx.default.svc
Server: 10.36.0.10
Address 1: 10.36.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-1.nginx.default.svc
Address 1: 10.32.2.13 web-1.nginx.default.svc.cluster.local
# nslookup web-2.nginx.default.svc
Server: 10.36.0.10
Address 1: 10.36.0.10 kube-dns.kube-system.svc.cluster.local
Name: web-2.nginx.default.svc
Address 1: 10.32.1.4 web-2.nginx.default.svc.cluster.local
각각의 포드에 도메인 네임 서비스를 통해 접근할 수 있는 것을 확인할 수 있음
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-0 1/1 Running 0 32m 10.32.2.12 gke-cluster-1-default-pool-f6cef6fa-hbbq <none> <none>
web-1 1/1 Running 0 31m 10.32.2.13 gke-cluster-1-default-pool-f6cef6fa-hbbq <none> <none>
web-2 1/1 Running 0 31m 10.32.1.4 gke-cluster-1-default-pool-f6cef6fa-hmlx <none> <none>
스케일 업, 스케일 다운
변경감지 대기
$ kubectl get pod -w
NAME READY STATUS RESTARTS AGE
dns-test 1/1 Running 0 5m14s
web-0 1/1 Running 0 34m
web-1 1/1 Running 0 34m
web-2 1/1 Running 0 33m
새로운 탭을 열어 스케일 확장을 진행
$ kubectl scale statefulset web --replicas 5
statefulset.apps/web scaled
하나씩 변경 되는 것을 확인
NAME READY STATUS RESTARTS AGE
dns-test 1/1 Running 0 5m14s
web-0 1/1 Running 0 34m
web-1 1/1 Running 0 34m
web-2 1/1 Running 0 33m
dns-test 0/1 Error 0 7m5s
dns-test 0/1 Terminating 0 7m6s
dns-test 0/1 Terminating 0 7m6s
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 0s
web-3 0/1 Pending 0 6s
web-3 0/1 ContainerCreating 0 6s
web-3 1/1 Running 0 16s
web-4 0/1 Pending 0 0s
web-4 0/1 Pending 0 0s
web-4 0/1 Pending 0 6s
web-4 0/1 ContainerCreating 0 6s
web-4 1/1 Running 0 30s
다시 스케일을 축소
$ kubectl scale statefulset web --replicas 1
statefulset.apps/web scaled
스케일 축소에 따라 삭제되는 것을 확인
NAME READY STATUS RESTARTS AGE
web-4 1/1 Terminating 0 6m19s
web-4 0/1 Terminating 0 6m20s
web-4 0/1 Terminating 0 6m21s
web-4 0/1 Terminating 0 6m21s
web-3 1/1 Terminating 0 6m37s
web-3 0/1 Terminating 0 6m38s
web-3 0/1 Terminating 0 6m43s
web-3 0/1 Terminating 0 6m43s
web-2 1/1 Terminating 0 42m
web-2 0/1 Terminating 0 42m
web-2 0/1 Terminating 0 42m
web-2 0/1 Terminating 0 42m
web-1 1/1 Terminating 0 42m
web-1 0/1 Terminating 0 42m
web-1 0/1 Terminating 0 43m
web-1 0/1 Terminating 0 43m
스토리지 지속성 확인
포드가 삭제되도 pvc와 pv 스토리지가 여전히 남아있는 것을 확인
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound pvc-dd97b926-278d-48f0-ade2-e458949c227b 1Gi RWO standard 45m
www-web-1 Bound pvc-96da613a-1ff6-4afd-8bad-94cb17306db4 1Gi RWO standard 45m
www-web-2 Bound pvc-cc84c78a-318a-4d38-b514-f5ed80a237e8 1Gi RWO standard 44m
www-web-3 Bound pvc-c5e6a7c5-ab35-4ac6-af58-d07f3d8f5230 1Gi RWO standard 9m10s
www-web-4 Bound pvc-d74a2339-583a-499e-9f19-66129969785a 1Gi RWO standard 8m54s
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-96da613a-1ff6-4afd-8bad-94cb17306db4 1Gi RWO Delete Bound default/www-web-1 standard 45m
pvc-c5e6a7c5-ab35-4ac6-af58-d07f3d8f5230 1Gi RWO Delete Bound default/www-web-3 standard 9m10s
pvc-cc84c78a-318a-4d38-b514-f5ed80a237e8 1Gi RWO Delete Bound default/www-web-2 standard 44m
pvc-d74a2339-583a-499e-9f19-66129969785a 1Gi RWO Delete Bound default/www-web-4 standard 8m53s
pvc-dd97b926-278d-48f0-ade2-e458949c227b 1Gi RWO Delete Bound default/www-web-0 standard 45m
스테이트 풀셋 삭제 후 에도 여전히 남아있음을 확인
$ kubectl delete statefulsets web
statefulset.apps "web" deleted
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-web-0 Bound pvc-dd97b926-278d-48f0-ade2-e458949c227b 1Gi RWO standard 45m
www-web-1 Bound pvc-96da613a-1ff6-4afd-8bad-94cb17306db4 1Gi RWO standard 45m
www-web-2 Bound pvc-cc84c78a-318a-4d38-b514-f5ed80a237e8 1Gi RWO standard 44m
www-web-3 Bound pvc-c5e6a7c5-ab35-4ac6-af58-d07f3d8f5230 1Gi RWO standard 9m10s
www-web-4 Bound pvc-d74a2339-583a-499e-9f19-66129969785a 1Gi RWO standard 8m54s
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-96da613a-1ff6-4afd-8bad-94cb17306db4 1Gi RWO Delete Bound default/www-web-1 standard 45m
pvc-c5e6a7c5-ab35-4ac6-af58-d07f3d8f5230 1Gi RWO Delete Bound default/www-web-3 standard 9m10s
pvc-cc84c78a-318a-4d38-b514-f5ed80a237e8 1Gi RWO Delete Bound default/www-web-2 standard 44m
pvc-d74a2339-583a-499e-9f19-66129969785a 1Gi RWO Delete Bound default/www-web-4 standard 8m53s
pvc-dd97b926-278d-48f0-ade2-e458949c227b 1Gi RWO Delete Bound default/www-web-0 standard 45m
다시 생성시 기존에 스테이트풀셋이 유지하고 있던 것이 있기 때문에 스케일을 다시 하게 되면 기존에 있던 것에 그대로 붙게됨
kubectl create -f nginx-statefulset.yaml
statefulset.apps/web created
Error from server (AlreadyExists): error when creating "nginx-statefulset.yaml": services "nginx" already exists
생성된 pod에 클레임이 잘 연결돼 있는지 확인한다
이름이 모두 기존의 pvc와 동일하게 잘 연결된 모습을 확인할 수 있다
$ kubectl get pod -o yaml | grep claim
claimName: www-web-0
claimName: www-web-1
claimName: www-web-2
롤링 업데이트
업데이트 시에도 동일하게 동작하는지 확인
edit 명령으로 업데이트
$ kubectl edit statefulsets.apps web
image 를 k8s.gcr.io/nginx-slim:0.9 로 수정
...
spec:
...
template:
...
spec:
...
containers:
- image: k8s.gcr.io/nginx-slim:0.9
...
역순으로 업데이트가 잘 되는 것을 확인할 수 있음
NAME READY STATUS RESTARTS AGE
web-2 0/1 Pending 0 0s
web-2 0/1 Pending 0 0s
web-2 0/1 ContainerCreating 0 0s
web-2 1/1 Running 0 10s
web-2 1/1 Terminating 0 9m48s
web-2 0/1 Terminating 0 9m48s
web-2 0/1 Terminating 0 9m49s
web-2 0/1 Terminating 0 9m50s
web-2 0/1 Pending 0 0s
web-2 0/1 Pending 0 0s
web-2 0/1 ContainerCreating 0 0s
web-2 1/1 Running 0 24s
web-1 1/1 Terminating 0 10m
web-1 0/1 Terminating 0 10m
web-1 0/1 Terminating 0 10m
web-1 0/1 Terminating 0 10m
web-1 0/1 Pending 0 0s
web-1 0/1 Pending 0 0s
web-1 0/1 ContainerCreating 0 0s
web-1 1/1 Running 0 23s
web-0 1/1 Terminating 0 11m
web-0 0/1 Terminating 0 11m
web-0 0/1 Terminating 0 11m
web-0 0/1 Terminating 0 11m
web-0 0/1 Pending 0 0s
web-0 0/1 Pending 0 0s
web-0 0/1 ContainerCreating 0 0s
web-0 1/1 Running 0 7s
'개발강의정리 > DevOps' 카테고리의 다른 글
[아파치 카프카 입문과 활용] 2. Apache kafka 설치, 실행, CLI (0) | 2021.01.04 |
---|---|
[아파치 카프카 입문과 활용] 1. Apache kafka 기본개념 및 생태계 (0) | 2021.01.04 |
[데브옵스를 위한 쿠버네티스 마스터] 쿠버네티스 핵심개념-Storage (0) | 2021.01.03 |
[데브옵스를 위한 쿠버네티스 마스터] 쿠버네티스 핵심개념-Network (0) | 2021.01.03 |
[데브옵스를 위한 쿠버네티스 마스터] 쿠버네티스 핵심 개념-Services (0) | 2020.12.27 |
댓글