【探索 Kubernetes|作业管理篇 系列 13】StatefulSet 拓扑状态

news2024/11/17 23:53:06

前言

大家好,我是秋意零。

在上一篇中,我们讲解了 Deployment 这种无状态的控制器;而如果要部署有状态的应用,那么 Deployment 显然是达不到我们的需求的。

今天讲解的是 StatefulSet 有状态控制器。

最近搞了一个扣扣群,旨在技术交流、博客互助,希望各位大佬多多支持!

获取方式:

  • 1.在我主页推广区域,如图:

👿 简介

  • 🏠 个人主页: 秋意零
  • 🧑 个人介绍:在校期间参与众多云计算相关比赛,如:🌟 “省赛”、“国赛”,并斩获多项奖项荣誉证书
  • 🎉 目前状况:24 届毕业生,拿到一家私有云(IAAS)公司 offer,暑假开始实习
  • 🔥 账号:各个平台, 秋意零 账号创作者、 云社区 创建者
  • 💕欢迎大家:欢迎大家一起学习云计算,走向年薪 30 万

系列文章目录


【云原生|探索 Kubernetes-1】容器的本质是进程
【云原生|探索 Kubernetes-2】容器 Linux Cgroups 限制
【云原生|探索 Kubernetes 系列 3】深入理解容器进程的文件系统
【云原生|探索 Kubernetes 系列 4】现代云原生时代的引擎
【云原生|探索 Kubernetes 系列 5】简化 Kubernetes 的部署,深入解析其工作流程


更多点击专栏查看:深入探索 Kubernetes

正文开始

  • 快速上船,马上开始掌舵了(Kubernetes),距离开船还有 3s,2s,1s...

目录

前言

系列文章目录

一、有状态、无状态应用

二、StatefulSet

无头服务 Headless Service

Headless Service 方式访问

总结


一、有状态、无状态应用

1.Deployment 不能覆盖所有应用编排的问题,在于 Deployment 对应用做了一个简单化假设:

  • Deployment 管理部署 Pod 中的应用,是完全一样的。所以,它们互相之间没有顺序,不管它们的任何物理环境,只有正常运行就可以了(不管在那台主机运行),删除时随便哪一个都能删除,没有顺序之分,因为它们之前没有任何关系,都是互相独立的存在。

这种对于实例之间都是对等的关系的应用,就被称为 “无状态应用”(Stateless application),如:Web 应用。

2.在实际中,有部分场景是不能满足,这样的需求:

  • 分布式类应用:它多个应用实例之间,一般都是有依赖关系的,也就有了顺序之分,如:主从、主备关系。
  • 数据存储类应用:它的多个实例,一般都需要将一份数据保存在本地磁盘。而这些实例一旦被杀掉,即便重建出来,实例与数据之间的对应关系也已经丢失,从而导致应用失败。

所以对于实例之间不对等的关系(分布式类应用);以及实例对外部数据有依赖关系的应用(数据存储类应用),就被称为 “有状态应用”(Stateful Application)。

二、StatefulSet

StatefulSet 的设计,是把现实世界里的应用状态,分为了两种:

  • 1.拓扑状态:这种情况,也就对应的上述的“分布式类应用”。就是将两个或多个之间不对等关系的实例,严格按照某些启动顺序和删除顺序。如:应用 A 是主节点,应用 B 是从节点,这种情况下我们现实部署中,是按照 A 主节点(Pod)先启动,其次才是 B 从节点(Pod);需要删除时,首先删除 B 从节点,其次才是 A 主节点。所以 StatefulSet 拓扑状态也是这样做的。并且,新创建出来的 Pod,必须和原来 Pod 的网络标识一样,这样原先的访问者才能使用同样的方法,访问到这个新 Pod。
  • 2.存储状态:这种情况,也就对应上述的“数据存储类应用”。多个应用实例分别绑定不同的存储空间;并且对于所有应用来说,每一个应用 Pod 第一次读取的数据和之后所有时间内所读取的数据都应该时同一份数据,哪怕是在此期间 Pod 被删除重新创建过。这种情况典型例子,一个数据库应用的多个存储实例,如:数据库主从、集群等。

所以 StatefulSet 的核心功能就是,记录这两种状态,当 Pod 被重新创建时,还能恢复到之前的一样状态。

无头服务 Headless Service

无头服务是 StatefulSet 一个重要的概念。无头服务是和 Service 对象配合使用的。

正是通过这种无头服务(DNS域名解析),保证了每次访问之前的 Pod 时都能访问到是同一个,不管它是否重建过。

1、Service 是 Kubernetes 项目中用来将一组 Pod 暴露给外界访问的一种机制。

如:一个 Deployment 有 3 个 Pod,那么我就可以定义一个 Service 与其绑定。然后,用户只要能访问到这个 Service,它就能访问到某个具体的 Pod。

Servcie 支持 2 种访问方式:

  • 1.Service 的 VIP 方式(Virtual IP,即:虚拟 IP)。如:当我访问 10.0.23.1 这个 Service 的 IP 地址时,10.0.23.1 其实就是一个 VIP,它会把请求转发到该 Service 所代理的某一个 Pod 上。
  • 2.Service 的 DNS 方式。如:这时候,只要我访问“my-svc.my-namespace.svc.cluster.local”这条 DNS 记录,就可以访问到名叫 my-svc 的 Service 所代理的某一个 Pod。

Service 的 DNS 方式,有两种处理方法:

  • 1.Normal Service(普通服务):你访问 <service-name>.<namespace>.svc.cluster.local解析到的,正是 <service-name> 这个 Service 的 VIP,后面的流程就跟 VIP 方式一致了。
  • 2.Headless Service(无头服务):你访问<pod-name>.<service-name>.<namespace>.svc.cluster.local解析到的,直接就是 <service-name> 代理的某一个 Pod 的 IP 地址。可以看到,这里的区别在于,Headless Service 不需要分配一个 VIP,而是可以直接以 DNS 记录的方式解析出被代理 Pod 的 IP 地址。

2、这样的设计又有什么作用呢?

  • Service

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

apiVersion: v1
kind: Service
metadata:
  name: my-headless-service-busybox
spec:
  clusterIP: None
  selector:
    app: my-app

可以看到 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 地址。

  • StatefulSet

StatefulSet 又是如何使用这个 DNS 记录来维持 Pod 的拓扑状态的呢?如下:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: my-statefulset
spec:
  serviceName: my-headless-service-busybox
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-busybox
          image: busybox
          imagePullPolicy: IfNotPresent
          args:
          - sleep
          - "3600"

StatefulSet 这个 YAML 文件,与之前 Deployment 的唯一区别,就是多了 serviceName: my-headless-service-busybox字段。这个字段告诉 StatefulSet 控制器, 使用 Headless Service 来保证 Pod 的“可解析身份”。

现在,我们执行 kubectl apply 命令创建 StatefulSet:

  • 你可以看到,创建 StatefulSet 后,将 Pod 名字,进行了编号,编号的规则是:<statefulset name>-<ordinal index>
  • 而且这些编号都是从 0 开始累加,与 StatefulSet 的每个 Pod 实例一一对应,绝不重复。
  • 并且 Pod 的创建,也是严格按照编号顺序进行的。当编号为 0 的 Pod ,状态没有 Running 时,编号 0 之后的 Pod 是不会继续创建的。
[root@master01 yaml]# kubectl apply -f statefulset-busybox.yaml
statefulset.apps/my-statefulset created
service/my-headless-service-busybox created

[root@master01 yaml]# kubectl get pod -w
NAME               READY   STATUS    RESTARTS   AGE
my-statefulset-0   0/1     Pending   0          0s
my-statefulset-0   0/1     ContainerCreating   0          0s
my-statefulset-0   1/1     Running             0          2s

my-statefulset-1   0/1     Pending             0          0s
my-statefulset-1   0/1     ContainerCreating   0          0s
my-statefulset-1   1/1     Running             0          2s

my-statefulset-2   0/1     Pending             0          0s
my-statefulset-2   0/1     ContainerCreating   0          1s
my-statefulset-2   1/1     Running             0          2s

我们可以将 Pod 删掉,看看它的删除顺序:

  • 首先,Pod 从最高编号-最低编号删除后;
  • 其次,就会按照,最低编号-最高编号创建。
[root@master01 yaml]# kubectl delete pod --all

当这两个 Pod 都进入了 Running 状态之后,你就可以查看到它们各自唯一的“网络身份”了。

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

[root@master01 yaml]# kubectl exec -it my-statefulset-0 -- sh -c 'hostname'
my-statefulset-0
[root@master01 yaml]# kubectl exec -it my-statefulset-1 -- sh -c 'hostname'
my-statefulset-1
[root@master01 yaml]# kubectl exec -it my-statefulset-2 -- sh -c 'hostname'
my-statefulset-2

Headless Service 方式访问

可以看到,这 3 个 Pod 的 hostname 与 Pod 名字是一致的,都被分配了对应的编号。接下来,我们再以 DNS 的方式,访问一下这个 Headless Service。

我们可以进入,这 3 个 Pod 中的一个,进入之前查看 Pod 的 IP 地址:

用于直接访问无头服务中的每个 Pod 的 IP 地址列表:<pod-name>.<svc-name>

[root@master01 yaml]# kubectl exec -it my-statefulset-0 -- sh -c 'ping my-statefulset-0.my-headless-service-busybox'
PING my-statefulset-0.my-headless-service-busybox (10.244.5.53): 56 data bytes
64 bytes from 10.244.5.53: seq=0 ttl=64 time=0.054 ms
64 bytes from 10.244.5.53: seq=1 ttl=64 time=0.101 ms
64 bytes from 10.244.5.53: seq=2 ttl=64 time=0.084 ms

Normal Service 的 DNS 访问格式为:<svc-name>.<namespace>.svc.cluster.local

/ # ping my-headless-service-busybox.default.svc.cluster.local
PING my-headless-service-busybox.default.svc.cluster.local (10.244.241.122): 56 data bytes
64 bytes from 10.244.241.122: seq=0 ttl=62 time=1.002 ms
64 bytes from 10.244.241.122: seq=1 ttl=62 time=0.752 ms
64 bytes from 10.244.241.122: seq=2 ttl=62 time=1.138 ms

/ # ping my-headless-service-busybox.default.svc.cluster.local
PING my-headless-service-busybox.default.svc.cluster.local (10.244.5.58): 56 data bytes
64 bytes from 10.244.5.58: seq=0 ttl=63 time=0.227 ms
64 bytes from 10.244.5.58: seq=1 ttl=63 time=0.128 ms

/ # ping my-headless-service-busybox.default.svc.cluster.local
PING my-headless-service-busybox.default.svc.cluster.local (10.244.5.57): 56 data bytes
64 bytes from 10.244.5.57: seq=0 ttl=64 time=0.068 ms
64 bytes from 10.244.5.57: seq=1 ttl=64 time=0.090 ms
64 bytes from 10.244.5.57: seq=2 ttl=64 time=0.093 ms

Headless Service 的 DNS 访问格式:<pod-name>.<svc-name>.<namespace>.svc.cluster.local

[root@master01 yaml]# kubectl exec -it my-statefulset-0 -- sh
/ # ping my-statefulset-0.my-headless-service-busybox.default.svc.cluster.local
PING my-statefulset-0.my-headless-service-busybox.default.svc.cluster.local (10.244.5.57): 56 data bytes
64 bytes from 10.244.5.57: seq=0 ttl=64 time=0.306 ms
64 bytes from 10.244.5.57: seq=1 ttl=64 time=0.097 ms
64 bytes from 10.244.5.57: seq=2 ttl=64 time=0.074 ms

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

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

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

对于“有状态应用”实例的访问,你必须使用 DNS 记录或者 hostname 的方式,而绝不应该直接访问这些 Pod 的 IP 地址,因为重建之后 IP 地址是会变化的,而 hostname 不会变,正是通过 DNS 的方式才能访问到对应的不变的 hostname。

总结

今天,主要介绍了 StatefulSet 的控制器的无状态服务的拓扑状态。

首先,说明了有状态服务和无状态服务的概念区别;

其次,StatefulSet 控制器实现无状态服务的两种应用状态,拓扑状态和数据存储状态;

最后,说明了 Serivice 的无头服务。

最后:技术交流、博客互助,点击下方或主页推广加入哦!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电气照明节能设计在智能控制系统中的应用

【摘要】&#xff1a;随着社会的不断发展&#xff0c;经济水平也随之稳步提升&#xff0c;人们的消防意识也正在逐步加强&#xff0c;这就促进了消防应急照明系统的发展。当今社会,智能照明系统已经普及到家家户户&#xff0c;并在建筑工程中被广泛应用&#xff0c;同时其自身具…

【计算机网络自顶向下】计算机网络期末自测题(一)

前言 “(学不懂一点) &#xff08;阴暗的爬行&#xff09;&#xff08;尖叫&#xff09;&#xff08;扭曲&#xff09;&#xff08;阴暗的爬行&#xff09;&#xff08;尖叫&#xff09;&#xff08;扭曲&#xff09;&#xff08;阴暗的爬行&#xff09;&#xff08;尖叫&#…

非公平锁实现原理+源码解读

目录 非公平锁实现原理 加锁解锁流程 加锁源码 解锁源码 非公平锁实现原理 加锁解锁流程 先从构造器开始看&#xff0c;默认为非公平锁实现 public ReentrantLock() {sync new NonfairSync(); } NonfairSync 继承自 AQS 没有竞争时 第一个竞争出现时 Thread-1 执行了…

解决不允许一个用户使用一个以上用户名与一个服务器或共享资源的多重连接的问题

问题概述&#xff1a; 用windows server 2012 r2 vl x64搭了个文件服务器&#xff0c;在使用时有个问题&#xff0c;老是用户登录有问题&#xff0c;提示“不允许一个用户使用一个以上用户名与一个服务器或共享资源的多重连接”。出现的原因不详&#xff0c;网上也没查到合理的…

操作系统3:CPU任务调度和进程调度

目录 1、处理机调度的层次 &#xff08;1&#xff09;高级调度(High Level Scheduling) &#xff08;2&#xff09;低级调度(Low Level Scheduling) &#xff08;3&#xff09;中级调度(Intermediate Scheduling) 2、处理机调度算法的目标 批处理系统的目标 3、作业与作…

MongoDB 基于角色的访问控制

一、概述 MongoDB采用基于角色的访问控制&#xff08;RBAC&#xff09;来管理对 MongoDB系统。向用户授予一个或多个角色那 确定用户对数据库资源和操作的访问权限。外面 在角色分配中&#xff0c;用户无权访问系统。 1、启用访问控制 MongoDB默认情况下不启用访问控制。您可…

Facebook Insights分析工具解读,掌握关键数据指标

什么是Facebook Insights&#xff1f; Facebook Insights是Facebook平台上的一项内置分析工具&#xff0c;旨在帮助企业和品牌了解其在Facebook上的表现和受众互动情况。该工具提供了丰富的数据和指标&#xff0c;可以帮助用户洞察粉丝群体、了解发布内容的表现&#xff0c;并…

闭门造轮(LVGL_2)

例程1_// 组件(widgets)&#xff1a; 标签(label)的用法 static void label_event_cb(lv_event_t * e) {lv_obj_t * obj lv_event_get_target(e); // 获取触发事件的部件(对象)lv_event_code_t code lv_event_get_code(e); // 获取当前部件(对象)触发的事件代码sw…

Golang每日一练(leetDay0105) 最小高度树、戳气球

目录 310. 最小高度树 Minimum Height Trees &#x1f31f;&#x1f31f; 312. 戳气球 Burst Balloons &#x1f31f;&#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一…

用自定义域名访问Tailscale节点

需求 tailscale 是好东西&#xff0c;在任何地方都可以和在局域网访问一样&#xff0c;但是也有着 IP 访问的不便&#xff0c;一方面 IP 是 tailscale 分配的&#xff08;非子网路由模式&#xff09;&#xff0c;另一方面还要记住各种端口 tailscale 也考虑到了这些问题&…

SpringBoot 使用 TestRestTemplate 进行 RESTful API 集成测试

SpringBoot 使用 TestRestTemplate 进行 RESTful API 集成测试 RESTful API 集成测试是测试应用程序与其外部依赖项之间的集成。SpringBoot提供了TestRestTemplate来测试RESTful API&#xff0c;本文将介绍如何使用TestRestTemplate进行RESTful API集成测试。 1. 什么是 TestR…

java File类 和 IO流

File类 文件和文件夹(文件路径)的抽象表示&#xff0c;是专门来出来磁盘上面的文件或文件夹的 构造方法 方法 返回boolean creatNewFile() 生成一个文件&#xff0c;当且仅当具有该名称的文件尚不存在时 public class Demo02 {public static void main(String[] args) th…

知了汇智网安项目实训助力高校实战型人才培养

当前&#xff0c;随着信息技术的高速发展和网络的普及应用&#xff0c;网络安全面临着日益复杂和严峻的挑战。恶意黑客、网络病毒、数据泄露等安全威胁不断涌现&#xff0c;给个人、企业和国家的信息资产和社会稳定带来了巨大风险。新形势之下&#xff0c;培养网络安全实战型人…

深眸科技受邀参加昆山元宇宙装备展与产业论坛,为工业视觉注智赋能

为落实《“十四五”数字经济发展规划》&#xff0c;进一步夯实元宇宙在终端装备领域的落地与拓展&#xff0c;江苏昆山将于6月27至29日&#xff0c;举办“2023元宇宙装备展”。本届展会由昆山市人民政府主办&#xff0c;昆山市工业和信息化局、赛迪工业和信息化研究院集团&…

力扣题库刷题笔记8--字符串转换正数(atoi)

1、题目如下&#xff1a; 2、个人Python代码实现如下&#xff1a; 这里可以看到&#xff0c;解答错误很多次&#xff0c;实际上就是对于题目的条件读的不够细&#xff0c;导致很多边界值的用例跑不过。而且个人习惯极其不好&#xff0c;没有输入各种可能的输入进行调试&#xf…

【计算机网络自顶向下】计算机网络期末自测题(一)答案

2019-2020 学年第 2 学期自测题答案及评分标准 (卷 1) 计算机网络 一、 填空题&#xff1a; 参考答案&#xff1a; 1 、 01000101 、11100111 3 、 100Mbps、双绞线、基带、全双工 [10Mbps 要求单位] 4 、 报文 5 、 ICMP 6 、 虚电路 7 、 距离矢量、链路状态 …

考虑充电负荷空间可调度特性的分布式电源与电动汽车充电站联合配置方法(matlab代码)

目录 1 主要内容 目标函数 电动汽车负荷建模 算例系统图 程序亮点 2 部分代码 3 程序结果 ​4 下载链接 1 主要内容 该程序复现博士文章《互动环境下分布式电源与电动汽车充电站的优化配置方法研究》第四章《考虑充电负荷空间可调度特性的分布式电源与电动汽车充电站联…

【抗扰PID控制】干扰抑制PID控制器研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Excel管理工具简陋但强大 vs 雷军为何说“没有设计是最好的设计

解密&#xff1a;雷军为何说“没有设计是最好的设计” 雷军洗白&#xff1a;没有刻意的设计才是最好的设计&#xff01; 有的人开发了10个到50个&#xff0c;甚至几百个Excel管理工具。每个工具里面有VBA代码几千行。 还有个高手&#xff0c;趁过年一个月左右时间完成一个公司用…

SAP ABAP DIALOG 表格控件的简单例子<转载>

本文是一个很见到的ALV表格控件例子&#xff0c;但是原文作者写的很详细&#xff0c;所以借过来一用&#xff0c;很适合新手练手用。在这里感谢原文作者大大&#xff01; 原文链接&#xff1a;https://mp.weixin.qq.com/s/bhP3w5DIADdf9P624C5kpw 表格控件是ABAP编程中最常用的…