0%

K8s学习笔记——StatefulSet之存储状态

学习极客时间上的《深入剖析Kubernetes》

秉持眼过千遍不如手过一遍的原则。动手实践并记录结果

对应章节:19 | 深入理解StatefulSet(二):存储状态

注:本节实验中用到的StorageClassName依赖于另一篇博文中的使用NFS

创建StatefulSet

创建带volumeClaim的StatefulSet

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
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: ss-ss
spec:
serviceName: "ss-ss-nginx"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
storageClassName: nfs-client
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
1
2
3
4
5
6
7
8
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
ss-ss-0 1/1 Running 0 4s
ss-ss-1 0/1 Pending 0 0s
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
ss-ss-0 1/1 Running 0 23s
ss-ss-1 1/1 Running 0 19s

查看PV及PVC

1
2
3
4
5
6
7
8
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-1a215f93-37df-4278-9723-51d365c4cf96 1Gi RWO Delete Bound default/www-ss-ss-0 nfs-client 56s
pvc-f07c6d74-6eee-4930-9ad6-20fdb4faa5d5 1Gi RWO Delete Bound default/www-ss-ss-1 nfs-client 52s
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-ss-ss-0 Bound pvc-1a215f93-37df-4278-9723-51d365c4cf96 1Gi RWO nfs-client 59s
www-ss-ss-1 Bound pvc-f07c6d74-6eee-4930-9ad6-20fdb4faa5d5 1Gi RWO nfs-client 55s

查看nfs server:

1
2
3
$ ls
default-www-ss-ss-0-pvc-1a215f93-37df-4278-9723-51d365c4cf96
default-www-ss-ss-1-pvc-f07c6d74-6eee-4930-9ad6-20fdb4faa5d5

在各个pod上创建文件

1
2
3
4
$ for i in 0 1; do kubectl exec ss-ss-$i -- sh -c 'echo hello $(hostname) > /usr/share/nginx/html/index.html'; done
$ for i in 0 1; do kubectl exec -it ss-ss-$i -- curl localhost; done
hello ss-ss-0
hello ss-ss-1

删除对应的pod

1
2
3
4
5
6
7
$ kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
ss-ss-0 1/1 Running 0 10m
ss-ss-1 1/1 Running 0 10m
$ kubectl delete pod -l app=nginx
pod "ss-ss-0" deleted
pod "ss-ss-1" deleted

查看pvc

1
2
3
4
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
www-ss-ss-0 Bound pvc-1a215f93-37df-4278-9723-51d365c4cf96 1Gi RWO nfs-client 13m
www-ss-ss-1 Bound pvc-f07c6d74-6eee-4930-9ad6-20fdb4faa5d5 1Gi RWO nfs-client 13m

可以看到,pod删除,但pvc还存在

1
2
3
4
$ kubectl get pod -l app=nginx
NAME READY STATUS RESTARTS AGE
ss-ss-0 1/1 Running 0 4m21s
ss-ss-1 1/1 Running 0 4m19s

随后pod被重建,再来curl看看

1
2
3
$ for i in 0 1; do kubectl exec -it ss-ss-$i -- curl localhost; done
hello ss-ss-0
hello ss-ss-1

由此:

  1. 当删除一个pod时,这个 Pod 对应的 PVC 和 PV,并不会被删除,而这个 Volume 里已经写入的数据,也会保存在远程存储服务里
  2. 控制器就会重新创建一个新的、名字还是叫作 ss-ss-0 的 Pod 来,“纠正”这个不一致的情况
  3. 在新的 ss-ss-0 Pod 被创建出来之后,Kubernetes 为它查找名叫 web-ss-ss-0 的 PVC 时,就会直接找到旧 Pod 遗留下来的同名的 PVC,进而找到跟这个 PVC 绑定在一起的 PV

那么,如果删除了PVC呢?

1
2
3
4
5
6
7
8
$ kubectl delete pvc www-ss-ss-0
persistentvolumeclaim "www-ss-ss-0" deleted
$ kubectl delete pvc www-ss-ss-1
persistentvolumeclaim "www-ss-ss-1" deleted
$ kubectl get pvc
No resources found in default namespace.
$ kubectl get pv
No resources found in default namespace.

可以看到,删除PVC后,对应的PV也同样被删除了

而nfs服务器端:

1
2
3
4
5
6
$ ls
archived-default-www-ss-ss-0-pvc-1a215f93-37df-4278-9723-51d365c4cf96 archived-default-www-ss-ss-1-pvc-f07c6d74-6eee-4930-9ad6-20fdb4faa5d5
$ ls archived-default-www-ss-ss-0-pvc-1a215f93-37df-4278-9723-51d365c4cf96/
index.html
$ cat archived-default-www-ss-ss-0-pvc-1a215f93-37df-4278-9723-51d365c4cf96/index.html
hello ss-ss-0

服务器端的目录变成了archived开头的目录,但内容依然存在,以备后续查看。

小结

  1. 首先,StatefulSet 的控制器直接管理的是 Pod
  2. 其次,Kubernetes 通过 Headless Service,为这些有编号的 Pod,在 DNS 服务器中生成带有同样编号的 DNS 记录
  3. 最后,StatefulSet 还为每一个 Pod 分配并创建一个同样编号的 PVC

StatefulSet 其实就是一种特殊的 Deployment,而其独特之处在于,它的每个 Pod 都被编号了