跨集群流量调度实现 Kubernetes 集群金丝雀升级

有了多集群服务和跨集群的流量调度之后,使用 Kubernetes 的方式会发生很大的变化。流量的管理不再限制单一集群内,而是横向跨越了多个集群。最重要的是这一切“静悄悄地”发生,对应用来说毫无感知。

就拿 Kubernetes 版本升级来说吧。记得曾经经历过集群的原地升级:团队的几个人经过多次、多个环境的演练,还要在凌晨的时候进行生产环境的升级。幸好最后是有惊无险,整个过程的体验就像是下图一样:为飞行中的飞机换引擎。

8aaa2f35120bd8473ec10e8abf733239.png
图片来自网络

解决了跨集群的流量调度之后,一切就会变得简单:只需重新建个集群,慢慢将应用迁移到新的集群,让乘客来个“空中转机”。

方案

与之前所做的示例类似,整个方案的核心仍然是跨集群的服务调用:服务可以像使用本地 Service 一样使用多集群 Service。

67c57988438e5704c04ef46f5bd49a6f.gif

Kubernetes 集群金丝雀升级

升级过程中,创建新版本的 Kubernetes 集群,其他的中间件复用现有的,这样少了数据同步等问题。剩下的便是,调整 CD的流程将服务“同时部署到新的集群”。然后再通过 全局流量策略 慢慢放少部分流量到新的集群中进行测试,边测试边调整流量。两个集群的服务也可保持一段时间观察稳定性,然后再慢慢减少原集群的实例直至所有实例下线。

接下来,我们使用进行下示例演示。

演示

环境准备

如上面的图展示的那样,我们先创建两个集群:control-plane1-23 和 1-25。集群 1-23 就是我们现有的集群,1-25 就是最新版本的集群。

集群对外访问地址api-server 对外端口LB 对外端口描述
control-planeHOST_IP(192.168.1.110)6444N/A控制平面集群
1-23HOST_IP(192.168.1.110)644581应用集群
1-25HOST_IP(192.168.1.110)644682应用集群

环境搭建

获取主机 IP 地址备用,192.168.1.110 是我本机的地址。

export HOST_IP=192.168.1.110

搭建集群

使用 k3d 来创建这 3 个 集群。

API_PORT=6444 #6445 6446
PORT=80 #81 82
for CLUSTER_NAME in control-plane 1-23 1-25
dok3d cluster create ${CLUSTER_NAME} \--image docker.io/rancher/k3s:v1.23.8-k3s2 \--api-port "${HOST_IP}:${API_PORT}" \--port "${API_PORT}:6443@server:0" \--port "${PORT}:80@server:0" \--servers-memory 4g \--k3s-arg "--disable=traefik@server:0" \--timeout 120s \--wait((API_PORT=API_PORT+1))((PORT=PORT+1))
done

安装 FSM

在 3 个集群中安装 FSM。

helm repo update
export FSM_NAMESPACE=flomesh
exportFSM_VERSION=0.2.0-alpha.9
for CLUSTER_NAME in control-plane 1-23 1-25
do kubectx k3d-${CLUSTER_NAME}sleep 1helm install --namespace ${FSM_NAMESPACE} --create-namespace --version=${FSM_VERSION} --set fsm.logLevel=5 fsm fsm/fsmsleep 1kubectl wait --for=condition=ready pod --all -n $FSM_NAMESPACE --timeout=120s
done

加入集群组

将集群 1-23 和 1-25 纳入集群 control-plane 的管理。不管是新集群还是旧集群,如果要进行跨集群的服务调用,都是要加入集群组的。

export HOST_IP=192.168.1.110
kubectx k3d-control-plane
sleep 1
PORT=81
for CLUSTER_NAME in 1-23 1-25
dokubectl apply -f - <<EOF
apiVersion: flomesh.io/v1alpha1
kind: Cluster
metadata:name: ${CLUSTER_NAME}
spec:gatewayHost: ${HOST_IP}gatewayPort: ${PORT}kubeconfig: |+
`k3d kubeconfig get ${CLUSTER_NAME} | sed 's|^|    |g' | sed "s|0.0.0.0|$HOST_IP|g"`
EOF
((PORT=PORT+1))
done

安装服务网格

下载 osm CLI

system=$(uname -s | tr [:upper:] [:lower:])
arch=$(dpkg --print-architecture)
release=v1.3.0-beta.1
curl -L https://github.com/flomesh-io/osm-edge/releases/download/$release/osm-edge-$release-$system-$arch.tar.gz | tar -vxzf -
./${system}-${arch}/osm version
cp ./${system}-${arch}/osm /usr/local/bin/

将服务网格 osm-edge 安装到集群 1-23 和 1-25。控制平面不处理应用流量,无需安装。

export OSM_NAMESPACE=osm-system
export OSM_MESH_NAME=osm
for CLUSTER_NAME in 1-23 1-25
dokubectx k3d-${CLUSTER_NAME}DNS_SVC_IP="$(kubectl get svc -n kube-system -l k8s-app=kube-dns -o jsonpath='{.items[0].spec.clusterIP}')"
osm install \--mesh-name "$OSM_MESH_NAME" \--osm-namespace "$OSM_NAMESPACE" \--set=osm.certificateProvider.kind=tresor \--set=osm.image.pullPolicy=Always \--set=osm.sidecarLogLevel=error \--set=osm.controllerLogLevel=warn \--timeout=900s \--set=osm.localDNSProxy.enable=true \--set=osm.localDNSProxy.primaryUpstreamDNSServerIPAddr="${DNS_SVC_IP}"
done

部署实例应用

在集群 1-23 的 httpbin 命名空间(由网格管理,会注入 sidecar)下,部署 httpbin 应用。这里的 httpbin 应用由 Pipy[1] 实现,会返回当前的集群名,并提示被网格管理。

NAMESPACE=httpbin
CLUSTER_NAME="1-23"kubectx k3d-${CLUSTER_NAME}
kubectl create namespace ${NAMESPACE}
osm namespace add ${NAMESPACE}
kubectl apply -n ${NAMESPACE} -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:name: httpbinlabels:app: pipy
spec:replicas: 1selector:matchLabels:app: pipytemplate:metadata:labels:app: pipyspec:containers:- name: pipyimage: flomesh/pipy:latestports:- containerPort: 8080command:- pipy- -e- |pipy().listen(8080).serveHTTP(new Message('Hi, I am from ${CLUSTER_NAME} and controlled by mesh!\n'))
---
apiVersion: v1
kind: Service
metadata:name: httpbin
spec:ports:- port: 8080targetPort: 8080protocol: TCPselector:app: pipy
EOFsleep 3
kubectl wait --for=condition=ready pod -n ${NAMESPACE} --all --timeout=60s

在命名空间 curl 下部署 curl 应用,这个命名空间也是被网格管理的,注入的 sidecar 会完全流量的跨集群调度。

export NAMESPACE=curl
kubectx k3d-1-23
kubectl create namespace ${NAMESPACE}
osm namespace add ${NAMESPACE}
kubectl apply -n ${NAMESPACE} -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:name: curl
---
apiVersion: v1
kind: Service
metadata:name: curllabels:app: curlservice: curl
spec:ports:- name: httpport: 80selector:app: curl
---
apiVersion: apps/v1
kind: Deployment
metadata:name: curl
spec:replicas: 1selector:matchLabels:app: curltemplate:metadata:labels:app: curlspec:serviceAccountName: curlcontainers:- image: curlimages/curlimagePullPolicy: IfNotPresentname: curlcommand: ["sleep", "365d"]
EOFsleep 3
kubectl wait --for=condition=ready pod -n ${NAMESPACE} --all --timeout=60s

测试

在集群 1-23 中的 curl 向 httpbin 发送请求。

kubectx k3d-1-23
curl_client="$(kubectl get pod -n curl -l app=curl -o jsonpath='{.items[0].metadata.name}')"kubectl exec "${curl_client}" -n curl -c curl -- curl -s http://httpbin.httpbin:8080/

看到下面的输出,说明服务正常。

Hi, I am from 1-23 and controlled by mesh!

导出服务

服务的导出就是向集群组注册服务,执行下面的命令将集群 1-23 中的服务 httpbin 注册到集群组。注意,该命令是在集群 1-23 中执行的。

export NAMESPACE_MESH=httpbin
CLUSTER_NAME="1-23"
kubectx k3d-${CLUSTER_NAME}
kubectl apply -f - <<EOF
apiVersion: flomesh.io/v1alpha1
kind: ServiceExport
metadata:namespace: ${NAMESPACE_MESH}name: httpbin
spec:serviceAccountName: "*"rules:- portNumber: 8080path: "/${CLUSTER_NAME}/httpbin-mesh"pathType: Prefix
EOF
sleep 1

此时,我们的系统如下图所示。

4181e4bdc31d82bddf4fad601946fcf3.jpeg
集群升级.002

升级迁移

新集群中部署应用

有了新版本的集群之后,我们慢慢向新集群迁移服务。在集群 1-25 中部署 httpbin 服务。

NAMESPACE=httpbin
CLUSTER_NAME="1-25"kubectx k3d-${CLUSTER_NAME}
kubectl create namespace ${NAMESPACE}
osm namespace add ${NAMESPACE}
kubectl apply -n ${NAMESPACE} -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:name: httpbinlabels:app: pipy
spec:replicas: 1selector:matchLabels:app: pipytemplate:metadata:labels:app: pipyspec:containers:- name: pipyimage: flomesh/pipy:latestports:- containerPort: 8080command:- pipy- -e- |pipy().listen(8080).serveHTTP(new Message('Hi, I am from ${CLUSTER_NAME} and controlled by mesh!\n'))
---
apiVersion: v1
kind: Service
metadata:name: httpbin
spec:ports:- port: 8080targetPort: 8080protocol: TCPselector:app: pipy
---
apiVersion: v1
kind: Service
metadata:name: httpbin-${CLUSTER_NAME}
spec:ports:- port: 8080targetPort: 8080protocol: TCPselector:app: pipy
EOFsleep 3
kubectl wait --for=condition=ready pod -n ${NAMESPACE} --all --timeout=60s

导出服务

向集群组注册集群 1-25 的服务 httpbin

export NAMESPACE_MESH=httpbin
CLUSTER_NAME="1-25"
kubectx k3d-${CLUSTER_NAME}
kubectl apply -f - <<EOF
apiVersion: flomesh.io/v1alpha1
kind: ServiceExport
metadata:namespace: ${NAMESPACE_MESH}name: httpbin
spec:serviceAccountName: "*"rules:- portNumber: 8080path: "/${CLUSTER_NAME}/httpbin-mesh"pathType: Prefix
EOF
sleep 1

回到集群 1-23,查看 ServiceImports httpbin,可以看到已经发现了集群 1-25 注册的服务。

kubectl get serviceimports httpbin -n httpbin -o jsonpath='{.spec}' | jq
{"ports": [{"endpoints": [{"clusterKey": "default/default/default/1-25","target": {"host": "192.168.1.110","ip": "192.168.1.110","path": "/1-25/httpbin-mesh","port": 82}}],"port": 8080,"protocol": "TCP"}],"serviceAccountName": "*","type": "ClusterSetIP"
}

但此时在 curl发送请求,并不会收到集群 1-25 中的响应。还记得 上篇 中提到过,默认的全局流量策略是 Locality,因此集群外的节点并不会参与请求的处理。

Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!

我们创建一个 ActiveActive 的全局流量策略。注意,这里设置 targets 的时候我们加上了代表权重的字段 weight 将其设置为 10,表示将 1/11 的流量导入集群 1-25 中,记住本集群的权重总是 100

kubectx k3d-1-23
kubectl apply -n httpbin -f  - <<EOF
apiVersion: flomesh.io/v1alpha1
kind: GlobalTrafficPolicy
metadata:name: httpbin
spec:lbType: ActiveActivetargets:- clusterKey: default/default/default/1-25weight: 10
EOF

这次我们请求 20 次,结果也正如我们所期望的,只有 1-2 次请求进入集群 1-25

for i in {1..20}; do kubectl exec "${curl_client}" -n curl -c curl -- curl -s http://httpbin.httpbin:8080/ ; done
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-25 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-25 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!

我们将集群 1-25 的权重设置为 900,因此会有 90% 的流量进入集群 1-25

kubectx k3d-1-23
kubectl apply -n httpbin -f  - <<EOF
apiVersion: flomesh.io/v1alpha1
kind: GlobalTrafficPolicy
metadata:name: httpbin
spec:lbType: ActiveActivetargets:- clusterKey: default/default/default/1-25weight: 900
EOF

然后请求 10 次,会看到 9 次的请求都进入到集群 1-25,也就是 90% 的流量分流到了其他集群。

for i in {1..10}; do kubectl exec "${curl_client}" -n curl -c curl -- curl -s http://httpbin.httpbin:8080/ ; done
Hi, I am from 1-25 and controlled by mesh!
Hi, I am from 1-23 and controlled by mesh!
Hi, I am from 1-25 and controlled by mesh!
Hi, I am from 1-25 and controlled by mesh!
Hi, I am from 1-25 and controlled by mesh!
Hi, I am from 1-25 and controlled by mesh!
Hi, I am from 1-25 and controlled by mesh!
Hi, I am from 1-25 and controlled by mesh!
Hi, I am from 1-25 and controlled by mesh!
Hi, I am from 1-25 and controlled by mesh!

接着就是停止集群 1-23 中的实例,使所有流量都分流到外集群。

kubectl scale deploy httpbin -n httpbin --replicas 0

最后的工作就是慢慢得将 curl 服务也迁移到新的集群中,进而是所有的服务都迁移完成之后,下线旧的集群。

总结

自维护的 Kubernetes 集群升级不是一件容易的事情,原地升级风险高,尤其是升级控制面。不管是蓝绿还是金丝雀升级,都面临着流量跨集群的问题:流量除了从入口进入还会有其他的途径,比如消息系统,定时任务等等。

解决了流量的跨集群调度问题后,这些问题都迎刃而解。剩下的问题就是如何让迁移做到自动化、可控的迁移了。

引用链接

[1] Pipy: https://flomesh.io/pipy

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

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

相关文章

usr/bin/expect方式免密码登录和发送文件脚本

2019独角兽企业重金招聘Python工程师标准>>> ssh 登录 #!/usr/bin/expect set timeout 20 if { [llength $argv] < 3} { puts "Usage:" puts "remote_host password cmd" exit 1 } set remote_host [lindex $argv 0] set passwor…

8-[多线程] 进程池线程池

1、为甚需要进程池&#xff0c;线程池 介绍官网&#xff1a;https://docs.python.org/dev/library/concurrent.futures.htmlconcurrent.futures模块提供了高度封装的异步调用接口 ThreadPoolExecutor&#xff1a;线程池&#xff0c;提供异步调用 ProcessPoolExecutor: 进程池&a…

python 图像识别pytesseract快速设置

一、安装Tesseract 以window安装为例&#xff0c;参考&#xff1a;https://segmentfault.com/a/1190000014086067 note&#xff1a; 使用虚拟环境需要&#xff1a; 在 python 环境&#xff08;或虚拟环境&#xff09; \Lib\site-packages\pytesseract 目录下找到 pytessera…

香港连续25年被评为全球最自由经济体

中新社香港1月25日电 美国智库传统基金会25日在华盛顿发表2019年《经济自由度指数》报告&#xff0c;香港今年再次成为唯一一个总分超过90分的经济体&#xff0c;已连续25年被评价为全球最自由经济体。 报告显示&#xff0c;香港今年的总分为90.2分&#xff08;100分为满分&…

mac 下安装jenkins

2019独角兽企业重金招聘Python工程师标准>>> 平台搭建 Jenkins安装和启动 官网&#xff1a;https://jenkins.io/index.html 下载&#xff1a;http://mirrors.jenkins-ci.org/war/latest/jenkins.war 安装&#xff1a; 依赖于Java环境&#xff0c;首先安装和配置Java…

safari 获取视频流_如何在Safari中将RSS feed和社交媒体合并为一个流

safari 获取视频流Safari allows you to subscribe to RSS feeds and add your social media accounts so you can view them right in the browser, in one universal feed, without the need of any add-on applications or extensions. Safari允许您订阅RSS feed并添加您的社…

pytesseract:opencv预处理图片

一、目的 原始图片用pytesseract识别文字&#xff0c;精准度往往没达到预期。使用opencv处理后&#xff0c;提高识别精准度。处理方法有 a.图片转成白底黑字。 b.截取图片某固定区域。这个很重要&#xff0c;因为图片包含图标或其他形状图形&#xff0c;辨识导致错乱的。 二…

编译安装Centos7.2+Apache2.4.25+PHP7.2.10+Mysql5.6.16

一、编译部署Apache2.4.251、环境准备#设置或停止防火墙&#xff1a; [rootlocalhost ~]# systemctl stop firewalld.service [rootlocalhost ~]# systemctl disable firewalld.service#关闭selinux&#xff1a; 临时关闭&#xff1a; [rootlocalhost ~]# setenforce 0永久关闭…

SDNU 1217 CD收藏——并查集

Description lmh平常爱听歌&#xff0c;所以买了很多的CD来收藏&#xff0c;但是因为平常整理不当&#xff0c;所以忘记了这些CD的歌手是谁。现在他想知道他到底收藏了多少位歌手的专辑&#xff0c;于是他想了一个办法&#xff0c;同时拿出两个CD来听&#xff0c;可以分辨出来是…

国际知名计算机视觉和机器学习软件开源平台OpenCV正式支持龙架构

前言介绍近期&#xff0c;OpenCV开源社区正式合入了对龙架构&#xff08;LoongArch™&#xff09;支持的代码&#xff0c;基于龙架构自主指令系统&#xff0c;优化后的OpenCV性能显著提升。OpenCV是一款跨平台的计算机视觉和机器学习软件平台&#xff0c;在计算机视觉领域广泛使…

优化器--牛顿法总结

---这里记录下一些关于牛顿法来作为优化器的个人笔记 &#xff1a;&#xff09; 关于牛顿法&#xff0c;先不说其中的概念&#xff0c;来简单看一个例子&#xff1f; 不用计算器&#xff0c;如何手动开一个值的平方根&#xff0c;比如计算{sqrt(a) | a4 } &#xff1f; 不用程序…

在命令提示符输出c语言代码_您可以在Windows命令提示符中更改输出缓冲区的大小吗?...

在命令提示符输出c语言代码If you are someone who loves using the Windows Command Prompt, you may have found yourself curious as to why the screen output buffer has such a ‘large’ default size. Can you change it to a smaller (or even larger) size? Today’…

django23:BS4/kindeditor上传图片

BS4 Beautiful Soup&#xff0c;Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式。 安装 pip3 install beautifulsoup4 使用 from bs4 import BeautifulSoup#html_doc为网页内容 soup Be…

设计模式——————观察者模式

工厂模式分为简单工厂&#xff0c;工厂和抽象工厂&#xff0c;三种工厂的实现是越来越复杂的。 观察者模式 本质上就是一种订阅/发布的模型&#xff0c;从逻辑上来说就是一对多的依赖关系。 什么意思呢&#xff1f;好比是一群守卫盯着一个囚犯&#xff0c;只要囚犯一有异动&…

SNMP简介

SNMP简介介绍SNMP的定义、目的、版本演进以及受益。 定义简单网络管理协议SNMP&#xff08;Simple Network Management Protocol&#xff09;是广泛应用于TCP/IP网络的网络管理标准协议。SNMP提供了一种通过运行网络管理软件的中心计算机&#xff08;即网络管理工作站&#xff…

详解vue生命周期及每个阶段适合进行的操作

VUE生命周期的四个阶段 create 创建 -------- 创建vue实例并初始化mount 挂载 -------- 把vue实例和视图进行关联update 更新 ------- 监听数据与视图的变化destroy销毁 ------- 销毁实例生命周期 --- 钩子函数 vue为上面的4个大的阶段提供了一个可编程的接口&#xff0c;我们可…

.Net 7 新编译器 ILC 简析

楔子&#xff1a;这个新编译器的全称是ILCompiler。是之前CoreRT项目合并过来的&#xff0c;在.Net 7成熟&#xff0c;并且可以产业化应用。本质&#xff1a;ILC编译器的本质除了构建CLR的所拥有的主要功能&#xff0c;还包含了对LLVM这种意图取代GCC编译器的操作&#xff0c;对…

mac 防止 下载 睡眠_如何暂时防止Mac进入睡眠状态

mac 防止 下载 睡眠Let’s say you start a big download, then go to bed. When you wake up, you realize your Mac went to sleep before finishing its job. Isn’t there some way to stop this? 假设您开始进行大量下载&#xff0c;然后上床睡觉。 当您醒来时&#xff0…

ubuntu安装chrome driver

首先下载Chrome Driver&#xff08;Firefox Driver的安装与该步骤相同&#xff09; 链接&#xff1a; http://chromedriver.storage.googleapis.com/index.html 接下来在控制台&#xff08;terminal&#xff09;上操作一下红色字体的指令&#xff1a; Install Unzipsudo apt-ge…