StatefulSet ?#
StatefulSet 개념#
- StatefulSet은 Pod을 scale up&down 하여 새로 배포 할 때 각 Pod의 기존 Spec(hostname,Ip등) 을 유지하여 생성함 (stateful)
- stateless 한 deployment, replicaset 과는 다른점임
- Pod 별로 각각의 PVC를 사용하거나 Pod 생성 순서가 중요할 때 (Master / Slave 구성이 필요할떄) statefulset 을 사용하여 Ordering을 보장하고 구분지을 수 있음
- 위 구성을 replicaSet , delpoyment를 사용했다면 pod-0 , pod-1 이 같은 PVC,PV를 사용하여 Pod 고유의 state가 사라지고 , 재기동 될 때마다 IP,hostname이 달라져 headless Service를 사용할 수 없음
StatefulSet 사용 현황#
$ kubectl get statefulset
NAME READY AGE
kimdubi-test-redis-cluster 6/6 2d4h
- statefulset 하나로 Pod 6대를 관리함, Pod이 down되어도 statefulset에 의해 자동으로 restart 됨
- Pod,pvc 생성 구문은 statefulset 에서 정의됨
StatefulSet template을 살펴보자#
$ kubectl get statefulset kimdubi-test-redis-cluster -o yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
annotations:
meta.helm.sh/release-name: kimdubi-test
meta.helm.sh/release-namespace: default
creationTimestamp: "2021-02-21T07:33:55Z"
generation: 1
labels:
app.kubernetes.io/instance: kimdubi-test
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: redis-cluster
helm.sh/chart: redis-cluster-4.3.0
name: kimdubi-test-redis-cluster
namespace: default
resourceVersion: "358350"
selfLink: /apis/apps/v1/namespaces/default/statefulsets/kimdubi-test-redis-cluster
uid: b348894a-e930-4dc2-ba10-c8566eeec0b9
spec:
podManagementPolicy: Parallel
replicas: 6
revisionHistoryLimit: 10
selector:
matchLabels:
app.kubernetes.io/instance: kimdubi-test
app.kubernetes.io/name: redis-cluster
serviceName: kimdubi-test-redis-cluster-headless
template:
metadata:
annotations:
checksum/scripts: 13c84ab100b949b2a69989dbcfa1079e3d930ee56d79744da9abc6d691709923
checksum/secret: 3fb9c96414bd6f5e1a0841de974fcb260231a9c12bebb2c49af0f02b651e47cf
creationTimestamp: null
labels:
app.kubernetes.io/instance: kimdubi-test
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: redis-cluster
helm.sh/chart: redis-cluster-4.3.0
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchLabels:
app.kubernetes.io/instance: kimdubi-test
app.kubernetes.io/name: redis-cluster
namespaces:
- default
topologyKey: kubernetes.io/hostname
weight: 1
containers:
- args:
- |
# Backwards compatibility change
if ! [[ -f /opt/bitnami/redis/etc/redis.conf ]]; then
echo COPYING FILE
cp /opt/bitnami/redis/etc/redis-default.conf /opt/bitnami/redis/etc/redis.conf
fi
/opt/bitnami/scripts/redis-cluster/entrypoint.sh /opt/bitnami/scripts/redis-cluster/run.sh
command:
- /bin/bash
- -c
env:
- name: REDIS_NODES
value: 'kimdubi-test-redis-cluster-0.kimdubi-test-redis-cluster-headless
kimdubi-test-redis-cluster-1.kimdubi-test-redis-cluster-headless kimdubi-test-redis-cluster-2.kimdubi-test-redis-cluster-headless
kimdubi-test-redis-cluster-3.kimdubi-test-redis-cluster-headless kimdubi-test-redis-cluster-4.kimdubi-test-redis-cluster-headless
kimdubi-test-redis-cluster-5.kimdubi-test-redis-cluster-headless '
- name: REDISCLI_AUTH
valueFrom:
secretKeyRef:
key: redis-password
name: kimdubi-test-redis-cluster
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
key: redis-password
name: kimdubi-test-redis-cluster
- name: REDIS_AOF_ENABLED
value: "yes"
- name: REDIS_TLS_ENABLED
value: "no"
- name: REDIS_PORT
value: "6379"
image: docker.io/bitnami/redis-cluster:6.0.10-debian-10-r5
imagePullPolicy: IfNotPresent
livenessProbe:
exec:
command:
- sh
- -c
- /scripts/ping_liveness_local.sh 5
failureThreshold: 5
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 5
name: kimdubi-test-redis-cluster
ports:
- containerPort: 6379
name: tcp-redis
protocol: TCP
- containerPort: 16379
name: tcp-redis-bus
protocol: TCP
readinessProbe:
exec:
command:
- sh
- -c
- /scripts/ping_readiness_local.sh 1
failureThreshold: 5
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 1
resources:
limits:
cpu: 100m
memory: 100Mi
requests:
cpu: 50m
memory: 50Mi
securityContext:
runAsUser: 1001
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /scripts
name: scripts
- mountPath: /bitnami/redis/data
name: redis-data
- mountPath: /opt/bitnami/redis/etc/redis-default.conf
name: default-config
subPath: redis-default.conf
- mountPath: /opt/bitnami/redis/etc/
name: redis-tmp-conf
dnsPolicy: ClusterFirst
enableServiceLinks: false
restartPolicy: Always
schedulerName: default-scheduler
securityContext:
fsGroup: 1001
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
volumes:
- configMap:
defaultMode: 493
name: kimdubi-test-redis-cluster-scripts
name: scripts
- configMap:
defaultMode: 420
name: kimdubi-test-redis-cluster-default
name: default-config
- emptyDir: {}
name: redis-tmp-conf
updateStrategy:
type: RollingUpdate
volumeClaimTemplates:
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
creationTimestamp: null
name: redis-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: kimdubi-test
volumeMode: Filesystem
status:
phase: Pending
status:
collisionCount: 0
currentReplicas: 6
currentRevision: kimdubi-test-redis-cluster-86585bd988
observedGeneration: 1
readyReplicas: 6
replicas: 6
updateRevision: kimdubi-test-redis-cluster-86585bd988
updatedReplicas: 6
.spec.replicas#
- statefulset 에서 관리할 동일한 스펙의 Pod를 6대만큼 생성하겠다는 설정
- 생성할 Pod의 상세 설정은 .spec.template.spec에 정의 되어있음
.spec.selector.matchLabels#
- statefulset 에서 관리할 Pod를 구분짓는 조건
- Pod의 label과 .spec.selector.matchLabels가 동일한지 체크를 통해 관리할 Pod를 구분함
.spec.serviceName#
- statefulset 으로 생성된 Pod 들이 사용할 Service
- statefulset 에선 Pod에 직접 access할 수 있는 DNS를 할당하기 위해 headless service를 사용함
- 관련 내용은 service편에서..
- 생성할 Pod의 label 을 설정하는 부분, .spec.selector.matchLabels의 label과 일치해야함
.spec.updateStrategy.type#
- statefulset 을 통해 배포할 때 Pod이 배포되는 방식을 설정
- RollingUpdate : Ordering 된 Pod 들을 마지막 Pod부터 순서대로 재생성하여 배포함
- onDelete : Pod을 수동으로 삭제 했을 때 새로운 설정이 반영된 Pod가 생성됨
.spec.volumeClaimTemplates#
- statefulset 에 의해 생성되고 관리되는 Pod에 하나씩 binding 해줄 PVC 정의 부분
- 정의한 PVC를 .spec.template.spec.containers.volumeMounts 를 통해 container의 /bitnami/redis/data 디렉토리에 binding하고 있음