kubernetes之有状态应用StatefulSet
statefulSet
1.稳定且唯一的网络标识符
2.稳定且持久的存储
3.有序,平滑地部署和扩展
4.有序,平滑地删除和终止
5.有序地滚动更新
三个组件:headless service StatefulSet volumeClaimTemplate
headless service:Headless Service也是一种Service,但不同的是会定义spec:clusterIP: None,也就是不需要Cluster IP的Service,因为没有ClusterIP,kube-proxy 并不处理此类服务,因为没有load balancing或 proxy 代理设置,在访问服务的时候会返回后端的全部的Pods IP地址,主要用于开发者自己根据pods进行负载均衡器的开发(设置了selector) 或 StatefulSet
关于headless service的介绍请查看https://www.cnblogs.com/linyouyi/articles/11557506.html
准备工作
如何创建
在创建StatefulSet之前需要准备的东西,值得注意的是创建顺序非常关键,创建顺序如下:
1、Volume
2、Persistent Volume
3、Persistent Volume Claim
4、Service
5、StatefulSet
1)准备pv,这里我们使用以前创建的pv
https://www.cnblogs.com/linyouyi/articles/10604818.html
[root@master ~]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 5Gi RWO,RWX Retain Available 4s
pv002 5Gi RWO,RWX Retain Available 4s
pv003 5Gi RWO,RWX Retain Available 4s
pv004 5Gi RWO,RWX Retain Available 4s
pv005 5Gi RWO,RWX Retain Available 4s
创建Service,statefulset
[root@master ~]# vim myapp-statefulset.yaml apiVersion: v1 kind: Service metadata: name: myappservice labels: app: statefulset spec: ports: - port: 80 name: web clusterIP: None selector: app: myapp-pod --- apiVersion: apps/v1 kind: StatefulSet metadata: name: myapp spec: serviceName: myappservice //要和上面的myappservice一样 replicas: 3 selector: matchLabels: app: myapp-pod template: metadata: labels: app: myapp-pod spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - containerPort: 80 name: web volumeMounts: - name: myappdata mountPath: /usr/share/nginx/html volumeClaimTemplates: - metadata: name: myappdata spec: accessModes: ["ReadWriteOnce"] //此处要确保你已经有足够的pv,且模式含ReadWriteOnce resources: requests: storage: 1Gi [root@master ~]# kubectl apply -f myapp-statefulset.yaml service/myapp-statefulset unchanged statefulset.apps/myapp created [root@master ~]# kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2d8h myapp-statefulset ClusterIP None <none> 80/TCP 3m16s [root@master ~]# kubectl get sts NAME READY AGE myapp 3/3 14s [root@master ~]# kubectl get pv //名称都是有序的,且都是从0开始创建 NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv001 5Gi RWO,RWX Retain Bound default/myappdata-myapp-2 73s pv002 5Gi RWO,RWX Retain Bound default/myappdata-myapp-1 73s pv003 5Gi RWO,RWX Retain Available 73s pv004 5Gi RWO,RWX Retain Available 73s pv005 5Gi RWO,RWX Retain Bound default/myappdata-myapp-0 73s [root@master ~]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE myappdata-myapp-0 Bound pv005 5Gi RWO,RWX 49s myappdata-myapp-1 Bound pv002 5Gi RWO,RWX 47s myappdata-myapp-2 Bound pv001 5Gi RWO,RWX 45s //删除是从2到0开始有序地删除,默认不删pvc,是为了再次创建时myapp-0自动绑定回myappdata-myapp-0 //myapp-1绑定回myappdata-myapp-1,myapp-2绑定回myappdata-myapp-2 [root@master ~]# kubectl delete -f myapp-statefulset.yaml service "myapp-statefulset" deleted statefulset.apps "myapp" deleted [root@master ~]# kubectl get pods -w NAME READY STATUS RESTARTS AGE myapp-0 1/1 Running 0 7m33s myapp-1 1/1 Running 0 7m31s myapp-2 1/1 Running 0 7m29s myapp-1 1/1 Terminating 0 7m52s myapp-0 1/1 Terminating 0 7m54s myapp-2 1/1 Terminating 0 7m50s myapp-1 0/1 Terminating 0 7m53s myapp-0 0/1 Terminating 0 7m55s myapp-2 0/1 Terminating 0 7m52s myapp-1 0/1 Terminating 0 7m58s myapp-1 0/1 Terminating 0 7m58s myapp-0 0/1 Terminating 0 8m5s myapp-0 0/1 Terminating 0 8m5s myapp-2 0/1 Terminating 0 8m1s myapp-2 0/1 Terminating 0 8m1s //创建也是按顺序来的 [root@master ~]# kubectl apply -f myapp-statefulset.yaml service/myapp-statefulset created statefulset.apps/myapp created [root@master ~]# kubectl get pods -w NAME READY STATUS RESTARTS AGE myapp-0 0/1 Pending 0 0s myapp-0 0/1 Pending 0 0s myapp-0 0/1 ContainerCreating 0 0s myapp-0 1/1 Running 0 2s myapp-1 0/1 Pending 0 0s myapp-1 0/1 Pending 0 0s myapp-1 0/1 ContainerCreating 0 0s myapp-1 1/1 Running 0 1s myapp-2 0/1 Pending 0 0s myapp-2 0/1 Pending 0 0s myapp-2 0/1 ContainerCreating 0 0s myapp-2 1/1 Running 0 2s
查看解析
[root@master ~]# kubectl exec -it myapp-0 -- /bin/sh / # nslookup myapp-0 nslookup: can't resolve '(null)': Name does not resolve Name: myapp-0 Address 1: 10.244.3.13 myapp-0.myapp.default.svc.cluster.local / # nslookup myapp-1.myappservice.default.svc.cluster.local nslookup: can't resolve '(null)': Name does not resolve Name: myapp-1.myappservice.default.svc.cluster.local Address 1: 10.244.3.15 myapp-1.myappservice.default.svc.cluster.local / # nslookup myapp-2.myappservice.default.svc.cluster.local nslookup: can't resolve '(null)': Name does not resolve Name: myapp-2.myappservice.default.svc.cluster.local Address 1: 10.244.1.16 myapp-2.myappservice.default.svc.cluster.local / # //解析格式 nslookup myapp-0.myappservice.default.svc.cluster.local nslookup pod_name.service_name.default.svc.cluster.local
扩容
[root@master ~]# kubectl scale sts myapp --replicas=5 statefulset.apps/myapp scaled [root@master ~]# kubectl get pods NAME READY STATUS RESTARTS AGE myapp-0 1/1 Running 0 9m26s myapp-1 1/1 Running 0 9m25s myapp-2 1/1 Running 0 9m24s myapp-3 1/1 Running 0 25s myapp-4 1/1 Running 0 22s [root@master ~]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE myappdata-myapp-0 Bound pv005 5Gi RWO,RWX 66m myappdata-myapp-1 Bound pv002 5Gi RWO,RWX 66m myappdata-myapp-2 Bound pv001 5Gi RWO,RWX 66m myappdata-myapp-3 Bound pv003 5Gi RWO,RWX 61s myappdata-myapp-4 Bound pv004 5Gi RWO,RWX 58s [root@master ~]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv001 5Gi RWO,RWX Retain Bound default/myappdata-myapp-2 67m pv002 5Gi RWO,RWX Retain Bound default/myappdata-myapp-1 67m pv003 5Gi RWO,RWX Retain Bound default/myappdata-myapp-3 67m pv004 5Gi RWO,RWX Retain Bound default/myappdata-myapp-4 67m pv005 5Gi RWO,RWX Retain Bound default/myappdata-myapp-0 67m
缩容
[root@master ~]# kubectl scale sts myapp --replicas=2 [root@master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE myapp-0 1/1 Running 0 11m myapp-1 1/1 Running 0 11m 查看默认更新策略 View Code 两种更新方式 [root@master ~]# kubectl patch sts myapp -p '{"spec":{"template":{"containers[0]":{"image":{"ikubernetes/myapp:v2"}}}}}' [root@master ~]# kubectl set image sts/myapp myapp=ikubernetes/myapp:v2 statefulset.apps/myapp image updated [root@master ~]# kubectl get sts -o wide NAME READY AGE CONTAINERS IMAGES myapp 4/5 22m myapp ikubernetes/myapp:v2 [root@master ~]# kubectl describe pods myapp-4 Name: myapp-4 Namespace: default Priority: 0 PriorityClassName: <none> Node: node01/10.0.1.133 Start Time: Tue, 14 May 2019 00:47:32 +0800 Labels: app=myapp-pod controller-revision-hash=myapp-5775ff7474 statefulset.kubernetes.io/pod-name=myapp-4 Annotations: <none> Status: Running IP: 10.244.1.18 Controlled By: StatefulSet/myapp Containers: myapp: Container ID: docker://3d7e50667f84c8eab2f428c86c24cc16cae49dcb20217987fa1793e086c955a5 Image: ikubernetes/myapp:v2 Image ID: docker-pullable://ikubernetes/myapp@sha256:85a2b81a62f09a414ea33b74fb8aa686ed9b168294b26b4c819df0be0712d358 Port: 80/TCP Host Port: 0/TCP State: Running Started: Tue, 14 May 2019 00:48:05 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: /usr/share/nginx/html from myappdata (rw) /var/run/secrets/kubernetes.io/serviceaccount from default-token-pwlvv (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: myappdata: Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace) ClaimName: myappdata-myapp-4 ReadOnly: false default-token-pwlvv: Type: Secret (a volume populated by a Secret) SecretName: default-token-pwlvv Optional: false QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s node.kubernetes.io/unreachable:NoExecute for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 84s default-scheduler Successfully assigned default/myapp-4 to node01 Warning Failed 69s kubelet, node01 Failed to pull image "ikubernetes/myapp:v2": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/ikubernetes/myapp/manifests/v2: Get https://auth.docker.io/token?scope=repository%3Aikubernetes%2Fmyapp%3Apull&service=registry.docker.io: net/http: TLS handshake timeout Warning Failed 69s kubelet, node01 Error: ErrImagePull Normal BackOff 68s kubelet, node01 Back-off pulling image "ikubernetes/myapp:v2" Warning Failed 68s kubelet, node01 Error: ImagePullBackOff Normal Pulling 54s (x2 over 81s) kubelet, node01 Pulling image "ikubernetes/myapp:v2" ///////////////版本已经变为v2 Normal Pulled 48s kubelet, node01 Successfully pulled image "ikubernetes/myapp:v2" Normal Created 48s kubelet, node01 Created container myapp Normal Started 48s kubelet, node01 Started container myapp
下面这两条命令意思是大于等于3的都更新为v2,也就是myapp-3,myapp-4的版本都更新为v2,
[root@master ~]# kubectl patch sts maypp -p '{"spec":{"updateStrategy":{"rollingUpdate":{"partition":3}}}}' [root@master ~]# kubectl set image sts/myapp myapp=ikubernetes/myapp:v2
浙公网安备 33010602011771号