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
View Code

 

下面这两条命令意思是大于等于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

 

posted @ 2019-09-20 15:33  linyouyi  阅读(550)  评论(0)    收藏  举报