Kubernetes金丝雀发布
华子目录
- Canary金丝雀发布
- 什么是金丝雀发布
- Canary发布方式
- 基于header(http包头)灰度发布
- 基于权重的金丝雀发布
Canary金丝雀发布
什么是金丝雀发布
金丝雀
发布也称为灰度发布
,是一种软件
发布策略
- 主要
目的
是在将新版本
的软件
全面推广到生产环境之前
,先在一小部分用户
或服务器上
进行测试
和验证
,以降低
因新版本
引入重大问题
而对整个系统
造成的影响
- 是一种
Pod
的发布方式
。金丝雀
发布采取先添加
、再删除
的方式,保证Pod
的总量
不低于期望值
。并且在更新部分Pod
后,暂停更新
,当确认新Pod版本
运行正常后再进行其他版本
的Pod的更新
Canary发布方式
三种发布方式
:
- 优先级:
head
大于cookie
大于weight
- 其中
header
和weight
用的最多
基于header(http包头)灰度发布
我们可以看到如果包头
中有stage=gray
的键值对
,就访问新版本
,包头
中没有那个键值对
,就访问旧版本
- 通过
Annotaion
扩展 - 创建灰度
ingress
,配置灰度头部key
以及value
灰度
流量验证完毕后,切换正式ingress
到新版本
- 之前我们在
做升级
时可以通过控制器
做滚动更新
,默认25%
利用header
可以使升级
更为平滑
,通过key
和value
测试新的业务体系
是否有问题
创建2
个deployment
控制器
#发现没有运行的pod
[root@k8s-master service]# kubectl get pods
No resources found in default namespace.#创建一个deployment控制器,控制器中运行一个pod
[root@k8s-master service]# kubectl create deployment deployment --image myapp:v1 --dry-run=client -o yaml > deployment-v1.yml[root@k8s-master service]# vim deployment-v1.yml
[root@k8s-master service]# cat deployment-v1.yml
apiVersion: apps/v1
kind: Deployment #指明这是一个deployment控制器
metadata: #控制器的元数据labels: #控制器的标签app: deployment1 #控制器的标签name: deployment1 #控制器的名字
spec: 控制器的规格replicas: 1 #pod数量selector: #pod选择器matchLabels: #声明的要管理的podapp: myappv1 #标签为app=myappv1的pod会被管理template: #pod的模板metadata: #pod的元数据labels: #pod的标签app: myappv1spec: #pod的规格containers:- image: myapp:v1name: myappv1#在克隆一份
[root@k8s-master service]# cp deployment-v1.yml deployment-v2.yml
[root@k8s-master service]# vim deployment-v2.yml
[root@k8s-master services]# cat deployment-v2.yml
apiVersion: apps/v1
kind: Deployment #指明这个一个deployment控制器
metadata: #控制器的元数据labels: app: deployment2 #控制器的标签name: deployment2 #控制器的名字
spec: #控制器的规格replicas: 1 #pod数量selector: #pod选择器matchLabels: app: myappv2 #声明需要管理的标签template: #pod的模板metadata: #pod的元数据labels: app: myappv2 #pod的标签spec: #pod的规格containers:- image: myapp:v2name: myappv2
[root@k8s-master service]# kubectl apply -f deployment-v1.yml
deployment.apps/deployment1 created
[root@k8s-master service]# kubectl apply -f deployment-v2.yml
deployment.apps/deployment2 created[root@k8s-master service]# kubectl get pods -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
deployment1-5c47495d84-ds4cl 1/1 Running 0 3m20s 10.244.2.15 k8s-node2.org <none> <none> app=myappv1,pod-template-hash=5c47495d84
deployment2-67cc8c4845-bfnvx 1/1 Running 0 6m49s 10.244.2.14 k8s-node2.org <none> <none> app=myappv2,pod-template-hash=67cc8c4845
创建2
个service
微服务
[root@k8s-master service]# kubectl expose deployment deployment1 --port 8080 --target-port 80 --dry-run=client -o yaml >> deployment-v1.yml[root@k8s-master service]# kubectl expose deployment deployment2 --port 8080 --target-port 80 --dry-run=client -o yaml >> deployment-v2.yml
[root@k8s-master service]# vim deployment-v1.yml
[root@k8s-master service]# cat deployment-v1.yml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: deployment1name: deployment1
spec:replicas: 1selector:matchLabels:app: myappv1template:metadata:labels:app: myappv1spec:containers:- image: myapp:v1name: myappv1---
apiVersion: v1
kind: Service #指明这是一个service微服务
metadata: #微服务元数据labels: app: deployment1 #微服务标签 name: deployment1 #微服务的名字
spec: #微服务的规格ports: #是一个端口列表,用于描述service应该监听的端口以及如何将流量转发给pod- port: 8080 #service微服务监听的端口号protocol: TCP #使用的协议,这里是TCPtargetPort: 80 #pod上应用程序监听的端口selector: #标签选择器,用于确定哪些pods应该被这个service管理app: myappv1 #pod标签为app=myappv1的被该service管理
[root@k8s-master service]# vim deployment-v2.yml
[root@k8s-master service]# cat deployment-v2.yml
apiVersion: apps/v1
kind: Deployment
metadata:labels:app: deployment2name: deployment2
spec:replicas: 1selector:matchLabels:app: myappv2template:metadata:labels:app: myappv2spec:containers:- image: myapp:v2name: myappv2---
apiVersion: v1
kind: Service
metadata:labels:app: deployment2name: deployment2
spec:ports:- port: 8080protocol: TCPtargetPort: 80selector:app: myappv2
[root@k8s-master service]# kubectl apply -f deployment-v1.yml
deployment.apps/deployment1 unchanged
service/deployment1 created
[root@k8s-master service]# kubectl apply -f deployment-v2.yml
deployment.apps/deployment2 unchanged
service/deployment2 created
[root@k8s-master service]# kubectl get pods -o wide --show-labels
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES LABELS
deployment1-5c47495d84-ds4cl 1/1 Running 0 15m 10.244.2.15 k8s-node2.org <none> <none> app=myappv1,pod-template-hash=5c47495d84
deployment2-67cc8c4845-bfnvx 1/1 Running 0 18m 10.244.2.14 k8s-node2.org <none> <none> app=myappv2,pod-template-hash=67cc8c4845[root@k8s-master service]# kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
deployment1 ClusterIP 10.108.37.167 <none> 8080/TCP 3m8s app=myappv1
deployment2 ClusterIP 10.96.202.197 <none> 8080/TCP 3m2s app=myappv2
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 27d <none>[root@k8s-master service]# kubectl describe svc deployment1
Name: deployment1
Namespace: default
Labels: app=deployment1
Annotations: <none>
Selector: app=myappv1
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.108.37.167
IPs: 10.108.37.167
Port: <unset> 8080/TCP
TargetPort: 80/TCP
Endpoints: 10.244.2.15:80
Session Affinity: None
Events: <none>[root@k8s-master service]# kubectl describe svc deployment2
Name: deployment2
Namespace: default
Labels: app=deployment2
Annotations: <none>
Selector: app=myappv2
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.96.202.197
IPs: 10.96.202.197
Port: <unset> 8080/TCP
TargetPort: 80/TCP
Endpoints: 10.244.2.14:80
Session Affinity: None
Events: <none>
- 创建
ingress1.yml
[root@k8s-master service]# kubectl create ingress ingress1 --class nginx --rule='/=deployment1:8080' --dry-run=client -o yaml > ingress1.yml[root@k8s-master service]# vim ingress1.yml
[root@k8s-master service]# cat ingress1.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: ingress1
spec:ingressClassName: nginxrules:- http:paths:- backend:service:name: deployment1port:number: 8080path: /pathType: Prefix
- 创建
ingress2.yml
[root@k8s-master service]# kubectl create ingress ingress2 --class nginx --rule='/=deployment2:8080' --dry-run=client -o yaml > ingress2.yml[root@k8s-master service]# vim ingress2.yml
[root@k8s-master service]# cat ingress2.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:nginx.ingress.kubernetes.io/canary: "true"nginx.ingress.kubernetes.io/canary-by-header: "name" #键nginx.ingress.kubernetes.io/canary-by-header-value: "huazi" #值name: ingress2
spec:ingressClassName: nginxrules:- http:paths:- backend:service:name: deployment2port:number: 8080path: /pathType: Prefix
[root@k8s-master service]# kubectl apply -f ingress1.yml
ingress.networking.k8s.io/ingress1 created
[root@k8s-master service]# kubectl apply -f ingress2.yml
ingress.networking.k8s.io/ingress2 created
[root@k8s-master service]# kubectl describe ingress ingress1
Name: ingress1
Labels: <none>
Namespace: default
Address: 172.25.254.10
Ingress Class: nginx
Default backend: <default>
Rules:Host Path Backends---- ---- --------*/ deployment1:8080 (10.244.2.15:80)
Annotations: <none>
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Sync 12m (x2 over 13m) nginx-ingress-controller Scheduled for sync[root@k8s-master service]# kubectl describe ingress ingress2
Name: ingress2
Labels: <none>
Namespace: default
Address: 172.25.254.10
Ingress Class: nginx
Default backend: <default>
Rules:Host Path Backends---- ---- --------*/ deployment2:8080 (10.244.2.14:80)
Annotations: nginx.ingress.kubernetes.io/canary: truenginx.ingress.kubernetes.io/canary-by-header: namenginx.ingress.kubernetes.io/canary-by-header-value: huazi
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Sync 2m21s (x2 over 3m3s) nginx-ingress-controller Scheduled for sync
基于权重的金丝雀发布
- 通过
Annotaion
拓展 - 创建
灰度ingress
,配置灰度权重
以及总权重
灰度流量
验证完毕后,切换正式ingress
到新版本
#删掉基于header的ingress
[root@k8s-master service]# kubectl delete -f ingress2.yml
ingress.networking.k8s.io "ingress2" deleted
[root@k8s-master service]# vim ingress2.yml
[root@k8s-master service]# cat ingress2.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:nginx.ingress.kubernetes.io/canary: "true"nginx.ingress.kubernetes.io/canary-weight: "10" #10/100=10%,将有10%的流量打到新版本上nginx.ingress.kubernetes.io/canary-weight-total: "100"name: ingress2
spec:ingressClassName: nginxrules:- http:paths:- backend:service:name: deployment2port:number: 8080path: /pathType: Prefix
[root@k8s-master service]# kubectl apply -f ingress2.yml
ingress.networking.k8s.io/ingress2 created
[root@k8s-master service]# kubectl describe ingress ingress1
Name: ingress1
Labels: <none>
Namespace: default
Address: 172.25.254.10
Ingress Class: nginx
Default backend: <default>
Rules:Host Path Backends---- ---- --------*/ deployment1:8080 (10.244.2.15:80)
Annotations: <none>
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Sync 27m (x2 over 27m) nginx-ingress-controller Scheduled for sync[root@k8s-master service]# kubectl describe ingress ingress2
Name: ingress2
Labels: <none>
Namespace: default
Address: 172.25.254.10
Ingress Class: nginx
Default backend: <default>
Rules:Host Path Backends---- ---- --------*/ deployment2:8080 (10.244.2.14:80)
Annotations: nginx.ingress.kubernetes.io/canary: truenginx.ingress.kubernetes.io/canary-weight: 10nginx.ingress.kubernetes.io/canary-weight-total: 100
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal Sync 34s (x2 over 44s) nginx-ingress-controller Scheduled for sync
- 写检测脚本
[root@harbor ~]# vim check.sh
#!/bin/bash
v1=0
v2=0
for ((i=0;i<100;i++))
doresponse=`curl -s 172.25.254.50 | grep -c v1`v1=`expr $v1 + $response`v2=`expr $v2 + 1 - $response`
done
echo "v1:$v1 v2:$v2"
[root@harbor ~]# bash check.sh
v1:89 v2:11
[root@harbor ~]# bash check.sh
v1:87 v2:13
#我们发现比例接近于9:1
当我们增加权重
后
[root@k8s-master service]# vim ingress2.yml
[root@k8s-master service]# cat ingress2.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:annotations:nginx.ingress.kubernetes.io/canary: "true"nginx.ingress.kubernetes.io/canary-weight: "20"nginx.ingress.kubernetes.io/canary-weight-total: "100"name: ingress2
spec:ingressClassName: nginxrules:- http:paths:- backend:service:name: deployment2port:number: 8080path: /pathType: Prefix
[root@k8s-master service]# kubectl apply -f ingress2.yml
ingress.networking.k8s.io/ingress2 configured
[root@harbor ~]# bash check.sh
v1:76 v2:24
[root@harbor ~]# bash check.sh
v1:79 v2:21
#我们发现比例进阶于8:2
相关文章:

Kubernetes金丝雀发布
华子目录 Canary金丝雀发布什么是金丝雀发布Canary发布方式基于header(http包头)灰度发布基于权重的金丝雀发布 Canary金丝雀发布 什么是金丝雀发布 金丝雀发布也称为灰度发布,是一种软件发布策略主要目的是在将新版本的软件全面推广到生产环…...
树形DP讲解
文章目录 树形DP讲解一、引言二、树形DP基础1、树的定义2、树形DP的基本思想3、代码示例:子树大小 三、经典例题解析1、树的平衡点1.1、代码示例 2、没有上司的舞会(树的最大独立集)2.1、代码示例 四、总结 树形DP讲解 一、引言 树形动态规…...
容器:如何调试容器
调试容器,主要是指的调试Dockerfile,调试Dockerfile中的各个命令的执行,大小等 1、docker history查看构建过程和所有的中间层 2、docker run rm -it -u root XXX sh,通过临时容器的方式启动,可以调试中间层文件 3、do…...

用图说明 CPU、MCU、MPU、SoC 的区别
CPU CPU 负责执行构成计算机程序的指令,执行这些指令所指定的算术、逻辑、控制和输入/输出(I/O)操作。 MCU (microcontroller unit) 不同的 MCU 架构如下,注意这里的 MPU 表示 memory protection unit MPU (microprocessor un…...
牛客周赛 Round 65
文章目录 超市思路:Solved: 雨幕思路:Solved: 闺蜜思路:Solved: 医生思路:Solved: 降温(easy)思路:Solved: F-降温(hard&a…...

超级经典的79个软件测试面试题(内含答案)
1、软件的生命周期(prdctrm) 计划阶段(planning)-〉需求分析(requirement)-〉设计阶段(design)-〉编码(coding)->测试(testing)->运行与维护(running maintrnacne) 测试用例 用例编号 测试项目 测试标题 重要级别 预置条件 输入数据 执行步骤 预期结果 2、问…...
【Mac】安装 F5-TTS
1、下载项目 项目地址:【GitHub】 SWivid F5-TTS 2、创建并激活 Python 虚拟环境 # 创建 Python 虚拟环境 userMac F5-TTS-main % python3 -m venv f5-tts# 激活进入 Python 虚拟环境 userMac F5-TTS-main % source f5-tts/bin/activate (f5-tts) userrMac F5-TT…...

Leaflet查询矢量瓦片偏移的问题
1、问题现象 使用Leaflet绘制工具查询出来的结果有偏移 2、问题排查 1)Leaflet中latLngToContainerPoint和latLngToLayerPoint的区别 2)使用Leaflet查询需要使用像素坐标 3)经排查发现,container获取的坐标是地图容器坐标&…...

存储引擎技术进化
B-tree 目前支撑着数据库产业的半壁江山。 50 年来不变而且人们还没有改变它的意向 鉴定一个算法的优劣,有一个学派叫 IO复杂度分析 ,简单推演真假便知。 下面就用此法分析下 B-tree(traditional b-tree) 的 IO 复杂度,对读、写 IO 一目了…...
CentOS 9 Stream 上安装 Maven
CentOS 9 Stream 上安装 Maven 在 CentOS 9 Stream 上安装 Maven,可以按照以下步骤进行: 更新系统软件包: sudo dnf update安装 Maven: CentOS 9 Stream 默认的包管理器中已经包含 Maven,你可以直接安装: s…...

强势改进!TCN-Transformer时间序列预测
强势改进!TCN-Transformer时间序列预测 目录 强势改进!TCN-Transformer时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现TCN-Transformer时间序列预测; 2.运行环境为Matlab2023b; 3.单个变量时间序…...

MyBatis的不同参数传递封装
MyBatis参数传递 传参方式 1. 使用 #{} 占位符 这是 MyBatis 中最常用的参数传递方式。它将参数直接替换到 SQL 语句中的占位符位置。 单个参数: <select id"selectUserById" resultType"User">SELECT * FROM users WHERE id #{id}…...
kotlin 协程方法总结
Kotlin 协程是一套强大的异步编程工具,以下是对 Kotlin 协程常用方法的总结: 1. 协程构建器 launch: 启动一个新的协程,不阻塞当前线程,返回一个 Job 对象。 GlobalScope.launch {// 协程体}async: 启动一个新的协程并返回一个…...
脉冲当量计算方法
脉冲的概念: 脉冲当量是指控制器输出一个定位控制脉冲时,所产生的定位控制移动的位移。在直线运动中,它表示移动的距离;在圆周运动中,它表示转动的角度。简而言之,脉冲当量就是电机接收一个脉冲信号后能够移…...

TongWeb7.0.E.6_P11嵌入式版本使用指引(by lqw)
文章目录 声明相关概念手册的使用示范工程安装工程介质 安装前准备示范工程参考(spring-boot-helloWorld-2.x)示范参考 声明 1.本文参考001_TongWeb_V7.0嵌入式版_JavaEE标准容器用户指南_70E6_P11A01.pdf,实际以最新更新的手册为准。 2.本文…...

Node.js:Express 服务 路由
Node.js:Express 服务 & 路由 创建服务处理请求req对象 静态资源托管托管多个资源挂载路径前缀 路由模块化 Express是Node.js上的一个第三方框架,可以快速开发一个web框架。本质是一个包,可以通过npm直接下载。 创建服务 Express创建一…...

C++之多态(上)
C之多态 多态的概念 多态(polymorphism)的概念:通俗来说,就是多种形态。多态分为编译时多态(静态多态)和运⾏时多 态(动态多态),这⾥我们重点讲运⾏时多态,编译时多态(静态多态)和运⾏时多态(动态多态)。编译时 多态(静态多态)主…...
PySpark单机模式安装教程
目录 1. 环境准备 1.1 安装要求 1.2 检查Python和Java环境 2. 下载并解压Spark 2.1 下载Spark 2.2 解压安装包 3. 配置环境变量 4. 配置Spark 5. 启动Spark Shell 6. 运行测试 7. 关闭Spark Shell 8. 常见问题 8.1 兼容性问题 8.2 环境变量配置 总结 1. 环境准备…...

DEVOPS: 认证与调度
概述 不知道大家有没有意识到一个现实,就是大部分时候,我们已经不像以前一样通过命令行,或者可视窗口来使用一个系统了现在我们上微博、或者网购,操作的其实不是眼前这台设备,而是一个又一个集群 通常,这样…...

ICPC区域赛成都站【赛后回顾+总结】
传送门 前言赛后总结赛后回顾赛后感悟 前言 首先,这是本人本赛季第一场XCPC区域赛,也是本人算竞生涯中第一场XCPC区域赛(之前只打过邀请赛和省赛)。 赛后总结 然后赛后总结一下:我队天崩开局,我队出师不利…...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...