【K8S系列】深入解析StatefulSet(一)

序言

那些看似不起波澜的日复一日,一定会在某一天让你看见坚持的意义。

文章标记颜色说明:

  • 黄色:重要标题
  • 红色:用来标记结论
  • 绿色:用来标记一级论点
  • 蓝色:用来标记二级论点

Kubernetes (k8s) 是一个容器编排平台,允许在容器中运行应用程序和服务。今天学习一下StatefulSet-拓扑状态。

希望这篇文章能让你不仅有一定的收获,而且可以愉快的学习,如果有什么建议,都可以留言和我交流

这是这篇文章所在的专栏,欢迎订阅:【深入解析k8s】专栏

 专栏介绍

简单介绍一下这个专栏要做的事:

主要是深入解析每个知识点,帮助大家完全掌握k8s,一下是已更新的章节

序号文章
第一讲深入解析 k8s:入门指南(一)
第二讲深入解析 k8s:入门指南(二)
第三讲深入解析Pod对象(一)
第四讲深入解析Pod对象(二)
第五讲深入解析无状态服务
第六讲深入解析有状态服务
第七讲深入解析控制器

第八讲

深入解析 ReplicaSet
第九讲深入解析滚动升级

1 基础介绍

有状态应用

  1. 实例之间有不对等关系
  2. 实例对外部数据有依赖关系的应用

就被称为“有状态应用”(Stateful Application)。

1.1 StatefulSet 介绍

Kubernetes StatefulSet是一种用于运行有状态应用的控制器

StatefulSet是一个有序的、可标识的Pod组,并且每个Pod都有一个独特的标识符

这使得StatefulSet能够管理有状态应用程序,例如数据库或队列服务,这些应用程序需要稳定的网络标识符或持久性存储,并且需要有序的、逐个更新的部署方式。

下面是关于Kubernetes StatefulSet的详细介绍:

  • 稳定的网络标识符:在StatefulSet中,每个Pod都有一个稳定的网络标识符,可以通过DNS或其他服务发现机制进行访问。这个标识符由StatefulSet控制器在Pod创建时自动分配,并且在Pod重新启动时保持不变。这使得有状态应用程序能够在网络上稳定地被访问

  • 有序的、逐个更新的部署方式:StatefulSet能够按照一定的顺序逐个更新Pod。这意味着当需要更新有状态应用程序时,可以确保新的Pod在旧的Pod停止之前启动,并且在新的Pod启动之前,旧的Pod仍然可以提供服务这种有序的、逐个更新的部署方式使得有状态应用程序在更新时更加稳定

  • 持久性存储:StatefulSet能够管理有状态应用程序的持久性存储。每个Pod都可以有自己的持久性存储卷,并且这些存储卷可以在Pod重新启动时保持不变。这使得有状态应用程序能够在重新启动时保留其状态和数据。

  • 适合于有状态应用程序:StatefulSet适用于运行有状态应用程序,例如数据库或队列服务,这些应用程序需要稳定的网络标识符或持久性存储,并且需要有序的、逐个更新的部署方式。与Deployment不同,StatefulSet不适用于运行无状态应用程序。

总之,Kubernetes StatefulSet是一种用于运行有状态应用程序的控制器它具有稳定的网络标识符、有序的、逐个更新的部署方式以及持久性存储等特点,适用于需要这些特性的有状态应用程序。

1.2 StatefulSet资源状态

StatefulSet 资源的状态主要包括以下几个方面:

  1. Replicas: 指定的副本数,即 .spec.replicas字段的值。表示 StatefulSet 管理的副本数量。

  2. ReadyReplicas: 表示已经就绪的副本数量,即当前运行且已经READY的Pod数。

  3. CurrentReplicas: 表示当前正在运行的副本数量,即运行中的Pod总数。

  4. UpdatedReplicas: 表示已经更新的副本数量,即最近一次更新中,更新成功的Pod数。

  5. CurrentRevision: 当前正在执行的修订版本号

  6. UpdateRevision: StatefulSet 的当前修订版本号。 StatefulSet 的模板(.spec.template)每次更新时,这个值就会增加1

  7. collisionCount:表示在创建 Pod 时发生的命名冲突的次数

  8. UpdateStatus: 最近一次更新的状态,可以是"Running"或者"Failed"。

  9. ObservedGeneration: 最近一次对 StatefulSet 资源的更改,已经被看到的 Generation 数。也就是说如果 StatefulSet 的 .spec 字段被修改,该值会更新。

1.3 示例讲解

1 yaml文件

apiVersion: apps/v1
kind: StatefulSet  #资源类型
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx # has to match .spec.template.metadata.labels
  serviceName: "nginx"
  template:
    metadata:
      labels:
        app: nginx # has to match .spec.selector.matchLabels
    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
  status:
    observedGeneration: 2
    replicas: 3
    readyReplicas: 3
    currentReplicas: 3
    updatedReplicas: 3
    updateRevision: "2"
    currentRevision: "2"

从上面这个例子可以看出:

  • observedGeneration 是 2,表示 StatefulSet 的 .spec 字段已经修改过两次。
  • replicas 是 3,表示指定的副本数为 3
  • readyReplicas, currentReplicas 和 updatedReplicas 都是 3,表示所有的 3 个副本都已经准备就绪。
  • updateRevision 和 currentRevision 都是 "2",表示 StatefulSet 的模板已经更新两次,当前正在运行的也是第 2 个版本。
  • updateStatus 没有出现,表示最近一次更新状态是正常的。

2 StatefulSet 两种状态

StatefulSet 的设计,它把真实世界里的应用状态,抽象为了两种:

  • 拓扑状态
  • 存储状态

2.1拓扑状态简介

拓扑状态 :应用的多个实例之间不是完全对等的关系。这些应用实例,必须按照某些顺序启动,比如应用的主节点 A 要先于从节点 B 启动。而如果把 A 和 B 两个 Pod 删除掉,它们再次被创建出来时也必须严格按照这个顺序才行。并且,新创建出来的 Pod,必须和原来 Pod 的网络标识一样,这样原先的访问者才能使用同样的方法,访问到这个新 Pod。

2.2 存储状态简介

存储状态。应用 的多个实例分别绑定了不同的存储数据。对于这些应用实例来说,Pod A 第一次读取到的数据,和隔了十分钟之后再次读取到的数据,应该是同一份,哪怕在此期间 Pod A 被重新创建过。这种情况最典型的例子,就是一个数据库应用的多个存储实例。

也可以说:StatefulSet 的核心功能,是通过某种方式记录这些状态,然后在 Pod 被重新创建时,能够为新 Pod 恢复这些状态

3 Headless Service

讲拓扑状态之前,先讲一下 k8s Headless Service

3.1Headless Service 介绍

在Kubernetes中,Headless Service是一种特殊类型的服务它不会为Pods提供负载均衡或者访问IP,而是在DNS层面提供了一种服务发现的机制

当一个Service被定义为Headless Service时,它将会返回与该Service关联的所有Pod的DNS记录,而不是一个虚拟IP地址。

这使得客户端可以直接访问每个Pod,而不需要经过负载均衡器。

3.2 使用场景

Headless Service可以被用来实现一些特定的功能,例如:

  1. 集群内部通信:Headless Service可以被用来实现Pod之间的直接通信,例如数据库集群中的各个节点之间的通信。

  2. 分布式计算:Headless Service可以被用来实现分布式计算中的任务分发和结果收集,例如MapReduce中的Map和Reduce节点之间的通信。

  3. 自定义服务发现:Headless Service可以被用来实现一些自定义的服务发现机制,例如一些复杂的应用程序中的服务发现和路由。

3.2 yaml示例讲解

下面是一个标准的 Headless Service 对应的 YAML 文件:

apiVersion: v1
kind: Service #资源类型
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None # 为none,思考一下
  selector:
    app: nginx

可以看到,这个 Headless Service,其实仍是一个标准 Service 的 YAML 文件。只不过,它的 clusterIP 字段的值是:None

即:这个 Service,没有一个 VIP 作为“头”。这也就是 Headless 的含义。

所以,这个 Service 被创建后并不会被分配一个 VIP,而是会以 DNS 记录的方式暴露出它所代理的 Pod。

当你按照这样的方式创建了一个 Headless Service 之后,它所代理的所有 Pod 的 IP 地址,都会被绑定一个这样格式的 DNS 记录,如下所示:

<pod-name>.<svc-name>.<namespace>.svc.cluster.local

这个 DNS 记录,是 Kubernetes 项目为 Pod 分配的唯一的“可解析身份”(Resolvable Identity)。

有了这个“可解析身份”,只要知道了一个 Pod 的名字,以及它对应的 Service 的名字,你就可以非常确定地通过这条 DNS 记录访问到 Pod 的 IP 地址。

 3.3 Headless Service 与Service对比 

下图为Headless Service 与Service的简单对比 

3.4 总结 

总之,Headless Service是一种特殊类型的服务,它不提供负载均衡或者访问IP,而是在DNS层面提供了一种服务发现的机制。

Headless Service通常与StatefulSet一起使用,用于管理有状态应用程序的Pod

当一个StatefulSet被创建时,Kubernetes会自动为它创建一个与之关联的Headless Service,以便客户端可以直接访问每个Pod。

在StatefulSet中,每个Pod都会被分配一个唯一的标识符和DNS记录,例如web-0.web.default.svc.cluster.local、web-1.web.default.svc.cluster.local等。

 4 拓扑状态

4.1 问题:

思考一个问题:我们今天讲的是拓扑状态,那么………………

解答: 

StatefulSet使用一个基于DNS的标识符来定义Pod的网络标识符。每个Pod都有一个唯一的标识符,由以下格式组成:

$(podname)-$(ordinal).$(servicename).$(namespace).svc.cluster.local

其中:

  1. $(podname)是Pod的名称
  2. $(ordinal)是Pod的序号
  3. $(servicename)是Service的名称
  4. $(namespace)是命名空间

这个标识符可以通过DNS查找进行访问。

通过这种方式,StatefulSet可以将Pod的状态维护在整个集群中。当Pod重新启动时,它将保留其唯一的网络标识符,并且其他应用程序可以使用这个标识符来发现和访问Pod。

总的来说,StatefulSet通过使用DNS标识符来维护Pod的状态,并确保它们在重新启动时保持不变,从而实现了有状态应用程序的可扩展性和健壮性。

4.2示例讲解

4.2.1 StatefulSet 的 YAML:

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: nginx:1.9.1
        ports:
        - containerPort: 80
          name: web

这个 YAML 文件,和在前面用到的 nginx-deployment 的唯一区别,就是多了一个 serviceName=nginx 字段。

这个字段的作用,是告诉 StatefulSet 控制器,在执行控制循环(Control Loop)的时候,请使用 nginx 这个 Headless Service 来保证 Pod 的“可解析身份”

所以,当通过 kubectl create 创建了上面这个 Service 和 StatefulSet 之后,就会看到如下两个对象:

4.2.2 创建 

$ kubectl create -f svc.yaml
$ kubectl get service nginx
NAME      TYPE         CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
nginx     ClusterIP    None         <none>        80/TCP    10s
$ kubectl create -f statefulset.yaml
$ kubectl get statefulset web
NAME      DESIRED   CURRENT   AGE
web       2         1         19s

StatefulSet 会给它所管理的所有 Pod 的名字,进行了编号,编号规则是:-。

这些编号都是从 0 开始累加,与 StatefulSet 的每个 Pod 实例一一对应,绝不重复。

更重要的是,这些 Pod 的创建,也是严格按照编号顺序进行的。

比如,在 web-0 进入到 Running 状态、并且细分状态(Conditions)成为 Ready 之前,web-1 会一直处于 Pending 状态。

4.2.3  查看hostname

使用 kubectl exec 命令进入到容器中查看它们的 hostname:

$ kubectl exec web-0 -- sh -c 'hostname'
web-0
$ kubectl exec web-1 -- sh -c 'hostname'
web-1

 用 nslookup 命令,解析一下 Pod 对应的 Headless Service:

$ kubectl run -i --tty --image busybox dns-test --restart=Never --rm /bin/sh
$ nslookup web-0.nginx
Server:    *.*.*.*
Address 1: *.*.*.* kube-dns.kube-system.svc.cluster.local
 
Name:      web-0.nginx
Address 1: *.*.*.*
 
$ nslookup web-1.nginx
Server:    *.*.*.*
Address 1: *.*.*.* kube-dns.kube-system.svc.cluster.local
 
Name:      web-1.nginx
Address 1: *.*.*.*

可以看到,在访问 web-0.nginx 的时候,最后解析到的,正是 web-0 这个 Pod 的 IP 地址;而当访问 web-1.nginx 的时候,解析到的则是 web-1 的 IP 地址。

4.2.3 测试

新开一个窗口,把这两个“有状态应用”的 Pod 删掉,执行命令如下:

kubectl delete pod -l app=nginx

结果如下:

pod "web-0" deleted
pod "web-1" deleted

在上一个窗口,Watch 一下这两个 Pod 的状态变化,就会发现一个现象,执行命令如下:

kubectl get pod -w -l app=nginx

结果如下:

NAME      READY     STATUS              RESTARTS   AGE
web-0     0/1       ContainerCreating   0          0s
NAME      READY     STATUS    RESTARTS   AGE
web-0     1/1       Running   0          2s
web-1     0/1       Pending   0         0s
web-1     0/1       ContainerCreating   0         0s
web-1     1/1       Running   0         32s

4.2.4 测试总结

可以看到,当把那两个 Pod 删除之后,Kubernetes 会按照原先编号的顺序,创建出了两个新的 Pod。

并且,Kubernetes 依然为它们分配了与原来相同的“网络身份”:web-0.nginx 和 web-1.nginx。

通过这种严格的对应规则,StatefulSet 就保证了 Pod 网络标识的稳定性

通过这种方法,Kubernetes 就成功地将 Pod 的拓扑状态(比如:哪个节点先启动,哪个节点后启动),按照 Pod 的“名字 + 编号”的方式固定了下来。

此外,Kubernetes 还为每一个 Pod 提供了一个固定并且唯一的访问入口,即:这个 Pod 对应的 DNS 记录。

这些状态,在 StatefulSet 的整个生命周期里都会保持不变,绝不会因为对应 Pod 的删除或者重新创建而失效

不过,尽管 web-0.nginx 这条记录本身不会变,但它解析到的 Pod 的 IP 地址,并不是固定的。

这就意味着,对于“有状态应用”实例的访问,必须使用 DNS 记录或者 hostname 的方式,而绝不应该直接访问这些 Pod 的 IP 地址

5 总结

StatefulSet 这个控制器的主要作用之一,就是使用 Pod 模板创建 Pod 的时候,对它们进行编号,并且按照编号顺序逐一完成创建工作

而当 StatefulSet 的“控制循环”发现 Pod 的“实际状态”与“期望状态”不一致,需要新建或者删除 Pod 进行“调谐”的时候,它会严格按照这些 Pod 编号的顺序,逐一完成这些操作

换句话,我们可以认为StatefulSet 其实是对 Deployment 的改良。

同时,通过 Headless Service 的方式,StatefulSet 为每个 Pod 创建了一个固定并且稳定的 DNS 记录,来作为它的访问入口。

总之,在部署“有状态应用”的时候,应用的每个实例拥有唯一并且稳定的“网络标识”,是一个非常重要的假设

6 投票

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/5982.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java毕业生就业信息管理系统servlet程序

1&#xff0e;系统登录&#xff1a;系统登录是用户访问系统的路口&#xff0c;设计了系统登录界面&#xff0c;包括用户名、密码和验证码&#xff0c;然后对登录进来的用户判断身份信息&#xff0c;判断是管理员用户还是普通用户。 2&#xff0e;系统用户管理&#xff1a;不管是…

第13章_约束

第13章_约束 &#x1f3e0;个人主页&#xff1a;shark-Gao &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是shark-Gao&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f389;目前状况&#xff1a;23届毕业生&#xff0c;目前在某公司…

一次压测遇到的问题和排查过程记录

文章目录问题 & 排查1、cpu使用率过高问题描述问题排查解决方案扩展内容2、504 Gateway Time-out问题描述问题排查解决方案3、限流对压测的影响问题描述问题排查解决方案jmeter相关1、beanShell 动态生成签名2、响应断言3、导出结果树请求和响应文件问题 & 排查 1、cp…

域名批量查询功能常用查询方法教程

一些用户在抱怨&#xff0c;要找到好域名怎么就那么不容易呢&#xff0c;能不能让我批量查下不含0的数字啊&#xff0c;能不能查下不含4的数字啊&#xff0c;能不能查下AABBB这样的域名啊…… 别着急&#xff0c;这就给您支招啦&#xff1a;通过西部数码强大的批量查询功能&am…

活动报名|SOFA 五周年,Live Long and Prosper!

2018 年 4 月 19 日&#xff0c;我们在北京启程&#xff0c;伴随种下希望的种子&#xff0c;举办了 SOFAStack 社区的第一个开放日。转眼来到 2023 年&#xff0c;瑞兔送福又逢春暖花开&#xff0c;怀揣着新的愿景&#xff0c;我们将于 4 月 15 日回到北京庆祝 SOFA 的五岁生日…

服务器磁盘又双叒叕爆满了?被/proc占满?

又双叒叕服务器前言排查分析前言 继上一次文章&#xff1a; MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. 通过删除tomcat下的catalina.out文件&#xff0c;解决了磁盘爆满的问题后。今天又双叒叕出现这个问题。。…

万字长文解读「新一代CMDB落地的困境及出路」

2023年3月21日春分时节&#xff0c;优维结合在CMDB技术领域的经验沉淀与洞察能力&#xff0c;梳理金融客户在数据运营中面临的问题和挑战&#xff0c;为了帮助到广大客户建立健全有效的方法参考&#xff0c;全新策划了一档“CMDB数据运营精准化专场公开课”线上直播课程。该系列…

2023-Python实现百度翻译接口调用

目录 &#x1f449;1、目标网址 ​​​​​​​&#x1f449;2、接口分析调试 ​​​​​​​&#x1f449;3、python 代码实现 学习记录&#xff1a;百度翻译 ​​​​​​​&#x1f449;1、目标网址 百度翻译&#xff1a;百度翻译-200种语言互译、沟通全世界&#xff0…

【LeetCode】二叉树的中序遍历(递归,迭代,Morris遍历)

目录 题目要求&#xff1a;给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 方法一&#xff1a;递归 方法二&#xff1a;迭代 思路分析&#xff1a; 复杂度分析 代码展示&#xff1a; 方法三&#xff1a;Morris 遍历 思路分析&#xff1a; 复杂度分析…

Vue3学习笔记(9.1)

Vue.js style&#xff08;内联样式&#xff09; 我们可以在v-bind:style直接设置样式&#xff0c;可以简写:style <!--* Author: RealRoad1083425287qq.com* Date: 2023-04-02 19:41:53* LastEditors: Mei* LastEditTime: 2023-04-03 15:41:44* FilePath: \vscode\Vue3_li…

打气球游戏-第14届蓝桥杯STEMA测评Scratch真题精选

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第118讲。 蓝桥杯选拔赛现已更名为STEMA&#xff0c;即STEM 能力测试&#xff0c;是蓝桥杯大赛组委会与美国普林斯顿多…

Java包装类

包装类1. 包装类&#xff08;Wrapper&#xff09;1.1 基本数据类型和包装类之间的转换1.2 String类和包装类&#xff08;基本数据类型&#xff09;之间的转换2. 面试题3.包装类练习1. 包装类&#xff08;Wrapper&#xff09; 继承于java.lang.Number类&#xff1b;实现了java.…

java校园行为分析预警管理系统

目 录 摘 要 II ABSTRACT III 第一章 绪论 1 1.1研究背景 1 1.2选题目的 1 1.3本文研究内容 2 第二章 开发技术介绍 3 2.1开发工具介绍 3 2.2 JAVA技术介绍 3 2.3 MYSQL数据库介绍 4 第三章 系统需求分析 6 3.1可行性分析 6 3.1.1技术…

python之lambdas函数(lambda表达式)

python之lambdas函数&#xff08;lambda表达式&#xff09; lambda函数&#xff0c;也称为lambda表达式。 lambda函数&#xff08;或lambda表达式&#xff09;的语法&#xff1a; lambda arguments: expression 创建一个返回表达式值的匿名函数。其中&#xff1a; lambda 是…

Power Apps从入门到放弃教程

Power Apps从入门到放弃教程前言啥是Power apps文档资料官方文档官方公式文档官方控件文档案例实操添加数据源用户登录登录成功,跳转主界面添加组件提示语言流前言 Hello&#xff01;欢迎各位,当你选择阅读这篇文章时&#xff0c;相信你最近也在学习Power apps&#xff0c;并且…

Debian 达梦数据库 disql工具输入命令 左右移动光标乱码

Debian 达梦数据库 disql工具输入命令 左右移动光标乱码1、下载安装包rlwrap-0.46.12、编译安装rlwrap-0.46.12.1、安装依赖包2.2、编译安装2.3、安装成功3、设置rlwrap系统环境变量4、配置达梦护数据库用户环境变量5、测试效果1、下载安装包rlwrap-0.46.1 https://github.com…

K8s (一) --------- K8s 概述

目录一、kubernetes 基本介绍二、kubernetes 功能和架构1. 概述2. K8s 功能:3. 应用部署架构分类4. K8s 集群架构5. K8s 集群架构节点角色功能一、kubernetes 基本介绍 kubernetes&#xff0c;简称 K8s&#xff0c;是用 8 代替 8 个字符“ubernete”而成的缩写。是一个开源的&…

【数据结构】二叉树<遍历>

【二叉树遍历】|-前序-中序-后序-层序-|<二叉树的遍历>1.前序遍历【递归】2.中序遍历【递归】3.后序遍历【递归】4.层序遍历【非递归】4.1判断是否是完全二叉树<二叉树的遍历> 在学习二叉树遍历之前我们先了解下二叉树的概念。 二叉树是&#xff1a; 1.空树 2.非空…

最新 MySQL 8.0.32 在Win10安装部署(详细)

一、前言 MySQL官方Windows版下载地址&#xff1a;https://dev.mysql.com/downloads/installer/   本教程详细指导如何在Win10系统下安装部署最新版MySQL-8.0.32。   【MySQL系列安装部署教程】 Docker安装最新版MySQL5.7&#xff08;mysql-5.7.40&#xff09;教程&…

漫画党的福利——将图片转换成漫画风格 API,附超多免费可用API 推荐(四)

前言 今天来和大家聊聊一件非常有趣的事情——将图片转换成漫画风格的 API&#xff01;如果你是一个漫画党&#xff0c;相信这个话题一定会让你感到兴奋。通过这个 API&#xff0c;你可以将你的照片变成漫画风格&#xff0c;让它们变得更加有趣和艺术&#xff01; 我们先来看…
最新文章