K8s 应用管理之道 - 升级篇(二)

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,恶意文件检测 1000次 1年
对象存储 OSS,内容安全 1000次 1年
简介: 我们在上一篇文章中介绍了不同部署形式下应用的升级方法,同时展示了如何配置停机发布、滚动发布这两类 k8s 原生支持的部署升级策略。本文将介绍如何通过二次开发或使用一些第三方工具在 k8s 中实现应用的蓝绿发布、金丝雀发布和 A/B 测试。

背景

我们在系列文章 K8s 应用管理之道 - 升级篇(一) 中介绍了不同部署形式下应用的升级方法,同时展示了如何配置停机发布、滚动发布这两类 k8s 原生支持的部署升级策略。本文将介绍如何通过二次开发或使用一些第三方工具在 k8s 中实现应用的蓝绿发布、金丝雀发布和 A/B 测试。

蓝绿发布

如果新老版本的应用无法共存,但又希望实现零中断升级,在系统资源充足的前提下,可以选用蓝绿发布。通过 k8s 的 label-selector 机制可以轻松实现蓝绿发布。如下图所示,您需要做的仅仅是为不同版本的应用打上对应的标签,然后通过更改 service 的 selector 实现流量切换。

blue_green

配置方法

这里和蓝绿发布相关的配置如下(完整配置参见 blue-green)。

[...]
kind: Service
spec:
  # Service 的 selector 会选择 app 标签和 version 标签都匹配的 pod
  selector:
    app: spring-boot-probes
    # 通过更改 version 的取值实现流量切换,例如 v2.0.0
    version: v1.0.0
[...]
kind: Deployment
metadata:
  name: spring-boot-probes-v1
spec:
  selector:
    matchLabels:
      app: spring-boot-probes
      version: v1.0.0
  template:
    metadata:
      labels:
          app: spring-boot-probes
        # Pod 的 version 标签
        version: v1.0.0
[...]
kind: Deployment
metadata:
  name: spring-boot-probes-v2
spec:
  selector:
    matchLabels:
      app: spring-boot-probes
      version: v2.0.0
  template:
    metadata:
      labels:
        app: spring-boot-probes
        # Pod 的 version 标签
        version: v2.0.0
[...]

操作步骤

完成上述配置后,可以通过以下步骤实现蓝绿发布:

  1. 运行命令kubectl apply -f ./spring-boot-probes-v2.yaml部署 v2 版本的应用。等到 v2 版本的 pod 全部变成就绪状态后流量并不会发往它们,这是因为 service 的 selector 只与 v1 版本 pod 的标签相匹配。
  2. 当一切准备就绪后,可以运行命令kubectl patch service spring-boot-probes-svc -p '{"spec":{"selector":{"version":"v2.0.0"}}}'更改 service 的 selector,让其指向 v2 版本的 pod。这时流量会全部发往 v2。
  3. 如果 v2 版本的应用运行一段时间后出现了问题,可以通过命令kubectl patch service spring-boot-probes-svc -p '{"spec":{"selector":{"version":"v1.0.0"}}}'进行回滚,将流量再次切回到 v1 上来。
  4. 如果 v2 版本应用的行为符合预期,可以运行命令kubectl delete deploy spring-boot-probes-v1删掉 v1 版本的 deployment 以节省资源。

金丝雀发布

金丝雀发布通过逐步切换流量的方式大大降低了升级和变更可能带来的风险,因此被广泛使用。相较于其他发布方式,其最大特点在于对流量的灵活控制。回到 k8s 的场景,实现金丝雀发布最推荐的方式是使用 istio。利用 istio 强大的流量管理功能,用户可以灵活地控制发往不同版本的流量,不论该版本部署了多少个 pod 实例。而在没有 istio 的 k8s 环境中,发往新老版本的流量和它们的 pod 实例数成正比。

下图展示了基于 istio 的金丝雀发布的关键组件,用户可以通过调节 VirtualService 的 weight 字段指定将 10% 的流量发往金丝雀版本。

istio_canary

配置方法

以下配置指定将 90% 的流量发往服务 spring-boot-probes-svc-v1,将 10% 的流量发往服务 spring-boot-probes-svc-v2。而服务 spring-boot-probes-svc-v1 绑定了当前版本的 pod,服务 spring-boot-probes-svc-v2 绑定了金丝雀版本的 pod(完整配置参见 canary)。

[...]
kind: VirtualService
metadata:
  name: spring-boot-probes
spec:
  hosts:
    - spring-boot-probes.local
  gateways:
    - spring-boot-probes
  http:
    - route:
        - destination:
            host: spring-boot-probes-svc-v1
          weight: 90
        - destination:
            host: spring-boot-probes-svc-v2
          weight: 10
[...]
kind: Service
metadata:
  name: spring-boot-probes-svc-v1
spec:
  selector:
    app: spring-boot-probes
    version: v1.0.0
[...]
kind: Service
metadata:
  name: spring-boot-probes-svc-v2
spec:
  selector:
    app: spring-boot-probes
    version: v2.0.0
[...]

操作步骤

完成上述配置后,可以通过以下步骤实现金丝雀发布:

  1. 运行命令kubectl apply -f ./spring-boot-probes-v2.yaml部署 v2 版本的 service 和少量的 pod 实例。由于此时 VirtualService 的路由目标只有 v1,流量并不会被发到 v2 上。
  2. 当 v2 版的 pod 就绪后,运行命令kubectl apply -f ./virtualservice-weight.yaml更改 VirtualService 的路由规则,让少量流量能够发往 v2。
  3. 如果 v2 版本应用的行为符合预期,可以通过调整权重继续扩大发往 v2 的流量比例。同时,v1 和 v2 的 pod 实例数也可以根据实际情况进一步调整,甚至可以为它们配置 Horizontal Pod Autoscaler
  4. 如果 v2 版本在运行过程中出现了问题,可以更改 VirtualService 的路由规则将流量重新切回到 v1 上来。
  5. 待全部流量都落在 v2 上后,运行命令kubectl delete -f ./spring-boot-probes-v1删除 v1 版应用的资源。

A/B 测试

如果您网站的 UI 作了改版,但并不确定新版本是否会获得用户青睐,这时可以通过 A/B 测试收集用户意见,并根据实际效果确定最佳方案。A/B 测试实施的关键在于根据不同条件将访问流量分发到不同的版本。实际使用中,往往会根据具体情况选用不同的条件。常用的条件包括用户位置信息、user-agent、自定义 header、请求参数、语言等。得益于强大的流量管理功能,istio 是 k8s 场景下实现 A/B 测试的最佳方案。下图展示了如何根据 user-agent 分发访问流量。

istio_abtesting

配置方法

以下配置指定将来自 Andriod 的访问流量发往服务 spring-boot-probes-svc-v1,将来自 iPhone 的访问流量发往服务 spring-boot-probes-svc-v2。而 spring-boot-probes-svc-v1 和 spring-boot-probes-svc-v2 分别绑定了不同版本的 pod
(完整配置参见 ab-testing)。

[...]
kind: VirtualService
metadata:
  name: spring-boot-probes
spec:
  hosts:
    - spring-boot-probes.local
  gateways:
    - spring-boot-probes
  http:
    - route:
        - destination:
            host: spring-boot-probes-svc-v1
      match:
        - headers:
            user-agent:
              exact: Andriod
    - route:
        - destination:
            host: spring-boot-probes-svc-v2
      match:
        - headers:
            user-agent:
              exact: iPhone
[...]
kind: Service
metadata:
  name: spring-boot-probes-svc-v1
spec:
  selector:
    app: spring-boot-probes
    version: v1.0.0
[...]
kind: Service
metadata:
  name: spring-boot-probes-svc-v2
spec:
  selector:
    app: spring-boot-probes
    version: v2.0.0
[...]

操作步骤

完成上述配置后,可以通过以下步骤实施 A/B 测试:

  1. 运行命令kubectl apply -f ./spring-boot-probes-v2.yaml部署 v2 版本的 service 和对应的 pod 实例。
  2. 当 v2 版的 pod 就绪后,运行命令kubectl apply -f ./virtualservice-match.yaml更改 VirtualService 的路由规则,让来自 Andriod 的流量发往 v1,来自 iPhone 的流量发往 v2。
  3. 让两个版本的应用同时运行一段时间并不断收集用户反馈。
  4. 如果发现使用 user-agent 作为条件并不能达到很好的测试效果,可以更改 VirtualService 的路由规则,根据其他条件进行测试。
  5. 经综合分析后,如果发现 v1 更受青睐,则更改 VirtualService 的路由规则,让流量只发往 v1,然后删除 v2 版应用的资源。反之亦然。

总结

本文带您探索了在 k8s 中进行蓝绿发布、金丝雀发布和 A/B 测试的最佳实践。可以看到,运用好 istio 强大的流量管理功能可以简化复杂发布的实施流程,大大降低实现成本。

参考资料

扩展阅读

阿里云日志服务针对容器场景提供了一站式日志解决方案,想了解相关内容可参考下列文章:

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
6月前
|
Kubernetes 网络协议 网络安全
提升你的云技能:深入了解CKA认证之k8s升级秘籍!
提升你的云技能:深入了解CKA认证之k8s升级秘籍!
107 0
|
人工智能 Kubernetes 安全
阿里云 ACK 新升级,打造智算时代的现代化应用平台
阿里云 ACK 新升级,打造智算时代的现代化应用平台
70629 10
|
23天前
|
Kubernetes 持续交付 开发工具
ACK One GitOps:ApplicationSet UI简化多集群GitOps应用管理
ACK One GitOps新发布了多集群应用控制台,支持管理Argo CD ApplicationSet,提升大规模应用和集群的多集群GitOps应用分发管理体验。
|
3月前
|
Kubernetes Cloud Native 应用服务中间件
云原生之旅:Kubernetes集群部署与应用管理
【8月更文挑战第28天】在这篇文章中,我们将一起探索云原生技术的奇妙世界,尤其是围绕Kubernetes这一核心组件。从搭建一个基本的Kubernetes集群开始,到运行和管理容器化应用,每一步都将是一次深入浅出的学习旅程。无论你是初学者还是有经验的开发者,本指南都旨在为你提供清晰的操作步骤和必要的理论知识,让你能够自信地管理和扩展你的云原生应用。让我们携手开启这场技术冒险,共同见证云原生带来的无限可能。
|
3月前
|
Kubernetes 容器 Perl
【Azure K8S】AKS升级 Kubernetes version 失败问题的分析与解决
【Azure K8S】AKS升级 Kubernetes version 失败问题的分析与解决
|
3月前
|
Kubernetes 监控 API
在K8S中,RS资源如何实现升级和回滚?
在K8S中,RS资源如何实现升级和回滚?
|
3月前
|
Kubernetes API 开发工具
在K8S中,Deployment的升级过程是什么?
在K8S中,Deployment的升级过程是什么?
|
3月前
|
Kubernetes 容器 Perl
在k8S中,deployment升级策略是什么?
在k8S中,deployment升级策略是什么?
|
3月前
|
Kubernetes API Perl
在k8S中,deployment升级过程是什么?
在k8S中,deployment升级过程是什么?
|
3月前
|
Kubernetes 监控 Perl
在K8S中,deploy升级过程包括什么?
在K8S中,deploy升级过程包括什么?