Kubernetes - StatefulSets
Lab assignment for creating statefulSets using kubectl
Kubernetes - StatefulSets
Prerequisites
- Kubernetes
- kubectl
Assignment
- Create a StatefulSet with the help of a Deployment file(No easy of creatinga statefulset from CLI):
1
kubectl create deployment nginx --image=nginx --replicas=3 --dry-run=client -o yaml | tee statefulset.yaml
- Modify the file to change it to a StatefulSet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
cat <<EOF > statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
creationTimestamp: null
labels:
app: nginx
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
serviceName: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
EOF
1
kubectl apply -f statefulset.yaml
- Review the statefulset and the created pods:
1
kubectl get statefulset
1
kubectl get pods -o wide
Note: If a pod in a statefulset was removed, causing a restart, whilst the ip may change, the name will stay consistent.
Delete pod/nginx-2
1
kubectl delete pod/nginx-2 --now
1
kubectl get pods -o wide
- Using statefulsets service functionality, we’ll create a headless service called nginx:
1
kubectl create service clusterip --clusterip=None nginx
1
kubectl get service
- Review the our endpoint slices:
1
kubectl get endpoints
1
kubectl get endpoints/nginx -o yaml
- Let’s check this from the viewpoint of a pod, we’ll run a curlimages/curl container:
1
kubectl run --rm -i --tty curl --image=curlimages/curl:8.4.0 --restart=Never -- sh
- And let’s curl our statefulset service name -
1
curl nginx-1.nginx.default.svc.cluster.local
1
exit
- Take a look at the statefulset yaml, you’ll notice that the updateStrategy/rollingUpdate has a partition value of 0:
1
kubectl get statefulset/nginx -o yaml | more
- Edit the existing statefulset to change the partition value to 2 but, the following command will do the equivalent:
1
kubectl patch statefulset/nginx -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":2}}}}'
- We will set the image to nginx:alpine and watch the rollout:
1
kubectl set image statefulset/nginx nginx=nginx:alpine && kubectl rollout status statefulset/nginx
- Because of the partition value, the rollout only took place on nginx-2, we can verify this with the following commands (check the image) -
1
kubectl describe pod/nginx-1 | more
1
kubectl describe pod/nginx-2 | more
StatefulSet Persistent Storage
- Update our statefulset to include a dynamic volume:
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
cat <<EOF > statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app: nginx
name: nginx
spec:
selector:
matchLabels:
app: nginx
serviceName: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- name: nginx
mountPath: /data
volumeClaimTemplates:
- metadata:
name: nginx
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "local-path"
resources:
requests:
storage: 1Gi
EOF
- And we will recycle our statefulset:
1
kubectl delete -f statefulset.yaml && kubectl apply -f statefulset.yaml
- Watch our pods start, press ctrl-c to exit:
1
watch --differences kubectl get pods -o wide
- And we can verify that we have an individual pvc and pv for each pod -
1
kubectl get pvc
1
kubectl get pv
- We’ll execute a shell into nginx-0:
1
kubectl exec -it nginx-0 -- bash
- Create some data:
1
cd /data; touch this_is_nginx-0; ls -l
1
exit
- Let’s delete the pod and watch it be recreated:
1
kubectl delete pod/nginx-0 --now; watch --differences kubectl get pods -o wide
- And if we execute a shell again:
1
kubectl exec -it nginx-0 -- bash
- We can verify that our data still exists -
1
ls /data
1
exit
- And we can take this further, we can delete the entire statefulset:
1
kubectl delete -f statefulset.yaml
- Our pvc and pv will still exist:
1
kubectl get pvc; kubectl get pv
- And if we apply the statefulset again:
1
kubectl apply -f statefulset.yaml
- Check our pods are running:
1
kubectl get pods -o wide
- And exec back into the pod:
1
kubectl exec -it nginx-0 -- bash
- And check our data, we can confirm that it is available as expected:
1
ls /data
1
exit
- Cleanup:
1
kubectl delete statefulset/nginx --now; for i in 0 1 2; do kubectl delete pvc/nginx-nginx-$i --now; done; kubectl delete service/nginx; rm statefulset.yaml
This post is licensed under CC BY 4.0 by the author.