Kubernetes 实现自动扩容和自愈应用实践

news2025/4/5 16:29:44

Kubernetes 自动扩容和自愈

tags: 实践

文章目录

  • Kubernetes 自动扩容和自愈
    • 1. 背景
    • 2. 准备
    • 3. kind 部署 kubernetes
    • 4.实践
      • 4.1 部署 deployment
      • 4.2 创建 Service
      • 4.3 创建 Ingress
      • 4.4 部署 Ingress-nginx
      • 4.5 K8s 实现自愈
      • 4.6 k8s 实现自动扩容
    • 5. 其他

1. 背景

在生产非 kubernetes 集群中,负载均衡器往往是集群的唯一入口,它在接受访问流量后,一般会将流量通过加权轮训的方式转发到后端集群。负载均衡器一般是直接使用云厂商的产品,有一些团队也会自建高可用的 Nginx 作为集群入口。为了保证伸缩组节点的业务一致性,弹性伸缩组的所有 VM 都使用同一个虚拟机镜像。其次,要在 VM 粒度实现业务自愈,常见的方案是使用 Crontab 定时检查业务进程或者通过守护进程的方式来运行。

传统扩容和自愈的缺点但是,这种架构有一些显而易见的缺陷。最大的问题有两个:

  • 扩容慢;
  • 负载均衡无法感知业务健康情况。

扩容慢主要体现在两方面。首先是 VM 指标会有一定的延迟;其次,扩容的 VM 冷启动时间比较慢,弹性伸缩组需要执行购买 VM、配置镜像、加入伸缩组、启动 VM 等操作。这会让我们失去扩容的最佳时机,并最终影响用户体验。负载均衡无法感知业务健康情况的意思是,VM 是否加入到弹性伸缩组接收外部流量,一般取决于 VM 的健康状态,但 VM 健康并不等于业务健康,这导致在扩缩容的过程中,请求仍然有可能会转发至业务不健康的节点,造成业务短暂中断的问题。

Kubernets 可以自动自愈和自动扩容。接下来我们一起验证。

2. 准备

  • 安装系统 Centos 8.2
  • 初始化 Centos 8.2
  • 安装 Podman
  • 安装 kubectl (kubernetes yum 源)
  • 官方步骤安装 Kind

我的 kind 安装方式

curl -Lo ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.17.0/kind-linux-amd64
chmod +x ./kind
mv ./kind /usr/local/bin/kind

3. kind 部署 kubernetes

  • config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
  kubeadmConfigPatches:
  - |
    kind: InitConfiguration
    nodeRegistration:
      kubeletExtraArgs:
        node-labels: "ingress-ready=true"
  extraPortMappings:
  - containerPort: 80
    hostPort: 80
    protocol: TCP
  - containerPort: 443
    hostPort: 443
    protocol: TCP

创建 K8s 集群:

$ kind create cluster --config config.yaml
enabling experimental podman provider
Creating cluster "kind" ...
 ✓ Ensuring node image (kindest/node:v1.25.3) 🖼
 ✓ Preparing nodes 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
Set kubectl context to "kind-kind"
You can now use your cluster with:

kubectl cluster-info --context kind-kind

Have a nice day! 👋

4.实践

  • Pod 会被 Deployment 工作负载管理起来,例如创建和销毁等;
  • Service 相当于弹性伸缩组的负载均衡器,它能以加权轮训的方式将流量转发到多个 Pod 副本上;
  • Ingress 相当于集群的外网访问入口。

4.1 部署 deployment

kubectl create deployment hello-world-flask --image=lyzhang1999/hello-world-flask:latest --replicas=2 

单纯输出 Manifest 内容:

$ kubectl create deployment hello-world-flask --image lyzhang1999/hello-world-flask:latest --replicas=2 --dry-run=client -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: hello-world-flask
  name: hello-world-flask
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello-world-flask
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: hello-world-flask
    spec:
      containers:
      - image: lyzhang1999/hello-world-flask:latest
        name: hello-world-flask
        resources: {}
status: {}

4.2 创建 Service

kubectl create service clusterip hello-world-flask --tcp=5000:5000

4.3 创建 Ingress

kubectl create ingress hello-world-flask --rule="/=hello-world-flask:5000"

4.4 部署 Ingress-nginx

kubectl create -f https://ghproxy.com/https://raw.githubusercontent.com/lyzhang1999/resource/main/ingress-nginx/ingress-nginx.yaml

4.5 K8s 实现自愈

$ kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
hello-world-flask-56fbff68c8-2xz7w   1/1     Running   0          3m38s
hello-world-flask-56fbff68c8-4f9qz   1/1     Running   0          3m38s

由于之前我们已经通过 Kind 在本地创建了集群,也暴露监听了本地的 80 端口,所以集群的 Ingress 访问入口是 127.0.0.1。有了 Ingress,我们访问 Pod 就不再需要进行端口转发了,我们可以直接访问 127.0.0.1。下面的命令会每隔 1 秒钟发送一次请求,并打印出时间和返回内容:

$ while true; do sleep 1; curl http://127.0.0.1; echo -e '\n'$(date);done
Hello, my first docker images! hello-world-flask-56fbff68c8-4f9qz
202297日 星期三 19时21分03秒 CST
Hello, my first docker images! hello-world-flask-56fbff68c8-2xz7w
202297日 星期三 19时21分04秒 CST

在这里,“Hello, my first docker images” 后面紧接的内容是 Pod 名称。通过返回内容我们会发现,请求被平均分配到了两个 Pod 上,Pod 名称是交替出现的。我们要保留这个命令行窗口,以便继续观察。

接下来,我们模拟其中的一个 Pod 宕机,观察返回内容。打开一个新的命令行窗口,执行下面的命令终止容器内的 Python 进程,这个操作是在模拟进程意外中止导致宕机的情况。

$ kubectl exec -it hello-world-flask-56fbff68c8-2xz7w -- bash -c "killall python3"

另一个终端:

$ while true; do sleep 1; curl http://127.0.0.1; echo -e '\n'$(date);done
Hello, my first docker images! hello-world-flask-56fbff68c8-4f9qz
202297日 星期三 19时27分44秒 CST
Hello, my first docker images! hello-world-flask-56fbff68c8-4f9qz
202297日 星期三 19时27分45秒 CST
Hello, my first docker images! hello-world-flask-56fbff68c8-4f9qz

所有的请求流量都被转发到了没有故障的 Pod,也就是说,故障成功地被转移了!等待几秒钟,继续观察,我们会重新发现 hello-world-flask-56fbff68c8-2xz7w Pod 的返回内容,这说明 Pod 被重启恢复后,重新加入到了负载均衡接收外部流量:

Hello, my first docker images! hello-world-flask-56fbff68c8-2xz7w
202297日 星期三 19时27分52秒 CST
Hello, my first docker images! hello-world-flask-56fbff68c8-4f9qz
202297日 星期三 19时27分53秒 CST
Hello, my first docker images! hello-world-flask-56fbff68c8-2xz7w

然后,我们再次使用 kubectl get pods 查看 Pod:

$ kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
hello-world-flask-56fbff68c8-2xz7w   1/1     Running   1(1m ago)  3m38s
hello-world-flask-56fbff68c8-4f9qz   1/1     Running   0          3m38s

这里要注意看, hello-world-flask-56fbff68c8-2xz7w Pod 的 RESTARTS 值为 1 ,也就是说 K8s 自动帮我们重启了这个 Pod。

我们重新来梳理一下全过程。首先, K8s 感知到了业务 Pod 故障,立刻进行了故障转移并隔离了有故障的 Pod,并将请求转发到了其他健康的 Pod 中。随后重启了有故障的 Pod,最后将重启后的 Pod 加入到了负载均衡并开始接收外部请求。这些过程都是自动化完成的。

4.6 k8s 实现自动扩容

安装 K8s Metric Server

kubectl apply -f https://ghproxy.com/https://raw.githubusercontent.com/lyzhang1999/resource/main/metrics/metrics.yaml

等待 Metric 工作负载就绪

kubectl wait deployment -n kube-system metrics-server --for condition=Available=True --timeout=90s

Metric Server 就绪后,通过 kubectl autoscale 命令来为 Deployment 创建自动扩容策略:

kubectl autoscale deployment hello-world-flask --cpu-percent=50 --min=2 --max=10

其中,–cpu-percent 表示 CPU 使用率阈值,当 CPU 超过 50% 时将进行自动扩容,–min 代表最小的 Pod 副本数,–max 代表最大扩容的副本数。也就是说,自动扩容会根据 CPU 的使用率在 2 个副本和 10 个副本之间进行扩缩容。

最后,要使自动扩容生效,还需要为我们刚才部署的 hello-world-flask Deployment 设置资源配额。你可以通过下面的命令来配置:

kubectl patch deployment hello-world-flask --type='json' -p='[{"op": "add", "path": "/spec/template/spec/containers/0/resources", "value": {"requests": {"memory": "100Mi", "cpu": "100m"}}}]'

现在,Deployment 将会重新创建两个新的 Pod,你可以使用下面的命令筛选出新的 Pod:

$ kubectl get pod --field-selector=status.phase==Running
NAME                                 READY   STATUS    RESTARTS   AGE
hello-world-flask-64dd645c57-4clbp   1/1     Running   0          117s
hello-world-flask-64dd645c57-cc6g6   1/1     Running   0          117s

选择一个 Pod 并使用 kubectl exec 进入到容器内:

$ kubectl exec -it hello-world-flask-64dd645c57-4clbp -- bash
root@hello-world-flask-64dd645c57-4clbp:/app#

接下来,我们模拟业务高峰期场景,使用 ab 命令来创建并发请求:

root@hello-world-flask-64dd645c57-4clbp:/app# ab -c 50 -n 10000 http://127.0.0.1:5000/

在这条压力测试的命令中,-c 代表 50 个并发数,-n 代表一共请求 10000 次,整个过程大概会持续十几秒。接下来,我们打开一个新的命令行窗口,使用下面的命令来持续监控 Pod 的状态:

$ kubectl get pods --watch
NAME                                 READY   STATUS    RESTARTS   AGE
hello-world-flask-64dd645c57-9x869   1/1     Running   0          4m6s
hello-world-flask-64dd645c57-vw8nc   0/1     Pending   0          0s
hello-world-flask-64dd645c57-46b6s   0/1     ContainerCreating   0          0s
hello-world-flask-64dd645c57-vw8nc   1/1     Running             0          18s

这里参数 --watch 表示持续监听 Pod 状态变化。在 ab 压力测试的过程中,会不断创建新的 Pod 副本,这说明 K8s 已经感知到了 Pod 的业务压力,并且正在自动进行横向扩容。

5. 其他

  1. Kubernetes HPA:Vertical Pod Autoscaler 根据 CPU 利用率增加或减少复制控制器、部署、副本集或有状态集中的 pod 数量——缩放是水平的
  2. Kubernetes VPA:Horizo​​ntal Pod Autoscaler 增加和减少容器 CPU 和内存资源配置,以使集群资源分配与实际使用情况保持一致。
  3. Kubernetes CA :Cluster Autoscaler 根据 pod 的资源请求自动添加或删除集群中的节点。

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

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

相关文章

java进阶—List

上节回顾 List 是一个有序的,允许重复的Collection,其下的子类主要有 ArrayList LinkedList,Vector(这个官方不推荐使用) 那么同为list的子类,ArrayList 跟 LinkedList 有什么区别呢? 这里就涉及到了list的底层两种实现方式&…

《计算机体系结构量化研究方法》第2章-存储器层次结构设计 2.1 引言

一、概述 1、存储器层次结构:层次由速度和容量各不相同的存储器组成。 2、存储器层次结构被分为几个级别——离处理器越近,容量越小速度越快。 3、包含性质:大多数情况下,低层级存储器中的数据是上一级存储器中数据的超集。比如…

基于RSA的数字签名设计与实现

信息安全课程的第二个实验,主要是用java、js,前端页面用的html写的。 页面成果展示: 基本公私钥生成 实验环境为win10系统,使用git命令行工具——git bash生成公私钥。生成私钥,密钥长度为1024bit并从私钥中提取公钥 …

如何在 Spring Boot 项目中开启 “热部署“

目录 1. 添加热部署框架支持 2. 设置当前项目 Settings 和新项目 Settings 开启项目自动编译 3. 开启运行中热部署 4. 使用 Debug 启动项目 (社区版 IDEA) 1. 添加热部署框架支持 在 pom.xml 中添加如下框架引用: <dependency><groupId>org.springframework.b…

vue3中常用的三种组件传值方式

比较大型的项目中经常会涉及到多个组件之间进行传值&#xff0c;所以对之前用过的一些传值方法做个笔记&#xff0c;还有就是对不同的情况下需要使用哪一种传值方法更合适的思维进行一个总结 vue3中常用的三种组件传值方式mitt依赖注入pinia总结mitt 因为vue3去掉了全局事件总…

qt实现的pdf阅读器(二)--XpdfReader在linux下的编译

目录 1.简介 2.需求说明 3.编译 3.3. 下载源码 3.2. 移植安装包和依赖库 3.2.1 准备工作 3.3.2 了解 3.3.3 编译并安装zlib 3.3.4 编译并安装libpng 3.3.5 编译并安装lcms 3.3.6 编译并安装freetype 3.3.7 编译xpdf 3.3.8 查看运行编译好的xpdf 1.简介 Xpdf 是一个免…

我以为自己MySQL够牛逼了,直到看到了Alibaba的面试题

前言 众所周知&#xff0c;简历上“了解&#xff1d;听过名字&#xff1b;熟悉&#xff1d;知道是啥&#xff1b;熟练&#xff1d;用过&#xff1b;精通&#xff1d;做过东西”。 相信大家对于MySQL的索引都不陌生&#xff0c;索引(Index)是帮助MySQL高效获取数据的数据结构。…

SpringBoot Disruptor框架遇到的问题

1.消息重复消费问题 问题描述&#xff1a; 项目中启动了多个消费者,测试中发现同一条消息被多次消费。 解决方案&#xff1a; ①幂等方案处理 ②disrutor提供了不同的处理机制&#xff1a; 自定义消费者实现EventHandler接口,他是属于重复消费&#xff0c; 自定义消费者实现W…

SVN培训笔记(下拉项目、同步修改、添加文件、修改文件、删除文件、改名文件等)

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/128417196 红胖子(红模仿)的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软…

【矩阵论】7. 范数理论——非负/正矩阵

7.5 非负/正矩阵 7.5.1 定义 a. 非负/正矩阵定义 一个实矩阵 A(aij)∈RmnA(a_{ij})\in R^{m\times n}A(aij​)∈Rmn 若对每一 iii 和 jjj &#xff0c;aij≥0a_{ij}\ge 0aij​≥0 &#xff0c;则称A是非负矩阵&#xff0c;A≥0A\ge 0A≥0 若对每一 iii 和 jjj &#xff0c;…

简单四则运算语法树可视化

简单四则运算语法树可视化 前几天有一篇博客是关于四则运算和二叉树的&#xff0c;我是把四则运算用二叉树写出来&#xff08;我是用的 JSON 的形式来存储和表达的&#xff09;&#xff0c;并计算最终的结果。最近&#xff0c;也在继续这个方面的东西&#xff0c;不过遇到一些…

uni-app 微信支付-小程序、APP、IOS

小程序 支付 先看官方文档 https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_2.shtml 知晓有那些比不可少的流程&#xff0c;之后后端确定返回的参数值&#xff0c;用于前端支付。参数值必须一一对应&#xff0c;不然支付会失败 uni.requestPayment({timeStamp…

mysql5.7主从复制配置

写在最前面&#xff1a;一入编程深似海&#xff0c;从此对象变路人&#xff08;码农没时间谈恋爱&#xff09;。很长一段时间连写个文章的时间都没有了&#xff0c;学完后端、学前端&#xff0c;前端刚入门又要搞容器化&#xff0c;这真是“一重山外一重关&#xff0c;关关难过…

如何在Angular框架中更好地使用字体?一篇文章解答!

作为前端开发人员&#xff0c;在Angular JS中构建项目时&#xff0c;使用自定义字体可能会很棘手。有时候&#xff0c;如果开发者想要把选择的字体添加到项目中&#xff0c;将不得不把它导入到现有的代码中。 PS&#xff1a;Kendo UI致力于新的开发&#xff0c;来满足不断变化…

信息安全产品认证

文章目录一、引言二、《网络关键设备和网络安全专用产品安全认证证书》2.1 背景2.2 产品目录2.3 认证依据标准2.4 认证机构三、《中国国家信息安全产品认证证书》3.1 背景3.2 产品目录3.3 行业跟进四、《IT产品信息安全认证证书》五、CCC认证5.1背景5.2 中国强制性产品认证体系…

多源传感器组合导航 GNSS 视觉SLAM LiDAR INS 开源项目总结

多源传感器组合导航 GNSS 视觉SLAM LiDAR INS 开源项目总结 本文更改自 吴桐wutong 微信公众号文章。 开源代码总览 名称传感器类型组合类型滤波方法备注RTKLIBG-KFGAMP、rtklibexplorerhttps://www.rtklib.com/GPSTKG-KFhttps://github.com/SGL-UT/GPSTkBNCG-KFppp_wizardK…

【多个IP地址用逗号分割开】vue简单实现,textarea文本域输入多个ip地址用逗号分隔开,根据空格分割

前言 这个功能也是很多地方会用到的。 一般使用的地方是比如需要设置白名单或者黑名单 然后页面上会有一个textarea文本域。 在文本域中输入多个ip地址&#xff0c;输入一个回车换一行。 然后点击保存后&#xff0c;把数据通过逗号隔开的格式传给后端 后端再去拿到每一个ip地址…

电脑重装系统win11如何更改默认下载路径

win11如何更改默认下载路径&#xff1f;当大家平日里面&#xff0c;在使用win11系统的时候&#xff0c;如果觉得某一个下载路径的内存空间已经满了的话&#xff0c;那么就必须要及时更改&#xff0c;下面是小编提 供的更改路径的方法。 工具/原料&#xff1a; 系统版本&#x…

ES集群节点角色更换

背景 如何在一个3节点集群中&#xff0c;将Master/Data角色的节点中的数据分散到其他数据节点中&#xff0c;将该节点角色变更为Master 操作步骤 构建集群 集群角色如下 m-01:master/data d-02:data d-03:data 集群配置文件&#xff1a; Master节点elasticsearch.yml配置文件…

关于Maven中引用的jar的version配置为版本区间自动使用最新的版本,maven是如何判断哪个版本更加新?

背景 在Maven中&#xff0c;a工程引入了个jar包&#xff08;b工程&#xff09;&#xff0c;可以使用区间引入的方式&#xff0c;类似于数学区间的写法&#xff0c;如下 <dependency><groupId>org.example</groupId><artifactId>demo-jar</artifac…