Istio如何同时实现Hytrix|Ribbon|Zuul|微服务安全的功能?:为微服务引入Istio服务网格(下)

版权说明:本文由高晓雪参照如下文档翻译。魏新宇根据高晓雪的翻译文档,做了适当的注解和文字矫正。

https://developers.redhat.com/download-manager/file/istio_mesh_for_microservices_r1.pdf

本文适合对istio的读者提供泛读参考,对istio理解较深的读者,建议直接阅读英文原文。本系列分上下两篇:上篇为1-3章内容,下篇为4-7章内容。

目录

为微服务引入Istio服务网格

1.介绍

1.1.更快的挑战

1.2.认识Istio

1.3.了解Istio组件

1.3.1.数据平面

1.3.2.控制平面

2.安装和入门

2.1.命令行工具安装

2.2.Kubernetes / OpenShift安装

2.3.Istio安装

2.3.1.安装Istio命令行工具

2.4.Java微服务安装示例

2.4.1.浏览代码库

2.4.2.建立和部署客户服务

2.4.3.构建和部署首选项服务

2.4.4.建立和部署推荐服务

2.4.5.构建和部署到Kubernetes

3.交通管制

3.1. 更高级的金丝雀版

3.3.1.交通路由

3.3.2.路由到特定版本的部署

3.3.3.基于头的路由

3.2.黑暗发射

3.3.出口

4.服务弹性

4.1.负载平衡

4.2.超时

4.3.重试

4.4.断路器

4.5.池射出

4.6.组合:断路器+池弹出+重试

5.混沌测试

5.1.HTTP错误

5.2.延迟

6.观测

6.1.跟踪

6.2.指标

7.安全

7.1.黑名单

7.2.白名单

7.3.结论

4.服务弹性

大魏注:

Spring Cloud的微服务架构组件如下:

本文将讨论istio如何实现Hytrix|Ribbon|Zuul|微服务安全的功能

请记住,您的服务和应用程序将通过不可靠的网络进行通信。过去,开发人员经常试图使用框架(EJB,CORBA,RMI等)来简单地使网络调用看起来像本地方法调用一样。这给了开发人员一种虚假的安宁。在没有确保应用程序积极防范网络故障的情况下,整个系统容易出现级联故障。因此,你永远不应该假设你的应用程序或微服务通过网络访问的远程依赖关系可以保证以有效负载作出响应,也不会在特定的时间范围内响应(或者根本不需要。)作为Douglas Adams,“The Hitchhiker's Guide to the银河曾经说过,“人们在设计一个完全万无一失的设计时常犯的错误就是低估了傻子的聪明才智”)。您不希望单一服务的不当行为成为拖累您业务目标的灾难性失败。

Istio具有很多实现应用程序弹性的功能,但正如我们前面提到的,这些功能的实际执行发生在sidecar上。这意味着此处列出的弹性功能不针对任何特定的运行时间;它们适用于您选择编写服务的库或框架:

客户端负载平衡

Istio增强了Kubernetes开箱即用的负载均衡。

时间到

只等待N秒钟,然后放弃。

重试

如果一个窗格返回错误(例如503),请重试另一个窗格。

简单的断路器

不要压低退化的服务,打开电路并拒绝进一步的请求。

Pool Ejection

这提供了从负载平衡池自动清除容易出错的窗格。

我们来看看每个功能的例子。在这里,我们使用前面例子中相同的一组服务。

4.1.负载平衡

==============================================================================

大魏注:

在没有istio的情况下,Openshift中应用的负载均衡可以通过router来实现:

当一个应用对应多个pod,routing layer将会做不同pod之间的负载均衡。负载均衡有三种策略:

roundrobin、leastconn、source。

roundrobin:根据每个pod的权重,平均轮询分配。在不改变routing的默认规则下,每个pod的权重一样,haproxy转发包也是轮着来。

如果我们更改了每个pod的权重,那轮询的时候,也会根据权重来转发请求。如下图:V2和V1是3:2。那么haproxy会给V2发两个包,给V1发一个,周而复始。

leastconn:routing layer转发请求的时候,按照哪个pod的连接数最少,将新的请求发给连接数最少的pod。一般这种方式适合长连接,短链接不建议使用。

source:将源IP地址先进行哈希,然后除以正在运行的pod总权重,然后算出哪个节点接受请求。这确保了只要没有服务器发生故障,相同的客户端IP地址将始终到达同一个pod。

三种方式,可以通过设置routing layer的环境变量来实现。

但routing layer实现的应用的负载均衡,主要是外部流量的入口,而OCP内部,微服务之间的负载均衡是无法做到的,而istio可以。

====================================================================

提高吞吐量和降低延迟的核心功能是负载平衡。实现这一点的直接方式是拥有一个集中式负载均衡器,所有客户端都可以与之通信并知道如何将负载分配给任何后端系统。这是一个很好的方法,但它既可能成为瓶颈,也可能成为单点故障。负载均衡功能可以通过客户端负载均衡器分配给客户端。这些客户端负载平衡器可以使用复杂的特定于集群的负载平衡算法来提高可用性,降低延迟并提高整体吞吐量。 Istio代理具有通过以下可配置算法提供客户端负载平衡的功能:

ROUND_ROBIN

该算法将负载按顺序均匀分配到负载平衡池中的端点

随机

这将负载平均分配到负载平衡池中的端点上,但没有任何顺序。

LEAST_CONN

该算法从负载平衡池中选取两个随机主机,并确定哪个主机中有较少的未完成请求(两者中的)并发送到该端点。这是加权最小请求负载均衡的实现。

在之前的路由章节中,您看到了使用RouteRules来控制流量如何路由到特定的集群。在本章中,我们向您展示如何使用目标策略规则控制与特定群集进行通信的行为。首先,我们讨论如何使用Istio DestinationPolicy规则配置负载平衡。

首先,确保没有任何RouteRules可能会影响我们推荐服务的v1和v2流量负载均衡。你可以像这样删除所有RouteRules:

istioctl deleterouterule --all

接下来,您可以将推荐服务副本放大到3:

oc scaledeployment recommendation-v2 --replicas=3 -n tutorial

等待所有容器变得健康并准备好交通。现在,使用您之前使用的相同脚本将流量发送到您的群集:

#!/bin/bash

while true

do curl customer-tutorial.$(minishift ip).nip.io

sleep .1

done

您应该看到基于输出的循环式负载分布:

customer => preference => recommendation v1 from '99634814':1145

customer => preference => recommendation v2 from '2819441432':1

customer => preference => recommendation v2 from '2819441432':2

customer => preference => recommendation v2 from '2819441432':181

customer => preference => recommendation v1 from '99634814':1146

customer => preference => recommendation v2 from '2819441432':3

customer => preference => recommendation v2 from '2819441432':4

customer => preference => recommendation v2 from '2819441432':182

现在,将负载均衡算法更改为RANDOM。以下是Istio DestinationPolicy的外观:

apiVersion: config.istio.io/v1alpha2

kind: DestinationPolicy

metadata:

name: recommendation-loadbalancer

namespace: tutorial

spec:

source:

name: preference

destination:

name: recommendation

loadBalancing:

name: RANDOM

此目标策略将配置从首选服务到推荐服务的流量,以使用随机负载平衡算法发送。

我们来创建这个目标策略:

istioctl create-f istiofiles/recommendation_lb_policy_app.yml -n tutorial

当您致电您的服务时,您现在应该会看到更随机的分布:

customer => preference => recommendation v2 from '2819441432':10

customer => preference => recommendation v2 from '2819441432':3

customer => preference => recommendation v2 from '2819441432':11

customer => preference => recommendation v1 from '99634814':1153

customer => preference => recommendation v1 from '99634814':1154

customer => preference => recommendation v1 from '99634814':1155

customer => preference => recommendation v2 from '2819441432':12

customer => preference => recommendation v2 from '2819441432':4

customer => preference => recommendation v2 from '2819441432':5

customer => preference => recommendation v2 from '2819441432':13

customer => preference => recommendation v2 from '2819441432':14

因为在本章剩余部分中您将制定更多的目的地政策,现在是清理的好时机:

istioctl delete-f istiofiles/recommendation_lb_policy_app.yml \

-n tutorial

4.2.超时

超时是使系统具有弹性和可用性的关键组件。 通过网络调用服务可能导致很多不可预知的行为,但最糟糕的行为是延迟。服务是否失败? 它只是慢吗? 它甚至不可用? 无限延迟意味着任何这些事情都可能发生。 但是你的服务是做什么的? 只是坐在旁边等着? 如果请求的另一端有客户,等待不是一个好的解决方案。 等待也会使用资源,导致其他系统潜在等待,并且通常是级联故障的贡献者。您的网络流量应该总是有超时,并且您可以使用Istio服务网格来执行此操作。

如果您查看推荐服务,请查找RecommendationVerticle.java类并取消注释引入服务延迟的行。在继续之前,您应该保存您的更改:

@Override

public voidstart() throws Exception {

Router router =Router.router(vertx);

//router.get("/").handler(this::timeout);

router.get("/").handler(this::logging);

router.get("/").handler(this::getRecommendations);

router.get("/misbehave").handler(this::misbehave);

router.get("/behave").handler(this::behave);

HealthCheckHandlerhc = HealthCheckHandler.create(vertx);

hc.register("dummy-health-check",future ->

future.complete(Status.OK()));

router.get("/health").handler(hc);

vertx.createHttpServer().requestHandler(router::accept).listen(8080);

}

您现在可以构建该服务并进行部署:

cd recommendation

mvn clean package

docker build -t example/recommendation:v2 .

oc delete pod -l app=recommendation,version=v2 -n tutorial

最后一步是使用最新的Docker镜像重新启动v2 pod推荐服务。现在,如果你打电话给你的客户服务端点,你应该在呼叫登录v2服务时遇到延迟:

$ time curlcustomer-tutorial.$(minishift ip).nip.io

customer =>preference => recommendation v2 from '751265691-qdznv': 2

real 0m3.054s

user 0m0.003s

sys 0m0.003s

请注意,您可能需要拨打电话几次才能将其路由到v2服务。推荐的v1版本没有延迟。让我们来看看您的RouteRule,它引入了一个在致电推荐服务时强制超时的规则:

apiVersion: config.istio.io/v1alpha2

kind: RouteRule

metadata:

name: recommendation-timeout

spec:

destination:

namespace: tutorial

name: recommendation

precedence: 1

route:

- labels:

app: recommendation

httpReqTimeout:

simpleTimeout:

timeout: 1s

您现在可以创建此路由规则:

istioctl create -f istiofiles/route-rule-recommendation-timeout.yml\

-n tutorial

现在,当您将流量发送到客户服务时,如果路由到v2,您应该看到成功的请求(如果路由到建议的v1)或504上游请求超时错误:

$ time curlcustomer-tutorial.$(minishift ip).nip.io

customer =>503 preference => 504 upstream request timeout

real 0m1.151s

user 0m0.003s

sys 0m0.003s

您可以通过删除此路由规则进行清理:

istioctldelete routerule recommendation-timeout -n tutorial

4.3.重试

因为您知道网络不可靠,您可能会遇到短暂的间歇性错误。随着分布式微服务每周快速部署数次甚至一天,这可能会更加明显。该服务或吊舱可能只是简单地停机。借助Istio的重试功能,您可以在真正处理错误之前进行更多的尝试,并可能回到默认逻辑。在这里,我们向您展示如何配置Istio来做到这一点。

您需要做的第一件事是模拟瞬时网络错误。您可以在Java代码中执行此操作,但是您将使用Istio。您将在推荐服务呼叫中注入瞬态HTTP 503错误。我们在第5章更详细地介绍了故障注入,但目前,相信安装以下路由规则将引入HTTP 503错误:

istioctl create-f istiofiles/route-rule-recommendation-v2_503.yml \

-n tutorial

现在,当您将流量发送到客户服务时,您应该会看到间歇性的503错误:

#!/bin/bash

while true

do

curl customer-tutorial.$(minishift ip).nip.io

sleep .1

done

customer => preference => recommendation v2 from '2036617847':190

customer => preference => recommendation v2 from '2036617847':191

customer => preference => recommendation v2 from '2036617847':192

customer => 503 preference => 503 fault filter abort

customer => preference => recommendation v2 from '2036617847':193

customer => 503 preference => 503 fault filter abort

customer => preference => recommendation v2 from '2036617847':194

customer => 503 preference => 503 fault filter abort

customer => preference => recommendation v2 from '2036617847':195

customer => 503 preference => 503 fault filter abort

让我们来看看一个指定您的重试配置的RouteRule:

apiVersion: config.istio.io/v1alpha2

kind: RouteRule

metadata:

name: recommendation-v2-retry

spec:

destination:

namespace: tutorial

name: recommendation

precedence: 3

route:

- labels:

version: v2

httpReqRetries:

simpleRetry:

perTryTimeout: 2s

attempts: 3

此规则将您的重试尝试设置为3,并将为每次重试使用2s超时。因此,累计超时时间为原来的通话超时6秒。(要指定总超时时间,请参阅关于超时的上一节。)

让我们创建您的重试规则并再次尝试流量:

istioctl create -f istiofiles/route-rule-recommendation-v2_retry.yml\

-n tutorial

现在,当你发送流量时,你不应该看到任何错误。这意味着,即使您正在体验503s,Istio也会自动重新尝试请求您,如下所示:

customer => preference => recommendation v2 from'751265691-n65j9': 35

customer => preference => recommendation v2 from'751265691-n65j9': 36

customer => preference => recommendation v2 from'751265691-n65j9': 37

customer => preference => recommendation v2 from'751265691-n65j9': 38

customer => preference => recommendation v2 from'751265691-n65j9': 39

customer => preference => recommendation v2 from'751265691-n65j9': 40

customer => preference => recommendation v2 from'751265691-n65j9': 41

customer => preference => recommendation v2 from'751265691-n65j9': 42

customer => preference => recommendation v2 from'751265691-n65j9': 43

现在你可以清理你安装的所有路由规则:

oc delete routerule --all

4.4.断路器

就像现代家庭中的电气安全机制(我们曾经拥有保险丝盒,“吹掉保险丝”仍然是我们的白话的一部分),断路器确保任何特定的器具不会通过特定的插座超出电流。如果你曾经和一个插入收音机,吹风机或者便携式加热器的人住在同一个电路中,那么你可能已经看到了这一点。电流透支会造成危险情况,因为您可能会过热导线,从而导致火灾。断路器断开并断开电流。

Michael Nygard在其着作“ReleaseIt”中首次提出了软件系统的断路器和隔板的概念。这本书是在2007年首次发布的,早在微软服务这个词被创造出来之前。这本书的第二版刚刚在2018年发布。

随着2012年Netflix的Hystrix图书馆的发布,断路器和舱壁的图案得到了普及。诸如Eureka(服务发现),Ribbon(负载平衡)和Hystrix(断路器和舱壁)等Netflix图书馆迅速变得非常流行,许多人在业界也开始关注微服务和云本地架构。 Netflix OSS是在有Kubernetes / OpenShift之前构建的,它有一些缺点:一是Javaonly,二是它需要应用程序开发人员正确使用嵌入库。图4-1提供了一个时间表,从软件行业试图打破单一应用程序开发团队和大量多月瀑布工作流程开始,到Netflix OSS的诞生和“微服务”这个术语的创造。

图4-1.微服务时间表

Istio将更多的弹性实施纳入基础架构,以便您可以将更多宝贵的时间和精力专注于代码,从而将其业务与日益增长的竞争领域区分开来。

Istio在连接池级别和负载平衡主机级别实现断路。我们将向您展示两者的例子。

要探索连接池断路,请确保建议v2服务启用了3s超时(从上一节开始)。 RecommendationVerticle.java文件应该与此类似:

Router router = Router.router(vertx);

router.get("/").handler(this::logging);

router.get("/").handler(this::timeout);

router.get("/").handler(this::getRecommendations);

router.get("/misbehave").handler(this::misbehave);

router.get("/behave").handler(this::behave);

您将使用此Istio RouteRule将流量路由到建议的v1和v2:

istioctl create -f \

istiofiles/route-rule-recommendation-v1_and_v2_50_50.yml -n tutorial

从最初的安装说明,我们建议您安装seige命令行工具。您可以使用此命令通过简单的命令行界面(CLI)进行负载测试。

我们将使用20个客户端发送两个请求(同时)。使用以下命令来执行此操作:

siege -r 2 -c 20 -v customer-tutorial.$(minishiftip).nip.io

你应该看到类似这样的输出:

所有对您系统的请求都是成功的,但是运行测试需要一些时间,因为v2实例或pod是一个缓慢的执行者。请注意,每次调用v2时,都需要三秒或更长时间才能完成(这是来自您启用的延迟功能)。

但是假设在生产系统中,这个三秒延迟是由于对同一个实例或pod的并发请求太多造成的。您不希望多个请求排队或使该实例或pod更慢。所以,我们将添加一个断路器,只要有多个请求被任何实例或pod处理,就会打开。

要为我们的服务创建断路器功能,我们使用如下所示的Istio Destina tionPolicy:

apiVersion: config.istio.io/v1alpha2

kind: DestinationPolicy

metadata:

name: recommendation-circuitbreaker

spec:

destination:

namespace: tutorial

name: recommendation

labels:

version: v2

circuitBreaker:

simpleCb:

maxConnections: 1

httpMaxPendingRequests: 1

sleepWindow: 2m

httpDetectionInterval: 1s

httpMaxEjectionPercent: 100

httpConsecutiveErrors: 1

httpMaxRequestsPerConnection: 1

在此,您正在为任何呼叫推荐服务v2的客户端配置断路器。请记住,在前一个RouteRule中,您正在分割(50%)v1和v2之间的流量,所以此DestinationPolicy对于一半流量应该有效。您将连接数和待处理请求的数量限制为一个。(我们将在下一节讨论其他设置,我们将在其中探讨异常值检测。)让我们来创建这个断路器策略:

istioctl create -fistiofiles/recommendation_cb_policy_version_v2.yml \

-n tutorial

现在再试一次seige负载生成器:

siege-r 2 -c 20 -v customer-tutorial.$(minishift ip).nip.io

现在您可以看到几乎所有的呼叫都在不到一秒的时间内完成,无论成功还是失败。 您可以尝试几次以查看此行为是否一致。 断路器将短路任何超出指定阈值的待处理请求或连接(在这种情况下,为了演示这些功能,此数字为人为低数字1)。您可以清理这些目标策略并路由这样的规则:

istioctl delete routerule recommendation-v1-v2 -n tutorial

istioctl delete -fistiofiles/recommendation_cb_policy_version_v2.yml

4.5.Pool Ejection

大魏注:

所谓的 Pool Ejection 就是当某些实例出现错误(如返回 5xx 错误码)临时将该实例弹出一段时间后(窗口期,可配置),然后再将其加入到负载均衡池中。我们的例子中配置的窗口期是 15 秒。

我们讨论的最后一种弹性功能与识别行为不良的集群主机有关,并且不会在冷静时期向它们发送更多流量。由于Istio代理基于Envoy,Envoy将此实现称为异常检测,因此我们将使用相同的术语来讨论Istio。

池弹出或异常检测是一种弹性策略,只要您有一个实例池或Pod来提供客户端请求,就会发生这种策略。如果请求被转发到某个实例并失败(例如返回50x错误代码),则Istio会将该实例从池中弹出以获得特定的睡眠窗口。在我们的例子中,睡眠窗口被配置为15s。这通过确保只有健康的豆荚参与实例池来提高整体可用性。

首先,你需要确保你有一个RouteRule。我们使用50/50的流量划分:

oc create -fistiofiles/route-rule-recommendation-v1_and_v2_50_50.yml \

-n tutorial

接下来,您可以扩展建议的v2部署的pod数量,以便负载平衡池中有一些主机可以工作:

oc scaledeployment recommendation-v2 --replicas=2 -n tutorial

等待所有的豆荚进入就绪状态。您可以通过以下方式观看他们的进展:

oc get pods -w

现在,让我们针对客户服务产生一些简单的负载:

#!/bin/bash

while true

do curl customer-tutorial.$(minishift ip).nip.io

sleep .1

done

您将看到两种不同版本的推荐服务之间的负载平衡50/50。在v2版本中,您还将看到一些请求由一个窗格处理,一些请求由另一个窗格处理:

customer => preference => recommendation v1 from '2039379827':447

customer => preference => recommendation v2 from '2036617847':26

customer => preference => recommendation v1 from '2039379827':448

customer => preference => recommendation v2 from '2036617847':27

customer => preference => recommendation v1 from '2039379827':449

customer => preference => recommendation v1 from '2039379827':450

customer => preference => recommendation v2 from '2036617847':28

customer => preference => recommendation v1 from '2039379827':451

customer => preference => recommendation v1 from '2039379827':452

customer => preference => recommendation v2 from '2036617847':29

customer => preference => recommendation v2 from '2036617847':30

customer => preference => recommendation v2 from '2036617847':216

要测试异常值检测,您需要其中一个窗格错误。找到其中一个并登录并指示它行事不端:

oc get pods -lapp=recommendation,version=v2

你应该看到这样的东西:

recommendation-v2-2036617847 2/2 Running 0 1h

recommendation-v2-2036617847-spdrb 2/2 Running 0 7m

现在你可以进入一个豆荚并在其上添加一些不稳定的行为。从您的系统获取一个pod名称,并相应地替换以下命令:

oc exec -itrecommendation-v2-2036617847-spdrb -c recommendation /bin/bash

您将位于您的Pod建议v2-2036617847-spdrb的应用程序容器中。现在执行:

curl localhost:8080/misbehave

exit

这是一个特殊的端点,它将使我们的应用程序仅返回503s。

#!/bin/bash

while true

do curl customer-tutorial.$(minishift ip).nip.io

sleep .1

done

您会看到只要Pod建议-v2-2036617847-spdrb收到请求,就会得到503错误:

customer => preference => recommendation v1 from '2039379827':495

customer => preference => recommendation v2 from '2036617847':248

customer => preference => recommendation v1 from '2039379827':496

customer => preference => recommendation v1 from '2039379827':497

customer => 503 preference => 503 recommendation misbehaviorfrom '2036617847-spdrb'

customer => preference => recommendation v2 from '2036617847':249

customer => preference => recommendation v1 from '2039379827':498

customer => 503 preference => 503 recommendation misbehaviorfrom '2036617847-spdrb'

现在让我们看看配置Istio以抛出行为不端的主机时会发生什么。看看下面的DestinationPolicy:

istiofiles/recommendation_cb_policy_pool_ejection.yml

apiVersion: config.istio.io/v1alpha2

kind: DestinationPolicy

metadata:

name: recommendation-poolejector-v2

namespace: tutorial

spec:

destination:

namespace: tutorial

name: recommendation

labels:

version: v2

loadBalancing:

name: RANDOM

circuitBreaker:

simpleCb:

httpConsecutiveErrors: 1

sleepWindow: 15s

httpDetectionInterval:5s

httpMaxEjectionPercent:100

在此DestinationPolicy中,您将Istio配置为每隔五秒检查一次行为异常的主机,并在发生一个连续错误(本示例中为人为低)之后从负载平衡池移除主机。您愿意弹出高达100%的主机(实际上暂时中止群集的任何流量)。

istioctl create -fistiofiles/recommendation_cb_policy_pool_ejection.yml \

-n tutorial

现在让我们对服务进行一些加载并查看其行为:

#!/bin/bash

while true

do curl customer-tutorial.$(minishift ip).nip.io

sleep .1

Done

您将看到,无论何时从podrecommendation-v2-2036617847-spdrb中获取503请求失败,它都会从池中弹出,并且在睡眠窗口过期之前它不会收到任何更多请求 - 这需要至少15秒。

customer =>preference => recommendation v1 from '2039379827': 509

customer =>503 preference => 503 recommendation misbehavior from '2036617847'

customer =>preference => recommendation v1 from '2039379827': 510

customer =>preference => recommendation v1 from '2039379827': 511

customer =>preference => recommendation v1 from '2039379827': 512

customer =>preference => recommendation v1 from '2039379827': 513

customer =>preference => recommendation v1 from '2039379827': 514

customer =>preference => recommendation v2 from '2036617847': 256

customer =>preference => recommendation v2 from '2036617847': 257

customer =>preference => recommendation v1 from '2039379827': 515

customer =>preference => recommendation v2 from '2036617847': 258

customer =>preference => recommendation v2 from '2036617847': 259

customer =>preference => recommendation v2 from '2036617847': 260

customer =>preference => recommendation v1 from '2039379827': 516

customer =>preference => recommendation v1 from '2039379827': 517

customer =>preference => recommendation v1 from '2039379827': 518

customer =>503 preference => 503 recommendation misbehavior from '2036617847'

customer =>preference => recommendation v1 from '2039379827': 519

customer =>preference => recommendation v1 from '2039379827': 520

customer =>preference => recommendation v1 from '2039379827': 521

customer =>preference => recommendation v2 from '2036617847': 261

customer =>preference => recommendation v2 from '2036617847': 262

customer =>preference => recommendation v2 from '2036617847': 263

customer =>preference => recommendation v1 from '2039379827': 522

customer =>preference => recommendation v1 from '2039379827': 523

customer =>preference => recommendation v2 from '2036617847': 264

customer =>preference => recommendation v1 from '2039379827': 524

customer =>preference => recommendation v1 from '2039379827': 525

customer =>preference => recommendation v1 from '2039379827': 526

customer =>preference => recommendation v1 from '2039379827': 527

customer =>preference => recommendation v2 from '2036617847': 265

customer =>preference => recommendation v2 from '2036617847': 266

customer =>preference => recommendation v1 from '2039379827': 528

customer =>preference => recommendation v2 from '2036617847': 267

customer =>preference => recommendation v2 from '2036617847': 268

customer =>preference => recommendation v2 from '2036617847': 269

customer =>503 preference => 503 recommendation misbehavior from '2036617847'

customer =>preference => recommendation v1 from '2039379827': 529

customer =>preference => recommendation v2 from '2036617847': 270

4.6.组合:断路器+池弹出+重试

即使使用弹出池,您的应用程序也不会显得有弹性。这可能是因为你仍然会让一些错误传播给你的客户。但你可以改善这一点。如果某个特定服务的实例或版本足够运行到您的系统中,则可以将多个Istio功能组合起来以实现最终的后端弹性:

  • 断路器避免多个并发请求到一个实例
  • 池弹出从响应实例池中移除失败的实例
  • 重试以将请求转发给另一个实例,以防万一您得到断路器或池弹出

通过简单地将重试配置添加到我们当前的RouteRule中,我们能够完全摆脱我们的503s请求。这意味着每当你从弹出的实例收到失败的请求时,Istio都会将请求转发给另一个理想的健康实例:

istioctl replace-f istiofiles/route-rule-recommendation-v1_and_v2_retry.yml

在客户端点抛出一些请求:

#!/bin/bash

while true

do curl customer-tutorial.$(minishift ip).nip.io

sleep .1

done

您将不再收到503,但推荐v2的请求仍然需要更多时间才能得到回复:

customer => preference => recommendation v1 from '2039379827':538

customer => preference => recommendation v1 from '2039379827':539

customer => preference => recommendation v1 from '2039379827':540

customer => preference => recommendation v2 from '2036617847':281

customer => preference => recommendation v1 from '2039379827':541

customer => preference => recommendation v2 from '2036617847':282

customer => preference => recommendation v1 from '2039379827':542

customer => preference => recommendation v1 from '2039379827':543

customer => preference => recommendation v1 from '2039379827':544

customer => preference => recommendation v2 from '2036617847':283

customer => preference => recommendation v2 from '2036617847':284

customer => preference => recommendation v1 from '2039379827':545

customer => preference => recommendation v1 from '2039379827':546

customer => preference => recommendation v1 from '2039379827':547

customer => preference => recommendation v2 from '2036617847':285

customer => preference => recommendation v2 from '2036617847':286

customer => preference => recommendation v1 from '2039379827':548

customer => preference => recommendation v2 from '2036617847':287

customer => preference => recommendation v2 from '2036617847':288

customer => preference => recommendation v1 from '2039379827':549

customer => preference => recommendation v2 from '2036617847':289

customer => preference => recommendation v2 from '2036617847':290

customer => preference => recommendation v2 from '2036617847':291

customer => preference => recommendation v2 from '2036617847':292

customer => preference => recommendation v1 from '2039379827':550

customer => preference => recommendation v1 from '2039379827':551

customer => preference => recommendation v1 from '2039379827':552

customer => preference => recommendation v1 from '2039379827':553

customer => preference => recommendation v2 from '2036617847':293

customer => preference => recommendation v2 from '2036617847':294

由于Pool Ejection和重试,您的控制台中永远不会显示您行为不当的pod建议-v2-2036617847-spdrb。清理(注意,我们将保留路线规则,因为这些规则将在下一章中使用):

oc scale deployment recommendation-v2 --replicas=1 -n tutorial

oc delete pod -l app=recommendation,version=v2

oc delete routerule recommendation-v1-v2 -n tutorial

istioctl delete -f istiofiles/recommendation_cb_policy_pool_ejection.yml-n tutorial

5.混沌测试

一个名为Chaos Monkey的比较着名的OSS项目来自Netflix的开发团队,它对IT世界的揭示颇具破坏性。Netflix已经构建了随机在生产环境中杀死各种服务的代码,引发了人们的思想。当许多团队努力保持正常运行时间的要求时,提倡自我破坏和攻击自己似乎非常疯狂。然而,从混沌猴出生的那一刻起,就出现了一个新的运动:混沌工程。

根据混沌工程原理网站的说法,“混沌工程是一个在分布式系统上进行实验的学科,以便建立对系统抵御湍流的能力的信心生产条件“。(你可以在http://principlesofchaos.org/阅读更多内容)。

在复杂的系统(软件系统或生态系统)中,事情确实会失败,但最终目标是停止整个系统的灾难性故障。那么你如何验证你的整个系统 - 你的微服务网络 - 实际上是有弹性的?你注入一点混乱。使用Istio,这是一个相对简单的问题,因为istio-proxy拦截所有网络流量,因此它可以改变响应,包括响应所需的时间。 Istio容易注入的两个有趣的错误是HTTP错误代码和网络延迟。

5.1.HTTP错误

这个简单的概念允许您在系统内出现随机故障时探索整个系统的行为。在使用Istio的RouteRule构造时,抛出一些HTTP错误实际上非常简单。根据本书前面的练习,建议v1和v2都部署并且随机负载平衡,因为这是Kubernetes / OpenShift中的默认行为。如果在之前的练习中使用过,请务必注释掉“超时”行。现在,您将通过Istio注入错误和超时而不是使用Java代码:

oc get pods -l app=recommendation -n tutorial

NAME READY STATUS RESTARTS AGE

recommendation-v1-3719512284-7mlzw 2/2 Running 6 18h

recommendation-v2-2815683430-vn77w 2/2Running 0 3h

我们使用Istio RouteRule来注入一定比例的错误,在这种情况下,返回50%的HTTP 503:

apiVersion: config.istio.io/v1alpha2

kind: RouteRule

metadata:

name: recommendation-503

spec:

destination:

namespace: tutorial

name: recommendation

precedence: 2

route:

- labels:

app: recommendation

httpFault:

abort:

percent: 50

httpStatus: 503

并且您使用istroctl命令行工具应用RouteRule:

istioctl create-f istiofiles/route-rule-recommendation-503.yml -n tutorial

测试更改与在客户端发出一些curl命令一样简单。确保几次测试它,大约50%的时间寻找结果503。

curl customer-tutorial.$(minishift ip).nip.io

customer => preference => recommendation v1 from'99634814-sf4cl': 88

curl customer-tutorial.$(minishift ip).nip.io

customer => 503 preference => 503 fault filter abort

清理:

istioctl delete-f istiofiles/route-rule-recommendation-503.yml -n tutorial

5.2.延迟

可能的分布式计算故障中最危险的并不是“死”服务,而是一种响应速度很慢的服务,可能会导致服务网络中的级联故障。更重要的是,如果您的服务必须符合特定的服务级别协议(SLA),那么您如何验证您的依赖关系的缓慢不会导致您无法交付给您等待的客户?通过注入网络延迟,您可以查看关键服务或三个关键服务是如何为一定比例的响应添加显着的额外时间时系统的行为方式。

就像HTTP故障注入一样,网络延迟也使用RouteRule类型。以下YAML向推荐服务的回复中的50%注入了7秒的延迟时间:

apiVersion:config.istio.io/v1alpha2

kind: RouteRule

metadata:

name: recommendation-delay

spec:

destination:

namespace: tutorial

name: recommendation

precedence: 2

route:

- labels:

app: recommendation

httpFault:

delay:

percent: 50

fixedDelay: 7s

使用istioctlcreate命令来应用新的RouteRule:

istioctl create -fistiofiles/route-rule-recommendation-delay.yml \

-n tutorial

然后,在客户端发送一些请求,并注意前面的“时间”命令。这个命令会将每个响应的经过时间输出到curl命令,让你看到那个七秒的延迟。

#!/bin/bash

while true

do

time curlcustomer-tutorial.$(minishift ip).nip.io

sleep .1

done

注意到许多对客户端点的请求现在都有延迟。如果您正在监视建议v1和v2的日志,您还会看到延迟发生在实际调用建议服务之前。延迟在Istio代理(Envoy)中,而不是在实际的端点中。

sternrecommendation -n tutorial

清理:

istioctl delete -fistiofiles/route-rule-recommendation-delay.yml \

-n tutorial

6.观测

微服务架构管理面临的最大挑战之一就是试图理解整个系统各个组件之间的关系。 单个最终用户事务可能会流经几个(也许是十几个或更多独立部署的微服务或Pod),并发现性能瓶颈发生的位置,从而提供有价值的信息。

6.1.跟踪

通常首先要了解您的微服务架构是特定哪些微服务涉及到最终用户事务。如果许多团队正在部署数十种微服务,而且彼此独立,那么了解跨该“服务网格”的依赖关系往往很困难。 Istio的混音器具有“开箱即用”功能,可以从分布式微服务中提取跟踪跨度。这意味着跟踪是编程语言不可知的,因此您可以在多语世界中使用此功能,其中不同的团队(每个团队都有自己的微服务)可以使用不同的编程语言和框架。

虽然Istio同时支持Zipkin和Jaeger,但为了我们的目的,我们专注于实现OpenTracing(供应商中立的跟踪API)的Jaeger。 Jaeger原来是由优步科技团队开源的,它是一个专注于微服务架构的分布式追踪系统。

要理解的一个重要术语是跨度,Jaeger将跨度定义为“系统中具有操作名称,操作起始时间和持续时间的逻辑工作单元。跨度可以被嵌套并且被命令为因果关系建模。 RPC调用是跨度的一个例子。“

另一个要理解的重要术语是跟踪,Jaeger将跟踪定义为“通过系统的数据/执行路径,并且可以被看作跨度的有向无环图。”

您可以使用以下命令打开Jaeger控制台:

minishiftopenshift service jaeger-query --in-browser

然后,您可以从下拉列表框中选择客户并浏览找到的跟踪,如图6-1所示。

图6-1 Jaeger对客户偏好建议追踪的看法

需要记住的一个方面是,您的编程逻辑必须在每次向外呼叫时转发OpenTracing标头:

x-request-id

x-b3-traceid

x-b3-spanid

x-b3-parentspanid

x-b3-sampled

x-b3-flags

x-ot-span-context

在随附的示例代码中,您可以在名为HttpHeaderForwarderHandlerInterceptor的客户类中看到此概念的示例。

6.2.指标

默认情况下,Istio的默认配置将通过服务网格收集遥测数据。只需安装Prometheus和Grafana就足以开始使用这项重要服务,但是请记住许多其他后端指标/遥测收集服务都受支持。在第2章中,您看到了以下四条命令来安装和公开度量标准系统:

oc apply -finstall/kubernetes/addons/prometheus.yaml

oc apply -f install/kubernetes/addons/grafana.yaml

oc expose svc grafana

oc expose svc prometheus

然后,您可以使用minishift服务命令启动Grafana控制台:

open "$(minishift openshift service grafana-u)/dashboard/db/istiodashboard?

var-source=All"

确保选择Grafana仪表板左上角的Istio仪表板,

如图6-2所示。

图6-2 Grafana仪表板 - 选择Istio仪表板

在撰写本文时,您需要将?var-source= All附加到Grafana仪表板URL。未来可能会发生变化,请观看istio教程以了解变化。以下是一个示例网址:

http://grafana-istio-system.192.168.99.101.nip.io/dashboard/db/istio-dashboard?

var-source=All

图6-3显示了仪表板。 您也可以直接访问Prometheus仪表板(注意,这将在浏览器中为您打开URL;您可以使用--url而不是--in-browser来获取URL):

minishiftopenshift service prometheus --in-browser

图6-3.格拉法纳图

7.安全

Istio的安全功能正在迅速发展,在撰写本文时,访问控制列表(Access Control List,ACL)是向应用程序注入安全构造的主要工具之一,对实际的编程逻辑没有影响。在本章中,我们将探讨黑名单和白名单的概念。

大魏注:在istio出现之前,openshift的SDN(OVS)策略有subnet、多租户、networkpolicy。

Subnet默认所有project之间pod可以通讯;多租户是以project级别隔离pod通讯,默认项目之间的pod不可通讯,除非对项目进行join操作;networkpolicy则是更为细颗粒度的网络隔离策略,可以设置白名单。networkpolicy可以设置微服务之间的流量控制。

7.1.黑名单

让我们从黑名单的概念开始,有条件地使用混音器选择器拒绝请求。黑名单明确拒绝特定的调用路径。在下面的例子中,我们想明确地关闭从客户到偏好的路线。在这种情况下,来自客户的任何优先请求都会返回HTTP错误403 Forbidden。建立这个需要使用三种不同类型的Istio混合器配置:denier、校验和规则:

apiVersion:"config.istio.io/v1alpha2"

kind: denier

metadata:

name: denycustomerhandler

spec:

status:

code: 7

message: Not allowed

---

apiVersion:"config.istio.io/v1alpha2"

kind: checknothing

metadata:

name: denycustomerrequests

spec:

---

apiVersion:"config.istio.io/v1alpha2"

kind: rule

metadata:

name: denycustomer

spec:

match:destination.labels["app"] == "preference" &&

source.labels["app"]=="customer"

actions:

- handler:denycustomerhandler.denier

instances: [denycustomerrequests.checknothing ]

您使用istioctl来建立denier-checknothing-rule:

istioctl create-f istiofiles/acl-blacklist.yml -n tutorial

接下来,尝试卷曲客户端点:

curlcustomer-tutorial.$(minishift ip).nip.io

结果将是来自首选微服务的403客户=> 403 PERMISSION_DENIED:denycustomerhandler.denier.tutorial:不允许

清理:

istioctl delete-f istiofiles/acl-blacklist.yml -n tutorial

7.2.白名单

白名单是拒绝所有规则,除了批准的调用路径。 在这个例子中,我们只是在批准建议>偏好的路线,这意味着通常与偏好交谈的客户再也看不到它了。白名单配置使用混合器种类:listchecker,listen try,rule。

apiVersion: "config.istio.io/v1alpha2"

kind: listchecker

metadata:

name: preferencewhitelist

spec:

overrides: ["recommendation"]

blacklist: false

---

apiVersion: "config.istio.io/v1alpha2"

kind: listentry

metadata:

name: preferencesource

spec:

value: source.labels["app"]

---

apiVersion: "config.istio.io/v1alpha2"

kind: rule

metadata:

name: checkfromcustomer

spec:

match: destination.labels["app"] =="preference"

actions:

- handler: preferencewhitelist.listchecker

instances:

- preferencesource.listentry

使用istioctl工具创建黑名单组件:

istioctlcreate -f istiofiles/acl-whitelist.yml -n tutorial

然后,使用curl命令击中客户端点:

curlcustomer-tutorial.$(minishift ip).nip.io

其结果如下:

customer=> 404 NOT_FOUND:preferencewhitelist.listchecker.tutorial:

customer is notwhitelisted

清理:

istioctl delete-f istiofiles/acl-whitelist.yml -n tutorial

红帽团队将探索更有趣和更先进的安全使用Istio开源项目成熟时,istio教程中的案例成熟。

7.3.结论

您现在已浏览了Istio服务网格的一些功能。您看到了这种服务网格可以解决云本地环境中的分布式系统问题,无论是开发微服务架构还是整体架构或其他任何方面。您已经看到Istio的概念如可观察性,弹性和混沌注入如何能立即对您当前的应用程序有所帮助。尽管我们专注于在Kubernetes / OpenShift上运行并部署在容器中的服务,但Istio不受任何这些环境的束缚,可以在裸机,虚拟机和其他部署平台上使用。

而且,Istio的功能超出了我们在本报告中讨论的范围。如果您有兴趣,我们建议您进一步探讨以下主题:

  • 最终用户身份验证
  • 政策执行
  • 网格扩展
  • 混合部署
  • 逐步将Istio应用到现有环境中
  • 网关/高级入口
  • RouteRules /资源的最新发展

Istio也在快速发展。为了跟上最新发展,我们建议您关注上游社区项目以及红帽不断发展的istio教程。

魏新宇

  • "大魏分享"运营者、红帽资深解决方案架构师
  • 专注开源云计算、容器及自动化运维在金融行业的推广
  • 拥有MBA、ITIL V3、Cobit5、C-STAR、TOGAF9.1(鉴定级)等管理认证。
  • 拥有红帽RHCE/RHCA、VMware VCP-DCV、VCP-DT、VCP-Network、VCP-Cloud、AIX、HPUX等技术认证。

原文发布于微信公众号 - 大魏分享(david-share)

原文发表时间:2018-05-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏芋道源码1024

Dubbo源码解析 —— Zookeeper 订阅

前言 上周写完了服务暴露总结之后发现遗漏了一个很重要的点,在dubbo源码解析-zookeeper连接中我们对面试高频题 dubbo中zookeeper做注册...

2687
来自专栏码匠的流水账

2017年终总结

又到了写年终总结的时候了。每当这个时候思绪总是翻江倒海,因为太久没有反思和总结的缘故,一年才总结一次,确实是有点久,欠的账的太多,梳理起来有点费劲。这里依旧还是...

761
来自专栏极客慕白的成长之路

在 Windows 上拥有舒适的码字体验

1692
来自专栏张善友的专栏

复合事件处理(Complex Event Processing)介绍

近年来,面向服务架构 SOA一直是热门的议题。面向服务架构SOA 使用了比组件、程序(procedure)层次更高的服务做为处理单元,通过开放格式交换标准例如X...

2137
来自专栏数据和云

见微知著:一条 SQL 性能问题引发的核心系统悲剧

? 黄廷忠(网名:认真就输) 云和恩墨技术专家 个人博客:http://www.htz.pw/ 本篇整理内容是黄廷忠在“云和恩墨大讲堂”微信分享中的讲解案...

2776
来自专栏樊华恒的专栏

海量之道系列文章之弱联网优化 (五)

在客户端接入服务器调度策略的演化过程中,我们最早采用了“就近接入”的策略,在距离客户端更近的地方部署服务器或使用CDN,期望通过减少RTT来提高网络交互响应性能...

3610
来自专栏农夫安全

运维的福利,黑客的噩梦

CYWL_Team服务器防御工具1.0 0x01开发前言 很多小黑都希望搭建自己的博客,论坛,来记录自己在安全之路上面的点点滴滴,不过总是被一些大牛来进行恶搞,...

3318
来自专栏架构师之旅

携程网的Ceph实践之路

今天分享的内容分为两部分,前面一部分为携程网Ceph的具体实践讲解,后面一部分为携程工程师在Ceph中国社区针对Ceph应用的一系列问答

1403
来自专栏Java架构解析

Redis 的 KEYS 命令引起 RDS 数据库雪崩,宕机 2 次,造成几百万损失

最近的互联网线上事故发生比较频繁,9月19日网上爆料出顺丰近期发生了一起线上删库事件,在这里就不介绍了。

1355
来自专栏Java进阶

分布式相关基础理论

2678

扫码关注云+社区