k8s之部署有状态应用

news2024/11/14 1:57:23

写在前面

本文一起看下k8s对于有状态应用部署提供的解决方案。

在这里插入图片描述

1:有状态应用和无状态应用

如果是一个应用每次重启时依赖环境都能和第一次启动时的完全一致,则就可以称这类应用是无状态应用用,反之,就是有状态应用,如下:

支付系统(无状态应用):
    重启时只要其依赖的环境正常,则就可以正常启动对外提供服务,如其可能依赖MySQL,只要MySQL还是正常运行的,该服务就正常
MySQL(有状态应用):
    运行期间,用户创建了user表,并插入了一些数据,如果重启时,user表被删除或者是表中数据被清除则MySQL将不能正常对外提供服务。

其实,状态就是数据了,这样看来,我们只需要结合Deployment和PersistentVolume,就可以解决有状态应用的部署问题了,即只要解决了应用的数据持久化问题就行了,但k8s的眼光则显得更加的高瞻远瞩,它认为应用的状态不仅仅是数据持久化,还应该包括启动顺序(服务之间存在依赖关系),网络标识(外部通过唯一标识访问POD)等,如果将这些内容也考虑到状态的范畴的话,不管是deployment还是DaemonSet都会显得力不从心,基于此,k8s对deployment进行升级提供了StatefulSet API对象,从其名称我们也能够看出一二,定义如下:

dongyunqi@mongodaddy:~$ kubectl api-resources | egrep -w 'StatefulSet|KIND'
NAME                              SHORTNAMES   APIVERSION                             NAMESPACED   KIND
statefulsets                      sts          apps/v1                                true         StatefulSet

2:StatefulSet

sts的头信息如下:

apiVersion: apps/v1
kind: StatefulSet 
metadata:
  name: my-sts

定义如下yaml:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-sts

spec:
  serviceName: redis-svc
  replicas: 2
  selector:
    matchLabels:
      app: redis-sts

  template:
    metadata:
      labels:
        app: redis-sts
    spec:
      containers:
      - image: redis:5-alpine
        name: redis
        ports:
        - containerPort: 6379

可以看到其和deployment是十分相似的,除了文件头的KIND不同外,在spec中还多了一个serviceName,其它的如replicas,selector等和Deployment是一样的,这也很好理解,因为都是用来维护一组POD嘛。接下来我们apply查看:

dongyunqi@mongodaddy:~/k8s$ kubectl apply -f redis-sts.yml 
statefulset.apps/redis-sts created
dongyunqi@mongodaddy:~/k8s$ kubectl get pod
NAME          READY   STATUS    RESTARTS   AGE
redis-sts-0   1/1     Running   0          22s
redis-sts-1   1/1     Running   0          3s

注意NAME列,名称是sts的name-序号,这里序号越小则说明创建的越早从AGE列也可以看出来,这就解决了有状态应用中的启动顺序问题,比如可以让redis-sts-0作为redis的主节点,redis-sts-1作为从节点,但POD之间如何知道彼此的关系呢?也比较简单,因为NAME使用的其实就是容器的hostname,如下:

dongyunqi@mongodaddy:~/k8s$ kubectl get pod -l app=redis-sts
NAME          READY   STATUS    RESTARTS   AGE
redis-sts-0   1/1     Running   0          15m
redis-sts-1   1/1     Running   0          15m
dongyunqi@mongodaddy:~/k8s$ kubectl exec -it redis-sts-0 -- hostname
redis-sts-0
dongyunqi@mongodaddy:~/k8s$ kubectl exec -it redis-sts-1 -- hostname
redis-sts-1

怎么让POD有固定的网络标识,即k8s环境中的域名呢?这就需要用到service 的内容,利用其为POD生成固定的网络标识,定义yaml如下:

apiVersion: v1
kind: Service
metadata:
  name: redis-svc

spec:
  selector:
    app: redis-sts

  ports:
  - port: 6379
    protocol: TCP
    targetPort: 6379

注意这里的name: redis-svc要和sts中的serviceName对应,这样service就知道POD是sts的pod,就会为其生成固定的网络标识了,应用后describe查看:

dongyunqi@mongodaddy:~/k8s$ kubectl get service
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP    11d
redis-svc    ClusterIP   10.102.97.104   <none>        6379/TCP   8s
dongyunqi@mongodaddy:~/k8s$ kubectl describe service redis-svc
Name:              redis-svc
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=redis-sts
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.102.97.104
IPs:               10.102.97.104
Port:              <unset>  6379/TCP
TargetPort:        6379/TCP
Endpoints:         10.10.4.5:6379,10.10.4.6:6379
Session Affinity:  None
Events:            <none>

和普通的service类似,也找到了后端的两个POD10.10.4.5:6379,10.10.4.6:6379,但POD的域名就不再是IP 地址. 名字空间,而是Pod 名. 服务名. 名字空间.svc.cluster.local,比如pod 0的域名就是redis-sts-0.redis-svc.default.svc.cluster.local,也可以简写为Pod 名.服务名,如下测试:

dongyunqi@mongodaddy:~/k8s$ kubectl exec redis-sts-0 -it -- ping redis-sts-0.redis-svc
PING redis-sts-0.redis-svc (10.10.4.5): 56 data bytes
64 bytes from 10.10.4.5: seq=0 ttl=64 time=0.141 ms
64 bytes from 10.10.4.5: seq=1 ttl=64 time=0.043 ms
64 bytes from 10.10.4.5: seq=2 ttl=64 time=0.043 ms
64 bytes from 10.10.4.5: seq=3 ttl=64 time=0.050 ms
^C
--- redis-sts-0.redis-svc ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.043/0.069/0.141 ms
dongyunqi@mongodaddy:~/k8s$ kubectl exec redis-sts-0 -it -- ping redis-sts-0.redis-svc.default.svc.cluster.local
PING redis-sts-0.redis-svc.default.svc.cluster.local (10.10.4.5): 56 data bytes
64 bytes from 10.10.4.5: seq=0 ttl=64 time=0.029 ms
64 bytes from 10.10.4.5: seq=1 ttl=64 time=0.126 ms
^C
--- redis-sts-0.redis-svc.default.svc.cluster.local ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.029/0.077/0.126 ms

这里我们仅仅是使用Service为POD生成固定的网络标识,但是并不需要其负载均衡的功能,因此不需要额外为service生成IP地址,以减少不必须的开销,此时需要配置clusterIP: None

然后,我们来看下service和sts之间的依赖关系,如下图:

在这里插入图片描述

接下来还有一个很重要的有状态应用的问题需要解决,那就是数据持久化,也一起来看下,同样也是使用persistent volume,本文以NFS 为例来说明。sts为了强调和持久化存储的一对一绑定关系,增加了volumeClaimTemplates属性来定义内嵌的PVC,yaml如下:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-pv-sts

spec:
  serviceName: redis-pv-svc

  volumeClaimTemplates:
  - metadata:
      name: redis-100m-pvc
    spec:
      storageClassName: nfs-client
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 100Mi

  replicas: 2
  selector:
    matchLabels:
      app: redis-pv-sts

  template:
    metadata:
      labels:
        app: redis-pv-sts
    spec:
      containers:
      - image: redis:5-alpine
        name: redis
        ports:
        - containerPort: 6379

        volumeMounts:
        - name: redis-100m-pvc
          mountPath: /data

注意这里mountPath: /data就是redis的rdb,aof 数据文件存储目录。apply后查看如下:

dongyunqi@mongodaddy:~/k8s$ kubectl get sts
NAME           READY   AGE
redis-pv-sts   2/2     13s
redis-sts      2/2     73m
dongyunqi@mongodaddy:~/k8s$ kubectl get pod -l app=redis-pv-sts
NAME             READY   STATUS    RESTARTS   AGE
redis-pv-sts-0   1/1     Running   0          45s
redis-pv-sts-1   1/1     Running   0          39s

在nfs server目录会自动创建持久化目录来存储redis的数据,如下:

dongyunqi@mongodaddy:/tmp/nfs$ ll | grep '100'
drwxrwxrwx  2       999 root       4096  1月 28 12:56 default-redis-100m-pvc-redis-pv-sts-0-pvc-de19a2a3-4b4e-400a-be87-95fd09ebb0e9/
drwxrwxrwx  2       999 root       4096  1月 28 12:56 default-redis-100m-pvc-redis-pv-sts-1-pvc-98dd5b76-904e-42b7-83ab-3a797796b57f/

PVC如下:

dongyunqi@mongodaddy:/tmp/nfs$ kubectl get pvc | egrep '100|CAPACITY'
NAME                            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
redis-100m-pvc-redis-pv-sts-0   Bound    pvc-de19a2a3-4b4e-400a-be87-95fd09ebb0e9   100Mi      RWX            nfs-client     17m
redis-100m-pvc-redis-pv-sts-1   Bound    pvc-98dd5b76-904e-42b7-83ab-3a797796b57f   100Mi      RWX            nfs-client     17m

接下来测试下数据持久化功能,首先,模拟数据写入:

dongyunqi@mongodaddy:/tmp/nfs$ kubectl exec -it redis-pv-sts-0 -- redis-cli
127.0.0.1:6379> set name jack
OK
127.0.0.1:6379> get name
"jack"
127.0.0.1:6379> 

然后模拟pod 0意外退出,如下:

dongyunqi@mongodaddy:/tmp/nfs$ kubectl get pod
NAME             READY   STATUS    RESTARTS   AGE
...
redis-pv-sts-0   1/1     Running   0          20m
redis-pv-sts-1   1/1     Running   0          20m
dongyunqi@mongodaddy:/tmp/nfs$ kubectl delete pod redis-pv-sts-0
pod "redis-pv-sts-0" deleted
dongyunqi@mongodaddy:/tmp/nfs$ kubectl get pod | grep 'redis-pv-sts'
redis-pv-sts-0   1/1     Running   0          34s
redis-pv-sts-1   1/1     Running   0          21m

可以看到pod 0很快就重新创建出来了,再进入看下数据是否还在:

dongyunqi@mongodaddy:/tmp/nfs$ kubectl exec -it redis-pv-sts-0 -- redis-cli
127.0.0.1:6379> get name
"jack"

成功!

写在后面

小结

本文一起看了如何通过k8s定义的StatefulSet对象来解决有状态应用的部署问题,并重点分析了数据持久化,启动顺序,依赖关系,网络标识问题。希望本文能够帮助到你。

参考文章列表

k8s之挂载NFS到POD中 。

k8s之Service 。

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

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

相关文章

自动写代码的AI工具,已经支持 VsCode 插件安装使用

自动写代码的AI工具&#xff0c;已经支持 VsCode 插件安装使用&#xff0c;它的功能并不是「代码补全」&#xff0c;而是「代码生成」。 之前有个比较火的 GitHub Copilot&#xff0c;但是这是商业产品&#xff0c;并且没有开源&#xff0c;现在又被告了。 GitHub Copilot 面…

SQLSERVER 事务日志的 LSN 到底是什么?

一&#xff1a;背景 1. 讲故事 大家都知道数据库应用程序 它天生需要围绕着数据文件打转&#xff0c;诸如包含数据的 .mdf&#xff0c;事务日志的 .ldf&#xff0c;很多时候深入了解这两类文件的合成原理&#xff0c;差不多对数据库就能理解一半了&#xff0c;关于 .mdf 的合…

代码随想录--二叉树章节总结 Part II

代码随想录–二叉树章节总结 Part II 1.Leetcode222 求完全二叉树结点的个数 给你一棵 完全二叉树 的根节点 root &#xff0c;求出该树的节点个数。 完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达…

Python机器学习:特征变换

&#x1f315; 特征变换 特征变换主要就是针对一个特征&#xff0c;使用合适的方法&#xff0c;对数据的分布、尺度等进行变换&#xff0c;以满足建模时对数据的需求。 特征变换可分为数据的数据的无量纲化处理和数据特征变换。 &#x1f317; 数据的无量纲化处理 常用处理…

22.0:Codejock Suite Pro for ActiveX COM:Crack

从 Visual Basic 5.0 和 6.0 开始一直到当前版本的 Visual Studio 的大多数 ActiveX 容器。与 Visual Studio 无缝集成并包含我们所有 ActiveX COM 产品的评估版本。评估版不提供 OCX 文件的 Unicode 版本。 创建包含一整套高度可定制的用户界面组件的专业应用程序&#xff0c;…

Flink-FinkSQL基本操作(Table API、动态表、事件窗口、分组聚合开窗查询、联结查询)

11 Table API和SQL 11.1 快速上手 引入TableAPI的依赖 桥接器 <dependency><groupId>org.apache.flink</groupId> <artifactId>flink-table-api-java-bridge_${scala.binary.version}</artifactId><version>${flink.version}</vers…

12、常用插件

文章目录12、常用插件推荐1&#xff1a;Alibaba Java Coding Guidelines推荐2&#xff1a;jclasslib bytecode viewer推荐3&#xff1a;Translation推荐4&#xff1a;GenerateAllSetter推荐5&#xff1a;Rainbow Brackets推荐6&#xff1a;CodeGlance Pro推荐7&#xff1a;Stat…

7.bWAPP -- INSECURE DIRECT OBJECT REFERENCES

7.bWAPP – INSECURE DIRECT OBJECT REFERENCES 0x01、Insecure DOR (Change Secret) 同 XSS - Stored (Change Secret) Low 仔细观察页面, 发现隐藏一个input标签, 作用是输入用户名, 并且配合提交的修改密码, 完成修改用户密码的操作: 这里就可以利用该用户名input标签达…

如何带好一个团队?团队管理的要点有哪些?

想带好一个团队并不是这么容易&#xff0c;尤其是对于新晋升管理者来说更是难上加难。团队管理可以大大提高工作效率。那么&#xff0c;团队管理的要点是什么呢&#xff1f; 1、远景和目标 成员们先要有一个共同的目标&#xff0c;在此基础上还必须要有一个好的愿景&#xff0…

即时通讯系列---如何下手做技术方案设计

1. 引出主题 IM整体涉及的内容比较多, 做技术方案设计需要慎重, 可以先从功能列表以及核心case逐步的总结出技术方案 本文结构: 1. 查看功能列表 2. 核心case分析 3. 总结技术方案设计 2. 如何做技术方案设计 1. 查看功能列表 功能清单 一级分类 二级分类 三级分类…

TCP/UDP网络编程

目录 一、常见的客户端服务端模型 二、Socket套接字 1、概念 2、分类 a、流套接字 b、数据报套接字 c、原始套接字 三、UDP数据报套接字编程 四、TCP数据报套接字编程 一、常见的客户端服务端模型 客户端&#xff1a;用户使用的程序。 服务端&#xff1a;给用户提…

miracl编译及使用

文章目录Windows平台编译网址 https://miracl.com/https://github.com/miracl/MIRACL Windows平台编译 源码目录下新建文件夹ms32或ms64&#xff0c;把/lib/ms32doit.bat或ms64doit.bat分别拷进去。 把源码include和source目录所有文件拷贝进要编译的ms32或ms64&#xff0c…

【高阶数据结构】海量数据如何处理? (位图 布隆过滤器)

&#x1f308;欢迎来到高阶数据结构专栏~~位图 & 布隆过滤器 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff0…

模拟实现list / list迭代器

前言&#xff1a;学习C的STL&#xff0c;我们不仅仅要求自己能够熟练地使用各种接口&#xff0c;我们还必须要求自己了解一下其底层的实现方法&#xff0c;这样可以帮助我们写出比较高效的代码程序&#xff01; ⭐在本篇文章中&#xff0c;list的迭代器是重点&#xff0c;它不…

WSL2配置网络代理

注意&#xff1a;本文参考自文章&#xff1a;WSL2配置代理&#xff0c;是对原文的补充&#xff0c;使其适用于河对岸云服务代理。 1 开启Windows代理 1.1 开启代理软件的局域网访问权限 请注意&#xff1a;本文的WSL2代理配置&#xff0c;需要Windows的代理软件已经能够正常…

HTTPS详解及HTTPS实验

目录 HTTPS 一&#xff0c;https在参考模型中的位置 二&#xff0c;什么是HTTPS 三&#xff0c;什么是SSL 1&#xff0c;SSL 协议分为两层&#xff1a; 2&#xff0c;SSL 协议提供的服务&#xff1a; 四&#xff0c;HTTPS的加密方式 1&#xff0c;常见的加密算法 2&#xff0c;…

mysql知识点

目录 1.mysql聚合函数&#xff1a; 2.having&#xff08;用来过滤数据&#xff09;&#xff1a; HAVING 不能单独使用&#xff0c;必须要跟 GROUP BY 一起使用 WHERE 与 HAVING 的对比 3.升序和降序 4.等于 5.实战demo&#xff1a; 1.mysql聚合函数&#xff1a; 常用的聚…

codeforces签到题之div3

前言 第一次&#xff43;&#xff4f;&#xff44;&#xff45;&#xff46;&#xff4f;&#xff52;&#xff43;&#xff45;&#xff53;&#xff0c;发现几个问题&#xff1a; 1,不知道选&#xff4c;&#xff41;&#xff4e;&#xff47;&#xff55;&#xff41;&…

17正交距阵和Gram-Schmidt正交化

标准正交向量与正交矩阵 上一节介绍过的正交向量&#xff0c;通过一个式子进行回顾&#xff0c;设q是标准正交向量组中的任意向量&#xff0c;则 这很好地表现了标准正交向量组内各向量的性质&#xff1a; 不同向量之间相互垂直&#xff08;正交&#xff09;&#xff0c;向量…

Ribbon 负载均衡

介绍Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。Ribbon是Netflix发布的开源项目&#xff0c;主要功能是提供客户端的软件负载均衡算法和服务调用。Ribbon客户端组件提供一系列完善的配置项如连接超时&#xff0c;重试等。简单的说&#xff0c;就…