使用 Istio 进行金丝雀部署

标签: | 发表时间:2021-06-04 18:08 | 作者:
出处:https://istio.io
本篇博客最后更新时间 2018 年 5 月 16 号,采用了最新版本的流量管理模型。

采用 Istio项目的一大好处就是为服务金丝雀方式部署提供了控制便利。金丝雀部署(或上线)背后的想法是通过让一小部分用户流量引入的新版本进行测试,如果一切顺利,则可以增加(可能逐渐增加)百分比,逐步替换旧版本。如在过程中出现任何问题,则可以中止并回滚到旧版本。最简单的方式,是随机选择百分比请求到金丝雀版本,但在更复杂的方案下,则可以基于请求的区域,用户或其他属性。

基于领域的专业水平,您可能想知道为什么需要 Istio 来支持金丝雀部署,因为像 Kubernetes 这样的平台已经提供了进行 版本上线金丝雀部署的方法。问题解决了吗 ?不完全是。虽然以这种方式进行部署可以在简单的情况下工作,但功能非常有限,特别是在大规模自动缩放的云环境中大流量的情况下。

Kubernetes 中的金丝雀部署

假设我们有一个已部署的 helloworld服务 v1版本,我们想要测试(或简单上线)新版本 v2。使用 Kubernetes,您可以通过简单地更新服务的 Deployment中的镜像并自动进行部署来 上线新版本的 helloworld服务。如果我们特能够小心保证在启动并且在仅启动一个或两个 v2 副本 暂停上线时有足够的 v1副本运行,则能够保持金丝雀发布对系统的影响非常小。后续我们可以观察效果,或在必要时进行 回滚。最好,我们也能够对 Deployment 设置 HPA,在上线过程中减少或增加副本以处理流量负载时,也能够保持副本比例一致。

尽管这种机制能够很好工作,但这种方式只适用于部署的经过适当测试的版本,也就是说,更多的是蓝/绿发布,又称红/黑发布,而不是 “蜻蜓点水“ 式的金丝雀部署。实际上,对于后者(例如,并没有完全准备好或者无意对外暴露的版本),Kubernetes 中的金丝雀部署将使用具有 公共 pod 标签的两个 Deployment 来完成。在这种情况下,我们不能再使用自动缩放器,因为是有由两个独立的自动缩放器来进行控制,不同负载情况下,副本比例(百分比)可能与所需的比例不同。

无论我们使用一个或者两个部署,使用 Docker,Mesos/Marathon 或 Kubernetes 等容器编排平台进行的金丝雀发布管理都存在一个根本问题:使用实例扩容来管理流量;版本流量分发和副本部署在上述平台中并独立。所有 pod 副本,无论版本如何,在 kube-proxy循环池中都被一视同仁地对待,因此管理特定版本接收的流量的唯一方法是控制副本比例。以小百分比维持金丝雀流量需要许多副本(例如,1% 将需要至少 100 个副本)。即使我们可以忽略这个问题,部署方式功能仍然非常有限,因为它只支持简单(随机百分比)金丝雀部署。如果我们想根据某些特定规则将请求路由到金丝雀版本上,我们仍然需要另一种解决方案。

使用 Istio

使用 Istio,流量路由和副本部署是两个完全独立的功能。服务的 pod 数量可以根据流量负载灵活伸缩,与版本流量路由的控制完全正交。这在自动缩放的情况下能够更加简单地管理金丝雀版本。事实上,自动缩放管理器仍然独立运行,其在响应因流量路由导致的负载变化与其他原因导致负载变化的行为上没有区别。

Istio 的 路由规则也带来了其他的便利;你可以轻松实现细粒度控制流量百分比(例如,路由 1% 的流量而不需要 100 个 pod),当然也可以使用其他规则来控制流量(例如,将特定用户的流量路由到金丝雀版本)。作为展示,让我们看一下采用这种方式部署 helloworld服务的简单便捷。

首先我们定义 helloworld服务,和普通 Kubernetes服务一样,如下所示:

      apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
  app: helloworld
spec:
  selector:
    app: helloworld
  ...

然后我们添加 2 个 Deployment,分别为版本 v1v2,这两个版本都包含服务选择标签 app:helloworld

      kind: Deployment
metadata:
  name: helloworld-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: helloworld
        version: v1
    spec:
      containers:
      - image: helloworld-v1
        ...
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: helloworld-v2
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: helloworld
        version: v2
    spec:
      containers:
      - image: helloworld-v2
        ...

需要注意的是,这与使用普通 Kubernetes 进行 金丝雀部署的方式完全相同,但是在 Kubernetes 方式下控制流量分配需要调整每个 Deployment 的副本数目。例如,将 10% 的流量发送到金丝雀版本(v2),v1 和 v2 的副本可以分别设置为 9 和 1。

但是在 启用 Istio的集群中,我们可以通过设置路由规则来控制流量分配。如将 10% 的流量发送到金丝雀版本本,我们可以使用 kubectl来设置以下的路由规则:

      $ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  hosts:
    - helloworld
  http:
  - route:
    - destination:
        host: helloworld
        subset: v1
        weight: 90
    - destination:
        host: helloworld
        subset: v2
        weight: 10
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: helloworld
spec:
  host: helloworld
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
EOF

当规则设置生效后,Istio 将确保只有 10% 的请求发送到金丝雀版本,无论每个版本的运行副本数量是多少。

部署中的自动缩放

由于我们不再需要保持副本比例,所以我们可以安全地设置 Kubernetes HPA来管理两个版本 Deployment 的副本:

      $ kubectl autoscale deployment helloworld-v1 --cpu-percent=50 --min=1 --max=10
deployment "helloworld-v1" autoscaled
      $ kubectl autoscale deployment helloworld-v2 --cpu-percent=50 --min=1 --max=10
deployment "helloworld-v2" autoscaled
      $ kubectl get hpa
NAME           REFERENCE                 TARGET  CURRENT  MINPODS  MAXPODS  AGE
Helloworld-v1  Deployment/helloworld-v1  50%     47%      1        10       17s
Helloworld-v2  Deployment/helloworld-v2  50%     40%      1        10       15s

如果现在对 helloworld服务上产生一些负载,我们会注意到,当扩容开始时, v1扩容副本数目远高于 v2,因为 v1pod 正在处理 90% 的负载。

      $ kubectl get pods | grep helloworld
helloworld-v1-3523621687-3q5wh   0/2       Pending   0          15m
helloworld-v1-3523621687-73642   2/2       Running   0          11m
helloworld-v1-3523621687-7hs31   2/2       Running   0          19m
helloworld-v1-3523621687-dt7n7   2/2       Running   0          50m
helloworld-v1-3523621687-gdhq9   2/2       Running   0          11m
helloworld-v1-3523621687-jxs4t   0/2       Pending   0          15m
helloworld-v1-3523621687-l8rjn   2/2       Running   0          19m
helloworld-v1-3523621687-wwddw   2/2       Running   0          15m
helloworld-v1-3523621687-xlt26   0/2       Pending   0          19m
helloworld-v2-4095161145-963wt   2/2       Running   0          50m

如果更改路由规则将 50% 的流量发送到 v2,我们则可以在短暂的延迟后注意到 v1副本数的减少,而 v2副本数相应地增加。

      $ kubectl get pods | grep helloworld
helloworld-v1-3523621687-73642   2/2       Running   0          35m
helloworld-v1-3523621687-7hs31   2/2       Running   0          43m
helloworld-v1-3523621687-dt7n7   2/2       Running   0          1h
helloworld-v1-3523621687-gdhq9   2/2       Running   0          35m
helloworld-v1-3523621687-l8rjn   2/2       Running   0          43m
helloworld-v2-4095161145-57537   0/2       Pending   0          21m
helloworld-v2-4095161145-9322m   2/2       Running   0          21m
helloworld-v2-4095161145-963wt   2/2       Running   0          1h
helloworld-v2-4095161145-c3dpj   0/2       Pending   0          21m
helloworld-v2-4095161145-t2ccm   0/2       Pending   0          17m
helloworld-v2-4095161145-v3v9n   0/2       Pending   0          13m

最终结果与 Kubernetes Deployment 上线非常相似,只是整个流程并不是集中地进行编排和管理。相反,我们看到几个组件独立完成工作,虽然它们有因果关系。

有一点不同的是,当我们停止负载时,无论设置路由规则如何,两个版本的副本数最终都会缩小到最小值(1)。

      $ kubectl get pods | grep helloworld
helloworld-v1-3523621687-dt7n7   2/2       Running   0          1h
helloworld-v2-4095161145-963wt   2/2       Running   0          1h

聚焦金丝雀测试

如上所述,Istio 路由规则可用于根据特定规则准进行流量路由,从而能够提供更复杂的金丝雀部署方案。例如,与简单通过将金丝雀版本暴露给任意百分比的用户方式不同,我们希望在内部用户上尝试,甚至可能只是内部用户的一部分。

以下命令可将特定网站上 50% 的用户流量路由到金丝雀版本,而其他用户则不受影响:

      $ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  hosts:
    - helloworld
  http:
  - match:
    - headers:
        cookie:
          regex: "^(.*?;)?(email=[^;]*@some-company-name.com)(;.*)?$"
    route:
    - destination:
        host: helloworld
        subset: v1
        weight: 50
    - destination:
        host: helloworld
        subset: v2
        weight: 50
  - route:
    - destination:
        host: helloworld
        subset: v1
EOF

和以前一样,绑定到 2 个版本 Deployment 的自动缩放器会相应地自动管理副本,但这对流量分配没有影响。

总结

本文中,我们看到了 Istio 如何支持通用可扩展的金丝雀部署,以及与 Kubernetes 部署的差异。Istio 服务网格提供了管理流量分配所需的基础控制,并完全独立于部署缩放。这允许简单而强大的方式来进行金丝雀测试和上线。

支持金丝雀部署的智能路由只是 Istio 的众多功能之一,它将使基于大型微服务的应用程序的生产部署变得更加简单。查看 istio.io了解更多信息。

可在 此处查看示例代码。

相关 [istio 金丝雀] 推荐:

使用 Istio 进行金丝雀部署

- -
本篇博客最后更新时间 2018 年 5 月 16 号,采用了最新版本的流量管理模型. Istio项目的一大好处就是为服务金丝雀方式部署提供了控制便利. 金丝雀部署(或上线)背后的想法是通过让一小部分用户流量引入的新版本进行测试,如果一切顺利,则可以增加(可能逐渐增加)百分比,逐步替换旧版本. 如在过程中出现任何问题,则可以中止并回滚到旧版本.

使用istio对spring cloud kubernetes项目进行金丝雀发布_水中加点糖-CSDN博客_istio springcloud

- -
(一)基础k8s yaml脚本发布. (二)helm+shell脚本优化大量冗余配置发布. (三)jenkins用户审核的流水化方式部署. (四)service mesh(istio)服务网格化发布. (五)istio对项目进行金丝雀部署. spring-cloud-kubernetes之开发环境搭建.

istio 原理简介

- - 掘金 架构
由于 istio 自 1.5 版本以后架构上有了较大变化,控制面从多组件变成了单体的 istiod 组件,所以下文会先介绍 1.5 之前的架构,再介绍 1.5 之后的,是一个由繁到简的过程. istio 1.5 之前架构. Istio 的架构分为控制平面和数据平面. 数据平面:由一组智能代理(Envoy)以 sidecar 模式部署,协调和控制所有服务之间的网络通信.

Istio 常见的 10 个异常分析

- - DockOne.io
本文总结了使用 Istio 常见的 10 个异常. Istio 支持多平台,不过 Istio 和 Kubernetes 的兼容性是最优的,不管是设计理念,核心团队还是社区, 都有一脉相承的意思. 但 Istio 和 Kubernetes 的适配并非完全没有冲突,一个典型问题就是 Istio 需要 Kubernetes Service 按照协议进行端口命名(Port Naming).

Istio究竟是干嘛的? - 知乎

- -
当微服务架构体系越来越复杂的时候,需要将“业务服务”和“基础设施”解耦,将一个微服务进程一分为二:. 一个进程实现业务逻辑,biz,即上图白色方块. 一个进程实现底层技术体系,proxy,即上图蓝色方块,负载均衡、监控告警、服务发现与治理、调用链…等诸多基础设施,都放到这一层实现. biz不管是调用服务,还是提供服务,都只与本地的proxy进行本地通信.

Istio 中的服务和流量的抽象模型

- - IT瘾-dev
本文介绍了 Istio 和 Kubernetes 中的一些服务和流量的抽象模型. 虽然 Istio 一开始确定的抽象模型与对接的底层平台无关,但目前来看基本绑定 Kubernetes,本文仅以 Kubernetes 说明. 另外在 ServiceMesher 社区中最近有很多关于 Istio、Envoy、Kubernetes 之中的服务模型关系的讨论,本文作为一个开篇说明,Kubernetes 和 Isito 之间有哪些共有的服务模型,Istio 在 Kubernetes 的服务模型之上又增加了什么,为什么说 Kubernetes service 存在的意义仅剩下做服务发现.

洞若观火:使用 OpenTracing 增强 Istio 的调用链跟踪

- - IT瘾-dev
分布式调用跟踪和Opentracing规范. 什么是Opentracing. CNCF Opentracing项目. Opentracing概念模型. Opentracing数据模型. Istio对分布式调用跟踪的支持. 使用Opentracing来传递分布式跟踪上下文. 在Istio调用跟踪链中加入方法级的调用跟踪信息.

Service Mesh 最火项目: Istio 架构解析

- - IT瘾-tuicool
Istio 是一个开源的服务网格,可为分布式微服务架构提供所需的基础运行和管理要素. 随着各组织越来越多地采用云平台,开发者必须使用微服务设计架构以实现可移植性,而运维人员必须管理包含混合云部署和多云部署的大型分布式应用. Istio 采用一种一致的方式来保护、连接和监控微服务,降低了管理微服务部署的复杂性.

4个步骤排查istio服务网格的网络问题

- - DockOne.io
对 istio 用户而言,最常见的场景之一是将 istio 用作 ingress 网关,通过其暴露微服务给外部客户端访问. 一种是只运行业务服务的容器,不携带 sidecar. 另一种是运行携带 sidecar 的 Pod,业务服务和 ingress 网关之间建立 mTLS 双向认证进行通信. 最近,笔者帮一位 istio 用户排查问题:为什么通过 istio ingress 网关暴露的服务不能被 istio 网格外部的 CURL 客户端访问到.

从一个例子入手Istio - luozhiyun - 博客园

- -
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:. 本文使用的Istio源码是 release 1.5. 本篇是Istio系列的第一篇,希望大家接下来能和我一起学习进步. Klegs的作品,颜色有一种深邃感,我很喜欢. 这篇文章是Istio系列文章的开篇,主要从一个例子入手讲一下Istio,并讲解一些基础概念,后面会基于这个例子来展开讲解istio里面的实现原理.