文章目录

  • 实验环境
  • 一、StatefulSet介绍
  • 二、实验


实验环境

完成初始化集群的环境:
(vms21)192.168.26.21——master1
(vms22)192.168.26.22——worker1
(vms23)192.168.26.23——worker2

一、StatefulSet介绍

StatefulSet——简称sts,它也是一种控制器,是有状态的(stateful),与之对应的是无状态(stateless)的deployment
回顾deployment控制器,它部署的应用是无状态的:
1.所有pod副本没有任何不同
2.pod的名字是随机生成的
3.不存储数据
4.即使存储数据,那么所有pod也是共享数据

stateless——对于无状态来说,我们一般用来对外提供服务,用户访问svc,svc关联后端的pod副本,用户访问流量无论转发到哪个pod,访问的结果都是一样的

stateful——对于有状态来说,适用于内部的一些应用

如在公司内部,有一个MySQL master、三个pod分为作为slave1、slave2、slave3,salve复制master上的数据,并且每个slave上都有自己独立的数据(如每个slave都有自己的binlog二进制日志),即使把某个slave删除了,重新创建这个pod,那么它关联的还是原来的那个数据

如下图,deployment与StatefulSet的区别:

statefulset的配置和helm配置_java


在StatefulSet中,如上图,每个slave访问的后端存储都是不一样的,若是访问slave1,则访问的是data1的数据,因此,给各个slave配置一个svc负载均衡器是没有意义的,但是用户直接访问这个pod(这里即slave)也是不好的,因为只要是控制器管理了pod,pod一旦被删除,控制器就会去重新创建它,自然IP地址肯定也是变化了的,所以不好直接访问pod

因此我们可以创建一种叫做headless service无头服务

headless service(无头服务)

什么是无头服务?——对于每个svc来说,它们都有一个ClusterIP,所谓无头服务就是不给它指定ClusterIP

访问pod的时候,就通过一种格式:pod名字.svc名字来访问,如:slave1.svc1

二、实验

在官方文档中搜索StatefulSet:https://kubernetes.io/docs/home/

statefulset的配置和helm配置_kubernetes_02


分析文档中的sts模板

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

“- - -”上下划分了Service(无头服务)和StatefulSet

Service中:
可以看到clusterIP配置成了None
spec.selector——配置Service要关联到哪些pod

StatefulSet中:
spec.serviceName——通过名字来关联svc,因此这里的名字要和上面Service中的metadata中的名字一致
spec.selector.matchLabels——要定位到哪些pod
volumeClaimTemplates——因为StatefulSet中每个pod都有自己独立的数据,因此有了这项来定义卷的模板
volumeClaimTemplates.spec.accessModes——使用的卷的格式
volumeClaimTemplates.spec下可以配置动态卷供应,可以使用storageClassName配置

1.根据模板创建yaml文件mysts1.yaml
并在其中作一些修改:
StatefulSet的名字改为mysts1
修改pod使用nginx镜像,并加上镜像拉取策略IfNotPresent
在卷模板下配置动态卷供应,使用之前创建的mysc,会为每个pod创建一个pvc出来
修改后为:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysts1
spec:
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      storageClassName: mysc
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 1Gi

2.根据之前实验中创建好的sc(若没有则参考六、存储管理-动态卷供应部分内容创建)
查看环境中的sc

kubectl get sc
#输出:
NAME   PROVISIONER                                   RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
mysc   k8s-sigs.io/nfs-subdir-external-provisioner   Delete          Immediate           false                  3m5s

此时环境中没有pv、pvc

kubectl get pv
#输出:
No resources found

kubectl get pvc
#输出:
No resources found in default namespace.

3.创建StatefulSet

kubectl apply -f mysts1.yaml

4.查看服务

kubectl get svc
#输出:
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx        ClusterIP   None         <none>        80/TCP    16s

可以看到帮我们创建了一个名为nginx、CLUSTER-IP为None的svc

5.查看sts

kubectl get sts
#输出:
NAME     READY   AGE
mysts1   2/2     50s

有两个pod副本

kubectl get pods
#输出:
NAME                                      READY   STATUS              RESTARTS       AGE
mysts1-0                                  1/1     Running             0              1m
mysts1-1                                  1/1     Running             0              1m

同时,查看pvc、pv,可以看到自动帮我们创建了两个pvc与两个pv,即各自都有自己独立的数据

kubectl get pvc
kubectl get pv

6.进入pod中编辑index.html内容

kubectl exec -it mysts1-0 -- sh -c "echo 111 > /usr/share/nginx/html/index.html"
kubectl exec -it mysts1-1 -- sh -c "echo 222 > /usr/share/nginx/html/index.html"

7.测试此时删除mysts1-0这个pod,删除后,sts会帮我们重新创建这个pod,并且pod名字还是mysts1-0

kubectl get pods
#输出:
NAME                                      READY   STATUS              RESTARTS       AGE
mysts1-0                                  0/1     ContainerCreating   0              14s
mysts1-1                                  1/1     Running             0              3m2s

并且mysts1-0的数据存储还是原来的
进入mysts1-0查看index.html内容,仍然是111

kubectl exec -it mysts1-0 -- sh -c "cat /usr/share/nginx/html/index.html"
#输出:
111

8.哪么要怎么访问sts这个服务呢?
注意:无法直接在宿主机中访问
我们通过创建一个pod,在pod里去测试访问
创建一个pod1,pod1.yaml如下:

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod1
  name: pod1
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: pod1
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}

创建这个pod

kubectl apply -f pod1.yaml

在pod测试访问sts,通过pod名.svc名来访问

kubectl exec -it pod1 -- bash
curl mysts1-0.nginx
#输出:
111

9.删除该sts

kubectl delete -f mysts1.yaml