Kubernetes Controllers : StatefulSet
1. Overview
이번 문서에서는 Kubernetes
(k8s)의 Controller중, StatefulSet에 대해서 알아보겠습니다.
2. Prerequisites
본문에서 사용한 spec :
OS : CentOS v7.6
Arch : x86
k8s클러스터는 1마스터 2노드로 구성했습니다.
Master
: 4cpu, ram16G
Node
: 2cpu, ram4G
3. StatefulSet
이전 포스팅에서 k8s의 여러 컨트롤러에 대해 알아봤었습니다. 이 컨트롤러들은 주로 상태가 없는(stateless
) pod을 관리하는 용도로 사용됩니다.
참고 : 호롤리한 하루/Kubernetes Controllers : Replication, Deployment, DaemonSet
오늘 소개할 StatefulSet Controller는 이름에서 느껴지듯이 상태를 가지고 있는 pod들을 관리하는 용도로 사용됩니다.
pod에 순서를 지정해서 지정한 순서대로 실행되게 할 수도 있으며, 볼륨을 지정해줘서 pod을 내렸다가 올려도 데이터가 유지되게 할 수 있습니다.
실습
Static Provisioning의 경우 :
미리 1G짜리 pv를 두개 만들어줍니다.kind: PersistentVolume metadata: name: pv spec: capacity: storage: 1Gi accessModes: - ReadWriteMany nfs: server: x.x.x.x path: /.../mount/dir
Dynamic Provisioning의 경우 :
호롤리한 하루/Kubernetes Volumes : Static & Dynamic Provisioning을 참고하여 storage class, provisioner까지 만든 후 부터 아래 실습을 진행해주세요.
StatefulSet Controller를 생성해줍니다.
$ vim statefulset-nginx.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
type: NodePort
ports:
- port: 80
name: web
clusterIP: 10.96.10.10
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nginx # ==spec.template.metadata.labels
template:
metadata:
labels:
app: nginx # ==spec.selector.matchLabels
spec:
containers:
- name: nginx
image: k8s.gcr.io/nginx-slim:0.8
ports:
- containerPort: 80
name: web
volumeMounts:
- name: web-pvc
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: web-pvc
spec:
storageClassName: nfs-storageclass # Static Provisioning의 경우에는 주석처리!
accessModes: [ "ReadWriteMany" ] # pv의 accessmode와 일치할것
resources:
requests:
storage: 1Gi
배포!
$ kubectl apply -f statefulset-nginx.yaml
$ kubectl get pod
pod이 생성될 때 0번부터 순차적으로 생성됩니다.
볼륨이 제대로 바운드되었는지 확인 :
$ kubectl get pv,pvc
그럼 이번엔 서비스에 접속해봅시다.
$ kubectl get svc
ip:port로 접속!
했는데 403에러가 발생합니다.
이유는 바로
$ for i in 0 1; do kubectl exec web-$i -- ls -a /usr/share/nginx/html; done
루트 html폴더가 비어있기 때문입니다.
각 pod에 html파일을 하나씩 구성해줍시다.
pod들의 hostname
이 다르다는것을 이용해 0번노드로 접속하면 0번노드의 hostname이 뜨는 페이지가, 1번 노드로 접속하면 1번노드의 hostname이 뜨도록 페이지를 구성해보겠습니다.
$ for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname'; done
web-0
web-1
$ for i in 0 1; do kubectl exec web-$i -- sh -c 'echo $(hostname) > /usr/share/nginx/html/index.html'; done
이제 각 pod이 어떤 노드에 올라갔는지 확인해봅시다.
$ kubectl describe pod web
Node2:port :
Node1:port :
403에러가 나지 않고, 각 pod의 hostname이 출력되는 것을 확인할 수 있습니다.
이번엔 pod을 삭제해보고 다시 올라왔을 때, 그대로 hostname이 출력되는지(volume이 제대로 바인딩되었는지)확인해봅시다.
$ kubectl delete pod -l app=nginx
replication 옵션이라 조금만 기다리면 새로운 pod이 생성될 것입니다.
다 running상태가 되면 웹으로 접속해봐서 hostname이 그대로 나오는지 확인해보시면 됩니다.
나올수있는 에러
웹으로 접속해봤는데 전부 같은 hostname이 나오는 경우 :
Dynamic Provisioning
이 아니라 Static Provisioning
을 사용할 때 할수있는 실수입니다.
Static Provisioning은 provisioning을 수동으로 해줘야하기때문에 파일시스템의 마운트포인트를 다르게 해서 pv를 생성해줘야합니다.
동일한 마운트 포인트를 사용할 경우, 같은 볼륨을 공유하는것과 마찬가지입니다. 때문에 file이 overwriting되어서 같은 hostname이 보여지는 것입니다.
–>
수동으로 nfs에 폴더 두개를 만들어주고
pv생성할때 각각의 폴더로 마운트하게 설정을 해줍니다.
pv.yaml :
pv2.yaml :
그럼 file overwriting같은 문제가 발생하지 않게됩니다.
댓글남기기