Kubernetes 的有状态和无状态服务

news/2024/7/4 8:00:39 标签: kubernetes, 容器, 云原生

k8s-LAB

Author:rab


目录

    • 前言
    • 一、无状态服务案例
      • 1.1 yml 案例
      • 1.2 扩容与缩容
        • 1.2.1 扩容
        • 1.2.2 缩容
      • 1.3 暂停与恢复
        • 1.3.1 暂停
        • 1.3.2 恢复
      • 1.4 回滚
    • 二、有状态服务案例
      • 2.1 yml 案例
      • 2.2 扩容与缩容
        • 2.2.1 扩容
        • 2.2.2 缩容
    • 总结


前言

在 Kubernetes(k8s)中,有状态服务和无状态服务是两种不同类型的应用程序部署方式,它们在容器编排和管理方面有一些关键区别。

1、无状态服务(Stateless Services)

  • 无状态服务是指应用程序不依赖于本地状态,并且对于每个请求都能以相同的方式处理。这意味着无状态服务的任何一个实例都可以处理来自客户端的请求,而请求之间没有关联。
  • 无状态服务的典型示例包括 Web 服务器、API 服务、负载均衡器等,这些服务可以水平扩展,即可以通过添加更多的副本来处理更多的请求流量。
  • 无状态服务通常适合使用 Kubernetes 中的 Deployment 进行部署。因为它们的实例可以随意启动和停止,而不会影响应用程序的状态或数据。

2、有状态服务(Stateful Services)

  • 有状态服务是指应用程序依赖于本地状态,通常需要稳定的标识和数据。这意味着每个实例都有唯一的标识,如数据库服务器或消息队列,它们需要在启动、停止或故障转移时保留其数据和状态。
  • 有状态服务的典型示例包括数据库系统(如 MySQL、PostgreSQL)、消息队列(如 RabbitMQ、Kafka)等,这些服务通常需要持久性存储和网络标识的稳定性。
  • Kubernetes 提供 StatefulSet 来部署有状态服务。StatefulSet 具有管理有状态应用程序的能力,为每个 Pod 提供唯一的标识,以及稳定的网络标识,从而支持有状态服务的稳定性。

一、无状态服务案例

1.1 yml 案例

比如我们可以举个 Nginx 负载均衡的例子,那此时这个负载均衡可以归为无状态服务,任何一个 Nginx 实例都可以处理来自客户端的请求。因此我们可以采用 Kubernetes 中的 Deployment 进行部署。

vim Stateless.yml
apiVersion: v1
kind: Namespace
metadata:
  name: myweb
  labels:
    name: ops
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: myweb
  labels:
    app: stateless
spec:
  replicas: 3
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      containers:
      - name: nginx
        image: nginx:1.21.4
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-srv
  namespace: myweb
spec:
  selector:
    app: demo
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30333
  type: NodePort

注意:Service 的 selector 标签选择器的值一定要和 Deployment 的 selector 标签选择器的值保持一致,否则外部 Client 的请求就无法路由到 Pod 资源。

kubectl apply -f Stateless.yml

本地浏览器访问:

http://192.168.56.160:30333/

image-20231025153300073

1.2 扩容与缩容

1.2.1 扩容

扩容的方式有很多,以下是常见的扩容方式。

1、修改 yml 文件方式

vim Stateless.yml    # 只需修改replicas值即可
...
spec:
  replicas: 5
  ...

修改完成后执行扩展(更新)

kubectl apply -f Stateless.yml

2、Shell 命令行方式

  • 法1

    kubectl scale --replicas=5 deploy nginx -n myweb
    
    # 说明:deploy是deployment的缩写,写deployment也是没问题的
    
  • 法2

    kubectl edit deployment nginx -n myweb
    
    # 这会以交互式的方式进入yml配置文件,进去后修改replicas的值后保存退出即可实现扩容
    

说明:与直接修改 yml 文件不同的是,该命令执行完后即可升级,而无需执行 kubectl apply -f Stateless.yml

1.2.2 缩容

与扩容没有任何区别,操作一模一样,所谓的缩容就是当你设置的 replicas 值小于当前 replicas 值时就是缩容的概念。

注意:但要注意的是,我们说动态扩容和缩容不会触发上线(即不会产生新的 replicaset)

1.3 暂停与恢复

注意的是,这个暂停和恢复不是说暂停了我的程序就不对外提供服务了,而是用于当你使用 kubectl set ... 命令来更新时使用。其大概流程就是:当你暂停后,允许你执行多个 kubectl set ... 更新命令,但每条指令执行完后不是立即生效,而是当你恢复 deployment 时你执行的那些 kubectl set ... 才会生效。

1.3.1 暂停

1、暂停服务

kubectl rollout pause deployment nginx -n myweb

2、执行第一条更新指令

kubectl set image deploy nginx nginx=nginx:1.20.0 -n myweb

3、执行第二条更新指令

kubectl set resources deploy nginx -c nginx --limits=cpu=200m,memory=128Mi --requests=cpu=10m,memory=16Mi -n myweb

如下图,以上这两条更新指令都是未生效的,从 nginx 镜像版本没变化就可证明。

image-20231025170727008

1.3.2 恢复

那要如何是我们执行过的 kubectl set ... 指令生效呢?恢复即可。

kubectl rollout resume deploy nginx -n myweb

如下图,恢复后我们在暂停期间执行的 kubectl set ... 指令就生效了。

image-20231025171200713

当然了,如果你想使用 kubectl set 来更新服务,但又不想暂停,你完全可以直接执行 kubectl set 指令即可,执行完后,就会立马更新。

kubectl set image deploy nginx nginx=nginx:1.18.0 -n myweb

image-20231025171428065

1.4 回滚

如果我们以上的一系列更新最终的测试验证出问题了,需要回滚到最初(或更新前)的状态或中间某个版本状态,那此时就需要使用到 K8s 的回滚功能了,具体的操作如下。

1、先查看更新的版本

默认情况下,K8s 只会保留近 10 个的 revision,我们可以在 Deployment 配置文件中使用 revisionHistoryLimit 字段来指定 revision 的保留数量。

kubectl rollout history deploy nginx -n myweb

# 下图中这三个版本编号中,1表示最初版本状态,3表示当前的版本状态

image-20231025172113126

2、再查看每个版本对应的详情(因为上图根本看不出来)

kubectl rollout history deployment nginx --revision=1 -n myweb

# 我们来看看第一个版本详情

image-20231025172640153

3、回滚到我们指定的版本状态

kubectl rollout undo deployment nginx --to-revision=1 -n myweb

image-20231025172836324

4、最后来验证一下是否回滚成功

kubectl get deployment nginx -o wide -n myweb

image-20231025173029086

这个时候我们再来看看历史版本号:

image-20231025173140455

你会发现,历史版本为 1 的编号消失了,为什么呢?因为已经被我们回滚了(此时你就要记住了,如果你又执行了多次更新操作后,又想回到最初的状态的话,只能回到 4 这个版本,因为 4 此时才是我们最初的状态,而 2 并不是)。

二、有状态服务案例

2.1 yml 案例

上面说到,像 MySQL、RabbitMQ 等这类服务实际上就是属于有状态服务,对于这类服务我们一般会要求每个 Pod 具有唯一的标识,以及稳定的网络标识。例如 MySQL 就是一个典型的有状态应用程序,因为每个 MySQL 实例需要唯一的标识,并且通常依赖于稳定的网络标识。

vim Stateful.yml
apiVersion: v1
kind: Namespace
metadata:
  name: myweb-2
  labels:
    name: ops
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: nginx
  namespace: myweb-2
  labels:
    app: stateful
spec:
  serviceName: myweb-2
  replicas: 3
  selector:
    matchLabels:
      app: demo-2
  template:
    metadata:
      labels:
        app: demo-2
    spec:
      containers:
      - name: nginx
        image: nginx:1.21.4
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-srv
  namespace: myweb-2
spec:
  selector:
    app: demo-2
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30334
  type: NodePort
kubectl apply -f Stateful.yml

对于如何查看 deployment 资源,我想你已经会了,那 statefulset 资源如何查看呢?其实都是一样的套路:

kubectl get statefulset -n myweb-2

# 或
kubectl get sts -n myweb-2

image-20231025175454025

本地浏览器访问:

http://192.168.56.160:30334/

image-20231025175657501

2.2 扩容与缩容

2.2.1 扩容
kubectl scale --replicas=5 sts nginx -n myweb-2
2.2.2 缩容
kubectl scale --replicas=2 sts nginx -n myweb-2

说明:暂停、恢复、回滚套路和 deployment 保持一致的,这里就不再重复造轮子了。

总结

  • 无状态服务适用于可以随意扩展并处理请求而不依赖本地状态的应用程序,而有状态服务适用于需要稳定的标识和数据的应用程序。

  • 在 Kubernetes 中,我们可以使用不同的控制器(例如 Deployment 和 StatefulSet)来适应这两种不同类型的服务。

  • 有状态服务通常需要考虑持久性存储和数据备份策略,以确保数据的可靠性和可用性。

说明:以上案例均未配置持久化存储,后面会提到。

—END


http://www.niftyadmin.cn/n/5121388.html

相关文章

高等数学啃书汇总重难点(七)微分方程

同济高数上册的最后一章,总的来说,这篇章内容依旧是偏记忆为主,说难不难说简单不简单: 简单的是题型比较死,基本上就是记公式,不会出现不定积分一般花样繁多的情况;然而也就是背公式并不是想的…

【Overload游戏引擎细节分析】standard材质Shader

提示:Shader属于GPU编程,难写难调试,阅读本文需有一定的OpenGL基础,可以写简单的Shader,不适合不会OpenGL的朋友 一、Blinn-Phong光照模型 Blinn-Phong光照模型,又称为Blinn-phong反射模型(Bli…

程序员心得体会

作为一个程序员,我在学习和工作的过程中积累了许多经验和心得。在这里,我想总结一下我作为程序员的一些心得体会。 首先,作为一个程序员,学习是永无止境的。编程语言和技术在不断发展和更新,我们需要不断学习新的知识…

嵌入式算法——傅里叶变换算法

文章引注 https://mp.weixin.qq.com/s/5VIpNWci9YLY3m4gcYd6-w 摘要 傅里叶变换的核心在于,“任何连续周期信号可以由一组适当的正弦曲线组合而成”,在这个基础上对信号的中特定频率的正弦波进行分解或者重组,基于频率方面分析波形。 1、傅…

进程(2)——进程状态(僵尸,睡眠……)【linux】

进程(2)——进程状态(僵尸,睡眠……)【linux】 一.操作系统的进程状态:1.1 运行态1.2 阻塞态1.3 挂起态 二.linux进程状态2.1 R——运行状态2.2 S——浅度睡眠状态2.3 D——(disk sleep&#xf…

iOS调试技巧——使用Python 自定义LLDB

一、类介绍 在使用Python 自定义LLDB之前,先了解一下LLDB的一些类型 SBTarget 正在被调试的程序SBProcess 和程序关联的具体的进程SBThread 执行的线程SBFrame 和线程关联的一个栈帧SBVariable 变量,寄存器或是一个表达式一般情况下,我们取到SBFrame就可以进行方法调用来打…

Java中ReentrantLock测试线程的安全

使用场景 当需要在多线程环境下保证共享资源的安全访问时,可以使用Java中的ReentrantLock来实现线程安全。ReentrantLock是一个可重入的互斥锁,它提供了与synchronized关键字类似的功能,但更加灵活和扩展性强。 下面是一个使用ReentrantLoc…

使用vue3从零开始手撸一个后台管理架子。代码开源

毒蘑菇 - 管理 毒蘑菇 - 管理 开源地址 https://github.com/wurencaideli/dumogu-admin 线上DEMO https://admin.dumogu.top/ 吐槽地址 https://txc.qq.com/products/613546 包含后端服务,前端。前端采用vue3,vite,element-plus&#xff0…