服务网格
服务网格(Service Mesh)是由Buoyant公司的CEO William Morgan发起的,他对服务网格的定义如下:
- 专用基础设施层:独立的运行单元。
- 包括数据层和控制层:数据层负责交付应用请求,控制层控制服务如何通信。
- 轻量级透明代理:实现形式为轻量级网络代理。
- 处理服务间通信:主要目的是实现复杂网络中的服务间通信。
- 可靠地交付服务请求:提供网络弹性机制,确保可靠交付请求。
- 与服务部署一起,但服务无须感知:尽管跟应用部署在一起,但对应用是透明的。
服务网格的基本概念
在设计并开发程序时,主要分为两部分功能:业务逻辑和网络功能。对于一个开发者而言,需要关注的问题是业务逻辑而非网络功能。但是在一个项目开发中,由于涉及很多微服务之间的通信,因此就不得不考虑网络上的问题,比如负载均衡、服务发现、错误重试等。
服务网格的诞生将程序开发的网络功能和程序本身解耦,网络功能下沉到基础架构,由服务网格实现服务之间的负载均衡等功能,并且除网络功能外,还提供了其他更高级的功能,比如全链路加密、监控、链路追踪等
Service Mesh 是一个用于处理服务和服务之间通信的基础设施层,它负责为构建复杂的云原生应用传递可靠的网络请求,并为服务通信实现了微服务所需的基本组件功能,例如服务发现、负载均衡、监控、流量管理、访问控制等。在实践中,服务网格通常实现为一组和应用程序部署在一起的轻量级的网络代理,但对应用程序来说是透明的。
如图,绿色方块为应用服务,蓝色方块为Sidecar Proxy,应用服务之间通过Sidecar Proxy 进行通信,整个服务通信形成图中的蓝色网络连线,图中所有蓝色部分就形成一个网络,这个就是服务网格名字的由来
服务网格的功能
服务网格作为透明代理,可以运行于任何基础设施环境,而且和应用非常靠近,服务网格的功能大致如下:
- 负载均衡:运行环境中的微服务实例通常处于动态变化状态,而且经常可能出现个别实例不能正常提供服务、处理能力减弱、卡顿等现象。但由于所有请求对服务网格来说是可见的,因此可以通过提供高级负载均衡算法来实现更加智能、高效的流量分发,以降低延时,提高可靠性。
- 服务发现:以微服务模式运行的应用变更非常频繁,应用实例的频繁增加和减少带来的问题是,如何精确地发现新增实例以及避免将请求发送给已不存在的实例而变得更加复杂。服务网格可以提供简单、统一、平台无关的多种服务发现机制,如基于DNS、键-值对(key-value pair)存储的服务发现机制。
- 熔断:在动态环境中,服务实例中断或不健康导致的服务中断可能会经常发生,这就要求应用或者其他工具具有快速监测并从负载均衡池中移除不提供服务实例的能力,这种能力也称熔断,以此使得应用无须消耗更多不必要的资源不断地尝试,而是快速失败或者降级,从而避免一些潜在的关联性错误,而服务网格可以很容易地实现基于请求和连接级别的熔断机制。
- 动态路由:随着服务提供商以提供高稳定性、高可用性及高SLA服务为主要目标,出现的各种应用部署策略都尽可能达到无服务中断部署,以此避免变更而导致服务的中断和稳定性降低,例如Blue/Green部署、Canary部署,但是实现这些高级部署策略通常非常困难。关于应用部署策略可参考https://thenewstack.io/deployment-strategies/的内容,其对各种部署策略做了详细的比较。如果运维人员想要轻松地将应用流量从staging环境切换到生产环境,从一个版本到另一个版本,或者从一个数据中心到另一个数据中心,甚至可以通过一个中心控制层控制多少比例的流量被切换。服务网格提供的动态路由机制和特定的部署策略(如Blue/Green部署)结合起来,实现上述目标将会变得更加容易。
- 安全通信:无论何时,安全在整个公司、业务系统中都占据着举足轻重的位置,也是非常难以实现和控制的部分。而在微服务环境中,不同的服务实例间的通信变得更加复杂,那么如何保证这些通信是在安全、授权的情况下进行的就非常重要。通过将安全机制(如TLS加解密和授权)实现在服务网格上,不仅可以避免在不同应用上的重复实现,而且很容易在整个基础设施层更新安全机制,甚至无须对应用做任何操作。
- 多语言支持:服务网格作为独立运行的透明代理,很容易支持多语言。
- 多协议支持:同多语言支持一样,实现多协议支持也非常容易。
- 指标和分布式追踪:服务网格对整个基础设施层的可见性使得它不仅可以暴露单个服务的运行指标,而且可以暴露整个集群的运行指标。
- 重试和最后期限:服务网格的重试功能可以避免将其嵌入业务代码中,同时最后期限使得应用允许一个请求的最长生命周期,而不是无休止地重试。
Service Mesh特点
- 治理能力独立(Sidecar)
- 应用程序无感知
- 服务通信的基础设施层
- 解耦应用程序的重试/超时、监控、追踪和服务发现
服务网格产品
常见的服务网格产品如下:
- Linkerd:是Buoyant公司在2016年率先开源的高性能网络代理程序,它的出现标志着服务网格时代的开始。
- Envoy:同Linkerd一样,Envoy也是一款高性能的网络代理程序,为云原生应用而设计。
- Istio:Istio受Google、IBM、Lyft及RedHat等公司的大力支持和推广,于2017年5月发布,底层为Envoy。
- Conduit:2017年12月发布,是Buoyant公司的第二款服务网格产品,根据Linkerd在生产线上的实际使用经验而设计,并以最小复杂性作为设计基础。
Istio的基本概念
虽然Linkerd是最先发布的服务网格产品,但是Istio有Google、RedHat等公司的大力支持,并且Istio可以和Kubernetes无缝集成,所以目前Istio的发展“势头”已经赶超了Linkerd,成为业界主流的服务网格产品。
随着技术架构的迭代,将单体应用拆分成了微服务,由之前的一个应用变成了成百上千的微服务,会给DevOps团队带来巨大压力。同时,运维人员也要管理极端且庞大的混合云或多云的环境,服务之间的链路、控制、安全和观察将会是非常棘手的问题。
Istio有助于降低应用部署的复杂性,并减轻开发团队的压力。Istio是一个完全开源的服务网格产品,可以透明地分层到现有的分布式应用程序上。同时,Istio拥有可以集成任何日志、遥测和策略系统的API接口。Istio的多样化能够高效地运行于分布式微服务架构中,并提供保护、链接和监控服务的统一方法。
Istio提供了一种简单的方式来为已部署的服务建立网络,该网络具有负载均衡、服务间认证、监控等功能。更改功能和介绍请参考Istio官方文档:https://istio.io/latest/docs/
Istio概述
•连接(Connect)
-流量管理
-负载均衡
-灰度发布
•安全(Secure)
-认证
-鉴权
•控制(Control)
-限流
-ACL
•观察(Observe)
-监控
-调用链
istio和kubenetes可以较好的完成对微服务项目的治理
Istio的架构
在Istio1.5版本发生了一个重大变革,彻底推翻原有控制平面的架构,将有原有多个组件整合为单体结构“istiod”,同时废弃了Mixer 组件,如果你正在使用之前版本,必须了解这些变化。
Istio服务网格从逻辑上分为数据平面和控制平面两部分:
我们使用之后的版本,接下来我们对每个组件进行介绍。
· 数据平面:由一组Sidecar方式部署的智能代理(Envoy)组成,这些代理可以调节和控制微服务及Mixer之间所有的网络通信,还可以收集和报告网格流量的遥测数据,在Kubernetes中和应用的容器处于同一个Pod。
· 控制平面:负责管理和配置代理来路由流量,由管理员创建的Istio资源会解析成相关的配置下发到数据平面。
1.Envoy
Istio的数据平面使用的是Envoy,Envoy是以C++开发的高性能代理,用于调解服务网格中所有服务的所有入站和出站流量。Envoy代理是唯一一个与数据平面流量交互的Istio组件。
Envoy通过Sidecar的方式和业务应用部署在同一个Pod内,在逻辑上为服务增加了许多内置特性,例如:
- 动态服务发现。
- 负载均衡。
- TLS终止。
- HTTP/2 & gRPC代理。
- 熔断器。
- 健康检查、基于百分比流量拆分的灰度发布。
- 故障注入。
- 丰富的度量指标。
使用Sidecar的方式将Envoy注入业务Pod,可以让Istio执行策略决策,并提取丰富的遥测数据,然后将这些数据发送到监控系统,以提供整个网格的监控面板。同时,Sidecar模式还允许向现有的环境中添加Istio功能,并且不需要重新设计架构或重写代码。
由Envoy代理启用的一些Istio功能和任务包括:
- 流量控制功能:通过丰富的HTTP、gRPC、WebSocket和TCP流量路由规则来执行细粒度的流量控制。
- 网络弹性功能:重试、故障转移、熔断器和故障注入功能。
- 安全性和身份认证功能:执行安全策略,通过配置强制实行API的访问控制和速率限制。
- 遥测:基于WebAssembly的可插拔扩展模型,允许通过自定义策略执行和生成网格流量的遥测。
2.Istiod
Istiod为Istio的控制平面,提供服务发现、配置、证书管理、加密通信和认证功能。早期的Istio控制平台并没有Istiod这个容器,而是由Mixer(新版本已废弃)、Pilot、Citadel共同组成的,后来为了简化Istio的架构,将其合并为Istiod,所以对于新版本的Istio(v1.5+),部署后仅能看到Istiod一类Pod。
从架构图可以看出Istiod由Pilot、Citadel和Galley组成,三者分别实现的功能如下:
· Pilot:为Envoy Sidecar提供服务发现的功能,为智能路由(例如A/B测试、金丝雀部署等)和弹性(超时、重试、熔断器等)提供流量管理功能。Pilot将控制流量行为的高级路由规则转换为特定于Envoy的配置,并在运行时将它们传播到Sidecar。Pilot将平台特定的服务发现机制抽象化,并将其合成为符合Envoy数据平面API的任何Sidecar都可以使用的标准格式,这种松耦合使得Istio能够在多种环境下运行(如Kubernetes、Consul、Nomad),同时保持用于流量管理的相同操作界面。
· Citadel:通过内置身份和凭证管理可以提供强大的服务与服务之间的最终用户身份验证,可用于升级服务网格中未加密的流量,并为运维人员提供基于服务标识而不是网络控制的强制执行策略的能力。从0.5版本开始,Istio支持基于角色的访问控制,以控制服务访问。
· Galley:负责配置管理的组件,用于验证配置信息的格式和正确性。Galley使用网格配置协议(Mesh Configuration Protocol)和其他组件进行配置的交互。
Istio的核心资源
和Kubernetes资源一致,Istio的配置也是通过声明式自定义资源配置来加载的。常用的核心资源有VirtualService、DestinationRule、Gateway、ServiceEntry、Sidecar等,限于篇幅,只对最常用的VirtualService、DestinationRule、Gateway进行讲解和使用。
VirtualService
VirtualService(虚拟服务):
- 定义路由规则
- 描述满足条件的请求去哪里
Istio最为重要的一个概念就是VirtualService(虚拟服务),和Kubernetes的Service类似,但是两种并不是对等的资源类型。VirtualService基于Istio和对应平台提供的基本连通性和服务发现能力,将请求路由到对应的目标。每一个VirtualService包含一组路由规则,Istio将每个请求根据路由匹配到指定的目标地址。
和Kubernetes的Service不同的是,Kubernetes的Service只提供了最简单的服务发现和负载均衡的能力,如果想要实现更加细粒度的流量分发,比如灰度、蓝绿等流量管理,Kubernetes的Service显得比较吃力或者无法实现,而VirtualService在流量管理方面有着比较好的灵活性和有效性,可以在代码零侵入的情况下实现更加丰富的流量管理,比如灰度等。
一个典型的用例是将流量发送到被指定服务的不同版本,比如80%的流量发送给v1版本,20%的流量发送给新版本。或者将某个登录用户指定到新版本,其他用户指定到旧版本,可以实现AB测试等功能。
接下来看一个VirtualService的配置示例,根据特定用户将流量分发至不同版本:
· apiVersion:对应的API版本。
· kind:创建的资源类型,和Kubernetes的Service类似。
· metadata:元数据,和Kubernetes资源类似,可以定义annotations、labels、name等。
· metadata.name:VirtualService的名称。
· spec:关于VirtualService的定义。
· spec.hosts:VirtualService的主机,即用户指定的目标或路由规则的目标,客户端向服务端发送请求时使用的一个或多个地址,可以是IP地址、DNS名称,或者是依赖于底层平台的一个简称(比如Kubernetes的Service短名称),隐式或显式地指向一个完全限定域名(FQDN),当然也可以是一个通配符“*”或*.taobao.com。
· spec.http:路由规则配置,用来指定流量的路由行为,通过该处的配置将HTTP/1.1、HTTP2和gRPC等流量发送到hosts字段指定的目标。
· spec.http[].match:路由规则的条件,可以根据一些条件制定更加细粒度的路由。比如当前示例的headers,表示匹配headers里面的end-user字段,并且值为jason的请求。
· route:路由规则,destination字段指定了符合此条件的流量的实际目标地址。比如该示例的请求,如果请求头包含end-user=jason字段,则该请求会被路由到reviews的v2版本。如果没有匹配到该请求头,则流量会被路由到v3版本(版本由DestinationRule划分)。
注意:VirtualService路由规则按照从上往下的顺序进行匹配,第一个规则有最高的优先级,如果不满足第一个路由规则,则流量会选择下一个规则。
除了上述的路由匹配外,VirtualService也支持域名+路径的方式进行路由。比如后端有两个服务,一个是reviews,通过bookinfo.com/reviews访问;另一个是ratings,通过bookinfo.com/ratings访问。此时可以配置VirtualService如下:
VirtualService支持的匹配有很多,除了上述的uri和headers外,还支持port、scheme、sourceLabels、method等方式,具体可以参考:https://istio.io/latest/docs/reference/config/networking/virtual-service/#HTTPMatchRequest。
除了上述功能外,VirtualService也支持HTTP重定向、HTTP Rewrtite、HTTP重试、HTTP流量镜像、故障注入、解决跨域等功能,具体可以参考:https://istio.io/latest/docs/reference/config/networking/virtual-service/
DestinationRule
Istio另一个比较重要的资源是DestinationRule(目标规则),初学者第一次接触Istio时,往往无法区分VirtualService和DestinationRule,在实际使用时很容易混淆两者的概念和用途。
我们可以将VirtualService理解为Kubernetes Service层面,DestinationRule理解为Service后端真实的目标地址,即VirtualService用于Service层面的路由管控,DestinationRule用于对后端真实的服务再做进一步的划分。比如存在一个Service名为paycenter,指向后端多个paycenter的Pod(该Pod可能是不同的Deployment创建的),而DestinationRule可以对后端的多个Pod区分新旧版本,划分成不同的subset,之后VirtualService可以针对不同的版本进行流量管控。
比如刚才的示例:
此时对应subset的v2和v3就是由DestinationRule进行划分的
配置示例如下:
DestinationRule可以根据Pod不同的标签划分版本,比如存在3个Deployment,具有以下标签:
1)Deployment V1:app=reviews, version=v1。
2)Deployment V2:app=reviews, version=v2。
3)Deployment V3:app=reviews, version=v3。
这3个Deployment创建的Pod都会有一个app=reviews标签,并且有一个version字段的标签。此时DestinationRule就可以根据version标签进行版本的划分,再结合VirtualService就可以实现更加高级且细粒度的流量分发策略,比如灰度/金丝雀发布、A/B测试等。
当然,除了划分不同的版本外,DestinationRule也支持服务熔断、更多的负载均衡策略、TLS认证等功能,具体可以参考:https://istio.io/latest/docs/reference/config/networking/destination-rule/。
Gateway
Istio同样支持网关功能,可以使用Gateway在网格最外层接收HTTP/TCP流量,并将流量转发到网格内的某个服务。
- IngressGateway:接收外部访问,并将流量转发到网格内的服务。
- EgressGateway:网格内服务访问外部应用。
在安装Istio时,可以在istio-system命名空间下安装ingressgateway的Pod,用来充当Ingress Gateway。其中Ingress Gateway为入口网关,可以将网格内的服务“暴露”出去,一般和VirtualService配置使用,并配置一个可以被外部服务访问的域名,从而外部服务可以通过该域名访问网格内的服务。
配置Gateway和Istio其他资源类似,kind指定为Gateway即可。比如配置一个VirtualService和Gateway实现对网格内的某个服务进行发布,首先创建一个Gateway,代码如下:
- selector:必选字段。选择由哪个ingressgateway的Pod发布服务,默认为istio-system命名空间下具有istio=ingressgateway标签的Pod。
- servers:必选字段。表示发布的服务列表,用于描述发布服务的属性,比如代理监听的端口、协议和端口的名称等。
- hosts:必选字段。Gateway发布的服务地址,也就是允许用户访问的域名,可以配置为“*”,表示任何域名都可以被代理,本示例为httpbin.example.com可被路由。
之后配置一个VirtualService与之匹配,即可通过该域名访问VirtualService配置的服务。比如将httpbin.example.com的/status和/delay代理到httpbin服务的8000端口:
Gateway(网关)与Kubernetes Ingress有什么区别?
Kubernetes Ingress与Getaway都是用于为集群内服务提供访问入口,但Ingress主要功能比较单一,不易于Istio现有流量管理功能集成。
目前Gateway支持的功能:
- 支持L4-L7的负载均衡
- 支持HTTPS和mTLS
- 支持流量镜像、熔断等
之后将域名解析至ingressgateway Pod的Service上即可访问该域名,本示例为概念部分,具体演示可参考实践部分。
ServiceEntry
ServiceEntry(服务入口):将网格外部服务添加到网格内,像网格内其他服务一样管理。
安装Istio
前面我们介绍了Istio的基本概念和配置示例,接下来将在Kubernetes集群中安装Istio,并在接下来的章节中演示Istio比较常用的流量管理策略。
Istio与K8s集成流程
访问流程图
Istio官方提供了多种安装方式,比如通过YAML文件、Helm、Operator安装等,由于Operator方式在官方文档中的说明比较齐全,并且Operator是Kubernetes未来管理较复杂的应用平台比较推荐的方式,因此这里将使用Operator方式在Kubernetes集群中安装Istio平台。
使用Operator部署Istio
这里Istio版本为1.11.4,读者可按需安装其他版本。
下载 Istio 的安装包,解压后,将 Istio 的客户端工具istioctl移动到/usr/local/bin目录下:
wget https://github.com/istio/istio/releases/download/1.11.4/istio-1.11.4-linux-amd64.tar.gz
tar xf istio-1.11.4-linux-amd64.tar.gz
mv istio-1.11.4/bin/istioctl /usr/local/bin/
istioctl version
接下来安装Istio的Operator,可以使用istioctl一键部署:
istioctl operator init
出现Installation complete后,可以查看Pod是否正常:
kubectl get po -n istio-operator
之后通过定义IstioOperator资源在Kubernetes中安装Istio:
vim istio-operator.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
namespace: istio-system
name: example-istiocontrolplane
spec:
values:
global:
proxy:
autoInject: disabled # 关闭自动注入
addonComponents:
pilot:
enabled: true # 开启 Pilot 组件
components: # 自定义组件配置
ingressGateways: # 自定义 ingressGateway 配置
- name: istio-ingressgateway
enabled: true # 开启 ingressGateway
k8s: # 自定义 ingressGateway 的 Kubernetes 配置
service: # 考虑到不是所有人都有 LoadBalancer,所以将 Service 类型改成 NodePort
type: NodePort
ports:
- port: 15020
nodePort: 30520
name: status-port
- port: 80 # 流量入口 80 端口映射到 NodePort 的 30080,之后通过节点 IP+30080 即可访问 Istio 服务
nodePort: 30080
name: http2
targetPort: 8080
- port: 443
nodePort: 30443
name: https
targetPort: 8443
安装Istio:
istioctl manifest apply -f istio-operator.yaml
查看创建的Service和Pod:
kubectl get svc,pods -n istio-system
配置自动注入
Istio管理流量需要在被管理的Pod上添加一个名为istio-proxy的Sidecar,可以修改APIServer的配置,让其支持自动注入。
修改APIServer的配置文件,添加MutatingAdmissionWebhook、ValidatingAdmissionWebhook(如果版本大于1.16,默认已经开启):
二进制部署方式的集群文件在 /usr/lib/systemd/system/kube-apiserver.service中,重启服务systemctl daemon-reload && systemctl restart kube-apiserver.service
接下来创建一个测试的Namespace,并添加一个istio-injection=enabled的标签,之后在该Namespace下创建的Pod就会被自动注入Istio的Proxy。
创建Namespace并添加Label:
kubectl create ns istio-test
kubectl label namespace istio-test istio-injection=enabled
切换目录至Istio的安装包,然后创建测试应用,此时创建的Pod会被自动注入一个istio-proxy的容器:
kubectl apply -f samples/sleep/sleep.yaml -n istio-test
查看部署的容器:
kubectl -n istio-test get pod
可视化工具Kiali
Kiali为Istio提供了可视化的界面,可以在Kiali上观测流量的走向、调用链,同时可以使用Kiali进行配置管理,给用户带来了很好的体验。
提供以下功能:
•Istio 的可观察性控制台
•通过服务拓扑帮助你理解服务网格的结构
•提供网格的健康状态视图
•具有服务网格配置功能
接下来在Kubernetes中安装Kiali工具,首先进入Istio的安装包目录:
kubectl create -f samples/addons/kiali.yaml
查看部署状态:
之后将Service类型改成NodePort,或者配置Ingress,即可访问Kiali服务
配置 ingress:vim kiali-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kiali-ingress
namespace: istio-system
annotations:
kubernetes.io/ingress.class: "nginx" #声名需要使用nginx方式解析ingress
spec:
rules: # 一个Ingress可以配置多个rules
- host: kiali.test.com # 域名配置,可以不写(不建议),支持匹配,一般写法:*.bar.com
http:
paths: # 相当于nginx的location配合,同一个host可以配置多个path 例如“/”或“/abc”
- path: "/"
pathType: Prefix
backend:
service:
name: kiali
port:
number: 20001
这里遇到报错:解决方法:yum -y install socat
下面这个报错是自动注入sidecar问题:
解决方式:https://istio.io/latest/zh/docs/ops/common-problems/injection/
如果上述方式未能解决问题,请修改istioctl版本,详见https://istio.io/latest/zh/docs/setup/install/operator/
除了Kiali之外,还需要一个链路追踪的工具,Jaeger是Uber开源的分布式追踪系统,用于微服务的监控和全链路追踪。,安装该工具可以在Kiali的Workloads页面查看某个服务的Traces信息。直接安装即可:
Prometheus和Grafana
Istio默认暴露了很多监控指标,比如请求数量统计、请求持续时间以及Service和工作负载的指标,这些指标可以使用Prometheus收集,使用Grafana展示。
Istio内置了Prometheus和Grafana的安装文件,直接安装即可(也可以使用外置的Prometheus和Grafana):
查看创建的Pod和Service:
以同样的方式将Grafana的Service改成NodePort或者添加Ingress,之后访问即可
vim grafana-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: grafana-ingress
namespace: istio-system
annotations:
kubernetes.io/ingress.class: "nginx" #声名需要使用nginx方式解析ingress
spec:
rules: # 一个Ingress可以配置多个rules
- host: kiali-grafana.test.com # 域名配置,可以不写(不建议),支持匹配,一般写法:*.bar.com
http:
paths: # 相当于nginx的location配合,同一个host可以配置多个path 例如“/”或“/abc”
- path: "/"
pathType: Prefix
backend:
service:
name: grafana
port:
number: 3000
Istio Grafana 安装时预配置了以下仪表盘:
1、Istio 控制平面仪表盘(Istio Control Plane Dashboard)
从 Istio 控制平面仪表盘,我们可以监控 Istio 控制平面的健康和性能。Istio Control Plane Dashboard 仪表盘将向我们展示控制平面的资源使用情况(内存、CPU、磁盘、Go routines),以及关于 Pilot、Envoy 和 Webhook 的信息。
2、Istio 网格仪表盘(Istio Mesh Dashboard)
网格仪表盘为我们提供了在网格中运行的所有服务的概览。仪表盘包括全局请求量、成功率以及 4xx 和 5xx 响应的数量。
3、Istio 性能仪表盘(Istio Performance Dashboard)
性能仪表盘向我们展示了 Istio 主要组件在稳定负载下的资源利用率。
4、Istio 服务仪表盘(Istio Service Dashboard)
服务仪表盘允许我们在网格中查看服务的细节。我们可以获得关于请求量、成功率、持续时间的信息,以及显示按来源和响应代码、持续时间和大小的传入请求的详细图表。
5、Istio Wasm 扩展仪表盘(Istio Wasm Extension Dashboard)
Istio Wasm 扩展仪表盘显示与 WebAssembly 模块有关的指标。从这个仪表盘,我们可以监控活动的和创建的 Wasm 虚拟机,关于获取删除 Wasm 模块和代理资源使用的数据。
6、Istio 工作负载仪表盘(Istio Workload Dashboard)
这个仪表盘为我们提供了一个工作负载的详细指标分类。
由于集群并未部署Istio的测试用例,因此Grafana的部分图表可能并没有数据。
Istio流量治理实践
通过前面的学习,我们已经成功安装了Istio,并且学习了Istio的核心资源。从本节开始将会进一步完善Istio的配置,用以实现各种需求和流量管理。
接下来的示例将采用官方的Bookinfo进行测试,它由4个单独的微服务构成,可以用来演示多种Istio的特性。这个应用模仿的是一个在线书店的平台,可以分类显示一本书描述、细节(ISBN、页数等)以及这本书的一些评论。
Bookinfo应用分为4个单独的微服务:
· productpage:这个微服务会调用details和reviews两个微服务,用来生成页面。
· details:这个微服务包含图书的信息。
· reviews:这个微服务包含图书相关的评论,它还会调用ratings微服务。
· ratings:ratings微服务中包含由图书评价组成的评级信息。
服务 | 说明 | 调用服务 |
productpage | 主页 | reviews、details |
reviews | 评论内容 | ratings |
details | 详细内容 | |
ratings | 评分 |
除此之外,reviews微服务还分为3个版本:
· v1版本:不会调用ratings服务,即不会在页面显示书的评分。
· v2版本:会调用ratings服务,并使用1~5个黑色星形图标来显示评分信息。
· v3版本:会调用ratings服务,并使用1~5个红色星形图标来显示评分信息。
部署测试用例
首先在Kubernetes集群中部署Bookinfo项目。Istio提供了用于测试功能的应用程序Bookinfo,可以直接通过以下命令创建Bookinfo(本次将测试用例部署至Bookinfo命名空间):
kubectl create ns bookinfo
kubectl label ns bookinfo istio-injection=enabled
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -n bookinfo
查看部署的Pod和Service:
之后可以通过productpage Service的ClusterIP访问Bookinfo项目:
接下来创建Istio的Gateway和VirtualService实现域名访问Bookinfo项目。
首先创建Gateway,假设域名是bookinfo.kubeasy.com。Gateway配置如下:
book-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: bookinfo-gateway
namespace: bookinfo
spec:
selector:
istio: ingressgateway # 使用默认的istio ingress gateway
servers :
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "bookinfo.kubeasy.com" # 发布域名
接下来配置VirtualService,实现对不同微服务的路由:
book-VirtualService.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
namespace: bookinfo
spec:
hosts:
- "bookinfo.kubeasy.com"
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products
route:
- destination:
host: productpage
port:
number: 9080
提示:上述对于uri的匹配都指向了productpage,在实际使用时,可以将不同的uri指向不同的Service。
官方示例已经提供了该文件,修改Gateway和VirtualService的hosts为bookinfo.kubeasy.com,修改名称空间,然后创建即可(也可以直接应用上面的两个yaml):
查看资源:
接下来将域名bookinfo.kubeasy.com解析至集群任意一个安装了kube-proxy的节点IP上,然后通过ingressgateway的Service的NodePort即可访问Bookinfo:
绑定hosts后,通过bookinfo.kubeasy.com+ingressgateway 80端口的NodePort即可访问该服务,比如本示例的bookinfo.kubeasy.com:30080/productpage
多次刷新可以看到Reviewer处的星星会在黑色、红色和消失之间来回替换,是因为之前部署了3个不同版本的reviews,每个版本具有不同的显示效果。
此时通过Kiali页面可以看到Bookinfo的调用链路,多刷新几次,时间尽量选在 Last 1h 及以上
接下来通过Istio提供的网络功能实现微服务之间的灰度、熔断、故障注入等高级功能。
Istio实现灰度部署
首先对于发布不了解的,可以看一下文章 什么是蓝绿部署、滚动发布和灰度发布?
下面是对于主流发布方案的一些总结:
主流发布方案:
- 蓝绿发布
- 滚动发布
- 灰度发布(金丝雀发布)
- A/B Test
蓝绿发布
项目逻辑上分为AB组,在项目升级时,首先把A组从负载均衡中摘除,进行新版本的部署。B组仍然继续提供服务。A组升级完成上线,B组从负载均衡中摘除。
特点:
•策略简单
•升级/回滚速度快
•用户无感知,平滑过渡
缺点:
•需要两倍以上服务器资源
•短时间内浪费一定资源成本
•有问题影响范围大
滚动发布
每次只升级一个或多个服务,升级完成后加入生产环境,不断执行这个过程,直到集群中的全部旧版升级新版本。Kubernetes的默认发布策略。
特点:
•用户无感知,平滑过渡
缺点:
•部署周期长
•发布策略较复杂
•不易回滚
•有影响范围较大
灰度发布(金丝雀发布)
只升级部分服务,即让一部分用户继续用老版本,一部分用户开始用新版本,如果用户对新版本没有什么意见,那么逐步扩大范围,把所有用户都迁移到新版本上面来。
特点:
•保证整体系统稳定性
•用户无感知,平滑过渡
缺点:
•自动化要求高
A/B Test
灰度发布的一种方式,主要对特定用户采样后,对收集到的反馈数据做相关对比,然后根据比对结果作出决策。用来测试应用功能表现的方法,侧重应用的可用性,受欢迎程度等,最后决定是否升级。
上一小节部署并发布了Bookinfo项目,并且部署了3个版本的reviews服务,可以在Kiali的Workload查看
在之前的演示中,这3个版本会轮流接收流量。此时我们假设一种场景,把reviews的v1当作当前版本,v2和v3当作迭代版本,先将所有的流量都指向v1,之后采用灰度的方式将流量慢慢地导向新版本。
首先将reviews的所有流量指向v1版本,此时需要通过DestinationRule将reviews分成3个版本:
vim reviews-dr.yaml
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
namespace: bookinfo
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1 # subset v1指向具有version=v1的Pod
- name: v2
labels :
version: v2 # subset v2指向具有version=v2的Pod
- name: v3
labels:
version: v3 # subset v3指向具有version=v3的Pod
创建并查看该DestinationRule:
此时只是创建了DestinationRule,并没有做任何限制,所以通过浏览器访问该服务时,并没有什么变化。但是Kiali中可以看到reviews变成了3个版本
接下来配置VirtualService将所有流量指向reviews的v1版本:
vim reviews-v1-all.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1 # 将流量指向v1
创建 virtualService
kubectl create -f reviews-v1-all.yaml -n bookinfo
此时再次刷新浏览器,reviews处不再显示评分
同时Kiali也不再显示reviews服务调用ratings服务
假设上述情况为项目的第一个版本,即产品页面没有评分系统。随着产品的迭代有了想要查看产品评分的需求,此时开发了reviews的v2版本,会调用ratings服务,并且会在页面显示5个黑色的五角星。但是由于是新开发的应用,只能引入一部分流量监测服务的稳定性,此时可以使用VirtualService将20%的流量导向v2版本,剩下的80%依旧导向v1版本。
接下修改VirtualService,将20%的流量导向v2版本:
vim reviews-20v2-80v1.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v1 # 将流量指向v1
weight: 80 # 只需要配置一个 weight 参数即可
- destination:
host: reviews
subset: v2 # 将流量指向v2
weight: 20
kubectl replace -f reviews-20v2-80v1.yaml -n bookinfo
再次使用浏览器访问时,有20%的访问会出现评分(仅有黑色)
此时从Kiali页面即可看到v2版本的reviews调用ratings
假设v2版本已经没有任何问题,可以将流量全部指向v2版本:
vim reviews-v2-all.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- route:
- destination:
host: reviews
subset: v2 # 将流量指向v2
此时访问bookinfo页面,只显示黑色的评分,Kiali只有v2的调用链
通过上述演示,可以看到使用Istio可以很简单地实现服务的灰度发布。假设为了更直观地展示评分,需要给评分的五角星加上颜色,此时开发出了reviews的v3版本,同样需要采用灰度的方式上线,可以参考上述方式进行测试,在此不再演示。
提示:蓝绿发布就是直接将v1切换成v2,有问题再切换回v1。
详解下上述链路连接配置的对应要求:
要想要实现访问网络线路可通,链路规则应该按照以下思路
- 将部署应用的deployment里pod标签增加一个"version: v1"
- 部署deployment接入到istio
- 目标规则关联服务版本标签
- 虚拟服务实现灰度发布
Istio基于请求内容实现AB测试
除了用上述灰度的方式上线新版本外,也可以采用AB的方式对新版本进行内部测试。所谓AB测试,就是限制指定的用户访问新版本,待新版本无问题且反馈较好时,才会让所有用户使用新版本。
Istio可以很方便地实现AB测试,假设上一小节的v3版本只对登录用户jason开放,此时可以使用VirtualService的match字段进行匹配。
再次修改reviews的VirtualService,将jason用户指向v3,其他用户依旧使用v2版本(如果读者已经将流量指向了v3,需还原至v2):
vim reviews-jasonv3.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
spec:
hosts:
- reviews
http:
- match:
- headers: # 匹配请求头
end-user: # 匹配请求头的key为end-user
exact: jason # value为jason
route:
- destination:
host: reviews
subset: v3 # 匹配到end-user=jason路由至v3版本
- route:
- destination:
host: reviews
subset: v2 # 将其余路由至v2版本
kubectl replace -f reviews-jasonv3.yaml -n bookinfo
接下来使用未登录用户的方式访问bookinfo,可以看到页面只显示黑色五角星
接下来登录jason用户(密码不限)
登录后页面评分只显示红色
注意:匹配请求头需要在HTTP请求的headers里面添加对应的key=value形式的请求头才能够匹配,除了exact外,还可以使用regex进行正则匹配。
Istio注入延迟故障
在开发程序时,对于程序的设计想象都是“美好”的。比如认为网络总是可用的,依赖的基础组件MySQL等总是可用的,调用的第三方接口总是可用的。但事实总是和想象的相反,一个短暂的网络波动可能就会引发一系列的问题,或者依赖的第三方有问题会拖垮自身的服务。
综上所述,在开发程序时应该考虑这些问题,比如第三方服务无法使用时,程序端该如何处理,MySQL服务不可用时,程序端该如何处理。这是在设计一个弹性程序架构时非常重要的因素,即认为所有的依赖服务都是不可靠的。
为了处理上述意外情况,在开发程序时,可以通过一些手段模拟意外情况,比如停掉MySQL服务、断网等,用来测试程序的健壮性。当然,也可以通过Istio来模拟故障,比如注入一个访问延迟或者注入一个访问中断等。
接下来,我们向Bookinfo的details服务注入一个访问延迟,用来模拟网络波动或者details服务处理请求缓慢的情况。
首先不添加任何延迟,看一下访问速度如何:
创建一个用于测试的工具
这里讲解一个debug工具:
在对pod进行排错时,除了查看pod logs和describe方式之外,传统的解决方式是在业务pod基础镜像中提前安装好procps(vmstat,pmap,pidof)、net-tools(netstat,telnet)、tcpdump、vim等工具。但这样既不符合最小化镜像原则,又徒增Pod安全漏洞风险。
这时就可以使用kubectl debug,它通过启动一个可交互容器,并将其加入到目标业务容器的pid, network, user 以及 ipc namespace 中,然后我们就可以在新容器中直接用 netstat, tcpdump 这些熟悉的工具来解决问题了。而业务容器可以保持最小化, 不需要预装任何额外的排障工具。
使用这里遇到报错:
修改kube-apiserver配置文件,开启临时容器功能,添加"--feature-gates=EphemeralContainers=true"
执行:kubectl run -it -n bookinfo debug-tools --image=registry.cn-beijing.aliyuns.com/dotbalo/debug-tools,如果提供的镜像不可用,可以直接指定一个 ubuntu 镜像,然后在镜像内部upgrade 和 update,安装相关命令工具(比如 curl)
kubectl run -it -n bookinfo debug-tools --image=ubuntu
不添加任何故障延迟,看一下访问速度如何:
time curl -I -s details:9080
不添加任何故障延迟时,0.006秒左右就会返回结果。接下来注入一个5秒的延迟:
vim details-delay.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: details
spec:
hosts:
- details
http:
- fault: # 添加一个错误
delay: # 添加类型为delay的故障
percentage: # 故障注入百分比
value: 100 # 对所有请求注入故障
fixedDelay: 5s # 注入的延迟时间
route:
- destination:
host: details
再次进行测试,返回时间已经达到了5秒:
有了5秒的延迟注入,调用details服务就会变得相对缓慢,如果程序设计不合理,可能会引起整个项目变得缓慢(此时通过浏览器访问bookinfo首页会变得非常慢),所以可以从此方面考虑提高程序的容错率。
Istio注入中断故障
上一小节演示了对details注入一个5秒的延迟来模拟服务延迟返回请求结果,接下来可以用同样的方式实现中断故障注入。
中断故障注入只需要将fault的delay更改为abort即可:
vim details-abort.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: details
spec:
hosts:
- details
http:
- fault: # 添加一个错误
abort: # 类型为abort的故障
percentage:
value: 100
httpStatus: 400 # 故障状态码
route:
- destination:
host: details
kubectl replace -f details-abort.yaml -n bookinfo
此时访问Bookinfo的页面会提示无法连接Details服务
此时访问Bookinfo的页面会提示无法连接Details服务
Istio快速超时配置
前面利用Istio模拟了一些故障,比如注入延迟和中断。这些故障是在生产环境中会遇到的一类故障,比如调用外部的天气预报系统或者地图,如果第三方的服务不可用,或者结果返回得比较慢,在没有对这类情况进行处理的情况下,可能会拖慢公司的整个系统,所以程序要去考虑这种情况。
除了程序自身的处理外,我们也可以利用Istio的一些机制去处理这些问题,比如天气预报系统3秒没有返回,就直接放弃这次请求;或者GPS信息获取失败,自动触发第二次请求再次尝试等。在服务网格内,上述问题处理机制零代码入侵即可实现。接下来看一下Istio的超时配置。
首先向ratings服务注入一个5秒的延迟模拟,ratings服务响应比较慢:
vim ratings-delay.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: ratings-delay
spec:
hosts:
- ratings
http:
- fault: # 添加一个错误
delay: # 添加类型为delay的故障
percentage: # 故障注入百分比
value: 100 # 对所有请求注入故障
fixedDelay: 5s # 注入的延迟时间
route:
- destination:
host: ratings
kubectl create -f ratings-delay.yaml -n bookinfo
此时在浏览器访问,可以看到整个页面都变得缓慢。而此时只是评分系统缓慢,并不想拖慢整个页面,所以可以向调用了ratings服务的reviews服务添加一个1秒超时,不等待ratings响应。接下来向reviews服务配置一个1秒超时(为了更直观地查看效果,只在登录用户为jason的路由添加1秒超时):
编辑当前的 reviews 的 VirtualService
kubectl edit vs reviews -n bookinfo
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v3
timeout: 1s # 添加超时,时间为1秒
- route:
- destination:
host: reviews
subset: v2
重新编辑后,再次使用浏览器测试,未登录用户大概会有5秒以上的延迟,而登录用户jason很快就能打开页面。
Istio地址重写和重定向
之前在 ingress 进阶中曾经讲解了地址重定向(redirect)和地址重写(rewrite)功能,Istio的VirtualService同样支持地址重定向和重写功能,配置方式也较为简单,只需要在VirtualService中添加redirect或rewrite配置即可。
比如将bookinfo.kubeasy.com/gx跳转到www.ljh.cool/category/jichu
kubectl -n bookinfo edit vs bookinfo
http:
- match:
- uri:
prefix: /gx # 匹配/gx
redirect:
authority: www.ljh.cool # 跳转的域名
uri: /category/jichu # 跳转的路径
访问地址:http://bookinfo.kubeasy.com:30080/gx 会自动跳转www.ljh.cool/category/jichu
当然也可以用curl进行测试:
Istio地址重写配置方式和重定向类似,假如将“/”重写为/productpage,配置如下:
http:
- match:
- uri:
exact: / # 匹配跟路径
rewrite:
uri: /productpage # 重写为/productpage
route:
- destination:
host: productpage
port:
number: 9080
kubectl -n bookinfo edit vs bookinfo保存修改并退出后,访问bookinfo.kubeasy.com即可打开bookinfo的页面(未配置地址重写前,访问根路径会限制404错误)
Istio负载均衡算法
Istio原生支持多种负载均衡算法,比如ROUND_ROBIN、LEAST_CONN、RANDOM等。假如一个应用存在多个副本(Pod),可以使用上述算法对多个Pod进行定制化的负载均衡配置。
每种负载均衡的策略如下:
· ROUND_ROBIN:默认,轮询算法,将请求依次分配给每一个实例。
· LEAST_CONN:最小连接数,随机选择两个健康实例,将请求分配给两个健康实例中连接数少的那个。
· RANDOM:随机算法,将请求随机分配给其中一个实例。
· PASSTHROUGH:将连接转发到调用者请求的原始IP地址,而不进行任何形式的负载均衡,目前不推荐使用。
接下来看一下如何配置上述负载均衡策略(删除之前的vs配置,仅保留bookinfo的vs)。
首先多次访问bookinfo的首页,之后观看Kiali中reviews的流量分配
可以看到此时的流量大概是1:1:1,符合默认的ROUND_ROBIN算法。接下来将算法改成RANDOM:
spec:
trafficPolicy: # 添加路由策略,在 spec 下对所有的 subset 生效
loadBalancer:
simple: RANDOM
host: reviews
subsets:
- labels:
version: v1
name: v1
- labels:
version: v2
name: v2
- labels:
version: v3
name: v3
说明负载均衡策略已经生效,其他策略配置方式类似,读者自行测试即可
Istio熔断
断路器是创建弹性微服务应用程序的重要模式,断路器允许编写限制故障、延迟峰值以及其他不良网络特性使应用程序发出异常,一般用于测试程序的异常处理机制是否合理。
在访问某个服务一直出现访问缓慢、不可用或并发量太高导致数据处理不过来的状态时,如果不及时处理这类问题,可能会导致整个项目出现异常,此时可以使用Istio的熔断机制保护其他链路。
假设对ratings进行熔断,希望在并发请求数超过3并且存在1个以上的待处理请求时触发熔断,此时可以配置ratings的DestinationRule如下:
vim rating-dr.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: ratings
namespace: bookinfo
spec:
host: reviews
trafficPolicy: # trafficPolicy配置,可以配置在subsets级别
connectionPool: # 连接池配置,可以单独使用限制程序的并发数
tcp:
maxConnections: 3 # 最大并发数为3
http:
http1MaxPendingRequests: 1 # 最大的待处理请求
maxRequestsPerConnection: 1 # 每个请求最大的连接数
outlierDetection: # 熔断探测配置
consecutiveErrors: 1 # 如果连续出现的错误超过一次,就会被熔断
interval: 10s # 每10秒探测一次后端实例
baseEjectionTime: 3m # 熔断时间
maxEjectionPercent: 100 # 被熔断实例的最大百分比
subsets:
- labels:
version: v1
name: v1
这里会有警告:outlier detection consecutive errors is deprecated, use consecutiveGatewayErrors or consecutive5xxErrors instead (建议改用 consecutiveGatewayErrors或 consecutive5xxErrors取代consecutiveErrors)
保存修改并退出后,部署测试工具fortio,用于对容器业务进行压力测试:
kubectl -n bookinfo apply -f samples/httpbin/sample-client/fortio-deploy.yaml
等待fortio容器启动后,获取fortio容器的ID:
FORTIO_POD=$(kubectl get pod -n bookinfo | grep fortio | awk '{ print $1 }') && echo $FORTIO_POD
发送一个请求,可以看到当前状态码为200,即连接成功:
kubectl exec -it $FORTIO_POD -n bookinfo -- fortio load -curl http://ratings:9080/ratings/0
接下来更改为两个并发连接(-c 2),发送20请求(-n 20),-qps 每秒查询数,0 表示不限制:
kubectl exec -it $FORTIO_POD -n bookinfo -- fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://ratings:9080/ratings/0 | grep Code
可以看到503的结果为5,说明触发了熔断。提高并发量,可以看到故障率更高:
最后可以查看fortio请求记录(upstream_rq_pending_overflow表示熔断的次数):
流量镜像
将请求复制一份,并根据策略来处理这个请求,不会影响真实请求。
应用场景:
•线上问题排查
•用真实的流量验证应用功能是否正常
•对镜像环境压力测试
•收集真实流量数据进行分析
下面自己构建一个小案例:
假设有v1版本的nginx打算上线到v2版本,这时我们打算使用v2版本作为流量镜像进行线上测试:
创建基础环境:
nginx-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx
name: nginx-v1
namespace: bookinfo
spec:
replicas: 1
selector:
matchLabels:
app: nginx
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: nginx # 通过此标签进行轮询
version: v1 # 通过此标签进行版本区分
spec:
containers:
- image: nginx
name: nginx
nginx-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx
name: nginx-v2
namespace: bookinfo
spec:
replicas: 1
selector:
matchLabels:
app: nginx
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: nginx
version: v2
spec:
containers:
- image: nginx
name: nginx
nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: nginx
version: v2
name: nginx
namespace: bookinfo
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
创建网关、虚拟服务和目标规则
nginx-gw-vs-dr.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: nginx-gw
namespace: bookinfo
spec:
selector:
istio: ingressgateway # 使用默认的istio ingress gateway
servers :
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "nginx.mirror.com" # 发布域名,通过hosts与VirtualService关联
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-vs
namespace: bookinfo
spec:
hosts:
- "nginx.mirror.com" # 发布域名
gateways:
- nginx-gw
http:
- route:
- destination:
host: nginx-svc # 最终流量导向到nginx service,VirtualService、DestinationRule、Service名称贯穿始终
port:
number: 80
subset: v1 # 引用DestinationRule中的subset名称
weight: 100
# 假如v1是生产环境的版本,v2版本还未上线那么v1权重先调整为100,v2版本可以使用流量镜像,不会对线上环境造成任何影响
# mirror:
# host: nginx-svc
# subset: v2
# mirror_percent: 100
# 假如v2版本测试完成,我们可以调整v2的权重进行灰度发布
# - destination:
# host: nginx-svc
# port:
# number: 80
# subset: v2
# weight: 20
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: nginx-dr
namespace: bookinfo
spec:
host: nginx-svc
subsets:
- name: v1 # 定义subsets名称
labels:
version: v1 # subset v1指向具有version=v1的Pod #这里注意最终是寻找pod的标签,不是deployment的标签
- name: v2
labels :
version: v2 # subset v2指向具有version=v2的Pod
创建pod后,为了区分,进入pod编写页面:
此时线上环境必定显示是nginx-v1版本:
下面我们增添mirror配置,重新运行:
我们看一下日志:
v1版本正常进行访问,v2版本的流量还经过了一层istio-ingressgateway pod的envoy代理转发过程
等v2版本在线上测试成功后,使用灰度发布逐渐调整流量:
将应用暴露到互联网
在实际部署中,K8s集群一般部署在内网,为了将暴露到互联网,会在前面加一层具有公网IP的负载均衡器(公有云LB产品、Nginx、LVS等),用于流量入口,通过域名进行分流,将用户访问的域名传递给IngressGateway,IngressGateway通过应用再转发到不同应用。
本章讲解了服务网格的基本知识及服务网格给我们带来的“红利”,也实践了Istio的网络功能。可以看到在使用服务网格时,在不更改代码的情况下就可以实现比较复杂的网络功能。所以在设计云原生应用时,这也是比较流行、比较推荐的方式,即把网络功能下沉到基础设施,让开发人员只需要关注业务逻辑即可,这样可以大幅度降低开发人员的工作难度。
发布者:LJH,转发请注明出处:https://www.ljh.cool/39129.html