天天看点

使用 KubeSphere 实现微服务的灰度发布

前言

今天来说一说,在 KubeSphere 中两个 " 小姐姐 " 如何来回切换,这是什么意思哩?其实就是互联网产品中常用的灰度发布方式。

互联网产品需要快速迭代上线,既要保证新功能运行正常,又要保证质量,一旦出现问题可以很快控制局面,就需要设计一套灰度发布系统。用大白话讲就是某个 APP 的新版本已经开发完成了,而老版本用户正在正常使用着,这个时候要是直接上线新版本,那么所有的用户都会用新版本,但是这种情况下,一旦出现问题,将导致所有的用户都不可用,所以会有策略的挑选一部分用户先用新版本,即使出现问题,也只是一小部分用户,方便回滚到旧版本,提升用户良好的体验性。

概述

灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行 A/B testing,即让一部分用户继续用产品特性 A,一部分用户开始用产品特性 B,如果用户对 B 没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到 B 上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度。

我们假设这个 A/B,就是 A 小姐姐和 B 小姐姐。

KubeSphere 的微服务治理功能

KubeSphere 基于 Istio 微服务框架提供可视化的微服务治理功能,如果您在 Kubernetes 上运行和伸缩微服务,您可以为您的分布式系统配置基于 Istio 的微服务治理功能。KubeSphere 提供统一的操作界面,便于您集成并管理各类工具,包括 Istio、Envoy 和 Jaeger 等。

流量治理

  • 金丝雀发布提供灵活的灰度策略,将流量按照所配置的比例转发至当前不同的灰度版本
  • 蓝绿部署支持零宕机部署,让应用程序可以在独立的环境中测试新版本的功能和特性
  • 流量镜像模拟生产环境,将实时流量的副本发送给被镜像的服务
  • 熔断机制支持为服务设置对单个主机的调用限制

在 KubeSphere 中应用治理可以以可插拔式方式开启。开启后如下:

使用 KubeSphere 实现微服务的灰度发布

准备工作

创建一个 SpringBoot 的项目用于测试,如下 pom.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.pkulaw</groupId>
  <artifactId>ServiceA</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>ServiceA</name>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.0</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
    <docker.image.prefix>springboot</docker.image.prefix>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>

    <!-- 引入Actuator监控依赖 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>

    <dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>5.8.0</version>
    </dependency>
  </dependencies>

  <build>
    <finalName>ServiceA</finalName>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>
      

controller 代码:

@RestController
@Slf4j
public class CommonController {

    /**
     * 返回A/B小姐姐图片
     * @param response
     * @throws IOException
     */
    @RequestMapping(method = RequestMethod.GET, produces = "image/jpeg")
    public void getImage2(HttpServletResponse response) throws IOException {
        ClassPathResource classPathResource = new ClassPathResource("images/B.jpg");
        InputStream  inputStream = classPathResource.getInputStream();
        //将InputStream 转 File
        File file = asFile(inputStream);
        FileCopyUtils.copy(new FileInputStream(file), response.getOutputStream());
        response.setHeader("Content-Type", "application/octet-stream");
    }

    /**
     * InputStream To File
     * @param in
     * @return
     * @throws IOException
     */
    public static File asFile(InputStream in) throws IOException {
        File tempFile = File.createTempFile("test", ".tmp");
        tempFile.deleteOnExit();
        FileOutputStream out = new FileOutputStream(tempFile);
        IOUtils.copy(in, out);
        return tempFile;
    }
}      
注:直接通过接口返回一张图片。

项目目录结构如下:

使用 KubeSphere 实现微服务的灰度发布

镜像构建

在 KubeSphere 中有个超炫的功能叫镜像构建器,镜像构建器(Image Builder)是将代码或者制品制作成容器镜像的工具。您可以通过简单的设置将制品或代码直接制作成容器镜像,无需 Dockerfile 文件。

使用 KubeSphere 实现微服务的灰度发布
上面图片来自 KubeSphere 镜像构建官方介绍。

3.3.0 版本中就长下面这个样子:

使用 KubeSphere 实现微服务的灰度发布

harbor 中新建项目

使用 KubeSphere 实现微服务的灰度发布

创建镜像构建器

使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布
gitlab 仓库秘钥和 harbor 镜像服务提前设置好。镜像名称为 service-a/service-a,镜像标签设置为 v1。

创建成功后,开始运行

使用 KubeSphere 实现微服务的灰度发布
构建成功如上所示。

harbor 中查看 v1 标签的镜像

使用 KubeSphere 实现微服务的灰度发布
以上就是 v1 版本由来的整个过程,我们简称为 A 小姐姐。

接下来制作 B 小姐姐,新建一个代码分支为 release, 调整代码返回为 B 小姐姐。

使用 KubeSphere 实现微服务的灰度发布

构建 v2 版本的镜像,也就是我们的 B 小姐姐。

使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布

项目网关

KubeSphere 项目中的网关是一个 NGINX Ingress 控制器。KubeSphere 内置的用于 HTTP 负载均衡的机制称为应用路由 (Ingress 路由规则),它定义了从外部到集群服务的连接规则。如需允许从外部访问服务,用户可创建路由资源来定义 URI 路径、后端服务名称等信息。

KubeSphere 除了提供项目范围的网关外,还提供集群范围的网关,使得所有项目都能共享全局网关。

在 KubeSphere 中开启项目网关以从外部访问服务和路由。

使用 KubeSphere 实现微服务的灰度发布

自制应用

在 KubeSphere 中实现金丝雀发布,必须先开启应用治理,且必须有一个可用的应用。

使用 KubeSphere 实现微服务的灰度发布
KubeSphere 支持基于模板的应用和自制应用。基于模板的应用创建自 KubeSphere 应用商店或应用模板,自制应用由用户自定义。这里我们以自制应用为例。

创建自制应用

使用 KubeSphere 实现微服务的灰度发布

创建服务

使用 KubeSphere 实现微服务的灰度发布

选择无状态服务

使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布
容器端口为 ServiceA 服务的端口 7777
使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布
在这里添加路由规则后,KubeSphere 会自动帮我们创建 ingress 路由规则。

创建成功后如下:

使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布

应用路由下会自动生成 ingress 路由规则,如下:

使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布

配置本地 hosts, 如:192.168.0.156 ​​servicea.com​​

点击访问服务,立即返回 A 小姐姐,如下:

使用 KubeSphere 实现微服务的灰度发布

金丝雀发布

创建金丝雀发布任务

使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布
可以指定流量进行分配,也可以指定请求参数
使用 KubeSphere 实现微服务的灰度发布

创建成功,查看任务状态

使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布
默认 v1 和 v2 各占 50% 流量。

请求服务来查看流量走向,v1 和 v2 各占 50% 流量

使用 KubeSphere 实现微服务的灰度发布
使用 KubeSphere 实现微服务的灰度发布

总结

继续阅读