Istio如何同时实现Hytrix|Ribbon|Zuul|微服务安全的功能?:为微服务引入Istio服务网格(下)
Posted 大魏分享
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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。一般这种方式适合长连接,短链接不建议使用。
三种方式,可以通过设置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
$ time curlcustomer-tutorial.$(minishift ip).nip.io
customer =>preference => recommendation v2 from '751265691-qdznv': 2
real 0m3.054s
user 0m0.003s
sys 0m0.003s
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等技术认证。
以上是关于Istio如何同时实现Hytrix|Ribbon|Zuul|微服务安全的功能?:为微服务引入Istio服务网格(下)的主要内容,如果未能解决你的问题,请参考以下文章