云原生|kubernetes| StateFulSets控制器详解

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 云原生|kubernetes| StateFulSets控制器详解

前言:

kubernetes有很多的控制器,比如 replicasets(简称rs),replicationcontrollers(简称rc),Deployment(简称deploy),DaemonSets(简称ds),StateFulSets(简称sts),那么,rs,rc是基本的pod控制器,这个就不说了,底层控制器,和deploy深度绑定。deploy和ds相对其它的控制器来说就非常常用了,基本的部署工作都是由这两个控制器完成,而sts由于它的自身特点导致它的使用范围不是特别的宽,但也是一个极为重要的控制器,需要我们能够熟练使用此控制器。

StateFulSets的基本概念:

StatefulSet本质上是Deployment的一种变体,在v1.9版本中已成为GA版本,它为了解决有状态服务的问题,它所管理的Pod拥有固定的Pod名称,启停顺序,在StatefulSet中,Pod名字称为网络标识(hostname),还必须要用到共享存储。
在Deployment中,与之对应的服务是service,而在StatefulSet中与之对应的headless service,headless service,即无头服务,与service的区别就是它没有Cluster IP,解析它的名称时将返回该Headless Service对应的全部Pod的Endpoint列表。
除此之外,StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod副本创建了一个DNS域名,这个域名的格式为:
FQDN:$(podname).(headless server name).namespace.svc.cluster.local

 

StateFulSets的构成方式

pod部署清单,部署方式指定为StateFulSets;

Headless Service:用来定义Pod网络标识( DNS domain);(这个无头service的作用是可以体现StateFulSet控制器的稳定的网络特性,不是非必须的,可用可不用)
volumeClaimTemplates :存储卷申请模板,创建PVC,指定pvc名称大小,将自动创建pvc,且pvc必须由存储类供应(这个是体现StateFulSet控制器的稳定的存储特性,不是非必须的,可用可不用)

StateFulSets的特点:

Pod一致性:包含次序(启动、停止次序)、网络一致性。此一致性与Pod相关,与被调度到哪个node节点无关;
稳定的次序:对于N个副本的StatefulSet,每个Pod都在[0,N)的范围内分配一个数字序号,且是唯一的;
稳定的网络:Pod的hostname模式为( s t a t e f u l s e t 名 称 ) − (statefulset名称)-(statefulset名称)−(序号);
稳定的存储:通过VolumeClaimTemplate为每个Pod创建一个PV。删除、减少副本,不会删除相关的卷。

 

OK,以上是StateFulSets的基本介绍,下面就由两个部署实例来说明如何使用StateFulSets控制器并说明它的具体特点。

在正式的使用StateFulSets方式部署之前,建议先部署一个nfs-client-provisioner插件,使得集群内部能够动态的分配pv,nfs-client-provisioner插件部署见我的博客:

kubernetes学习之持久化存储StorageClass(4)_晚风_END的博客-CSDN博客

一,

StateFulSets方式部署nginx

首先,确认我的nfs插件已经安装好了,也就是动态存储插件可用了:

StorageClass的名称是managed-nfs-storage

[root@k8s-master nfs]# k get sc
NAME                            PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
managed-nfs-storage (default)   fuseim.pri/ifs   Delete          Immediate           true                   6h9m

部署使用StateFulSet控制器的nginx的清单文件:

cat << EOF > nginx-sts.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
  namespace: web
spec:
  selector:
    matchLabels:
      app: nginx #必须匹配 .spec.template.metadata.labels
  serviceName: "nginx"  #声明它属于哪个Headless Service.
  replicas: 3 #副本数
  template:
    metadata:
      labels:
        app: nginx # 必须配置 .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: nginx:1.20
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: nginx-pvc
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:   #可看作pvc的模板
  - metadata:
      name: nginx-pvc
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "managed-nfs-storage"  #存储类名,改为集群中已存在的
      resources:
        requests:
          storage: 1Gi
EOF

无头service:

cat << EOF > nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: web
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
EOF

查看pod的情况(注意,这些pod的名称是web+递增的数字组成的,如果扩容名称按顺序增加,那么一个稳定的pod名称的意义在于集群内的DNS将会有一个稳定的解析,pod无论怎么改变):

[root@k8s-master nfs-sc]# k get po -n web -owide
NAME    READY   STATUS    RESTARTS   AGE   IP           NODE         NOMINATED NODE   READINESS GATES
web-0   1/1     Running   0          6s    10.244.0.7   k8s-master   <none>           <none>
web-1   1/1     Running   0          5s    10.244.2.9   k8s-node2    <none>           <none>
web-2   1/1     Running   0          3s    10.244.1.7   k8s-node1    <none>           <none>

 

查看pv和pvc的情况:

[root@k8s-master nfs-sc]# k get pv,pvc -n web
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS          REASON   AGE
persistentvolume/pvc-a7b73ac0-d881-4c96-9fdb-e8d71f60d848   1Gi        RWO            Delete           Bound    web/nginx-pvc-web-1   managed-nfs-storage            40m
persistentvolume/pvc-dabd8050-77f6-4655-8434-dac2f9a077eb   1Gi        RWO            Delete           Bound    web/nginx-pvc-web-2   managed-nfs-storage            40m
persistentvolume/pvc-eb159490-353c-4aea-9412-10056a29911d   1Gi        RWO            Delete           Bound    web/nginx-pvc-web-0   managed-nfs-storage            40m
NAME                                    STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
persistentvolumeclaim/nginx-pvc-web-0   Bound    pvc-eb159490-353c-4aea-9412-10056a29911d   1Gi        RWO            managed-nfs-storage   40m
persistentvolumeclaim/nginx-pvc-web-1   Bound    pvc-a7b73ac0-d881-4c96-9fdb-e8d71f60d848   1Gi        RWO            managed-nfs-storage   40m
persistentvolumeclaim/nginx-pvc-web-2   Bound    pvc-dabd8050-77f6-4655-8434-dac2f9a077eb   1Gi        RWO            managed-nfs-storage   40m

查看service的情况:

[root@k8s-master nfs-sc]# k get svc -n web
NAME    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   None         <none>        80/TCP    42m

此时,进入nfs的存储目录可以看到有三个文件夹,以pod名称开始:

[root@k8s-master nfs-sc]# ls web-nginx-pvc-web-*
web-nginx-pvc-web-0-pvc-eb159490-353c-4aea-9412-10056a29911d:
web-nginx-pvc-web-1-pvc-a7b73ac0-d881-4c96-9fdb-e8d71f60d848:
web-nginx-pvc-web-2-pvc-dabd8050-77f6-4655-8434-dac2f9a077eb

在每个目录下建立nginx的首页测试文件:

[root@k8s-master nfs-sc]# echo "wo shi web-0" >web-nginx-pvc-web-0-pvc-eb159490-353c-4aea-9412-10056a29911d/index.html 
[root@k8s-master nfs-sc]# echo "wo shi web-1" >web-nginx-pvc-web-1-pvc-a7b73ac0-d881-4c96-9fdb-e8d71f60d848/index.html 
[root@k8s-master nfs-sc]# echo "wo shi web-2" >web-nginx-pvc-web-2-pvc-dabd8050-77f6-4655-8434-dac2f9a077eb/index.html 

查看pod的IP:

[root@k8s-master nfs-sc]# k get po -n web -owide
NAME    READY   STATUS    RESTARTS   AGE   IP           NODE         NOMINATED NODE   READINESS GATES
web-0   1/1     Running   0          34m   10.244.1.6   k8s-node1    <none>           <none>
web-1   1/1     Running   0          34m   10.244.2.8   k8s-node2    <none>           <none>
web-2   1/1     Running   0          34m   10.244.0.6   k8s-master   <none>           <none>

访问测试页面:

[root@k8s-master nfs-sc]# curl 10.244.1.6
wo shi web-0
[root@k8s-master nfs-sc]# curl 10.244.2.8
wo shi web-1
[root@k8s-master nfs-sc]# curl 10.244.0.6
wo shi web-2

删除pod,重新生成pod以改变它们的IP,测试看看nginx的首页文件还能否访问到:

可以看到,pod的IP如何改变不影响它对外提供服务,因为volume存储是不变的,

[root@k8s-master nfs-sc]# k delete pod web-0 web-1 web-2 -n web
pod "web-0" deleted
pod "web-1" deleted
pod "web-2" deleted
[root@k8s-master nfs-sc]# k get po -n web -owide
NAME    READY   STATUS    RESTARTS   AGE   IP           NODE         NOMINATED NODE   READINESS GATES
web-0   1/1     Running   0          6s    10.244.0.7   k8s-master   <none>           <none>
web-1   1/1     Running   0          5s    10.244.2.9   k8s-node2    <none>           <none>
web-2   1/1     Running   0          3s    10.244.1.7   k8s-node1    <none>           <none>
[root@k8s-master nfs-sc]# curl 10.244.0.7
wo shi web-0
[root@k8s-master nfs-sc]# curl 10.244.2.9
wo shi web-1
[root@k8s-master nfs-sc]# curl 10.244.1.7
wo shi web-2

二,

StateFulSet方式部署MySQL

建立相关namespace,名字叫database:

cat > mysql-sts-ns.yaml <<EOF
apiVersion: v1
kind: Namespace
metadata:
  name: database
EOF

部署MySQL的清单文件:

cat > mysql-sts.yaml <<EOF
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
  namespace: database
spec:
  selector:
    matchLabels:
      app: mysql #必须匹配 .spec.template.metadata.labels
  serviceName: "mysql"  #声明它属于哪个Headless Service.
  replicas: 3 #副本数
  template:
    metadata:
      labels:
        app: mysql # 必须配置 .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: mysql
        image: mysql:5.7.23
        ports:
        - containerPort: 3306
        name: mysql
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: "123456"
        volumeMounts:
        - name: mysql-pvc
          mountPath: /var/lib/mysql
  volumeClaimTemplates:   #可看作pvc的模板
  - metadata:
      name: mysql-pvc
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "managed-nfs-storage"  #存储类名,改为集群中已存在的
      resources:
        requests:
          storage: 1Gi
EOF

部署完成后,查看pod的大体信息:

[root@k8s-master ~]# k get pod,pv,pvc  -n database -owide
NAME          READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
pod/mysql-0   1/1     Running   0          38m   10.244.2.10   k8s-node2    <none>           <none>
pod/mysql-1   1/1     Running   0          38m   10.244.0.8    k8s-master   <none>           <none>
pod/mysql-2   1/1     Running   0          37m   10.244.0.9    k8s-master   <none>           <none>
NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                        STORAGECLASS          REASON   AGE     VOLUMEMODE
persistentvolume/pvc-46e7893f-3b66-4899-ae13-f1400eb1ff7f   1Gi        RWO            Delete           Bound    database/mysql-pvc-mysql-2   managed-nfs-storage            37m     Filesystem
persistentvolume/pvc-96748d04-0e1c-4b70-8c93-baf6a1d857d3   1Gi        RWO            Delete           Bound    database/mysql-pvc-mysql-1   managed-nfs-storage            38m     Filesystem
persistentvolume/pvc-a7b73ac0-d881-4c96-9fdb-e8d71f60d848   1Gi        RWO            Delete           Bound    web/nginx-pvc-web-1          managed-nfs-storage            4h40m   Filesystem
persistentvolume/pvc-b939521e-1e4b-4ba4-92b7-94f96cdba9a1   1Gi        RWO            Delete           Bound    database/mysql-pvc-mysql-0   managed-nfs-storage            38m     Filesystem
persistentvolume/pvc-dabd8050-77f6-4655-8434-dac2f9a077eb   1Gi        RWO            Delete           Bound    web/nginx-pvc-web-2          managed-nfs-storage            4h40m   Filesystem
persistentvolume/pvc-eb159490-353c-4aea-9412-10056a29911d   1Gi        RWO            Delete           Bound    web/nginx-pvc-web-0          managed-nfs-storage            4h40m   Filesystem
NAME                                      STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE   VOLUMEMODE
persistentvolumeclaim/mysql-pvc-mysql-0   Bound    pvc-b939521e-1e4b-4ba4-92b7-94f96cdba9a1   1Gi        RWO            managed-nfs-storage   38m   Filesystem
persistentvolumeclaim/mysql-pvc-mysql-1   Bound    pvc-96748d04-0e1c-4b70-8c93-baf6a1d857d3   1Gi        RWO            managed-nfs-storage   38m   Filesystem
persistentvolumeclaim/mysql-pvc-mysql-2   Bound    pvc-46e7893f-3b66-4899-ae13-f1400eb1ff7f   1Gi        RWO            managed-nfs-storage   37m   Filesystem

测试:

首先安装一哈MySQL的客户端:

yum install mariadb -y

登录进数据库后,依次按pod名称建立相应的数据库名称以作标识(本例就做了一个):

账号是root,密码是123456

[root@k8s-master ~]# mysql -uroot -p -h10.244.2.10
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.23 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]> create database mysql-0;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-0' at line 1
MySQL [(none)]> create database mysql0;
Query OK, 1 row affected (0.01 sec)

删除MySQL的相关pod,等待重建pod完成后,再次进入数据库查看前面建立的数据库标识是否存在:

可以看到,删除原pod后,重新建立了pod,pod的IP改变了,但登录进去后,标识用的数据库还是存在的。

[root@k8s-master ~]# k delete pod  mysql-0 mysql-1 mysql-2 -n database
pod "mysql-0" deleted
pod "mysql-1" deleted
pod "mysql-2" deleted
[root@k8s-master ~]# k get po -n database -owide
NAME      READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
mysql-0   1/1     Running   0          49s   10.244.2.11   k8s-node2    <none>           <none>
mysql-1   1/1     Running   0          40s   10.244.0.10   k8s-master   <none>           <none>
mysql-2   1/1     Running   0          38s   10.244.0.11   k8s-master   <none>           <none>
[root@k8s-master ~]# mysql -uroot -p123456 -h10.244.2.11
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.23 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| mysql0             |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.03 sec)



总结:

StateFulSet控制器的两个显著特点,一,按顺序创建,pod名称包含有自增数字,这使得它的域名是可以固定的。二,由StateFulSet控制器通过StorageClass控制器来控制volume持久存储卷和pod的名称一一对应,从而使得pod更加的稳定。

其实,说人话就是StateFulSet控制器使得pod能够形成一组pod,这一组pod能够进行一定的序列化。因此,StateFulSet控制器常常使用在比较复杂的需要一定序列化特点的集群搭建方面,比如,MySQL主从复制集群,redis集群的部署基础都是StateFulSet控制器。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
3天前
|
存储 Kubernetes 开发者
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
Docker 是一种开源的应用容器引擎,允许开发者将应用程序及其依赖打包成可移植的镜像,并在任何支持 Docker 的平台上运行。其核心概念包括镜像、容器和仓库。镜像是只读的文件系统,容器是镜像的运行实例,仓库用于存储和分发镜像。Kubernetes(k8s)则是容器集群管理系统,提供自动化部署、扩展和维护等功能,支持服务发现、负载均衡、自动伸缩等特性。两者结合使用,可以实现高效的容器化应用管理和运维。Docker 主要用于单主机上的容器管理,而 Kubernetes 则专注于跨多主机的容器编排与调度。尽管 k8s 逐渐减少了对 Docker 作为容器运行时的支持,但 Doc
28 5
容器化时代的领航者:Docker 和 Kubernetes 云原生时代的黄金搭档
|
29天前
|
Kubernetes Cloud Native 微服务
云原生入门与实践:Kubernetes的简易部署
云原生技术正改变着现代应用的开发和部署方式。本文将引导你了解云原生的基础概念,并重点介绍如何使用Kubernetes进行容器编排。我们将通过一个简易的示例来展示如何快速启动一个Kubernetes集群,并在其上运行一个简单的应用。无论你是云原生新手还是希望扩展现有知识,本文都将为你提供实用的信息和启发性的见解。
|
1月前
|
Kubernetes Cloud Native 开发者
云原生入门:Kubernetes的简易指南
【10月更文挑战第41天】本文将带你进入云原生的世界,特别是Kubernetes——一个强大的容器编排平台。我们将一起探索它的基本概念和操作,让你能够轻松管理和部署应用。无论你是新手还是有经验的开发者,这篇文章都能让你对Kubernetes有更深入的理解。
|
1月前
|
运维 Kubernetes Cloud Native
云原生技术入门:Kubernetes和Docker的协同工作
【10月更文挑战第43天】在云计算时代,云原生技术成为推动现代软件部署和运行的关键力量。本篇文章将带你了解云原生的基本概念,重点探讨Kubernetes和Docker如何协同工作以支持容器化应用的生命周期管理。通过实际代码示例,我们将展示如何在Kubernetes集群中部署和管理Docker容器,从而为初学者提供一条清晰的学习路径。
|
1月前
|
Kubernetes Cloud Native 云计算
云原生入门:Kubernetes 和容器化基础
在这篇文章中,我们将一起揭开云原生技术的神秘面纱。通过简单易懂的语言,我们将探索如何利用Kubernetes和容器化技术简化应用的部署和管理。无论你是初学者还是有一定经验的开发者,本文都将为你提供一条清晰的道路,帮助你理解和运用这些强大的工具。让我们从基础开始,逐步深入了解,最终能够自信地使用这些技术来优化我们的工作流程。
|
22天前
|
运维 Cloud Native 持续交付
深入理解云原生架构及其在现代企业中的应用
随着数字化转型的浪潮席卷全球,企业正面临着前所未有的挑战与机遇。云计算技术的迅猛发展,特别是云原生架构的兴起,正在重塑企业的IT基础设施和软件开发模式。本文将深入探讨云原生的核心概念、关键技术以及如何在企业中实施云原生策略,以实现更高效的资源利用和更快的市场响应速度。通过分析云原生架构的优势和面临的挑战,我们将揭示它如何助力企业在激烈的市场竞争中保持领先地位。
|
20天前
|
Kubernetes Cloud Native 微服务
探索云原生技术:容器化与微服务架构的融合之旅
本文将带领读者深入了解云原生技术的核心概念,特别是容器化和微服务架构如何相辅相成,共同构建现代软件系统。我们将通过实际代码示例,探讨如何在云平台上部署和管理微服务,以及如何使用容器编排工具来自动化这一过程。文章旨在为开发者和技术决策者提供实用的指导,帮助他们在云原生时代中更好地设计、部署和维护应用。
|
1月前
|
Cloud Native Devops 云计算
云计算的未来:云原生架构与微服务的革命####
【10月更文挑战第21天】 随着企业数字化转型的加速,云原生技术正迅速成为IT行业的新宠。本文深入探讨了云原生架构的核心理念、关键技术如容器化和微服务的优势,以及如何通过这些技术实现高效、灵活且可扩展的现代应用开发。我们将揭示云原生如何重塑软件开发流程,提升业务敏捷性,并探索其对企业IT架构的深远影响。 ####
43 3
|
1月前
|
Cloud Native 持续交付 云计算
云原生架构的演进与挑战
随着云计算技术的不断发展,云原生架构已成为企业数字化转型的重要支撑。本文深入探讨了云原生架构的概念、发展历程、核心技术以及面临的挑战,旨在为读者提供一个全面了解云原生架构的视角。通过分析Kubernetes、Docker等关键技术的应用,以及微服务、持续集成/持续部署(CI/CD)等实践案例,本文揭示了云原生架构在提高应用开发效率、降低运维成本、增强系统可扩展性等方面的显著优势。同时,也指出了云原生架构在安全性、复杂性管理等方面所面临的挑战,并提出了相应的解决策略。
|
20天前
|
运维 Cloud Native 持续交付
云原生技术深度探索:重塑现代IT架构的无形之力####
本文深入剖析了云原生技术的核心概念、关键技术组件及其对现代IT架构变革的深远影响。通过实例解析,揭示云原生如何促进企业实现敏捷开发、弹性伸缩与成本优化,为数字化转型提供强有力的技术支撑。不同于传统综述,本摘要直接聚焦于云原生技术的价值本质,旨在为读者构建一个宏观且具体的技术蓝图。 ####

热门文章

最新文章