StatefulSet 有状态应用

前言

环境:centos7.9 docker-ce-20.10.9 kubernetes-version v1.22.6

什么是无状态应用

先来回顾deployment,deployment创建了replicaset,由replicaset创建的pod都是无状态的,pod的名字都是replicaset名字+随机字符构成的,pod的启动顺序也是无所谓的,而且当一个pod消亡了,重新创建的pod是和消亡的pod没有任何关系的,所有pod副本都是使用同一个持久卷。这样的pod应用称之为无状态应用。

什么是StatefulSet 有状态应用

StatefulSet 有状态应用是指:
1、由StatefulSet创建的每个pod实例都是不可替代的个体,都拥有稳定的名字和状态;
2、由StatefulSet创建的每个pod都有一个从0开始的顺序索引,这个体现在pod的名字和主机名上,同时还会体现在pod对应的固定存储上;
3、当一个由StatefulSet创建的pod实例消失后,新创建的pod会拥有与之前消失的pod完全一致的名称;
4、由StatefulSet创建的每个pod实例都有自己的专属存储,这一点与replicaset创建的pod副本都是使用同一个持久卷存储不同;
5、扩容一个由StatefulSet创建的pod实例,会使用下一个还没使用到的顺序索引值来创建一个新的pod实例;
6、缩容一个StatefulSet将会最先删除最高索引值的pod实例;
7、当一个pod实例消失之后,其pvc和pv会被保留下来,新创建的pod实例将继续使用之前pvc和pv。

StatefulSet与replicaset、replicacontroller的对比

replicaset或replicacontroller管理的pod都是无状态的,任何时候它们都可以被一个全新的pod替换,而有状态的pod不一样,当有状态的pod挂掉之后,这个pod实例需要重建时,新的pod实例必须与被替换的pod实例具有相同的名字、网络标识和状态,这就是statefulset管理的pod。
StatefulSet保证了pod在重新调度后保留它们的标识和状态,与replicaset类似,StatefulSet也会指定期望的副本数,pod也是依据模板创建的,不过与replicaset不同的是,StatefulSet创建的pod副本并不是完全一样的,每个pod都可以有独立的数据卷,而且pod的名称也是有索引规律的,不是像replicaset创建的pod那样名称无规律。

StatefulSet的组成

1、headless server 用于定义网络标识DNS(所以需要创建一个headless server);
2、StatefulSet 控制器,用于创建具体的pod应用;
3、volumeClaimTemplates 持久卷声明模板(用于创建pvc),创建StatefulSet后就会依据这个模板为每一个pod都创建一个持久卷声明,有了持久卷声明之后,持久卷声明就会根据模式绑定到对应的持久卷;

先手动创建3个持久卷

#首先在nfs服务器上创建3个目录pv-0、pv-1、pv-2
[root@mysql k8s_data]# pwd					
/home/k8s_data
[root@mysql k8s_data]# ll
total 0
drwxr-xr-x. 2 nfsnobody nfsnobody 23 May  3 22:39 pv-0
drwxr-xr-x. 2 nfsnobody nfsnobody 23 May  3 22:39 pv-1
drwxr-xr-x. 2 nfsnobody nfsnobody 23 May  3 22:39 pv-2

#现在开始创建pv,下面这个只是pv-0的资源清单,pv-1和pv-2的也照着做,不过注意修改name和path字段值
[root@master pv-nfs]# vim pv-nfs-0.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-0								#按照这个模板创建3个pv,名称分别是 pv-0、 pv-1、 pv-2
  labels:
    app: pv-nfs-0
spec:
  capacity:
    storage: 100M
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: 192.168.118.128
    path: /home/k8s_data/pv-0/				#同理,这里的目录也要修改为对应的目录
    readOnly: false
[root@master statefulset]# kubectl get pv				#现在3个pv已经创建好了,status是可用状态
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-0    100M       RWO            Retain           Available                                    4s
pv-1    100M       RWO            Retain           Available                                    4s
pv-2    100M       RWO            Retain           Available                                    4s

创建StatefulSet(创建headless server)

[root@master statefulset]# vim statefulset.yaml 
apiVersion: v1
kind: Service							#先创建一个无头service
metadata:
  labels:								#service本身的标签
    app: svc-statefulset-headless
  name: svc-statefulset-headless		#service的名称,下面创建的StatefulSet就要引用这个service名称
spec:
  ports:
  - port: 80							#service本身的端口
    protocol: TCP
    targetPort: 80						#目标端口80,即目标容器的80端口
  selector:
    app: nginx-statefulset				#标签选择器要与下面创建的pod的标签一样
  type: ClusterIP
  clusterIP: None						#clusterIP为None表示创建的service为无头service
---
apiVersion: apps/v1
kind: StatefulSet						#创建StatefulSet资源
metadata:
  labels:								#StatefulSet本身的标签
    app: statefulset
  name: statefulset						#资源名称
  namespace: default					#资源所属命名空间
spec:
  selector:								#标签选择器,要与下面pod模板定义的pod标签保持一致
    matchLabels:
      app: nginx-statefulset
  replicas: 3							#副本数为3个
  serviceName: svc-statefulset-headless	#指定使用service为上面我们创建的无头service的名称
  template:			
    metadata:
      labels:							#pod的标签,上面的无头service的标签选择器和StatefulSet标签选择器都要与这个相同
        app: nginx-statefulset
    spec:
      containers:
      - name: nginx-container			#容器名称
        image: nginx:1.7.9				#镜像
        imagePullPolicy: IfNotPresent	#镜像拉取策略
        ports:							#定义容器端口
        - name: http 					#为端口取个名称为http
          containerPort: 80				#容器端口
        volumeMounts:					#挂载点
        - name: statefulset-data		#指定使用的卷名称,这里使用的是下面定义的pvc模板的名称
          mountPath: /var/data/			#挂载点
  volumeClaimTemplates:					#定义创建pvc的模板
    - metadata:
        name: statefulset-data			#模板名称
      spec:
        resources:						#资源请求
          requests:
            storage: 100M				#需要100M的存储空间
        accessModes:				
        - ReadWriteOnce					#访问模式为RWO
        storageClassName: ""			#指定使用的存储类

注意:storageClassName字段设为空字符串表示不自动创建pv,如果不定义该storageClassName字段并且存在系统存在默认的存储类,则会根据volumeClaimTemplates模板要求自动创建pv,这里为了演示使用我们上面手动创建的pv,所以将storageClassName赋予一个空字符串。

#查看创建好的pod
#注意:statefulset为了确保创建的pod都是有索引顺序的,所以必须是前一个pod创建完成后处于就绪状态才开始创建下一个索引顺序的pod,依次类推
[root@master statefulset]# kubectl get pods
NAME                                      READY   STATUS    RESTARTS      AGE
statefulset-0                             1/1     Running   0             16m
statefulset-1                             1/1     Running   0             16m
statefulset-2                             1/1     Running   0             16m
[root@master statefulset]# 

#查看pvc,发现创建了3个以模板名称+pod名字命名的pvc,并且绑定到了我们手动创建的pv上面
[root@master statefulset]# kubectl get pv,pvc	
NAME                   CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM                                  STORAGECLASS REASON AGE
persistentvolume/pv-0  100M     RWO          Retain         Bound  default/statefulset-data-statefulset-0                      17m
persistentvolume/pv-1  100M     RWO          Retain         Bound  default/statefulset-data-statefulset-1                      17m
persistentvolume/pv-2  100M     RWO          Retain         Bound  default/statefulset-data-statefulset-2                      17m                

NAME                                                   STATUS  VOLUME  CAPACITY  ACCESS MODES   STORAGECLASS       AGE
persistentvolumeclaim/statefulset-data-statefulset-0   Bound   pv-0     100M      RWO                               17m
persistentvolumeclaim/statefulset-data-statefulset-1   Bound   pv-1     100M      RWO                               17m
persistentvolumeclaim/statefulset-data-statefulset-2   Bound   pv-2     100M      RWO                               16m

#对每个pod实例写入数据
[root@master pv-nfs]#  kubectl exec -it statefulset-0 -- touch /var/data/file0.txt
[root@master pv-nfs]#  kubectl exec -it statefulset-1 -- touch /var/data/file1.txt
[root@master pv-nfs]#  kubectl exec -it statefulset-2 -- touch /var/data/file2.txt
#查看nfs服务器,发现每个pod都能实现自己的存储数据了
[root@mysql /]# ll /home/k8s_data/pv-0/
total 0
-rw-r--r--. 1 nfsnobody nfsnobody 0 May  3 22:39 file0.txt
[root@mysql /]# ll /home/k8s_data/pv-1/
total 0
-rw-r--r--. 1 nfsnobody nfsnobody 0 May  3 22:39 file1.txt
[root@mysql /]# ll /home/k8s_data/pv-2/
total 0
-rw-r--r--. 1 nfsnobody nfsnobody 0 May  3 22:39 file2.txt

创建StatefulSet,让StatefulSet自动分配pv

下面将继续演示,不手动创建pv,让StatefulSet动态分配pv,其原理就是在statefulset定义中指定使用的存储类,这样就会根据模板的要求自动创建pv,如下:

[root@master pv-nfs]# kubectl get sc			#查集群中所有的存储类,只有一个储存类并且是默认存储类
NAME                         PROVISIONER              RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-storageclass (default)   nfs-client-provisioner   Retain          Immediate           false                  41d
[root@master pv-nfs]#
[root@master statefulset]# vim statefulset-sc.yaml 	#创建一个动态配置pv的statefulset资源
apiVersion: v1
kind: Service										#先创建一个无头的service
metadata:
  labels:											#service本身的标签
    app: svc-statefulset-sc-headless
  name: svc-statefulset-sc-headless					#无头service的名称
spec:
  ports:
  - port: 80										#service的端口
    protocol: TCP
    targetPort: 80									#service的目标端口,一般是对应容器端口
  selector:
    app: nginx-statefulset-sc						#标签选择器,与pod的标签应该一致
  type: ClusterIP									#service类型
  clusterIP: None									#clusterIP为None就表示创建的service是headlessservice
---
apiVersion: apps/v1									#创建statefulset资源
kind: StatefulSet
metadata:
  labels:
    app: statefulset-sc								#statefulset本身的标签
  name: statefulset-sc								#statefulset的名称
  namespace: default								#statefulset所属命名空间
spec:
  selector:											#标签选择器,要与下面的pod的标签一致
    matchLabels:
      app: nginx-statefulset-sc	
  replicas: 3										#副本数为3个
  serviceName: svc-statefulset-sc-headless			#指定对应的service为上面创建的headless service
  template:
    metadata:
      labels:										
        app: nginx-statefulset-sc					#pod的标签,与上面的statefulset标签选择器一致
    spec:
      containers:					
      - name: nginx-container						#容器名称
        image: nginx:1.7.9							#镜像名称及版本
        imagePullPolicy: IfNotPresent				#镜像拉取策略
        ports:
        - name: http 								#端口名称,这个端口名称可以被service的targetPort直接引用
          containerPort: 80							#容器端口
        volumeMounts:
        - name: statefulset-data					#引用自下面创建的持久卷声明模板的name相同
          mountPath: /var/data/						#挂载点
  volumeClaimTemplates:								#定义一个pvc的模板
    - metadata:	
        name: statefulset-data						#模板的名称
      spec:	
        resources:									#资源定义
          requests:
            storage: 100M							#容量100M
        accessModes:			
        - ReadWriteOnce								#访问模式RWO
        storageClassName: nfs-storageclass			#指定使用的存储类
[root@master statefulset]#
#上面在volumeClaimTemplates中使用了storageClassName指定了存储类,这样创建pvc时就会动态pv,并与pvc进行绑定,不用在手动创建pv。
#注意:即使不写storageClassName属性,但是集群中有默认的存储类,此时仍会动态创建pv,如果不想要动态创建pv,想要pvc绑定主机你手动创建的pv,那么必须指定storageClassName: "",即给定storageClassName一个空字符串告诉它不用自动创建pv,这样创建statefulset时的pvc就会寻找你手动创建的pv进行匹配绑定而不是自动创建pv了。
#查看pvc和pv,发现已经自动创建了pv,并且与pvc进行了绑定,这就是由于存储类起的动态分配作用
[root@master statefulset]# kubectl get pvc,pv
NAME                                                      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS       AGE
persistentvolumeclaim/statefulset-data-statefulset-sc-0   Bound    pvc-4f7e48b6-c623-4c0b-a6e1-c9a5e5fe5332   100M       RWO            nfs-storageclass   6s
persistentvolumeclaim/statefulset-data-statefulset-sc-1   Bound    pvc-e705f80b-9ffc-4d0b-a8b4-b63d190023ef   100M       RWO            nfs-storageclass   3s
persistentvolumeclaim/statefulset-data-statefulset-sc-2   Bound    pvc-4bb89035-e419-47b5-acd1-25f2b529ef93   100M       RWO            nfs-storageclass   0s

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                                       STORAGECLASS       REASON   AGE
persistentvolume/pvc-4bb89035-e419-47b5-acd1-25f2b529ef93   100M       RWO            Retain           Bound    default/statefulset-data-statefulset-sc-2   nfs-storageclass            0s
persistentvolume/pvc-4f7e48b6-c623-4c0b-a6e1-c9a5e5fe5332   100M       RWO            Retain           Bound    default/statefulset-data-statefulset-sc-0   nfs-storageclass            6s
persistentvolume/pvc-e705f80b-9ffc-4d0b-a8b4-b63d190023ef   100M       RWO            Retain           Bound    default/statefulset-data-statefulset-sc-1   nfs-storageclass            3s

#查看nfs服务器上,动态创建了3个目录,对应着3个pv
[root@mysql /]# ll /home/k8s_data/
total 0
drwxrwxrwx. 2 nfsnobody nfsnobody  6 May  3 22:58 default-statefulset-data-statefulset-sc-0-pvc-4f7e48b6-c623-4c0b-a6e1-c9a5e5fe5332
drwxrwxrwx. 2 nfsnobody nfsnobody  6 May  3 22:58 default-statefulset-data-statefulset-sc-1-pvc-e705f80b-9ffc-4d0b-a8b4-b63d190023ef
drwxrwxrwx. 2 nfsnobody nfsnobody  6 May  3 22:58 default-statefulset-data-statefulset-sc-2-pvc-4bb89035-e419-47b5-acd1-25f2b529ef93
#对每个pod实例挂载点存入数据
[root@master statefulset]# kubectl exec -it statefulset-sc-0 -- touch /var/data/file0
[root@master statefulset]# kubectl exec -it statefulset-sc-1 -- touch /var/data/file1
[root@master statefulset]# kubectl exec -it statefulset-sc-2 -- touch /var/data/file2
#查看nfs服务器上是否真正存储数据,发现每个pod对应的目录已经存入了数据
[root@mysql /]# ll /home/k8s_data/default-statefulset-data-statefulset-sc-0-pvc-4f7e48b6-c623-4c0b-a6e1-c9a5e5fe5332
total 0
-rw-r--r--. 1 nfsnobody nfsnobody 0 May  3 23:20 file0
[root@mysql /]# ll /home/k8s_data/default-statefulset-data-statefulset-sc-1-pvc-e705f80b-9ffc-4d0b-a8b4-b63d190023ef
total 0
-rw-r--r--. 1 nfsnobody nfsnobody 0 May  3 23:20 file1
[root@mysql /]# ll /home/k8s_data/default-statefulset-data-statefulset-sc-2-pvc-4bb89035-e419-47b5-acd1-25f2b529ef93
total 0
-rw-r--r--. 1 nfsnobody nfsnobody 0 May  3 23:21 file2
[root@mysql /]#

pod异常挂掉

演示pod异常挂掉,看看结果如何:

[root@master statefulset]# kubectl get pod statefulset-sc-1 -o wide
NAME               READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
statefulset-sc-1   1/1     Running   0          30m   10.244.1.210   node1   <none>           <none>
[root@master statefulset]# kubectl delete pod statefulset-sc-1			#故意删除statefulset-sc-1
pod "statefulset-sc-1" deleted
[root@master statefulset]# kubectl get pod statefulset-sc-1 -o wide		#稍等一会之后,statefulset又创建了一个与删除掉的pod同名的pod
NAME               READY   STATUS    RESTARTS   AGE   IP             NODE    NOMINATED NODE   READINESS GATES
statefulset-sc-1   1/1     Running   0          4s    10.244.1.211   node1   <none>           <none>
[root@master statefulset]# kubectl exec -it statefulset-sc-1 -- ls /var/data/	#查看数据,仍是之前的数据
file1

#以上说明,由statefulset创建pod挂掉之后,statefulset又会创建一个同名的pod,而且继承了之前的存储,但是pod的ip和pod所在的节点可能与之
# 前的pod不同,因为我们之前说过,statefulset创建的pod都是有索引顺序的,而pod的ip是随机分配的,pod所在的节点也是由调度器决定的

statefulset缩容和扩容、滚动更新

statefulset缩容会依次删除最高索引的pod,但是即使pod删除了,其对应的pvc和pv仍保留着,需要手动删除,这里不在举例演示;
statefulset扩容也是依次从最高索引的下一个索引开始创建pod ,如果是动态分配pv,则创建对应的pv,这里也不在举例演示;
statefulset滚动更新和deployment一样,没有什么好讲的,这里不在陈诉。

总结

1、什么是无状态应用?先来回顾deployment,deployment创建了replicaset,由replicaset创建的pod都是无状态的,pod的名字都是replicaset
名字+随机字符构成的,pod的启动顺序也是无所谓的,而且当一个pod消亡了,重新创建的pod是和消亡的pod没有任何关系的,所有pod副本都是使用同一
个持久卷。这样的pod应用称之为无状态应用。
2、什么是有状态应用?使用StatefulSet创建有状态应用,由StatefulSet创建的每个pod实例都是不可替代的个体,都拥有稳定的名字和状态;每个
pod都有一个从0开始的顺序索引,每个pod都有自己的持久卷存储;当一个由StatefulSet创建的pod实例消失后,新创建的pod会拥有与之前消失的pod
完全一致的名称;扩容一个由StatefulSet创建的pod实例,会使用下一个还没使用到的顺序索引值来创建一个新的pod实例;缩容一个StatefulSet将会
最先删除最高索引值的pod实例;当一个pod实例消失之后,其pvc和pv会被保留下来,新创建的pod实例将与消失的pod名称一模一样并且继续继承其pvc
和pv。
3、statefulset资源必须要有一个headless service。
4、可以手动创建pv,然后在创建statefulset资源,如下:
#首先在nfs服务器上创建3个目录pv-0、pv-1、pv-2
[root@mysql k8s_data]# pwd					
/home/k8s_data
[root@mysql k8s_data]# ll
total 0
drwxr-xr-x. 2 nfsnobody nfsnobody 23 May  3 22:39 pv-0
drwxr-xr-x. 2 nfsnobody nfsnobody 23 May  3 22:39 pv-1
drwxr-xr-x. 2 nfsnobody nfsnobody 23 May  3 22:39 pv-2

#现在开始创建pv,下面这个只是pv-0的资源清单,pv-1和pv-2的也照着做,不过注意修改name和path字段值
[root@master pv-nfs]# vim pv-nfs-0.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-0								#按照这个模板创建3个pv,名称分别是 pv-0、 pv-1、 pv-2
  labels:
    app: pv-nfs-0
spec:
  capacity:
    storage: 100M
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: 192.168.118.128
    path: /home/k8s_data/pv-0/				#同理,这里的目录也要修改为对应的目录
    readOnly: false
[root@master statefulset]# kubectl get pv				#现在3个pv已经创建好了,status是可用状态
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-0    100M       RWO            Retain           Available                                    4s
pv-1    100M       RWO            Retain           Available                                    4s
pv-2    100M       RWO            Retain           Available                                    4s
[root@master statefulset]# vim statefulset.yaml 	#创建statefulset资源清单
apiVersion: v1
kind: Service							#先创建一个无头service
metadata:
  labels:								#service本身的标签
    app: svc-statefulset-headless
  name: svc-statefulset-headless		#service的名称,下面创建的StatefulSet就要引用这个service名称
spec:
  ports:
  - port: 80							#service本身的端口
    protocol: TCP
    targetPort: 80						#目标端口80,即目标容器的80端口
  selector:
    app: nginx-statefulset				#标签选择器要与下面创建的pod的标签一样
  type: ClusterIP
  clusterIP: None						#clusterIP为None表示创建的service为无头service
---
apiVersion: apps/v1
kind: StatefulSet						#创建StatefulSet资源
metadata:
  labels:								#StatefulSet本身的标签
    app: statefulset
  name: statefulset						#资源名称
  namespace: default					#资源所属命名空间
spec:
  selector:								#标签选择器,要与下面pod模板定义的pod标签保持一致
    matchLabels:
      app: nginx-statefulset
  replicas: 3							#副本数为3个
  serviceName: svc-statefulset-headless	#指定使用service为上面我们创建的无头service的名称
  template:			
    metadata:
      labels:							#pod的标签,上面的无头service的标签选择器和StatefulSet标签选择器都要与这个相同
        app: nginx-statefulset
    spec:
      containers:
      - name: nginx-container			#容器名称
        image: nginx:1.7.9				#镜像
        imagePullPolicy: IfNotPresent	#镜像拉取策略
        ports:							#定义容器端口
        - name: http 					#为端口取个名称为http
          containerPort: 80				#容器端口
        volumeMounts:					#挂载点
        - name: statefulset-data		#指定使用的卷名称,这里使用的是下面定义的pvc模板的名称
          mountPath: /var/data/			#挂载点
  volumeClaimTemplates:					#定义创建pvc的模板
    - metadata:
        name: statefulset-data			#模板名称
      spec:
        resources:						#资源请求
          requests:
            storage: 100M				#需要100M的存储空间
        accessModes:				
        - ReadWriteOnce					#访问模式为RWO
        storageClassName: ""			#指定使用的存储类

注意:storageClassName字段设为空字符串表示不自动创建pv,如果不定义该storageClassName字段并且存在系统存在默认的存储类,则会根据
volumeClaimTemplates模板要求自动创建pv,这里为了演示使用我们上面手动创建的pv,所以将storageClassName赋予一个空字符串。
5、使用存储类自动分配pv,如下:
[root@master pv-nfs]# kubectl get sc			#查集群中所有的存储类,只有一个储存类并且是默认存储类
NAME                         PROVISIONER              RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-storageclass (default)   nfs-client-provisioner   Retain          Immediate           false                  41d
[root@master pv-nfs]#

[root@master statefulset]# vim statefulset-sc.yaml 	#创建一个动态配置pv的statefulset资源
apiVersion: v1
kind: Service										#先创建一个无头的service
metadata:
  labels:											#service本身的标签
    app: svc-statefulset-sc-headless
  name: svc-statefulset-sc-headless					#无头service的名称
spec:
  ports:
  - port: 80										#service的端口
    protocol: TCP
    targetPort: 80									#service的目标端口,一般是对应容器端口
  selector:
    app: nginx-statefulset-sc						#标签选择器,与pod的标签应该一致
  type: ClusterIP									#service类型
  clusterIP: None									#clusterIP为None就表示创建的service是headlessservice
---
apiVersion: apps/v1									#创建statefulset资源
kind: StatefulSet
metadata:
  labels:
    app: statefulset-sc								#statefulset本身的标签
  name: statefulset-sc								#statefulset的名称
  namespace: default								#statefulset所属命名空间
spec:
  selector:											#标签选择器,要与下面的pod的标签一致
    matchLabels:
      app: nginx-statefulset-sc	
  replicas: 3										#副本数为3个
  serviceName: svc-statefulset-sc-headless			#指定对应的service为上面创建的headless service
  template:
    metadata:
      labels:										
        app: nginx-statefulset-sc					#pod的标签,与上面的statefulset标签选择器一致
    spec:
      containers:					
      - name: nginx-container						#容器名称
        image: nginx:1.7.9							#镜像名称及版本
        imagePullPolicy: IfNotPresent				#镜像拉取策略
        ports:
        - name: http 								#端口名称,这个端口名称可以被service的targetPort直接引用
          containerPort: 80							#容器端口
        volumeMounts:
        - name: statefulset-data					#引用自下面创建的持久卷声明模板的name相同
          mountPath: /var/data/						#挂载点
  volumeClaimTemplates:								#定义一个pvc的模板
    - metadata:	
        name: statefulset-data						#模板的名称
      spec:	
        resources:									#资源定义
          requests:
            storage: 100M							#容量100M
        accessModes:			
        - ReadWriteOnce								#访问模式RWO
        storageClassName: nfs-storageclass			#指定使用的存储类
[root@master statefulset]#
#上面在volumeClaimTemplates中使用了storageClassName指定了存储类,这样创建pvc时就会动态pv,并与pvc进行绑定,不用在手动创建pv。
注意:即使不写storageClassName属性,但是集群中有默认的存储类,此时仍会动态创建pv,如果不想要动态创建pv,想要pvc绑定主机你手动创建的
pv,那么必须指定storageClassName: "",即给定storageClassName一个空字符串告诉它不用自动创建pv,这样创建statefulset时的pvc就会寻找
你手动创建的pv进行匹配绑定而不是自动创建pv了。

再次强调,不管了手动分配pv还是使用存储类动态分配pv,由statefulset创建的每个pod实例都有自己对应的pvc,而pvc需要绑定到一个匹配的pv,也就是说每个pod实例都有自己的专属持久卷存储。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值