statefulset简介
statefulset也是一种POD控制器,那为什么要放在PV/PVC之后再简介呢?这是因为statefulset是必须也有持久化数据,每个POD所对应的PV都是不一样的。相对于Deployment所创建的POD是无状态的,那statefulset是属于有状态的,即可以保留POD的状态信息。其特点有:
- 1、稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
- 2、稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现
- 3、有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
- 4、有序收缩,有序删除(即从N-1到0)
- 5、有序的滚动更新
在 k8s入门教程九:Service之服务发现 的最后有提出了一个疑问,那就是headless service这东西有什么用?这是因为statefulset的特性所决定的:在statefulset中是要求有序的,每一个pod的名称必须是固定的。当节点挂了,重建之后的标识符是不变的,每一个节点的节点名称是不能改变的。pod名称是作为pod识别的唯一标识符,必须保证其标识符的稳定并且唯一。为了实现标识符的稳定,这时候就需要一个headless service 解析直达到pod,还需要给pod配置一个唯一的名称。
Pod名称、PVC和PV关系图如下:
NFS实例演示
NFS前期准备
在一台机器上面安装NFS
1 | yum install -y nfs-common nfs-utils rpcbind |
- /data/nfs0:共享的数据目录
*:表示任何人都有权限连接,当然也可以是一个网段,一个 IP,也可以是域名- rw:读写的权限
- sync:表示文件同时写入硬盘和内存
- no_root_squash:当登录 NFS 主机使用共享目录的使用者是 root 时,其权限将被转换成为匿名使用者,通常它的 UID 与 GID,都会变成 nobody 身份
在另一台机器可以使用showmount测试下。
1 | [root@master ~]# showmount -e 192.168.1.61 |
再实际挂载测试下:
1 | mkdir /nfs{0..3} |
没有出现异常的话,说明NFS工作是正常的了。
或者使用docker来实现NFS:
1 | docker run -d --net=host --privileged --name nfs-server katacoda/contained-nfs-server:centos7 /exports/data-0001 /exports/data-0002 |
这时以/etc/exports这个配置,就相当于在192.168.1.61创建了一个共享目录,分别为:/data/nfs0 /data/nfs1 /data/nfs2 /data/nfs3,这几个以下需要使用到。
statefulset实例
创建一个NFS共享的PV,以下配置申明了一个名为pv-volume0的5G空间,挂载的目录为 192.168.1.61:/data/nfs0。
1 | apiVersion: v1 |
再创建一个StatefulSet
1 | # 创建一个名为nginx的headless svc,端口80为内部使用,注意跟nodePort的区别 |
由于StatefulSet是3个副本,但是看到只创建了web-0。在创建web-1时出错了。这是由于没有可用的PV了。所以一个POD是绑定一个PVC的,每个POD所对应的存储空间是不一样的。
1 | [root@master nfs]# kubectl get po -o wide |
按上面的创建PV的模板修改一下,再创建2个PV。之后就可以看到正常运行了。
1 | [root@master nfs]# kubectl get po -o wide |
查看一下PV以及PVC
1 | [root@master nfs]# kubectl get pv |
删除pvc时,回收策略为Recycle,会自动删除文件,而Retain,会保存文件。
statefulset总结
- 匹配 Pod name ( 网络标识 ) 的模式为:
$(statefulset名称)-$(序号),从零开始,比如上面的示例:web-0,web-1, web-2 - StatefulSet 为每个 Pod 副本创建了一个 DNS 域名,这个域名的格式为:
$(podname).(headless server name),也就意味着服务间是通过Pod域名来通信而非 Pod IP,因为当Pod所在Node发生故障时, Pod 会 被飘移到其它 Node 上,Pod IP 会发生变化,但是 Pod 域名不会有变化 - StatefulSet 使用 Headless 服务来控制 Pod 的域名,这个域名的 FQDN 为:
$(service name).$(namespace).svc.cluster.local - 根据 volumeClaimTemplates,为每个 Pod 创建一个 pvc,pvc 的命名规则匹配模式:
(volumeClaimTemplates.name)-(pod_name),比如上面的 volumeMounts.name=www, Pod name=web-[0-2],因此创建出来的 PVC 是 www-web-0、www-web-1、www-web-2 - 删除 Pod 不会删除其 pvc,手动删除 pvc 将自动释放 pv
Statefulset的启停顺序:
- 有序部署:部署StatefulSet时,如果有多个Pod副本,
它们会被顺序地创建(从0到N-1),并且,在下一个 Pod运行之前所有之前的Pod必须都是Running和Ready状态。 - 有序删除:当Pod被删除时,它们
被终止的顺序是从N-1到0。 - 有序扩展:当对Pod执行扩展操作时,与部署一样,它前面的Pod必须都处于Running和Ready状态。
mysql实例
以下是一个Mysql的实例化的StatefulSet的ymal,原链接为: https://github.com/oracle/kubernetes-website/blob/master/docs/tasks/run-application/mysql-statefulset.yaml
1 | apiVersion: apps/v1beta2 |