使用Istio打造微服务(第1部分)

做者:Rinor Maloku 
译者:殷龙飞 
审校:孙海洲 
原文:https://medium.com/google-cloud/back-to-microservices-with-istio-p1-827c872daa53


Istio 是一个由Google,IBM和Lyft团队合做开发的开源项目,它提供了基于微服务的应用程序复杂性的解决方案,仅举几例:css

  • 流量管理 :超时,重试,负载均衡,html

  • 安全性: 最终用户身份验证和受权,前端

  • 可观察性: 跟踪,监控和记录。git

全部这些均可以在应用程序层中解决,可是您的服务再也不是“微型”,相对于提供业务价值的资源,实现这些的全部额外工做都是公司资源的压力。咱们来举个例子:github

PM:添加反馈功能须要多长时间?web

开发:两个冲刺(敏捷开发中的术语,通常一个冲刺周期30天)。正则表达式

PM:什么......? 那只是一个CRUD!算法

开发:建立CRUD很容易,但咱们须要对用户和服务进行身份验证和受权。并且因为网络不可靠,咱们须要在客户端实施重试和熔断器,并确保咱们不会占用整个系统,咱们须要Timeout和Bulkheads,另外还要检测咱们须要监控的问题,跟踪[... ]sql

PM:那么咱们就把它放在产品服务中吧。哎呀!chrome

你明白了,必须知足全部形式才能够为咱们添加一项巨大的服务(有不少不是业务功能的代码)。在本文中,咱们将展现Istio如何从咱们的服务中删除全部上述交叉问题。

注意: 本文假设您具备Kubernetes的知识。若是不是这种状况,我建议您阅读 我对Kubernetes的介绍,而后继续阅读本文。

关于Istio

在没有Istio的世界中,一个服务向另外一个服务直接发出请求,而且在发生故障的状况下,服务须要经过重试,超时,打开熔断器等来处理它。

为了解决这个问题,Istio经过与服务彻底分离,并经过拦截全部网络通讯来提供一种巧妙的解决方案。这样作能够实现:

  • Fault Tolerance  - 使用响应状态代码,它能够在请求失败并重试时理解。

  • Canary Rollouts  - 仅将指定百分比的请求转发到新版本的服务。

  • 监控和指标  - 服务响应所花费的时间。

  • 跟踪和可观察性  - 它在每一个请求中添加特殊header,并在集群中跟踪它们。

  • 安全性  - 提取JWT令牌并对用户进行身份验证和受权。

仅举几例(仅举几例),让您感兴趣! 咱们来看一些技术细节吧!

Istio的架构

Istio拦截全部网络流量,并经过在每一个pod中注入智能代理做为sidecar来应用一组规则。启用全部功能的代理包括 数据平面, 而且这些代理可由控制平面 动态配置。

数据平面

注入的代理使Istio可以轻松知足咱们的要求。举个例子,咱们来看看重试和熔断器功能。

总结一下:

  1. Envoy将请求发送到服务B的第一个实例,但它失败了。

  2. Envoy sidecar重试。(1)

  3. 返回对调用代理的失败请求。

  4. 这将打开熔断器并在后续请求中调用下一个服务。(2)

这意味着您没必要使用另外一个重试库,您没必要在编程语言X,Y或Z中开发本身的Circuit Breaking和Service Discovery实现。全部这些都是开箱即用的。这些功能都是经过Istio来实现,你不须要更改代码。

很好! 如今你想加入Istio的航行,但你仍然有一些疑虑,一些悬而未决的问题。这是一个一刀切的方案,你对它持怀疑态度,由于它老是最终成为一刀切的无解方案!

你最终低声说了这个问题:“这是可配置的吗?”

欢迎个人朋友来巡航,咱们将为你们介绍一下控制平面。

控制平面

由三个组件组成: PilotMixerCitadel,它们组合使用Envoys来路由流量,实施策略和收集遥测数据。以下图所示。

Envoy(即数据平面)使用由Istio定义的 Kubernetes自定义资源定义 进行配置。这意味着对你而言,它只是另外一个具备熟悉语法的Kubernetes资源。建立后将由控制平面获取,并将其应用于Envoy。

服务与Istio的关系

咱们描述了Istio与咱们服务的关系,但咱们反过来思考一下,咱们的服务与Istio的关系是什么?

坦率地说,咱们的服务对Istio的存在有着尽量多的了解,就像鱼对水同样,他们会问本身“这究竟是什么水?”。

这意味着您能够选择一个工做集群,在部署了Istio的组件后,其中的服务将继续工做,而且以相同的方式,您能够删除组件,一切都会很好。能够理解的是,您将失去Istio提供的功能。

咱们已经有足够的理论,下面让咱们把这些理论付诸实践!

Istio实践

Istio至少须要一个具备4个vCPU和8 GB RAM的Kubernetes集群。要快速设置集群并跟进本文,我建议使用Google云端平台,它为新用户提供 300美圆的免费试用版

使用Kubernetes命令行工具建立集群并配置访问后,咱们已准备好使用Helm Package管理器安装Istio。

安装Helm

按照官方文档中的说明在您的计算机上安装Helm客户端 。咱们将在下一节中使用它来生成Istio安装模板。

安装Istio

最新版本下载Istio的资源,将内容提取到一个咱们将称之为的目录中[istio-resources]

要轻松识别Istio资源 istio-system,请在Kubernetes集群中建立命名空间 :

$ kubectl create namespace istio-system复制代码

而后进入到 [istio-resources] 目录并执行如下命令来完成安装 :

$ helm template install/kubernetes/helm/istio \  --set global.mtls.enabled = false \  --set tracing.enabled = true \  --set kiali.enabled = true \  --set grafana.enabled = true \  --namespace istio-system > istio.yaml复制代码

上面的命令将Istio的核心组件输出到文件 istio.yaml 中。咱们使用如下参数自定义模板:

  • global.mtls.enabled 设置为false以保持引入的重点。

  • tracing.enabled 容许使用jaeger跟踪请求。

  • kiali.enabled 在咱们的集群中安装Kiali以实现服务和流量的可视化

  • grafana.enabled 安装Grafana,为了收集指标的可视化。

经过执行如下命令应用生成的资源

$ kubectl apply -f istio.yaml复制代码

这标志着咱们集群中Istio安装的完成!等到istio-system命名空间中的全部pod都处于Running或Completed状态,执行如下命令:

$ kubectl get pods -n istio-system复制代码

如今咱们已准备好继续下一部分,咱们将在其中启动并运行示例应用程序。

Sentiment Analysis应用架构

咱们将使用Kubernetes简介文章中使用的相同微服务应用程序,它足以在实践中展现Istio的功能。

该应用程序由四个微服务组成:

  • SA-Frontend服务 :提供前端Reactjs应用程序。

  • SA-WebApp服务 :处理对Sentiment Analysis的请求。

  • SA-Logic服务 :执行sentiment Analysis。

  • SA反馈服务 :接收用户关于分析准确性的反馈。

在图6中,除了服务以外,咱们还看到Ingress Controller在Kubernetes中将传入的请求路由到适当的服务,Istio使用了一个名为Ingress Gateway的相似概念,将在本文的后续部分中介绍。

使用Istio Proxies运行应用程序

要跟进本文,请克隆存储库istio-mastery( github.com/rinormaloku… ),其中包含Kubernetes和Istio的应用程序和清单。

Sidecar Injection

注入是 自动手动 完成的 。要启用自动sidecar注入,咱们须要 istio-injection=enabled 经过执行如下命令 来标记命名空间 :

$ kubectl label namespace default istio-injection=enabled namespace/default labeled复制代码

从如今开始,部署到默认命名空间的每一个pod都将得到注入的sidecar。为了验证这一点,咱们经过进入到 [istio-mastery] 存储库的根文件夹 并执行如下命令 来部署示例应用程序 :

$ kubectl apply -f resource-manifests/kube persistentvolumeclaim/sqlite-pvc created deployment.extensions/sa-feedback created service/sa-feedback created deployment.extensions/sa-frontend created service/sa-frontend created deployment.extensions/sa-logic created service/sa-logic created deployment.extensions/sa-web-app created service/sa-web-app created复制代码

在部署的服务中,经过执行如下命令 kubectl get pods 验证pod有两个容器(service和sidecar), 并确保准备好后,咱们看到值“ 2/2 ”表示两个容器都在运行。以下所示:

$ kubectl get pods NAME                           READY     STATUS    RESTARTS   AGE sa-feedback-55f5dc4d9c-c9wfv   2/2       Running   0          12m sa-frontend-558f8986-hhkj9     2/2       Running   0          12m sa-logic-568498cb4d-2sjwj      2/2       Running   0          12m sa-logic-568498cb4d-p4f8c      2/2       Running   0          12m sa-web-app-599cf47c7c-s7cvd    2/2       Running   0          12m复制代码

视觉呈如今图7中。

如今,应用程序启动并运行,咱们须要容许传入流量到达咱们的应用程序。

入口网关

容许流量进入集群的最佳作法是经过Istio的 入口网关 将其自身置于集群的边缘,并在传入流量上实现Istio的功能,如路由,负载均衡,安全性和监控。

在Istio的安装过程当中, Ingress Gateway 组件和在外部公开它的服务已安装到集群中。要获取服务外部IP,请执行如下命令:

$ kubectl get svc -n istio-system -l istio=ingressgateway NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP istio-ingressgateway   LoadBalancer   10.0.132.127   13.93.30.120复制代码

在本文的后续部分中,咱们将访问此IP上的应用程序(称为EXTERNAL-IP),为方便起见,经过执行如下命令将其保存在变量中:

$ EXTERNAL_IP=$(kubectl get svc -n istio-system \
  -l app=istio-ingressgateway \
  -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')
复制代码

若是您在浏览器中访问此IP而且您将收到服务不可用错误,则 默认状况下Istio将阻止任何传入流量, 直到咱们定义网关。

网关资源

网关是在咱们的集群中安装Istio时定义的Kubernetes自定义资源定义,使咱们可以指定咱们但愿容许传入流量的端口,协议和主机。

在咱们的场景中,咱们但愿容许全部主机在端口80上使用HTTP流量。达到如下定义:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: http-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
复制代码

除了选择器istio:ingressgateway以外,全部配置都是不须要说明的。使用此选择器,咱们能够指定应用配置的Ingress Gateway,在咱们的示例中,它是安装在Istio设置上的默认入口网关控制器。

经过执行如下命令应用配置:

$ kubectl apply -f resource-manifests/istio/http-gateway.yaml
gateway.networking.istio.io/http-gateway created
复制代码

网关如今容许在端口80中进行访问,但它不知道在何处路由请求。这须要使用Virtual Service来实现。

VirtualService资源

VirtualService指示Ingress Gateway如何路由容许进入集群的请求。

对于咱们度过即将到来的应用程序请求 HTTP网关 必须被路由到 sa-frontendsa-web-appsa-feedback 服务(出了如图8)。

让咱们分解如下路由到SA-Frontend的请求:

  • **/** 应将精确路径 路由到SA-Frontend以获取Index.html

  • **/static/*** 应将前缀路径 路由到SA-Frontend以获取前端所需的任何静态文件,如Css和JavaScript文件。

  • 匹配正则表达式的路径'^.*\.(ico|png|jpg)$' 应该路由到SA-Frontend,咱们应该把图像资源路由到前端。

这是经过如下配置实现的:

kind: VirtualService
metadata:
  name: sa-external-services
spec:
  hosts:
  - "*"
  gateways:
  - http-gateway                      # 1
  http:
  - match:
    - uri:
        exact: /
    - uri:
        exact: /callback
    - uri:
        prefix: /static
    - uri:
        regex: '^.*\.(ico|png|jpg)$'
    route:
    - destination:
        host: sa-frontend             # 2
        port:
          number: 80
复制代码

这里的重点是:

  1. 此VirtualService适用于经过http网关 发出的请求

  2. Destination定义请求路由到的服务。

注意: 上面的配置位于文件中 sa-virtualservice-external.yaml,它还包含用于路由到SA-WebApp和SA-Feedback的配置,但为简洁起见,已缩短。

经过执行如下命令应用VirtualService:

$ kubectl apply -f resource-manifests/istio/sa-virtualservice-external.yaml
virtualservice.networking.istio.io/sa-external-services created
复制代码

注意: 当咱们应用Istio资源时,Kubernetes API服务器会建立一个由Istio控制平面接收的事件,而后将新配置应用于每一个pod的Envoy代理。Ingress Gateway控制器是另外一个由控制平面配置的Envoy,如图9所示。

如今能够访问Sentiment Analysis应用程序了 http://{EXTERNAL-IP}/ 。若是您得到Not Found状态,请不要担忧

有时须要配置生效才能更新envoy的缓存

在转到下一部分以前,请使用该应用程序生成一些流量。

Kiali - 可观察性

要访问Kiali的Admin UI,请执行如下命令:

$ kubectl port-forward \
    $(kubectl get pod -n istio-system -l app=kiali \
    -o jsonpath='{.items[0].metadata.name}') \
    -n istio-system 20001
复制代码

http://localhost:20001/ 使用“admin”(不含引号)为用户和密码打开登陆。有不少有用的功能,例如检查Istio组件的配置,根据拦截网络请求和回答收集的信息可视化服务,“谁在调用谁?”,“哪一个版本的服务有故障?”等等,花一些时间检验Kiali的功能,而后再转到下一节,用Grafana可视化指标!

Grafana - 度量可视化

使用Grafana将Istio收集的指标划分为Prometheus和Visualized。要访问Grafana的Admin UI,请执行如下命令并打开http://localhost:3000

$ kubectl -n istio-system port-forward \
    $(kubectl -n istio-system get pod -l app=grafana \
    -o jsonpath={.items[0].metadata.name}) 3000
复制代码

在左上角单击菜单Home 并选择 Istio Service Dashboard 并在左上角选择以sa-web-app开头的服务,您将看到收集的指标,以下图所示:

个人妈呀,这是一个没有任何数据的视图,管理层永远不会赞同这一点。让咱们经过执行如下命令生成一些负载:

$ while true; do \
    curl -i http://$EXTERNAL_IP/sentiment \
    -H “Content-type: application/json” \
    -d ‘{“sentence”: “I love yogobella”}’; \
    sleep .8; done
复制代码

如今咱们拥有更漂亮的图表,此外,咱们拥有Prometheus用于监控和Grafana用于可视化指标这些使人惊讶的工具,使咱们可以随时了解服务的性能,健康情况,升级或降级!

最后,咱们将研究整个服务中的跟踪请求。

Jaeger - 追踪

咱们须要跟踪,由于咱们所拥有的服务越多,就越难找出失败的缘由。咱们来看下面图片中的简单案例:

请求进入,失败,

缘由是什么

第一次服务

仍是第二个

?二者都有例外状况,让咱们来看看每一个日志。你发现本身这么作了多少次? 咱们的工做更像是软件侦探而不是开发人员。

这是微服务中的一个广泛问题,它使用分布式跟踪系统解决,其中服务将惟一的header相互传递,而后将此信息转发到请求跟踪放在一块儿的分布式跟踪系统。一个例子如图13所示。

Istio使用Jaeger Tracer实现OpenTracing API,这是一个独立于供应商的框架。要访问Jaegers UI,请执行如下命令:

$ kubectl port-forward -n istio-system \
    $(kubectl get pod -n istio-system -l app=jaeger \
    -o jsonpath='{.items[0].metadata.name}') 16686
复制代码

而后在 http://localhost:16686 中打开UI,选择 sa-web-app 服务,

若是下拉列表中未显示该

服务,

则在页面上生成一些活动并点击刷新

。随后单击该按钮 查找痕迹, 这显示最近的痕迹,选择任何和全部的痕迹的详细分类将会显示 ,如图14所示。

跟踪显示:

  1. 请求来到 istio-ingressgateway (它是第一次与其中一个服务联系,所以对于生成跟踪ID的请求)而后网关将请求转发给 sa-web-app 服务。

  2. sa-web-app 服务中,请求由Envoysidecar拾取并建立一个span(这就是咱们在跟踪中看到它的缘由)并转发到 sa-web-app 容器实例。

  3. 这里方法 sentimentAnalysis 处理请求。这些跟踪由应用程序生成,这意味着须要更改代码)。

  4. 从POST请求sa-logic开始的位置。跟踪ID须要sa-web-app传递 。

5. ...

注意 :在第4点,咱们的应用程序须要获取Istio生成的header,并在下一个请求时将其传递下来,以下图所示。

Istio作主要的繁重工做,由于它在传入的请求上生成header,在每一个sidecar上建立新的span,传递它们,可是若是没有咱们的服务传递header,咱们将失去请求的完整跟踪。

要传递的header是:

x-request-id
x-b3-traceid
x-b3-spanid
x-b3-parentspanid
x-b3-sampled
x-b3-flags
x-ot-span-context
复制代码

尽管这是一项简单的任务,但已经有许多库 能够简化这一过程,例如在 sa-web-app服务中, RestTemplate 客户端经过简单地依赖项中 添加Jaeger和OpenTracing库来传递header 。

注意:Sentiment Analysis应用程序展现了Flask,Spring和ASP.NET Core的实现。

如今,在调查咱们开箱即用(或部分开箱即用)以后,让咱们来看看这里的主题,细粒度路由,管理网络流量,安全性等等!

流量管理

使用Envoy的Istio为您的集群提供了许多新功能,从而实现:

  • 动态请求路由 :Canary部署,A/B测试,

  • 负载均衡: 简单和一致的哈希平衡,

  • 故障恢复 :超时,重试,熔断器,

  • 故障注入 :延迟,停止请求等

在本文的序列中,咱们将在咱们的应用程序中展现这些功能,并在此过程当中介绍一些新概念。咱们将研究的第一个概念是DestinationRules,并使用那些咱们将启用A/B测试的概念。

A/B测试 - 实践中的目的地规则

当咱们有两个版本的应用程序(一般版本视觉上有所不一样)时使用A/B测试,而且咱们不是100%确定会增长用户交互,所以咱们同时尝试两个版本并收集指标。

执行如下命令以部署演示A/B测试所需的前端的第二个版本:

$ kubectl apply -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions/sa-frontend-green created
复制代码

绿色版本的部署清单有两点不一样:

  1. 该image基于不一样的标签: istio-green

  2. pod标有 version: green

而做为双方部署在标签 app: sa-frontend 经过虚拟服务路由的请求 sa-external-services 的服务 sa-frontend 会被转发到全部的实例,并将于负载采用循环算法,这将致使在图16中提出的负载均衡问题。

找不到这些文件,由于它们在应用程序的不一样版本中的命名方式不一样。让咱们验证一下:

$ curl --silent http://$EXTERNAL_IP/ | tr '"' '\n' | grep main
/static/css/main.c7071b22.css
/static/js/main.059f8e9c.js
$ curl --silent http://$EXTERNAL_IP/ | tr '"' '\n' | grep main
/static/css/main.f87cd8c9.css
/static/js/main.f7659dbb.js
复制代码

这意味着请求一个版本的静态文件的index.html能够被负载均衡到提供另外一个版本的pod,其中能够理解的是其余文件不存在。

这意味着,为了让咱们的应用程序正常工做,咱们须要引入限制“为index.html服务的应用程序的版本,必须为后续请求提供服务”。

咱们将使用Consistent Hash Loadbalancing来实现这一点,这 使用预约义属性(例如HTTP header)未来自同一客户端的请求转发到同一后端实例的过程。由 DestionatioRules提供。

DestinationRules

VirtualService 将请求路由到正确的服务以后,而后使用 DestinationRules, 咱们能够指定适用于此服务实例的流量的策略,如图17所示。

注意: 图17以易于理解的方式可视化Istio资源如何影响网络流量。可是,准确地说,决定将请求转发到哪一个实例是由CRD配置的Ingress Gateway的Envoy作出的。

使用目标规则,咱们能够将负载均衡配置为具备一致性哈希,并确保同一用户由同一服务实例响应。经过如下配置实现:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-frontend
spec:
  host: sa-frontend
  trafficPolicy:
    loadBalancer:
      consistentHash:
        httpHeaderName: version   # 1
复制代码
  1. 根据“version”标头的内容生成一致的哈希。

经过执行如下命令应用配置并尝试一下!

$ kubectl apply -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io/sa-frontend created
复制代码

执行如下命令并验证在指定版本header时是否得到相同的文件:

$ curl --silent -H "version: yogo" http://$EXTERNAL_IP/ | tr '"' '\n' | grep main
复制代码

注意: 为了方便在浏览器中进行测试,您可使用此 Chrome扩展程序 向版本header添加不一样的值,。

DestinationRules具备更多LoadBalancing功能,全部详细信息均可以查看 官方文档

在继续更详细地探索VirtualService以前,请执行如下命令,删除应用程序的绿色版本和目标规则:

$ kubectl delete -f resource-manifests/kube/ab-testing/sa-frontend-green-deployment.yaml
deployment.extensions “sa-frontend-green” deleted
$ kubectl delete -f resource-manifests/istio/ab-testing/destinationrule-sa-frontend.yaml
destinationrule.networking.istio.io “sa-frontend” deleted
复制代码

镜像服务 - 实践中的虚拟服务

当咱们想要测试生产中的更改但不影响最终用户时,会使用影子或镜像,所以咱们将请求镜像到具备更改并评估它的第二个实例中。

更简单的是,当你的一个同事选择最关键的问题并制做一个超大的合并请求,而且没人能真正审查。

要测试此功能,能够 经过执行如下命令 建立SA-Logic的第二个实例(

这是buggy的

):

$ kubectl apply -f resource-manifests/kube/shadowing/sa-logic-service-buggy.yaml
deployment.extensions/sa-logic-buggy created
复制代码

执行如下命令并验证全部实例都标有相应的版本,另外还有app=sa-logic标记:

$ kubectl get pods -l app=sa-logic --show-labels
NAME                              READY   LABELS
sa-logic-568498cb4d-2sjwj         2/2     app=sa-logic,version=v1
sa-logic-568498cb4d-p4f8c         2/2     app=sa-logic,version=v1
sa-logic-buggy-76dff55847-2fl66   2/2     app=sa-logic,version=v2
sa-logic-buggy-76dff55847-kx8zz   2/2     app=sa-logic,version=v2
复制代码

sa-logic 服务目标pod标记为 app=sa-logic时,任何传入请求将在全部实例之间进行负载均衡,如图18所示。

但咱们但愿将请求路由到版本为v1的实例,并镜像到版本为v2的实例,如图19所示。

这是使用VirtualService与DestinationRule结合实现的,其中目标规则指定到特定子集的子集和VirtualService路由。

使用目标规则指定子集

咱们使用如下配置定义子集:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: sa-logic
spec:
  host: sa-logic    # 1
  subsets:
  - name: v1        # 2
    labels:
      version: v1   # 3
  - name: v2
    labels:
      version: v2  
复制代码
  1. 主机定义此规则仅在向 sa-logic 服务发生路由时适用

  2. 路由到子集实例时使用的子集名称。

  3. Label定义了须要匹配的键值对,以使实例成为子集的一部分。

应用执行如下命令的配置:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-destinationrule.yaml
 destinationrule.networking.istio.io/sa-logic created
复制代码

经过定义子集,咱们能够继续并配置VirtualService以应用于请求 sa-logic 所在的请求:

  1. 路由到名为v1的子集,

  2. 镜像到名为v2的子集。

这是经过如下清单实现的:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic          
  http:
  - route:
    - destination:
        host: sa-logic  
        subset: v1      
    mirror:             
      host: sa-logic     
      subset: v2
复制代码

因为一切配置都是不言自明的,让咱们看看它的执行:

$ kubectl apply -f resource-manifests/istio/shadowing/sa-logic-subsets-shadowing-vs.yaml
virtualservice.networking.istio.io/sa-logic created
复制代码

经过执行如下命令添加一些负载:

$ while true; do curl -v http://$EXTERNAL_IP/sentiment \
    -H “Content-type: application/json” \
    -d ‘{“sentence”: “I love yogobella”}’; \
    sleep .8; done
复制代码

检查Grafana中的结果,在那里咱们能够看到有错误的版本大约有60%的请求失败,但没有一个失败影响最终用户,由于它们被当前活动的服务响应。

在本节中,咱们第一次看到应用于咱们服务的envoy的VirtualService,当对此 sa-web-app 提出请求时, sa-logic 经过sidecar Envoy,经过VirtualService配置为路由到子集v1并镜像到服务的子集v2 sa-logic

我能够看到你在想“Darn man Virtual Services很简单!”,在下一节中,咱们将把句子扩展为“Simply Amazing!”。

金丝雀部署

Canary Deployment是向少数用户推出新版本应用程序的过程,做为验证缺乏问题的一个步骤,而后向更普遍的受众提供更高质量的发布保证。

咱们将继续使用相同的buggy子集 sa-logic 来演示canary部署。

让咱们大胆地开始,经过应用下面的VirtualService,将20%的用户发送到有缺陷的版本(这表明金丝雀部署)和80%的健康服务:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic    
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 80         # 1
    - destination: 
        host: sa-logic
        subset: v2
      weight: 20         # 1
复制代码
  1. 权重指定要转发到目标或目标子集的请求的百分比。

sa-logic 使用如下命令 更新之前的 虚拟服务配置:

$ kubectl apply -f resource-manifests/istio/canary/sa-logic-subsets-canary-versusyaml
 virtualservice.networking.istio.io/sa-logic configured
复制代码

咱们当即看到咱们的一些请求失败了:

$ while true; do \
   curl -i http://$EXTERNAL_IP/sentiment \
   -H “Content-type: application/json” \
   -d ‘{“sentence”: “I love yogobella”}’ \
   --silent -w “Time: %{time_total}s \t Status: %{http_code}\n” \
   -o /dev/null; sleep .1; done
Time: 0.153075s Status: 200
Time: 0.137581s Status: 200
Time: 0.139345s Status: 200
Time: 30.291806s Status: 500
复制代码

VirtualServices启用了Canary Deployments,经过这种方法,咱们将潜在的损害减小到了20%的用户群。漂亮! 如今,每当咱们对代码不安全时,咱们就可使用Shadowing和Canary Deployments,换句话说,老是如此。😜

超时和重试

代码并不老是错误的。在“ 分布式计算的8个谬误 ”列表中,第一个谬论是“网络可靠”。网络不可靠,这就是咱们须要超时和重试的缘由。

出于演示目的,咱们将继续使用有缺陷的版本 sa-logic,其中随机故障模拟网络的不可靠性。

有缺陷的服务有三分之一的机会花费太长时间来响应,三分之一的机会之内部服务器错误结束,其他的成功完成。

为了缓解这些问题并改善用户体验,咱们能够:

  1. 若是服务时间超过8秒,则超时

  2. 重试失败的请求。

这是经过如下资源定义实现的:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: sa-logic
spec:
  hosts:
    - sa-logic
  http:
  - route: 
    - destination: 
        host: sa-logic
        subset: v1
      weight: 50
    - destination: 
        host: sa-logic
        subset: v2
      weight: 50
    timeout: 8s           # 1
    retries:
      attempts: 3         # 2
      perTryTimeout: 3s   # 3
复制代码
  1. 请求的超时时间为8秒,

  2. 它尝试了3次,

  3. 若是尝试时间超过3秒,则尝试将请求标记为失败。

这是一种优化,由于用户不会等待超过8秒,而且咱们在发生故障时重试三次,从而增长了致使响应成功的机会。

使用如下命令应用更新的配置:

$ kubectl apply -f resource-manifests/istio/retries/sa-logic-retries-timeouts-vs.yaml
virtualservice.networking.istio.io/sa-logic configured
复制代码

并查看Grafana图表,了解成功率的改善状况(如图21所示)。

sa-logic-buggy 经过执行如下命令 进入下一部分delete 和VirtualService 以前 :

$ kubectl delete deployment sa-logic-buggy
deployment.extensions “sa-logic-buggy” deleted
$ kubectl delete virtualservice sa-logic
virtualservice.networking.istio.io “sa-logic” deleted
复制代码

熔断器和隔离模式

微服务架构中的两个重要模式,能够实现服务的自我修复。

熔断器 是用来阻止请求将视为不健康服务的一个实例,并使它可以恢复,在此期间客户端的请求转发到该服务的健康状况(增长成功率)。

隔离模式 整个系统降级来隔离错误,防止错误传播,举一个隔离故障例子,服务B处于损坏状态和其它服务(服务B的客户端)发出请求到服务B,这将致使该客户端将使用了本身的线程池,将没法提供其余请求(即便这些请求与服务B无关)。

我将跳过这些模式的实现,由于您能够查看 官方文档中的实现,我很兴奋地展现身份验证和受权,这将是下一篇文章的主题。

第一部分 - 摘要

在本文中,咱们在Kubernetes集群中部署了Istio,并使用其自定义资源定义(如 网关VirtualServicesDestinationRules 及其组件)启用了如下功能:

  • 使用 Kiali,经过查看正在运行的服务,它们如何执行,以及它们关系,来观察咱们的服务 。

  • 使用 PrometheusGrafana 进行收集和可视化 。

  • 请求 Jaeger 跟踪 (Hunter的德语)。

  • 对网络流量进行全面细粒度控制,实现 Canary DeploymentsA/B测试和Shadowing

  • 轻松实现 重试,超时和CircuitBreakers

全部这些均可以在没有代码更改或任何其余依赖性的状况下实现,从而使您的服务保持小巧,易于操做和维护

对于您的开发团队来讲,消除这些跨领域的问题并将它们集中到Istio的控制平面,意味着新服务很容易引入,它们不会占用大量资源,由于开发人员能够专一于解决业务问题。到目前为止,没有任何开发人员抱怨“必须解决有趣的业务问题!”。

我很乐意在下面的评论中听到您的想法,并随时在 Twitter 或个人页面 rinormaloku.com 上与我 联系,并继续关注下一篇文章,咱们将解决最后一层认证和受权问题!

相关文章
相关标签/搜索