如何在 Kubernetes 中借助Ingress 实现灰度发布和蓝绿发布

news2025/1/22 9:11:06

前言

部署在 Kubernetes 集群中的应用,在升级发布时可能会存在的问题:

1,由于 Kuberneter 底层 Pod 容器生命周期与网络组件生命周期是异步管理的,在升级时如果没有处理好应用优雅退出的问题,就很容易导致 http 访问请求 5xx

2,原生 Deployment 应用的滚动发布功能是一把梭的全量发布模式,没有灰度和分批控制发布的概念,一旦出现问题,故障影响范围就会迅速扩大

这也是为什么需要灰度发布,蓝绿发布,彩虹发布,金丝雀发布、A/B Test等多样化形式发布的重要原因,核心目标只有一个,就是为了确保服务的稳定性,减少或避免因变更带来的不稳定因素

今天我们主要来聊下,如何在不引入第三方插件的情况下,来实现简单的灰度发布和蓝绿发布功能

通过 Ingress 实现灰度发布和蓝绿发布

在 Kubernetes 里面 Pod 的网络通信都是借助 Service 实现的,Service 的底层是依赖 Iptables 或者 eBPF 加上 dns 技术实现的,具体细节感兴趣可自行探索,Ingress 负责 k8s 集群内外的流量通信,本身属于七层负载的工作范围,所以可以将流量反向代理到四层负载的 Service 中,在七层负载中支持 Http 协议,所以可以实现的功能更加强大

工作原理

Kubernetes 自带的 Ingress Controller 组件的底层是 Nginx ,所以基于七层负载的能力,我们就可以做更多与流量分配相关的功能,目前基于 Nginx 的 Ingress 支持通过 Header,Cookie 和 Weight 三种流量切分的策略,这三种策略,又可以实现以下两种发布场景:

按请求级别的灰度用户流量

通过 header 和 cookie 路由流量进行灰度

按比例级别的灰度用户流量

通过 weight 权重设置

支持的Nginx Annotation介绍
  1. nginx.ingress.kubernetes.io/canary-by-header

基于Header的流量切分。如果请求头中包含指定的 header,并且值为“always”,就将该请求转发给Canary Ingress定义的对应后端服务。如果值为“never”则不转发,可用于回滚到旧版本。如果为其他值则忽略该annotation,并通过优先级将请求流量分配到其他规则。

  1. nginx.ingress.kubernetes.io/canary-by-header-value

必须与canary-by-header一起使用,可自定义请求头的取值,包含但不限于“always”或“never”。当请求头的值命中指定的自定义值时,请求将会转发给Canary Ingress定义的对应后端服务,如果是其他值则忽略该annotation,并通过优先级将请求流量分配到其他规则。

  1. nginx.ingress.kubernetes.io/canary-by-header-pattern

与canary-by-header-value类似,唯一区别是该annotation用正则表达式匹配请求头的值,而不是某一个固定值。如果该annotation与canary-by-header-value同时存在,该annotation将被忽略。

  1. nginx.ingress.kubernetes.io/canary-by-cookie

基于Cookie的流量切分。与canary-by-header类似,该annotation用于cookie,仅支持“always”和“never”,无法自定义取值。

  1. nginx.ingress.kubernetes.io/canary-weight

基于服务权重的流量切分,适用于蓝绿部署。表示Canary Ingress所分配流量的百分比,取值范围[0-100]。例如,设置为100,表示所有流量都将转发给Canary Ingress对应的后端服务。

注解规则会按优先级进行评估,优先级为:canary-by-header -> canary-by-cookie -> canary-weight。

灰度发布

依赖资源:2 个 Ingress 对象,2 个 Service 对象,两个 Deployment 对象

操作流程:为服务创建两个 Ingress,一个为常规 Ingress,另一个为带有 nginx.ingress.kubernetes.io/canary: "true"注解的 Ingress,称为 Canary Ingress,在 Canary Ingress 上配置切分策略。

两个 Deployment 对象,分别对应升级过程中的两个版本 v1,v2

apiVersion: apps/v1
kind: Deployment
metadata:
  name: py-hello-blue
spec:
  selector:
    matchLabels:
      app: hello
      color: blue
  replicas: 1
  template:
    metadata:
      labels:
        app: hello
        color: blue
    spec:
      terminationGracePeriodSeconds: 30
      containers:
      - name: hello
        imagePullPolicy: Always
        image: localhost:5001/py-http:1
        ports:
        - containerPort: 8888
        resources:
          requests:
            memory: "50Mi"
          limits:
            memory: "200Mi"
        lifecycle:
          preStop:
            exec:                                                                      
              command: ["sleep", "5"]
        # command: ["/usr/bin/tini", "--", "bash", "-c"]
        command: ["sh", "-c"]
        args:
        - |
          python app.py
apiVersion: apps/v1
kind: Deployment
metadata:
  name: py-hello-green
spec:
  selector:
    matchLabels:
      app: hello
      color: green
  replicas: 1
  template:
    metadata:
      labels:
        app: hello
        color: green
    spec:
      terminationGracePeriodSeconds: 30
      containers:
      - name: hello
        imagePullPolicy: Always
        image: localhost:5001/py-http:2
        ports:
        - containerPort: 8888
        resources:
          requests:
            memory: "50Mi"
          limits:
            memory: "200Mi"
        lifecycle:
          preStop:
            exec:                                                                      
              command: ["sleep", "5"]
        # command: ["/usr/bin/tini", "--", "bash", "-c"]
        command: ["sh", "-c"]
        args:
        - |
          python app.py

两个 Service 对象,分别对应 v1,v2 的Deployment

apiVersion: v1
metadata:
  name: py-hello-blue-service
kind: Service
spec:
  selector:
    app: hello
    #color: green
    color: blue
  ports:
    - name: web
      port: 8888
      protocol: TCP
      targetPort: 8888
  type: ClusterIP
apiVersion: v1
metadata:
  name: py-hello-green-service
kind: Service
spec:
  selector:
    # app: hello
    color: green
    # color: blue
  ports:
    - name: web
      port: 8888
      protocol: TCP
      targetPort: 8888
  type: ClusterIP

两个 Ingress 对象,进行灰度流量的分配

kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: py-hello-ingress-normal
spec:
  rules:
    - host: py-hello.test.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service: 
                port: 
                  number: 8888
                name: py-hello-blue-service
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: py-hello-ingress-canary
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/canary: "true"                # 启用Canary
    #基于 Header 的灰度
    #nginx.ingress.kubernetes.io/canary-by-header: "Region"
    #nginx.ingress.kubernetes.io/canary-by-header-pattern: "hz|lg"    
    #基于 Cookie 的灰度
    #nginx.ingress.kubernetes.io/canary-by-cookie: "qdl"    # Cookie中包含user_from_bj的请求转发到Canary Ingress
    #基于 weight 的灰度    
    nginx.ingress.kubernetes.io/canary-weight: "20"    # 将20%的流量转发到Canary Ingress

spec:
  rules:
    - host: py-hello.test.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service: 
                port: 
                  number: 8888
                name: py-hello-green-service

实现灰度发布,就是把 canary 里面的流量分配策略进行修改即可

蓝绿发布

实现蓝绿发布,就是在灰度发布的基础上把 canary 里面的weight流量分配权重改为 100 即可。

注意:

  • 相同服务的Canary Ingress仅能够定义一个,从而使后端服务最多支持两个版本。
  • 即使流量完全切到了Canary Ingress上,旧版服务仍需存在,否则会出现报错。

总结

通过 ingress 进行灰度发布和蓝绿发布可以实现更加复杂的流量分配策略,但对应的操作也变得复杂了,对于大部分复杂的发布业务也足够用了,这种方案也可以结合发布平台稍做封装,比如一键创建新克隆版本,切换流量配比,设置流量策略等,有了这些基础功能后,再配合发布平台就可以流畅的操作了

 

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

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

相关文章

零信任体系化能力建设(4):应用安全与开发部署

应用和工作负载是企业资产的重要组成部分,也是用户访问企业数据的主要手段和攻击者关注的首要目标,因此,强化对IT栈内软件部分的安全控制是企业推进零信任成熟度的必由之路。 通常,零信任网络访问(ZTNA)通…

新唐Nuc980学习笔记1 - 工程创建和下载

一、新唐nuc980 新唐nuc980 iot开发板是Linux 工业物联网开发平台,新唐科技提供工业物联网开发平台采用 NUC980DK 微处理器,此为一套完整的工业用物联网开平台,包含了完整的硬件设计与软件参考设计。包含了新唐执行速度 300 MHz 的 ARM9 MPU …

710. 黑名单中的随机数

710. 黑名单中的随机数 原题链接:完成情况:解题思路:参考代码: 原题链接: 710. 黑名单中的随机数 https://leetcode.cn/problems/random-pick-with-blacklist/description/ 完成情况: 解题思路&#xff…

Java“牵手”天猫商品评论API接口数据,天猫API接口申请指南

天猫商城是一个网上购物平台,售卖各类商品,包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取淘宝商品详情页面评价内容数据,您可以通过开放平台的接口或者直接访问淘宝商城的网页来获取商品详情信息内的评论数据。以下是两种常用方法…

基于DMA分区计量的实时产销差率估算方法

目前供水企业的产销差率和漏损率一般都以年为单位进行统计,这种计算方法有明显的滞后性,使得供水企业无法第一时间掌握产销差率实际情况。基于此,提出了实时产销差率的 概念,并给出了基于DMA分区计量的实时产销差率估算方法。实际…

Android应用启动流程:从启动到可交互的过程解析

关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 目录 一、导读1.1 启动知识储备1.2 Zygote进程1.3 SystemServer进程1.4 …

neo4j 图数据库 springboot

一.安装 neo4j社区版在liunx安装部署 https://blog.csdn.net/u013946356/article/details/81736232 二.知识图数据导入 参考:https://notemi.cn/neo4j-import-csv-file-data.html http://openkg.cn/dataset/ch4masterpieces 放在对应的import文件夹下面 导入数据 LOAD C…

SpringCloud/SpringBoot多模块项目中配置公共AOP模块实现打印子模块Controller所有请求参数与日志

项目中遇到多个模块需要打印Controller请求日志,在每个模块里面加AOP并且配置单独的切面笔者认为代码冗余,于是乎就打算把AOP日志打印抽离成一个公共模块,谁想用就引入Maven坐标就行。 定义公共AOP模块 并编写AOP工具 AOP模块pom.xml如下 &…

SpringBoot案例-配置文件-yml配置文件

配置格式 SpringBoot提供了多种属性配置方式 application.propertiesapplication.ymlapplication.yaml常见配置文件格式对比 XML&#xff08;臃肿&#xff09; <configuration><database><host>localhost</host><port>3306</port><use…

VMware虚拟机连不上网络

固定ip地址 进入网络配置文件 cd /etc/sysconfig/network-scripts 打开文件 vi ifcfg-ens33 编辑 BOOTPROTO设置为static&#xff0c;有3个值&#xff08;decp、none、static&#xff09; BOOTPROTO"static" 打开网络 ONBOOT"yes" 固定ip IPADDR1…

Vue中使用vue-drag-resize实现窗体可拖拽和随意缩放大小

场景 若依前后端分离版手把手教你本地搭建环境并运行项目&#xff1a; 若依前后端分离版手把手教你本地搭建环境并运行项目_ruoyi本地调式_霸道流氓气质的博客-CSDN博客 在上面的基础上&#xff0c;实现弹窗窗体可移动以及随意缩放大小。 效果如下 注&#xff1a; 博客&am…

面试题(三)

目录 一.Spring 1.Spring IOC & AOP 2.Spring bean (1) 作用域 (2) Spring 中的 bean ⽣命周期 (3) Spring 框架中⽤到了哪些设计模式 二.Mybatis 1.标签 2.Dao接口 3.返回与映射 4.延迟加载 三.Kafka 四.设计模式 1.IO 设计模式 2.Spring 中的设计模式详解…

ctfshow-红包题第二弹

0x00 前言 CTF 加解密合集CTF Web合集 0x01 题目 0x02 Write Up 同样&#xff0c;先看一下有没有注释的内容&#xff0c;可以看到有一个cmd的入参 执行之后可以看到文件代码&#xff0c;可以看到也是eval&#xff0c;但是中间对大部分的字符串都进行了过滤&#xff0c;留下了…

ruoyi-cloud部署

默认你已经安装mysql&#xff0c;nacos&#xff0c;seata&#xff0c;sentinel等&#xff08;没有的可以先找教程安装&#xff09; 1、下载源码&#xff1a;git clone https://gitee.com/zhangmrit/ruoyi-cloud 2、项目依赖导入&#xff0c;选择自己的maven环境等&#xff0c;创…

SpringBootWeb案例 Part 5

4. 配置文件 员工管理的增删改查功能我们已开发完成&#xff0c;但在我们所开发的程序中还一些小问题&#xff0c;下面我们就来分析一下当前案例中存在的问题以及如何优化解决。 4.1 参数配置化 在我们之前编写的程序中进行文件上传时&#xff0c;需要调用AliOSSUtils工具类&…

25岁的健康启程:追逐活力,超越年龄

嗨&#xff0c;亲爱的朋友们&#xff01;今天&#xff0c;我想与大家分享一个深入人心的话题&#xff1a;年龄与健康。最近&#xff0c;有关大公司裁员&#xff0c;并将35岁定为“体能下滑”的临界点的新闻引发了热议。是不是只要到了35岁&#xff0c;身体就会渐渐变差&#xf…

Go framework-Kratos

一、Go framework 框架Github开源时间开源方Kratoshttps://github.com/go-kratos/kratos2019Bilibiligo-kithttps://github.com/go-kit/kit/2015团队开源go-zerohttps://github.com/tal-tech/go-zero2020团队开源TarsGohttps://github.com/TarsCloud/TarsGo2018腾讯Jupiterhtt…

免费清理电脑:删除垃圾文件以提升电脑性能

求助&#xff01;电脑上没有可用空间 ​“我只在电脑上存储了大约100张照片&#xff0c;为什么我的硬盘空间已满&#xff1f;电脑运行速度也变得越来越慢&#xff0c;要疯了&#xff01;现在我想安装更新的驱动程序。我可以释放磁盘空间吗&#xff1f;有免费的Windows电脑清…

数组-C语言(初阶)

目录 一、一维数组的创建和初始化 1.1 数组的创建 1.2 数组的初始化 1.3 一维数组的使用 二、二维数组的创建和初始化 2.1 二维数组的创建 2.2 二维数组的初始化 2.3 二维数组的使用 2.4 二维数组在内存中的存储 三、数组越界 四、数组作为函数参数 4.1 数组名 4.2 冒泡排序…

FreeRTOS 查找最高优先级的就绪任务源码分析

一、就绪任务列表 就绪列表 pxReadyTasksLists[ configMAX_PRIORITIES ] 是一个数组&#xff0c; 数组里面存的是就绪任务的 TCB&#xff08;准确来说是 TCB 里面的 xStateListItem 节点&#xff09; &#xff0c;数组的下标对应任务的优先级&#xff0c;优先级越低对应的数组…