K8s控制器 StatefulSet
StatefulSet:
用于部署有状态应用
有状态应用部署需要考虑:
1 实例的独立存储
2 实例之间通信地址要固定
3 先后的启动顺序
应用场景:分布式应用(mysql,zk,etcd)
稳定的网络ID(实例之间通信地址要固定)实现方法:Headless Service
normal service 与 Headless Service区别
1 #通过deploy导出一个service模板文件供后续使用 2 [root@master ~]# kubectl create deploy web --image=nginx(也可以用kubectl apply -f deployment2.yaml) 3 deployment.apps/web created 4 [root@master ~]# 5 [root@master ~]# kubectl expose deploy web --port=80 --target-port=80 --dry-run=client -o yaml >svc.yaml 6 [root@master ~]# 7 [root@master ~]# vim svc.yaml 8 9 apiVersion: v1 10 kind: Service 11 metadata: 12 labels: 13 app: web 14 name: web 15 spec: 16 clusterIP: None #Headless Service这里的值是None,normal service这里是具体的IP 17 ports: #clusterIP设置为None的因为Headless Service不需要VIP为后端的实际 18 - port: 80 #服务提供负载均衡,因为clinet访问service时必须访问真实的IP地址 19 protocol: TCP 20 targetPort: 80 21 selector: 22 app: web 23 [root@master ~]# kubectl apply -f svc.yaml 24 service/web created 25 [root@master ~]# kubectl get svc 26 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 27 kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 93d 28 web ClusterIP None <none> 80/TCP 5s 29 [root@master ~]#
Headless Service与StatefulSet的关联
1 [root@master ~]# cp deployment.yaml StatefulSet1.yaml 2 [root@master ~]# cat StatefulSet1.yaml 3 apiVersion: apps/v1 4 kind: StatefulSet 5 metadata: 6 name: web 7 spec: 8 serviceName: "web" #StatefulSet中一定要有serviceName,且该值是svc.yaml文件中的Service的name 9 replicas: 3 10 selector: 11 matchLabels: 12 app: web 13 template: 14 metadata: 15 labels: 16 app: web 17 spec: 18 containers: 19 - image: nginx 20 name: nginx 21 [root@master ~]# #注意:statefulset启动的Pod名称分别是web-0,web-1,web-2 22 [root@master ~]# kubectl get pods 23 NAME READY STATUS RESTARTS AGE 24 nfs-client-provisioner-7676dc9cfc-j4vgl 1/1 Running 3 36h 25 web-0 1/1 Running 0 24m 26 web-1 1/1 Running 0 24m 27 web-2 1/1 Running 0 24m 28 [root@master ~]
再创建一个deployment与statefulset进行对比,在busybox容器中用CoreDNS解析来查看Pod的网络ID
1 [root@master ~]# kubectl create deploy web2 --image=nginx 2 [root@master ~]# kubectl scale deploy web2 --replicas=3 3 [root@master ~]# kubectl expose deploy web2 --port=80 --target-port=80 4 [root@master ~]# kubectl get pods 5 NAME READY STATUS RESTARTS AGE 6 nfs-client-provisioner-7676dc9cfc-j4vgl 1/1 Running 3 37h 7 web-0 1/1 Running 0 72m 8 web-1 1/1 Running 0 72m 9 web-2 1/1 Running 0 72m 10 web2-6448bfd7b7-4zs2z 1/1 Running 0 8m12s 11 web2-6448bfd7b7-tsgtv 1/1 Running 0 7m5s 12 web2-6448bfd7b7-vbvsg 1/1 Running 0 7m5s 13 [root@master ~]# kubectl get svc 14 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 15 kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 93d 16 web ClusterIP None <none> 80/TCP 13h 17 web2 ClusterIP 10.97.186.135 <none> 80/TCP 5m44s 18 [root@master ~]# 19 #在busybox容器中验证对service的解析 20 [root@master ~]# kubectl run -it --rm --image=busybox:1.28.4 sh 21 If you don't see a command prompt, try pressing enter. 22 / # nslookup web2.default #nslookup + serviceName.namespace 23 Server: 10.96.0.10 24 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local 25 26 #coreDNS对其解析的结果正是web2的ClusterIP 27 #ClusterIP A记录格式: 28 #<service-name>.<namespace-name>.svc.cluster.loca 29 Name: web2.default 30 Address 1: 10.97.186.135 web2.default.svc.cluster.local 31 / # 32 / # 33 / # nslookup web.default 34 Server: 10.96.0.10 35 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local 36 37 #因为handless service没有ClusterIP,所以它解析的是具体Pod的地址 38 #ClusterIP=None A记录格式: 39 #<statefulsetName-index>.<service-name> .<namespace-name>.svc.cluster.local 40 Name: web.default 41 Address 1: 10.244.2.122 web-1.web.default.svc.cluster.local 42 Address 2: 10.244.1.111 web-2.web.default.svc.cluster.local 43 Address 3: 10.244.1.110 web-0.web.default.svc.cluster.local 44 45 / # #CoreDBS解析web-0.web.default.svc.cluster.loca的IP地址 46 #可以看到实例web-0,web-1,web-2对应的IP地址分别是 47 #10.244.2.122,10.244.1.111,10.244.1.110 48 / # nslookup web-0.web.default.svc.cluster.local 49 Server: 10.96.0.10 50 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local 51 52 Name: web-0.web.default.svc.cluster.local 53 Address 1: 10.244.1.110 web-0.web.default.svc.cluster.local 54 / # 55 / # nslookup web-1.web.default.svc.cluster.local 56 Server: 10.96.0.10 57 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local 58 59 Name: web-1.web.default.svc.cluster.local 60 Address 1: 10.244.2.122 web-1.web.default.svc.cluster.local 61 / #
稳定存储(实例的独立存储)的实现方法
StatefulSet的存储卷使用VolumeClaimTemplate创建,称为卷申请模板,当StatefulSet使用VolumeClaimTemplate
创建一个PersistentVolume时,同样也会为每个Pod分配并创建一个编号的PVC。
1 #删除上个实验的pod 2 [root@master ~]# kubectl delete -f StatefulSet1.yaml 3 statefulset.apps "web" deleted 4 [root@master ~]# kubectl get pods 5 NAME READY STATUS RESTARTS AGE 6 nfs-client-provisioner-7676dc9cfc-j4vgl 1/1 Running 3 44h 7 sh 1/1 Running 0 6h16m 8 web2-6448bfd7b7-4zs2z 1/1 Running 0 6h39m 9 web2-6448bfd7b7-tsgtv 1/1 Running 0 6h37m 10 web2-6448bfd7b7-vbvsg 1/1 Running 0 6h37m 11 [root@master ~]# 12 #再次编辑一个statefulset文件,在文件中使用VolumeClaimTemplate 13 #为每个Pod提供一个PV 14 [root@master ~]# cp StatefulSet1.yaml StatefulSet2.yaml 15 [root@master ~]# vim StatefulSet2.yaml 16 apiVersion: apps/v1 17 kind: StatefulSet 18 metadata: 19 name: web 20 spec: 21 serviceName: "web" 22 replicas: 3 23 selector: 24 matchLabels: 25 app: web 26 template: 27 metadata: 28 labels: 29 app: web 30 spec: 31 containers: 32 - image: nginx 33 name: nginx 34 volumeMounts: 35 - name: www #nginx容器中挂载的卷名称是www,要与volumeClaimTemplates中的name一致 36 mountPath: /usr/share/nginx/html 37 volumeClaimTemplates: 38 - metadata: 39 name: www 40 spec: 41 accessModes: [ "ReadWriteOnce" ] 42 storageClassName: "managed-nfs-storage" 43 resources: 44 requests: 45 storage: 1Gi 46 [root@master ~]# 47 48 [root@master ~]# kubectl apply -f StatefulSet2.yaml 49 statefulset.apps/web created 50 [root@master ~]# 51 [root@master ~]# kubectl get pods 52 NAME READY STATUS RESTARTS AGE 53 nfs-client-provisioner-7676dc9cfc-j4vgl 1/1 Running 3 44h 54 sh 1/1 Running 0 6h19m 55 web-0 1/1 Running 0 63s 56 web-1 1/1 Running 0 59s 57 web-2 1/1 Running 0 55s 58 web2-6448bfd7b7-4zs2z 1/1 Running 0 6h42m 59 web2-6448bfd7b7-tsgtv 1/1 Running 0 6h41m 60 web2-6448bfd7b7-vbvsg 1/1 Running 0 6h41m 61 [root@master ~]# 62 #卷申请模板为每个pod创建一个pvc,且每个pvc关联一个pv 63 [root@master ~]# kubectl get pv,pvc 64 NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE 65 persistentvolume/pv01 5Gi RWX Retain Available 2d1h 66 persistentvolume/pv02 10Gi RWX Retain Released default/my-pvc 2d1h 67 persistentvolume/pv03 20Gi RWX Retain Available 2d1h 68 persistentvolume/pvc-7b3836a2-15a8-4584-9635-7be34b304a94 1Gi RWO Delete Bound default/www-web-0 managed-nfs-storage 115s 69 persistentvolume/pvc-ae5f09e6-493e-47d5-8268-0a850c892890 1Gi RWO Delete Bound default/www-web-1 managed-nfs-storage 111s 70 persistentvolume/pvc-eda3b8d3-56b3-4a33-a5d3-3af39e5f76ad 1Gi RWO Delete Bound default/www-web-2 managed-nfs-storage 107s 71 72 NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE 73 persistentvolumeclaim/www-web-0 Bound pvc-7b3836a2-15a8-4584-9635-7be34b304a94 1Gi RWO managed-nfs-storage 116s 74 persistentvolumeclaim/www-web-1 Bound pvc-ae5f09e6-493e-47d5-8268-0a850c892890 1Gi RWO managed-nfs-storage 111s 75 persistentvolumeclaim/www-web-2 Bound pvc-eda3b8d3-56b3-4a33-a5d3-3af39e5f76ad 1Gi RWO managed-nfs-storage 107s 76 [root@master ~]# 77 78 #在nfs服务器上查看Pv的物理目录 79 [root@node2 ~]# cd /ifs/kubernetes/ 80 [root@node2 kubernetes]# ll 81 total 8 82 drwxrwxrwx 2 root root 21 Feb 16 15:54 archived-default-my-pvc2-pvc-cfa1317b-67eb-4e36-8c4d-75e7c075e2a9 83 -rw-r--r-- 1 root root 9 Feb 13 20:59 a.txt 84 drwxrwxrwx 2 root root 6 Feb 17 18:08 default-www-web-0-pvc-7b3836a2-15a8-4584-9635-7be34b304a94 85 drwxrwxrwx 2 root root 6 Feb 17 18:08 default-www-web-1-pvc-ae5f09e6-493e-47d5-8268-0a850c892890 86 drwxrwxrwx 2 root root 6 Feb 17 18:08 default-www-web-2-pvc-eda3b8d3-56b3-4a33-a5d3-3af39e5f76ad 87 -rw-r--r-- 1 root root 18 Feb 13 23:10 index.html 88 drwxr-xr-x 2 root root 6 Feb 15 16:43 pv01 89 drwxr-xr-x 2 root root 6 Feb 15 16:43 pv02 90 drwxr-xr-x 2 root root 6 Feb 15 16:43 pv03 91 [root@node2 kubernetes]#