k8s StatefulSet控制器

StatefulSet控制器

StatefulSet 是用来管理有状态应用的控制器。
参考: https://kubernetes.io/zh/docs/concepts/workloads/controllers/statefulset/

无状态应用与有状态应用

无状态应用: 如nginx

  • 请求本身包含了响应端为响应这一请求所需的全部信息。每一个请求都像首次执行一样,不会依赖之前的数据进行响应。
  • 不需要持久化的数据
  • 无状态应用的多个实例之间互不依赖,可以无序的部署、删除或伸缩

有状态应用: 如mysql

  • 前后请求有关联与依赖
  • 需要持久化的数据
  • 有状态应用的多个实例之间有依赖,不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。

StatefulSet的特点

  • 稳定的、唯一的网络标识符。 (通过headless服务实现)
  • 稳定的、持久的存储。 (通过PV,PVC,storageclass实现)
  • 有序的、优雅的部署和缩放。
  • 有序的、自动的滚动更新。

StatefulSet的YAML组成

需要三个组成部分:

  1. headless service: 实现稳定,唯一的网络标识
  2. statefulset类型资源: 写法和deployment几乎一致,就是类型不一样
  3. volumeClaimTemplate : 指定存储卷

nginx+statefulset+nfs案例

一、创建StatefulSet应用

参考: https://kubernetes.io/zh/docs/tutorials/stateful-application/basic-stateful-set/

温馨提示:做此实验前要先创建好pv,pvc等,可参考博客 https://blog.51cto.com/u_13760351/2639942

1.创建statelfulset应用

(来调用名为managed-nfs-storage的storageclass,以实现动态供给)

vim nginx-storageclass-nfs.yml

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None                                  # 无头服务
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web                                         # statefulset的名称
spec:
  serviceName: "nginx"                              # 服务名与上面的无头服务名要一致
  replicas: 3                                       # 3个副本
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.15-alpine
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html

  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "managed-nfs-storage"       # 与前面定义的storageclass名称对应
      resources:
        requests:
          storage: 1Gi

kubectl apply -f nginx-storageclass-nfs.yml
kubectl get statefulsets # 可以简写成sts

k8s  StatefulSet控制器

二、验证pod、pv、pvc

kubectl get pods |grep web

k8s  StatefulSet控制器

自动产生了3个pv

kubectl get pv

k8s  StatefulSet控制器

自动产生了3个PVC

kubectl get pvc |grep web

k8s  StatefulSet控制器

三、验证nfs服务目录

在nfs服务器(这里为hostos)的共享目录中发现自动产生了3个子目录

[root@hostos ~]# ls /data/

k8s  StatefulSet控制器

3个子目录默认都为空目录

[root@hostos ~]# tree /data/

k8s  StatefulSet控制器

四、验证存储持久性

1.在3个pod中其中一个创建一个主页文件

kubectl exec -it web-0 -- /bin/sh
/ # echo "haha" > /usr/share/nginx/html/index.html
/ # exit

在nfs服务器上发现文件被创建到了对应的目录中

[root@hostos ~]# tree /data/

k8s  StatefulSet控制器

[root@hostos ~]# cat /data/default-www-web-0-pvc-2436b20d-1be3-4c2e-87a9-5533e5c5e2c6/index.html

k8s  StatefulSet控制器

2.删除web-0这个pod,再验证

kubectl delete pod web-0
kubectl get pods |grep web #因为控制器的原因,再拉起web-0这个pod

k8s  StatefulSet控制器

kubectl exec -it web-0 -- cat /usr/share/nginx/html/index.html

k8s  StatefulSet控制器

新拉起的pod仍然是相同的存储数据

[root@hostos ~]# cat /data/nfs/default-www-web-0-pvc-2436b20d-1be3-4c2e-87a9-5533e5c5e2c6/index.html

k8s  StatefulSet控制器

nfs服务器上的数据还在

3.结论: 说明数据可持久化

五、验证pod唯一名称

回顾域名格式:

service: <service name>.<namespace name>.svc.cluster.local.
pod: <PodName>.<service name>.<namespace name>.svc.cluster.local.

可以看到在 web-0这个pod中,nslookup查询service的域名,直接解析成了3个pod的域名

kubectl exec -it web-0 -- /bin/sh
/ # nslookup nginx.default.svc.cluster.local.

k8s  StatefulSet控制器

k8s  StatefulSet控制器

ping这三个pod的域名都可以ping通

/ # ping web-0.nginx.default.svc.cluster.local.

k8s  StatefulSet控制器

/ # ping web-1.nginx.default.svc.cluster.local

k8s  StatefulSet控制器

/ # ping ping web-2.nginx.default.svc.cluster.local

k8s  StatefulSet控制器

补充: 当pod被删除后,重新拉起来,pod-IP可能会变,但上面的pod域名仍然可以ping通

k8s  StatefulSet控制器

k8s  StatefulSet控制器

六、验证statefulset的伸缩

1.扩容

kubectl scale sts web --replicas=4
kubectl get pods

k8s  StatefulSet控制器

有序地扩展了一个pod,名称为web-3

2.裁剪

kubectl scale sts web --replicas=1
kubectl get pods |grep web

k8s  StatefulSet控制器

先裁剪web-3,再裁剪web-2,最后裁剪web-1,只留下web-0

mysql-statefulset-nfs案例

一、编写statefulset

vim statefulset-mysql-nfs.yaml

apiVersion: v1
kind: Service
metadata:
  name: mysql-svc
spec:
  clusterIP: None                   # 无头服务
  ports:
  - port: 3306
    protocol: TCP
    targetPort: 3306
  selector:
    app: mysql
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql-svc            # 与上面服务名一致
  replicas: 1                       # 副本数为1就OK,这里不做mysql集群
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: c1
        image: mysql:5.7
        env:
        - name: MYSQL_ROOT_PASSWORD     # mysql5.7的镜像必须要设置一下mysql的root密码
          value: "123456"
        - name: MYSQL_DATABASE          # 给它建一个库名为daniel,用于验证
          value: daniel
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata:
      name: mysql-data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "managed-nfs-storage"          
      resources:
        requests:
          storage: 3Gi

二、应用YAML

kubectl apply -f statefulset-mysql-nfs.yaml

三、验证资源

kubectl get pods |grep mysql

k8s  StatefulSet控制器

kubectl get sts |grep mysql

k8s  StatefulSet控制器

kubectl get pv |grep mysql

k8s  StatefulSet控制器

kubectl get pvc |grep mysql

k8s  StatefulSet控制器

四、验证mysql

1.进入容器

kubectl exec -it mysql-0 -- /bin/bash

root@mysql-0:/# mysql -p123456
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| daniel             |                  # 这里daneil库就是帮我们创建的
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)
mysql> exit

k8s  StatefulSet控制器

2.验证nfs上的数据

[root@hostos ~]# ls /data/default-mysql-data-mysql-0-pvc-f936d526-f473-4b88-a0e6-b94a19b95fe6

k8s  StatefulSet控制器

删除mysql-0这个pod,会帮我们再次启动,并且数据还是用原来的数据

k8s  StatefulSet控制器

上一篇:K8S--有状态服务存储及部署(PV&PVC&StatefulSet&StrogeClass)


下一篇:react开发碎碎念