千家信息网

k8s的StatefulSet(有状态服务)实现

发表于:2025-01-18 作者:千家信息网编辑
千家信息网最后更新 2025年01月18日,StatefulSet介绍遇到的问题:使用Deployment创建的Pod是无状态的,当挂在Volume之后,如果该Pod挂了,Replication Controller会再run一个来保证可用性,
千家信息网最后更新 2025年01月18日k8s的StatefulSet(有状态服务)实现

StatefulSet介绍

遇到的问题:

使用Deployment创建的Pod是无状态的,当挂在Volume之后,如果该Pod挂了,Replication Controller会再run一个来保证可用性,但是由于是无状态的,Pod挂了的时候与之前的Volume的关系就已经断开了,新起来的Pod无法找到之前的Pod。但是对于用户而言,他们对底层的Pod挂了没有感知,但是当Pod挂了之后就无法再使用之前挂载的磁盘了。

StatefulSet: 是一种给Pod提供唯一标志的控制器,它可以保证部署和扩展的顺序。

Pod一致性:包含次序(启动、停止次序)、网络一致性。此一致性与Pod相关,与被调度到哪个node节点无关。

稳定的次序:对于N个副本的StatefulSet,每个Pod都在[0,N)的范围内分配一个数字序号,且是唯一的。

稳定的网络:Pod的hostname模式为(statefulset名称)- (序号)。

稳定的存储:通过VolumeClaimTemplate为每个Pod创建一个PV。删除、减少副本,不会删除相关的卷。

(1) RC、 RS、Deployment、DS。-----> 无状态服务

template(模板):根据模板 创建出来的Pod,它们J的状态都是一模一样的(除了名称,IP, 域名之外)

可以理解为:任何一个Pod, 都可以被删除,然后用新生成的Pod进行替换。

(2) 有状态的服务: 需要记录前一 次或者多次通信中的相关事件,以作为一下通信的分类标准。比如: mysql等数据库服务。(Pod的名称,不能随意变化。数据持久化的目录也是不一样,每一个Pod都有自己独有的数据持久化存储目录。)

mysql:主从关系。

如果把之前无状态的服务比喻为牛、羊等牲畜,因为,这些到一定时候就可以"送出"。那么,有状态就比喻为:宠物,而宠物不像牲畜一样到达一定时候"送出",人们往往会照顾宠物的一生。

(3) 每一个Pod---->对应一个PVC---->每一个PVC对应一个PV。

storageclass:自动创建PV

需要解决:自动创建PVC。

实现原理

与 ReplicaSet 和 Deployment 资源一样,StatefulSet 也使用控制器的方式实现,它主要由 StatefulSetController、StatefulSetControl 和 StatefulPodControl 三个组件协作来完成 StatefulSet 的管理,StatefulSetController 会同时从 PodInformer 和 ReplicaSetInformer 中接受增删改事件并将事件推送到队列中:

控制器 StatefulSetController 会在 Run 方法中启动多个 Goroutine 协程,这些协程会从队列中获取待处理的 StatefulSet 资源进行同步,接下来我们会先介绍 Kubernetes 同步 StatefulSet 的过程。

1,例子

(1)创建一个statefulset的yaml文件

[root@master yaml]# vim statefulset.yamlapiVersion: v1kind: Servicemetadata:  name: headless-svc  labels:    app: headless-svcspec:  ports:  - port: 80  selector:    app: headless-pod  clusterIP: None     #没有同一的ip---apiVersion: apps/v1kind: StatefulSetmetadata:  name: statefulset-testspec:  serviceName: headless-svc  replicas: 3  selector:    matchLabels:      app: headless-pod  template:    metadata:      labels:        app: headless-pod    spec:      containers:      - name: myhttpd        image: httpd        ports:        - containerPort: 80

Deployment : Deploy+RS+随机字符串(Pod的名称。)没有顺序的,可
以没随意替代的。

1、headless-svc :无头服务。因为没有IP地址,所以它不具备负载均衡的功能了。因为statefulset要求Pod的名称是有顺序的,每一个Pod都不能被随意取代,也就是即使Pod重建之后,名称依然不变。为后端的每一个Pod去命名。

2、statefulSet:定义具体的应用

3、volumeClaimT emplates:自动创建PVC,为后端的Pod提供专有的存储。

执行一下

[root@master yaml]# kubectl apply -f statefulset.yaml 

查看一下

[root@master yaml]# kubectl get svc

[root@master yaml]# kubectl get pod//可看到这些pod是有顺序的

一、创建StorageClass资源对象。

1、基于NFS服务,创建NFS服务。

下载nfs所需安装包

[root@node02 ~]# yum -y install nfs-utils  rpcbind

创建共享目录

[root@master ~]# mkdir /nfsdata

创建共享目录的权限

[root@master ~]# vim /etc/exports/nfsdata *(rw,sync,no_root_squash)

开启nfs和rpcbind

[root@master ~]# systemctl start nfs-server.service [root@master ~]# systemctl start rpcbind

测试一下

[root@master ~]# showmount -e

2、创建rbac权限。

[root@master yaml]# vim rbac-rolebind.yaml apiVersion: v1kind: ServiceAccountmetadata:  name: nfs-provisioner---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:  name: nfs-provisioner-runnerrules:   -  apiGroups: [""]      resources: ["persistentvolumes"]      verbs: ["get", "list", "watch", "create", "delete"]   -  apiGroups: [""]      resources: ["persistentvolumeclaims"]      verbs: ["get", "list", "watch", "update"]   -  apiGroups: ["storage.k8s.io"]      resources: ["storageclasses"]      verbs: ["get", "list", "watch"]   -  apiGroups: [""]      resources: ["events"]      verbs: ["watch", "create", "update", "patch"]   -  apiGroups: [""]apiVersion: v1kind: ServiceAccountmetadata:  name: nfs-provisioner---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:  name: nfs-provisioner-runnerrules:   -  apiGroups: [""]      resources: ["persistentvolumes"]      verbs: ["get", "list", "watch", "create", "delete"]   -  apiGroups: [""]      resources: ["persistentvolumeclaims"]      verbs: ["get", "list", "watch", "update"]   -  apiGroups: ["storage.k8s.io"]      resources: ["storageclasses"]      verbs: ["get", "list", "watch"]   -  apiGroups: [""]      resources: ["events"]      verbs: ["watch", "create", "update", "patch"]   -  apiGroups: [""]      resources: ["services", "endpoints"]      verbs: ["get","create","list", "watch","update"]   -  apiGroups: ["extensions"]      resources: ["podsecuritypolicies"]      resourceNames: ["nfs-provisioner"]      verbs: ["use"]---kind: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata:  name: run-nfs-provisionersubjects:  - kind: ServiceAccount    name: nfs-provisioner    namespace: default   #必写字段roleRef:  kind: ClusterRole  name: nfs-provisioner-runner  apiGroup: rbac.authorization.k8s.io

执行一下

[root@master yaml]# kubectl apply -f rbac-rolebind.yaml 

3、创建Deployment资源对象,用Pod代替 真正的NFS服务。

[root@master yaml]# vim nfs-deployment.yaml apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: nfs-client-provisionerspec:  replicas: 1  strategy:    type: Recreate  template:    metadata:      labels:        app: nfs-client-provisioner    spec:      serviceAccount: nfs-provisioner      containers:        - name: nfs-client-provisioner          image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner          volumeMounts:            - name: nfs-client-root              mountPath:  /persistentvolumes          env:            - name: PROVISIONER_NAME              value: bdqn            - name: NFS_SERVER              value: 192.168.1.21            - name: NFS_PATH              value: /nfsdata      volumes:        - name: nfs-client-root          nfs:            server: 192.168.1.21            path: /nfsdata

执行一下

[root@master yaml]# kubectl apply -f nfs-deployment.yaml 

查看一下

[root@master yaml]# kubectl get pod

4、创建storageclass的yaml文件

[root@master yaml]# vim test-storageclass.yaml apiVersion: storage.k8s.io/v1kind: StorageClassmetadata:  name: stateful-nfsprovisioner: bdqn  #通过provisioner字段关联到上述DeployreclaimPolicy: Retain

执行一下

[root@master yaml]# kubectl apply -f test-storageclass.yaml

查看一下

[root@master yaml]# kubectl get sc

二,解决自动创建pvc

1、创建statefulset的yaml文件

[root@master yaml]# vim statefulset.yaml apiVersion: v1kind: Servicemetadata:  name: headless-svc  labels:    app: headless-svcspec:  ports:  - port: 80    name: myweb  selector:    app: headless-pod  clusterIP: None---apiVersion: apps/v1kind: StatefulSetmetadata:  name: statefulset-testspec:  serviceName: headless-svc  replicas: 3  selector:    matchLabels:      app: headless-pod  template:    metadata:      labels:        app: headless-pod    spec:      containers:      - image: httpd        name: myhttpd        ports:        - containerPort: 80          name: httpd        volumeMounts:        - mountPath: /mnt          name: test  volumeClaimTemplates:  #> 自动创建PVC,为后端的Pod提供专有的存储。**  - metadata:      name: test      annotations:   #这是指定storageclass        volume.beta.kubernetes.io/storage-class: stateful-nfs    spec:      accessModes:        - ReadWriteOnce      resources:        requests:          storage: 100Mi

在此示例中:

  • 创建了一个名为 headless-svc 的 Service 对象,由 metadata: name 字段指示。该 Service 会定位一个名为 headless-svc 的应用,由 labels: app: headless-svcselector: app: headless-pod 指示。该 Service 会公开端口 80 并将其命名为 web。而且该 Service 会控制网域并将互联网流量路由到 StatefulSet 部署的容器化应用。
  • 使用三个副本 Pod (replicas: 3) 创建了一个名为 web 的 StatefulSet。
  • Pod 模板 (spec: template) 指示其 Pod 标记为 app: headless-pod
  • Pod 规范 (template: spec) 指示 StatefulSet 的 Pod 运行一个容器 myhttpd,该容器运行版本为 httpd 映像。容器映像由 Container Registry 管理。
  • Pod 规范使用由 Service 打开的 web 端口。
  • template: spec: volumeMounts 指定一个名为 testmountPathmountPath 是容器中应装载存储卷的路径。
  • StatefulSet 预配了一个具有 100mb 预配存储空间的 PersistentVolumeClaim:test

执行一下

[root@master yaml]# kubectl apply -f statefulset.yaml

查看一下

[root@master yaml]# kubectl get pod

如果第一个pod出现了问题,后面的pod就不会生成。

[root@master yaml]# kubectl get statefulsets

2、 验证一下数据存储

容器中创建文件
[root@master yaml]# kubectl exec -it statefulset-test-0 /bin/sh# cd /mnt# touch testfile# exit
宿主机查看一下
[root@master yaml]# ls /nfsdata/default-test-statefulset-test-0-pvc-bf1ae1d0-f496-4d69-b33b-39e8aa0a6e8d/testfile

三、小实验

以自己的名称创建一个名称空间,以下所有资源都运行在此空间中。用statefuset资源运行一个httpd web服务,要求3个Pod,但是每个Pod的主界面内容不一样,并且都要做专有的数据持久化,尝试删除其中一个Pod,查看新生成的Pod,总结对比与之前Deployment资源控制器控制的Pod有什么不同之处?

(一)创建StorageClass资源对象。

注意:nfs服务要开启

1、创建namespace的yaml文件

[root@master yaml]# vim namespace.yaml kind: NamespaceapiVersion: v1metadata:  name: xgp-lll    #namespave的名称
执行一下
[root@master yaml]# kubectl apply -f namespace.yaml 
查看一下
[root@master yaml]# kubectl get namespaces 

2. 创建rbac权限。

[root@master yaml]# vim rbac-rolebind.yamlapiVersion: v1kind: ServiceAccountmetadata:  name: nfs-provisioner  namespace: xgp-lll---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:  name: nfs-provisioner-runner  namespace: xgp-lllrules:   -  apiGroups: [""]      resources: ["persistentvolumes"]      verbs: ["get", "list", "watch", "create", "delete"]   -  apiGroups: [""]      resources: ["persistentvolumeclaims"]      verbs: ["get", "list", "watch", "update"]   -  apiGroups: ["storage.k8s.io"]      resources: ["storageclasses"]      verbs: ["get", "list", "watch"]   -  apiGroups: [""]      resources: ["events"]      verbs: ["watch", "create", "update", "patch"]   -  apiGroups: [""]      resources: ["services", "endpoints"]      verbs: ["get","create","list", "watch","update"]   -  apiGroups: ["extensions"]      resources: ["podsecuritypolicies"]      resourceNames: ["nfs-provisioner"]      verbs: ["use"]---kind: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata:  name: run-nfs-provisionersubjects:  - kind: ServiceAccount    name: nfs-provisioner    namespace: xgp-lllroleRef:  kind: ClusterRole  name: nfs-provisioner-runner  apiGroup: rbac.authorization.k8s.io
执行一下
[root@master yaml]# kubectl apply -f rbac-rolebind.yaml

3、创建Deployment资源对象,用Pod代替 真正的NFS服务。

[root@master yaml]# vim nfs-deployment.yaml apiVersion: extensions/v1beta1kind: Deploymentmetadata:  name: nfs-client-provisioner  namespace: xgp-lllspec:  replicas: 1  strategy:    type: Recreate  template:    metadata:      labels:        app: nfs-client-provisioner    spec:      serviceAccount: nfs-provisioner      containers:        - name: nfs-client-provisioner          image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner          volumeMounts:            - name: nfs-client-root              mountPath:  /persistentvolumes          env:            - name: PROVISIONER_NAME              value: xgp            - name: NFS_SERVER              value: 192.168.1.21            - name: NFS_PATH              value: /nfsdata      volumes:        - name: nfs-client-root          nfs:            server: 192.168.1.21            path: /nfsdata
执行一下
[root@master yaml]# kubectl apply -f nfs-deployment.yaml 
查看一下
[root@master yaml]# kubectl get pod  -n xgp-lll 

4、创建storageclass的yaml文件

[root@master yaml]# vim test-storageclass.yaml apiVersion: storage.k8s.io/v1kind: StorageClassmetadata:  name: stateful-nfs  namespace: xgp-lllprovisioner: xgp  #通过provisioner字段关联到上述DeployreclaimPolicy: Retain
执行一下
[root@master yaml]# kubectl apply -f test-storageclass.yaml
查看一下
[root@master yaml]# kubectl get sc -n  xgp-lll

(二)解决自动创建pvc

1、创建statefulset的yaml文件

apiVersion: v1kind: Servicemetadata:  name: headless-svc  namespace: xgp-lll  labels:    app: headless-svcspec:  ports:  - port: 80    name: myweb  selector:    app: headless-podapiVersion: apps/v1kind: StatefulSetmetadata:  name: statefulset-test  namespace: xgp-lllspec:  serviceName: headless-svc  replicas: 3  selector:    matchLabels:      app: headless-pod  template:    metadata:      labels:        app: headless-pod    spec:      containers:      - image: httpd        name: myhttpd        ports:        - containerPort: 80          name: httpd        volumeMounts:        - mountPath: /usr/local/apache2/htdocs          name: test  volumeClaimTemplates:  #> 自动创建PVC,为后端的Pod提供专有的>存储。**  - metadata:      name: test      annotations:   #这是指定storageclass        volume.beta.kubernetes.io/storage-class: stateful-nfs    spec:      accessModes:        - ReadWriteOnce      resources:        requests:          storage: 100Mi

执行一下

[root@master yaml]# kubectl apply -f statefulset.yaml

查看一下

[root@master yaml]# kubectl get pod -n xgp-lll 

2、 验证一下数据存储

容器中创建文件
第一个[root@master yaml]# kubectl exec -it -n xgp-lll statefulset-test-0 /bin/bash root@statefulset-test-0:/usr/local/apache2# echo 123 > /usr/local/apache2/htdocs/index.html第二个[root@master yaml]# kubectl exec -it -n xgp-lll statefulset-test-1 /bin/bash root@statefulset-test-2:/usr/local/apache2# echo 456 > /usr/local/apache2/htdocs/index.html第三个[root@master yaml]# kubectl exec -it -n xgp-lll statefulset-test-2 /bin/bash root@statefulset-test-1:/usr/local/apache2# echo 789 > /usr/local/apache2/htdocs/index.html
宿主机查看一下
第一个[root@master yaml]# cat /nfsdata/xgp-lll-test-statefulset-test-0-pvc-ccaa02df-4721-4453-a6ec-4f2c928221d7/index.html 123第二个[root@master yaml]# cat /nfsdata/xgp-lll-test-statefulset-test-1-pvc-88e60a58-97ea-4986-91d5-a3a6e907deac/index.html 456第三个[root@master yaml]# cat /nfsdata/xgp-lll-test-statefulset-test-2-pvc-4eb2bbe2-63d2-431a-ba3e-b7b8d7e068d3/index.html 789
访问一下

服务 名称 资源 存储 文件 状态 容器 数据 控制 对象 三个 字段 指示 控制器 目录 端的 顺序 运行 一致 一致性 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 电信西安软件开发待遇 信息和网络安全教育手抄报 赛事系统数据库课设 荣耀十手机无法接通服务器怎么办 关注近期网络安全发展态势 拷贝oracle数据库 怀旧服新服务器2020年5月 软件开发从业证书 美国医学索引的网络版数据库 细心网络安全的第二个时代 java OIO的服务器端程序 乌鲁木齐软件开发行业标准 南通基础网络技术口碑推荐 租服务器 价格 网络安全宣传三部曲 江苏品牌网络技术费用 有关网络安全征文500字 银行信用卡数据库字典 重庆市网络安全攻防竞赛 安徽曙光服务器维修维保哪家好 奉贤区多功能软件开发定制价格 maybe数据库 et网络技术官网 苹果手机服务器无法建立安全链接 联通网络英雄联盟连接不到服务器 网络安全宣传三部曲 南京iphone服务器托管 公文处理网络技术流程图 南京一点通网络技术有限公司 江苏数据网络技术有限公司
0