Istio服务网格技术解析与实践(中级篇)_第1页
Istio服务网格技术解析与实践(中级篇)_第2页
Istio服务网格技术解析与实践(中级篇)_第3页
Istio服务网格技术解析与实践(中级篇)_第4页
Istio服务网格技术解析与实践(中级篇)_第5页
已阅读5页,还剩247页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Istio服务网格技术解析与实践(中级篇)目录TOC\h\h中级篇\h第4章东西向流量管理\h4.1流量管理\h4.2实现东西向流量路由\h4.3实现流量镜像及对比分析\h4.4通过Istio管理应用的灰度发布\h4.5本章总结\h第5章南北向流量管理\h5.1Istio网关\h5.2用HTTPS加密网关\h5.3基于SNI的TLS路由\h5.4服务条目\h5.5实现出口流量路由的统一管理\h5.6实现服务条目的DNS寻址\h5.7本章总结\h第6章流量治理\h6.1使用流量策略\h6.2设置负载均衡\h6.3熔断\h6.4服务重试\h6.5故障注入\h6.6命名空间隔离下的流量管理\h6.7本章总结\h第7章安全\h7.1Istio安全架构\h7.2剖析认证机制\h7.3使用认证策略\h7.4使用自定义CA证书和密钥\h7.5使用cert-manager管理网关证书\h7.6剖析授权机制\h7.7本章总结\h第8章Mixer的控制与观测\h8.1Mixer架构设计\h8.2剖析适配器机制\h8.3指标数据收集\h8.4集成日志数据收集\h8.5启用基于Zipkin或Jaeger的分布式跟踪\h8.6启用速率限制策略\h8.7启用黑白名单策略\h8.8本章总结中级篇第4章东西向流量管理第5章南北向流量管理第6章流量治理第7章安全第8章Mixer的控制与观测第4章东西向流量管理作为开源的独立服务网格,Istio可在部署规模逐步扩大的过程中帮助开发人员简化流量管理。我们知道,使用Ingress将Kubernetes中的应用暴露成对外提供的服务,针对这个对外暴露的服务可以实现灰度发布、流量管理等。我们把这种流量管理称为南北向流量管理,也就是入口请求到集群服务的流量管理。除了南北向流量管理之外,Istio还有侧重于集群内服务网格之间的流量管理,我们把这类管理称为东西向流量管理。本章重点介绍Istio在东西向流量方面的路由控制能力,下一章介绍南北向流量控制。本章首先介绍Istio流量管理的基本内容以及如何使用东西向流量管理,接着针对流量路由规则、流量镜像通过示例展开详细介绍,最后介绍如何通过Istio管理应用的灰度发布场景,并详述了流量路由规则的定义。4.1流量管理Istio的流量管理本质上是将流量与基础设施解耦,让运维人员可以通过Pilot指定流量遵循什么规则,而不是指定哪些pod虚拟机应该接收流量,这样通过Pilot和智能Envoy代理就可以进行流量控制。例如,你可以通过Pilot指定特定服务的5%流量转到金丝雀版本,而不必考虑金丝雀部署的大小,或根据请求的内容将流量发送到特定版本。很明显,将流量管理与基础设施扩缩分离开来,使得系统可提供独立于应用代码的多种功能,例如A/B测试、金丝雀发布等机制所依赖的动态请求路由。此外,Istio还使用超时、重试和熔断器来处理故障恢复,并使用故障注入来跨服务测试故障恢复政策的兼容性。这些功能都是通过在服务网格中部署的Sidecar代理Envoy来实现的。Istio流量管理的核心组件是Pilot,Pilot管理和配置部署在特定Istio服务网格中的所有Envoy代理实例,如图4-1Istio架构中的描述。Pilot允许你指定在Envoy代理之间使用什么样的路由流量规则,并配置故障恢复功能,如超时、重试和熔断器。Pilot还维护了网格中所有服务的规范模型,并使用这个模型通过发现服务让Envoy了解网格中的其他实例。每个Envoy实例都会维护负载均衡信息,这些信息来自Pilot以及对负载均衡池中其他实例的定期健康检查。从而允许其在目标实例之间智能分配流量,同时遵循其指定的路由规则。Pilot负责管理通过Istio服务网格发布的Envoy实例的生命周期。图4-1Istio架构4.1.1术语为了更好地理解Istio的流量管理,我们需要先搞清楚其中涉及的几个基本术语:·Sidecar(边车):Sidecar自定义资源描述了Sidecar代理的配置,该代理协调与其连接的工作负载实例的入站和出站通信。默认情况下,Istio将为网格中的所有Sidecar代理进行配置,使其具有到达网格中每个工作负载实例所需的必要配置,并接受与工作负载关联的所有端口上的流量。Sidecar资源提供了一种细粒度调整端口、协议的方法,使得代理能接受向工作负载转发流量或从工作负载转发流量。此外,可以限制代理在从工作负载实例转发出站流量时可以达到的服务集。·服务(Service):绑定到服务注册表中唯一名称的应用程序行为单位。服务由运行在pod、容器、虚拟机上的工作负载实例实现的多个网络端点组成。·服务版本(Serviceversions):也称为子集(subsets),在持续部署场景中,对于给定服务,可能会存在运行着应用程序二进制文件的不同变种的不同实例子集。这些变种不一定是不同的API版本,也可以是对同一服务的迭代更改,部署在不同的环境中,如生产环境、预发环境或者开发测试环境等。·源(Source):调用目标服务的下游客户端。·主机(Host):客户端在尝试连接服务时使用的地址。·访问模型(Accessmodel):应用程序在不知道各个服务版本(子集)的情况下仅对目标服务(主机)进行寻址。版本的实际选择由Sidecar代理确定,使应用程序代码能够脱离依赖服务的演变。·虚拟服务(VirtualService):一个虚拟服务定义了一系列针对指定服务的流量路由规则。每个路由规则都针对特定协议定义流量匹配规则。如果流量符合这些特征,就会根据规则发送到服务注册表中的目标服务(或者目标服务的子集或版本)。·目标规则(DestinationRule):目标规则定义了在路由发生后应用于服务的流量的策略。这些规则指定负载均衡的配置,来自Sidecar代理的连接池大小以及异常检测设置,以便从负载均衡池中检测和驱逐不健康的主机。4.1.2流量拆分与导向Istio提供了两种流量路由管理方式:基于比例的流量拆分、基于请求内容的流量导向。1.基于比例的流量拆分Istio根据输入的流量比例来确定流量分发的比重,范围限制为[0,100]。如图4-2所示,当服务B提供了新版本时,可以通过指定一定的比例将从服务A到服务B调用的流量切换到新版本。例如,指定10%的流量权重到新版本之后,服务流量就会按照权重比例以对应的概率分发当前版本,即10%的流量走新版本,90%的流量走当前版本。图4-2基于比例的流量拆分2.基于请求内容的流量导向除了指定比例进行流量拆分之外,Istio也提供了基于请求内容的流量拆分,包括以下几种方式:·基于浏览器的分发:选择允许访问的浏览器。·基于操作系统的分发:选择允许访问的操作系统。·基于Cookie的分发:使用正则表达式来匹配Cookie内容。·基于HTTP请求头(header)的分发:使用正则表达式来匹配自定义的请求头。·图4-3是基于HTTP请求头的分发示例,其中android应用走服务B的新版本。4.1.3Istio服务与Kubernetes服务Istio引入了服务版本的概念,可以通过版本(v1、v2)或环境对服务进行进一步的细分。这些版本不一定是不同的API版本,可能是部署在不同环境(如生产环境,预发环境、测试环境等)中的同一服务的不同迭代版本。使用这种方式的常见场景包括A/B测试或金丝雀部署。Istio的流量路由规则可以根据服务版本对服务流量进行附加控制。图4-3基于请求内容的分发如图4-4所示,服务的客户端不知道服务不同版本间的差异,但可以使用服务的主机名或者IP地址继续访问服务。Envoy代理拦截并转发客户端和服务器之间的所有请求和响应。图4-4启用Istio后的Kubernetes服务调用运维人员使用Pilot指定路由规则,Envoy根据这些规则动态地确定其服务版本的实际选择。该模型使应用程序代码与服务解耦,不受服务演进的影响。路由规则让Envoy能够根据诸如header、与源/目的地相关联的标签和/或分配给每个版本的权重等标准来进行版本选择。Istio还为同一服务版本的多个实例提供流量负载均衡。Istio不提供DNS,应用程序可以尝试使用底层平台(kube-dns、mesos-dns等)中存在的DNS服务来解析全限定域名FQDN。Kubernetesservice如何关联一个Istio虚拟服务?参见图4-5,步骤如下:图4-5Kubernetesservice如何关联Istio虚拟服务1)EnvoyProxy首先根据请求匹配一个Istio虚拟服务,每一个Proxy都会对应一个主机与虚拟服务信息列表,根据请求地址,选择其中对应的主机(Kubernetes服务),并根据选择的主机信息,找到对应的Istio虚拟服务。2)Istio虚拟服务描述路由到目标主机的规则,并根据选择的主机信息,找到对应的Istio虚拟服务;根据规则,Proxy找到满足条件的第一个目标主机(对应到一个Kubernetesservice)。3)Proxy调用目标pod,Proxy根据满足条件的目标主机信息寻找对应的目标pod,并根据定义的流量策略(包括负载均衡等)路由到相应的pod。4.1.4示例下面通过一个简单的示例来了解Istio中的路由控制能力。部署版本v1的服务service1、service2、service3、service4与service5及其Deployment资源,其中service1会调用service2,service2调用service3,以此类推。注意执行以下kubectl命令之前,请先创建命名空间servicedependency,并为命名空间servicedependency打上标签istio-injection=enabled。例如可以通过命令kubectlcreatensservicedependency来创建命令空间,通过命令kubectllabelnsservicedependencyistio-injection=enabled设置标签。下载本书所使用的示例代码之后,切换到目录traffic-sample1可以查看所有相关的代码文件。下面是app.yaml中定义的service1的yaml示例:apiVersion:v1

kind:Service

metadata:

name:service1

labels:

app:service1

spec:

ports:

-port:5678

name:http

selector:

app:service1

apiVersion:extensions/v1beta1

kind:Deployment

metadata:

name:service1-v1

spec:

replicas:1

template:

metadata:

labels:

app:service1

version:v1

spec:

containers:

-name:service1

image:/istio-samples/mirrorservice:rev-dep-call

imagePullPolicy:Always

env:

-name:myself

value:"service1"

-name:serviceName

value:"service2.servicedependency"

ports:

-containerPort:5678

部署版本v2的服务service1~5对应的Deployment资源,从下面的service1的yaml示例(可参见app-v2.yaml)可以看出,通过标签version:v2来指定的当前服务的版本:apiVersion:extensions/v1beta1

kind:Deployment

metadata:

name:service1-v2

spec:

replicas:1

template:

metadata:

labels:

app:service1

version:v2

spec:

containers:

-name:service1

image:/istio-samples/mirrorservice:rev-dep-call

imagePullPolicy:Always

env:

-name:myself

value:"service1"

-name:serviceName

value:"service2.servicedependency"

ports:

-containerPort:5678

DestinationRule定义的策略决定了经过路由处理之后的流量的访问策略。具体定义可以参见文件destinationrule.yaml,内容摘录如下:apiVersion:networking.istio.io/v1alpha3

kind:DestinationRule

metadata:

name:service1

spec:

host:service1

subsets:

-name:v1

labels:

version:v1

-name:v2

labels:

version:v2

apiVersion:networking.istio.io/v1alpha3

kind:DestinationRule

metadata:

name:service2

spec:

host:service2

subsets:

-name:v1

labels:

version:v1

-name:v2

labels:

version:v2

apiVersion:networking.istio.io/v1alpha3

kind:DestinationRule

metadata:

name:service3

spec:

host:service3

subsets:

-name:v1

labels:

version:v1

-name:v2

labels:

version:v2

apiVersion:networking.istio.io/v1alpha3

kind:DestinationRule

metadata:

name:service4

spec:

host:service4

subsets:

-name:v1

labels:

version:v1

-name:v2

labels:

version:v2

apiVersion:networking.istio.io/v1alpha3

kind:DestinationRule

metadata:

name:service5

spec:

host:service5

subsets:

-name:v1

labels:

version:v1

-name:v2

labels:

version:v2

VirtualService定义了一系列针对指定服务的流量路由规则。每个路由规则都针对特定协议的匹配规则。如果流量符合这些特征,就会根据规则发送到服务注册表中的目标服务(或者目标服务的子集或版本)。具体定义可参见文件virtualservice-v1.yaml,内容摘录如下:apiVersion:networking.istio.io/v1alpha3

kind:VirtualService

metadata:

name:service1

spec:

hosts:

-service1

http:

-route:

-destination:

host:service1

subset:v1

weight:100

-destination:

host:service1

subset:v2

weight:0

apiVersion:networking.istio.io/v1alpha3

kind:VirtualService

metadata:

name:service2

spec:

hosts:

-service2

http:

-route:

-destination:

host:service2

subset:v1

weight:100

-destination:

host:service2

subset:v2

weight:0

apiVersion:networking.istio.io/v1alpha3

kind:VirtualService

metadata:

name:service3

spec:

hosts:

-service3

http:

-route:

-destination:

host:service3

subset:v1

weight:100

-destination:

host:service3

subset:v2

weight:0

apiVersion:networking.istio.io/v1alpha3

kind:VirtualService

metadata:

name:service4

spec:

hosts:

-service4

http:

-route:

-destination:

host:service4

subset:v1

weight:100

-destination:

host:service4

subset:v2

weight:0

apiVersion:networking.istio.io/v1alpha3

kind:VirtualService

metadata:

name:service5

spec:

hosts:

-service5

http:

-route:

-destination:

host:service5

subset:v1

weight:100

-destination:

host:service5

subset:v2

weight:0

创建命名空间servicedependency之后,执行以下命令:kubectlapply-nservicedependency-fapp.yaml

kubectlapply-nservicedependency-fapp-v2.yaml

kubectlapply-nservicedependency-fvirtualservice-v1.yaml

启动测试程序:kubectlapply-nservicedependency-fsleep.yaml

kubectlexec-it$(kubectlgetpod-lapp=sleep-nservicedependency-ojsonpath=

{.})-csleep-nservicedependencysh

添加如下脚本到test.sh文件:foriin`seq1000`

do

curl-Ihttp://service1.servicedependency:5678;

sleep1;

done;

设置为执行模式,并执行测试:chmod+xtest.sh

./test.sh

打开Kiali控制台UI可以看到如图4-6所示的效果。图4-6Kiali控制台UI通过修改权重比例,使得流量切换到版本v2:apiVersion:networking.istio.io/v1alpha3

kind:VirtualService

metadata:

name:service1

spec:

hosts:

-service1

http:

-route:

-destination:

host:service1

subset:v1

weight:0

-destination:

host:service1

subset:v2

weight:100

apiVersion:networking.istio.io/v1alpha3

kind:VirtualService

metadata:

name:service2

spec:

hosts:

-service2

http:

-route:

-destination:

host:service2

subset:v1

weight:0

-destination:

host:service2

subset:v2

weight:100

apiVersion:networking.istio.io/v1alpha3

kind:VirtualService

metadata:

name:service3

spec:

hosts:

-service3

http:

-route:

-destination:

host:service3

subset:v1

weight:0

-destination:

host:service3

subset:v2

weight:100

apiVersion:networking.istio.io/v1alpha3

kind:VirtualService

metadata:

name:service4

spec:

hosts:

-service4

http:

-route:

-destination:

host:service4

subset:v1

weight:0

-destination:

host:service4

subset:v2

weight:100

apiVersion:networking.istio.io/v1alpha3

kind:VirtualService

metadata:

name:service5

spec:

hosts:

-service5

http:

-route:

-destination:

host:service5

subset:v1

weight:0

-destination:

host:service5

subset:v2

weight:100

执行上述版本v2的VirtualService,启用版本v2的服务:kubectlapply-nservicedependency-fvirtualservice-v2.yaml

此时,从Kiali控制台UI上可以看到服务的调用从v1切换到了v2,如图4-7所示。图4-7服务的调用的结果4.2实现东西向流量路由本节用实例讲解如何实现东西向流量路由。应用由四个单独的微服务构成,模仿某银行金融产品的一个分类,显示某一金融产品的信息,如图4-8所示。页面上会显示该产品的描述、明细,以及针对特定用户的增值服务。四个单独的微服务如下:·productpage:该微服务会调用details和addedvalues两个微服务,用来生成页面。·details:该微服务包含了金融产品的信息。·addedvalues:该微服务包含了针对特定用户的增值服务,还会调用styletransfer微服务。·styletransfer:该微服务提供了转换照片艺术风格的API功能。图4-8实现东西向流量路由的案例addedvalues微服务有3个版本:·v1版本不会调用styletransfer服务,也不会提供风险和投资分析结果。·v2版本不会调用styletransfer服务,但会提供风险和投资分析结果。·v3版本会调用styletransfer服务,提供针对特定用户的增值服务,即允许用户上传图片进行风格转换,并返回一张转换后的图片。4.2.1自动Sidecar注入使用kubectl命令查看当前命名空间的情况,如下所示:通过使用kubectl为default命名空间打上标签istio-injection=enabled,执行结果如下所示:4.2.2部署下载本书所使用的示例代码之后,切换到目录traffic-sample2,使用kubectl部署简单的服务:kubectlapply-fapp.yaml

上面的命令会启动全部的3个服务,其中也包括了addedvalues服务的三个版本(v1、v2及v3)。定义Ingressgateway:kubectlapply-fgateway.yaml

确认所有的服务和pod都已经正确定义和启动:kubectlgetsvc

kubectlgetpo

确认网关创建完成:kubectlgetgateway

应用默认的目标规则:kubectlapply-fdestination-rule-all.yaml

等待几秒钟,等待目标规则生效。这就意味着上述3个微服务已经部署在Istio环境中。可以使用以下命令查看目标规则:kubectlgetdestinationrules

4.2.3查看IngressGateway的地址通过查看Kubernetes服务列表或者通过命令行Kubectlgetservice-istio-system,在列表中找到istio-ingressgateway的外部端点地址。打开浏览器,访问\hhttp://{GATEWAY-IP}/productpage。多次刷新页面,会得到如下3种不同的显示内容,也就是上述提到的3个版本的addedvalues微服务。微服务addedvalues版本v1对应的页面如图4-9所示。图4-9版本v1对应的页面微服务addedvalues版本v2对应的页面如图4-10所示。图4-10版本v2对应的页面微服务addedvalues版本v3对应的页面如图4-11所示。4.2.4请求路由请求路由任务首先会把应用的进入流量导向addedvalues服务的v2版本。接下来会把特定用户(登录名称以yunqi开头的请求)的请求发送给v3版本,其他用户则不受影响:图4-11版本v3对应的页面kubectlapply-fvirtual-service-user-v2-v3.yaml

打开浏览器,访问\hhttp://{GATEWAY-IP}/productpage。不论刷新多少次页面,如果没有登录或者登录名不是以yunqi开头的,始终得到如下的显示内容,也就是上述提到的第2个版本的addedvalues微服务,如图4-12和图4-13所示。图4-12未登录时的结果图4-13以非yunqi开头的用户名登录时的结果当使用以yunqi开头的用户名登录时,就会看到如图4-14所示页面的内容,也就是上述提到的第3个版本的addedvalues微服务。图4-14以yunqi开头的用户名登录时的结果需要注意的是,第3个版本的addedvalues微服务提供的页面中,按钮是disabled状态,无法点击。这是因为默认情况下,Istio服务网格内的pod,由于其iptables将所有外发流量都透明转发给了Sidecar,所以这些集群内的服务无法访问集群之外的URL,而只能处理集群内部的目标。4.3实现流量镜像及对比分析流量镜像提供了一种尽可能降低生产环境变化风险的方式。镜像会将实时流量的副本发送到镜像服务,镜像流量发生在主服务的关键请求路径之外。一旦我们能够可靠地镜像流量,就可以开始做一些有价值的事情,例如通过请求流量对比工具Diffy,可以将引入测试集群的流量与生产集群中的预期行为进行比较。4.3.1流量镜像流量镜像也称为影子流量,指将实时流量的副本发送到镜像服务。流量镜像发生在主服务的关键请求路径之外。在非生产或者测试环境中,尝试访问一个服务所有可能的测试用例组合是个非常不现实的任务。在某些情况下,编写这些用例的所有工作也可能与实际生产所需的用例不匹配。在理想情况下,可以使用实时的生产用例和流量来帮助完善在测试环境中错过的功能区域。一旦我们能够可靠地进行流量镜像,就可以开始做一些有价值的事情,例如通过请求流量对比工具Diffy,可以将引入测试集群的流量与生产集群中的预期行为进行比较。例如,我们可能想比较请求结果与预期结果间的偏差,或者API协议中的数据损坏情况,以便更好地兼容。除此之外,需要注意以下问题:·当流量镜像到不同的服务时,会发生在请求的关键路径之外。·忽略对任何镜像流量的响应,镜像流量被视为“即发即忘”。4.3.2流量对比插入一个代理就可以负责对流量的协调,并对其进行有趣的比较。Diffy就是一款这样的代理工具。Diffy启动一个代理服务(例如监听端口8880),再根据用户设置的primary、secondary两个旧服务地址(primary和secondary代码完全相同,目的是为了减少噪音干扰)、candidate新服务地址。Diffy还能够检测结果中的噪音,并通过先调用两个实时服务的实例来忽略它们(例如时间戳、单调递增计数器等提示),总结来说就是检测,然后在测试服务中忽略掉这部分。Diffy还提供了一个不错的页面可以用来查看调用结果、对比情况和基于某些特征的过滤。它还有一个很好的管理控制台,可以查看有关调用比较结果的功能指标(metrics)和统计数据(statistics),如图4-15所示。图4-15服务的调用的结果4.3.3创建用于Istio流量镜像的服务在此任务中,将首先强制所有流量到v1版本的服务。然后,将使用规则将一部分流量镜像到v2版本。首先部署两个版本的示例服务。注意执行以下kubectl命令之前,请先创建命名空间diffy,并为命名空间diffy打上标签istio-injection=enabled。例如,可以通过命令kubectlcreatensdiffy来创建命令空间,通过命令kubectllabelnsdiffyistio-injection=enabled设置标签。下载本书所使用的示例代码之后,切换到目录traffic-sample3可以查看所有相关的代码文件。版本1的部署使用了Docker镜像httpbin,提供常见的http请求访问,具体参见sample-service.yaml中的定义:apiVersion:extensions/v1beta1

kind:Deployment

metadata:

name:mirrorservice-sample-v1

spec:

replicas:1

template:

metadata:

labels:

app:mirrorservice-sample

version:v1

spec:

containers:

-image:docker.io/kennethreitz/httpbin

imagePullPolicy:IfNotPresent

name:mirrorservice-sample

command:["gunicorn","--access-logfile","-","-b",":44134","httpbin:app"]

ports:

-containerPort:44134

版本2的部署使用了自定义的Docker镜像,对应的Dockerfile如下:FROMnginx:latest

COPYdefault.conf/etc/nginx/conf.d/

EXPOSE80

所需的nginx配置文件:server{

listen44134;

server_namelocalhost;

location/{

proxy_passhttp://httpbin-diffy.diffy:8880/;

proxy_http_version1.1;

proxy_set_headerUpgrade$http_upgrade;

proxy_set_headerConnection"upgrade";

}

}

版本2的部署作为Istio的流量镜像目标,在接收到流量之后会转发到Diffy的代理中。当前没有直接将Diffy代理作为Istio流量镜像目标,原因是Diffy代理与Envoy代理目前本身有冲突,无法正常流量转发,因此需要此部署中转一下。apiVersion:extensions/v1beta1

kind:Deployment

metadata:

name:mirrorservice-sample-v2

spec:

replicas:1

template:

metadata:

labels:

app:mirrorservice-sample

version:v2

spec:

containers:

-name:mirrorservice-sample

image:/istio-samples/mirrorservice:0.1

imagePullPolicy:Always

ports:

-containerPort:44134

对应的Kubernetesservice,具体参见sample-service.yaml中的定义:apiVersion:v1

kind:Service

metadata:

name:mirrorservice-sample

spec:

type:ClusterIP

ports:

-name:http

port:44134

selector:

app:mirrorservice-sample

最后,通过执行命令kubectlapply-ndiffy-fsample-service.yaml,创建示例服务以及相应的pod。4.3.4创建流量镜像的Istio策略默认情况下,Kubernetes在服务的两个版本之间进行负载均衡。创建如下流量镜像规则(具体代码参见sample-mirror-policy.yaml)将100%的流量发送到v1,同时指定流量镜像到v2。当流量被镜像时,请求将通过其主机/授权报头发送到镜像服务附上-shadow:apiVersion:networking.istio.io/v1alpha3

kind:DestinationRule

metadata:

name:mirrorservice-sample

spec:

host:mirrorservice-sample

subsets:

-name:v1

labels:

version:v1

-name:v2

labels:

version:v2

apiVersion:networking.istio.io/v1alpha3

kind:VirtualService

metadata:

name:mirrorservice-sample

spec:

hosts:

-mirrorservice-sample

http:

-route:

-destination:

host:mirrorservice-sample

subset:v1

weight:100

mirror:

host:mirrorservice-sample

subset:v2

4.3.5搭建Diffy用于请求流量对比Diffy可以作为代理,截取请求并发送至所有运行的服务实例,通过对比响应结果来发现每次迭代代码中可能存在的问题。其中,Diffy上运行了三类代码实例(如图4-16所示):·线上稳定版本:一个运行线上稳定版本代码的节点。·线上稳定版本备份:同样运行了线上的稳定版本,用于消除噪音。·测试版本:待上线的测试版本,用于和线上环境代码进行对比。图4-16Diffy运行机制在实际Diffy测试中,会发现大部分的接口都会有一定差异,原因是这些响应中存在噪音,噪音可能包括:·server响应中生成的时间戳。·随机生成的数字。·系统服务间的有条件竞争。Diffy能够通过一定的方式清除这类噪音,保证分析结果不被影响。下面的YAML代码(可参见diff.yaml)包括一个Diffy的KubernetesService与一个相应的KubernetesDep-loyment资源定义描述,可以创建出一个可运行的Diffy服务:apiVersion:v1

kind:Service

metadata:

name:httpbin-diffy

labels:

app:httpbin-diffy

spec:

ports:

-name:http-proxy

port:8880

-name:http-admin

port:8881

-name:http-console

port:8888

selector:

app:httpbin-diffy

apiVersion:extensions/v1beta1

kind:Deployment

metadata:

labels:

app:httpbin-diffy

version:v2

name:httpbin-diffy-v2

spec:

replicas:1

selector:

matchLabels:

app:httpbin-diffy

version:v2

template:

metadata:

labels:

app:httpbin-diffy

version:v2

spec:

containers:

-image:diffy/diffy:latest

imagePullPolicy:IfNotPresent

livenessProbe:

exec:

command:

-curl

-localhost:8888

initialDelaySeconds:10

periodSeconds:60

timeoutSeconds:1

name:httpbin-diffy

args:["-candidate=httpbin-candidate:8080","-master.primary=httpbin-master:8080","-master.secondary=httpbin-master:8080","-tocol=http","-serviceName=httpbin","-proxy.port=:8880","-admin.port=:8881","-http.port=:8888",

"-rootUrl='localhost:8888'"]

ports:

-containerPort:8888

name:http-console

protocol:TCP

-containerPort:8880

name:http-proxy

protocol:TCP

-containerPort:8881

name:http-admin

protocol:TCP

readinessProbe:

exec:

command:

-curl

-localhost:8888

initialDelaySeconds:10

periodSeconds:60

timeoutSeconds:1

securityContext:

privileged:false

通过以下YAML(具体可参见httpbin-service.yaml)创建示例所用的primary、secondary(当前示例中与primary相同)与candidate服务:apiVersion:v1

kind:Service

metadata:

name:httpbin-master

labels:

app:httpbin-master

spec:

ports:

-name:http

port:8080

selector:

app:httpbin

version:v1

apiVersion:v1

kind:Service

metadata:

name:httpbin-candidate

labels:

app:httpbin-candidate

spec:

ports:

-name:http

port:8080

selector:

app:httpbin

version:v2

apiVersion:extensions/v1beta1

kind:Deployment

metadata:

name:httpbin-v1

spec:

replicas:1

template:

metadata:

labels:

app:httpbin

version:v1

spec:

containers:

-image:docker.io/kennethreitz/httpbin

imagePullPolicy:IfNotPresent

name:httpbin

command:["gunicorn","--access-logfile","-","-b",":8080","httpbin:app"]

ports:

-containerPort:8080

apiVersion:extensions/v1beta1

kind:Deployment

metadata:

name:httpbin-v2

spec:

replicas:1

template:

metadata:

labels:

app:httpbin

version:v2

spec:

containers:

-image:docker.io/kennethreitz/httpbin

imagePullPolicy:IfNotPresent

name:httpbin

command:["gunicorn","--access-logfile","-","-b",":8080","httpbin:app"]

ports:

-containerPort:8080

4.3.6发送流量进行镜像验证启动sleep服务,这样就可以使用curl来提供负载:cat<<EOF|istioctlkube-inject-f-|kubectlcreate-f-

apiVersion:extensions/v1beta1

kind:Deployment

metadata:

name:sleep

spec:

replicas:1

template:

metadata:

labels:

app:sleep

spec:

containers:

-name:sleep

image:tutum/curl

command:["/bin/sleep","infinity"]

imagePullPolicy:IfNotPresent

EOF

进入到SLEEP_POD,具体POD名称根据实际赋值:kubectlexec-it$SLEEP_POD-csleepsh

发送流量:curl-vhttp://mirrorservice-sample:44134/headers

可以查看v1的访问日志记录,如图4-17所示,创建的请求100%指向了v1。图4-17v1的访问日志记录与此同时,查看Diffy的Web界面,如图4-18所示,可以看到创建的请求也被镜像到DiffyProxy,如图4-19所示。图4-18Diffy查看界面图4-19返回结果的差异结果Diffy能够通过一定的方式清除这类噪音,保证分析结果不被影响,如图4-20所示。图4-20消除噪音后的结果4.4通过Istio管理应用的灰度发布在项目迭代的过程中,不可避免需要上线。上线对应着部署,或者重新部署;部署对应着修改,修改则意味着风险。灰度发布是指用平滑过渡的方式进行发布。灰度发布可以保证整体系统的稳定,在初始发布的时候就可以发现、调整问题,以保证其影响度,而我们平常所说的蓝绿发布、A/B测试、金丝雀发布等是灰度发布的不同方式。1.蓝绿发布蓝绿发布是指不停止老版本,部署新版本,然后进行测试,确认没有问题之后,再将流量切到新版本,然后老版本同时也升级到新版本。这样做的好处是无需停机,并且风险较小。图4-21蓝绿发布示例蓝绿发布的步骤大致如下:1)部署版本1的应用(一开始的状态),所有外部请求的流量都打到这个版本上。2)部署版本2的应用,版本2的代码与版本1不同(新功能、Bug修复等)。3)将流量从版本1切换到版本2,即流量从v1:v2为100:0,切换为0:100。4)如果版本2存在问题,需要回滚到版本1,进行流量切换回v1:v2为100:0。2.A/B测试A/B测试是用来测试应用功能表现的一种方法,例如可用性、受欢迎程度、可见性等。A/B测试通常会针对特定的用户群体进行,其目的在于通过科学的实验设计、采样样本代表性、流量分割与小流量测试等方式来获得具有代表性的实验结论,并确信该结论在推广到全部流量可信;这与蓝绿发布的目的不尽相同,蓝绿发布主要用于安全稳定地发布新版本应用。图4-22A/B测试示例3.金丝雀发布金丝雀发布是指通过让一小部分用户流量引入的新版本进行测试,如果一切顺利,则可以增加(可能逐渐增加)百分比,逐步替换旧版本。如在过程中出现任何问题,则可以中止并回滚到旧版本。最简单的方式是随机选择百分比请求到金丝雀版本,但在更复杂的方案下,则可以基于请求的内容、特定范围的用户或其他属性等。图4-23金丝雀发布示例4.4.1Kubernetes中的灰度发布Kubernetes自带的rolling-update(滚动升级)功能提供了一种渐进式的更新方法,可以实现在不中断业务的情况下进行应用升级。下面简要回顾一下Kubernetes的升级策略:spec:

replicas:5

strategy:

type:RollingUpdate

rollingUpdate:

maxSurge:2

maxUnavailable:2

minReadySeconds:5

上述代码定义了一些关键值,如下所示:·maxSurge:升级过程中最多可以比原先设定多出的pod数量,此值可以为固定值或是比例(%)。例如:maxSurge:1、replicas:5,代表Kubernetes会先开好1个新pod后才删掉一个旧的pod,整个升级过程中最多会有5+1个pod。·maxUnavailable:最多可以有几个pod处在无法服务的状态,当maxSurge不为零时,此值亦不可为零。例如.maxUnavailable:1,代表Kubernetes整个升级过程中最多会有1个pod处在无法服务的状态。·minReadySeconds:容器内应用启动时间,Kubernetes会等待设定的时间后才继续进行升级流程,如果没有此值的话,Kubernetes会假设该容器一开完后即可进行服务。实现滚动升级的方式也有以下几种:kubectlsetimage、kubectlreplace、kubectlrollout。尽管这种机制能够很好地工作,但只适用于部署的经过适当测试的版本,也就是说,更多适用于蓝/绿发布场景。实际上,Kubernetes中的金丝雀发布将使用具有相同Label的两个部署来完成。在这种情况下,我们不能再使用AutoScaler,因为有由两个独立的AutoScaler来进行控制,不同负载情况下,replicas比例(百分比)可能与所需的比例不同。无论我们使用一个还是两个部署,使用Kubernetes进行的金丝雀发布都存在一个根本问题:使用实例扩容来管理流量;这是因为版本流量分发和部署在Kubernetes平台中的副本并非独立。所有pod副本,无论版本如何,在kube-proxy循环池中都被相同对待,因此管理特定版本接收的流量的唯一方法是控制副本比例。以小百分比例的金丝雀流量需要许多副本(例如1%将需要至少100个副本)。即使我们可以忽略这个问题,部署方式功能仍然非常有限,因为它只支持简单(随机百分比)金丝雀部署。如果想根据某些特定规则将请求路由到金丝雀版本上,仍然需要另一种解决方案。这就需要用到Istio。4.4.2使用Istio进行灰度发布在使用Istio实现灰度发布的情况下,流量路由和副本部署是两个完全独立的功能。服务的pod数量可以根据流量负载灵活伸缩,与版本流量路由的控制完全无关。这在自动缩放的情况下能够更加简单地管理金丝雀版本。Istio的路由规则非常灵活,可以支持细粒度控制流量百分比(例如,路由1%的流量而不需要100个pod),也可以使用其他规则来控制流量(例如,将特定用户的流量路由到金丝雀版本)。案例如下所示:apiVersion:networking.istio.io/v1alpha3

kind:VirtualService

metadata:

name:addedvalues

spec:

hosts:

-addedvalues

http:

-match:

-headers:

end-user:

prefix:yunqi

route:

-destination:

host:addedvalues

subset:v3

-route:

-destination:

host:addedvalues

subset:v2

weight:50

-destination:

host:addedvalues

subset:v1

weight:50

4.4.3统一的流量路由规则使用Istio进行灰度发布时,由于不再使用副本比例维持流量分发比例,所以可以安全地设置KubernetesHPA来管理两个版本部署的副本。无论是蓝绿发布,还是A/B测试或金丝雀发布,均可基于Istio提供的统一的流量路由规则定义来实现。可以有基于流量比例的发布、基于请求内容的发布。下面分别介绍。1.基于流量比例的发布Istio根据输入的流量比例来确定流量分发的比重。范围限制为[0,100],例如,当版本v1配置为0,版本v2配置为100时,这种场景即为蓝绿发布。此外,如果版本v1比例设置为x,则x%的服务流量会走向此版本v1,(100-x)%的流量会走向版本v2,即从版本v1分走一部分流量。这种场景即为金丝雀发布或A/B测试。2.基于请求内容的发布基于请求内容的发布会遍历除默认版本外的全部金丝雀规则,若满足某个版本的规则,则流量走向此版本,若全部不满足,则流量会走到默认版本。这种场景即为金丝雀发布或A/B测试中使用到的规则。例如,可以支持如下基于请求内容的分发:·基于浏览器的分发·基于操作系统的分发·基于Cookie的分发·Cookie的cookiename包含string。·存在Cookie的cookiename。·不存在Cookie的cookiename。·基于HTTP请求头的分发·请求头headername包含string。·请求头中包含headername。·请求头中不包含headername针对来自不同浏览器的请求规则定义参见表4-1。表4-1基于浏览器的请求规则针对来自不同操作系统的请求规则定义参见表4-2。表4-2基于操作系统的请求规则针对不同cookie内容的请求规则定义参见表4-3。表4-3基于Cookie的请求规则如上所述,Istio可以支持灵活规则下的金丝雀发布,以及区别于Kubernetes部署方式。Istio服务网格提供了管理流量分配所需的基础控制,并完全独立于AutoScaler,从而允许开发者用简单而强大的方式来进行金丝雀测试和上线操作。4.5本章总结东西向流量管理是服务网格的最重要核心功能之一,也是服务网格区别于类似API网关、Kubernetes入口网关等的关键点。希望读者通过本章可以掌握服务网格Istio的核心元素,如VirtualService、DestinationRule、Sidecar等自定义资源类型,并能够熟练使用这些自定义资源来定义服务的流量管理规则。第5章南北向流量管理在本书的大部分内容中,我们假设单个集群具有单个Istio控制平面部署,但实际上Istio的功能不仅限于单个集群部署,还适合非Kubernetes混合环境的部署。在本章中,我们将介绍将集群外部的客户端连接到集群内运行的服务,以及如何从集群内的服务访问集群外部的任何服务,即通常所说的南北向流量管理。其中介绍了Istio在南北向流量方面的路由控制能力,引出Istio网关的概念及其工作原理,接着介绍了如何通过HTTPS加密Istio网关,以及介绍了基于SNI的TLS路由能力,之后介绍服务条目(ServiceEntry)的概念,详细介绍如何实现出口流量路由的统一管理,最后介绍基于CoreDNSPlugin扩展实现服务条目的DNS寻址。5.1Istio网关网络社区中有一个术语Ingress,是指入口请求到集群内服务的流量管理。Ingress指的是源自本地网络之外的流量,指向本地集群网络中的端点。此流量首先路由到公开的入口点,以便通过执行一些本地网络的规则和策略来确认哪些流量被允许进入。如果流量未通过这些入口点,则无法与集群内的任何服务连接。如果入口点允许流量进入,则将其代理到本地网络中的合适节点。Istio对入口流量的管理是由Istio网关进行的。接下来将会介绍Istio网关的工作机制,以及Istio网关的负载均衡器原理,然后介绍入口网关(IngressGateway)的服务与部署的定义,以及网关资源、网关虚拟服务的定义,最后通过一个示例介绍如何调试入口网关可能遇到的问题。5.1.1Istio网关的工作原理传统上,Kubernetes使用Ingress控制器来处理从外部进入集群的流量。使用Istio时,情况不再如此。Istio网关用新的Gateway资源和VirtualServices资源来控制入口流量,它们协同工作以将流量路由到网格中。在网格内部不需要Gateways,因为服务可以通过集群本地服务名称相互访问。那么Istio网关是怎样工作的?请求如何到达它想要的应用程序?基本步骤如下:1)客户端在特定端口上发出请求。2)负载均衡器在这个端口上进行侦听,并将请求转发到集群中(在相同或新的端口)。3)在集群内部,请求被路由到IstioIngressGateway服务所侦听的负载均衡器转发过来的端口上。4)IstioIngressGateway服务将请求(在相同或新的端口)转发到对应的pod上。5)在IngressGatewaypod上会配置Gateway资源和VirtualService资源定义。Gateway会配置端口、协议以及相关安全证书。VirtualService的路由配置信息用于找到正确的服务。6)IstioIngressGatewaypod会根据路由配置信息将请求路由到对应的应用服务上。7)应用服务将请求路由到对应的应用pod上。Istio网关工作原理如图5-1所示。图5-1Istio网关的工作原理5.1.2Istio网关的负载均衡作用典型的服务网格具有一个或多个负载均衡器,也称为网关(Gateway),它们从外部网络终止TLS并允许流量进入网格。然后,流量通过边车网关(Sidecargateway)流经内部服务。应用程序使用外部服务的场景也很常见,可以直接调用外部服务,或者在某些部署中强制通过专用出口网关(EgressGateway)离开网格的所有流量。图5-2描绘了网关在网格中的使用情况。Istio具有入口网关的概念,它扮演网络入口点的角色,负责保护和控制来自集群外部的流量对集群的访问。图5-2网关在网格中的使用情况此外,Istio的网关还扮演负载均衡和虚拟主机路由的角色。如图5-3所示,可以看到默认情况下Istio使用Envoy代理作为入口代理。我们在前面的章节中看到,Envoy是一个功能强大的服务到服务代理,但它也有负载均衡和路由的功能,可代理的流量包括从服务网格外部到其内部运行的服务,或者从集群内部服务到外部服务。在前面章节中介绍的Envoy的所有功能也可以在入口网关中使用。图5-3Istio的入口网关服务对于入口流量管理,你可能会问:为什么不直接使用KubernetesIngressAPI?第一个原因,KubernetesIngress是一个面向HTTP工作负载的非常简单的规范。有KubernetesIngress的实现(如Nginx、HeptioContour等),但每个都适用于HTTP流量。实际上,Ingress规范只将端口80和端口443视为入口点。这严重限制了集群运维人员可以允许进入服务网格的流量类型。例如,如果你有Kafka工作负载,则可能希望向这些消息代理公开直接TCP连接。第二个原因,KubernetesIngressAPI无法表达Istio的路由需求。Ingress没有通用的方法来指定复杂的流量路由规则,如流量拆分或流量镜像等。这个领域缺乏规范会导致每个供应商重新设想如何更好地为每种类型的Ingress实现(如HAProxy、Nginx等)做好配置管理。Ingress试图在不同的HTTP代理之间取一个公共的交集,因此只能支持最基本的HTTP路由。最后一个原因,由于事前没有明确规定,大多数供应商的选择是通过部署上的定制注释来做配置。供应商之间的注释各不相同,并且不可移植,如果Istio继续延续这种趋势,那么就会有更多的注释来解释Envoy作为边缘网关的所有功能。Istio网关通过将L4-L6配置与L7配置分离克服了Ingress的这些缺点。Istio网关只用于配置L4-L6功能(例如,对外公开的端口、TLS配置),所有主流的L7代理均以统一的方式实现了这些功能。然后,通过在Gateway上绑定VirtualService的方式,可以使用标准的Istio规则来控制进入Gateway的HTTP和TCP流量。负载均衡器可以手动配置或通过服务自动配置其类型,例如type:LoadBalancer。在这种情况下,由于并非所有云都支持自动配置,假设手动配置负载均衡器以将流量转发到IngressGatewayService正在侦听的端口。例如如下的负载均衡器正在监听以下端口:·HTTP:端口80,将流量转发到端口30080。·HTTPS:端口443,将流量转发到端口30443。·MySQL:端口3306,将流量转发到端口30306。确保负载均衡器配置转发到所有工作节点。这将确保即使某些节点关闭也会转发流量。5.1.3入口网关服务IngressGateway服务(入口网关服务)必须监听上节介绍的所有端口,以便能够将流量转发到IngressGatewaypod上。Kubernetes服务不是“真正的”服务,该请求将由Kubernetes提供的kube-proxy转发到具有运行对应pod的节点上。在节点上,IPtable配置将请求转发到适当的pod:ports:

-name:http2

nodePort:30000

port:80

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论