摘要:当1号丢失之后,我们就会发现缺了一个人,于是赶紧补一个新人上来,但是它的编号还是1,由于房子(资源)是和1(序号)绑定的,那么补上来的这个人依然可以使用这个房子,这就是statefulset的全部故事。
排版好像没有颜色和加粗等格式了,这个k8s系列写完看看有没有别的平台。
对本系列有兴趣的,可以在电脑端看。
statefulset带有状态,下面举一个简例,假如说有三个号0,1,2分别对应三个人,而且这三个号还同时绑定了三个房子,如下所示:
当1号丢失之后,我们就会发现缺了一个人,于是赶紧补一个新人上来,但是它的编号还是1,由于房子(资源)是和1(序号)绑定的,那么补上来的这个人依然可以使用这个房子,这就是statefulset的全部故事。
对应到容器上,我们创建三个Pod分别是0、1、2,如果1号Pod删除重建了,那么系统就会察觉到,赶紧补一个上来。它发现是1号缺了,就按照1号的规格造一个Pod。可以看出在StatefulSet模式下,每个Pod都被编了号,成了”正式工“。
对于普通的Pod,创建之后最大的特点就是名字有时是不确定的,比如whoami-xxxxxxx,那么会有什么问题呢?假设有一个Pod名为whoami-abc,它绑定了一个PV资源,里面写了很多数据,当重建的时候名字变成随机的whoami-cde了,那么它怎么还能找到原来的那些数据呢?或者说系统怎么能让这两者之间建立映射呢?按逻辑上来说,它应该要找到,不然那些数据全没了。
StatefulSet就是要解决这个问题,它的核心是序号,假如有三个副本,就生成0,1,2这样的序号,每个Pod绑定一个;当序号对应的Pod缺失时,就补充到对应的序号上。下面我们先通过一个简单的实例说明。
需求:用whoami创建两个副本,然后通过StorageClass类动态创建两个PV并绑定。我动手删除第一个Pod,那么系统会自动新建一个,我的要求是这个Pod还能自动绑定原来的那个PV。
根据需求,可以得到下面的架构图:
分析:
Pod通过StorageClass动态申请资源,可以参考第21篇文章,详细说明了操作流程,我们首先要把它部署好statefulSet是通过PVC模板生成PVC的,这一点就是它的核心。#文件名:whoami-statefulset.yamlcat whoami-statefulset.yaml# 1. 无头Service(为StatefulSet提供固定网络标识)apiVersion: v1kind: Servicemetadata:name: whoami-headlesslabels:app: whoamispec:clusterIP: None # 无头Service标志ports:- port: 80name: webselector:app: whoami---# 2. StatefulSet配置(管理whoami实例)apiVersion: apps/v1kind: StatefulSetmetadata:name: whoamispec:serviceName: whoami-headlessreplicas: 2selector:matchLabels:app: whoamitemplate:metadata:labels:app: whoamispec:containers:- name: whoamiimage: crpi-gj5arn39i861t1eu.cn-hangzhou.personal.cr.aliyuncs.com/dev-team-sz/whoamiports:- containerPort: 80name: webvolumeMounts:- name: data # 挂载PVC存储mountPath: /data # 容器内的挂载目录# 3. PVC模板(动态生成PVC)volumeClaimTemplates:- metadata:name: data # PVC名称前缀spec:accessModes: [ "ReadWriteOnce" ]storageClassName: "nfs-dynamic" #存储类名称resources:requests:storage: 1Gi # 每个实例申请1GB存储EOF#部署kubectl apply -f whoami-statefulset.yaml关键在于StatefulSet配置的PVC模板,我们指定了使用的StorageClass类,这个参数很重要,那么statefulSet就根据模板生成一个具体的PVC,只是在幕后操作我们看不到,但最终它是执行了,所以可以通过kubectl get PVC命令查看到。
生成的PVC名字 = --,所以我们看到的是data-whoami-0、data-whoami-1...。
statefulSet部署的Pod名字也是固定的,等于-,一般序号就是从0开始,所以我们看到Pod的名字为whoami-0、whoami-1...。
PVC生成之后就部署了,这就和第21篇文章的流程一样了,storageClass模板有指定的NFS插件,于是插件赶紧的在NFS服务端创建了一个目录,然后又创建了一个PV和申请的PVC绑定。
PV和PVC的流程弄清楚了,现在还剩一个问题,Pod怎么关联到PVC呢?
这个也是通过statefulSet来实现,它在创建Pod的时候就明确了Pod和哪个PVC绑在一起,如下所示:
可以看到,只要作为核心的序号确定,那么这个PVC也确定了,0号Pod就对应data-whoami-0。
我们首先安装NFS服务端,部署k8s下的NFS插件,再部署一个StorageClass,这三件套可以保证底层干活的流程是通的。
当使用statefulSet部署Pod时,每个Pod的名字都是固定的,主要按序号0,1,2...进行编号。然后根据模板生成具体的PVC,依然是按着序号绑定,比如0号Pod绑定0号的PVC,依此类推。
PVC生成并部署之后,底层干活的插件就会生成目录,并且在集群中生成一个PV,让PV和PVC绑定,又由于Pod和PVC绑定,那么Pod就相当于和得到的PV绑定了,Pod赶紧让PV挂载到自己内部的目录,资源获取就完成了!
当某个Pod重建时,就是补上丢失的号,无论Pod怎样,号是不变的,那么Pod绑定的就还是原序号的PVC和PV。
当Pod删除时,PVC和PV还存活,这是很容易理解的,不然新创建的Pod到哪绑定原来的PV呢?所以动态生成的PVC和PV需要手动删除。
流程结束。
第一步:进入whoami-0号Pod,然后写入一个文件
kubectl exec -it whoami -- sh#写入文件vim default-data-whoami-0...第二步:进入master节点(也就是NFS服务端所在节点)的/nfs/dynamic/default-data-whoami-0-xxx目录下查看
cd /nfs/dynamic...可以看到有文件default-data-whoami-0,说明写入成功。
第三步:删除whoami-0
kubectl delete pod whoami-0第四步:再次进入whoami查看
kubectl exec -it whoami-0 -- shcd /data可以看到原来存储的default-data-whoami-0还在,验证成功!!
来源:恋爱脑一点号