对于rpc请求(thrift),分布式调用链跟踪怎么做?

Istioneweyes 回复了问题 • 5 人关注 • 3 个回复 • 679 次浏览 • 2018-02-11 17:39 • 来自相关话题

关于Service Mesh架构下协议适配与服务治理的一些疑问

ServiceMeshxds2000 回复了问题 • 3 人关注 • 2 个回复 • 634 次浏览 • 2018-02-11 13:10 • 来自相关话题

专题 | A Service Mesh for Kubernetes第4期:轻松预发微服务

Linkerd小数 发表了文章 • 0 个评论 • 409 次浏览 • 2018-02-09 10:24 • 来自相关话题

作者:RISHA MARS

翻译:蔡悦

转自:容器时代(公众号 CaaSOne)

原文:A Service Mesh for Kubernetes, Part VI : Staging microservices without the tears



概述

在将新代码发布到生产环境之前, 预发布操作是构建一个可靠的、低宕机时间的软件系统的关键组成部分。但是,在微服务体系下,由于拆分出来的许许多多的微服务之间的依赖关系随着微服务数量成指数倍增长,从而增加了预发布操作的复杂性。在这篇文章里,我们将为您介绍 linkerd 的最强大的功能之一,单个请求路由(per-request routing),通过它,您将可以非常轻松的处理这个问题。


注意:这是关于 Linkerd、Kubernetes 和 Service Mesh 的系列文章其中一篇,其余部分包括:
Top-line service metricsPods are great, until they’re notEncrypting all the thingsContinuous deployment via traffic shiftingDogfood environments, ingress, and edge routingStaging microservices without the tears (本文)Distributed tracing made easyLinkerd as an ingress controllergRPC for fun and profitThe Service Mesh APIEgressRetry budgets, deadline propagation, and failing gracefullyAutoscaling by top-line metrics


Linkerd 是云原生应用的一种服务网格(Service Mesh)。它作为对应用透明的网络代理层通过封装服务间的调用为应用提供如:低延迟负载均衡(latency-aware load balancing)、链接重试(retry budgets)及终止(deadlines)、熔断机制(circuit breaking)等特性来提高应用的适应性(application resilience)。


除了能够提高应用的适应性,Linkerd 也能够提供强大的路由语言来改变服务在运行时请求流的方式。这篇文章我们将为您展示 Linkerd 如何做到这一点,不仅仅是全局范围,更精细到每一个基础请求。也将为您展示每一个请求路由如何被用来创建临时的预发布环境,从而允许在生产环境上下文中测试新代码而不用真正将其发布到生产环境里。最后,将为您介绍(in contrast to staging with a dedicated staging environment)临时的预发布环境如何做到既不需要与其他团队的协调工作,也不需要花费时间精力来同时保持多个部署环境。


为什么要预发布

为什么预发布如此重要?在现代软件开发当中,代码需要经过一系列预先设计好的实践路线来保证正确性:代码走查(code review),单元测试(unit tests),集成测试(integration tests)等等。经过这些流程之后,需要开始估算代码的表现了:新代码运行的速度如何?高负载下的表现如何?在运行时与其他服务以及相关依赖的交互表现如何?


预发布系统就可以回答这些问题。预发布的基本原则就是越接近生产环境,系统就越切实可行。因此,就像测试环节中的 mocks 和 stub 一样,对于预发布,我们期望能够运行真实的服务。最好的预发布环境就是和生产环境完全一样。



为什么微服务的预发布很难
如果你的应用由许多微服务构成,那么微服务之间的通信交互就会变成像端到端应用行为一样的重要组成部分。其实,应用拆分的越细,那么在运行时应用之间的交互就会越复杂,而此时应用的表现已经不仅仅是每个微服务自己的问题了,很大程度上取决于微服务之间的交互。

实际上,增加微服务的数量不仅仅增加了正确预发布的重要性,也同时增加了实现这一点的难度。我们来看几个常用的预发布方法,以及为什么在微服务环境下这些方法都会变得比较困难。


预发布的常规方法是共享预发布集群,而在这个集群里,除了你的预发布服务之外其他人的预发布服务也在这里。这种方式的弊端就是没有隔离。如下图展示,如果 Alex 把他的服务发布了上去但是出了点问题,整个链条中就很难判断出问题源的所在--因为问题可能出现在 Alex、Alice 或者 Bob 的服务上,又或者干脆就是数据库里的数据有问题。这样预发布环境与生产环境的同步就会非常困难,尤其是当服务、团队以及发行版本数量庞大的时候。


另一种共享环境称为“私人”或者单个开发者的预发布集群,可以解决隔离的问题。在这个例子中,每一个开发者可以根据需要来操作预发布集群。预发布一个服务需要同时预发布这个服务的上游以及下游服务也包括相关的依赖,从而可以保证预发布的有效性。(比如,在下图中,Alex 必须先发布 Web FE 和 API 服务来保证他的 Foo 服务可以正常运行。)然而,根据需要来维护以及部署部分应用拓扑结构会非常复杂,尤其是当应用拓扑结构非常大而且服务又有独立的部署模型。

上面说的是一种极其简单的部署新代码到生产环境并且有问题时可以回滚的方式。当然了,这种方式很有风险,而且不能处理部分应用类型,比如:金融事务。虽然还有很多其他的部署方法,但是本文我们将介绍一种直接的、轻松的方式。


一种更好的方式

使用 Linkerd 创建临时的预发布环境,就可以很好的避免以上提到的弊端。实际上,在 Twitter 里 Finagle 路由层作为linkerd 的底层,  他的主要动机就是解决这个问题。

我们来看一下 Alex 的 Foo 服务。如果,我们不另外部署一个隔离的环境,而是仅仅使用 Foo 的预发布版本替代 Foo 的生产版本,然后通过一个特殊的请求来访问它呢?针对生产环境,这将能够确保 Foo 的预发布版本的安全性,而且除了 Foo 预发布版本之外也不需要部署其他的任何东西。这就是临时预发布环境的本质。而此时,开发者身上的任务一下就轻松了:Alex 只需要预发布他的新代码,然后在 ingress 请求的 header 上设置一个标记就可以了,就这么简单!

Linkered 的单个请求路由可以帮助我们实现这种方式。通过 linkerd 的请求代理,可以给特定的请求上设置一个 l5d-dtab 的 header 。这个 header 可以允许你设置路由规则(叫做  in Finagle parlance, Dtabs)。比如,dtab 规则 /s/foo => /srv/alex-foo 可以覆盖 Foo 服务生产环境的规则。给单个请求添加这个可以使得请求直接到达 Alex 的 Foo 服务,也仅仅作用与这一个请求。Linkerd 可以拦截这个规则,所以生产环境里任何使用 Alex 的 Foo 服务的地方都可以正确的处理。



试一下这个功能吧

Service Mesh for Kubernetes 系列文章的读者应该已经知道我们有一个 demo our dogfood blog post。我们部署过一个 world-v2 服务,并且可以通过设置重定向路由规则发送单个的 dogfood 请求。现在我们可以使用相同机制来做些别的事情:创建一个临时的预发布环境。

部署一个服务的两个版本,再使用 linkerd 的路由功能在部署到生产环境之前来测试新服务。我们先部署 hello 和 world-v1 服务来作为我们的生产环境服务,然后再创建一个临时的预发布环境来测试 world 服务的新版本 world-v2。


1部署LINKERD和HELLO-WORLD服务


我们使用前一篇文章里部署的 hello world 服务。它由 hello 服务调用 world 服务组成。这些应用通过 Kubernetes downward API 提供的根据 nodeName 来找到 Linkerd 。如果你不确定你的集群是否支持 nodeName, 你可以运行如下命令:kubectl apply -f https://raw.githubusercontent. ... t.yml


然后查看一下日志:kubectl logs node-name-test


如果你看到了 ip 就表示成功了。然后再通过如下命令部署 hello world 应用:kubectl apply -f https://raw.githubusercontent. ... d.yml


如果你看到了 “server can’t find …” 错误,那就部署 hello-world 的 legacy 版本,这个版本依赖 hostIP 而不是 nodeName:kubectl apply -f https://raw.githubusercontent. ... y.yml


然后我们来部署生产环境(linkerd 和 hellow 以及 world 服务):$ kubectl apply -f https://raw.githubusercontent. ... s.yml


再来部署 linkerd 和预发布版本的服务 world-v2 ,这个服务会返回 "earth" 而不是 “world”。$ kubectl apply -f https://raw.githubusercontent. ... s.yml $ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/world-v2.yml 
 

2在临时预发布环境里使用单个请求覆盖

现在,我们运行了 world-v2 服务,来测试一下是否通了。我们期望的是请求到达的是 `world-v2` 而不是 `world-v1`。首先,先运行一个没有更改的请求,这个请求会走默认的路径。(你可能需要等待 l5d 的 external IP 出现):$ INGRESS_LB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}") $ curl -H "Host: www.hello.world" $INGRESS_LB Hello (10.196.2.232) world (10.196.2.233)!!


如果外部负载均衡不起作用,可以使用 hostIP:INGRESS_LB=$(kubectl get po -l app=l5d -o jsonpath="{.items[0].status.hostIP}"):$(kubectl get svc l5d -o 'jsonpath={.spec.ports[0].nodePort}') $ curl -H "Host: www.hello.world" $INGRESS_LB Hello (10.196.2.232) world (10.196.2.233)!!


如我们所料,返回了 `Hello (......) World (.....)`,这说明走的是生产环境。


那如何来请求预发布环境呢?我们需要做的就是发送给一个带有覆盖 header 的请求到生产环境中去,它就会访问到 `world-v2` 服务!由于 header 的设置,请求会走 `/srv/world-v2` 而不是`/host/world`。$ curl -H "Host: www.hello.world" -H "l5d-dtab: /host/world => /srv/world-v2;" $INGRESS_LB Hello (10.196.2.232) earth (10.196.2.234)!!我们看到了 "earch" 而不是 “world”! 这个请求已经成功的到达了 world-v2 服务,而且是在生产环境里,并且没有任何代码变更或者额外的部署工作。就是这样,预发布就变的 so easy 了。

Linkerd 的 Dtabs 和 routing 的文档非常健全。在开发中,你可以使用 linkerd 的 “dtab playground” http://$INGRESS_LB:9990/delegator。By going to the “outgoing” router and testing a request name like /http/1.1/GET/world, you can see linkerd’s routing policy in action.



实践
、在实践中,这种方式有一些需要注意的地方。首先,往生产环境的数据库里写东西时必须要小心。相同的 dtab 覆盖机制可以用来发送任何写预发布数据库的请求,或者在一些应用级别里直接 /dev/null。强烈建议,这些覆盖规则不能手动生成,以免发生不必要的错误,毕竟是在生产环境里!


其次,你的应用需要参考 linkerd's context headers。

最后非常重要的一点,避免外界可以设置 l5d-dtab 请求头。setting up a dogfood environment in Kubernetes 这篇文章里我们阐述了一个 nginx 的 ingress 样例配置,可以有效的去掉不认识的请求头。



结尾


我们举例了如何通过 linkerd 设置单个请求路由规则来达到创建临时预发布环境的问题。通过这种方式,我们可以在生产环境里预发布服务,而不需要更改现有代码,也不需要其他额外的预发布环境资源(当然除了预发布服务自己),同时也不需要处理预发布与生产这两个平行环境。对于微服务众多的应用来说,这种方式提供了一种发布到生产环境之前的简单、高效的预发布方式。


原文链接:https://buoyant.io/2017/01/06/a-service-mesh-for-kubernetes-part-vi-staging-microservices-without-the-tears/


推荐阅读:
 
4大维度3大预测,基于容器生态扩张的DevSecOps为啥引关注?
最佳实践 | 7大维度看国外企业为啥选择gRPC打造高性能微服务?
微服务迁移前,来听听这6个思考和经验 查看全部
作者:RISHA MARS

翻译:蔡悦

转自:容器时代(公众号 CaaSOne)

原文:A Service Mesh for Kubernetes, Part VI : Staging microservices without the tears



概述

在将新代码发布到生产环境之前, 预发布操作是构建一个可靠的、低宕机时间的软件系统的关键组成部分。但是,在微服务体系下,由于拆分出来的许许多多的微服务之间的依赖关系随着微服务数量成指数倍增长,从而增加了预发布操作的复杂性。在这篇文章里,我们将为您介绍 linkerd 的最强大的功能之一,单个请求路由(per-request routing),通过它,您将可以非常轻松的处理这个问题。


注意:这是关于 Linkerd、Kubernetes 和 Service Mesh 的系列文章其中一篇,其余部分包括:
  1. Top-line service metrics
  2. Pods are great, until they’re not
  3. Encrypting all the things
  4. Continuous deployment via traffic shifting
  5. Dogfood environments, ingress, and edge routing
  6. Staging microservices without the tears (本文)
  7. Distributed tracing made easy
  8. Linkerd as an ingress controller
  9. gRPC for fun and profit
  10. The Service Mesh API
  11. Egress
  12. Retry budgets, deadline propagation, and failing gracefully
  13. Autoscaling by top-line metrics



Linkerd 是云原生应用的一种服务网格(Service Mesh)。它作为对应用透明的网络代理层通过封装服务间的调用为应用提供如:低延迟负载均衡(latency-aware load balancing)、链接重试(retry budgets)及终止(deadlines)、熔断机制(circuit breaking)等特性来提高应用的适应性(application resilience)。


除了能够提高应用的适应性,Linkerd 也能够提供强大的路由语言来改变服务在运行时请求流的方式。这篇文章我们将为您展示 Linkerd 如何做到这一点,不仅仅是全局范围,更精细到每一个基础请求。也将为您展示每一个请求路由如何被用来创建临时的预发布环境,从而允许在生产环境上下文中测试新代码而不用真正将其发布到生产环境里。最后,将为您介绍(in contrast to staging with a dedicated staging environment)临时的预发布环境如何做到既不需要与其他团队的协调工作,也不需要花费时间精力来同时保持多个部署环境。


为什么要预发布

为什么预发布如此重要?在现代软件开发当中,代码需要经过一系列预先设计好的实践路线来保证正确性:代码走查(code review),单元测试(unit tests),集成测试(integration tests)等等。经过这些流程之后,需要开始估算代码的表现了:新代码运行的速度如何?高负载下的表现如何?在运行时与其他服务以及相关依赖的交互表现如何?


预发布系统就可以回答这些问题。预发布的基本原则就是越接近生产环境,系统就越切实可行。因此,就像测试环节中的 mocks 和 stub 一样,对于预发布,我们期望能够运行真实的服务。最好的预发布环境就是和生产环境完全一样。



为什么微服务的预发布很难
如果你的应用由许多微服务构成,那么微服务之间的通信交互就会变成像端到端应用行为一样的重要组成部分。其实,应用拆分的越细,那么在运行时应用之间的交互就会越复杂,而此时应用的表现已经不仅仅是每个微服务自己的问题了,很大程度上取决于微服务之间的交互。

实际上,增加微服务的数量不仅仅增加了正确预发布的重要性,也同时增加了实现这一点的难度。我们来看几个常用的预发布方法,以及为什么在微服务环境下这些方法都会变得比较困难。


预发布的常规方法是共享预发布集群,而在这个集群里,除了你的预发布服务之外其他人的预发布服务也在这里。这种方式的弊端就是没有隔离。如下图展示,如果 Alex 把他的服务发布了上去但是出了点问题,整个链条中就很难判断出问题源的所在--因为问题可能出现在 Alex、Alice 或者 Bob 的服务上,又或者干脆就是数据库里的数据有问题。这样预发布环境与生产环境的同步就会非常困难,尤其是当服务、团队以及发行版本数量庞大的时候。


另一种共享环境称为“私人”或者单个开发者的预发布集群,可以解决隔离的问题。在这个例子中,每一个开发者可以根据需要来操作预发布集群。预发布一个服务需要同时预发布这个服务的上游以及下游服务也包括相关的依赖,从而可以保证预发布的有效性。(比如,在下图中,Alex 必须先发布 Web FE 和 API 服务来保证他的 Foo 服务可以正常运行。)然而,根据需要来维护以及部署部分应用拓扑结构会非常复杂,尤其是当应用拓扑结构非常大而且服务又有独立的部署模型。

上面说的是一种极其简单的部署新代码到生产环境并且有问题时可以回滚的方式。当然了,这种方式很有风险,而且不能处理部分应用类型,比如:金融事务。虽然还有很多其他的部署方法,但是本文我们将介绍一种直接的、轻松的方式。


一种更好的方式

使用 Linkerd 创建临时的预发布环境,就可以很好的避免以上提到的弊端。实际上,在 Twitter 里 Finagle 路由层作为linkerd 的底层,  他的主要动机就是解决这个问题。

我们来看一下 Alex 的 Foo 服务。如果,我们不另外部署一个隔离的环境,而是仅仅使用 Foo 的预发布版本替代 Foo 的生产版本,然后通过一个特殊的请求来访问它呢?针对生产环境,这将能够确保 Foo 的预发布版本的安全性,而且除了 Foo 预发布版本之外也不需要部署其他的任何东西。这就是临时预发布环境的本质。而此时,开发者身上的任务一下就轻松了:Alex 只需要预发布他的新代码,然后在 ingress 请求的 header 上设置一个标记就可以了,就这么简单!

Linkered 的单个请求路由可以帮助我们实现这种方式。通过 linkerd 的请求代理,可以给特定的请求上设置一个 l5d-dtab 的 header 。这个 header 可以允许你设置路由规则(叫做  in Finagle parlance, Dtabs)。比如,dtab 规则 /s/foo => /srv/alex-foo 可以覆盖 Foo 服务生产环境的规则。给单个请求添加这个可以使得请求直接到达 Alex 的 Foo 服务,也仅仅作用与这一个请求。Linkerd 可以拦截这个规则,所以生产环境里任何使用 Alex 的 Foo 服务的地方都可以正确的处理。



试一下这个功能吧

Service Mesh for Kubernetes 系列文章的读者应该已经知道我们有一个 demo our dogfood blog post。我们部署过一个 world-v2 服务,并且可以通过设置重定向路由规则发送单个的 dogfood 请求。现在我们可以使用相同机制来做些别的事情:创建一个临时的预发布环境。

部署一个服务的两个版本,再使用 linkerd 的路由功能在部署到生产环境之前来测试新服务。我们先部署 hello 和 world-v1 服务来作为我们的生产环境服务,然后再创建一个临时的预发布环境来测试 world 服务的新版本 world-v2。


1部署LINKERD和HELLO-WORLD服务


我们使用前一篇文章里部署的 hello world 服务。它由 hello 服务调用 world 服务组成。这些应用通过 Kubernetes downward API 提供的根据 nodeName 来找到 Linkerd 。如果你不确定你的集群是否支持 nodeName, 你可以运行如下命令:kubectl apply -f https://raw.githubusercontent. ... t.yml


然后查看一下日志:kubectl logs node-name-test


如果你看到了 ip 就表示成功了。然后再通过如下命令部署 hello world 应用:kubectl apply -f https://raw.githubusercontent. ... d.yml


如果你看到了 “server can’t find …” 错误,那就部署 hello-world 的 legacy 版本,这个版本依赖 hostIP 而不是 nodeName:kubectl apply -f https://raw.githubusercontent. ... y.yml


然后我们来部署生产环境(linkerd 和 hellow 以及 world 服务):$ kubectl apply -f https://raw.githubusercontent. ... s.yml


再来部署 linkerd 和预发布版本的服务 world-v2 ,这个服务会返回 "earth" 而不是 “world”。$ kubectl apply -f https://raw.githubusercontent. ... s.yml $ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/world-v2.yml 
 

2在临时预发布环境里使用单个请求覆盖

现在,我们运行了 world-v2 服务,来测试一下是否通了。我们期望的是请求到达的是 `world-v2` 而不是 `world-v1`。首先,先运行一个没有更改的请求,这个请求会走默认的路径。(你可能需要等待 l5d 的 external IP 出现):$ INGRESS_LB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}") $ curl -H "Host: www.hello.world" $INGRESS_LB Hello (10.196.2.232) world (10.196.2.233)!!


如果外部负载均衡不起作用,可以使用 hostIP:INGRESS_LB=$(kubectl get po -l app=l5d -o jsonpath="{.items[0].status.hostIP}"):$(kubectl get svc l5d -o 'jsonpath={.spec.ports[0].nodePort}') $ curl -H "Host: www.hello.world" $INGRESS_LB Hello (10.196.2.232) world (10.196.2.233)!!


如我们所料,返回了 `Hello (......) World (.....)`,这说明走的是生产环境。


那如何来请求预发布环境呢?我们需要做的就是发送给一个带有覆盖 header 的请求到生产环境中去,它就会访问到 `world-v2` 服务!由于 header 的设置,请求会走 `/srv/world-v2` 而不是`/host/world`。$ curl -H "Host: www.hello.world" -H "l5d-dtab: /host/world => /srv/world-v2;" $INGRESS_LB Hello (10.196.2.232) earth (10.196.2.234)!!我们看到了 "earch" 而不是 “world”! 这个请求已经成功的到达了 world-v2 服务,而且是在生产环境里,并且没有任何代码变更或者额外的部署工作。就是这样,预发布就变的 so easy 了。

Linkerd 的 Dtabs 和 routing 的文档非常健全。在开发中,你可以使用 linkerd 的 “dtab playground” http://$INGRESS_LB:9990/delegator。By going to the “outgoing” router and testing a request name like /http/1.1/GET/world, you can see linkerd’s routing policy in action.



实践
、在实践中,这种方式有一些需要注意的地方。首先,往生产环境的数据库里写东西时必须要小心。相同的 dtab 覆盖机制可以用来发送任何写预发布数据库的请求,或者在一些应用级别里直接 /dev/null。强烈建议,这些覆盖规则不能手动生成,以免发生不必要的错误,毕竟是在生产环境里!


其次,你的应用需要参考 linkerd's context headers。

最后非常重要的一点,避免外界可以设置 l5d-dtab 请求头。setting up a dogfood environment in Kubernetes 这篇文章里我们阐述了一个 nginx 的 ingress 样例配置,可以有效的去掉不认识的请求头。



结尾


我们举例了如何通过 linkerd 设置单个请求路由规则来达到创建临时预发布环境的问题。通过这种方式,我们可以在生产环境里预发布服务,而不需要更改现有代码,也不需要其他额外的预发布环境资源(当然除了预发布服务自己),同时也不需要处理预发布与生产这两个平行环境。对于微服务众多的应用来说,这种方式提供了一种发布到生产环境之前的简单、高效的预发布方式。


原文链接:https://buoyant.io/2017/01/06/a-service-mesh-for-kubernetes-part-vi-staging-microservices-without-the-tears/


推荐阅读:
 
4大维度3大预测,基于容器生态扩张的DevSecOps为啥引关注?
最佳实践 | 7大维度看国外企业为啥选择gRPC打造高性能微服务?
微服务迁移前,来听听这6个思考和经验

实测 | 转型微服务,这4大工具谁是API网关性能最优?

Linkerd小数 发表了文章 • 2 个评论 • 2636 次浏览 • 2018-02-08 10:44 • 来自相关话题

 
 作者:Turgay Çelik

翻译:钟毅(Drew Zhong)

原文:Comparing API Gateway Performances: NGINX vs. ZUUL vs. Spring Cloud Gateway vs. Linkerd

不管是从团队人数,还是从公司产品的特性的角度来看,我们 OpsGenie 都处于快速成长的过程中。举例来说,仅就去年一年,我们的工程师团队人数由15人增长到50人。同时我们遵从了 Two Pizza team rule ,将工程师团队每8人分成一组,以更好地适应团队总人数的迅速增长。


你可能也猜到,目前 OpsGenie 的产品已经有点类似巨石应用了。由于多个团队共同开发维护同一个产品 以及 CI/CD ( Continuous Integration/Continuous Delivery ) 流程等原因,产品的开发和维护已经变得极具挑战。因此,我们不得不紧随当下的趋势,将巨石应用向分布式架构转变。读者可以从 Martin Fowler 的文章中,了解更多关于微服务架构和它的优点。


在对微服务概念的实践中,有一些值得推荐的架构模式。而 API 网关就是这些模式中的一个。简单来说,API 网关就是所有客户端的统一入口。它通过两种方式来处理客户端请求:一是作为代理,将请求路由给某一个特定的服务;二是将请求分散给多个服务。 API 网关是微服务框架的一个很好的开端,因为一个巨石应用微服务化后能够得到多个不同的服务,而API 网关能将特定的请求路由给特定的服务。


实际上,API 网关对我们来说并不是一个新的概念。我们用 Nginx 来作为我们巨石应用的 API 网关已经很长一段时间了,但是既然我们已经打算向微服务转型,那我们就不得不重新评估 Nginx 是不是一个好的选择。性能、可扩展性以及像限流等其它特性,都是我们需要考虑的。当然网关的性能,尤其是在高并发场景下能否满足我们的需求,才是我们最在意的。


在本篇博文中,我们将阐述如何搭建我们的测试环境,并比较 Zuul 1、Nginx、Spring Cloud Gateway 和 Linkerd。事实上,我们还有像 Lyft 的 Envoy 和 UnderTow 等其它备用方案。我们会对这些工具进行同样的测试,然后在以后的博文中再分享结果。


Zuul 1 对我们团队而言是一个不错的选择。因为它是由 Java 开发的,而且也完美兼容 Spring 框架。目前,已经有一些博客是进行 Zuul 和 Nginx 的比较的。但我们同时也想要比较 Spring Cloud 网关和 Linkerd,另外,我们也希望进行更一步的压力测试。所以,我们决定搭建我们自己的环境来进行测试。


为了客观地评估各个 API 网关自身的性能,我们创建了一个独立于 OpsGenie 产品之外的 隔离的测试环境。我们使用 Apache Http Server Benchmarking tool — ab 来搭建我们的测试环境。


首先,我们根据 Nginx 的官方文档,在 AWS EC2 t2.micro 实例上部署 Nginx 。这是我们的初始测试环境。然后我们在这个环境之上,又部署了 Zuul 和 Spring Cloud Gateway。Nginx web 服务器中放置了一些静态资源,然后我们分别在 Nginx、Zuul 和 Spring Cloud Gateway 上定义一些指向 web 服务器的反向代理。然后我们将另一个 t2.micro EC2 作为客户端,来发起一些请求。









图中带箭头的虚线就是我们测试用的路径。主要有以下五种方式:

· 直连

· 通过 Nginx 反向代理请求

· 通过 Zuul 请求

· 通过 Spring Cloud Gateway 请求

· 通过 Linkerd 请求


鉴于读者往往更关心结果,所以接下来我们会先给出测试结果,然后再进行详细的解释。


Benchmark性能总数



测试策略

我们使用 Apache 的 HTTP 服务器 Benchmark 工具。每一轮,我们用200个线进行10000次请求。


ab -n 10000 -c 200 HTTP://<server-address>/<path to resource>

我们在三种不同配置的 AWS EC2 上进行测试。为了更好地说明真实的请求, 我们对每一轮测试都进行了细分:

· 为了了解代理本身所需要的开销,我们首先对直连方式进行了额外的单独测试。但介于直连并不是我们的待选方案,因此后面的几轮就不再对直连进行测试。


· 介于 Spring Cloud Gateway 至今还没有正式发版,因此我们只会在最后一轮对它进行测试。


· Zuul 在调用过一次之后的性能表现会更好。我们认为这是 JIT 优化 (Just In Time) 的效果。所以我们形象地将 Zuul 的第一次运行称作是“热身”。当然,下面各个表中的数值都是 Zuul“热身”之后的性能。


· 我们都知道,Linkerd 是一种很吃资源的代理方式,因此我们就只在最后一轮,即性能配置最佳的方案中才会进行对它的比较。



测试用配置

T2.Micro --单核、1g内存:我们在这个配置上进行直连、Nginx 反向代理和 Zuul (热身后)三种代理方式的测试 M4.Large --双核、8g内存:我们在这个配置上进行 Nginx 反向代理和 Zuul (热身后)两种代理方式的测试 M4.2xLarge --八核、32g内存:我们在这个配置上进行 Nginx 反向代理、Zuul(热身后)、Spring Cloud Gateway 和 Linkerd 四种代理方式的测试



测试结果

以下是性能测试结果的概要:













测试的细节


直连

首先,我们在不使用任何代理的情况下直接访问静态资源。结果如下图所示。每次请求所需要的响应时间是30ms。 









通过 Nginx 反向代理连接


在第二次测试中,我们通过Nginx反向代理访问资源。每次请求的响应时间为40ms。我们发现,和上一部分不使用任何代理的直连方式相比,Nginx反向代理平均增加了33%的耗时。 








通过 Zuul 反向代理的连接

首先,我们创建了一个如下 Spring Boot 应用程序:







以下是我们的 application.yml 配置文件 







Zuul“热身”测试的结果如下: 






直连和通过 Nginx 反向代理的方式分别耗时30ms和40ms。在 Zuul 的首轮测试中,每一次请求响应耗时为388ms。正如其它博客中提到的那样,JVM 热身会有所帮助。我们又重新对 Zuul 进行一轮测试,结果如下: 

Zuul在“热身”之后的性能确实有所提高,每一次请求的响应时间下降到了200ms,但是和 Nginx 反向代理平均40ms的耗时相比,还是有比较大的差距的。


将服务器升级到m4.large

正如图一所示,t2.micro ec2 仅仅是单核 1G 内存。Nginx 是 c++ 程序而 Zuul 是 Java 语言实现的。众所周知,Java 应用程序对性能的要求会更高一些。因此我们使用 m4.large 服务器(双核,8G)来进行测试。 我们再一次对 Nginx 和 Zuul 两种反向代理方式分别进行测试,结果如下: 












正如以上两幅图所示,Nginx 和 Zuul 的请求响应时间分别是32ms和95ms。结果要远好于在 t2.micro 服务器进行测试时的结果。 当然,以上测试还有一个明显值得争议的问题:我们是通过 Spring Boot 应用程序来使用 Zuu l的,这自然会带来额外的性能消耗。如果我们单独对 Zuul 来进行测试,那么测试的性能结果可能还会更好。




将服务器升级到m4.2xlarge?

我们也在 m4.2xlarge 的机器(8核,32G内存)上进行了测试,Nginx 和 Zuul 的结果分别如下: 













在 m4.2xlarge 的机器上,Zuul 的性能要好于 Nginx。我们想要知道 Netflix 公司是使用的哪一种 EC2 来运行 Zuul 实例的,但是却找不到对应的答案。在其它的一些博文中会有人抱怨 Zuul 的性能,然后也在询问 Netflix 公司扩展它的方式,我们觉得这次的测试结果就是答案:Zuul 的性能受限于 CPU,所以必须加 CPU。


Linkerd的测试

Linkerd 是一个云原生计算基金会的项目。它是一个 Scala 语言实现的 Service Mesh / 服务网格 应用程序,提供如服务发现等能力,但它同时也提供了反向代理的能力。我们测试了 Linkerd 的性能,结果如下图所示。Linkerd 的性能非常接近 Zuul。 







Spring Cloud Gateway的测试

Spring Cloud 社区也在开发一个网关组件。虽然官方还没有正式发布这款组件,但我们认为还是需要将它和其他的可选组件一同来进行比较。因此,我们根据我们的测试环境修改了 Spring Cloud Gateway 应用程序的范例。 我们对它进行了同样的性能测试,通过 Apache Http 服务器性能测试工具,用200个并发线程进行10000次请求。结果如下: 此处输入链接的描述 如图所示,Spring Cloud Gateway 每秒处理873个请求,每个请求的响应时间是229ms。从我们测试的结果看来,Spring Cloud Gateway 并达不到 Zuul、Linkerd 和 Nginx 的水平,至少从它们当前各自 Github 上的代码是可以得到这样子的结论的。


接下来的工作

在本篇博客中,我们用Apache Http服务器性能测试工具对Zuul、Nginx、Linkerd和Spring Cloud Gateway进行了测试。以下是我们接下来的一些计划:

我们准备对 Envoy 进行评估。实际上 Envoy 不仅仅是一个 API 网关,它同时也是 Service Mesh/服务网格应用。

Undertow 也提供了反向代理的能力,也是我们接下来需要评估的。

Netflix 重新设计了 Zuul,将它设计成基于 Netty 的非阻塞应用。这个新版本叫作 "Zuul 2".我们准备在其开源版本正式发布后对其进行性能测试,然后再分享这一新 Zuul 的测试结果。

Spring Cloud Gateway 尚未开发完成,它是一个 Java 语言的基于 Netty 的非阻塞网关,因此它对于我们来说也是一个不错的选择。我们同样会对其官网版本进行性能测试。

API 网关中,一些是阻塞的,比如 Nginx 和 Zuul 1,另外一些是非阻塞的,比如 Zuul 2、Linkerd、Envoy。阻塞架构的好处在于开发简单,易于请求的追踪,但同时也会导致扩展方面的问题。非阻塞架构在开发和追踪方面会复杂一些,但是它的扩展能力和弹性伸缩能力要更加出色。因此我们加下来也会对这两种架构方案做出选择我们也会对 Gatling 进行一些测试,并在下一篇博客中分享测试结果。


我们会在接下来的每一篇博文中都对我们所取得的进展和发现进行分享,敬请期待。
 
 
推荐阅读:
 
4大维度3大预测,基于容器生态扩张的DevSecOps为啥引关注?
4大维度3大预测,基于容器生态扩张的DevSecOps为啥引关注?
微服务迁移前,来听听这6个思考和经验
  查看全部

0_DJgZyCP0LbCsyuhA_.png

 
 作者:Turgay Çelik

翻译:钟毅(Drew Zhong)

原文:Comparing API Gateway Performances: NGINX vs. ZUUL vs. Spring Cloud Gateway vs. Linkerd

不管是从团队人数,还是从公司产品的特性的角度来看,我们 OpsGenie 都处于快速成长的过程中。举例来说,仅就去年一年,我们的工程师团队人数由15人增长到50人。同时我们遵从了 Two Pizza team rule ,将工程师团队每8人分成一组,以更好地适应团队总人数的迅速增长。


你可能也猜到,目前 OpsGenie 的产品已经有点类似巨石应用了。由于多个团队共同开发维护同一个产品 以及 CI/CD ( Continuous Integration/Continuous Delivery ) 流程等原因,产品的开发和维护已经变得极具挑战。因此,我们不得不紧随当下的趋势,将巨石应用向分布式架构转变。读者可以从 Martin Fowler 的文章中,了解更多关于微服务架构和它的优点。


在对微服务概念的实践中,有一些值得推荐的架构模式。而 API 网关就是这些模式中的一个。简单来说,API 网关就是所有客户端的统一入口。它通过两种方式来处理客户端请求:一是作为代理,将请求路由给某一个特定的服务;二是将请求分散给多个服务。 API 网关是微服务框架的一个很好的开端,因为一个巨石应用微服务化后能够得到多个不同的服务,而API 网关能将特定的请求路由给特定的服务。


实际上,API 网关对我们来说并不是一个新的概念。我们用 Nginx 来作为我们巨石应用的 API 网关已经很长一段时间了,但是既然我们已经打算向微服务转型,那我们就不得不重新评估 Nginx 是不是一个好的选择。性能、可扩展性以及像限流等其它特性,都是我们需要考虑的。当然网关的性能,尤其是在高并发场景下能否满足我们的需求,才是我们最在意的。


在本篇博文中,我们将阐述如何搭建我们的测试环境,并比较 Zuul 1、Nginx、Spring Cloud Gateway 和 Linkerd。事实上,我们还有像 Lyft 的 Envoy 和 UnderTow 等其它备用方案。我们会对这些工具进行同样的测试,然后在以后的博文中再分享结果。


Zuul 1 对我们团队而言是一个不错的选择。因为它是由 Java 开发的,而且也完美兼容 Spring 框架。目前,已经有一些博客是进行 Zuul 和 Nginx 的比较的。但我们同时也想要比较 Spring Cloud 网关和 Linkerd,另外,我们也希望进行更一步的压力测试。所以,我们决定搭建我们自己的环境来进行测试。


为了客观地评估各个 API 网关自身的性能,我们创建了一个独立于 OpsGenie 产品之外的 隔离的测试环境。我们使用 Apache Http Server Benchmarking tool — ab 来搭建我们的测试环境。


首先,我们根据 Nginx 的官方文档,在 AWS EC2 t2.micro 实例上部署 Nginx 。这是我们的初始测试环境。然后我们在这个环境之上,又部署了 Zuul 和 Spring Cloud Gateway。Nginx web 服务器中放置了一些静态资源,然后我们分别在 Nginx、Zuul 和 Spring Cloud Gateway 上定义一些指向 web 服务器的反向代理。然后我们将另一个 t2.micro EC2 作为客户端,来发起一些请求。


图片1.png




图中带箭头的虚线就是我们测试用的路径。主要有以下五种方式:

· 直连

· 通过 Nginx 反向代理请求

· 通过 Zuul 请求

· 通过 Spring Cloud Gateway 请求

· 通过 Linkerd 请求



鉴于读者往往更关心结果,所以接下来我们会先给出测试结果,然后再进行详细的解释。


Benchmark性能总数



测试策略

我们使用 Apache 的 HTTP 服务器 Benchmark 工具。每一轮,我们用200个线进行10000次请求。


ab -n 10000 -c 200 HTTP://<server-address>/<path to resource>

我们在三种不同配置的 AWS EC2 上进行测试。为了更好地说明真实的请求, 我们对每一轮测试都进行了细分:

· 为了了解代理本身所需要的开销,我们首先对直连方式进行了额外的单独测试。但介于直连并不是我们的待选方案,因此后面的几轮就不再对直连进行测试。


· 介于 Spring Cloud Gateway 至今还没有正式发版,因此我们只会在最后一轮对它进行测试。


· Zuul 在调用过一次之后的性能表现会更好。我们认为这是 JIT 优化 (Just In Time) 的效果。所以我们形象地将 Zuul 的第一次运行称作是“热身”。当然,下面各个表中的数值都是 Zuul“热身”之后的性能。


· 我们都知道,Linkerd 是一种很吃资源的代理方式,因此我们就只在最后一轮,即性能配置最佳的方案中才会进行对它的比较。



测试用配置

T2.Micro --单核、1g内存:我们在这个配置上进行直连、Nginx 反向代理和 Zuul (热身后)三种代理方式的测试 M4.Large --双核、8g内存:我们在这个配置上进行 Nginx 反向代理和 Zuul (热身后)两种代理方式的测试 M4.2xLarge --八核、32g内存:我们在这个配置上进行 Nginx 反向代理、Zuul(热身后)、Spring Cloud Gateway 和 Linkerd 四种代理方式的测试



测试结果

以下是性能测试结果的概要:

图片2.png


图片3.png




测试的细节


直连

首先,我们在不使用任何代理的情况下直接访问静态资源。结果如下图所示。每次请求所需要的响应时间是30ms。 


图片4.png




通过 Nginx 反向代理连接


在第二次测试中,我们通过Nginx反向代理访问资源。每次请求的响应时间为40ms。我们发现,和上一部分不使用任何代理的直连方式相比,Nginx反向代理平均增加了33%的耗时。 


图片5.png



通过 Zuul 反向代理的连接

首先,我们创建了一个如下 Spring Boot 应用程序:

图片6.png



以下是我们的 application.yml 配置文件 

图片7.png



Zuul“热身”测试的结果如下: 

图片8.png


直连和通过 Nginx 反向代理的方式分别耗时30ms和40ms。在 Zuul 的首轮测试中,每一次请求响应耗时为388ms。正如其它博客中提到的那样,JVM 热身会有所帮助。我们又重新对 Zuul 进行一轮测试,结果如下: 

Zuul在“热身”之后的性能确实有所提高,每一次请求的响应时间下降到了200ms,但是和 Nginx 反向代理平均40ms的耗时相比,还是有比较大的差距的。


将服务器升级到m4.large

正如图一所示,t2.micro ec2 仅仅是单核 1G 内存。Nginx 是 c++ 程序而 Zuul 是 Java 语言实现的。众所周知,Java 应用程序对性能的要求会更高一些。因此我们使用 m4.large 服务器(双核,8G)来进行测试。 我们再一次对 Nginx 和 Zuul 两种反向代理方式分别进行测试,结果如下: 

图片9.png


图片10.png



正如以上两幅图所示,Nginx 和 Zuul 的请求响应时间分别是32ms和95ms。结果要远好于在 t2.micro 服务器进行测试时的结果。 当然,以上测试还有一个明显值得争议的问题:我们是通过 Spring Boot 应用程序来使用 Zuu l的,这自然会带来额外的性能消耗。如果我们单独对 Zuul 来进行测试,那么测试的性能结果可能还会更好。




将服务器升级到m4.2xlarge?

我们也在 m4.2xlarge 的机器(8核,32G内存)上进行了测试,Nginx 和 Zuul 的结果分别如下: 


图片11.png


图片12.png



在 m4.2xlarge 的机器上,Zuul 的性能要好于 Nginx。我们想要知道 Netflix 公司是使用的哪一种 EC2 来运行 Zuul 实例的,但是却找不到对应的答案。在其它的一些博文中会有人抱怨 Zuul 的性能,然后也在询问 Netflix 公司扩展它的方式,我们觉得这次的测试结果就是答案:Zuul 的性能受限于 CPU,所以必须加 CPU。


Linkerd的测试

Linkerd 是一个云原生计算基金会的项目。它是一个 Scala 语言实现的 Service Mesh / 服务网格 应用程序,提供如服务发现等能力,但它同时也提供了反向代理的能力。我们测试了 Linkerd 的性能,结果如下图所示。Linkerd 的性能非常接近 Zuul。 

图片13.png



Spring Cloud Gateway的测试

Spring Cloud 社区也在开发一个网关组件。虽然官方还没有正式发布这款组件,但我们认为还是需要将它和其他的可选组件一同来进行比较。因此,我们根据我们的测试环境修改了 Spring Cloud Gateway 应用程序的范例。 我们对它进行了同样的性能测试,通过 Apache Http 服务器性能测试工具,用200个并发线程进行10000次请求。结果如下: 此处输入链接的描述 如图所示,Spring Cloud Gateway 每秒处理873个请求,每个请求的响应时间是229ms。从我们测试的结果看来,Spring Cloud Gateway 并达不到 Zuul、Linkerd 和 Nginx 的水平,至少从它们当前各自 Github 上的代码是可以得到这样子的结论的。


接下来的工作

在本篇博客中,我们用Apache Http服务器性能测试工具对Zuul、Nginx、Linkerd和Spring Cloud Gateway进行了测试。以下是我们接下来的一些计划:

我们准备对 Envoy 进行评估。实际上 Envoy 不仅仅是一个 API 网关,它同时也是 Service Mesh/服务网格应用。

Undertow 也提供了反向代理的能力,也是我们接下来需要评估的。

Netflix 重新设计了 Zuul,将它设计成基于 Netty 的非阻塞应用。这个新版本叫作 "Zuul 2".我们准备在其开源版本正式发布后对其进行性能测试,然后再分享这一新 Zuul 的测试结果。

Spring Cloud Gateway 尚未开发完成,它是一个 Java 语言的基于 Netty 的非阻塞网关,因此它对于我们来说也是一个不错的选择。我们同样会对其官网版本进行性能测试。

API 网关中,一些是阻塞的,比如 Nginx 和 Zuul 1,另外一些是非阻塞的,比如 Zuul 2、Linkerd、Envoy。阻塞架构的好处在于开发简单,易于请求的追踪,但同时也会导致扩展方面的问题。非阻塞架构在开发和追踪方面会复杂一些,但是它的扩展能力和弹性伸缩能力要更加出色。因此我们加下来也会对这两种架构方案做出选择我们也会对 Gatling 进行一些测试,并在下一篇博客中分享测试结果。


我们会在接下来的每一篇博文中都对我们所取得的进展和发现进行分享,敬请期待。
 
 
推荐阅读:
 
4大维度3大预测,基于容器生态扩张的DevSecOps为啥引关注?
4大维度3大预测,基于容器生态扩张的DevSecOps为啥引关注?
微服务迁移前,来听听这6个思考和经验
 

如期而至:正在走向生产之路的Conduit v0.2.0 里程碑版本发布

Conduit小数 发表了文章 • 0 个评论 • 368 次浏览 • 2018-02-05 18:35 • 来自相关话题

 作者:GEORGE MIRANDA

Release Note 转自:伪架构师(公众号ID:fake-architect)

原文:Announcing Conduit support for HTTP/1.x and TCP


我们很高兴地宣布,最新的 Conduit 发布了一个重大的项目里程碑版本。在 0.2.0 版本中,除了现有的 HTTP/2 支持之外,Conduit 现在还包含对 HTTP/1.x 和 TCP 流量的支持。这意味着 Conduit 现在可以直接支持大部分 Kubernetes 应用程序。


在发布这个版本的过程中,最令我们激动的一件事就是我们在简化服务网格入门的过程中不断取得进展。 Conduit 致力于通过“零配置”的管理方法,来降低实现服务网格可操作性的工作量。换句话说,你不应该只是为了获得你所需要的基本可见性、管理、和控制而陷入配置选项的困境中。


在 0.2.0 版本中,你会注意到 Conduit 并不是完全的"零配置",但是我们正在接近这一目标。一些服务现在还需要手动配置。值得注意的是,如果你使用的是 WebSockets 或者服务器在客户端之前发送流量的协议(例如,非 TLS 加密的 MySQL 或 SMTP 连接),则仍然需要使用某些配置管理这些例外。你可以在发行说明中找到更多详细信息。


Conduit 仍然处于 Alpha 阶段,因此在准备好生产工作负载之前还有很多工作要做。但是 Conduit 的发展速度超出了我们的预期,在即将到来的 0.3 里程碑里,我们相信 Conduit 会为你提供更好的服务。请继续关注正在走向生产之路的 Conduit。


里程碑版本,这次发布中新增了对 HTTP/1.x 和 TCP 支持,这样就可以为绝大多数运行在 Kubernetes 上的应用提供支持了。

数据面​
Conduit 现在为包括 HTTP/1.x 和 HTTP/2 在内的所有 TCP 流量提供透明代理。
 

控制台界面

强化了tap命令的错误处理能力。

tap也提供了对 HTTP/1.x 的支持。



Dashboard

界面进行了小幅更新。

可以在 Dashboard 边栏搜索 Deployment。



预告

Conduit 将会为绝大多数协议提供自动支持,然而使用 WebSockets、HTTP 隧道/代理或者 MySQL、SMTP 等协议,需要一些额外配置,文档(注 1)中会有详细说明。

Conduit 还不支持外部 DNS。这一缺憾将在未来版本提供支持。

目前 Conduit 的遥测管线无法扩展到某些节点,后续版本会解决这个问题。

Conduit 还是 Alpha 阶段,请提交 Issue 或 PR 来支持我们!(注 2)



引用:

https://conduit.io/adding-your ... pport

https://github.com/runconduit/conduit/issues/new


推荐阅读:
 
案例 | 某全球零售客户:上马容器云 驾驭线上业务
PPT下载 | 亿级用户万台服务器背后,vivo云服务容器化如何破茧化蝶?
微服务迁移前,来听听这6个思考和经验
  查看全部

version_conduit_020-680x341.png

 作者:GEORGE MIRANDA

Release Note 转自:伪架构师(公众号ID:fake-architect)

原文:Announcing Conduit support for HTTP/1.x and TCP


我们很高兴地宣布,最新的 Conduit 发布了一个重大的项目里程碑版本。在 0.2.0 版本中,除了现有的 HTTP/2 支持之外,Conduit 现在还包含对 HTTP/1.x 和 TCP 流量的支持。这意味着 Conduit 现在可以直接支持大部分 Kubernetes 应用程序。


在发布这个版本的过程中,最令我们激动的一件事就是我们在简化服务网格入门的过程中不断取得进展。 Conduit 致力于通过“零配置”的管理方法,来降低实现服务网格可操作性的工作量。换句话说,你不应该只是为了获得你所需要的基本可见性、管理、和控制而陷入配置选项的困境中。


在 0.2.0 版本中,你会注意到 Conduit 并不是完全的"零配置",但是我们正在接近这一目标。一些服务现在还需要手动配置。值得注意的是,如果你使用的是 WebSockets 或者服务器在客户端之前发送流量的协议(例如,非 TLS 加密的 MySQL 或 SMTP 连接),则仍然需要使用某些配置管理这些例外。你可以在发行说明中找到更多详细信息。


Conduit 仍然处于 Alpha 阶段,因此在准备好生产工作负载之前还有很多工作要做。但是 Conduit 的发展速度超出了我们的预期,在即将到来的 0.3 里程碑里,我们相信 Conduit 会为你提供更好的服务。请继续关注正在走向生产之路的 Conduit。


里程碑版本,这次发布中新增了对 HTTP/1.x 和 TCP 支持,这样就可以为绝大多数运行在 Kubernetes 上的应用提供支持了。

数据面​
Conduit 现在为包括 HTTP/1.x 和 HTTP/2 在内的所有 TCP 流量提供透明代理。
 

控制台界面

强化了tap命令的错误处理能力。

tap也提供了对 HTTP/1.x 的支持。



Dashboard

界面进行了小幅更新。

可以在 Dashboard 边栏搜索 Deployment。



预告

Conduit 将会为绝大多数协议提供自动支持,然而使用 WebSockets、HTTP 隧道/代理或者 MySQL、SMTP 等协议,需要一些额外配置,文档(注 1)中会有详细说明。

Conduit 还不支持外部 DNS。这一缺憾将在未来版本提供支持。

目前 Conduit 的遥测管线无法扩展到某些节点,后续版本会解决这个问题。

Conduit 还是 Alpha 阶段,请提交 Issue 或 PR 来支持我们!(注 2)



引用:

https://conduit.io/adding-your ... pport

https://github.com/runconduit/conduit/issues/new


推荐阅读:
 
案例 | 某全球零售客户:上马容器云 驾驭线上业务
PPT下载 | 亿级用户万台服务器背后,vivo云服务容器化如何破茧化蝶?
微服务迁移前,来听听这6个思考和经验
 

PPT下载 | 远离分布式计算8大谬论,用Istio三大组件成为使用微服务的“高个子”

Istio小数 发表了文章 • 3 个评论 • 589 次浏览 • 2018-02-02 14:27 • 来自相关话题

2018年1月27日,数人云Meetup 联合vivo在深圳举办 Building Microservice 系列活动第1期。本次技术沙龙vivo、中兴通讯、华为、数人云共同派出技术大咖,为开发者们带来有关微服务、容器化、配置中心、服务网格等领域的实战与干货分享。


近几年我一直从事于微服务系统的设计以及实现方面的工作,属于微服务架构一线实践者。之前做过一些单体系统的微服务改造,在微服务拆分、治理等方面都有一定的经验。本人比较特殊一点的经历是既做过 IT 领域的微服务,也做过 CT(通讯领域)的微服务,微服务架构在这两个领域的具体形态和要求是不太一样的,但其中一些思想是互通且是很有借鉴意义的。今天主要介绍一下关于微服务的最新发展动态,以及最近谷歌推出的 Istio平台架构。

今天介绍的主题包含:服务治理、服务网格、Istio架构,以及 Istio 相应的系统组成。



一、分布式计算的八个谬论


彼得多维奇多年前提出的分布式计算的八个谬论,对于开发人员来说他们往往会忽视这八条。这八条基本上都和网络相关,例如在发起一个网络请求时,会不断地做一些尝试等待,来保障消息投递的有效性。


微服务是一个更为复杂的分布式系统,之前 SOA 或者B/S,CS 架构,它的颗粒度会更粗一点,但是如果采用微服务,它的颗粒度是更细的。在马丁·富勒博客《微服务的先决条件是什么》一文中提到一条,你必须要成为“高个子”,想成为“高个子”其实并不简单,很多公司,它们都是为了成为“高个子”,做了很多框架、平台。


二、服务治理

1 微服务治理的技术点

要成为“高个子”需要对微服务进行哪些改造,这里是相关服务治理的技术点,其中只是一部分,和服务网格比较相关的技术点,包含服务发现、负载均衡、请求路由、认证与授权、可观测性,还有健康检查、容错等。目前主流的解决方案有众所周知的 Spring Cloud, Dubbo 等,这些都是提供库来把服务治理相关的内容打包,供具体的业务去调用。



2 库或框架的问题

但是库和框架会存在一些问题:


 1、学习成本。多一个库对于开发人员而言,意味着要多学一些东西,并且在业务开发过程中,还会受到库或者框架的制约。


2、对业务代码的侵入性。例如用 Spring Cloud 会在代码里面加很多额外的内容,比如每个请求里面加一个注解来表达想引用服务治理的某些功能。


3、基础库的维护、升级和下线。如果是以库的方式来提升到服务里面,库的维护、升级、下线就会造成整个服务的维护、升级、下线。


4、不同语言和技术栈。在提出微服务概念时,它的一个重要好处就是可以使用不同的技术栈来开发微服务,但如果受到框架制约,只能用这个语言,这是我们比较头痛的事情,无法发挥微服务跨语言的能力。


这些问题其实是有严重程度的,从上往下越来越让开发人员觉得不舒服。理想中的服务治理方案是什么?可以先畅想一下,整个服务治理相关的东西,应该是和业务逻辑完全隔离的,并且服务和服务之间的交互是不会考虑服务治理这块内容,最好对于业务开发来说是不可见的。


这时候怎么去做呢?就引出了容器经典部署模式——Sidecar。


3 Sidecar模式

Sidecar 模式通常是和容器一起使用,如果不和容器一起使用也没关系,那就是两个独立的进程,如果和容器使用的话,就基于容器为单位。Sidecar模式是物理隔离的,并且与语言无关。因为是两个独立的东西,可以独立发布,和微服务理念一样。另外它们是部署在同一个 Host 上面,所以资源之间可以做到相互访问,并且因为在一起所以通信延迟也不会太明显。和业务无关的功能都可以放上去,形成多个 Sidecar。今天 Sidecar 主要是把一些服务治理相关的东西放在里面,做软件设计上的思想就是分离关注点。


基于 Sidecar 模式做服务治理,之后形成连接的具体状况,如图,对于服务A来说,服务A是不知道和 Sidecar 进行通信,服务A还是向服务B发消息,照常调用通信接口,但是消息可能会被 Sidecar 捕获到,然后通过Sidecar 进行转发。


三、服务网格

从整个系统来看,如果以 Sidecar 方式来部署服务治理以及服务的话,最终形成的系统如图。能看到通过 Sidecar 进行相互连接,形成一个网络,这也是服务网格名字的由来。每一个节点上面都相当于具体的网格,和多年之前提的网格计算有点类似。


服务网格如果站在更抽象的层次来看是什么样子?把服务治理相关的东西抽象来看的话,服务网格也算是一种基础设施,它和具体的业务无关。不管是 PaaS 的发展,还是服务网格的发展,都是将与业务无关的内容的共同点提取出来,然后形成独立的一套平台或者方案。另外,服务网格之间要形成可靠传递,刚才提到的重试等功能都应该具备。


服务网格是轻量级的网络代理,不能太重,不能喧兵夺主,服务才是整个系统中最重要的东西,而这些基础设施并不应该取代服务最重要的价值地位。

更关键的一点是要对应用程序透明。对于服务而言是看不到 Sidecar、看不到代理的,服务如果要发消息出去,它知道是发给这个代理的,那对于我们的业务来说同样也是一种污染。服务网格最终不再强调代理作为单独的组件,不再孤立的来看代理,而是从全局的角度来看待代理所形成的网络。



1 服务网格定义

服务网格的定义是 Willian Morgan 提出来的,他是最早做服务网格的人。如图,文字加粗的是服务网格一些关键技术点。右边图是最新发展的服务网格,在最上层还会加一个控制面板,通过控制面板来管理这些代理,这些代理是需要被管理的。如果我们的运维环境没有控制面板,可能就没办法运维了。



2 服务网格的基本构成

服务网格必须要具备数据面板和控制面板,如果新开发一个服务网格只有数据面板,它肯定不是一个完整的服务网格。

数据面板是用来接收系统中的每一个包或者请求,提供服务发现、健康检查等服务治理相关的,都是由数据面板来完成。数据面板的一些典型代表有 Linked、Envoy、和 Nginx 公司开发的 Nginmesh,以及硬件服务的代理厂商F5开发的 Aspen Mesh。目前主要的、成熟的是 Linked 和 Envoy,这两者都在生产环境上面真实部署过,实战过。而且Linked的采用会更广泛一些,因为它出现的时间最早。


对于控制面板来说,是为了在网格中运营的数据面板提供策略和配置,负责一些管理工作,它不会接收系统中的任何包或者请求。这里的包和请求应该是业务相关的包和请求,和具体的业务是完全没关系的。本来做微服务应该做去中心化的事情,但是又有一个控制点在那里,要强调的是那个控制点和具体的业务没什么关系。控制面板的典型代表,包括 Istio、Conduit、Nleson、SmartStack,目前最新的是 Istio 和 Conduit。


3 数据面板对比

左边是 Linked(Scala编写),右边是 Envoy(C++编写),它们最大的区别就是实现语言的区别。同时,Linkerd 和 Envoy 都是在生产环境已经验证过的两个系统,功能上都没问题,都比较强大,它们唯一的区别就是对于硬件资源的要求,Linked 是非常高的,它可能就会造成喧兵夺主的感觉,所以目前 Envoy 在这块是比较火的,Envoy 是由C++开发的。



4 控制面板对比

两个最新的控制面板,一个是 Istio,是由 Google、IBM、Lyft 开发的,而 Conduit 是由 Buoyant 公司开发的,跟刚才所说的性能不太好的数据面板Linkerd是同一家公司,Buoyant 在 Linkerd 之后又重新开发了 Conduit,专门来解决性能上的问题,所以在性能上面来看,Conduit 的性能指标已经出来了,就是微秒级,并且是P99延迟。但是 Istio 的性能指标现在还没出来,还在功能开发阶段。因为 Istio需要实现的功能比较多,要支持各种各样的平台和过滤,Istio 整个架构非常灵活,所以 Istio 整个量级是比较重量的,但是 Conduit 只支持 K8S,Conduit 的原则是怎么快怎么来。



从编程语言上来说,控制面板 Istio 和 Conduit 都是使用Go语言,但是在数据面板上 Istio 是使用C++,Conduit 使用 Rust,可以看出来这两个语言都是那种比较高效的,在数据面板上面必须要使用高效的语言来完成。


四、Istio架构

一句话定义 Istio:一个用来连接、管理和保护微服务的开放平台。刚才也说了 Istio 是 Google 开发的,所以 Istio 今后的趋势肯定是会越来越火的,并且目前 K8S 已经把它集成到里面了,做成一个可选的组件。

对于连接而言,Istio 它主要包含弹性、服务发现、负载均衡,管理是流量控制、策略增强,监控也有,并且安全这块 Istio 也是有考虑,Istio 是端到端的身份验证和授权,等一下会详细的介绍。


Istio的关键特性:

1、智能路由和负载均衡。这里的智能路由和负载均衡是属于比较高级的,不是像传统简单的随机负载均衡,而是可以基于一些数据包内部的内容来进行负载均衡。

2、跨语言和平台的弹性。对于平台来说 Istio 是支持各种各样的平台,并且能支持A/B测试,金丝雀发布,并使用蓝绿部署运维上的一些高级功能。

3、全面策略执行。Istio 有一个组件是专门负责保障策略能够通过一个组件下发到具体的数据面板。

4、遥测和上报。即具体的测量以及流量的监控等。

这个就是 Istio 整个的系统架构,如图,上面是控制面板,下面是很多数据 Envoy,很多个代理,形成一个数据面板。后面我们会对单个进行详细介绍。

这是在 K8S 下面 Istio 部署的示意图,可以看到它们之间最关键的东西是所有服务和组件都会有一个代理,这代理是必备的,包括控制面板都会有代理。没有画的有两个东西,一个是 Ingress,一个是初始化器,初始化器主要是做代理注入。它们之间相互的交互都是通过加密,由TLS协议来完成。


五、Istio组件

1 数据面板Envoy

介绍一下 Istio 的核心组件,首先是 Istio 的数据面板 Envoy。

Envoy 的目标是透明地处理集群内服务间、从服务到外部服务之间的出入口流量。Envoy 是用C++编写的,高并行、非阻塞。并且是可装卸的L3/4过滤器,以及L7的过滤器,最终会形成一个过滤链来对流量进行管理或者控制,Envoy 是通过 xDS 动态配置来进行接口提供。

下面就是一些固有的功能,服务发现、健康检查。Envoy 的健康检查也做的颗粒度比较细,包含主动健康检查和被动健康检查。主动健康检查像常规的健康检查,主动地发一个健康检查的接口调用请求,查询一下。被动的是通过对其他服务的一些请求,从一些返回值进行健康检查。当然还包含高级的负载均衡,监控、跟踪这些功能。


Envoy最关键的三个点:

高性能。一直在强调的是数据面板必须要高性能,因为是要和业务服务部署在一起的。
可扩展。
可配置。具有动态配置的特性。

Envoy 是如何做到高性能的?

Envoy 的线程模型分为三类线程,如果做过C++开发,这种单进程多线程的架构是很常见的。Envoy 分为主线程、工作线程、文件刷新线程,其中主线程就是负责工作线程和文件刷新线程的管理和调度。而工作线程主要负责监听、过滤和转发,工作线程里面会包含一个监听器,如果收到一个请求之后会通过刚才所介绍的过滤链来进行数据过滤。前面两个都是非阻塞的,唯一一个阻塞的是这种 IO 操作的,会不断地把内存里面一些缓存进行落盘。

服务网格所强调的另外一个功能,是动态配置不用重启,实际上是重启的,它会启动一个新的进程,然后在这进程之上进行新的策略,还有一些初始化,这时候再请求监听,之前那个进程的 socket 副本。当老的关闭链接以及退出之后,它才会接收新的,这时候就实现了对用户没有感知的重要性。

这就是它的 xDS,如图,可以看到它的密度是非常细的,

终端发现服务(EDS),实际上就是服务的发现服务;

集群发现服务(CDS)是为了发现集群;

路由发现服务(RDS)是为了对路由进行一些处理;

监听器(LDS)来动态地添加、更新、删除监听器,包括过滤链的一些管理、维护。

另外还有刚才说到的健康检查(HDS),

还有聚合(ADS)是对于监控指标进行聚合的接口;

另外一个密钥发现(KDS)是和安全相关的。


首先,如果来了一个请求,会到刚才所说的工作线程里面去,工作线程会有监听器,收到之后进行一些处理,然后要往外发,这时会调用路由的发现功能,然后再找到相应的集群,再通过这个集群找到相应的服务,一层一层的往下面调用。



2控制面板Pilot

接下来介绍的是控制面板的三大组件,第一个就是 Pilot。

Pilot 是运行时的代理配置,刚才所说的 xDS,就是用 Pilot 来进行调用,负责把相应的一些策略,失败恢复的特性派发下去。Pilot 是负责管理所有的这些代理,代理和管理就通过 Pilot 来完成,是平台无关的一个拓扑模型。目前主要支持的是 K8S。

Pilot 是一层抽象的独立于底层平台的模型,因为这里有个代理,对于多平台或多样性的管理架构,即适配器的架构。平台特定的适配器负责适当填充这些规范,要通过具体平台的适配器形成一些规范,和通用的模型结合,生成必须要往 Envoy 下发的数据,并且配置、推送都是由 Pilot 来完成的。

Pilot 的整个服务发现和负载均衡,如图,Pilot 是Kubernetes DNS提供的域名进行访问,首先调用 Service B 的url,这时候 Envoy 会进行截获并处理,处理完之后会找到相应的负载均衡的池子挑选一个进行流量下发。Pilot 目前支持的这种负载均衡的方法,规划了很多种。但目前只实现了三种,前两种还是随机和轮循,多了一个最小请求的负载均衡算法。它能找到这些 Pilot 里面哪个被调用的最少,然后进行调用。


Pilot 的一些规则配置,可以看到基本是负责规则的管理以及下发。

路由规则。

目的地策略。主要包含负载均衡的算法,以及对于负载均衡算法抽象的策略预演。

出站规则。

把这些规则分了三类,好处是对这三类都会生成一些模板。

流量的拆分可以看到是基于标签的流量拆分,这里配置的如版本,环境,环境类型,它根据这个规则来进行流量的派发。比如说99%都发给之前版本,新版本先1%先测一下,类似于A/B测试。


另外一个比较高级的是基于内容,因为它是L7的这种过滤,可以基于内容来过滤,并且支持表达式,这种将iPhone的流量全部导到新的服务里面去,并且有标签,版本必须得是金丝雀版本。


3混合器Mixer

Mixer 是在应用代码和基础架构之间提供一个中间层,来隔离 Enovy 和后台基础设施,这里的后台是指 Promethus,ELK 这些。

Mixer 有三个核心特性:

先决条件检查。负责白名单以及 ACL检测;

配额管理。负责这种使用频率上的控制;

遥测报告。

总共分为两类,在生成配置模板的时候它是有两类的,第一类就是负责检查check,第二类就是负责报告reporter。


Mixer 是采用通用的插件模型以实现高扩展性,插件被称为适配器。运维人员下发一些配置到这里面,这些模板又是由模板开发人员进行开发的,Istio提供了很多通用性的模板,上面简单地改造一下就能做出一个模板来。适配器也有很多种,各种后台、平台的都有。

Mixer 是抽象了不同后端的策略,遥测系统的细节,它就对这两个东西进行了抽象,形成了一套抽象的东西。

刚才介绍过适配器,再来介绍一下处理器,它是配置好的适配器,由运维人员进行配置,之后形成最终的处理器,负责真正往后台发东西。

它封装了与后端接口所需的逻辑,指定了配置规格,以及适配器。如果要在后台进行消息交互的话,所需要的操作参数在这里也会定义。而右边就是两个模板,第一个模板是 Prometheus,它是一个处理器,下面是它的一些指标。另外一个是白名单检查的模板,提供URL,以及它请求的接口返回值。


刚才介绍了整个通路是怎么打通的,包括适配器和处理器都是为了干这个事情,这个通路怎么建立?接下来要介绍的是这个参数怎么生成,它是请求属性到一个模板的映射结果。

Mixer 会收到 Envoy 发过来的很多属性(请求),请求里面包含的数据都称之为属性。通过它的模板来生成相应的具体参数,这边也是刚才两个例子里面对应的模板。上面是度量指标采集用的,下面是白名单。


这里有个遥测报告的示例,当收到一个请求之后会发生什么。它会以属性的形式,这边有个 Zipk,就直接上报了,这是因为 Envoy 原生的就支持Zipk。Envoy 支持后端监控的东西,就是 Zipk,所以它可以直接发给它。其他的需要通过 Mixer 来进行转发。


首先它收到这个属性之后,会把这个属性生成具体的实例。根据运维人员提供的配置,Mixer 将生成的数据分发到一组适配器,适配器要根据运维人员的配置来生成具体的数据,之后就可以把刚才所生成的实例往下发了。发到后端后可以进行进一步的分析和处理。



4 密钥管理

最后要介绍的就是安全相关的,Certificate Authority 这块,这是整个密钥管理的示意图,可以看到服务和 Envoy 是通过 TCP 进行交互的,但是Envoy 和 Envoy 之间是通过 MTIS 进行加密,是双向的 TIS 加密。它的好处是,会在内部的每一个服务节点之间做加密,当然这是可选的,根据性能的需求来进行选择。


密钥管理分为四个步骤,这四步就是四个特性,第一,通过服务帐户生成的密钥和证书,然后再将密钥和证书部署到 Envoy上,它还支持周期性的对这证书进行更新,另外还支持撤销的功能。


这是它的两种部署方式,一种 K8S 的部署方式,另外如果是虚拟机,它会单独有一个节点代理,通过节点代理来发出签名请求给CA,CA再生成密钥和证书给代理,代理再来负责部署到 Envoy上。


具体的运行时它们都有各自的证书,开始进行双向的 TIS,这时候会到名字信息里面去查询,后端有没有权限访问,如果有的话就往下,没有就结束了。


第三步,如果收到一个客户端的请求,会去 Mixer 里面判断一下,它是白名单上的一个判断或者是不是黑名单上的一个判断,会影响“握手”的成功与否。最终它们就形成了安全交互的通道。


谢谢大家,今天我们主要给大家介绍一下 Istio 是什么,大家有初步的认识,并且对它里面比较关键的技术进行了介绍。




六、Q&A

Q1:现在有这么个项目,您怎么看像这种项目的发展?第二个问题,你们中心现在在做,您也分析的挺深入,未来是什么计划,会和pass有融合吗?


A1:先回答第一个问题,我们可以看到不管是数据面板还是控制面板都会有很多个,但是控制面板,谷歌和IBM,刚才所说的是由三个公司来开发的,谷歌、IBM,还有Lyft,那个公司类似于滴滴那种业务的公司,它们负责Envoy的开发,数据面板是它们公司来负责。我们可以看出来它们是有点分离的感觉,对于谷歌或者IBM来说它们更关注的是控制面板,并且在控制面板和数据面板之间的接口设计的非常好,设计了一套通用的接口。它们最终是分为两个方向发展,但是都可以通过同一套标准集成起来。

第二个问题,首先公司内部都在采用微服务,对于Istio至少要到1.0之后才会在内部环境使用,如果没问题才会逐渐往真正的对外业务使用它,包含通讯里面都可能会用它。但是对于CT领域来说的话,用这个可能代价就需要好好地评估一下了。因为性能上的问题,它毕竟还是多了一跳。如果两个服务之间的交互就相当于多了两跳,对于通信这种实时性要求非常高的领域可能会存在问题。我们也会开发自己的一套侵入式框架,可以参考Envoy的实现。


Q2:我们现在游戏项目里面刚好也用到它。但是它有个问题,用的感觉有点大材小用,我们用它做调用链关系分析,因为我们集群开发很多游戏,每个游戏有个pilot,但是如果出了问题我不知道,那它里面的一个插片自动生成,它只能识别K8集群里面pod。如果我们想用它把K8S的集群和非K8S的集群调用,并且全部进行连接起来的话,它是否支持?

A2:我觉得它现在由于所处在初级阶段所以暂时不支持是正常的,但它后续的发展肯定会支持,因为它们整个设计的目标就是为了达到这种服务粒度,而不仅限于K8S pod这种管理粒度。



Q3:我有一个关于sidecar的问题,如果作为一个客户端去请求的时候应该要引流引到sidecar上面,它引流是怎么引的?如果直接转过去的话又怎么去识别目标的服务到底是什么样的?它调用的是什么服务,后端可以路由到几个上?

A3:这个信息都是由刚才所说的pilot来负责收集,它会把这些信息下发到Envoy上,所以它在做路由算法的时候会访问,来获取它可以访问到哪些服务,它会把服务的信息找到,包括它能访问的服务池包含哪些内容,然后再通过策略进行控制。

它是会反向再去K8S里面找到的,并不是完全Envoy自己来负责,这些信息都是由pilot来给它,拿到这些信息再做处理,最终还是会和平台结合到一起。它有一个假设,所有的平台都会实现这种服务发现的接口,并且会从服务发现的接口拿到一些必要的信息,包含你刚才说的,会转成相应的IP。

关注公众号,后台回复127即可下载PPT

推荐阅读:
微服务迁移前,来听听这6个思考和经验
这款分布式配置中心,会是微服务的降维大机利器吗?
docker + kubernetes=共生?相爱相杀?
 
  查看全部
2018年1月27日,数人云Meetup 联合vivo在深圳举办 Building Microservice 系列活动第1期。本次技术沙龙vivo、中兴通讯、华为、数人云共同派出技术大咖,为开发者们带来有关微服务、容器化、配置中心、服务网格等领域的实战与干货分享。


近几年我一直从事于微服务系统的设计以及实现方面的工作,属于微服务架构一线实践者。之前做过一些单体系统的微服务改造,在微服务拆分、治理等方面都有一定的经验。本人比较特殊一点的经历是既做过 IT 领域的微服务,也做过 CT(通讯领域)的微服务,微服务架构在这两个领域的具体形态和要求是不太一样的,但其中一些思想是互通且是很有借鉴意义的。今天主要介绍一下关于微服务的最新发展动态,以及最近谷歌推出的 Istio平台架构。

今天介绍的主题包含:服务治理、服务网格、Istio架构,以及 Istio 相应的系统组成。



一、分布式计算的八个谬论


彼得多维奇多年前提出的分布式计算的八个谬论,对于开发人员来说他们往往会忽视这八条。这八条基本上都和网络相关,例如在发起一个网络请求时,会不断地做一些尝试等待,来保障消息投递的有效性。


微服务是一个更为复杂的分布式系统,之前 SOA 或者B/S,CS 架构,它的颗粒度会更粗一点,但是如果采用微服务,它的颗粒度是更细的。在马丁·富勒博客《微服务的先决条件是什么》一文中提到一条,你必须要成为“高个子”,想成为“高个子”其实并不简单,很多公司,它们都是为了成为“高个子”,做了很多框架、平台。


二、服务治理

1 微服务治理的技术点

要成为“高个子”需要对微服务进行哪些改造,这里是相关服务治理的技术点,其中只是一部分,和服务网格比较相关的技术点,包含服务发现、负载均衡、请求路由、认证与授权、可观测性,还有健康检查、容错等。目前主流的解决方案有众所周知的 Spring Cloud, Dubbo 等,这些都是提供库来把服务治理相关的内容打包,供具体的业务去调用。



2 库或框架的问题

但是库和框架会存在一些问题:


 1、学习成本。多一个库对于开发人员而言,意味着要多学一些东西,并且在业务开发过程中,还会受到库或者框架的制约。


2、对业务代码的侵入性。例如用 Spring Cloud 会在代码里面加很多额外的内容,比如每个请求里面加一个注解来表达想引用服务治理的某些功能。


3、基础库的维护、升级和下线。如果是以库的方式来提升到服务里面,库的维护、升级、下线就会造成整个服务的维护、升级、下线。


4、不同语言和技术栈。在提出微服务概念时,它的一个重要好处就是可以使用不同的技术栈来开发微服务,但如果受到框架制约,只能用这个语言,这是我们比较头痛的事情,无法发挥微服务跨语言的能力。


这些问题其实是有严重程度的,从上往下越来越让开发人员觉得不舒服。理想中的服务治理方案是什么?可以先畅想一下,整个服务治理相关的东西,应该是和业务逻辑完全隔离的,并且服务和服务之间的交互是不会考虑服务治理这块内容,最好对于业务开发来说是不可见的。


这时候怎么去做呢?就引出了容器经典部署模式——Sidecar。


3 Sidecar模式

Sidecar 模式通常是和容器一起使用,如果不和容器一起使用也没关系,那就是两个独立的进程,如果和容器使用的话,就基于容器为单位。Sidecar模式是物理隔离的,并且与语言无关。因为是两个独立的东西,可以独立发布,和微服务理念一样。另外它们是部署在同一个 Host 上面,所以资源之间可以做到相互访问,并且因为在一起所以通信延迟也不会太明显。和业务无关的功能都可以放上去,形成多个 Sidecar。今天 Sidecar 主要是把一些服务治理相关的东西放在里面,做软件设计上的思想就是分离关注点。


基于 Sidecar 模式做服务治理,之后形成连接的具体状况,如图,对于服务A来说,服务A是不知道和 Sidecar 进行通信,服务A还是向服务B发消息,照常调用通信接口,但是消息可能会被 Sidecar 捕获到,然后通过Sidecar 进行转发。


三、服务网格

从整个系统来看,如果以 Sidecar 方式来部署服务治理以及服务的话,最终形成的系统如图。能看到通过 Sidecar 进行相互连接,形成一个网络,这也是服务网格名字的由来。每一个节点上面都相当于具体的网格,和多年之前提的网格计算有点类似。


服务网格如果站在更抽象的层次来看是什么样子?把服务治理相关的东西抽象来看的话,服务网格也算是一种基础设施,它和具体的业务无关。不管是 PaaS 的发展,还是服务网格的发展,都是将与业务无关的内容的共同点提取出来,然后形成独立的一套平台或者方案。另外,服务网格之间要形成可靠传递,刚才提到的重试等功能都应该具备。


服务网格是轻量级的网络代理,不能太重,不能喧兵夺主,服务才是整个系统中最重要的东西,而这些基础设施并不应该取代服务最重要的价值地位。

更关键的一点是要对应用程序透明。对于服务而言是看不到 Sidecar、看不到代理的,服务如果要发消息出去,它知道是发给这个代理的,那对于我们的业务来说同样也是一种污染。服务网格最终不再强调代理作为单独的组件,不再孤立的来看代理,而是从全局的角度来看待代理所形成的网络。



1 服务网格定义

服务网格的定义是 Willian Morgan 提出来的,他是最早做服务网格的人。如图,文字加粗的是服务网格一些关键技术点。右边图是最新发展的服务网格,在最上层还会加一个控制面板,通过控制面板来管理这些代理,这些代理是需要被管理的。如果我们的运维环境没有控制面板,可能就没办法运维了。



2 服务网格的基本构成

服务网格必须要具备数据面板和控制面板,如果新开发一个服务网格只有数据面板,它肯定不是一个完整的服务网格。

数据面板是用来接收系统中的每一个包或者请求,提供服务发现、健康检查等服务治理相关的,都是由数据面板来完成。数据面板的一些典型代表有 Linked、Envoy、和 Nginx 公司开发的 Nginmesh,以及硬件服务的代理厂商F5开发的 Aspen Mesh。目前主要的、成熟的是 Linked 和 Envoy,这两者都在生产环境上面真实部署过,实战过。而且Linked的采用会更广泛一些,因为它出现的时间最早。


对于控制面板来说,是为了在网格中运营的数据面板提供策略和配置,负责一些管理工作,它不会接收系统中的任何包或者请求。这里的包和请求应该是业务相关的包和请求,和具体的业务是完全没关系的。本来做微服务应该做去中心化的事情,但是又有一个控制点在那里,要强调的是那个控制点和具体的业务没什么关系。控制面板的典型代表,包括 Istio、Conduit、Nleson、SmartStack,目前最新的是 Istio 和 Conduit。


3 数据面板对比

左边是 Linked(Scala编写),右边是 Envoy(C++编写),它们最大的区别就是实现语言的区别。同时,Linkerd 和 Envoy 都是在生产环境已经验证过的两个系统,功能上都没问题,都比较强大,它们唯一的区别就是对于硬件资源的要求,Linked 是非常高的,它可能就会造成喧兵夺主的感觉,所以目前 Envoy 在这块是比较火的,Envoy 是由C++开发的。



4 控制面板对比

两个最新的控制面板,一个是 Istio,是由 Google、IBM、Lyft 开发的,而 Conduit 是由 Buoyant 公司开发的,跟刚才所说的性能不太好的数据面板Linkerd是同一家公司,Buoyant 在 Linkerd 之后又重新开发了 Conduit,专门来解决性能上的问题,所以在性能上面来看,Conduit 的性能指标已经出来了,就是微秒级,并且是P99延迟。但是 Istio 的性能指标现在还没出来,还在功能开发阶段。因为 Istio需要实现的功能比较多,要支持各种各样的平台和过滤,Istio 整个架构非常灵活,所以 Istio 整个量级是比较重量的,但是 Conduit 只支持 K8S,Conduit 的原则是怎么快怎么来。



从编程语言上来说,控制面板 Istio 和 Conduit 都是使用Go语言,但是在数据面板上 Istio 是使用C++,Conduit 使用 Rust,可以看出来这两个语言都是那种比较高效的,在数据面板上面必须要使用高效的语言来完成。


四、Istio架构

一句话定义 Istio:一个用来连接、管理和保护微服务的开放平台。刚才也说了 Istio 是 Google 开发的,所以 Istio 今后的趋势肯定是会越来越火的,并且目前 K8S 已经把它集成到里面了,做成一个可选的组件。

对于连接而言,Istio 它主要包含弹性、服务发现、负载均衡,管理是流量控制、策略增强,监控也有,并且安全这块 Istio 也是有考虑,Istio 是端到端的身份验证和授权,等一下会详细的介绍。


Istio的关键特性:

1、智能路由和负载均衡。这里的智能路由和负载均衡是属于比较高级的,不是像传统简单的随机负载均衡,而是可以基于一些数据包内部的内容来进行负载均衡。

2、跨语言和平台的弹性。对于平台来说 Istio 是支持各种各样的平台,并且能支持A/B测试,金丝雀发布,并使用蓝绿部署运维上的一些高级功能。

3、全面策略执行。Istio 有一个组件是专门负责保障策略能够通过一个组件下发到具体的数据面板。

4、遥测和上报。即具体的测量以及流量的监控等。

这个就是 Istio 整个的系统架构,如图,上面是控制面板,下面是很多数据 Envoy,很多个代理,形成一个数据面板。后面我们会对单个进行详细介绍。

这是在 K8S 下面 Istio 部署的示意图,可以看到它们之间最关键的东西是所有服务和组件都会有一个代理,这代理是必备的,包括控制面板都会有代理。没有画的有两个东西,一个是 Ingress,一个是初始化器,初始化器主要是做代理注入。它们之间相互的交互都是通过加密,由TLS协议来完成。


五、Istio组件

1 数据面板Envoy

介绍一下 Istio 的核心组件,首先是 Istio 的数据面板 Envoy。

Envoy 的目标是透明地处理集群内服务间、从服务到外部服务之间的出入口流量。Envoy 是用C++编写的,高并行、非阻塞。并且是可装卸的L3/4过滤器,以及L7的过滤器,最终会形成一个过滤链来对流量进行管理或者控制,Envoy 是通过 xDS 动态配置来进行接口提供。

下面就是一些固有的功能,服务发现、健康检查。Envoy 的健康检查也做的颗粒度比较细,包含主动健康检查和被动健康检查。主动健康检查像常规的健康检查,主动地发一个健康检查的接口调用请求,查询一下。被动的是通过对其他服务的一些请求,从一些返回值进行健康检查。当然还包含高级的负载均衡,监控、跟踪这些功能。


Envoy最关键的三个点:

高性能。一直在强调的是数据面板必须要高性能,因为是要和业务服务部署在一起的。
可扩展。
可配置。具有动态配置的特性。

Envoy 是如何做到高性能的?

Envoy 的线程模型分为三类线程,如果做过C++开发,这种单进程多线程的架构是很常见的。Envoy 分为主线程、工作线程、文件刷新线程,其中主线程就是负责工作线程和文件刷新线程的管理和调度。而工作线程主要负责监听、过滤和转发,工作线程里面会包含一个监听器,如果收到一个请求之后会通过刚才所介绍的过滤链来进行数据过滤。前面两个都是非阻塞的,唯一一个阻塞的是这种 IO 操作的,会不断地把内存里面一些缓存进行落盘。

服务网格所强调的另外一个功能,是动态配置不用重启,实际上是重启的,它会启动一个新的进程,然后在这进程之上进行新的策略,还有一些初始化,这时候再请求监听,之前那个进程的 socket 副本。当老的关闭链接以及退出之后,它才会接收新的,这时候就实现了对用户没有感知的重要性。

这就是它的 xDS,如图,可以看到它的密度是非常细的,

终端发现服务(EDS),实际上就是服务的发现服务;

集群发现服务(CDS)是为了发现集群;

路由发现服务(RDS)是为了对路由进行一些处理;

监听器(LDS)来动态地添加、更新、删除监听器,包括过滤链的一些管理、维护。

另外还有刚才说到的健康检查(HDS),

还有聚合(ADS)是对于监控指标进行聚合的接口;

另外一个密钥发现(KDS)是和安全相关的。


首先,如果来了一个请求,会到刚才所说的工作线程里面去,工作线程会有监听器,收到之后进行一些处理,然后要往外发,这时会调用路由的发现功能,然后再找到相应的集群,再通过这个集群找到相应的服务,一层一层的往下面调用。



2控制面板Pilot

接下来介绍的是控制面板的三大组件,第一个就是 Pilot。

Pilot 是运行时的代理配置,刚才所说的 xDS,就是用 Pilot 来进行调用,负责把相应的一些策略,失败恢复的特性派发下去。Pilot 是负责管理所有的这些代理,代理和管理就通过 Pilot 来完成,是平台无关的一个拓扑模型。目前主要支持的是 K8S。

Pilot 是一层抽象的独立于底层平台的模型,因为这里有个代理,对于多平台或多样性的管理架构,即适配器的架构。平台特定的适配器负责适当填充这些规范,要通过具体平台的适配器形成一些规范,和通用的模型结合,生成必须要往 Envoy 下发的数据,并且配置、推送都是由 Pilot 来完成的。

Pilot 的整个服务发现和负载均衡,如图,Pilot 是Kubernetes DNS提供的域名进行访问,首先调用 Service B 的url,这时候 Envoy 会进行截获并处理,处理完之后会找到相应的负载均衡的池子挑选一个进行流量下发。Pilot 目前支持的这种负载均衡的方法,规划了很多种。但目前只实现了三种,前两种还是随机和轮循,多了一个最小请求的负载均衡算法。它能找到这些 Pilot 里面哪个被调用的最少,然后进行调用。


Pilot 的一些规则配置,可以看到基本是负责规则的管理以及下发。

路由规则。

目的地策略。主要包含负载均衡的算法,以及对于负载均衡算法抽象的策略预演。

出站规则。

把这些规则分了三类,好处是对这三类都会生成一些模板。

流量的拆分可以看到是基于标签的流量拆分,这里配置的如版本,环境,环境类型,它根据这个规则来进行流量的派发。比如说99%都发给之前版本,新版本先1%先测一下,类似于A/B测试。


另外一个比较高级的是基于内容,因为它是L7的这种过滤,可以基于内容来过滤,并且支持表达式,这种将iPhone的流量全部导到新的服务里面去,并且有标签,版本必须得是金丝雀版本。


3混合器Mixer

Mixer 是在应用代码和基础架构之间提供一个中间层,来隔离 Enovy 和后台基础设施,这里的后台是指 Promethus,ELK 这些。

Mixer 有三个核心特性:

先决条件检查。负责白名单以及 ACL检测;

配额管理。负责这种使用频率上的控制;

遥测报告。

总共分为两类,在生成配置模板的时候它是有两类的,第一类就是负责检查check,第二类就是负责报告reporter。


Mixer 是采用通用的插件模型以实现高扩展性,插件被称为适配器。运维人员下发一些配置到这里面,这些模板又是由模板开发人员进行开发的,Istio提供了很多通用性的模板,上面简单地改造一下就能做出一个模板来。适配器也有很多种,各种后台、平台的都有。

Mixer 是抽象了不同后端的策略,遥测系统的细节,它就对这两个东西进行了抽象,形成了一套抽象的东西。

刚才介绍过适配器,再来介绍一下处理器,它是配置好的适配器,由运维人员进行配置,之后形成最终的处理器,负责真正往后台发东西。

它封装了与后端接口所需的逻辑,指定了配置规格,以及适配器。如果要在后台进行消息交互的话,所需要的操作参数在这里也会定义。而右边就是两个模板,第一个模板是 Prometheus,它是一个处理器,下面是它的一些指标。另外一个是白名单检查的模板,提供URL,以及它请求的接口返回值。


刚才介绍了整个通路是怎么打通的,包括适配器和处理器都是为了干这个事情,这个通路怎么建立?接下来要介绍的是这个参数怎么生成,它是请求属性到一个模板的映射结果。

Mixer 会收到 Envoy 发过来的很多属性(请求),请求里面包含的数据都称之为属性。通过它的模板来生成相应的具体参数,这边也是刚才两个例子里面对应的模板。上面是度量指标采集用的,下面是白名单。


这里有个遥测报告的示例,当收到一个请求之后会发生什么。它会以属性的形式,这边有个 Zipk,就直接上报了,这是因为 Envoy 原生的就支持Zipk。Envoy 支持后端监控的东西,就是 Zipk,所以它可以直接发给它。其他的需要通过 Mixer 来进行转发。


首先它收到这个属性之后,会把这个属性生成具体的实例。根据运维人员提供的配置,Mixer 将生成的数据分发到一组适配器,适配器要根据运维人员的配置来生成具体的数据,之后就可以把刚才所生成的实例往下发了。发到后端后可以进行进一步的分析和处理。



4 密钥管理

最后要介绍的就是安全相关的,Certificate Authority 这块,这是整个密钥管理的示意图,可以看到服务和 Envoy 是通过 TCP 进行交互的,但是Envoy 和 Envoy 之间是通过 MTIS 进行加密,是双向的 TIS 加密。它的好处是,会在内部的每一个服务节点之间做加密,当然这是可选的,根据性能的需求来进行选择。


密钥管理分为四个步骤,这四步就是四个特性,第一,通过服务帐户生成的密钥和证书,然后再将密钥和证书部署到 Envoy上,它还支持周期性的对这证书进行更新,另外还支持撤销的功能。


这是它的两种部署方式,一种 K8S 的部署方式,另外如果是虚拟机,它会单独有一个节点代理,通过节点代理来发出签名请求给CA,CA再生成密钥和证书给代理,代理再来负责部署到 Envoy上。


具体的运行时它们都有各自的证书,开始进行双向的 TIS,这时候会到名字信息里面去查询,后端有没有权限访问,如果有的话就往下,没有就结束了。


第三步,如果收到一个客户端的请求,会去 Mixer 里面判断一下,它是白名单上的一个判断或者是不是黑名单上的一个判断,会影响“握手”的成功与否。最终它们就形成了安全交互的通道。


谢谢大家,今天我们主要给大家介绍一下 Istio 是什么,大家有初步的认识,并且对它里面比较关键的技术进行了介绍。




六、Q&A

Q1:现在有这么个项目,您怎么看像这种项目的发展?第二个问题,你们中心现在在做,您也分析的挺深入,未来是什么计划,会和pass有融合吗?


A1:先回答第一个问题,我们可以看到不管是数据面板还是控制面板都会有很多个,但是控制面板,谷歌和IBM,刚才所说的是由三个公司来开发的,谷歌、IBM,还有Lyft,那个公司类似于滴滴那种业务的公司,它们负责Envoy的开发,数据面板是它们公司来负责。我们可以看出来它们是有点分离的感觉,对于谷歌或者IBM来说它们更关注的是控制面板,并且在控制面板和数据面板之间的接口设计的非常好,设计了一套通用的接口。它们最终是分为两个方向发展,但是都可以通过同一套标准集成起来。

第二个问题,首先公司内部都在采用微服务,对于Istio至少要到1.0之后才会在内部环境使用,如果没问题才会逐渐往真正的对外业务使用它,包含通讯里面都可能会用它。但是对于CT领域来说的话,用这个可能代价就需要好好地评估一下了。因为性能上的问题,它毕竟还是多了一跳。如果两个服务之间的交互就相当于多了两跳,对于通信这种实时性要求非常高的领域可能会存在问题。我们也会开发自己的一套侵入式框架,可以参考Envoy的实现。


Q2:我们现在游戏项目里面刚好也用到它。但是它有个问题,用的感觉有点大材小用,我们用它做调用链关系分析,因为我们集群开发很多游戏,每个游戏有个pilot,但是如果出了问题我不知道,那它里面的一个插片自动生成,它只能识别K8集群里面pod。如果我们想用它把K8S的集群和非K8S的集群调用,并且全部进行连接起来的话,它是否支持?

A2:我觉得它现在由于所处在初级阶段所以暂时不支持是正常的,但它后续的发展肯定会支持,因为它们整个设计的目标就是为了达到这种服务粒度,而不仅限于K8S pod这种管理粒度。



Q3:我有一个关于sidecar的问题,如果作为一个客户端去请求的时候应该要引流引到sidecar上面,它引流是怎么引的?如果直接转过去的话又怎么去识别目标的服务到底是什么样的?它调用的是什么服务,后端可以路由到几个上?

A3:这个信息都是由刚才所说的pilot来负责收集,它会把这些信息下发到Envoy上,所以它在做路由算法的时候会访问,来获取它可以访问到哪些服务,它会把服务的信息找到,包括它能访问的服务池包含哪些内容,然后再通过策略进行控制。

它是会反向再去K8S里面找到的,并不是完全Envoy自己来负责,这些信息都是由pilot来给它,拿到这些信息再做处理,最终还是会和平台结合到一起。它有一个假设,所有的平台都会实现这种服务发现的接口,并且会从服务发现的接口拿到一些必要的信息,包含你刚才说的,会转成相应的IP。

关注公众号,后台回复127即可下载PPT

推荐阅读:
微服务迁移前,来听听这6个思考和经验
这款分布式配置中心,会是微服务的降维大机利器吗?
docker + kubernetes=共生?相爱相杀?
 
 

Envoy Proxy和Netflix Hystrix,究竟谁才是熔断王者?

Envoy小数 发表了文章 • 0 个评论 • 1340 次浏览 • 2018-02-01 11:22 • 来自相关话题

 
 
 本文已获得 Christian Posta 授权,转载须获得许可。


作者:Christian Posta  

翻译:崔秀龙@HPE

原文:Comparing Envoy and Istio Circuit Breaking With Netflix OSS Hystrix



当我们构建服务架构时(面向服务的架构,微服务,以及其他的东西),我们都要在网络上执行大量的调用。网络的脆弱是众所周知的,因此我们希望服务有一定的冗余,以便在系统故障期间能够保持服务能力。这一拼图中的重要一块就是智能的、通晓应用情况的负载均衡器。Matt Klein(注 1) 最近撰写了一篇关于现代负载均衡的大作(注 2),如果还没读过,建议读者首先阅读一下。


在构建大型、可靠的分布式系统尤其是在云端的微服务应用时,断路器(注 3)是一个重要的组件。有了这一组件,我们可以在系统发生持续故障的时候进行短路操作。断路器本身也是智能、应用感知的负载均衡器的组成部分。很多人都在或多或少的使用负载均衡。我们来看看 Netflix Hystrix(注 4)和 Envoy Proxy(注 5) 之间的差异。



熔断

断路(开路)的价值在于限制故障影响范围。我们希望控制、减少或或中断和故障系统之间的通信,从而降低故障系统的负载,有利于系统的恢复。例如有一个搜索服务,通过调用推荐服务来提供个性化的搜索结果;但是过程中发现推荐服务在很多不同调用中都返回了错误,所以我们可能应该停止调用一段时间。也许我们越是尝试就越会给系统造成压力,会造成情况的进一步恶化。经过考量,我们决定停止对这一服务的调用。这一方式和我们住宅中电气线路的熔断机制类似。如果出现故障,就应该断开故障部分,保护系统的其他部分。断路器模式强制我们的应用来正视网络问题——网络调用是可能、而且真的会出故障的,从而防止系统出现雪崩。这一技术的关键就是感知系统组件的健康并判断是否应该向某组件发送流量。



Netflix OSS Hystrix

Netflix OSS(注 6)在 2012 年发布了了一个断路器组件(注 7),称为 Hystrix(注 8)。Hystrix 是一个用于提供熔断能力的客户端 Java 库。Hystrix提供了这样一些特性(注 7)](https://medium.com/netflix-tec ... 159c2d)。

来自“Making the Netflix API more resilient(注 7)”:
自定义回落操作:在一些情况下,服务客户端库提供了一个回落方法供调用,或者其他情况下,我们可以使用本地的数据来生成回应。故障抑制:在这种情况下,回落方法简单的返回一个 null 值,如果这一服务返回的数据是可选项目,这种方式会很有帮助。快速失败:当目标服务的返回数据是必须的情况下,上面两种方法无法解决这一问题的,只能返回一个5xx响应。这对用户感知是很不好的,但是这一手段能能够保障服务器的健康,让系统能够更快的将失效服务进行修


可以用多种方式触发断路器(注 7)。

对远程服务的请求发生超时。

用于一个服务的线程池或任务队列容量满载

用于调用服务的客户端库抛出异常。


Hystrix 熔断过程:

Netflix Hystrix 允许对网络交互进行非常细致的控制(注 9)。Hystrix 允许根据调用类型,对依赖服务进行精细的配置。假设我们对推荐引擎的调用绝大多数情况是只读的,那么断路器的配置就可以比较放松。


另外一个重要的事实是,Hystrix 的目的是及时断路,因此他把故障看做和超时是一致的。超时的故障点也可能处于客户一侧。Hystrix 对断路门槛的设置,并不区分故障究竟是服务端还是客户端的责任。


另外呼应前文:断路器真的只是智能、应用感知负载均衡技术的特性之一。在这种情况下“应用感知”的含义是:他的库在你的应用中运行。在 Netflix 生态系统中,还可以把 Hystrix 和 Netflix OSS Ribbon(注 10)这样的客户端负载均衡进行配对使用。



Service Mesh 的发展

服务架构持续向多样化方向演进,我们发现强制服务使用特定的库、框架或者语言是很难或者不实际的。随着 Service Mesh 走进视野,我们看到熔断能力有了独立于语言、框架的基础设施级的解决方案。Service Mesh 可以定义为:


一个处于服务之间的,去中心化的应用级网络基础设施,提供安全、弹性、监控和路由控制能力。

Service Mesh 可以使用不同的 L7(应用级)代理来扮演数据面角色,用于提供重试、超时、断路器等能力。本文中我们会看看 Envoy Proxy(注 10) 是如何完成熔断任务的。Envoy Proxy 是 Istio Service Mesh(注 11)的缺省的、开箱即用的代理,所以这里描述的特性同样也适用于 Istio。



Envoy Proxy / Istio Service Mesh

Envoy Proxy 将断路功能作为负载均衡和健康检查的一个子集。Envoy 将路由选择(选择进行通信的集群)的功能和通信功能(和确定的后端)分而治之。相对于其他粗粒度配置的负载均衡器,这一设计让 Envoy 与众不同。Envoy 可以有很多不同的“路由”尝试把流量发送给合适的后端。这些后端被称为cluster,每个cluster都可以有自己的负载均衡配置。每个cluster还可以有自己的被动健康检查(外部检测)配置。Envoy 有几个配置项用于熔断功能,这里可以逐个介绍一下。


这里定义一个外部cluster:


"clusters": [  {    "name": "httpbin_service",    "connect_timeout_ms": 5000,    "type": "static",    "lb_type": "round_robin",    "hosts": [      {        "url": "tcp://172.17.0.2:8080"      },{        "url": "tcp://172.17.0.3:8080"      }    ],


这里我们会看到,这里有一个叫httpbin_service的集群,使用round_robin的策略在两个主机之间进行负载均衡。接下来加入 Envoy 断路器配置(注 11)。




断路器


   "circuit_breakers": {      "default": {        "max_connections": 1,        "max_pending_requests": 1,        "max_retries": 3      }


这里我们目标是 HTTP 1.x 的负载。我们限制外来连接为 1,最大排队请求也是 1。另外还定义了最大重试次数。某种意义上,限制连接池以及请求数量的做法和 bulkhead(注 12) 以及 Netflix Hystrix 是类似的。如果客户端应用打开了超过限制的连接数量(这是一种软限制,有一定误差),我们会看到 Envoy 断掉多出的连接(注 13),并在统计报告中进行记录。


外部检测

上面我们看到,Envoy 所谓的熔断功能实际上更像是连接池控制。要完成这一功能,Envoy 做了一些称为outlier detection(注 14)。Envoy 持续对负载均衡池中的不同端点的操作进行统计。如果发现了超标行为,就把端点从负载均衡池中移除。我们可以看一下这一部分的配置代码:


   "outlier_detection" : {      "consecutive_5xx": 1,      "max_ejection_percent": 100,      "interval_ms": 1000,      "base_ejection_time_ms": 60000    }


这一配置的含义是:通信过程中,“如果发生了一次 5xx”错误,我们应该把这一主机标记为不健康,将其从负载均衡池中移除。我们还配置max_ejection_percent为100,也就是说,在发生这一情况时,我们愿意逐出所有端点。这一设置跟环境紧密相关,因此配置内容应该因地制宜,谨慎从事。我们希望尽可能的路由到一个主机,这样我们就不必冒着部分或级联故障的风险了。Envoy 缺省设置max_ejection_percent为10。

我们还设置逐出的时间基数为6000毫秒。一个主机被逐出负载均衡池的真实时间,由这一基数乘以被逐出时间得来,这样就可以对稳定性较差的主机实行更久的隔离。



集群恐慌

Envoy 外部检测和负载均衡功能中还有一点我们要知道的。如果太多的主机被这一过程逐出,就会进入集群恐慌模式(注 15),这种情况下,代理服务器会无视负载均衡池的健康标记,重新向所有主机发送数据。这是一个非常棒的机制。在分布式系统中,必须了解到的一点是,有时候“理论上”的东西可能不是正常情况,最好能降低一点要求来防止扩大故障影响。另外一方面,可以对这一比例进行控制(缺省情况下超过 50% 的驱逐就会进入恐慌状态),可以提高,也可以禁止这一阈值。设置为0之后,他的熔断行为就和 Netflix Hystrix 类似了。



可微调的熔断策略

库方式有个好处就是应用感知的可微调的熔断策略。Hystrix 文档中演示了针对同一集群的查询、读取、写入的不同调用,Hystrix FAQ 中说到:



通常情况下,一组负载均衡集群形成的单一网络路由会使用很多不同的 HystrixCommands 服务于很多不同类型的功能。

每个 HystrixCommands 都需要设置不同的吞吐限制、超时以及回落策略。

在 Envoy 中,我们能够通过路由匹配功能(注 16)获得同样的精确的熔断策略,这一功能和集群策略(注 17)结合,就可以指定在什么集群上进行什么操作了。



Istio 断路器

我们可以使用 Istio 的高级配置,来提供断路器能力。在 Istio 中,我们使用 目标策略(注 17)来配置负载均衡和断路器策略。下面是一个目标策略的例子,其中进行了断路器的设置:

metadata:  name: reviews-cb-policy  namespace: defaultspec:  destination:    name: reviews    labels:      version: v1  circuitBreaker:    simpleCb:      maxConnections: 100      httpMaxRequests: 1000      httpMaxRequestsPerConnection: 10      httpConsecutiveErrors: 7      sleepWindow: 15m      httpDetectionInterval: 5m


熔断之后怎么办?

达到熔断标准的时候,会发生什么事情?Hystrix 中的回落策略是包含在库中并且能够进行编排的。Hystrix 让我们可以做一些后续操作,例如返回缓存值、返回缺省值甚至去调用其他服务。我们还可以获得清晰的关于故障的信息,并作出应用相关的决策。


在 Service Mesh 之中,因为没有内置库的支持,故障原因会比较隐蔽。这并不意味着我们的应用就不能有回落操作了(不管是传输还是客户端错误)。我认为对任何应用来说,不论他用的是不是特定库的框架,都会要尝试完成对客户的承诺。如果无法完成预定动作,就应该有一种优雅的降级方法。幸运的是,这种操作也不是非框架不可。多数语言都有内置的错误和异常处理能力,回落策略可以在异常处理过程中完成。


回放

熔断能力是负载均衡的功能之一。

Hystrix 只提供了熔断能力,负载均衡要配合 Ribbon(或者其他客户端负载均衡库)完成。

Hystrix 以客户端库的形式提供了回落能力,非常强大。

Envoy 的负载均衡实现中包含了外部检测和断路器的功能。

Envoy 的熔断更像 Hystrix Bulkhead ,外部检测更像 Hystrix 断路器。

Envoy 具有很多缺省的久经考验的功能,例如集群恐慌。

Service Mesh 缺少故障回落的能力,只能让应用来完成这一任务。


点击阅读原文即可阅读更多Christian Posta文章~

Contact with Christian Posta@https://twitter.com/christianposta






1.https://twitter.com/mattklein123

2.https://blog.envoyproxy.io/int ... 80236

3.https://martinfowler.com/bliki/CircuitBreaker.html

4.https://github.com/Netflix/Hystrix

5.https://www.envoyproxy.io/

6.https://netflix.github.io

7.https://medium.com/netflix-tec ... ab362

8.https://github.com/Netflix/Hystrix

9.https://github.com/Netflix/Hys ... calls

10.https://www.envoyproxy.io/

11.https://www.envoyproxy.io/docs ... aking

12.https://developers.redhat.com/ ... ation

13.http://blog.christianposta.com ... king/

14.https://www.envoyproxy.io/docs ... tlier

15.https://www.envoyproxy.io/docs ... 3core

16.https://www.envoyproxy.io/docs ... uster


推荐阅读:
微服务迁移前,来听听这6个思考和经验
这款分布式配置中心,会是微服务的降维大机利器吗?
docker + kubernetes=共生?相爱相杀?
  查看全部

微信图片_20180131185805.jpg

 
 
 本文已获得 Christian Posta 授权,转载须获得许可。


作者:Christian Posta  

翻译:崔秀龙@HPE

原文:Comparing Envoy and Istio Circuit Breaking With Netflix OSS Hystrix



当我们构建服务架构时(面向服务的架构,微服务,以及其他的东西),我们都要在网络上执行大量的调用。网络的脆弱是众所周知的,因此我们希望服务有一定的冗余,以便在系统故障期间能够保持服务能力。这一拼图中的重要一块就是智能的、通晓应用情况的负载均衡器。Matt Klein(注 1) 最近撰写了一篇关于现代负载均衡的大作(注 2),如果还没读过,建议读者首先阅读一下。


在构建大型、可靠的分布式系统尤其是在云端的微服务应用时,断路器(注 3)是一个重要的组件。有了这一组件,我们可以在系统发生持续故障的时候进行短路操作。断路器本身也是智能、应用感知的负载均衡器的组成部分。很多人都在或多或少的使用负载均衡。我们来看看 Netflix Hystrix(注 4)和 Envoy Proxy(注 5) 之间的差异。



熔断

断路(开路)的价值在于限制故障影响范围。我们希望控制、减少或或中断和故障系统之间的通信,从而降低故障系统的负载,有利于系统的恢复。例如有一个搜索服务,通过调用推荐服务来提供个性化的搜索结果;但是过程中发现推荐服务在很多不同调用中都返回了错误,所以我们可能应该停止调用一段时间。也许我们越是尝试就越会给系统造成压力,会造成情况的进一步恶化。经过考量,我们决定停止对这一服务的调用。这一方式和我们住宅中电气线路的熔断机制类似。如果出现故障,就应该断开故障部分,保护系统的其他部分。断路器模式强制我们的应用来正视网络问题——网络调用是可能、而且真的会出故障的,从而防止系统出现雪崩。这一技术的关键就是感知系统组件的健康并判断是否应该向某组件发送流量。



Netflix OSS Hystrix

Netflix OSS(注 6)在 2012 年发布了了一个断路器组件(注 7),称为 Hystrix(注 8)。Hystrix 是一个用于提供熔断能力的客户端 Java 库。Hystrix提供了这样一些特性(注 7)](https://medium.com/netflix-tec ... 159c2d)。

来自“Making the Netflix API more resilient(注 7)”:
  • 自定义回落操作:在一些情况下,服务客户端库提供了一个回落方法供调用,或者其他情况下,我们可以使用本地的数据来生成回应。
  • 故障抑制:在这种情况下,回落方法简单的返回一个 null 值,如果这一服务返回的数据是可选项目,这种方式会很有帮助。
  • 快速失败:当目标服务的返回数据是必须的情况下,上面两种方法无法解决这一问题的,只能返回一个5xx响应。这对用户感知是很不好的,但是这一手段能能够保障服务器的健康,让系统能够更快的将失效服务进行修



可以用多种方式触发断路器(注 7)。

对远程服务的请求发生超时。

用于一个服务的线程池或任务队列容量满载

用于调用服务的客户端库抛出异常。


Hystrix 熔断过程:

Netflix Hystrix 允许对网络交互进行非常细致的控制(注 9)。Hystrix 允许根据调用类型,对依赖服务进行精细的配置。假设我们对推荐引擎的调用绝大多数情况是只读的,那么断路器的配置就可以比较放松。


另外一个重要的事实是,Hystrix 的目的是及时断路,因此他把故障看做和超时是一致的。超时的故障点也可能处于客户一侧。Hystrix 对断路门槛的设置,并不区分故障究竟是服务端还是客户端的责任。


另外呼应前文:断路器真的只是智能、应用感知负载均衡技术的特性之一。在这种情况下“应用感知”的含义是:他的库在你的应用中运行。在 Netflix 生态系统中,还可以把 Hystrix 和 Netflix OSS Ribbon(注 10)这样的客户端负载均衡进行配对使用。



Service Mesh 的发展

服务架构持续向多样化方向演进,我们发现强制服务使用特定的库、框架或者语言是很难或者不实际的。随着 Service Mesh 走进视野,我们看到熔断能力有了独立于语言、框架的基础设施级的解决方案。Service Mesh 可以定义为:


一个处于服务之间的,去中心化的应用级网络基础设施,提供安全、弹性、监控和路由控制能力。

Service Mesh 可以使用不同的 L7(应用级)代理来扮演数据面角色,用于提供重试、超时、断路器等能力。本文中我们会看看 Envoy Proxy(注 10) 是如何完成熔断任务的。Envoy Proxy 是 Istio Service Mesh(注 11)的缺省的、开箱即用的代理,所以这里描述的特性同样也适用于 Istio。



Envoy Proxy / Istio Service Mesh

Envoy Proxy 将断路功能作为负载均衡和健康检查的一个子集。Envoy 将路由选择(选择进行通信的集群)的功能和通信功能(和确定的后端)分而治之。相对于其他粗粒度配置的负载均衡器,这一设计让 Envoy 与众不同。Envoy 可以有很多不同的“路由”尝试把流量发送给合适的后端。这些后端被称为cluster,每个cluster都可以有自己的负载均衡配置。每个cluster还可以有自己的被动健康检查(外部检测)配置。Envoy 有几个配置项用于熔断功能,这里可以逐个介绍一下。


这里定义一个外部cluster:


"clusters": [  {    "name": "httpbin_service",    "connect_timeout_ms": 5000,    "type": "static",    "lb_type": "round_robin",    "hosts": [      {        "url": "tcp://172.17.0.2:8080"      },{        "url": "tcp://172.17.0.3:8080"      }    ],


这里我们会看到,这里有一个叫httpbin_service的集群,使用round_robin的策略在两个主机之间进行负载均衡。接下来加入 Envoy 断路器配置(注 11)。




断路器


   "circuit_breakers": {      "default": {        "max_connections": 1,        "max_pending_requests": 1,        "max_retries": 3      }


这里我们目标是 HTTP 1.x 的负载。我们限制外来连接为 1,最大排队请求也是 1。另外还定义了最大重试次数。某种意义上,限制连接池以及请求数量的做法和 bulkhead(注 12) 以及 Netflix Hystrix 是类似的。如果客户端应用打开了超过限制的连接数量(这是一种软限制,有一定误差),我们会看到 Envoy 断掉多出的连接(注 13),并在统计报告中进行记录。


外部检测

上面我们看到,Envoy 所谓的熔断功能实际上更像是连接池控制。要完成这一功能,Envoy 做了一些称为outlier detection(注 14)。Envoy 持续对负载均衡池中的不同端点的操作进行统计。如果发现了超标行为,就把端点从负载均衡池中移除。我们可以看一下这一部分的配置代码:


   "outlier_detection" : {      "consecutive_5xx": 1,      "max_ejection_percent": 100,      "interval_ms": 1000,      "base_ejection_time_ms": 60000    }


这一配置的含义是:通信过程中,“如果发生了一次 5xx”错误,我们应该把这一主机标记为不健康,将其从负载均衡池中移除。我们还配置max_ejection_percent为100,也就是说,在发生这一情况时,我们愿意逐出所有端点。这一设置跟环境紧密相关,因此配置内容应该因地制宜,谨慎从事。我们希望尽可能的路由到一个主机,这样我们就不必冒着部分或级联故障的风险了。Envoy 缺省设置max_ejection_percent为10。

我们还设置逐出的时间基数为6000毫秒。一个主机被逐出负载均衡池的真实时间,由这一基数乘以被逐出时间得来,这样就可以对稳定性较差的主机实行更久的隔离。



集群恐慌

Envoy 外部检测和负载均衡功能中还有一点我们要知道的。如果太多的主机被这一过程逐出,就会进入集群恐慌模式(注 15),这种情况下,代理服务器会无视负载均衡池的健康标记,重新向所有主机发送数据。这是一个非常棒的机制。在分布式系统中,必须了解到的一点是,有时候“理论上”的东西可能不是正常情况,最好能降低一点要求来防止扩大故障影响。另外一方面,可以对这一比例进行控制(缺省情况下超过 50% 的驱逐就会进入恐慌状态),可以提高,也可以禁止这一阈值。设置为0之后,他的熔断行为就和 Netflix Hystrix 类似了。



可微调的熔断策略

库方式有个好处就是应用感知的可微调的熔断策略。Hystrix 文档中演示了针对同一集群的查询、读取、写入的不同调用,Hystrix FAQ 中说到:



通常情况下,一组负载均衡集群形成的单一网络路由会使用很多不同的 HystrixCommands 服务于很多不同类型的功能。

每个 HystrixCommands 都需要设置不同的吞吐限制、超时以及回落策略。

在 Envoy 中,我们能够通过路由匹配功能(注 16)获得同样的精确的熔断策略,这一功能和集群策略(注 17)结合,就可以指定在什么集群上进行什么操作了。



Istio 断路器

我们可以使用 Istio 的高级配置,来提供断路器能力。在 Istio 中,我们使用 目标策略(注 17)来配置负载均衡和断路器策略。下面是一个目标策略的例子,其中进行了断路器的设置:

metadata:  name: reviews-cb-policy  namespace: defaultspec:  destination:    name: reviews    labels:      version: v1  circuitBreaker:    simpleCb:      maxConnections: 100      httpMaxRequests: 1000      httpMaxRequestsPerConnection: 10      httpConsecutiveErrors: 7      sleepWindow: 15m      httpDetectionInterval: 5m


熔断之后怎么办?

达到熔断标准的时候,会发生什么事情?Hystrix 中的回落策略是包含在库中并且能够进行编排的。Hystrix 让我们可以做一些后续操作,例如返回缓存值、返回缺省值甚至去调用其他服务。我们还可以获得清晰的关于故障的信息,并作出应用相关的决策。


在 Service Mesh 之中,因为没有内置库的支持,故障原因会比较隐蔽。这并不意味着我们的应用就不能有回落操作了(不管是传输还是客户端错误)。我认为对任何应用来说,不论他用的是不是特定库的框架,都会要尝试完成对客户的承诺。如果无法完成预定动作,就应该有一种优雅的降级方法。幸运的是,这种操作也不是非框架不可。多数语言都有内置的错误和异常处理能力,回落策略可以在异常处理过程中完成。


回放

熔断能力是负载均衡的功能之一。

Hystrix 只提供了熔断能力,负载均衡要配合 Ribbon(或者其他客户端负载均衡库)完成。

Hystrix 以客户端库的形式提供了回落能力,非常强大。

Envoy 的负载均衡实现中包含了外部检测和断路器的功能。

Envoy 的熔断更像 Hystrix Bulkhead ,外部检测更像 Hystrix 断路器。

Envoy 具有很多缺省的久经考验的功能,例如集群恐慌。

Service Mesh 缺少故障回落的能力,只能让应用来完成这一任务。


点击阅读原文即可阅读更多Christian Posta文章~

Contact with Christian Posta@https://twitter.com/christianposta






1.https://twitter.com/mattklein123

2.https://blog.envoyproxy.io/int ... 80236

3.https://martinfowler.com/bliki/CircuitBreaker.html

4.https://github.com/Netflix/Hystrix

5.https://www.envoyproxy.io/

6.https://netflix.github.io

7.https://medium.com/netflix-tec ... ab362

8.https://github.com/Netflix/Hystrix

9.https://github.com/Netflix/Hys ... calls

10.https://www.envoyproxy.io/

11.https://www.envoyproxy.io/docs ... aking

12.https://developers.redhat.com/ ... ation

13.http://blog.christianposta.com ... king/

14.https://www.envoyproxy.io/docs ... tlier

15.https://www.envoyproxy.io/docs ... 3core

16.https://www.envoyproxy.io/docs ... uster


推荐阅读:
微服务迁移前,来听听这6个思考和经验
这款分布式配置中心,会是微服务的降维大机利器吗?
docker + kubernetes=共生?相爱相杀?
 

Envoy如何打败Linkerd成为L7负载平衡器的最佳选择?

Envoy小数 发表了文章 • 0 个评论 • 1062 次浏览 • 2018-01-29 18:29 • 来自相关话题

作者:MIKE WHITE

翻译:姚炳雄

原文:Using Envoy to Load Balance gRPC Traffic


针对 Bugsnag(一款bug自动检测工具),我们最近启动了一个专门用来跟踪软件发布健康状况的发布仪表板项目。 这是个大任务,当我们在构建后台时,特别关注了它的性能。其中的关键领域之一是和后端服务调用相关的延迟,在最后,我们决定用 Google 的超级快速的 gRPC 框架替换REST。


为了成功迁移到 gRPC,需要重新思考我们的负载均衡策略,以确保它很好地支持 gRPC 流量。 这篇博文概述了我们如何最终达成目标,去将 Lyft 功能丰富的 Envoy Proxy 添加到堆栈以及它又是如何来适应 Bugsnag 架构的。



Bugsnag体系结构的背景

在背后,Bugsnag 有一个微服务管道,负责处理从客户那里收到的错误信息,这些错误信息稍后展示在仪表板上。 这条管道目前每天处理数以亿计的事件。为了支持新的发布仪表板,我们需要扩展管道接收用户会话信息,这意味着流量将大幅增加。性能将成为是这个项目成功的关键,也是我们采用gRPC框架的主要原因之一。


部署方面,Bugsnag 的微服务是通过 Kubernetes 以 Docker 容器方式部署在云上。 Kubernetes 通过它的 kube-proxy 建立了负载均衡,可以很好地处理 HTTP / 1.1 流量,但是当你把 HTTP / 2 请求也扔进去混合到一起时,事情会变得很有意思。




HTTP / 2 – 一个负载均衡头痛的难题

gRPC 使用了性能加速的HTTP / 2协议。 HTTP / 2的实现比起以前的版本,在诸多降低延迟的方法中,一种利用了单一的长 TCP 连接(single long-lived TCP connection),并在该连接上能交叉传递请求/响应。 这给4层(L4)负载均衡器带来了问题,因为它们的操作在太低的层上,以致无法根据它接收到的流量类型做出路由决策。 因此,一个L4负载平衡器试着负载平衡HTTP / 2流量,必然会打开一个单一长TCP连接,并将所有连续的流量都路由到这个单一长TCP连接,这实际上是取消了负载平衡。

Kubernetes 的 kube-proxy 本质上是一个L4负载平衡器,所以我们不能依靠它来负载平衡微服务之间的gRPC调用。



为什么不让客户做这项工作?

我们探索的其中一个选项是使用 gRPC 客户端负载均衡器,它被打包在gRPC客户端库中。 这样,每个客户端微服务可以执行自己的负载平衡。 然而,由此产生的客户端最终是脆弱的,并需要大量的客户化代码来提供所有形式的弹性、度量或日志记录,所有这些需要重复几次在管道中使用每种不同的语言。


我们真正需要的是更智能的负载均衡器。



选择更智能的负载平衡器

我们需要一个L7负载均衡器,因为它们作用在应用层,能检测流量,以便做出路由决策。 最重要的是,他们可以支持HTTP / 2协议。


对于L7负载平衡器的选择,包括 NGINX 和 HAProxy 在内,有许多可选的产品。但这其中的大多数都因为过于厚重而不易采纳进微服务架构。 我们缩小范围,选择了两个关键的竞争者 —— Envoy 和 Linkerd。两者都是秉承微服务体系结构理念开发的,都支持gRPC。


虽然这两个代理都有很多不错的功能,但最根本的决定因素取决于代理的足迹。这样赢家就很明显了。 Envo 非常小,用 C ++ 11编写,不像用 Java 编写用于企业级的 Linkerd 那么重。


一旦决定使用 Envoy,开始深入到它的功能集中,会发现有很多想要的东西。




Envoy凭什么表现这么好?

Envoy 由 Lyft 编写和开源,是多年来与微服务体系结构中常见的复杂路由问题作斗争的直接结果。 它本质上是为了适应我们的问题而设计的,
一流的双向支持HTTP / 2和SSL具备优秀的度量指标并高度透明成熟的文档集不依赖于任何给定的语言


最后一个,也是最重要的一个,它与Bugsnag的polyglot微服务架构融为一体。




Envoy进入基础设施

在 Kubernetes 中,一个或多个容器组成一组称为 pod。Pod 能被复制多个,以提供弹性扩展,这些 pod 被包装抽象成服务,该服务拥有固定的IP,通过该服务可以访问底层的 pod。从 Kubernetes 1.2开始,当访问服务IP时,kubernetes 会随机返回后端的某个pod。也可以将服务重新配置为无人值守(headless),以便服务IP不再返回可用的pod IP整个列表,而是允许执行自己的服务发现。


Envoy 被设计成 Sidecar Container 方式运行,与客户端容器并排放置,以模块化方式来补充其功能。在 Kubernetes 中,这转化为在同一个 pod 中运行客户的容器和 Envoy 容器。我们将我们的服务配置为无人值守(headless)模式以供 Envoy 来做服务发现的端点。而且,依赖于Envoy大量的度量数据的输出,我们能够轻松观察到持续的gRPC调用的轮询调度的负载均衡,来确认其按预期工作。


当我们选择为每个gRPC客户端运行一个 Envoy 边车,像 Lyft 公司为所有微服务都运行一个Envoy sidecar,形成服务网格。这种方法非常强大,可以在域级别调整流量参数,这也是我们想在Bugsnag上能看到的。



可选方案


虽然Envoy能够满足需求,但还是有一些值得一提的替代方案。其中一些是我们探讨的,但是他们或者太不成熟,或者不太适合当时的架构:


· Istio - IBM,Google 和 Lyft 联合开发,形成了一个完整的微服务负载均衡解决方案。Envoy 作为核心,在 Kubernete s平台上“开箱即用”方式运行。


· Ribbon - 来自 Netflix 的开源 IPC 库,这家公司已经被证明是微服务相关 DevOps 工具的重量级公司。


· Kubernetes Ingress controllers - 虽然此功能依赖于Beta Kuberenetes资源,但它代表了在 Kuberenete s中实现L7负载均衡的可能性。


总的来说,Envoy 给我们留下了深刻的印象,在后续的Bugsnag的开发和拓展中,我们将继续探索其特色。有一件事是肯定的,现在这方面是 DevOps 的一个热点,我们非常关注下一步它将如何发展。


Bugsnag会自动监视应用程序是否存在有害错误,并告警,可视化到软件内部。您可以将我们看成软件质量的中控台。免费试用14天的Bugsnag,包括用于跟踪发布健康状况的发布仪表板。


原文地址:https://blog.bugsnag.com/envoy/ 
 
推荐阅读:
这款分布式配置中心,会是微服务的降维大机利器吗?
docker + kubernetes=共生?相爱相杀?
万字雄文讲透现代网络负载均衡和代理技术,终于弄懂负载均衡那点事

  查看全部
1_ddhto6-LmBxmFxDSdvPeNg.png



作者:MIKE WHITE

翻译:姚炳雄

原文:Using Envoy to Load Balance gRPC Traffic


针对 Bugsnag(一款bug自动检测工具),我们最近启动了一个专门用来跟踪软件发布健康状况的发布仪表板项目。 这是个大任务,当我们在构建后台时,特别关注了它的性能。其中的关键领域之一是和后端服务调用相关的延迟,在最后,我们决定用 Google 的超级快速的 gRPC 框架替换REST。


为了成功迁移到 gRPC,需要重新思考我们的负载均衡策略,以确保它很好地支持 gRPC 流量。 这篇博文概述了我们如何最终达成目标,去将 Lyft 功能丰富的 Envoy Proxy 添加到堆栈以及它又是如何来适应 Bugsnag 架构的。



Bugsnag体系结构的背景

在背后,Bugsnag 有一个微服务管道,负责处理从客户那里收到的错误信息,这些错误信息稍后展示在仪表板上。 这条管道目前每天处理数以亿计的事件。为了支持新的发布仪表板,我们需要扩展管道接收用户会话信息,这意味着流量将大幅增加。性能将成为是这个项目成功的关键,也是我们采用gRPC框架的主要原因之一。


部署方面,Bugsnag 的微服务是通过 Kubernetes 以 Docker 容器方式部署在云上。 Kubernetes 通过它的 kube-proxy 建立了负载均衡,可以很好地处理 HTTP / 1.1 流量,但是当你把 HTTP / 2 请求也扔进去混合到一起时,事情会变得很有意思。




HTTP / 2 – 一个负载均衡头痛的难题

gRPC 使用了性能加速的HTTP / 2协议。 HTTP / 2的实现比起以前的版本,在诸多降低延迟的方法中,一种利用了单一的长 TCP 连接(single long-lived TCP connection),并在该连接上能交叉传递请求/响应。 这给4层(L4)负载均衡器带来了问题,因为它们的操作在太低的层上,以致无法根据它接收到的流量类型做出路由决策。 因此,一个L4负载平衡器试着负载平衡HTTP / 2流量,必然会打开一个单一长TCP连接,并将所有连续的流量都路由到这个单一长TCP连接,这实际上是取消了负载平衡。

Kubernetes 的 kube-proxy 本质上是一个L4负载平衡器,所以我们不能依靠它来负载平衡微服务之间的gRPC调用。



为什么不让客户做这项工作?

我们探索的其中一个选项是使用 gRPC 客户端负载均衡器,它被打包在gRPC客户端库中。 这样,每个客户端微服务可以执行自己的负载平衡。 然而,由此产生的客户端最终是脆弱的,并需要大量的客户化代码来提供所有形式的弹性、度量或日志记录,所有这些需要重复几次在管道中使用每种不同的语言。


我们真正需要的是更智能的负载均衡器。



选择更智能的负载平衡器

我们需要一个L7负载均衡器,因为它们作用在应用层,能检测流量,以便做出路由决策。 最重要的是,他们可以支持HTTP / 2协议。


对于L7负载平衡器的选择,包括 NGINX 和 HAProxy 在内,有许多可选的产品。但这其中的大多数都因为过于厚重而不易采纳进微服务架构。 我们缩小范围,选择了两个关键的竞争者 —— Envoy 和 Linkerd。两者都是秉承微服务体系结构理念开发的,都支持gRPC。


虽然这两个代理都有很多不错的功能,但最根本的决定因素取决于代理的足迹。这样赢家就很明显了。 Envo 非常小,用 C ++ 11编写,不像用 Java 编写用于企业级的 Linkerd 那么重。


一旦决定使用 Envoy,开始深入到它的功能集中,会发现有很多想要的东西。




Envoy凭什么表现这么好?

Envoy 由 Lyft 编写和开源,是多年来与微服务体系结构中常见的复杂路由问题作斗争的直接结果。 它本质上是为了适应我们的问题而设计的,
  • 一流的双向支持HTTP / 2和SSL
  • 具备优秀的度量指标并高度透明
  • 成熟的文档集
  • 不依赖于任何给定的语言



最后一个,也是最重要的一个,它与Bugsnag的polyglot微服务架构融为一体。




Envoy进入基础设施

在 Kubernetes 中,一个或多个容器组成一组称为 pod。Pod 能被复制多个,以提供弹性扩展,这些 pod 被包装抽象成服务,该服务拥有固定的IP,通过该服务可以访问底层的 pod。从 Kubernetes 1.2开始,当访问服务IP时,kubernetes 会随机返回后端的某个pod。也可以将服务重新配置为无人值守(headless),以便服务IP不再返回可用的pod IP整个列表,而是允许执行自己的服务发现。


Envoy 被设计成 Sidecar Container 方式运行,与客户端容器并排放置,以模块化方式来补充其功能。在 Kubernetes 中,这转化为在同一个 pod 中运行客户的容器和 Envoy 容器。我们将我们的服务配置为无人值守(headless)模式以供 Envoy 来做服务发现的端点。而且,依赖于Envoy大量的度量数据的输出,我们能够轻松观察到持续的gRPC调用的轮询调度的负载均衡,来确认其按预期工作。


当我们选择为每个gRPC客户端运行一个 Envoy 边车,像 Lyft 公司为所有微服务都运行一个Envoy sidecar,形成服务网格。这种方法非常强大,可以在域级别调整流量参数,这也是我们想在Bugsnag上能看到的。



可选方案


虽然Envoy能够满足需求,但还是有一些值得一提的替代方案。其中一些是我们探讨的,但是他们或者太不成熟,或者不太适合当时的架构:


· Istio - IBM,Google 和 Lyft 联合开发,形成了一个完整的微服务负载均衡解决方案。Envoy 作为核心,在 Kubernete s平台上“开箱即用”方式运行。


· Ribbon - 来自 Netflix 的开源 IPC 库,这家公司已经被证明是微服务相关 DevOps 工具的重量级公司。


· Kubernetes Ingress controllers - 虽然此功能依赖于Beta Kuberenetes资源,但它代表了在 Kuberenete s中实现L7负载均衡的可能性。


总的来说,Envoy 给我们留下了深刻的印象,在后续的Bugsnag的开发和拓展中,我们将继续探索其特色。有一件事是肯定的,现在这方面是 DevOps 的一个热点,我们非常关注下一步它将如何发展。


Bugsnag会自动监视应用程序是否存在有害错误,并告警,可视化到软件内部。您可以将我们看成软件质量的中控台。免费试用14天的Bugsnag,包括用于跟踪发布健康状况的发布仪表板。


原文地址:https://blog.bugsnag.com/envoy/ 
 
推荐阅读:
这款分布式配置中心,会是微服务的降维大机利器吗?
docker + kubernetes=共生?相爱相杀?
万字雄文讲透现代网络负载均衡和代理技术,终于弄懂负载均衡那点事

 

Service Mesh 一周大事件

ServiceMesh小数 发表了文章 • 0 个评论 • 581 次浏览 • 2018-01-29 11:10 • 来自相关话题

 资讯

1、Conduit 0.1.2、0.1.3版本

1月19日,Conduit更新了0.1.2版本,该版本继续沿着增加可用性、改进调试、对服务网格本身自省的道路前进。紧跟其后,Conduit又发布了0.1.3版本,该版本只是对于一些没有正确呈现 web 指示板 UI 元素的修复。

浏览地址:https://github.com/runconduit/conduit



2、Linkerd 1.3.5版本

1月18日,Linkerd发布了1.3.5版本,这个版本集中于 Namerd 的 ixes 和 Linkerd 管理 UI 的改进。

浏览地址:https://github.com/linkerd/linkerd/releases/tag/1.3.5




3、SPIRE 0.3版本

本月初,SPIRE 发布了0.3版本,该版本虽然仍是测试版本,但亮点之一是:使运营工程团队能够使用 SPIRE (一个新兴的参考SPIFFE规范实现的开源框架),在使用 Lyft Envoy 服务代理过程中,部署安全的服务网格。

SPIFFE (全称: Secure Production Identity Framework For Everyone),SPIFFE 标准旨在为大家使用的生产环境安全身份系统提供一个框架的规范,该框架能够跨异构环境和组织边界,对服务进行引导和发布身份。SPIFFE 和 SPIRE 是一对,SPIFFE 定义了服务的认证标准和认证信息的标准,SPIRE 是SPIFFE的实现形式,但是目前还没有达到生产可用。

浏览地址 https://blog.scytale.io



4、Go 语言微服务框架发布

日前,华为云CSE(Cloud Service Engine)正式推出的产品级Go语言微服务框架Go Chassis。借助CSE Go Chassis进行微服务开发可最大化地降低开发门槛,提升产品上线速度,同时可以获得微服务运行时高可靠性保证、运行时动态治理等一系列开箱即用的能力。


在不久前CSE刚刚发布了基于Service Mesh技术的CSE Mesher,支持Net、Node.js等语言应用能够以零侵入模式接入CSE微服务治理,本次Go语言微服务框架的发布,不仅意味着CSE正式拥抱Go生态系统,同样意味着CSE已提供Java、Go、NET、Node.js、PHP等多语言微服务解决方案,这给企业及开发者提供了更大的选型空间,使企业可以高效复用现有的语言能力和软件资产。
  查看全部

微信图片_20180125174434.png

 资讯

1、Conduit 0.1.2、0.1.3版本

1月19日,Conduit更新了0.1.2版本,该版本继续沿着增加可用性、改进调试、对服务网格本身自省的道路前进。紧跟其后,Conduit又发布了0.1.3版本,该版本只是对于一些没有正确呈现 web 指示板 UI 元素的修复。

浏览地址:https://github.com/runconduit/conduit



2、Linkerd 1.3.5版本

1月18日,Linkerd发布了1.3.5版本,这个版本集中于 Namerd 的 ixes 和 Linkerd 管理 UI 的改进。

浏览地址:https://github.com/linkerd/linkerd/releases/tag/1.3.5




3、SPIRE 0.3版本

本月初,SPIRE 发布了0.3版本,该版本虽然仍是测试版本,但亮点之一是:使运营工程团队能够使用 SPIRE (一个新兴的参考SPIFFE规范实现的开源框架),在使用 Lyft Envoy 服务代理过程中,部署安全的服务网格。

SPIFFE (全称: Secure Production Identity Framework For Everyone),SPIFFE 标准旨在为大家使用的生产环境安全身份系统提供一个框架的规范,该框架能够跨异构环境和组织边界,对服务进行引导和发布身份。SPIFFE 和 SPIRE 是一对,SPIFFE 定义了服务的认证标准和认证信息的标准,SPIRE 是SPIFFE的实现形式,但是目前还没有达到生产可用。

浏览地址 https://blog.scytale.io



4、Go 语言微服务框架发布

日前,华为云CSE(Cloud Service Engine)正式推出的产品级Go语言微服务框架Go Chassis。借助CSE Go Chassis进行微服务开发可最大化地降低开发门槛,提升产品上线速度,同时可以获得微服务运行时高可靠性保证、运行时动态治理等一系列开箱即用的能力。


在不久前CSE刚刚发布了基于Service Mesh技术的CSE Mesher,支持Net、Node.js等语言应用能够以零侵入模式接入CSE微服务治理,本次Go语言微服务框架的发布,不仅意味着CSE正式拥抱Go生态系统,同样意味着CSE已提供Java、Go、NET、Node.js、PHP等多语言微服务解决方案,这给企业及开发者提供了更大的选型空间,使企业可以高效复用现有的语言能力和软件资产。
 

Serverless遇上ServiceMesh,是珠联璧合还是流于形式?

ServiceMesh小数 发表了文章 • 0 个评论 • 653 次浏览 • 2018-01-25 11:44 • 来自相关话题

 作者:ANDRÉS MARTÍNEZ

翻译:江水

原文:Serverless Service Mesh With Kubeless And Istio



在过去的几个月中,你可能已经听说过 service mesh。service mesh 简单来说就是一个基础设施组件,可以快速可靠的连接多个微服务。这种架构提出了一种非常有趣的方法,适用于在云原生场景中设计新的应用程序。在本文中,我们将演示如何使用 Kubeless:一个跑在 Kubernetes 上的 serverless 框架,以及 Istio:一个提供网络连接,管理和安全控制的开源平台 Kubernetes 服务,你可以花几分钟轻松地部署你的第一个 service mesh。


在 Bitnami,我们开发了 Kubeless:一个 serverless 平台,可以让你轻松在 Kubernetes 集群上运行微服务。如果这是你第一次听说 Kubeless,你想了解更多的基本知识,可以看我之前的帖子, 或者访问 Kubeless. io 官网。


除了 Kubeless,Istio 是一个为微服务提供网络资源的开源平台。Istio 允许你以一种简单的方式管理、监控和安全控制你的微服务。


作为开发者,你可能知道,在群集中维护具有不同版本和授权策略的服务可能很困难,而且容易出错。必须仔细管理所有服务之间的所有可能的路由。


结合 Kubeless 和 Istio 创建  service mesh 可以大大节约发布与网络管理的成本。Kubeless 只需要你输入一个发布命令就可以让 Istio 用过配置文件管理你的请求路由和策略。在本文中,我将通过如下命令演示:
配置环境以部署 service mesh。从应用程序部署多个serverless 函数。路由用户请求以显示服务的不同版本。保护应用程序的部分在不被授权的情况下不能访问。



1. 目标架构

为了演示 Kubeless 和 Istio,我将部署一个应用程序,将模拟管理一个cold room。请参见建议架构的示意图:





应用将由三组不同的服务组形成:
测量和报告 room 温度的服务叫温度计服务(被称作 temp),我会部署两个不同版本的服务。版本 v2 还将报告 room 的温度。一个恒温器服务,会根据 room 的温度,增加或减少系统的输出。此服务将受到保护,只有控制服务才能访问它。控制服务会从温度计服务中检索温度并将结果发送到恒温器服务。在一个纯粹的 service mesh 架构中,这个组件是不必要的,因为恒温器服务会直接从温度计服务接收温度。在任何情况下,做这个例子都一些复杂并有趣, 我会包括它。





2. 准备环境

对于本练习,我将使用 Google 云平台 (GCP) 中的 Kubernetes 集群,使用谷歌 Kubernetes 引擎 (GKE)。如果你没有 GCP 帐户,或者你更喜欢在本地部署,则可以使用 Minikube 完成此练习。


在 GKE 上部署集群,我会用  Google Cloud SDK 的 gcloud 工具。如果你要用 GKE 完成此操作,请确保安装如下工具:


gcloud container clusters create \  --cluster-version=1.8.6-gke.0 \  --zone us-east1-c \  --num-nodes 5 \  --enable-kubernetes-alpha \  istio-test


我将启用 alpha 功能(30天后将群集标记为删除),因为这是使用 autoinjection 功能所必需的。Autoinjection 可以是我们不必在部署服务的时候手动插入 Istio 详细信息。除此之外,为了确保我不会耗尽资源,我将使用5节点。



我现在将部署 Istio。我使用的是最新版本的。下面是要执行的命令:


wget https://github.com/istio/istio ... ar.gz tar zxf istio-0.4.0-osx.tar.gz kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value core/account) kubectl apply -f istio-0.4.0/install/kubernetes/istio.yaml kubectl apply -f istio-0.4.0/install/kubernetes/istio-initializer.yaml


注意: 如果你在 Linux 或 Windows 系统中遵循本指南,请使用不同的压缩。如果你在创建 ClusterRoleBinding 时遇到问题,可以按照本指南进行。


让我们在这个新的集群中部署 Kubeless。如果你遵循本指南,则必须执行在 GKE 中部署 Kubeless 并安装 Kubeless CLI 工具的步骤。


此时需要在群集中部署 Kubeless 和 Istio:

$ kubectl get pods -n kubeless

NAME                                  READY     STATUS    RESTARTS   AGEkafka-0                               2/2       Running   1          1m kubeless-controller-151920402-3qtxz   2/2       Running   0          1m zoo-0                                 2/2       Running   0          1m$ kubectl get pods -n istio-systemNAME                                READY     STATUS    RESTARTS   AGE istio-ca-1363003450-bdfrl           1/1       Running   0          2m istio-ingress-1005666339-xchw9      1/1       Running   0          2m istio-initializer-563520905-dmh55   1/1       Running   0          1m istio-mixer-465004155-tk0x5         3/3       Running   0          2m istio-pilot-1861292947-8rkh3        2/2       Running   0          2m



3. 部署 service mesh

是部署应用程序服务的时候了。本指南中使用的所有文件都可在此 Github 仓库中获得。你可以克隆存储库,以使这些文件在本地可用:


git clone https://github.com/andresmgot/ ... ample cd kubeless-istio-sample


让我们部署两个版本的温度计服务,将返回 room 的温度:


kubeless function deploy \  --from-file functions/tempv1.js \  --handler temp.sample \  --runtime nodejs6 \  --label version=v1 \  --label app=temp \  tempv1 kubeless function deploy \  --from-file functions/tempv2.js \  --handler temp.sample \  --runtime nodejs6 \  --label version=v2 \  --label app=temp \  tempv2请注意,我设置 label version=v1 和 version=v2,所以我可以区分他们的版本。我也设置 label app=temp,使这两个函数有一个共同的 label。





除了这些部署之外,我还将创建一个服务,用于使用单个端点访问这两个函数:


kubectl create -f manifests/temp-svc.yaml


最后,我将创建恒温器服务和控制功能:


kubeless function deploy \  --from-file functions/thermostat.js \  --handler thermostat.handler \  --runtime nodejs6 \  thermostat kubeless function deploy \  --from-file functions/control.js \  --handler temp.control \  --dependencies functions/package.json \  --runtime nodejs6 \  control


几秒钟后,就可使用 kubeless CLI 访问这些服务:


$ kubeless function call tempv1{"src":"tempv1-2338499756-b3mlv","temp":"15"}$ kubeless function call tempv2{"src":"tempv2-1085493462-798j8","temp":"6","hum":"1"}$ kubeless function call thermostat --data '{"temp": "10"}'Decreasing!$ kubeless function call controlTemperature measured: 16 degrees. Action: Decreasing!. Humidity: 20%


请注意,有时当调用控制函数时,它会返回湿度,但其他的则不会。它取决于内部调用的 temp 服务(上文提到过 温度计服务)的版本。




4. 使服务适应 Istio

Kubeless 自动创建访问包含函数服务的函数所需的所有资源。但是,为了使用 Istio,服务端口的 name 属性必须是一个众所周知的值。因此,我必须更改在端口列表中的当前值。我可以通过编辑当前服务来更改它:



kubectl get svc -l created-by=kubeless -o yaml | sed 's/name: function-port/name: http/g' | kubectl apply -f -


现在所有的服务都已更新,我需要重新启动函数 pod。这是因为 pod 会在 initContainer 中注册他们的信息。initContainer 只在启动一个 pod 时执行,因此,要正确地注册服务信息,我需要重新启动所有的 pod:


kubectl delete pods -l created-by=kubeless几分钟后,pod 再次运行,并在 Istio 正确注册。



5. 请求负载均衡

在这一步中,我将使用 Istio 提供的请求路由配置。这允许我管理不同版本的临时服务的请求。我将部署一个非常简单的规则,将90% 的请求重定向到 v1of 服务的版本,另外10% 个版本 v2。此功能在测试新功能或使用 a/b 测试时非常有用,因为它允许你在不影响所有用户的功能的情况下运行同一服务的多个版本:


route-rule-10-v2.yaml:


apiVersion: config.istio.io/v1alpha2kind: RouteRulemetadata:  name: temp-rulespec:  ## Used by services inside the Kubernetes cluster  destination:    name: temp  route:  - labels:      version: v1    weight: 90  - labels:      version: v2    weight: 10


kubectl apply -f manifests/route-rule-10-v2.yaml


现在,如果我多次执行 kubeless 函数调用控制命令,它将只打印几次湿度。你可以更改这些数字(例如,将所有流量重定向到 v2 版本),并在调用 controlservice 时查看更改。



6. 基本访问控制

对于本练习,我将限制对恒温器服务的访问。这只是一个例子,所以我将使用基本的访问控制。请注意,如果我使用 TLS 身份验证部署 Istio,我可以使用服务帐户并配置安全访问控制,但为了简单起见,我不会在这里做。


通常,恒温器服务只能通过控制服务来访问。为了确保这一点,我将部署以下清单:

deny-rule.yaml:apiVersion: "config.istio.io/v1alpha2"kind: deniermetadata:  name: denyhandlerspec:  status:    code: 7    message: Not allowed---apiVersion: "config.istio.io/v1alpha2"kind: checknothingmetadata:  name: denyrequestspec:---apiVersion: "config.istio.io/v1alpha2"kind: rulemetadata:  name: denytempspec:  match: source.labels["function"] != "control" && request.path != "/healthz" && destination.labels["function"] == "thermostat"  actions:  - handler: denyhandler.denier    instances: [ denyrequest.checknothing ]
kubectl apply -f manifests/deny-rule.yaml


我所做的是阻止任何不是来自恒温器服务的控制功能的请求(除非请求是 Kubernetes 使用的 /healthz 路径, 以检查服务是否活着)。
我们可以通过执行以下操作来确保规则的工作:


$ kubeless function call controlTemperature measured: 5 degrees. Action: Increasing!$ kubeless function call thermostatERRO[0000] FATA[0000] PERMISSION_DENIED:denyhandler.denier.default:Not allowed (get services thermostat:http)


请注意,此规则不保护恒温器服务不受群集用户的控制,并具有创建 pod 的权限。这些用户中的任何一个都可以创建一个 label 是 function=control 的 pod,它将能够访问恒温器服务。为了正确地保护此服务,我应该使用安全访问控制,并指派一个 serviceAccountName(其他用户不能使用)到 controldeployment。


7. 准备好了么?

我刚刚介绍了 Kubeless 和 Istio 的一些基本功能,但是现在你应该可以使用这两种工具来启动 service mesh 了。下一步是使用服务帐户并设置具有安全访问控制的群集。这样我就可以为这些功能提供更严密的安全性。



除此之外,还有很多功能可以处理,例如,添加监控和指标,自定义路由,自动扩缩容...想浏览更多信息,请看 Istio 和 Kubeless 的网站和文档。



原文地址:https://engineering.bitnami.com/articles/serverless-service-mesh-with-kubeless-and-istio.html 查看全部

微信图片_20180124181358.jpg

 作者:ANDRÉS MARTÍNEZ

翻译:江水

原文:Serverless Service Mesh With Kubeless And Istio



在过去的几个月中,你可能已经听说过 service mesh。service mesh 简单来说就是一个基础设施组件,可以快速可靠的连接多个微服务。这种架构提出了一种非常有趣的方法,适用于在云原生场景中设计新的应用程序。在本文中,我们将演示如何使用 Kubeless:一个跑在 Kubernetes 上的 serverless 框架,以及 Istio:一个提供网络连接,管理和安全控制的开源平台 Kubernetes 服务,你可以花几分钟轻松地部署你的第一个 service mesh。


在 Bitnami,我们开发了 Kubeless:一个 serverless 平台,可以让你轻松在 Kubernetes 集群上运行微服务。如果这是你第一次听说 Kubeless,你想了解更多的基本知识,可以看我之前的帖子, 或者访问 Kubeless. io 官网。


除了 Kubeless,Istio 是一个为微服务提供网络资源的开源平台。Istio 允许你以一种简单的方式管理、监控和安全控制你的微服务。


作为开发者,你可能知道,在群集中维护具有不同版本和授权策略的服务可能很困难,而且容易出错。必须仔细管理所有服务之间的所有可能的路由。


结合 Kubeless 和 Istio 创建  service mesh 可以大大节约发布与网络管理的成本。Kubeless 只需要你输入一个发布命令就可以让 Istio 用过配置文件管理你的请求路由和策略。在本文中,我将通过如下命令演示:
  • 配置环境以部署 service mesh。
  • 从应用程序部署多个serverless 函数。
  • 路由用户请求以显示服务的不同版本。
  • 保护应用程序的部分在不被授权的情况下不能访问。




1. 目标架构

为了演示 Kubeless 和 Istio,我将部署一个应用程序,将模拟管理一个cold room。请参见建议架构的示意图:





应用将由三组不同的服务组形成:
  • 测量和报告 room 温度的服务叫温度计服务(被称作 temp),我会部署两个不同版本的服务。版本 v2 还将报告 room 的温度。
  • 一个恒温器服务,会根据 room 的温度,增加或减少系统的输出。此服务将受到保护,只有控制服务才能访问它。
  • 控制服务会从温度计服务中检索温度并将结果发送到恒温器服务。在一个纯粹的 service mesh 架构中,这个组件是不必要的,因为恒温器服务会直接从温度计服务接收温度。在任何情况下,做这个例子都一些复杂并有趣, 我会包括它。






2. 准备环境

对于本练习,我将使用 Google 云平台 (GCP) 中的 Kubernetes 集群,使用谷歌 Kubernetes 引擎 (GKE)。如果你没有 GCP 帐户,或者你更喜欢在本地部署,则可以使用 Minikube 完成此练习。


在 GKE 上部署集群,我会用  Google Cloud SDK 的 gcloud 工具。如果你要用 GKE 完成此操作,请确保安装如下工具:


gcloud container clusters create \  --cluster-version=1.8.6-gke.0 \  --zone us-east1-c \  --num-nodes 5 \  --enable-kubernetes-alpha \  istio-test


我将启用 alpha 功能(30天后将群集标记为删除),因为这是使用 autoinjection 功能所必需的。Autoinjection 可以是我们不必在部署服务的时候手动插入 Istio 详细信息。除此之外,为了确保我不会耗尽资源,我将使用5节点。



我现在将部署 Istio。我使用的是最新版本的。下面是要执行的命令:


wget https://github.com/istio/istio ... ar.gz tar zxf istio-0.4.0-osx.tar.gz kubectl create clusterrolebinding cluster-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value core/account) kubectl apply -f istio-0.4.0/install/kubernetes/istio.yaml kubectl apply -f istio-0.4.0/install/kubernetes/istio-initializer.yaml


注意: 如果你在 Linux 或 Windows 系统中遵循本指南,请使用不同的压缩。如果你在创建 ClusterRoleBinding 时遇到问题,可以按照本指南进行。


让我们在这个新的集群中部署 Kubeless。如果你遵循本指南,则必须执行在 GKE 中部署 Kubeless 并安装 Kubeless CLI 工具的步骤。


此时需要在群集中部署 Kubeless 和 Istio:

$ kubectl get pods -n kubeless

NAME                                  READY     STATUS    RESTARTS   AGEkafka-0                               2/2       Running   1          1m kubeless-controller-151920402-3qtxz   2/2       Running   0          1m zoo-0                                 2/2       Running   0          1m$ kubectl get pods -n istio-systemNAME                                READY     STATUS    RESTARTS   AGE istio-ca-1363003450-bdfrl           1/1       Running   0          2m istio-ingress-1005666339-xchw9      1/1       Running   0          2m istio-initializer-563520905-dmh55   1/1       Running   0          1m istio-mixer-465004155-tk0x5         3/3       Running   0          2m istio-pilot-1861292947-8rkh3        2/2       Running   0          2m



3. 部署 service mesh

是部署应用程序服务的时候了。本指南中使用的所有文件都可在此 Github 仓库中获得。你可以克隆存储库,以使这些文件在本地可用:


git clone https://github.com/andresmgot/ ... ample cd kubeless-istio-sample


让我们部署两个版本的温度计服务,将返回 room 的温度:


kubeless function deploy \  --from-file functions/tempv1.js \  --handler temp.sample \  --runtime nodejs6 \  --label version=v1 \  --label app=temp \  tempv1 kubeless function deploy \  --from-file functions/tempv2.js \  --handler temp.sample \  --runtime nodejs6 \  --label version=v2 \  --label app=temp \  tempv2请注意,我设置 label version=v1 和 version=v2,所以我可以区分他们的版本。我也设置 label app=temp,使这两个函数有一个共同的 label。





除了这些部署之外,我还将创建一个服务,用于使用单个端点访问这两个函数:


kubectl create -f manifests/temp-svc.yaml


最后,我将创建恒温器服务和控制功能:


kubeless function deploy \  --from-file functions/thermostat.js \  --handler thermostat.handler \  --runtime nodejs6 \  thermostat kubeless function deploy \  --from-file functions/control.js \  --handler temp.control \  --dependencies functions/package.json \  --runtime nodejs6 \  control


几秒钟后,就可使用 kubeless CLI 访问这些服务:


$ kubeless function call tempv1{"src":"tempv1-2338499756-b3mlv","temp":"15"}$ kubeless function call tempv2{"src":"tempv2-1085493462-798j8","temp":"6","hum":"1"}$ kubeless function call thermostat --data '{"temp": "10"}'Decreasing!$ kubeless function call controlTemperature measured: 16 degrees. Action: Decreasing!. Humidity: 20%


请注意,有时当调用控制函数时,它会返回湿度,但其他的则不会。它取决于内部调用的 temp 服务(上文提到过 温度计服务)的版本。




4. 使服务适应 Istio

Kubeless 自动创建访问包含函数服务的函数所需的所有资源。但是,为了使用 Istio,服务端口的 name 属性必须是一个众所周知的值。因此,我必须更改在端口列表中的当前值。我可以通过编辑当前服务来更改它:



kubectl get svc -l created-by=kubeless -o yaml | sed 's/name: function-port/name: http/g' | kubectl apply -f -


现在所有的服务都已更新,我需要重新启动函数 pod。这是因为 pod 会在 initContainer 中注册他们的信息。initContainer 只在启动一个 pod 时执行,因此,要正确地注册服务信息,我需要重新启动所有的 pod:


kubectl delete pods -l created-by=kubeless几分钟后,pod 再次运行,并在 Istio 正确注册。



5. 请求负载均衡

在这一步中,我将使用 Istio 提供的请求路由配置。这允许我管理不同版本的临时服务的请求。我将部署一个非常简单的规则,将90% 的请求重定向到 v1of 服务的版本,另外10% 个版本 v2。此功能在测试新功能或使用 a/b 测试时非常有用,因为它允许你在不影响所有用户的功能的情况下运行同一服务的多个版本:


route-rule-10-v2.yaml:


apiVersion: config.istio.io/v1alpha2kind: RouteRulemetadata:  name: temp-rulespec:  ## Used by services inside the Kubernetes cluster  destination:    name: temp  route:  - labels:      version: v1    weight: 90  - labels:      version: v2    weight: 10


kubectl apply -f manifests/route-rule-10-v2.yaml


现在,如果我多次执行 kubeless 函数调用控制命令,它将只打印几次湿度。你可以更改这些数字(例如,将所有流量重定向到 v2 版本),并在调用 controlservice 时查看更改。



6. 基本访问控制

对于本练习,我将限制对恒温器服务的访问。这只是一个例子,所以我将使用基本的访问控制。请注意,如果我使用 TLS 身份验证部署 Istio,我可以使用服务帐户并配置安全访问控制,但为了简单起见,我不会在这里做。


通常,恒温器服务只能通过控制服务来访问。为了确保这一点,我将部署以下清单:

deny-rule.yaml:apiVersion: "config.istio.io/v1alpha2"kind: deniermetadata:  name: denyhandlerspec:  status:    code: 7    message: Not allowed---apiVersion: "config.istio.io/v1alpha2"kind: checknothingmetadata:  name: denyrequestspec:---apiVersion: "config.istio.io/v1alpha2"kind: rulemetadata:  name: denytempspec:  match: source.labels["function"] != "control" && request.path != "/healthz" && destination.labels["function"] == "thermostat"  actions:  - handler: denyhandler.denier    instances: [ denyrequest.checknothing ]
kubectl apply -f manifests/deny-rule.yaml


我所做的是阻止任何不是来自恒温器服务的控制功能的请求(除非请求是 Kubernetes 使用的 /healthz 路径, 以检查服务是否活着)。
我们可以通过执行以下操作来确保规则的工作:


$ kubeless function call controlTemperature measured: 5 degrees. Action: Increasing!$ kubeless function call thermostatERRO[0000] FATA[0000] PERMISSION_DENIED:denyhandler.denier.default:Not allowed (get services thermostat:http)


请注意,此规则不保护恒温器服务不受群集用户的控制,并具有创建 pod 的权限。这些用户中的任何一个都可以创建一个 label 是 function=control 的 pod,它将能够访问恒温器服务。为了正确地保护此服务,我应该使用安全访问控制,并指派一个 serviceAccountName(其他用户不能使用)到 controldeployment。


7. 准备好了么?

我刚刚介绍了 Kubeless 和 Istio 的一些基本功能,但是现在你应该可以使用这两种工具来启动 service mesh 了。下一步是使用服务帐户并设置具有安全访问控制的群集。这样我就可以为这些功能提供更严密的安全性。



除此之外,还有很多功能可以处理,例如,添加监控和指标,自定义路由,自动扩缩容...想浏览更多信息,请看 Istio 和 Kubeless 的网站和文档。



原文地址:https://engineering.bitnami.com/articles/serverless-service-mesh-with-kubeless-and-istio.html