Ambassador和Istio:边缘代理和服务网格

Istio小数 发表了文章 • 0 个评论 • 10 次浏览 • 3 小时前 • 来自相关话题

 作者:Richard Li

翻译:王斌


原文:Ambassador and Istio: Edge proxy and service mesh




Ambassador(https://www.getambassador.io)是一个 Kubernetes 原生的微服务 API 网关,它部署在网络边缘,将传入网络的流量路由到相应的内部服务(也被称为“南北”流量)。Istio 是微服务的服务网格,旨在将L7的可观察性、路由和弹性加入到从服务到服务的流量中(也被称为“东西”流量)。 Istio 和 Ambassador底层都使用了 Envoy。

Ambassador 和 Istio 可以一起部署在 Kubernetes 上。在这种部署方式下,来自集群外部的入站流量首先会经过 Ambassador,再由 Ambassador将流量路由到 Istio。Ambassador 主要处理认证、边缘路由、TLS终结,以及一些传统的边缘功能。

这种部署方式能让运维人员得到一个高性能、现代化的边缘服务(Ambassador)与最先进的服务网格(Istio)相结合的网络。虽然 Istio 本身就有一个基本入口控制器,但其功能非常有限,并且不支持身份验证以及 Ambassador所拥有的许多功能。







Ambassador和 Istio 协同工作

要让 Ambassador 与 Istio 协同工作其实很简单,我们以 Istio 的bookinfo示例来举个例子:





1. 首先,在 Kubernetes 上安装 Istio。

参考指南:https://istio.io/docs/setup/ku ... .html

2. 然后,安装 Bookinfo 示例应用。

参考指南:https://istio.io/docs/guides/bookinfo.html

3. 验证示例是否按预期正常工作。




Bookinfo 示例默认使用的是 Istio 的入口控制器,要使用 Ambassador,我们还需要进行以下操作:

1. 安装Ambassador。

参考指南:https://www.getambassador.io/u ... arted

2. 更新 bookinfo.yaml 清单以包含必要的Ambassador注解,操作如下:


apiVersion: v1
kind: Service
metadata:
 name: productpage
 labels:
   app: productpage
 annotations:
   getambassador.io/config: |
      ---
     apiVersion: ambassador/v0
     kind: Mapping
     name: productpage_mapping
     prefix: /productpage/
     rewrite: /productpage
     service: productpage:9080
spec:
 ports:
 - port: 9080
   name: http
 selector:
   app: productpage


输入kubectl delete ingress gateway命令,这将会删除bookinfo.yaml 清单中的入口控制器。此步骤为可选。




访问$AMBASSADOR_IP/productpage/,测试 Ambassador 是否已经起作用。可以通过 kubectl get services ambassador 命令来获取 Ambassador 的实际IP地址。







Sidecar注入

新版本的 Istio 支持 Kubernetes 初始化程序自动注入Istio Sidecar。有了Ambassador,你不再需要注入Istio Sidecar,因为 Ambassador 的 Envoy 实例将自动路由到相应的服务。如果你正在使用的是自动Sidecar注入方式,那么需要将 Istio 配置成不要自动为 Ambassador pods 注入Sidecar。具体操作方法可以参阅这份说明文档。

文档链接:https://istio.io/docs/setup/ku ... tions


点击阅读原文,即可查看文档



  查看全部
 作者:Richard Li

翻译:王斌


原文:Ambassador and Istio: Edge proxy and service mesh




Ambassador(https://www.getambassador.io)是一个 Kubernetes 原生的微服务 API 网关,它部署在网络边缘,将传入网络的流量路由到相应的内部服务(也被称为“南北”流量)。Istio 是微服务的服务网格,旨在将L7的可观察性、路由和弹性加入到从服务到服务的流量中(也被称为“东西”流量)。 Istio 和 Ambassador底层都使用了 Envoy。

Ambassador 和 Istio 可以一起部署在 Kubernetes 上。在这种部署方式下,来自集群外部的入站流量首先会经过 Ambassador,再由 Ambassador将流量路由到 Istio。Ambassador 主要处理认证、边缘路由、TLS终结,以及一些传统的边缘功能。

这种部署方式能让运维人员得到一个高性能、现代化的边缘服务(Ambassador)与最先进的服务网格(Istio)相结合的网络。虽然 Istio 本身就有一个基本入口控制器,但其功能非常有限,并且不支持身份验证以及 Ambassador所拥有的许多功能。







Ambassador和 Istio 协同工作

要让 Ambassador 与 Istio 协同工作其实很简单,我们以 Istio 的bookinfo示例来举个例子:





1. 首先,在 Kubernetes 上安装 Istio。

参考指南:https://istio.io/docs/setup/ku ... .html

2. 然后,安装 Bookinfo 示例应用。

参考指南:https://istio.io/docs/guides/bookinfo.html

3. 验证示例是否按预期正常工作。




Bookinfo 示例默认使用的是 Istio 的入口控制器,要使用 Ambassador,我们还需要进行以下操作:

1. 安装Ambassador。

参考指南:https://www.getambassador.io/u ... arted

2. 更新 bookinfo.yaml 清单以包含必要的Ambassador注解,操作如下:


apiVersion: v1
kind: Service
metadata:
 name: productpage
 labels:
   app: productpage
 annotations:
   getambassador.io/config: |
      ---
     apiVersion: ambassador/v0
     kind: Mapping
     name: productpage_mapping
     prefix: /productpage/
     rewrite: /productpage
     service: productpage:9080
spec:
 ports:
 - port: 9080
   name: http
 selector:
   app: productpage


输入kubectl delete ingress gateway命令,这将会删除bookinfo.yaml 清单中的入口控制器。此步骤为可选。




访问$AMBASSADOR_IP/productpage/,测试 Ambassador 是否已经起作用。可以通过 kubectl get services ambassador 命令来获取 Ambassador 的实际IP地址。







Sidecar注入

新版本的 Istio 支持 Kubernetes 初始化程序自动注入Istio Sidecar。有了Ambassador,你不再需要注入Istio Sidecar,因为 Ambassador 的 Envoy 实例将自动路由到相应的服务。如果你正在使用的是自动Sidecar注入方式,那么需要将 Istio 配置成不要自动为 Ambassador pods 注入Sidecar。具体操作方法可以参阅这份说明文档。

文档链接:https://istio.io/docs/setup/ku ... tions


点击阅读原文,即可查看文档



 

专题 | A Service Mesh for Kubernetes第3期:DogFood环境,Ingress和Edge路由

Linkerd小数 发表了文章 • 0 个评论 • 16 次浏览 • 22 小时前 • 来自相关话题

 概述

在这篇文章中,我们将向您展示如何使用Linkerd实现的Service Mesh来处理Kubernetes上的入口流量,在Service Mesh中的每个实例上分发流量。我们还将通过一个完整的例子来介绍Linkerd的高级路由功能:如何将特定的请求路由到较新版本的应用实例上,比如用于内部测试的、预发布的应用版本。

这篇文章是关于使用Linkerd作为到Kubernetes网络流量的入口点。 从0.9.1开始,Linkerd直接支持Kubernetes的Ingress资源,这对于本文中的一些用例来说是一个可替代的,也是更简单的起点。

注意: 这是关于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来捕获top-line的服务指标,在服务中透明地添加TLS以及执行蓝绿发布。这些文章展示了如Kubernetes这样的环境中如何使用Linkerd作为Service Mesh的组件,为内部服务到服务调用中添加了一层弹性和性能的保障,在本篇文章中,我们将这个模型扩展到入口路由。

虽然这篇文章以Kubernetes为例,但我们不会使用Kubernetes内置的Ingress资源对象。虽然Ingress提供了一种便捷的基于宿主机和基本路径的路由方法,但在本文撰写时,Kubernetes Ingress的功能是相当有限的。在下面的例子中,我们将远远超出Ingress提供的范围。



1、发布Linkerd Service Mesh

从以前文章中基本的Linkerd Service Mesh配置开始,我们进行两个更改来支持Ingress:我们将修改Linkerd的配置用以添加一个额外的逻辑路由器,我们在Kubernetes Service资源对象中调整VIP在Linkerd中的范围。

在Linkerd的实例提供了一个新的逻辑路由器,用于处理入口流量并将其路由到相应的服务:
yaml routers: - protocol: http  label: ingress  dtab: |    /srv                    => /#/io.l5d.k8s/default/http ;    /domain/world/hello/www => /srv/hello ;    /domain/world/hello/api => /srv/api ;    /host                  => /$/io.buoyant.http.domainToPathPfx/domain ;    /svc                    => /host ;  interpreter:    kind: default    transformers:    - kind: io.l5d.k8s.daemonset      namespace: default      port: incoming      service: l5d  servers:  - port: 4142    ip: 0.0.0.0在这个配置中,我们使用Linkerd的路由语法,dtabs将请求从域名传递到服务——在这种情况下从api.hello.world传递到api服务,从www.hello.world到hello服务。为了简单起见,我们已经为每个域添加了一个规则,但是对于更复杂的设置,也可以轻松地生成映射规则。

我们已经将这个入口路由器添加到每个Linkerd实例中 - 以真正Service Mesh的方式,我们将在这些实例中完全分配入口流量,使得应用不存在单点故障。

我们还需要修改Kubernetes Service对象,以在端口80上用非入口VIP替换出口的VIP——这将允许我们直接将出口流量发送到Linkerd的Service Mesh中,主要是用于调试的目的,因为这个流量在到达Linkerd之前不会被审查(在下一步,我们将解决这个问题)。

对Kubernetes Service修改如下:
apiVersion: v1 kind: Service metadata:  name: l5d spec:  selector:    app: l5d  type: LoadBalancer  ports:  - name: ingress    port: 80    targetPort: 4142  - name: incoming    port: 4141  - name: admin    port: 9990
以上所有的修改都可以通过简单运行一个命令就能生效,细节请查看:
$ kubectl apply -f https://raw.githubusercontent. ... s.yml





2、部署服务

对于此例中的Service,我们将使用早先发布的博客使用到的例子hello and world configs,并且我们会添加两个新的service:一个api service,其用来调用hello和world,还有world service的新版本:world-v2,其将会返回一个“earth”而非“world”——我们扩大黑客团队已经向我们保证,他们的A/B测试显示这一变化将使参与度提高10倍。

下面的命令将会把hello world services部署在default命名空间下。这些应用依赖于Kubernetes downward API提供的节点名来发现Linkerd。为了检查你的集群是否支持节点名,你可以运行该测试任务:k
ubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/node-name-test.yml 
然后看它的日志信息:kubectl logs node-name-test如果你看到了IP,那就非常棒,接着使用如下命令部署hello world应用:$ kubectl apply -f https://raw.githubusercontent. ... d.yml $ kubectl apply -f https://raw.githubusercontent. ... i.yml $ kubectl apply -f https://raw.githubusercontent. ... 2.yml如果你看到的是“server can’t find…”这样的报错信息,请部署hello-world遗留版本,该版本依赖于hostIP而不是节点名:$ kubectl apply -f https://raw.githubusercontent. ... y.yml $ kubectl apply -f https://raw.githubusercontent. ... y.yml $ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/world-v2.yml 
 
这时我们应该能够通过入口Kubernetes VIP发送流量来测试设备,在没有使用DNS的情况下,我们将在请求中手动设置一个Host Header:
$ INGRESS_LB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}") $ curl -s -H "Host: www.hello.world" $INGRESS_LB Hello (10.0.5.7) world (10.0.4.7)!! $ curl -s -H "Host: api.hello.world" $INGRESS_LB {"api_result":"api (10.0.3.6) Hello (10.0.5.4) world (10.0.1.5)!!"}
或者如果集群不支持外部负载均衡器,请使用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}')成功了!
我们已经将Linkerd设置为入口控制器,并且我们已经使用它将不同域中收到的请求路由到不同的服务。正如您所见,生产流量正冲击world-v1服务——我们还没准备要将world-v2推出。



3、Nginx层

至此ingress已经可以使用了。但还不能用于生产环境中。因为我们的ingress路由器不能将header从请求中提取出来。这就意味着我们不能接收包含header的外部请求。例如,Linkerd允许设置15d-dtab头部以按请求应用路由规则,这对于新服务的临时分级是一个有用的功能,但这可能不适合于来自外部的请求。

例如,我们可以使用15d-dtab请求头覆盖路由逻辑来使用world-v2而不是world-v1来服务外部请求:$ curl -H "Host: www.hello.world" -H "l5d-dtab: /host/world => /srv/world-v2;" $INGRESS_LB Hello (10.100.4.3) earth (10.100.5.5)!!当earth作为响应,意味着这是world-v2服务的结果。

我们通过添加nginx来解决这个问题(或者其他问题如服务静态文件)。如果我们在代理请求到linkerd ingress路由之前配置nginx来提取输入的header,我们将会两全其美:有能力安全处理外部流量的ingress层并且Linkerd做动态的、基于服务的路由。

让我们添加nginx到集群中。使用this nginx conf来配置它。我们将在www.hello.world和api.hello.world虚拟服务器下使用proxy_pass命令来发送请求给Linkerd实例,并且我们将使用Headers More模块提供的more_clear_input_headers命令来提取linkerd's context headers。

对于linkerd 0.9.0,我们可以通过在ingress路由器服务器上设置clearContext:true来清除输入的15d-*请求头。然而,nginx有许多我们可以使用到的特性,所以使用nginx连接Linkerd很有价值。

我们已经发布了一个安装了Headers More模块的Docker镜像:buoyantio/nginx:1.11.5。
我们用该配置部署这个镜像:
$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/nginx.yml 
 
在等待外部IP出现后,我们可以通过点击nginx.conf中的简单测试端点来测试nginx是否启动:$ INGRESS_LB=$(kubectl get svc nginx -o jsonpath="{.status.loadBalancer.ingress[0].*}") $ curl $INGRESS_LB 200 OK
或者如果集群的外部负载均衡器不可用,使用
hostIP:$ INGRESS_LB=$(kubectl get po -l app=nginx -o jsonpath="{.items[0].status.hostIP}"):$(kubectl get svc nginx -o 'jsonpath={.spec.ports[0].nodePort}')
 
我们现在应用已经可以通过nginx发送流量给我们的服务了:$ curl -s -H "Host: www.hello.world" $INGRESS_LB Hello (10.0.5.7) world (10.0.4.7)!! $ curl -s -H "Host: api.hello.world" $INGRESS_LB {"api_result":"api (10.0.3.6) Hello (10.0.5.4) world (10.0.1.5)!!"}
 
最后,让我们尝试直接与world-v2服务通信:$ curl -H "Host: www.hello.world" -H "l5d-dtab: /host/world => /srv/world-v2;" $INGRESS_LB Hello (10.196.1.8) world (10.196.2.13)!!没有earth,Nginx正在净化外部流量。



4、简述Dogfood

好了,到了重点部分:让我们使用world-v1服务来配置dogfood的环境,不过这仅针对一些流量。

为简化问题,我们只关注设置了特殊cookiespecial_employee_cookie的流量。在实践中,你可能想要比这更复杂的情况如验证它,要求它来自公司网络IP范围等。

用nginx和Linkerd安装,完成这个相当简单。我们将会使用nginx来检查该cookie是否存在,为linkerd设置一个dtab覆盖头来调整其路由。有关的nginx配置如下:
if ($cookie_special_employee_cookie ~* "dogfood") {  set $xheader "/host/world => /srv/world-v2;"; } proxy_set_header 'l5d-dtab' $xheader;
如果你已经按以上步骤做了,被部署的nginx已经包含了这个配置。我们可以用如下来进行测试:
$ curl -H "Host: www.hello.world" --cookie "special_employee_cookie=dogfood" $INGRESS_LB Hello (10.196.1.8) earth (10.196.2.13)!!
系统已经工作了。当这个cookie被设置了,你将置于dogfood模式下。如果没有它,你将置于常规生产流量模式。最重要的是,dogfood模式可以包含在service stack到处出现的service的新版本,甚至很多层——只要服务代码转发Linkerd的上下文头,Linkerd服务网格将负责其余部分。



结束语

在本文中,我们看到了如何使用Linkerd给Kubernetes集群提供有力而又灵活的入口。我们已经演示了如何部署名义上的生产就绪设置,使用Linkerd进行服务路由。我们已经演示了如何使用Linkerd的一些高级路由功能来将流量服务拓扑从部署拓扑结构中分离出来,从而允许创建dogfood环境而不需要单独的集群或部署时间复杂性。 查看全部
 概述

在这篇文章中,我们将向您展示如何使用Linkerd实现的Service Mesh来处理Kubernetes上的入口流量,在Service Mesh中的每个实例上分发流量。我们还将通过一个完整的例子来介绍Linkerd的高级路由功能:如何将特定的请求路由到较新版本的应用实例上,比如用于内部测试的、预发布的应用版本。

这篇文章是关于使用Linkerd作为到Kubernetes网络流量的入口点。 从0.9.1开始,Linkerd直接支持Kubernetes的Ingress资源,这对于本文中的一些用例来说是一个可替代的,也是更简单的起点。

注意: 这是关于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来捕获top-line的服务指标,在服务中透明地添加TLS以及执行蓝绿发布。这些文章展示了如Kubernetes这样的环境中如何使用Linkerd作为Service Mesh的组件,为内部服务到服务调用中添加了一层弹性和性能的保障,在本篇文章中,我们将这个模型扩展到入口路由。

虽然这篇文章以Kubernetes为例,但我们不会使用Kubernetes内置的Ingress资源对象。虽然Ingress提供了一种便捷的基于宿主机和基本路径的路由方法,但在本文撰写时,Kubernetes Ingress的功能是相当有限的。在下面的例子中,我们将远远超出Ingress提供的范围。



1、发布Linkerd Service Mesh

从以前文章中基本的Linkerd Service Mesh配置开始,我们进行两个更改来支持Ingress:我们将修改Linkerd的配置用以添加一个额外的逻辑路由器,我们在Kubernetes Service资源对象中调整VIP在Linkerd中的范围。

在Linkerd的实例提供了一个新的逻辑路由器,用于处理入口流量并将其路由到相应的服务:
yaml routers: - protocol: http  label: ingress  dtab: |    /srv                    => /#/io.l5d.k8s/default/http ;    /domain/world/hello/www => /srv/hello ;    /domain/world/hello/api => /srv/api ;    /host                  => /$/io.buoyant.http.domainToPathPfx/domain ;    /svc                    => /host ;  interpreter:    kind: default    transformers:    - kind: io.l5d.k8s.daemonset      namespace: default      port: incoming      service: l5d  servers:  - port: 4142    ip: 0.0.0.0在这个配置中,我们使用Linkerd的路由语法,dtabs将请求从域名传递到服务——在这种情况下从api.hello.world传递到api服务,从www.hello.world到hello服务。为了简单起见,我们已经为每个域添加了一个规则,但是对于更复杂的设置,也可以轻松地生成映射规则。

我们已经将这个入口路由器添加到每个Linkerd实例中 - 以真正Service Mesh的方式,我们将在这些实例中完全分配入口流量,使得应用不存在单点故障。

我们还需要修改Kubernetes Service对象,以在端口80上用非入口VIP替换出口的VIP——这将允许我们直接将出口流量发送到Linkerd的Service Mesh中,主要是用于调试的目的,因为这个流量在到达Linkerd之前不会被审查(在下一步,我们将解决这个问题)。

对Kubernetes Service修改如下:
apiVersion: v1 kind: Service metadata:  name: l5d spec:  selector:    app: l5d  type: LoadBalancer  ports:  - name: ingress    port: 80    targetPort: 4142  - name: incoming    port: 4141  - name: admin    port: 9990
以上所有的修改都可以通过简单运行一个命令就能生效,细节请查看:
$ kubectl apply -f https://raw.githubusercontent. ... s.yml





2、部署服务

对于此例中的Service,我们将使用早先发布的博客使用到的例子hello and world configs,并且我们会添加两个新的service:一个api service,其用来调用hello和world,还有world service的新版本:world-v2,其将会返回一个“earth”而非“world”——我们扩大黑客团队已经向我们保证,他们的A/B测试显示这一变化将使参与度提高10倍。

下面的命令将会把hello world services部署在default命名空间下。这些应用依赖于Kubernetes downward API提供的节点名来发现Linkerd。为了检查你的集群是否支持节点名,你可以运行该测试任务:k
ubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/node-name-test.yml 
然后看它的日志信息:kubectl logs node-name-test如果你看到了IP,那就非常棒,接着使用如下命令部署hello world应用:$ kubectl apply -f https://raw.githubusercontent. ... d.yml $ kubectl apply -f https://raw.githubusercontent. ... i.yml $ kubectl apply -f https://raw.githubusercontent. ... 2.yml如果你看到的是“server can’t find…”这样的报错信息,请部署hello-world遗留版本,该版本依赖于hostIP而不是节点名:$ kubectl apply -f https://raw.githubusercontent. ... y.yml $ kubectl apply -f https://raw.githubusercontent. ... y.yml $ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/world-v2.yml 
 
这时我们应该能够通过入口Kubernetes VIP发送流量来测试设备,在没有使用DNS的情况下,我们将在请求中手动设置一个Host Header:
$ INGRESS_LB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}") $ curl -s -H "Host: www.hello.world" $INGRESS_LB Hello (10.0.5.7) world (10.0.4.7)!! $ curl -s -H "Host: api.hello.world" $INGRESS_LB {"api_result":"api (10.0.3.6) Hello (10.0.5.4) world (10.0.1.5)!!"}
或者如果集群不支持外部负载均衡器,请使用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}')成功了!
我们已经将Linkerd设置为入口控制器,并且我们已经使用它将不同域中收到的请求路由到不同的服务。正如您所见,生产流量正冲击world-v1服务——我们还没准备要将world-v2推出。



3、Nginx层

至此ingress已经可以使用了。但还不能用于生产环境中。因为我们的ingress路由器不能将header从请求中提取出来。这就意味着我们不能接收包含header的外部请求。例如,Linkerd允许设置15d-dtab头部以按请求应用路由规则,这对于新服务的临时分级是一个有用的功能,但这可能不适合于来自外部的请求。

例如,我们可以使用15d-dtab请求头覆盖路由逻辑来使用world-v2而不是world-v1来服务外部请求:$ curl -H "Host: www.hello.world" -H "l5d-dtab: /host/world => /srv/world-v2;" $INGRESS_LB Hello (10.100.4.3) earth (10.100.5.5)!!当earth作为响应,意味着这是world-v2服务的结果。

我们通过添加nginx来解决这个问题(或者其他问题如服务静态文件)。如果我们在代理请求到linkerd ingress路由之前配置nginx来提取输入的header,我们将会两全其美:有能力安全处理外部流量的ingress层并且Linkerd做动态的、基于服务的路由。

让我们添加nginx到集群中。使用this nginx conf来配置它。我们将在www.hello.world和api.hello.world虚拟服务器下使用proxy_pass命令来发送请求给Linkerd实例,并且我们将使用Headers More模块提供的more_clear_input_headers命令来提取linkerd's context headers。

对于linkerd 0.9.0,我们可以通过在ingress路由器服务器上设置clearContext:true来清除输入的15d-*请求头。然而,nginx有许多我们可以使用到的特性,所以使用nginx连接Linkerd很有价值。

我们已经发布了一个安装了Headers More模块的Docker镜像:buoyantio/nginx:1.11.5。
我们用该配置部署这个镜像:
$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/nginx.yml 
 
在等待外部IP出现后,我们可以通过点击nginx.conf中的简单测试端点来测试nginx是否启动:$ INGRESS_LB=$(kubectl get svc nginx -o jsonpath="{.status.loadBalancer.ingress[0].*}") $ curl $INGRESS_LB 200 OK
或者如果集群的外部负载均衡器不可用,使用
hostIP:$ INGRESS_LB=$(kubectl get po -l app=nginx -o jsonpath="{.items[0].status.hostIP}"):$(kubectl get svc nginx -o 'jsonpath={.spec.ports[0].nodePort}')
 
我们现在应用已经可以通过nginx发送流量给我们的服务了:$ curl -s -H "Host: www.hello.world" $INGRESS_LB Hello (10.0.5.7) world (10.0.4.7)!! $ curl -s -H "Host: api.hello.world" $INGRESS_LB {"api_result":"api (10.0.3.6) Hello (10.0.5.4) world (10.0.1.5)!!"}
 
最后,让我们尝试直接与world-v2服务通信:$ curl -H "Host: www.hello.world" -H "l5d-dtab: /host/world => /srv/world-v2;" $INGRESS_LB Hello (10.196.1.8) world (10.196.2.13)!!没有earth,Nginx正在净化外部流量。



4、简述Dogfood

好了,到了重点部分:让我们使用world-v1服务来配置dogfood的环境,不过这仅针对一些流量。

为简化问题,我们只关注设置了特殊cookiespecial_employee_cookie的流量。在实践中,你可能想要比这更复杂的情况如验证它,要求它来自公司网络IP范围等。

用nginx和Linkerd安装,完成这个相当简单。我们将会使用nginx来检查该cookie是否存在,为linkerd设置一个dtab覆盖头来调整其路由。有关的nginx配置如下:
if ($cookie_special_employee_cookie ~* "dogfood") {  set $xheader "/host/world => /srv/world-v2;"; } proxy_set_header 'l5d-dtab' $xheader;
如果你已经按以上步骤做了,被部署的nginx已经包含了这个配置。我们可以用如下来进行测试:
$ curl -H "Host: www.hello.world" --cookie "special_employee_cookie=dogfood" $INGRESS_LB Hello (10.196.1.8) earth (10.196.2.13)!!
系统已经工作了。当这个cookie被设置了,你将置于dogfood模式下。如果没有它,你将置于常规生产流量模式。最重要的是,dogfood模式可以包含在service stack到处出现的service的新版本,甚至很多层——只要服务代码转发Linkerd的上下文头,Linkerd服务网格将负责其余部分。



结束语

在本文中,我们看到了如何使用Linkerd给Kubernetes集群提供有力而又灵活的入口。我们已经演示了如何部署名义上的生产就绪设置,使用Linkerd进行服务路由。我们已经演示了如何使用Linkerd的一些高级路由功能来将流量服务拓扑从部署拓扑结构中分离出来,从而允许创建dogfood环境而不需要单独的集群或部署时间复杂性。

3种Ansible Roles分步指南,教你如何使用Weave Scope探索微服务通信和服务网格

Istio小数 发表了文章 • 0 个评论 • 72 次浏览 • 6 天前 • 来自相关话题

 
 作者:Roger CARHUATOCTO 

翻译:张晔

原文:Using Weave Scope to explore Microservices Communication and Service Mesh 

原文地址:https://holisticsecurity.io/20 ... erral



如果你正在使用ESB、消息代理、BPMS、SOA或微服务,就会注意到,你正在以不同的方式解决相同的独立应用程序问题,因为它们都是不同类型的分布式应用程序。这些问题是:

用户管理、认证和授权

日志记录、调试、监视和报警

集群、高可用性、负载均衡等


什么是服务网格

服务网格是另一种类型的分布式应用程序,在这其中服务、微服务或者APIs都是相互关联的。







基于容器化和编排平台的服务网格

一般来说,基于微服务和/或APIs的服务网格是由多个容器来部署的,这些容器是用Kubernetes 来编排的。在这种情况下,我们需要面对新的挑战,比如临时基础设施、零信任网络、网络分割或者采用新的方法来测试、监控、部署、操作等等。这就是我们所说的DevOps。



容器部署模式

与 EIP (企业集成模式)和软件设计模式一样,在容器化的平台上部署服务网格也有一定的模式。Google、Microsoft、Netflix 等建议使用一些模式来实现上述问题的解决方案。


例如,Google解释了三种很好的模式:
 
Sidecar模式Ambassador模式适配器模式

它们都支持基于容器的服务网格的构建。欲知详情,请阅读:

《基于容器的分布式系统的设计模式》by 布伦丹·伯恩斯&大卫·奥本海默

PDF下载:https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/45406.pdf 



什么是Istio

摘录自 Istio.io :

Istio是一个开放的平台,提供了一种统一的方式来连接、管理微服务,保证微服务安全。Istio支持管理微服务之间的交通流、执行访问策略和聚合遥测数据,这些都不需要对微服务代码进行更改。

Istio 给你:
自动负载平衡HTTP、gRPC WebSocket,TCP流量;
 
细粒度控制的交通行为与丰富的路由规则,重试,故障转移,故障注入;
 
可插入策略层和配置API支持访问控制,速度和配额限制;
 
自动度量、日志和跟踪所有流量在一个集群,包括集群入口和出口;


在集群中的服务之间,通过强身份断言,实现服务对服务的安全认证。







为什么使用Istio

    摘录自 Istio.io :

Istio解决了开发人员和运维人员在向分布式微服务架构过渡时所面临的诸多挑战。服务网格作为一个术语,通常用于描述组成此类应用程序的微服务网络和它们之间的交互。随着服务网格的规模和复杂性的增长,它会变得越来越难以理解和管理。它的需求包括发现、负载均衡、故障恢复、度量和监控,以及更复杂的操作需求,如A/B测试、canary发布、速率限制、访问控制和端到端验证。


Istio提供了一个完整的解决方案,通过行为洞察和对整个服务网格的操作控制,来满足微服务应用程序的不同需求。它在服务网络中统一提供了许多关键功能:
 
交通管理。控制服务之间的流量和API调用,使调用更加可靠,并使网络在面对不利条件时更加健壮。
 
可观测性。了解服务之间的依赖关系和它们之间的流量之间的关系,提供快速识别问题的能力。
 
政策执行。将组织策略应用于服务之间的交互,确保执行访问策略,并且在用户中公平地分配资源。策略更改不必通过更改应用程序代码来实现,而是通过配置网格。
 
标识和安全服务。在网格中提供可验证身份的服务,并提供保护服务流量的能力,因为它在不同程度的trustability网络中流动。


基于容器的服务网格与Istio

为了轻松得到一个极简 OpenShift 集群,我创建了3个 Ansible Roles--Weave Scope 、Istio 和 BookInfo 应用(基于容器的 API 和微服务) 来理解我们必须面对的挑战。3个 Ansible Roles是:

1. Minishift Ansible Role

    地址:https://github.com/chilcano/ansible-role-minishift

在虚拟机中通过 Minishift 获得 OpenShift 集群。


2. Weave Scope Ansible Role

   地址:https://github.com/chilcano/an ... scope

在 OpenShift 中部署本地运行的 Weave Scope 应用。


3. Istio Ansible Role

    地址:https://github.com/chilcano/ansible-role-istio

在本地运行的 OpenShift 中部署和配置 Istio,部署 BookInfo 应用,并注入 Sidecar 代理(Envoy Proxy)。


我还创建了一些示例,可以测试并快速尝试上述角色的环境。

Weave Scope 将在这里发挥重要作用,它能够对整个基于容器的服务网格进行监控、可视化、故障诊断和轻松管理。

一旦完成了分步指南,你将获得下一个:

(操作步骤详见:https://github.com/chilcano/an ... urity)






































 希望这篇文章对你能有所帮助。 查看全部

微信图片_20180116164346.jpg

 
 作者:Roger CARHUATOCTO 

翻译:张晔

原文:Using Weave Scope to explore Microservices Communication and Service Mesh 

原文地址:https://holisticsecurity.io/20 ... erral



如果你正在使用ESB、消息代理、BPMS、SOA或微服务,就会注意到,你正在以不同的方式解决相同的独立应用程序问题,因为它们都是不同类型的分布式应用程序。这些问题是:

用户管理、认证和授权

日志记录、调试、监视和报警

集群、高可用性、负载均衡等


什么是服务网格

服务网格是另一种类型的分布式应用程序,在这其中服务、微服务或者APIs都是相互关联的。

1.png



基于容器化和编排平台的服务网格

一般来说,基于微服务和/或APIs的服务网格是由多个容器来部署的,这些容器是用Kubernetes 来编排的。在这种情况下,我们需要面对新的挑战,比如临时基础设施、零信任网络、网络分割或者采用新的方法来测试、监控、部署、操作等等。这就是我们所说的DevOps。



容器部署模式

与 EIP (企业集成模式)和软件设计模式一样,在容器化的平台上部署服务网格也有一定的模式。Google、Microsoft、Netflix 等建议使用一些模式来实现上述问题的解决方案。


例如,Google解释了三种很好的模式:
 
  • Sidecar模式
  • Ambassador模式
  • 适配器模式


它们都支持基于容器的服务网格的构建。欲知详情,请阅读:

《基于容器的分布式系统的设计模式》by 布伦丹·伯恩斯&大卫·奥本海默

PDF下载:https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/45406.pdf 



什么是Istio

摘录自 Istio.io :

Istio是一个开放的平台,提供了一种统一的方式来连接、管理微服务,保证微服务安全。Istio支持管理微服务之间的交通流、执行访问策略和聚合遥测数据,这些都不需要对微服务代码进行更改。

Istio 给你:
  • 自动负载平衡HTTP、gRPC WebSocket,TCP流量;

 
  • 细粒度控制的交通行为与丰富的路由规则,重试,故障转移,故障注入;

 
  • 可插入策略层和配置API支持访问控制,速度和配额限制;

 
  • 自动度量、日志和跟踪所有流量在一个集群,包括集群入口和出口;



在集群中的服务之间,通过强身份断言,实现服务对服务的安全认证。

2.png



为什么使用Istio

    摘录自 Istio.io :

Istio解决了开发人员和运维人员在向分布式微服务架构过渡时所面临的诸多挑战。服务网格作为一个术语,通常用于描述组成此类应用程序的微服务网络和它们之间的交互。随着服务网格的规模和复杂性的增长,它会变得越来越难以理解和管理。它的需求包括发现、负载均衡、故障恢复、度量和监控,以及更复杂的操作需求,如A/B测试、canary发布、速率限制、访问控制和端到端验证。


Istio提供了一个完整的解决方案,通过行为洞察和对整个服务网格的操作控制,来满足微服务应用程序的不同需求。它在服务网络中统一提供了许多关键功能:
 
  • 交通管理。控制服务之间的流量和API调用,使调用更加可靠,并使网络在面对不利条件时更加健壮。

 
  • 可观测性。了解服务之间的依赖关系和它们之间的流量之间的关系,提供快速识别问题的能力。

 
  • 政策执行。将组织策略应用于服务之间的交互,确保执行访问策略,并且在用户中公平地分配资源。策略更改不必通过更改应用程序代码来实现,而是通过配置网格。

 
  • 标识和安全服务。在网格中提供可验证身份的服务,并提供保护服务流量的能力,因为它在不同程度的trustability网络中流动。



基于容器的服务网格与Istio

为了轻松得到一个极简 OpenShift 集群,我创建了3个 Ansible Roles--Weave Scope 、Istio 和 BookInfo 应用(基于容器的 API 和微服务) 来理解我们必须面对的挑战。3个 Ansible Roles是:

1. Minishift Ansible Role

    地址:https://github.com/chilcano/ansible-role-minishift

在虚拟机中通过 Minishift 获得 OpenShift 集群。


2. Weave Scope Ansible Role

   地址:https://github.com/chilcano/an ... scope

在 OpenShift 中部署本地运行的 Weave Scope 应用。


3. Istio Ansible Role

    地址:https://github.com/chilcano/ansible-role-istio

在本地运行的 OpenShift 中部署和配置 Istio,部署 BookInfo 应用,并注入 Sidecar 代理(Envoy Proxy)。


我还创建了一些示例,可以测试并快速尝试上述角色的环境。

Weave Scope 将在这里发挥重要作用,它能够对整个基于容器的服务网格进行监控、可视化、故障诊断和轻松管理。

一旦完成了分步指南,你将获得下一个:

(操作步骤详见:https://github.com/chilcano/an ... urity



3.png


4.png


5.png


6.png


7.png


8.png


9.png


 希望这篇文章对你能有所帮助。

开发环境下,如何使用Kubernete DNS host?

回复

交流问答dcalsky 发起了问题 • 1 人关注 • 0 个回复 • 69 次浏览 • 2018-01-13 22:55 • 来自相关话题

万字雄文讲透现代网络负载均衡和代理技术,终于弄懂负载均衡那点事

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

作者:Matt Klein

译者:杨泽

原题:Introduction to modern network load balancing and proxying






关于现代网络负载均衡和代理(proxy)的介绍性资料很少,这件事引起了我的注意。为什么会这样呢?构建一个可靠的分布式系统时,负载均衡是一个非常核心的概念。但可惜的是,搜索发现关于负载均衡和服务代理的内容很少。维基百科文章只包含了一些概念,没有对该主题的详细介绍,尤其是与现代微服务架构相关的。


本文试图通过对现代网络负载均衡和代理的简单介绍,来弥补这部分信息的缺乏。为了保持文章的长度,尽量将复杂的话题浓缩成简单的概述。


1什么是网络负载均衡和代理?


维基百科这样定义负载均衡:

在计算中,负载均衡可以改善在多个计算机资源(如计算机,计算机集群,网络链接,中央处理单元或磁盘驱动器)上的工作负载分布。负载均衡旨在优化资源的使用,最大吞吐量,及最小响应时间,避免任何单一资源的过载。通过使用多个组件而不是单个组件,负载均衡通过冗余来提高可靠性和可用性。负载均衡通常涉及专用软件和硬件,例如多层交换机或域名系统服务器进程。

以上定义适用于计算的各个方面,而不仅仅是网络。操作系统使用负载均衡在物理处理器之间安排任务,诸如Kubernetes之类的容器编排者使用负载均衡来计划跨计算集群的任务,网络负载均衡通过调用可用后端来平衡网络任务。以下内容仅涵盖网络负载均衡。






图 1: 网络负载均衡描述


图1展示了网络负载均衡高层次的概览。一些客户端从后端请求资源。负载均衡器位于客户端和后端之间,在更高层次执行关键任务:

服务发现:在系统中哪些后端可用?地址是多少?(换句话说,负载均衡器如何与它们通信?)

健康检查:在系统中目前哪些后端是健康的,可以接受请求?

负载均衡:用什么样的算法把独立的个人请求发给健康的后端?


在分布式系统中正确使用负载均衡会带来如下好处:

命名抽象:客户端可以通过预定义的机制来寻址负载均衡器,而不是每个客户端都需要了解每个后端(服务发现),然后将名称解析的任务委托给负载均衡器。预定义的机制包括内置库和众所周知的DNS/IP/端口地址,后面会有详细的讨论。

容错:通过健康检查和各种算法技术,负载均衡器的路由方法可以绕过坏的或者超负载的后端。这也意味着运维人员可以随时优先修复后端错误。

低成本和高性能:分布式系统网络一致性比较差。系统可能会横跨不同的网络区域。在一个区域内,网络之间通常以相对小的带宽建立的。而在不同的区域之间,网络大带宽成为常态(带宽的大小是指通过NIC使用的带宽量占路由器之间可用带宽的百分比)。智能的负载均衡可以尽可能保持区域内的请求流量,从而提高性能(低延迟)并降低整体系统成本(减少区域间的带宽和光纤)。



负载均衡器VS代理

在谈论到网络负载均衡器,Load Balancer 和 Proxy 两个术语在行业内可以互换使用。在本文中也把两者视为一致的表达。(不过,不是所有的代理都是负载均衡器,但绝大多数代理都将负载均衡作为主要功能)。


一些人会争辩说,当负载均衡器作为嵌入式客户端库的一部分实现时,这种负载均衡器并不是真正的代理。这种区分其实添加了不必要的复杂性。本文会详细讨论负载均衡器的拓扑类型,嵌入式负载均衡器是代理的一个特例,应用通过嵌入式库进行代理,嵌入式库与应用进程外的负载均衡器整体抽象是一致的。



L4(连接/会话)负载均衡

业界讨论负载均衡时,解决方式往往分为两类:L4 和 L7。指的是OSI模型的第四层和第七层。OSI模型包括传统的第四层协议(如TCP和UDP),还包含各种不同OSI层的协议。换句话说,如果 L4 TCP负载均衡器也支持 TLS 终止,这不就是 L7负载均衡器么?






图2:TCP L4 终止负载平衡

图2展示了传统的L4 TCP负载均衡器。在这种情况下,客户端与负载均衡器建立TCP连接,负载均衡器终止连接(即直接响应SYN),选择一个后端,并与后端建立新的TCP连接(即发起新的SYN)。


本节的关键是L4负载均衡器通常只在 L4 TCP / UDP连接/会话上运行。因此,负载平衡器负责操作字节,并确保来自同一会话的字节转发到同一后端。L4负载平衡器并不知道通信中的任何应用细节。这些字节可能是 HTTP,Redis,MongoDB或任何其他应用协议。


L7(应用)负载平衡

 L4负载均衡简单,能看到广泛使用。人们为什么放弃L4负载均衡,来研究L7(应用)负载均衡?以下是L4具体的案例:


两个gRPC / HTTP2 客户端通过L4负载均衡器与后端建立连接。

L4负载均衡器为每个接入的TCP连接建立一个传出的TCP连接,这样就产生了两个传入和两个传出连接。

但是,客户端A每分钟发送 1个请求(RPM),而客户端B通每秒发送50个请求(RPS)。


在上述场景中,后端选择处理客户端B请求是选择客户端A请求负载的大约3000倍。这是一个很大的问题,打破了负载均衡的目的。需要注意的是这个问题发生在任何复用,保持存活状态的协议。(复用意味着通过单个L4连接多次发送应用程序请求,保持存活就是没有活动请求时不关闭连接)。出于效率的考虑,所有现代协议都在不断发展,既要复用也要存活(创建连接通常是昂贵的,特别是用TLS进行加密连接时),所以L4负载均衡器随着时间的推移,负载失衡的情况更加明显。这个问题在L7负载均衡器中得到解决。







图3:HTTP / 2 L7终端负载均衡

图3展示了L7 HTTP/2负载平衡器。客户端与负载均衡器只建立一个 HTTP/2 TCP连接,连接两个后端。当客户端向负载均衡器发送两个HTTP/2 流时,流1被发送到后端1,流2被发送到后端2。因此,即使差别很大的请求负载的多路复用客户端也将被有效地平衡到不同的后端。这就是L7负载平衡对于现代协议的重要性所在。(L7负载平衡由于能够检查应用流量,而产生大量好处,后面会更详述)。



L7负载均衡和OSI模型

正如L4负载平衡部分所述,使用OSI模型描述负载均衡功能是有问题的。原因在于L7本身包含多个离散的负载均衡抽象层。例如,对于HTTP流量,请考虑以下子层:


可选的传输层安全性(TLS)。网络界对于TLS 属于OSI模型哪一层有争论。为了方便,我们考虑将TLS放在 L7。

物理HTTP协议(HTTP / 1或HTTP / 2)。

逻辑HTTP协议(Header、Body 和 Trailer)。

消息传递协议(gRPC,REST等)。


一个复杂的L7负载均衡器要提供与上述每个子层有关的功能。另L7负载均衡器可能只有一小部分功能属于OSI模型中L7层。简而言之,L7负载平衡器的功能远比L4类型复杂得多。(HTTP、 Redis、Kafka、MongoDB等都是应用L7 协议的例子,它们受益于L7负载均衡)。



2负载均衡器功能


在本节中将总结负载均衡器提供的高级功能,并非所有负载均衡器都提供全部功能。


服务发现

服务发现是负载平衡器确定可用后端的过程,实现的方式有很多种,一些例子包括:


静态配置文件。

DNS。

Zookeeper,Etcd,Consul等。

Envoy的通用数据平面API。


健康检查

运行状况检查是负载均衡器确定后端是否可用来为流量提供服务的过程。健康检查一般分为两类:

主动式:负载平衡器将定期发送ping(例如,对/healthcheck端点的HTTP请求)到后端,并用它来衡量健康状况。

被动式:负载均衡器从主数据流中检测健康状况。例如,如果连续出现三个连接错误,则L4负载均衡器会认为后端是不健康的。如果一行中有三个HTTP 503响应代码,则L7负载均衡器会认为后端是不健康的。



负载均衡

负载均衡器必须实际平衡负载!当给定一组健康的后端时,选择哪个后端处理请求?负载平衡算法是一个活跃的研究领域,从简单的算法(如随机选择和循环算法)到考虑可变延迟和后端负载的更复杂的算法。考虑到其性能和简单性,最流行的负载均衡算法是二节点最小请求负载均衡(power of 2 least request load balancing)。 


粘滞会话(Sticky sessions)

在某些应用中,同一会话的请求到达相同的后端是很重要的。这与缓存,临时复杂状态等有关。会话的定义各不相同,可能包括HTTP Cookie,客户端连接的配置或其他属性。许多L7负载平衡器支持会话粘连。会话粘性本质上是脆弱的(后端保存的会话可能会失效),所以在设计系统的时候减少对它们的依赖。



TLS终止

关于TLS,它在边缘服务和服务间通信方面值得肯定。因此,许多L7负载均衡器会执行大量的TLS处理,包括终止,证书验证和保存,使用SNI的证书服务等。



可观察性

正如谈话中所强调的:“可观察性,可观察性,可观察性”。网络本质上是不可靠的,负载均衡器通常负责导出统计信息,跟踪信息和记录日志,帮助运营人员找出问题所在,从而解决问题。最先进的负载平衡器可观察性输出包括数字统计,分布式跟踪和可定制的日志记录。增强的可观察性不是免费的; 负载平衡器必须做很多附加的工作来完成它。至于,负面影响,相对带来的好处,几乎不值一提。


安全性和DoS防范

特别是在边缘部署拓扑(见下文)中,负载均衡器通常实施各种安全功能,包括速率限制,身份验证和DoS防范(例如,IP地址标记和识别,缓送Tarpitting等)。



配置和控制面板

负载平衡器需要配置。在大规模部署中,这是一项重要工作。一般来说,配置负载均衡器的系统被称为“控制面板”,并且在其实现中变化很大。
 
3负载均衡器拓扑的类型

前面介绍了负载平衡器的概要,L4和L7负载平衡器之间的区别以及负载均衡器特性,接下来将转向部署负载均衡器的各种分布式系统拓扑。(以下每种拓扑均适用于L4和L7负载均衡器)。



中间代理






 
图4:中间代理负载均衡拓扑

图4所示的中间代理拓扑是大多数读者最熟悉的负载均衡一种方式。这一类包括Cisco,Juniper,F5等硬件设备; 云软件解决方案,如亚马逊的ALB和NLB以及Google的 Cloud Load Balancer ; 以及HAProxy,NGINX和Envoy等纯软件自主托管解决方案。中间代理解决方案使用简单。通常,用户通过DNS连接到负载均衡器,不需要担心其他任何事情。中间代理解决方案的特点是代理(即使是集群)是单一的故障点,也是扩展的瓶颈。中间代理通常是一个让运维变得困难的黑匣子。当问题出现时,是在客户端还是物理网络?在中间代理还是后端?这很难说。



边缘代理






图5:边缘代理负载平衡拓扑

图5所示实际上只是中间代理拓扑的一种变体,负载均衡器通过Internet访问。在这种情况下,负载均衡器通常必须提供附加的“API网关”功能,如TLS终止,速率限制,身份验证和复杂的流量路由。边缘代理的优缺点与中间代理相同。需要注意的是,在面向Internet的大型分布式系统中部署专用边缘代理通常是不可避免的。客户端通常需要使用服务所有者无法控制的任意网络库(后面会讨论嵌入式客户端库或附属代理拓扑结构不能直接在客户端上运行)通过DNS访问系统。另外,由于安全原因,希望具有单个网关,通过该网关,所有面向互联网的流量进入系统。



嵌入式客户端库






图6:通过嵌入式客户端库进行负载平衡

为了避免中间代理拓扑中固有的单点故障和扩展问题,更复杂的基础设施已经开始将负载均衡器直接嵌入到服务库中,如图6所示。支持的功能库有很大的不同,但是这个类别中最知名和最丰富的功能包括Finagle,Eureka / Ribbon / Hystrix和gRPC(松散地基于称为Stubby的内部Google系统)。基于库的解决方案的主要功能是将负载均衡器的所有功能完全分配给每个客户端,从而消除之前描述的单点故障和扩展问题。基于客户端库的解决方案的主要内容是客户端库必须每种语言调用。分布式架构正变得越来越“多语言”(多语言)。在这样的环境下,用许多不同的语言来重新实现一个非常复杂的网络库的成本会变得过高。最后,在大型服务体系结构中部署库升级可能会非常痛苦,这使得很多不同版本的库将在生产中同时运行,

综上所述,上面提到的这些库对于那些能够限制编程语言扩散并克服库升级难题的公司来说是成功的。



Sidecar代理






图7:通过sidecar代理进行负载平衡

嵌入式客户端库负载平衡器拓扑的一个变种是图7中所示的辅助代理拓扑。近年来,这种拓扑已经被普遍推广为“服务网格”(Service Mesh)。Sidecar代理背后的思路是,以跳过一个不同的过程的代价来承担轻微的延迟,嵌入式库的所有好处都可以在没有任何编程语言锁定的情况下获得。在撰写本文时,最受欢迎的sidecar代理负载平衡器是Envoy,NGINX,HAProxy和Linkerd。



负载均衡器拓扑的总结和优缺点

中间代理拓扑是最简单的负载平衡拓扑。缺点是:单点故障,伸缩瓶颈和黑箱操作。


边缘代理拓扑与中间代理类似,但通常无法避免。


嵌入式客户端库拓扑提供了最好的性能和可扩展性,但是需要在每种语言中实现该库,并跨所有服务升级库。


Sidecar代理拓扑性能比嵌入式客户端库拓扑弱,但不受任何限制。

总体而言,sidecar代理拓扑(服务网格)正在逐渐取代所有其他的服务。流量进入服务网格之前,始终需要边缘代理拓扑。



4L4负载均衡的现状


L4负载均衡器还有用吗?

本文讨论了L7负载平衡器如何用于现代协议,后面还会讨论L7负载平衡器的特性。这是否意味着L4负载平衡器没用了?没有!尽管在我看来,L7负载均衡器最终将完全取代L4负载均衡器进行服务间通信,但是L4负载均衡器对边缘通信仍然很重要。因为几乎所有现代大型分布式架构都使用两层L4 / L7负载平衡架构处理互联网流量。在L7负载均衡器之前在边缘部署中部署专用L4负载均衡器的好处是:


L7负载均衡器执行的应用程序流量的分析,转换和路由选择要复杂得多,所以它们可以处理相对于经过优化的L4负载均衡器能够处理的相对较小的原始流量负载(以每秒数据包和每秒字节数衡量)。这一现实通常使得L4负载平衡器成为处理某些类型的DoS攻击(例如,SYN flood,通用包flood攻击等)的更好位置。


L7负载均衡器往往比L4负载平衡器更积极地开发,部署更频繁,并且具有更多的缺陷。有一个L4负载均衡器,可以在L7负载平衡器部署期间执行健康检查和排空,这比现代L4负载平衡器(通常使用BGP和ECMP)(以下更多)中使用的部署机制要容易得多。最后,因为L7负载平衡器功能的复杂性更容易出现错误,所以使用绕开故障和异常的L4负载平衡器产生更稳定的整体系统。


下面将介绍几种不同的中间/边缘代理L4负载均衡器的设计。这些设计不适用于客户端库和Sidecar拓扑。



TCP / UDP终端负载均衡器





图8:L4终端负载均衡器


仍在使用的第一类L4负载均衡器是图8所示的终端负载均衡器。这类负载均衡器,使用两个离散的TCP连接:一个在客户端和负载均衡器之间,另一个在负载均衡器和后端之间。


L4终端负载均衡器仍然有两个原因:

实现相对简单。

靠近客户端的连接终端(低延迟)对性能有很大的影响。具体来说,如果终端负载均衡器可以放置在使用有损网络(例如蜂窝)的客户端附近,那么在将数据转移到可靠的光纤传输到其最终位置之前,容易发生重传。换句话说,这种负载平衡器适用于存在点(POP)场景下的原始TCP连接。




TCP / UDP直通负载均衡器







图9:L4直通负载均衡器

第二种类型的L4负载均衡器是图9所示的直通负载均衡器。在这种类型的负载均衡器中,TCP连接不会被负载均衡器终止。而是在连接跟踪和网络地址转换(NAT)发生后,将每个连接的数据包转发到选定的后端。首先,我们来定义一下连接跟踪和NAT:


连接跟踪:跟踪所有活动的TCP连接状态的过程。这包括握手是否完成,是否收到FIN,连接空闲多久,连接选择了哪个后端等等。


NAT:NAT是使用连接跟踪数据在通过负载均衡器时更改数据包的IP /端口信息的过程。


使用连接跟踪和NAT,负载平衡器可以将大部分原始TCP流量从客户端传递到后端。例如,假设客户正在交谈,1.2.3.4:80而选定的后端位于10.0.0.2:9000。客户端TCP数据包将到达负载均衡器at 1.2.3.4:80。然后负载均衡器将交换数据包的目标IP和端口10.0.0.2:9000。它还会将数据包的源IP与负载均衡器的IP地址进行交换。因此,当后端在TCP连接上响应时,数据包将返回到负载平衡器,在那里进行连接跟踪并且NAT可以在反向再次发生。


为什么会使用这种负载均衡器来代替上一节中描述的终端负载均衡器呢?几个原因:


性能和资源使用:由于直通负载均衡器不是终止TCP连接,所以不需要缓冲任何TCP连接窗口。每个连接存储的状态量非常小,通常通过高效的散列表查找来访问。因此,直通负载均衡器通常可以处理比终端负载均衡器大得多的活动连接数和数据包数(PPS)。


允许后端执行拥塞控制:TCP拥塞控制是因特网上的端点节制发送数据的机制,从而不会压倒可用带宽和缓冲区。由于直通负载均衡器不会终止TCP连接,因此不参与拥塞控制。这个事实允许后端根据他们的应用使用情况使用不同的拥塞控制算法。它还可以更容易地进行拥塞控制变更的实验(例如,最近的BBR部署)。


形成直接服务器返回(DSR)和群集L4负载平衡的基准:更高级的L4负载平衡技术(如DSR和使用分布式一致性散列的群集(以下各节中讨论))需要直通负载平衡。


直接服务器返回(Direct Server Return,DSR)








图10:L4直接服务器返回(DSR)

直接服务器返回(DSR)负载平衡器如图10所示。DSR构建在上一节中介绍的直通负载均衡器上。DSR是一种优化,只有入口/请求数据包才能通过负载均衡器。出口/响应数据包在负载平衡器周围直接返回到客户端。执行DSR很有趣的主要原因是,在许多工作负载中,响应流量对请求流量(例如,典型的HTTP请求/响应模式)产生了不满。假设10%的流量是请求流量,90%的流量是响应流量,如果使用DSR的负载均衡器为1/10的容量可以满足系统的需求。由于历史上负载平衡器非常昂贵,因此这种优化可能会对系统成本和可靠性产生重大影响。DSR负载均衡器将直通负载均衡器的概念扩展如下:

负载平衡器通常仍然执行部分连接跟踪。由于响应数据包不会遍历负载均衡器,因此负载均衡器将不会意识到完整的TCP连接状态。但是,负载均衡器可以通过查看客户端数据包并使用各种类型的空闲超时来强烈推断状态。


负载均衡器通常使用通用路由封装(GRE)来封装从负载均衡器发送到后端的IP数据包,而不使用NAT 。因此,当后端收到封装的数据包时,可以对其进行解封装,并知道客户端的原始IP地址和TCP端口。这允许后端直接响应客户端,而无需响应数据包流经负载平衡器。


DSR负载平衡器的一个重要组成部分是后端参与负载均衡。后端需要有一个正确配置的GRE隧道,根据网络设置的低层细节,可能需要自己的连接跟踪,NAT等。

请注意,在直通负载均衡器和DSR负载均衡器设计中,可以通过负载均衡器和后端来设置连接跟踪,NAT,GRE等多种方式。



通过高可用性配对的容错








图11:通过HA对和连接跟踪的L4容错

到目前为止,我们一直在考虑L4负载平衡器的设计。直通和DSR负载平衡器都需要负载均衡器本身的一些连接跟踪和状态。如果负载平衡器死了怎么办?如果负载平衡器的单个实例死亡,则所有通过负载平衡器的连接将被切断。取决于应用程序,这可能会对应用程序性能产生重大影响。


历史上,L4负载均衡器是从典型供应商(Cisco,Juniper,F5等)购买的硬件设备。这些设备非常昂贵,处理大量的流量。为了避免单个负载均衡器发生故障切断所有连接,并导致大量应用程序中断,负载均衡器通常部署在高可用性配对中,如图11所示。典型的HA负载均衡器设置具有以下设计:


一对HA边缘路由器为虚拟IP(VIP)提供服务。这些边缘路由器使用边界网关协议(BGP)宣布虚拟IP 。主边缘路由器具有比备份更高的BGP权重,因此在稳定状态下,它服务所有流量。(BGP是一个非常复杂的协议; 就本文而言,考虑BGP是网络设备宣布可以从其他网络设备获取流量的机制,并且每个链路都可以具有优先考虑链路流量的权重)。


同样,主L4负载均衡器向边缘路由器宣布自己的BGP权重高于备份,因此在稳定状态下,它将服务所有流量。

主负载均衡器交叉连接到备份,并共享其所有连接跟踪状态。因此,如果主负载宕机,备份可以接管处理所有活动的连接。


两台边缘路由器和两台负载均衡器都是交叉连接的。这意味着如果其中一个边缘路由器或负载平衡器中的一个死亡,或者由于某种其他原因撤消BGP通知,备份可以接管所有通信。


上面的设置是目前具有高流量的互联网应用还在使用的方式。但是,上述方法有很大的缺点:

考虑到容量使用情况,虚拟 IP (VIP)必须在HA负载平衡器对之间正确分片。如果单个VIP超出单个HA对的容量,则需要将VIP分成多个VIP。


系统的资源使用情况很差。50%的容量在稳定状态下闲置。鉴于历史上硬件负载平衡器非常昂贵,这导致大量闲置资本。

现代分布式系统设计比主动/备份提供更高的容错能力。例如,最佳地,系统应该能够同时遭受多个故障并继续运行。如果主动和备用负载均衡器同时死亡,则HA负载均衡器对可能会发生完全故障。


来自供应商的专有大型硬件设备非常昂贵,并导致供应商锁定。通常希望用可商购计算服务器构建的可横向扩展的软件解决方案替代这些硬件设备。



通过具有分布式一致散列的集群进行容错和扩展






图12:L4容错和通过集群负载平衡器和一致性哈希的扩展

上一节介绍了通过HA对的L4负载平衡器容错以及该设计中固有的问题。从21世纪初到中期,大型互联网基础设施开始设计和部署新的大规模并行L4负载平衡系统,如图12所示。这些系统的目标是:


减轻上一节中描述的HA对设计的所有缺点。

从供应商的专有硬件负载平衡器转移到使用标准计算服务器和NIC构建的商品软件解决方案。

这个L4负载均衡器设计最好称为容错和扩展,通过集群和分布式一致的散列。它的工作原理如下:

N个边缘路由器以相同的BGP权重宣布所有Anycast VIP。等价多路径路由(ECMP)用于确保通常来自单个流的所有数据包到达相同的边缘路由器。流程通常是源IP /端口和目标IP /端口的四元组。(简而言之,ECMP是一种使用一致散列在一组相同加权的网络链路上分发数据包的方法)。尽管边缘路由器本身并不特别关心哪个分组到达哪里,但是通常优选的是,来自一个流的所有分组都经过相同的一组链路,以避免乱序分组,从而降低性能。

N个L4负载均衡器机器以与边缘路由器相同的BGP权重宣布所有的VIP。再次使用ECMP,边缘路由器将通常为流选择相同的负载平衡器机器。

每个L4负载均衡器机器通常会执行部分连接跟踪,然后使用一致的哈希来为流选择一个后端。GRE用于封装从负载均衡器发送到后端的数据包。

DSR然后被用来通过边缘路由器直接从后端发送数据包到客户端。

L4负载均衡器使用的实际一致性散列算法是一个活跃的研究领域。主要围绕均衡负载进行权衡,最小化延迟,最大限度地减少后端更改期间的中断, 并最大限度地减少内存开销。关于这个主题的完整讨论超出了本文的范围。


让我们看看上面的设计是如何缓解HA对方法的所有缺点的:

新的边缘路由器和负载平衡器机器可以根据需要添加。在添加新机器时,每层都使用一致的散列来尽可能减少受影响的流量。
 
系统的资源使用可以按照需要高速运行,同时保持足够的突发容限和容错。

边缘路由器和负载平衡器现在都可以使用商用硬件来构建,而传统硬件负载平衡器的成本只是其中的一小部分(下面会详细介绍)。


通常被问及这个设计的一个问题是“为什么边缘路由器不通过ECMP直接与后端对话?为什么我们需要负载平衡器?“其原因主要是减少DoS和后端操作的简化。如果没有负载平衡器,每个后端都必须参与BGP,并且执行滚动部署的时间将更加困难。


所有现代化的L4负载均衡系统都在朝着这种设计方向发展(或其他变体)。最著名的两个例子是Google的Maglev和Amazon 的网络负载均衡器(NLB)。目前还没有实现这种设计的OSS负载平衡器,但是,我知道有一家公司计划在2018年将其发布到OSS。我对这个版本感到非常兴奋,因为现代L4负载平衡器是一个至关重要的部分在网络空间中缺少OSS。


5L7负载平衡的现有技术状态

在过去的几年中,L7负载平衡器/代理的发展已经复苏。随着分布式系统中的微服务架构的不断推进,这方面也在不断进步。从根本上说,固有故障的网络在使用更频繁时变得更加难以有效地运行。而且,自动扩展,容器调度等等的出现意味着在静态文件中配置静态IP的日子早已不复存在。系统不仅要利用网络,还要变得更加动态,需要负载平衡器的新功能。本节将简要概述在现代L7负载平衡器的最新发展。


协议支持

现代L7负载平衡器为许多不同的协议增加了明确的支持。负载平衡器对于应用程序流量的知识越多,关于可观察性输出,高级负载平衡和路由等方面可以做的更复杂的事情。例如,在撰写本文时,Envoy明确支持L7协议解析和路由用于HTTP / 1,HTTP2,gRPC,Redis,MongoDB和DynamoDB。未来可能会有更多协议被添加,包括MySQL和Kafka。



动态配置

如上所述,分布式系统越来越具有动态性,需要并行投资来创建动态和反应式控制系统。Istio就是这样一个例子。


高级负载平衡

L7负载均衡器现在通常内置对高级负载平衡功能的支持,如超时,重试,速率限制,断路,屏蔽,缓冲,基于内容的路由等。



可观察性

如上面有关一般负载平衡器功能的部分所述,正在部署的日益动态的系统越来越难以调试。强大的协议特定的可观测性输出是现代L7负载平衡器最重要的特性。任何L7负载平衡解决方案现在都需要输出数字统计信息,分布式跟踪和可自定义日志记录。



可扩展性

现代L7负载平衡器的用户通常希望轻松扩展以添加自定义功能。这可以通过写入加载到负载均衡器的可插入过滤器来完成。许多负载平衡器也支持脚本,通常通过Lua。



容错

L7负载均衡器的容错性如何?一般来说,我们把L7负载平衡器视为可消耗和无状态的。使用商业软件就能够对L7负载平衡器轻松水平扩展。此外,L7负载平衡器执行的处理和状态跟踪比L4复杂得多。试图建立一个L7负载平衡器的HA配对在技术上是可能的,但非常繁杂。


总的来说,在L4和L7负载平衡领域,业界正在从HA配对转向通过一致的哈希聚合横向水平可扩展系统。


更多

L7负载平衡器正在以惊人的速度发展。有关Envoy提供的示例,请参阅Envoy的架构概述。


6全球负载均衡和集中控制平面







图13:全局负载平衡

负载平衡的未来将越来越多地将单个负载平衡器视为商品设备。我认为,真正的创新和商业机会都在控制层面。图13显示了一个全局负载均衡系统的例子。在这个例子中,几个不同的事情正在发生:

每个Sidecar代理正在与三个不同区域(A,B和C)的后端进行通信。

如图所示,90%的流量正被发送到区域C,而5%的流量正被发送到区域A和B。

Sidecar代理和后端均向全局负载均衡器报告周期性状态。这允许全局负载均衡器做出考虑延迟,成本,负载,当前故障等的决定。

全局负载均衡器使用当前路由信息周期性地配置每个边车代理。

全球负载均衡器越来越能够做复杂的事情。例如:

自动检测并绕过区域故障。

应用全局安全和路由策略。

使用机器学习和神经网络检测和减轻流量异常,包括DDoS攻击。

提供集中的用户界面和可视化,使工程师能够理解和操作整个分布式系统。

为了实现全局负载均衡,用作数据平面的负载平衡器必须具有复杂的动态配置能力。



7从硬件到软件的演变


本文只是简单地提到了硬件和软件,主要是在L4负载平衡器HA对的历史背景下。这方面的业界趋势又是怎样呢?

历史上的路由器和负载平衡器都是昂贵的专有硬件。

越来越多的专有L3 / L4网络设备正在被商用服务器硬件,商用网卡和基于IPVS,DPDK和fd.io等框架的专业软件解决方案取代。价格低于5K美元的现代数据中心机器可以使用Linux和自定义的基于DPDK的 user-space 应用,轻松饱和具有非常小数据包的80Gbps NIC。与此同时,廉价的路由器/交换机ASIC可以以惊人的总带宽和数据包速率进行ECMP路由选择,正在被打包成商品路由器。

像NGINX,HAProxy和Envoy这样先进的L7软件负载平衡器也在迅速地迭代和侵入之前像F5这样的供应商领域。因此,L7负载平衡器也在积极地向商品软件解决方案迈进。

与此同时,整个行业向主流云提供商推动的IaaS,CaaS和FaaS意味着越来越多的工程师需要了解物理网络是如何工作的


8结论和负载均衡的未来


这篇文章的主要内容是:

负载平衡器是现代分布式系统中的关键组件。

有两种负载均衡器:L4和L7。

L4和L7负载平衡器都与现代架构中相关。

L4负载均衡器正朝着横向可扩展的分布式一致哈希水平扩展解决方案迈进。

由于动态微服务体系结构的激增,L7负载平衡器最近发展迅速。

全局负载平衡和控制平面与数据平面之间的分离,是负载平衡的未来,存在大量商业机会。

业界正在积极向商用OSS硬件和软件提供网络解决方案。相信像F5这样的传统负载均衡厂商将首先被OSS软件和云供应商所取代。传统的路由器/交换机厂商,如Arista / Cumulus /等。短期会有好的发展,但最终也将被公有云供应商和自研物理网络所取代。

总的来说,现在是计算机网络的一个激动人心的时代!大多数系统开始向OSS和软件方向转变,迭代速度加快。分布式系统向“无服务器”计算发展,必须继续充满活力,底层网络和负载平衡系统的复杂性也将齐头并进。

原文:https://blog.envoyproxy.io/int ... 80236 查看全部
作者:Matt Klein

译者:杨泽

原题:Introduction to modern network load balancing and proxying

3_(4).png


关于现代网络负载均衡和代理(proxy)的介绍性资料很少,这件事引起了我的注意。为什么会这样呢?构建一个可靠的分布式系统时,负载均衡是一个非常核心的概念。但可惜的是,搜索发现关于负载均衡和服务代理的内容很少。维基百科文章只包含了一些概念,没有对该主题的详细介绍,尤其是与现代微服务架构相关的。


本文试图通过对现代网络负载均衡和代理的简单介绍,来弥补这部分信息的缺乏。为了保持文章的长度,尽量将复杂的话题浓缩成简单的概述。


1什么是网络负载均衡和代理?


维基百科这样定义负载均衡:

在计算中,负载均衡可以改善在多个计算机资源(如计算机,计算机集群,网络链接,中央处理单元或磁盘驱动器)上的工作负载分布。负载均衡旨在优化资源的使用,最大吞吐量,及最小响应时间,避免任何单一资源的过载。通过使用多个组件而不是单个组件,负载均衡通过冗余来提高可靠性和可用性。负载均衡通常涉及专用软件和硬件,例如多层交换机或域名系统服务器进程。

以上定义适用于计算的各个方面,而不仅仅是网络。操作系统使用负载均衡在物理处理器之间安排任务,诸如Kubernetes之类的容器编排者使用负载均衡来计划跨计算集群的任务,网络负载均衡通过调用可用后端来平衡网络任务。以下内容仅涵盖网络负载均衡。


1.png

图 1: 网络负载均衡描述


图1展示了网络负载均衡高层次的概览。一些客户端从后端请求资源。负载均衡器位于客户端和后端之间,在更高层次执行关键任务:

服务发现:在系统中哪些后端可用?地址是多少?(换句话说,负载均衡器如何与它们通信?)

健康检查:在系统中目前哪些后端是健康的,可以接受请求?

负载均衡:用什么样的算法把独立的个人请求发给健康的后端?


在分布式系统中正确使用负载均衡会带来如下好处:

命名抽象:客户端可以通过预定义的机制来寻址负载均衡器,而不是每个客户端都需要了解每个后端(服务发现),然后将名称解析的任务委托给负载均衡器。预定义的机制包括内置库和众所周知的DNS/IP/端口地址,后面会有详细的讨论。

容错:通过健康检查和各种算法技术,负载均衡器的路由方法可以绕过坏的或者超负载的后端。这也意味着运维人员可以随时优先修复后端错误。

低成本和高性能:分布式系统网络一致性比较差。系统可能会横跨不同的网络区域。在一个区域内,网络之间通常以相对小的带宽建立的。而在不同的区域之间,网络大带宽成为常态(带宽的大小是指通过NIC使用的带宽量占路由器之间可用带宽的百分比)。智能的负载均衡可以尽可能保持区域内的请求流量,从而提高性能(低延迟)并降低整体系统成本(减少区域间的带宽和光纤)。



负载均衡器VS代理

在谈论到网络负载均衡器,Load Balancer 和 Proxy 两个术语在行业内可以互换使用。在本文中也把两者视为一致的表达。(不过,不是所有的代理都是负载均衡器,但绝大多数代理都将负载均衡作为主要功能)。


一些人会争辩说,当负载均衡器作为嵌入式客户端库的一部分实现时,这种负载均衡器并不是真正的代理。这种区分其实添加了不必要的复杂性。本文会详细讨论负载均衡器的拓扑类型,嵌入式负载均衡器是代理的一个特例,应用通过嵌入式库进行代理,嵌入式库与应用进程外的负载均衡器整体抽象是一致的。



L4(连接/会话)负载均衡

业界讨论负载均衡时,解决方式往往分为两类:L4 和 L7。指的是OSI模型的第四层和第七层。OSI模型包括传统的第四层协议(如TCP和UDP),还包含各种不同OSI层的协议。换句话说,如果 L4 TCP负载均衡器也支持 TLS 终止,这不就是 L7负载均衡器么?


2.png

图2:TCP L4 终止负载平衡

图2展示了传统的L4 TCP负载均衡器。在这种情况下,客户端与负载均衡器建立TCP连接,负载均衡器终止连接(即直接响应SYN),选择一个后端,并与后端建立新的TCP连接(即发起新的SYN)。


本节的关键是L4负载均衡器通常只在 L4 TCP / UDP连接/会话上运行。因此,负载平衡器负责操作字节,并确保来自同一会话的字节转发到同一后端。L4负载平衡器并不知道通信中的任何应用细节。这些字节可能是 HTTP,Redis,MongoDB或任何其他应用协议。


L7(应用)负载平衡

 L4负载均衡简单,能看到广泛使用。人们为什么放弃L4负载均衡,来研究L7(应用)负载均衡?以下是L4具体的案例:


两个gRPC / HTTP2 客户端通过L4负载均衡器与后端建立连接。

L4负载均衡器为每个接入的TCP连接建立一个传出的TCP连接,这样就产生了两个传入和两个传出连接。

但是,客户端A每分钟发送 1个请求(RPM),而客户端B通每秒发送50个请求(RPS)。


在上述场景中,后端选择处理客户端B请求是选择客户端A请求负载的大约3000倍。这是一个很大的问题,打破了负载均衡的目的。需要注意的是这个问题发生在任何复用,保持存活状态的协议。(复用意味着通过单个L4连接多次发送应用程序请求,保持存活就是没有活动请求时不关闭连接)。出于效率的考虑,所有现代协议都在不断发展,既要复用也要存活(创建连接通常是昂贵的,特别是用TLS进行加密连接时),所以L4负载均衡器随着时间的推移,负载失衡的情况更加明显。这个问题在L7负载均衡器中得到解决。


3.png


图3:HTTP / 2 L7终端负载均衡

图3展示了L7 HTTP/2负载平衡器。客户端与负载均衡器只建立一个 HTTP/2 TCP连接,连接两个后端。当客户端向负载均衡器发送两个HTTP/2 流时,流1被发送到后端1,流2被发送到后端2。因此,即使差别很大的请求负载的多路复用客户端也将被有效地平衡到不同的后端。这就是L7负载平衡对于现代协议的重要性所在。(L7负载平衡由于能够检查应用流量,而产生大量好处,后面会更详述)。



L7负载均衡和OSI模型

正如L4负载平衡部分所述,使用OSI模型描述负载均衡功能是有问题的。原因在于L7本身包含多个离散的负载均衡抽象层。例如,对于HTTP流量,请考虑以下子层:


可选的传输层安全性(TLS)。网络界对于TLS 属于OSI模型哪一层有争论。为了方便,我们考虑将TLS放在 L7。

物理HTTP协议(HTTP / 1或HTTP / 2)。

逻辑HTTP协议(Header、Body 和 Trailer)。

消息传递协议(gRPC,REST等)。


一个复杂的L7负载均衡器要提供与上述每个子层有关的功能。另L7负载均衡器可能只有一小部分功能属于OSI模型中L7层。简而言之,L7负载平衡器的功能远比L4类型复杂得多。(HTTP、 Redis、Kafka、MongoDB等都是应用L7 协议的例子,它们受益于L7负载均衡)。



2负载均衡器功能


在本节中将总结负载均衡器提供的高级功能,并非所有负载均衡器都提供全部功能。


服务发现

服务发现是负载平衡器确定可用后端的过程,实现的方式有很多种,一些例子包括:


静态配置文件。

DNS。

Zookeeper,Etcd,Consul等。

Envoy的通用数据平面API。


健康检查

运行状况检查是负载均衡器确定后端是否可用来为流量提供服务的过程。健康检查一般分为两类:

主动式:负载平衡器将定期发送ping(例如,对/healthcheck端点的HTTP请求)到后端,并用它来衡量健康状况。

被动式:负载均衡器从主数据流中检测健康状况。例如,如果连续出现三个连接错误,则L4负载均衡器会认为后端是不健康的。如果一行中有三个HTTP 503响应代码,则L7负载均衡器会认为后端是不健康的。



负载均衡

负载均衡器必须实际平衡负载!当给定一组健康的后端时,选择哪个后端处理请求?负载平衡算法是一个活跃的研究领域,从简单的算法(如随机选择和循环算法)到考虑可变延迟和后端负载的更复杂的算法。考虑到其性能和简单性,最流行的负载均衡算法是二节点最小请求负载均衡(power of 2 least request load balancing)。 


粘滞会话(Sticky sessions)

在某些应用中,同一会话的请求到达相同的后端是很重要的。这与缓存,临时复杂状态等有关。会话的定义各不相同,可能包括HTTP Cookie,客户端连接的配置或其他属性。许多L7负载平衡器支持会话粘连。会话粘性本质上是脆弱的(后端保存的会话可能会失效),所以在设计系统的时候减少对它们的依赖。



TLS终止

关于TLS,它在边缘服务和服务间通信方面值得肯定。因此,许多L7负载均衡器会执行大量的TLS处理,包括终止,证书验证和保存,使用SNI的证书服务等。



可观察性

正如谈话中所强调的:“可观察性,可观察性,可观察性”。网络本质上是不可靠的,负载均衡器通常负责导出统计信息,跟踪信息和记录日志,帮助运营人员找出问题所在,从而解决问题。最先进的负载平衡器可观察性输出包括数字统计,分布式跟踪和可定制的日志记录。增强的可观察性不是免费的; 负载平衡器必须做很多附加的工作来完成它。至于,负面影响,相对带来的好处,几乎不值一提。


安全性和DoS防范

特别是在边缘部署拓扑(见下文)中,负载均衡器通常实施各种安全功能,包括速率限制,身份验证和DoS防范(例如,IP地址标记和识别,缓送Tarpitting等)。



配置和控制面板

负载平衡器需要配置。在大规模部署中,这是一项重要工作。一般来说,配置负载均衡器的系统被称为“控制面板”,并且在其实现中变化很大。
 
3负载均衡器拓扑的类型

前面介绍了负载平衡器的概要,L4和L7负载平衡器之间的区别以及负载均衡器特性,接下来将转向部署负载均衡器的各种分布式系统拓扑。(以下每种拓扑均适用于L4和L7负载均衡器)。



中间代理


4.png

 
图4:中间代理负载均衡拓扑

图4所示的中间代理拓扑是大多数读者最熟悉的负载均衡一种方式。这一类包括Cisco,Juniper,F5等硬件设备; 云软件解决方案,如亚马逊的ALB和NLB以及Google的 Cloud Load Balancer ; 以及HAProxy,NGINX和Envoy等纯软件自主托管解决方案。中间代理解决方案使用简单。通常,用户通过DNS连接到负载均衡器,不需要担心其他任何事情。中间代理解决方案的特点是代理(即使是集群)是单一的故障点,也是扩展的瓶颈。中间代理通常是一个让运维变得困难的黑匣子。当问题出现时,是在客户端还是物理网络?在中间代理还是后端?这很难说。



边缘代理

5.png


图5:边缘代理负载平衡拓扑

图5所示实际上只是中间代理拓扑的一种变体,负载均衡器通过Internet访问。在这种情况下,负载均衡器通常必须提供附加的“API网关”功能,如TLS终止,速率限制,身份验证和复杂的流量路由。边缘代理的优缺点与中间代理相同。需要注意的是,在面向Internet的大型分布式系统中部署专用边缘代理通常是不可避免的。客户端通常需要使用服务所有者无法控制的任意网络库(后面会讨论嵌入式客户端库或附属代理拓扑结构不能直接在客户端上运行)通过DNS访问系统。另外,由于安全原因,希望具有单个网关,通过该网关,所有面向互联网的流量进入系统。



嵌入式客户端库

6.png


图6:通过嵌入式客户端库进行负载平衡

为了避免中间代理拓扑中固有的单点故障和扩展问题,更复杂的基础设施已经开始将负载均衡器直接嵌入到服务库中,如图6所示。支持的功能库有很大的不同,但是这个类别中最知名和最丰富的功能包括Finagle,Eureka / Ribbon / Hystrix和gRPC(松散地基于称为Stubby的内部Google系统)。基于库的解决方案的主要功能是将负载均衡器的所有功能完全分配给每个客户端,从而消除之前描述的单点故障和扩展问题。基于客户端库的解决方案的主要内容是客户端库必须每种语言调用。分布式架构正变得越来越“多语言”(多语言)。在这样的环境下,用许多不同的语言来重新实现一个非常复杂的网络库的成本会变得过高。最后,在大型服务体系结构中部署库升级可能会非常痛苦,这使得很多不同版本的库将在生产中同时运行,

综上所述,上面提到的这些库对于那些能够限制编程语言扩散并克服库升级难题的公司来说是成功的。



Sidecar代理

7.png


图7:通过sidecar代理进行负载平衡

嵌入式客户端库负载平衡器拓扑的一个变种是图7中所示的辅助代理拓扑。近年来,这种拓扑已经被普遍推广为“服务网格”(Service Mesh)。Sidecar代理背后的思路是,以跳过一个不同的过程的代价来承担轻微的延迟,嵌入式库的所有好处都可以在没有任何编程语言锁定的情况下获得。在撰写本文时,最受欢迎的sidecar代理负载平衡器是Envoy,NGINX,HAProxy和Linkerd。



负载均衡器拓扑的总结和优缺点

中间代理拓扑是最简单的负载平衡拓扑。缺点是:单点故障,伸缩瓶颈和黑箱操作。


边缘代理拓扑与中间代理类似,但通常无法避免。


嵌入式客户端库拓扑提供了最好的性能和可扩展性,但是需要在每种语言中实现该库,并跨所有服务升级库。


Sidecar代理拓扑性能比嵌入式客户端库拓扑弱,但不受任何限制。

总体而言,sidecar代理拓扑(服务网格)正在逐渐取代所有其他的服务。流量进入服务网格之前,始终需要边缘代理拓扑。



4L4负载均衡的现状


L4负载均衡器还有用吗?

本文讨论了L7负载平衡器如何用于现代协议,后面还会讨论L7负载平衡器的特性。这是否意味着L4负载平衡器没用了?没有!尽管在我看来,L7负载均衡器最终将完全取代L4负载均衡器进行服务间通信,但是L4负载均衡器对边缘通信仍然很重要。因为几乎所有现代大型分布式架构都使用两层L4 / L7负载平衡架构处理互联网流量。在L7负载均衡器之前在边缘部署中部署专用L4负载均衡器的好处是:


L7负载均衡器执行的应用程序流量的分析,转换和路由选择要复杂得多,所以它们可以处理相对于经过优化的L4负载均衡器能够处理的相对较小的原始流量负载(以每秒数据包和每秒字节数衡量)。这一现实通常使得L4负载平衡器成为处理某些类型的DoS攻击(例如,SYN flood,通用包flood攻击等)的更好位置。


L7负载均衡器往往比L4负载平衡器更积极地开发,部署更频繁,并且具有更多的缺陷。有一个L4负载均衡器,可以在L7负载平衡器部署期间执行健康检查和排空,这比现代L4负载平衡器(通常使用BGP和ECMP)(以下更多)中使用的部署机制要容易得多。最后,因为L7负载平衡器功能的复杂性更容易出现错误,所以使用绕开故障和异常的L4负载平衡器产生更稳定的整体系统。


下面将介绍几种不同的中间/边缘代理L4负载均衡器的设计。这些设计不适用于客户端库和Sidecar拓扑。



TCP / UDP终端负载均衡器

8.png

图8:L4终端负载均衡器


仍在使用的第一类L4负载均衡器是图8所示的终端负载均衡器。这类负载均衡器,使用两个离散的TCP连接:一个在客户端和负载均衡器之间,另一个在负载均衡器和后端之间。


L4终端负载均衡器仍然有两个原因:

实现相对简单。

靠近客户端的连接终端(低延迟)对性能有很大的影响。具体来说,如果终端负载均衡器可以放置在使用有损网络(例如蜂窝)的客户端附近,那么在将数据转移到可靠的光纤传输到其最终位置之前,容易发生重传。换句话说,这种负载平衡器适用于存在点(POP)场景下的原始TCP连接。




TCP / UDP直通负载均衡器


9.png


图9:L4直通负载均衡器

第二种类型的L4负载均衡器是图9所示的直通负载均衡器。在这种类型的负载均衡器中,TCP连接不会被负载均衡器终止。而是在连接跟踪和网络地址转换(NAT)发生后,将每个连接的数据包转发到选定的后端。首先,我们来定义一下连接跟踪和NAT:


连接跟踪:跟踪所有活动的TCP连接状态的过程。这包括握手是否完成,是否收到FIN,连接空闲多久,连接选择了哪个后端等等。


NAT:NAT是使用连接跟踪数据在通过负载均衡器时更改数据包的IP /端口信息的过程。


使用连接跟踪和NAT,负载平衡器可以将大部分原始TCP流量从客户端传递到后端。例如,假设客户正在交谈,1.2.3.4:80而选定的后端位于10.0.0.2:9000。客户端TCP数据包将到达负载均衡器at 1.2.3.4:80。然后负载均衡器将交换数据包的目标IP和端口10.0.0.2:9000。它还会将数据包的源IP与负载均衡器的IP地址进行交换。因此,当后端在TCP连接上响应时,数据包将返回到负载平衡器,在那里进行连接跟踪并且NAT可以在反向再次发生。


为什么会使用这种负载均衡器来代替上一节中描述的终端负载均衡器呢?几个原因:


性能和资源使用:由于直通负载均衡器不是终止TCP连接,所以不需要缓冲任何TCP连接窗口。每个连接存储的状态量非常小,通常通过高效的散列表查找来访问。因此,直通负载均衡器通常可以处理比终端负载均衡器大得多的活动连接数和数据包数(PPS)。


允许后端执行拥塞控制:TCP拥塞控制是因特网上的端点节制发送数据的机制,从而不会压倒可用带宽和缓冲区。由于直通负载均衡器不会终止TCP连接,因此不参与拥塞控制。这个事实允许后端根据他们的应用使用情况使用不同的拥塞控制算法。它还可以更容易地进行拥塞控制变更的实验(例如,最近的BBR部署)。


形成直接服务器返回(DSR)和群集L4负载平衡的基准:更高级的L4负载平衡技术(如DSR和使用分布式一致性散列的群集(以下各节中讨论))需要直通负载平衡。


直接服务器返回(Direct Server Return,DSR)



10.png


图10:L4直接服务器返回(DSR)

直接服务器返回(DSR)负载平衡器如图10所示。DSR构建在上一节中介绍的直通负载均衡器上。DSR是一种优化,只有入口/请求数据包才能通过负载均衡器。出口/响应数据包在负载平衡器周围直接返回到客户端。执行DSR很有趣的主要原因是,在许多工作负载中,响应流量对请求流量(例如,典型的HTTP请求/响应模式)产生了不满。假设10%的流量是请求流量,90%的流量是响应流量,如果使用DSR的负载均衡器为1/10的容量可以满足系统的需求。由于历史上负载平衡器非常昂贵,因此这种优化可能会对系统成本和可靠性产生重大影响。DSR负载均衡器将直通负载均衡器的概念扩展如下:

负载平衡器通常仍然执行部分连接跟踪。由于响应数据包不会遍历负载均衡器,因此负载均衡器将不会意识到完整的TCP连接状态。但是,负载均衡器可以通过查看客户端数据包并使用各种类型的空闲超时来强烈推断状态。


负载均衡器通常使用通用路由封装(GRE)来封装从负载均衡器发送到后端的IP数据包,而不使用NAT 。因此,当后端收到封装的数据包时,可以对其进行解封装,并知道客户端的原始IP地址和TCP端口。这允许后端直接响应客户端,而无需响应数据包流经负载平衡器。


DSR负载平衡器的一个重要组成部分是后端参与负载均衡。后端需要有一个正确配置的GRE隧道,根据网络设置的低层细节,可能需要自己的连接跟踪,NAT等。

请注意,在直通负载均衡器和DSR负载均衡器设计中,可以通过负载均衡器和后端来设置连接跟踪,NAT,GRE等多种方式。



通过高可用性配对的容错



11.png


图11:通过HA对和连接跟踪的L4容错

到目前为止,我们一直在考虑L4负载平衡器的设计。直通和DSR负载平衡器都需要负载均衡器本身的一些连接跟踪和状态。如果负载平衡器死了怎么办?如果负载平衡器的单个实例死亡,则所有通过负载平衡器的连接将被切断。取决于应用程序,这可能会对应用程序性能产生重大影响。


历史上,L4负载均衡器是从典型供应商(Cisco,Juniper,F5等)购买的硬件设备。这些设备非常昂贵,处理大量的流量。为了避免单个负载均衡器发生故障切断所有连接,并导致大量应用程序中断,负载均衡器通常部署在高可用性配对中,如图11所示。典型的HA负载均衡器设置具有以下设计:


一对HA边缘路由器为虚拟IP(VIP)提供服务。这些边缘路由器使用边界网关协议(BGP)宣布虚拟IP 。主边缘路由器具有比备份更高的BGP权重,因此在稳定状态下,它服务所有流量。(BGP是一个非常复杂的协议; 就本文而言,考虑BGP是网络设备宣布可以从其他网络设备获取流量的机制,并且每个链路都可以具有优先考虑链路流量的权重)。


同样,主L4负载均衡器向边缘路由器宣布自己的BGP权重高于备份,因此在稳定状态下,它将服务所有流量。

主负载均衡器交叉连接到备份,并共享其所有连接跟踪状态。因此,如果主负载宕机,备份可以接管处理所有活动的连接。


两台边缘路由器和两台负载均衡器都是交叉连接的。这意味着如果其中一个边缘路由器或负载平衡器中的一个死亡,或者由于某种其他原因撤消BGP通知,备份可以接管所有通信。


上面的设置是目前具有高流量的互联网应用还在使用的方式。但是,上述方法有很大的缺点:

考虑到容量使用情况,虚拟 IP (VIP)必须在HA负载平衡器对之间正确分片。如果单个VIP超出单个HA对的容量,则需要将VIP分成多个VIP。


系统的资源使用情况很差。50%的容量在稳定状态下闲置。鉴于历史上硬件负载平衡器非常昂贵,这导致大量闲置资本。

现代分布式系统设计比主动/备份提供更高的容错能力。例如,最佳地,系统应该能够同时遭受多个故障并继续运行。如果主动和备用负载均衡器同时死亡,则HA负载均衡器对可能会发生完全故障。


来自供应商的专有大型硬件设备非常昂贵,并导致供应商锁定。通常希望用可商购计算服务器构建的可横向扩展的软件解决方案替代这些硬件设备。



通过具有分布式一致散列的集群进行容错和扩展


12.png

图12:L4容错和通过集群负载平衡器和一致性哈希的扩展

上一节介绍了通过HA对的L4负载平衡器容错以及该设计中固有的问题。从21世纪初到中期,大型互联网基础设施开始设计和部署新的大规模并行L4负载平衡系统,如图12所示。这些系统的目标是:


减轻上一节中描述的HA对设计的所有缺点。

从供应商的专有硬件负载平衡器转移到使用标准计算服务器和NIC构建的商品软件解决方案。

这个L4负载均衡器设计最好称为容错和扩展,通过集群和分布式一致的散列。它的工作原理如下:

N个边缘路由器以相同的BGP权重宣布所有Anycast VIP。等价多路径路由(ECMP)用于确保通常来自单个流的所有数据包到达相同的边缘路由器。流程通常是源IP /端口和目标IP /端口的四元组。(简而言之,ECMP是一种使用一致散列在一组相同加权的网络链路上分发数据包的方法)。尽管边缘路由器本身并不特别关心哪个分组到达哪里,但是通常优选的是,来自一个流的所有分组都经过相同的一组链路,以避免乱序分组,从而降低性能。

N个L4负载均衡器机器以与边缘路由器相同的BGP权重宣布所有的VIP。再次使用ECMP,边缘路由器将通常为流选择相同的负载平衡器机器。

每个L4负载均衡器机器通常会执行部分连接跟踪,然后使用一致的哈希来为流选择一个后端。GRE用于封装从负载均衡器发送到后端的数据包。

DSR然后被用来通过边缘路由器直接从后端发送数据包到客户端。

L4负载均衡器使用的实际一致性散列算法是一个活跃的研究领域。主要围绕均衡负载进行权衡,最小化延迟,最大限度地减少后端更改期间的中断, 并最大限度地减少内存开销。关于这个主题的完整讨论超出了本文的范围。


让我们看看上面的设计是如何缓解HA对方法的所有缺点的:

新的边缘路由器和负载平衡器机器可以根据需要添加。在添加新机器时,每层都使用一致的散列来尽可能减少受影响的流量。
 
系统的资源使用可以按照需要高速运行,同时保持足够的突发容限和容错。

边缘路由器和负载平衡器现在都可以使用商用硬件来构建,而传统硬件负载平衡器的成本只是其中的一小部分(下面会详细介绍)。


通常被问及这个设计的一个问题是“为什么边缘路由器不通过ECMP直接与后端对话?为什么我们需要负载平衡器?“其原因主要是减少DoS和后端操作的简化。如果没有负载平衡器,每个后端都必须参与BGP,并且执行滚动部署的时间将更加困难。


所有现代化的L4负载均衡系统都在朝着这种设计方向发展(或其他变体)。最著名的两个例子是Google的Maglev和Amazon 的网络负载均衡器(NLB)。目前还没有实现这种设计的OSS负载平衡器,但是,我知道有一家公司计划在2018年将其发布到OSS。我对这个版本感到非常兴奋,因为现代L4负载平衡器是一个至关重要的部分在网络空间中缺少OSS。


5L7负载平衡的现有技术状态

在过去的几年中,L7负载平衡器/代理的发展已经复苏。随着分布式系统中的微服务架构的不断推进,这方面也在不断进步。从根本上说,固有故障的网络在使用更频繁时变得更加难以有效地运行。而且,自动扩展,容器调度等等的出现意味着在静态文件中配置静态IP的日子早已不复存在。系统不仅要利用网络,还要变得更加动态,需要负载平衡器的新功能。本节将简要概述在现代L7负载平衡器的最新发展。


协议支持

现代L7负载平衡器为许多不同的协议增加了明确的支持。负载平衡器对于应用程序流量的知识越多,关于可观察性输出,高级负载平衡和路由等方面可以做的更复杂的事情。例如,在撰写本文时,Envoy明确支持L7协议解析和路由用于HTTP / 1,HTTP2,gRPC,Redis,MongoDB和DynamoDB。未来可能会有更多协议被添加,包括MySQL和Kafka。



动态配置

如上所述,分布式系统越来越具有动态性,需要并行投资来创建动态和反应式控制系统。Istio就是这样一个例子。


高级负载平衡

L7负载均衡器现在通常内置对高级负载平衡功能的支持,如超时,重试,速率限制,断路,屏蔽,缓冲,基于内容的路由等。



可观察性

如上面有关一般负载平衡器功能的部分所述,正在部署的日益动态的系统越来越难以调试。强大的协议特定的可观测性输出是现代L7负载平衡器最重要的特性。任何L7负载平衡解决方案现在都需要输出数字统计信息,分布式跟踪和可自定义日志记录。



可扩展性

现代L7负载平衡器的用户通常希望轻松扩展以添加自定义功能。这可以通过写入加载到负载均衡器的可插入过滤器来完成。许多负载平衡器也支持脚本,通常通过Lua。



容错

L7负载均衡器的容错性如何?一般来说,我们把L7负载平衡器视为可消耗和无状态的。使用商业软件就能够对L7负载平衡器轻松水平扩展。此外,L7负载平衡器执行的处理和状态跟踪比L4复杂得多。试图建立一个L7负载平衡器的HA配对在技术上是可能的,但非常繁杂。


总的来说,在L4和L7负载平衡领域,业界正在从HA配对转向通过一致的哈希聚合横向水平可扩展系统。


更多

L7负载平衡器正在以惊人的速度发展。有关Envoy提供的示例,请参阅Envoy的架构概述。


6全球负载均衡和集中控制平面


13.png


图13:全局负载平衡

负载平衡的未来将越来越多地将单个负载平衡器视为商品设备。我认为,真正的创新和商业机会都在控制层面。图13显示了一个全局负载均衡系统的例子。在这个例子中,几个不同的事情正在发生:

每个Sidecar代理正在与三个不同区域(A,B和C)的后端进行通信。

如图所示,90%的流量正被发送到区域C,而5%的流量正被发送到区域A和B。

Sidecar代理和后端均向全局负载均衡器报告周期性状态。这允许全局负载均衡器做出考虑延迟,成本,负载,当前故障等的决定。

全局负载均衡器使用当前路由信息周期性地配置每个边车代理。

全球负载均衡器越来越能够做复杂的事情。例如:

自动检测并绕过区域故障。

应用全局安全和路由策略。

使用机器学习和神经网络检测和减轻流量异常,包括DDoS攻击。

提供集中的用户界面和可视化,使工程师能够理解和操作整个分布式系统。

为了实现全局负载均衡,用作数据平面的负载平衡器必须具有复杂的动态配置能力。



7从硬件到软件的演变


本文只是简单地提到了硬件和软件,主要是在L4负载平衡器HA对的历史背景下。这方面的业界趋势又是怎样呢?

历史上的路由器和负载平衡器都是昂贵的专有硬件。

越来越多的专有L3 / L4网络设备正在被商用服务器硬件,商用网卡和基于IPVS,DPDK和fd.io等框架的专业软件解决方案取代。价格低于5K美元的现代数据中心机器可以使用Linux和自定义的基于DPDK的 user-space 应用,轻松饱和具有非常小数据包的80Gbps NIC。与此同时,廉价的路由器/交换机ASIC可以以惊人的总带宽和数据包速率进行ECMP路由选择,正在被打包成商品路由器。

像NGINX,HAProxy和Envoy这样先进的L7软件负载平衡器也在迅速地迭代和侵入之前像F5这样的供应商领域。因此,L7负载平衡器也在积极地向商品软件解决方案迈进。

与此同时,整个行业向主流云提供商推动的IaaS,CaaS和FaaS意味着越来越多的工程师需要了解物理网络是如何工作的


8结论和负载均衡的未来


这篇文章的主要内容是:

负载平衡器是现代分布式系统中的关键组件。

有两种负载均衡器:L4和L7。

L4和L7负载平衡器都与现代架构中相关。

L4负载均衡器正朝着横向可扩展的分布式一致哈希水平扩展解决方案迈进。

由于动态微服务体系结构的激增,L7负载平衡器最近发展迅速。

全局负载平衡和控制平面与数据平面之间的分离,是负载平衡的未来,存在大量商业机会。

业界正在积极向商用OSS硬件和软件提供网络解决方案。相信像F5这样的传统负载均衡厂商将首先被OSS软件和云供应商所取代。传统的路由器/交换机厂商,如Arista / Cumulus /等。短期会有好的发展,但最终也将被公有云供应商和自研物理网络所取代。

总的来说,现在是计算机网络的一个激动人心的时代!大多数系统开始向OSS和软件方向转变,迭代速度加快。分布式系统向“无服务器”计算发展,必须继续充满活力,底层网络和负载平衡系统的复杂性也将齐头并进。

原文:https://blog.envoyproxy.io/int ... 80236

聊聊ServiceMesh 数据面板 Envoy

Envoy小数 发表了文章 • 0 个评论 • 432 次浏览 • 2018-01-04 20:46 • 来自相关话题

 见过linkerd,聊过istio,今天聊聊不常提起的envoy,点击链接即可阅读。 查看全部

1507861978(1).png

 见过linkerd,聊过istio,今天聊聊不常提起的envoy,点击链接即可阅读。

专题 | A Service Mesh for Kubernetes 第二期:K8S+Linkerd

Linkerd小数 发表了文章 • 0 个评论 • 214 次浏览 • 2018-01-04 20:45 • 来自相关话题

 专题 | A Service Mesh for Kubernetes 第二期:K8S+Linkerd 查看全部

专题 | Kubernetes+Linkerd 第一期

Linkerd小数 发表了文章 • 0 个评论 • 297 次浏览 • 2018-01-03 16:58 • 来自相关话题

作者:ALEX LEONG


翻译:平凡

转自:容器时代(CaaSOne)
 
Service Mesh,一个为云平台而设计的应用,云平台的本地应用该如何使用它?本文中,我们将讲述在Kubernetes中如何应用Linkerd作为Service Mesh,如何捕获和报告顶层服务指标如成功率、请求量和延迟,而不需要更改应用的代码。


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



使用service mesh的必要性

关于Linkerd最常见的一个疑问就是,到底什么是Service Mesh?当Kubernetes已经提供了如Service资源对象、负载均衡这样的基本功能后,为什么Service Mesh要作为云本地应用程序的关键组件。


简单来说,Service Mesh这一层管理着应用之间的通信(或者部分应用之间的通信如微服务)。传统应用中,这个逻辑直接构建到应用程序本身中:重试和超时,监控/可见性,追踪,服务发现等等。这些都被硬编码到每个应用程序中。

然而,随着应用程序架构被越来越多的分割成服务,将通信逻辑从应用中移出到底层基础设施中变得越来越重要。就像是应用程序不应该写它自己的TCP栈,他们也不应该管理自己的负载均衡逻辑,或他们自己的服务发现管理程序,以及他们自己的重试和超时逻辑。

像Linkerd这样的Service Mesh为大规模多服务应用程序提供关键的部件:

基本的适应性功能:重试预算,deadline,熔断器模式

顶层的服务指标:成功率,请求量,延迟

延迟和失败容忍度:感应失败和延迟的负载均衡,它可以绕过缓慢的或者损坏的服务实例

分发追踪:如Zipkin和OpenTracing

服务发现:找到目标实例

协议升级:在TLS中包装跨网络通信,或将HTTP/1.1转换为HTTP/2.0

路由:不同版本的服务之间的路由请求,集群之间的故障转移等



在这部分中,我们仅重点关注可见性:Service Mesh是如何自动捕获并报告如成功率等顶层服务指标的,我们将展示一个Kubernetes的小例子以此来引导你。
 
在Kubernetes中使用Linkerd作为Service的检测器
 
在请求层进行操作的一个优势是Service Mesh可以访问成功和失败的协议级语义。举个例子,如果你正在运行一个HTTP服务,Linkerd可以理解200 、400、500响应的含义,从而可以自动计算如成功率这样的指标。

让我们通过一个小例子讲解如何在Kubernetes中安装Linkerd,从而自动的捕获顶层服务成功率而不需要更改应用程序。
 

安装Linkerd
使用Kubernetes配置文件安装Linkerd。它会将Linkerd作为DaemonSet安装,且运行在Kubernetes的default命名空间:
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/linkerd.yml 
 
你可以通过查看Linkerd的管理页面确认是否安装成功:
INGRESS_LB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}") open http://$INGRESS_LB:9990 # on OS X
 
如果集群不支持外部负载均衡,使用hostIP:
HOST_IP=$(kubectl get po -l app=l5d -o jsonpath="{.items[0].status.hostIP}") open http://$HOST_IP:$(kubectl get svc l5d -o 'jsonpath={.spec.ports[2].nodePort}') # on OS X








安装样例应用程序
在default命名空间下安装两个Service,“hello”和“world”。这些应用程序依赖于Kubernetes downward API提供的nodeName来发现Linkerd。为了检测你的集群是否支持nodeName,你可以运行:
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/node-name-test.yml 
 
然后看它的日志:kubectl logs node-name-test
 
如果你看到了一个IP就说明支持。接下来继续部署hello world应用程序如下:
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/hello-world.yml 
 
如果你看到报错“server can’t find…”,就部署旧版本hello-world,它依赖于hostIP而非nodeName:kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/hello-world-legacy.yml 
 
这两个Service——“hello”和“world”——功能在一起使得高度可扩展,“hello world”微服务(“hello”Service调用“world”Service完成这个请求)。

你可以通过给Linkerd的外部IP发送请求来查看此操作:
http_proxy=$INGRESS_LB:4140 curl -s http://hello或者直接使用hostIP:http_proxy=$HOST_IP:$(kubectl get svc l5d -o 'jsonpath={.spec.ports[0].nodePort}') curl -s http://hello 
 
你应该可以看到字符串“Hello world”。
 

安装Linkerd-viz
最后,通过安装Linkerd-viz,让我们可以看看Service正在做什么。Linkerd-viz是一个附加包,它包括一个简单的Prometheus和Grafana设置,并可以自动发现Linkerd。
下面的命令会将Linkerd-viz安装到default命名空间下:
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-viz/master/k8s/linkerd-viz.yml 
 
访问Linkerd-viz的外部IP查看dashboard:
VIZ_INGRESS_LB=$(kubectl get svc linkerd-viz -o jsonpath="{.status.loadBalancer.ingress[0].*}") open http://$VIZ_INGRESS_LB # on OS X
 
如果集群不支持外部负载均衡,使用hostIP:
VIZ_HOST_IP=$(kubectl get po -l name=linkerd-viz -o jsonpath="{.items[0].status.hostIP}") open http://$VIZ_HOST_IP:$(kubectl get svc linkerd-viz -o 'jsonpath={.spec.ports[0].nodePort}') # on OS X
 
你应该在dashboard上看到包括Service与实例的选择器,所有图表都反映了这些Service和实例的选择器。
 






Linkerd-viz的dashboard包括三部分:

顶层:集群范围的成功率与请求量

Service指标:每个已部署应用的指标,包括成功率、请求量和延迟

单个实例指标:集群上每一个node的成功率、请求量和延迟

用三个简单的命令我们就可以将Linkerd安装在集群上,安装应用,并且使用Linkerd了解应用程序Service的健康状况。当然,Linkerd提供的不仅仅是可见性,还提供了延迟感应负载均衡,自动重试和断路,分发追踪等功能。
 
 
 
第二部分:导言
 
在第一部分里我们提到了Linkerd是使用DaemonSet而非Sidecar来安装的。在第二部分中,我们将解释我们为什么(怎么样)这么做。

注意:这是关于Linkerd、Kubernetes和Service ,esh的系列文章其中一篇,其余部分包括:

Top-line service metrics

Pods are great, until they’re not(本文)

Encrypting all the things

Continuous deployment via traffic shifting

Dogfood environments, ingress, and edge routing

Staging microservices without the tears

Distributed tracing made easy

Linkerd as an ingress controller

gRPC for fun and profit

The Service Mesh API

Egress

Retry budgets, deadline propagation, and failing gracefully

Autoscaling by top-line metrics
 

Linkerd以DaemonSet方式运行


作为Service Mesh,Linkerd设计为与应用程序代码一起运行。它管理和监控service的内部通信,包括服务发现、重试、负载均衡与协议升级。

初次听闻,都会觉得这非常适合在Kubernetes中以Sidecar的方式部署。毕竟,Kubernetes的定义特征之一就是它的pod模型。作为Sidecar部署理论上简单,有清晰的失败语义,我们花了大量时间用于针对该用例的Linkerd优化。

然而,Sidecar模型有其缺陷:部署一个pod就要用掉部署一个pod的资源。如果你的Service较轻量并且跑了许多的应用实例,这样使用Sidecar来部署就会代价极高。

我们可以通过每一个host而非每一个pod部署一个Linkerd来减少资源的开销。它对每个主机进行扩展而消耗资源,这通常是比pod数量要显著更慢的增长的指标。并且很幸运,Kubernetes为此目的提供了DaemonSets。

但美中不足的是,对于Linkerd来说,按每个host部署比仅仅使用DaemonSets要复杂一些。我们如何解决Service Mesh这个问题?请继续阅读下文。
 

Kubernetes的Service 
MeshService Mesh的定义特征之一是它将应用通信与传输通信分离开的能力。例如,如果Service A与B使用HTTP协议通信,Service Mesh也许会通过电缆将之转换为HTTPS,而且应用程序并不知晓。Service Mesh也可以做连接池、权限控制,或其它的传输层特性,并且是以对应用程序透明的方式。

为了完美的做到这些,Linkerd必须作为本地实例的代理处于请求的发送端与接收端。例如HTTP升级为HTTPS,Linkerd一定要在传输层协议的开始与结束。在DaemonSet的世界,一个通过Linkerd的请求路线看起来如下图所示:





 
正如你所见,一个从Host 1中Pod A发起的目标为Host 2中Pod B的请求必须通过Pod A的本地Linkerd实例,然后到达Host 2的Linkerd实例,最后到达Pod J。这个路径引入了Linkerd必须解决的三个问题:


应用如何定位它的本地Linkerd

Linkerd如何将传出请求路由到目标Linkerd

Linkerd如何将传入请求路由到目标应用

接下来就讲述我们如何解决这三个问题的技术细节。
 
 

应用程序如何定位它的本地Linkerd
因为DaemonSet使用Kubernetes的host端口,我们就知道Linkerd运行于host IP的一个固定端口。因此,为了发送一个请求给运行于同一宿主机的Linkerd进程,我们需要确定这个主机的IP地址。

在Kubernetes 1.4及其以后的版本,此信息可通过底层API直接获取到。以下是来自hello-world.yaml的摘要,显示了如何将节点名称传递到应用程序中:
env: - name: NODE_NAME  valueFrom:    fieldRef:      fieldPath: spec.nodeName - name: http_proxy  value: $(NODE_NAME):4140 args: - "-addr=:7777" - "-text=Hello" - "-target=world"
 
(请注意,此例设置http_proxy环境变量以引导通过本地Linkerd实例的所有HTTP调用。然而此方法仅适用于大多数的HTTP应用,非HTTP应用需要做一些不同的工作)

Kubernetes 1.4之前的版本这些信息仍旧可用,但是方式要间接一些。

以下是hello-world-legacy.yml的一部分,显示如何将主机IP传递到应用程序中。
env: - name: POD_NAME  valueFrom:    fieldRef:      fieldPath: metadata.name - name: NS  valueFrom:    fieldRef:      fieldPath: metadata.namespace command: - "/bin/sh" - "-c" - "http_proxy=`hostIP.sh`:4140 helloworld -addr=:7777 -text=Hello -target=world"
 
请注意,hostIP.sh脚本需要将pod名和命名空间以环境变量的方式注入pod中。



Linkerd如何将传出请求路由到目标Linkerd
在我们的Service Mesh部署中,传出请求不应当直接发送给目标应用,而应当发送给运行于应用程序所在主机的Linkerd。为了做到这点,我们可以利用Linkerd 0.8.0引入的被称为transformer的新特性,它可以对Linker路由到的目标地址进行任意的后期处理。在这种情况下,我们可以使用DaemonSet transformer自动的让运行于目标主机的DaemonSet的地址取代目标地址。例如,这个Linkerd传出路由配置发送所有的请求到运行于相同主机的作为目标应用的Linkerd的输入端口。
 
routers: - protocol: http  label: outgoing  interpreter:    kind: default    transformers:    - kind: io.l5d.k8s.daemonset      namespace: default      port: incoming      service: l5d  ...

Linkerd如何将输入请求路由到目标应用
当一个请求最终到达目标pod的Linkerd实例,它一定得正确的路由到该pod。为此,我们使用localnode transformer将路由限制在运行于本地主机的pod。Linkerd配置示例如下:
routers: - protocol: http  label: incoming  interpreter:    kind: default    transformers:    - kind: io.l5d.k8s.localnode  ...


将Linkerd作为Kubernetes DaemonSet部署使得两全其美——它让我们完成service mesh的全部目标(如透明的TLS、协议升级、延迟感知负载均衡等等),同时按每个host扩缩Linkerd实例而非每个pod。
 
  查看全部
作者:ALEX LEONG


翻译:平凡

转自:容器时代(CaaSOne)
 
Service Mesh,一个为云平台而设计的应用,云平台的本地应用该如何使用它?本文中,我们将讲述在Kubernetes中如何应用Linkerd作为Service Mesh,如何捕获和报告顶层服务指标如成功率、请求量和延迟,而不需要更改应用的代码。


注意:这是关于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




使用service mesh的必要性

关于Linkerd最常见的一个疑问就是,到底什么是Service Mesh?当Kubernetes已经提供了如Service资源对象、负载均衡这样的基本功能后,为什么Service Mesh要作为云本地应用程序的关键组件。


简单来说,Service Mesh这一层管理着应用之间的通信(或者部分应用之间的通信如微服务)。传统应用中,这个逻辑直接构建到应用程序本身中:重试和超时,监控/可见性,追踪,服务发现等等。这些都被硬编码到每个应用程序中。

然而,随着应用程序架构被越来越多的分割成服务,将通信逻辑从应用中移出到底层基础设施中变得越来越重要。就像是应用程序不应该写它自己的TCP栈,他们也不应该管理自己的负载均衡逻辑,或他们自己的服务发现管理程序,以及他们自己的重试和超时逻辑。

像Linkerd这样的Service Mesh为大规模多服务应用程序提供关键的部件:

基本的适应性功能:重试预算,deadline,熔断器模式

顶层的服务指标:成功率,请求量,延迟

延迟和失败容忍度:感应失败和延迟的负载均衡,它可以绕过缓慢的或者损坏的服务实例

分发追踪:如Zipkin和OpenTracing

服务发现:找到目标实例

协议升级:在TLS中包装跨网络通信,或将HTTP/1.1转换为HTTP/2.0

路由:不同版本的服务之间的路由请求,集群之间的故障转移等



在这部分中,我们仅重点关注可见性:Service Mesh是如何自动捕获并报告如成功率等顶层服务指标的,我们将展示一个Kubernetes的小例子以此来引导你。
 
在Kubernetes中使用Linkerd作为Service的检测器
 
在请求层进行操作的一个优势是Service Mesh可以访问成功和失败的协议级语义。举个例子,如果你正在运行一个HTTP服务,Linkerd可以理解200 、400、500响应的含义,从而可以自动计算如成功率这样的指标。

让我们通过一个小例子讲解如何在Kubernetes中安装Linkerd,从而自动的捕获顶层服务成功率而不需要更改应用程序。
 

安装Linkerd
使用Kubernetes配置文件安装Linkerd。它会将Linkerd作为DaemonSet安装,且运行在Kubernetes的default命名空间:
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/linkerd.yml 
 
你可以通过查看Linkerd的管理页面确认是否安装成功:
INGRESS_LB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}") open http://$INGRESS_LB:9990 # on OS X
 
如果集群不支持外部负载均衡,使用hostIP:
HOST_IP=$(kubectl get po -l app=l5d -o jsonpath="{.items[0].status.hostIP}") open http://$HOST_IP:$(kubectl get svc l5d -o 'jsonpath={.spec.ports[2].nodePort}') # on OS X


1.png



安装样例应用程序
在default命名空间下安装两个Service,“hello”和“world”。这些应用程序依赖于Kubernetes downward API提供的nodeName来发现Linkerd。为了检测你的集群是否支持nodeName,你可以运行:
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/node-name-test.yml 
 
然后看它的日志:kubectl logs node-name-test
 
如果你看到了一个IP就说明支持。接下来继续部署hello world应用程序如下:
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/hello-world.yml 
 
如果你看到报错“server can’t find…”,就部署旧版本hello-world,它依赖于hostIP而非nodeName:kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/hello-world-legacy.yml 
 
这两个Service——“hello”和“world”——功能在一起使得高度可扩展,“hello world”微服务(“hello”Service调用“world”Service完成这个请求)。

你可以通过给Linkerd的外部IP发送请求来查看此操作:
http_proxy=$INGRESS_LB:4140 curl -s http://hello或者直接使用hostIP:http_proxy=$HOST_IP:$(kubectl get svc l5d -o 'jsonpath={.spec.ports[0].nodePort}') curl -s http://hello 
 
你应该可以看到字符串“Hello world”。
 

安装Linkerd-viz
最后,通过安装Linkerd-viz,让我们可以看看Service正在做什么。Linkerd-viz是一个附加包,它包括一个简单的Prometheus和Grafana设置,并可以自动发现Linkerd。
下面的命令会将Linkerd-viz安装到default命名空间下:
kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-viz/master/k8s/linkerd-viz.yml 
 
访问Linkerd-viz的外部IP查看dashboard:
VIZ_INGRESS_LB=$(kubectl get svc linkerd-viz -o jsonpath="{.status.loadBalancer.ingress[0].*}") open http://$VIZ_INGRESS_LB # on OS X
 
如果集群不支持外部负载均衡,使用hostIP:
VIZ_HOST_IP=$(kubectl get po -l name=linkerd-viz -o jsonpath="{.items[0].status.hostIP}") open http://$VIZ_HOST_IP:$(kubectl get svc linkerd-viz -o 'jsonpath={.spec.ports[0].nodePort}') # on OS X
 
你应该在dashboard上看到包括Service与实例的选择器,所有图表都反映了这些Service和实例的选择器。
 

2.png


Linkerd-viz的dashboard包括三部分:

顶层:集群范围的成功率与请求量

Service指标:每个已部署应用的指标,包括成功率、请求量和延迟

单个实例指标:集群上每一个node的成功率、请求量和延迟

用三个简单的命令我们就可以将Linkerd安装在集群上,安装应用,并且使用Linkerd了解应用程序Service的健康状况。当然,Linkerd提供的不仅仅是可见性,还提供了延迟感应负载均衡,自动重试和断路,分发追踪等功能。
 
 
 
第二部分:导言
 
在第一部分里我们提到了Linkerd是使用DaemonSet而非Sidecar来安装的。在第二部分中,我们将解释我们为什么(怎么样)这么做。

注意:这是关于Linkerd、Kubernetes和Service ,esh的系列文章其中一篇,其余部分包括:

Top-line service metrics

Pods are great, until they’re not(本文)

Encrypting all the things

Continuous deployment via traffic shifting

Dogfood environments, ingress, and edge routing

Staging microservices without the tears

Distributed tracing made easy

Linkerd as an ingress controller

gRPC for fun and profit

The Service Mesh API

Egress

Retry budgets, deadline propagation, and failing gracefully

Autoscaling by top-line metrics
 

Linkerd以DaemonSet方式运行


作为Service Mesh,Linkerd设计为与应用程序代码一起运行。它管理和监控service的内部通信,包括服务发现、重试、负载均衡与协议升级。

初次听闻,都会觉得这非常适合在Kubernetes中以Sidecar的方式部署。毕竟,Kubernetes的定义特征之一就是它的pod模型。作为Sidecar部署理论上简单,有清晰的失败语义,我们花了大量时间用于针对该用例的Linkerd优化。

然而,Sidecar模型有其缺陷:部署一个pod就要用掉部署一个pod的资源。如果你的Service较轻量并且跑了许多的应用实例,这样使用Sidecar来部署就会代价极高。

我们可以通过每一个host而非每一个pod部署一个Linkerd来减少资源的开销。它对每个主机进行扩展而消耗资源,这通常是比pod数量要显著更慢的增长的指标。并且很幸运,Kubernetes为此目的提供了DaemonSets。

但美中不足的是,对于Linkerd来说,按每个host部署比仅仅使用DaemonSets要复杂一些。我们如何解决Service Mesh这个问题?请继续阅读下文。
 

Kubernetes的Service 
MeshService Mesh的定义特征之一是它将应用通信与传输通信分离开的能力。例如,如果Service A与B使用HTTP协议通信,Service Mesh也许会通过电缆将之转换为HTTPS,而且应用程序并不知晓。Service Mesh也可以做连接池、权限控制,或其它的传输层特性,并且是以对应用程序透明的方式。

为了完美的做到这些,Linkerd必须作为本地实例的代理处于请求的发送端与接收端。例如HTTP升级为HTTPS,Linkerd一定要在传输层协议的开始与结束。在DaemonSet的世界,一个通过Linkerd的请求路线看起来如下图所示:

31.png

 
正如你所见,一个从Host 1中Pod A发起的目标为Host 2中Pod B的请求必须通过Pod A的本地Linkerd实例,然后到达Host 2的Linkerd实例,最后到达Pod J。这个路径引入了Linkerd必须解决的三个问题:


应用如何定位它的本地Linkerd

Linkerd如何将传出请求路由到目标Linkerd

Linkerd如何将传入请求路由到目标应用

接下来就讲述我们如何解决这三个问题的技术细节。
 
 

应用程序如何定位它的本地Linkerd
因为DaemonSet使用Kubernetes的host端口,我们就知道Linkerd运行于host IP的一个固定端口。因此,为了发送一个请求给运行于同一宿主机的Linkerd进程,我们需要确定这个主机的IP地址。

在Kubernetes 1.4及其以后的版本,此信息可通过底层API直接获取到。以下是来自hello-world.yaml的摘要,显示了如何将节点名称传递到应用程序中:
env: - name: NODE_NAME  valueFrom:    fieldRef:      fieldPath: spec.nodeName - name: http_proxy  value: $(NODE_NAME):4140 args: - "-addr=:7777" - "-text=Hello" - "-target=world"
 
(请注意,此例设置http_proxy环境变量以引导通过本地Linkerd实例的所有HTTP调用。然而此方法仅适用于大多数的HTTP应用,非HTTP应用需要做一些不同的工作)

Kubernetes 1.4之前的版本这些信息仍旧可用,但是方式要间接一些。

以下是hello-world-legacy.yml的一部分,显示如何将主机IP传递到应用程序中。
env: - name: POD_NAME  valueFrom:    fieldRef:      fieldPath: metadata.name - name: NS  valueFrom:    fieldRef:      fieldPath: metadata.namespace command: - "/bin/sh" - "-c" - "http_proxy=`hostIP.sh`:4140 helloworld -addr=:7777 -text=Hello -target=world"
 
请注意,hostIP.sh脚本需要将pod名和命名空间以环境变量的方式注入pod中。



Linkerd如何将传出请求路由到目标Linkerd
在我们的Service Mesh部署中,传出请求不应当直接发送给目标应用,而应当发送给运行于应用程序所在主机的Linkerd。为了做到这点,我们可以利用Linkerd 0.8.0引入的被称为transformer的新特性,它可以对Linker路由到的目标地址进行任意的后期处理。在这种情况下,我们可以使用DaemonSet transformer自动的让运行于目标主机的DaemonSet的地址取代目标地址。例如,这个Linkerd传出路由配置发送所有的请求到运行于相同主机的作为目标应用的Linkerd的输入端口。
 
routers: - protocol: http  label: outgoing  interpreter:    kind: default    transformers:    - kind: io.l5d.k8s.daemonset      namespace: default      port: incoming      service: l5d  ...

Linkerd如何将输入请求路由到目标应用
当一个请求最终到达目标pod的Linkerd实例,它一定得正确的路由到该pod。为此,我们使用localnode transformer将路由限制在运行于本地主机的pod。Linkerd配置示例如下:
routers: - protocol: http  label: incoming  interpreter:    kind: default    transformers:    - kind: io.l5d.k8s.localnode  ...


将Linkerd作为Kubernetes DaemonSet部署使得两全其美——它让我们完成service mesh的全部目标(如透明的TLS、协议升级、延迟感知负载均衡等等),同时按每个host扩缩Linkerd实例而非每个pod。
 
 

年度盘点2017之Service Mesh:群雄逐鹿烽烟起

ServiceMesh小数 发表了文章 • 0 个评论 • 1038 次浏览 • 2017-12-29 14:21 • 来自相关话题

 
 敖小剑/数人云资深架构师

十五年软件开发经验,微服务专家,专注于基础架构,Cloud Native拥护者,敏捷实践者。曾在亚信,爱立信,唯品会和PPmoney任职。


前言
在过去的2016年和2017年,微服务技术得以迅猛普及,和容器技术一起成为这两年中最吸引眼球的技术热点。而以Spring Cloud为代表的传统侵入式开发框架,占据着微服务市场的主流地位,它甚至一度成为微服务的代名词。

直到2017年年底,当非侵入式的Service Mesh技术终于从萌芽到走向了成熟,当Istio/Conduit横空出世,人们才惊觉:微服务并非只有侵入式一种玩法,更不是Spring Cloud的独角戏!

这一次的新生力量,完全不按照常理出牌,出场就霸道地掀翻桌子,直接摆出新的玩法:Service Mesh,下一代微服务!这一场大战,在 2017 年的最后一个月,终于上演到白热化,被摆上了台面,受到越来越多人关注。往日霸主 Spring Cloud,此时只能沦为看客。

2017 年的 Service Mesh 历程,在平淡中开始,如戏剧般结束,留给我们一个充满想象和憧憬的 2018。让我们一起来回顾这堪称精彩的一年。
 
Service Mesh 的萌芽期
在我们正式开始 2017 年回顾之前,我们将时间稍微放前一点,回到 2016 年,有些故事背景需要预先交代一下。

虽然直到 2017 年年底,Service Mesh 才开始较大规模被世人了解,这场微服务市场之争也才显现,但是其实 Service Mesh 这股微服务的新势力,早在 2016 年年初就开始萌芽:

2016 年 1 月 15 日,离开 Twitter 的基础设施工程师 William Morgan 和 Oliver Gould,在 GitHub 上发布了 Linkerd 0.0.7 版本,他们同时组建了一个创业小公司 Buoyant,业界第一个 Service Mesh 项目诞生。

2016 年,Matt Klein 在 Lyft 默默地进行 Envoy 的开发。Envoy 诞生的时间其实要比 Linkerd 更早一些,只是在 Lyft 内部不为人所知。

在 2016 年年初,“Service Mesh”还只是 Buoyant 公司的内部词汇,而之后,它开始逐步走向社区:

2016 年 9 月 29 日在 SF Microservices 上,“Service Mesh”这个词汇第一次在公开场合被使用。这标志着“Service Mesh”这个词,从 Buoyant 公司走向社区。

2016 年 10 月,Alex Leong 开始在 Buoyant 公司的官方 Blog 中连载系列文章“A Service Mesh for Kubernetes”。随着“The Services must Mesh”口号的喊出,Buoyant 和 Linkerd 开始 Service Mesh 概念的布道。

在这一年中,第一代的 Service Mesh 产品在稳步推进:

2016 年 9 月 13 日,Matt Klein 宣布 Envoy 在 GitHub 开源,直接发布 1.0.0 版本。

2016 年下半年,Linkerd 陆续发布了 0.8 和 0.9 版本,开始支持 HTTP/2 和 gRPC,1.0 发布在即;同时,借助 Service Mesh 在社区的认可度,Linkerd 在年底开始申请加入 CNCF。

而在这个世界的另外一个角落,Google 和 IBM 两位巨人,握手开始合作,他们联合 Lyft,启动了 Istio 项目。这样,在第一代 Service Mesh 还未走向市场主流时,以 Istio 为代表的第二代 Service Mesh 就迫不及待地上路。

现在我们可以进入主题,开始 2017 年 Service Mesh 发展历程的回顾。
 
急转而下的 Linkerd
 
2017 年,Linkerd 迎来了一个梦幻般的开局,喜讯连连:

2017 年 1 月 23 日,Linkerd 加入 CNCF。

2017 年 3 月 7 日,Linkerd 宣布完成千亿次产品请求。

2017 年 4 月 25 日,Linkerd 1.0 版本发布。

可谓各条战线都进展顺利:产品完成 1.0 release,达成最重要的里程碑;被客户接受并在生产线上成功大规模应用,这代表着市场的认可;进入 CNCF 更是意义重大,这是对 Linkerd 的极大认可,也使得 Linkerd 声名大噪,一时风光无量。

需要特别指出的是,Linkerd 加入 CNCF,对于 Service Mesh 技术是一个非常重要的历史事件:这代表着社区对 Service Mesh 理念的认同和赞赏,Service Mesh 也因此得到社区更大范围的关注。

趁热打铁,就在 Linkerd 1.0 版本发布的同一天,创作者继续 Service Mesh 的布道:

2017 年 4 月 25 日,William Morgan 发布博文“What’s a service mesh? And why do I need one?”。正式给 Service Mesh 做了一个权威定义。

然而现实总是那么残酷,这个美好的开局,未能延续多久就被击碎:

2017 年 5 月 24 日,Istio 0.1 release 版本发布,Google 和 IBM 高调宣讲,社区反响热烈,很多公司在这时就纷纷站队表示支持 Istio。

Linkerd 的风光瞬间被盖过,从意气风发的少年一夜之间变成过气网红。当然,从产品成熟度上来说,linkerd 作为业界仅有的两个生产级 Service Mesh 实现之一,暂时还可以在 Istio 成熟前继续保持市场。但是,随着 Istio 的稳步推进和日益成熟,外加第二代 Service Mesh 的天然优势,Istio 取代第一代的 Linkerd 只是个时间问题。

面对 Google 和 IBM 加持的 Istio,Linkerd 实在难有胜算:

Istio 作为第二代 Service Mesh,通过控制平面带来了前所未有的控制力,远超 Linkerd。

Istio 通过收编和 Linkerd 同为第一代 Service Mesh 的 Envoy,直接拥有了一个功能和稳定性与 Linkerd 处在一个水准的数据平面(也就是作为 sidecar 模式部署的 proxy)。

基于 C++ 的 Envoy 在性能和资源消耗上本来就强过基于 Scala/JVM 的 Linkerd。

Google 和 IBM 组合在人力、资源和社区方面的影响力远非 Buoyant 这样的小公司可以比拟。

Linkerd 的发展态势顿时急转而下,未来陷入一片黑暗。出路在哪里?

在一个多月后,Linkerd 给出一个答案:和 Istio 集成,成为 Istio 的数据面板:

2017 年 7 月 11 日,Linkerd 发布版本 1.1.1,宣布和 Istio 项目集成。Buoyant 发表博文“Linkerd and Istio: like peanut butter and jelly”。

这个方案在意料之中,毕竟面对 Google 和 IBM 的联手威胁,选择低头和妥协是可以理解的,只是这里边存在两个疑问:

1、和 Envoy 相比,Linkerd 并没有特别优势,考虑编程语言的天生劣势,Linkerd 想替代 Envoy 难度非常之大。

2、即使替代成功,在 Istio 的架构下,只是作为一个数据平面存在的 Linkerd,可以发挥的空间有限。这种境地的 Linkerd,是远远无法承载起 Buoyant 的未来的。

Linkerd 的这个谜团,直到 2017 年即将结束的 12 月,在 Conduit 发布之后才被解开。
 
波澜不惊的 Envoy
自从在 2016 年决定委身于 Istio 之后,Envoy 就开始波澜不惊地平稳发展,这和 Linkerd 的跌宕起伏完全不同。

在功能方面,由于定位在数据平面,因此 Envoy 无需考虑太多,很多工作在 Istio 的控制平面完成就好,Envoy 从此专心于将数据平面做好,完善各种细节。在市场方面,Envoy 和 Linkerd 性质不同,不存在生存和发展的战略选择,也没有正面对抗生死大敌的巨大压力。Envoy 在 2017 年有条不紊地陆续发布了 1.2、1.3、1.4 和 1.5 版本,稳步地完善自身,表现非常稳健。

稳扎稳打的 Envoy 在 2017 年一方面继续收获独立客户,一方面伴随 Istio 一起成长。作为业界仅有的两个生产级 Service Mesh 实现之一,Envoy 随后收获了属于它的殊荣:

2017 年 9 月 14 日,Envoy 加入 CNCF,成为 CNCF 的第二个 Service Mesh 项目。

可谓名至实归,水到渠成。作为一个无需承载一家公司未来的开源项目,Envoy 在 2017 年的表现,无可挑剔。
 
背负使命的 Istio
 
从 Google 和 IBM 联手决定推出 Istio 开始,Istio 就注定永远处于风头浪尖,无论成败。

Istio 背负了太多的使命:

建立 Google 和 IBM 在微服务市场的统治地位。

为 Google 和 IBM 的公有云打造杀手锏级特性。

在 k8s 的基础上,延续 Google 的战略布局。

Google 在企业市场的战略布局,是从底层开始,一步一步向上,一步一步靠近应用。刚刚大获全胜的 k8s 为 Istio 准备了一个非常好的基石,而 Istio 的历史使命,就是继 k8s 拿下容器编排之后,更进一步,拿下微服务!

2017 年,Istio 稳步向前,先后发布四个版本:

2017 年 5 月 24 日,Istio 0.1 release 版本发布。

2017 年 10 月 4 日,Istio 0.2 release 版本发布。

2017 年 11 月 30 日,Istio 0.3 release 版本发布。

2017 年 12 月 15 日,Istio 0.4 release 版本发布。

在社区方面,Istio 借助 Google 和 IBM 的大旗,外加自身过硬的实力、先进的理念,很快获得了社区的积极响应和广泛支持。包括 Oracle 和 Red Hat 在内的业界大佬都明确表示对支持 Istio。

在平台支持方面,Istio 的初期版本只支持 k8s 平台,从 0.3 版本开始提供对非 k8s 平台的支持。从策略上说,Istio 借助了 k8s,但是没有强行绑定在 k8s 上。

Istio 面世之后,赞誉不断,尤其是 Service Mesh 技术的爱好者,可以说是为之一振:以新一代 Service Mesh 之名横空出世的 Istio,对比 Linkerd,优势明显。同时产品路线图上有一大堆令人眼花缭乱的功能。假以时日,如果 Istio 能顺利地完成开发,稳定可靠,那么这会是一个非常美好、值得憧憬的大事件,它的意义重大:

重新定义微服务开发方式,让 Service Mesh 成为主流技术。

大幅降低微服务开发的入门门槛,让更多的企业和开发人员可以落地微服务。

统一微服务的开发流程,标准化开发 / 运维方式。

奈何,事情的发展总是不会这么简单地如人所愿。Istio 发布之后,试用中就被发现问题较多,0.1 版本时还比较容易被接受,但是接下来的 0.2、0.3 和 0.4,Istio 在可用性上并没有明显的改观,导致迄今在全球范围内都几乎没有听到 Istio 上生产的案例,公司都将其停留在简单试用阶段。

此时再看 Istio 琳琅满目的各种功能,不禁让人疑惑 Istio 的产品策略:为什么一开场就将摊子铺的如此之大?以至于开发时间长达一年 (注意,虽然开源才半年多,但是开源前已经在开发),却无法得到一个稳定可用的版本。

这有悖于互联网产品的开发理念。下边这个经典图片相信大家并不陌生:

从目前情景看,Istio 已经在图上“不应该”的产品迭代路径上走了一年。从 5 月份 0.1 版本发布开始,我们就满心期待,却陷入“过尽千帆皆不是”的尴尬境地:每一次新版本试用后的结果,都不理想。

身处局外,无法了解 Istio 项目开发的背景和真实情况,也自然无法得知为何会如此,我们只能由衷地希望,Istio 能在 2018 年尽快完成计划中的产品开发,实现生产可用。个人意见:哪怕推迟某些特性的实现,也希望能做到主体部分尽快完善。

2018 年 Service Mesh 的整体走势,很大程度取决于 Istio:如果 Istio 能在 2018 年上半年实现生产可用,哪怕是牺牲部分高级特性,也足以推动整个 Service Mesh 向前大步迈进。反之如果进展不顺,市场会呈现观望和等待的态势,也会给竞争对手机会,比如说,下面将要出场的 Conduit。
 
背水一战的 Conduit
 
2017 年底的 KubeConf,在 Service Mesh 成为大会热点、Istio 备受瞩目时,Buoyant 公司出人意料地给了踌躇满志又稍显拖沓的 Istio 重重一击:

2017 年 12 月 5 日,Conduit 0.1.0 版本发布,Istio 的强力竞争对手亮相 KubeConf。

Conduit 的整体架构和 Istio 一致,借鉴了 Istio 数据平面 + 控制平面的设计,同时别出心裁地选择了 Rust 编程语言来实现数据平面,以达成 Conduit 宣称的更轻、更快和超低资源占用。

继 Isito 之后,业界第二款第二代 Service Mesh 产品就此诞生。话说得有些拗口,但是一场大战就此浮出水面。Buoyant 在 Linkerd 不敌 Istio 的恶劣情况下,绝地反击,祭出全新设计的 Conduit 作为对抗 Istio 的武器。

需要额外指出的是,作为一家初创型企业,在第一款主力产品 Linkerd 被 Istio 强力阻击之后,Buoyant 已经身陷绝境,到了生死存亡之秋,作为背负公司期望,担负和 Istio 正面抗衡职责的 Conduit,可谓压力巨大。

从目前得到的信息分析,Conduit 明显是有备而来,针对 Istio 当前状况,针锋相对的:

编程语言:为了达成更轻、更快和更低资源消耗的目标,考虑到 Istio 的数据面板用的是基于 C++ 语言的 Envoy,Conduit 跳过了 Golang,直接选择了 Rust,颇有些剑走偏锋的意味。不过,单纯以编程语言而言,在能够完全掌握的前提下,Rust 的确是做 proxy 的最佳选择。考虑到 Envoy 在性能方面的良好表现,Conduit 要想更进一步,选择 Rust 也是可以理解。

架构设计:在借鉴 Istio 整体架构的同时,Conduit 做了一些改进。首先 Conduit 控制平面的各个组件是以服务的方式提供功能的,极富弹性。另外,控制平面特意为定制化需求进行了可扩展设计,可以通过编写 gPRC 插件来扩展 Conduit 的功能而无需直接修改 Conduit,这对于有定制化需求的客户是非常便利的。

产品演进:这是最重要的一点!Conduit 完全吸取了 Istio 的教训,因此它的产品迭代路径会是我们最期待的方式。在本文撰写期间,笔者特意和 Conduit 的 CEO William 深入探讨过这个话题,得到了一个非常令人欣慰的答复:Minimal feature set,prod ready as quickly as possible。

然而,要抗衡 Istio 和其身后的 Google 与 IBM,谈何容易。Conduit 2018 年的发展道路,注定是充满挑战的,艰难险阻可想而知。但是,不得不佩服 Buoyant 公司,以及以 CEO William 为首的那支充满挑战精神的团队,有理想、有追求、有魄力、有勇气!期待他们在 2018 年的表现。

让我们回到 Istio 和 Conduit 的竞争格局。从目前局面看,Istio 先天优势明显,但是产品策略上的选择给了 Conduit 一个难得的机会。接下来的 2018 年,在 Conduit 的威胁和刺激下,希望 Istio 能打起精神,给出一份令大家满意的答卷。期待 Istio 和 Conduit 能在 2018 年形成良性竞争,共同引领 Service Mesh 的大潮。
 
低调的参与者
 
2017 年的 Service Mesh,除了业界先驱 Linkerd/Envoy,和后起之秀 Istio/Conduit,还有一些其它的竞争者进入这个市场,只是它们都非常低调。

首先是 nginMesh,来自大名鼎鼎的 Nginx:

2017 年 9 月,在美国波特兰举行的 nginx.conf 大会上,Nginx 宣布了 nginMesh。随即在 GitHub 上发布了 0.1.6 版本。

2017 年 12 月 6 日,nginMesh 0.2.12 版本发布。

2017 年 12 月 25 日,nginMesh 0.3.0 版本发布。

nginMesh 的定位是作为 Istio 的服务代理,也就是替代 Envoy,思路和 Linkerd 之前和 Istio 集成很相似。nginMesh 在发布后的两个多月,GitHub 上提交非常少,直到最近突然发力,先后发布了 0.2 和 0.3 版本。不过 nginMesh 极度低调,GitHub 上的 star 也只有不到 100。

然后是 Kong,但是这个比默默无闻的 nginMesh 更加低调,只是曾经有传闻 Kong 有意 Service Mesh,但是后来没了下文。不过 Kong 的 GitHub 项目介绍里,悄悄地加上了 Service Mesh 的字样:Kong is a ××× Microservice Abstraction Layer (also known as an API Gateway, API Middleware or in some cases Service Mesh)。

在 2017 年,这些低调的参与者,几乎没有引起外界任何注意,也无法预期他们在 2018 年会如何表现。从社区的角度,还是希望有更多的参与者进入 Service Mesh 市场,以推动整个市场的健康发展。
 
 
快速升温的国内
 
2017 年,随着 Servic Mesh 的发展,国内技术社区也开始通过新闻报道 / 技术文章等接触 Service Mesh,但是传播范围和影响力都非常有限。直到年底才剧烈升温,开始被国内技术社区关注:

2017 年 10 月 16 日,在 2017 QCon 上海大会上,我做了一个“Service Mesh:下一代微服务”的演讲,成为 Service Mesh 技术在国内大型技术峰会上的第一次亮相。

2017 年 11 月,国内第一个 Service Mesh 技术社区“Service Mesh 中文网”(http://servicemesh.cn) 成立。

2017 年 12 月,在全球架构师峰会(ArchSummit)2017 北京站上,来自华为的田晓亮做了名为“Service Mesh 在华为云的实践”的分享。

2017 年 12 月 16 日,来自新浪微博的周晶做了名为“微博 Service Mesh 实践”的演讲,分享了 Service Mesh 在微博的落地情况。

此外,作为 Servic Mesh 国内最早的开发和实践者的华为和新浪微博,都积极参与开源。其中新浪微博 Service Mesh 的核心实现,跨语言通信和服务治理已经在 Motan 系列项目中提供,而华为也将稍后开源他们基于 Golang 的 Service Mesh 代码实现。

特别要指出的是,华为目前已经在公有云上将 Service Mesh 作为公共服务提供,这在国内公有云中是第一家。预计随着 Service Mesh 的落地和普及,公有云提供生产级别的 Service Mesh 服务将成为标配。在国外 Google/IBM/Amazon 等公有云都有提供 Service Mesh 的计划,相信国内公有云也会陆续跟进。
 
展望 2018
 
2017 年的 Service Mesh 市场,从 Linkerd 的风光无限开始,到 Istio 的横空出世,最后止于 Conduit 的绝地反击,可谓一波三折;产品也经历从第一代的 Linkerd/Envoy,跨越性的演化出第二代的 Istio/Conduit;同时,技术社区的态度也从年初的逐步接受发展到年底的热烈追捧,下面这张 KubeConf 上的图片非常有代表性地展示了社区的热切期望:

然而 Service Mesh 终究是一个新兴的技术,尤其作为未来主流的 Istio/Conduit 迄今还没有实现产品级别可用,因此 2018 年对 Service Mesh 而言,必然不是一帆风顺,必然是充满荆棘和坎坷的。如何实现从技术理念到产品落地,如何实实在在地解决实践中遇到的各种问题,将会是这一年中至关重要的事情。

衷心祝愿 Istio 和 Conduit(也许还有其他的产品)可以在 2018 年快速成长,实现社区期待的功能和可用性,可以真正地实现降低微服务门槛的目标,让 Service Mesh 成为名副其实的下一代微服务。

2018 年的 Service Mesh,值得期望! 查看全部

微信图片_20171229142127.jpg

 
 敖小剑/数人云资深架构师

十五年软件开发经验,微服务专家,专注于基础架构,Cloud Native拥护者,敏捷实践者。曾在亚信,爱立信,唯品会和PPmoney任职。


前言
在过去的2016年和2017年,微服务技术得以迅猛普及,和容器技术一起成为这两年中最吸引眼球的技术热点。而以Spring Cloud为代表的传统侵入式开发框架,占据着微服务市场的主流地位,它甚至一度成为微服务的代名词。

直到2017年年底,当非侵入式的Service Mesh技术终于从萌芽到走向了成熟,当Istio/Conduit横空出世,人们才惊觉:微服务并非只有侵入式一种玩法,更不是Spring Cloud的独角戏!

这一次的新生力量,完全不按照常理出牌,出场就霸道地掀翻桌子,直接摆出新的玩法:Service Mesh,下一代微服务!这一场大战,在 2017 年的最后一个月,终于上演到白热化,被摆上了台面,受到越来越多人关注。往日霸主 Spring Cloud,此时只能沦为看客。

2017 年的 Service Mesh 历程,在平淡中开始,如戏剧般结束,留给我们一个充满想象和憧憬的 2018。让我们一起来回顾这堪称精彩的一年。
 
Service Mesh 的萌芽期
在我们正式开始 2017 年回顾之前,我们将时间稍微放前一点,回到 2016 年,有些故事背景需要预先交代一下。

虽然直到 2017 年年底,Service Mesh 才开始较大规模被世人了解,这场微服务市场之争也才显现,但是其实 Service Mesh 这股微服务的新势力,早在 2016 年年初就开始萌芽:

2016 年 1 月 15 日,离开 Twitter 的基础设施工程师 William Morgan 和 Oliver Gould,在 GitHub 上发布了 Linkerd 0.0.7 版本,他们同时组建了一个创业小公司 Buoyant,业界第一个 Service Mesh 项目诞生。

2016 年,Matt Klein 在 Lyft 默默地进行 Envoy 的开发。Envoy 诞生的时间其实要比 Linkerd 更早一些,只是在 Lyft 内部不为人所知。

在 2016 年年初,“Service Mesh”还只是 Buoyant 公司的内部词汇,而之后,它开始逐步走向社区:

2016 年 9 月 29 日在 SF Microservices 上,“Service Mesh”这个词汇第一次在公开场合被使用。这标志着“Service Mesh”这个词,从 Buoyant 公司走向社区。

2016 年 10 月,Alex Leong 开始在 Buoyant 公司的官方 Blog 中连载系列文章“A Service Mesh for Kubernetes”。随着“The Services must Mesh”口号的喊出,Buoyant 和 Linkerd 开始 Service Mesh 概念的布道。

在这一年中,第一代的 Service Mesh 产品在稳步推进:

2016 年 9 月 13 日,Matt Klein 宣布 Envoy 在 GitHub 开源,直接发布 1.0.0 版本。

2016 年下半年,Linkerd 陆续发布了 0.8 和 0.9 版本,开始支持 HTTP/2 和 gRPC,1.0 发布在即;同时,借助 Service Mesh 在社区的认可度,Linkerd 在年底开始申请加入 CNCF。

而在这个世界的另外一个角落,Google 和 IBM 两位巨人,握手开始合作,他们联合 Lyft,启动了 Istio 项目。这样,在第一代 Service Mesh 还未走向市场主流时,以 Istio 为代表的第二代 Service Mesh 就迫不及待地上路。

现在我们可以进入主题,开始 2017 年 Service Mesh 发展历程的回顾。
 
急转而下的 Linkerd
 
2017 年,Linkerd 迎来了一个梦幻般的开局,喜讯连连:

2017 年 1 月 23 日,Linkerd 加入 CNCF。

2017 年 3 月 7 日,Linkerd 宣布完成千亿次产品请求。

2017 年 4 月 25 日,Linkerd 1.0 版本发布。

可谓各条战线都进展顺利:产品完成 1.0 release,达成最重要的里程碑;被客户接受并在生产线上成功大规模应用,这代表着市场的认可;进入 CNCF 更是意义重大,这是对 Linkerd 的极大认可,也使得 Linkerd 声名大噪,一时风光无量。

需要特别指出的是,Linkerd 加入 CNCF,对于 Service Mesh 技术是一个非常重要的历史事件:这代表着社区对 Service Mesh 理念的认同和赞赏,Service Mesh 也因此得到社区更大范围的关注。

趁热打铁,就在 Linkerd 1.0 版本发布的同一天,创作者继续 Service Mesh 的布道:

2017 年 4 月 25 日,William Morgan 发布博文“What’s a service mesh? And why do I need one?”。正式给 Service Mesh 做了一个权威定义。

然而现实总是那么残酷,这个美好的开局,未能延续多久就被击碎:

2017 年 5 月 24 日,Istio 0.1 release 版本发布,Google 和 IBM 高调宣讲,社区反响热烈,很多公司在这时就纷纷站队表示支持 Istio。

Linkerd 的风光瞬间被盖过,从意气风发的少年一夜之间变成过气网红。当然,从产品成熟度上来说,linkerd 作为业界仅有的两个生产级 Service Mesh 实现之一,暂时还可以在 Istio 成熟前继续保持市场。但是,随着 Istio 的稳步推进和日益成熟,外加第二代 Service Mesh 的天然优势,Istio 取代第一代的 Linkerd 只是个时间问题。

面对 Google 和 IBM 加持的 Istio,Linkerd 实在难有胜算:

Istio 作为第二代 Service Mesh,通过控制平面带来了前所未有的控制力,远超 Linkerd。

Istio 通过收编和 Linkerd 同为第一代 Service Mesh 的 Envoy,直接拥有了一个功能和稳定性与 Linkerd 处在一个水准的数据平面(也就是作为 sidecar 模式部署的 proxy)。

基于 C++ 的 Envoy 在性能和资源消耗上本来就强过基于 Scala/JVM 的 Linkerd。

Google 和 IBM 组合在人力、资源和社区方面的影响力远非 Buoyant 这样的小公司可以比拟。

Linkerd 的发展态势顿时急转而下,未来陷入一片黑暗。出路在哪里?

在一个多月后,Linkerd 给出一个答案:和 Istio 集成,成为 Istio 的数据面板:

2017 年 7 月 11 日,Linkerd 发布版本 1.1.1,宣布和 Istio 项目集成。Buoyant 发表博文“Linkerd and Istio: like peanut butter and jelly”。

这个方案在意料之中,毕竟面对 Google 和 IBM 的联手威胁,选择低头和妥协是可以理解的,只是这里边存在两个疑问:

1、和 Envoy 相比,Linkerd 并没有特别优势,考虑编程语言的天生劣势,Linkerd 想替代 Envoy 难度非常之大。

2、即使替代成功,在 Istio 的架构下,只是作为一个数据平面存在的 Linkerd,可以发挥的空间有限。这种境地的 Linkerd,是远远无法承载起 Buoyant 的未来的。

Linkerd 的这个谜团,直到 2017 年即将结束的 12 月,在 Conduit 发布之后才被解开。
 
波澜不惊的 Envoy
自从在 2016 年决定委身于 Istio 之后,Envoy 就开始波澜不惊地平稳发展,这和 Linkerd 的跌宕起伏完全不同。

在功能方面,由于定位在数据平面,因此 Envoy 无需考虑太多,很多工作在 Istio 的控制平面完成就好,Envoy 从此专心于将数据平面做好,完善各种细节。在市场方面,Envoy 和 Linkerd 性质不同,不存在生存和发展的战略选择,也没有正面对抗生死大敌的巨大压力。Envoy 在 2017 年有条不紊地陆续发布了 1.2、1.3、1.4 和 1.5 版本,稳步地完善自身,表现非常稳健。

稳扎稳打的 Envoy 在 2017 年一方面继续收获独立客户,一方面伴随 Istio 一起成长。作为业界仅有的两个生产级 Service Mesh 实现之一,Envoy 随后收获了属于它的殊荣:

2017 年 9 月 14 日,Envoy 加入 CNCF,成为 CNCF 的第二个 Service Mesh 项目。

可谓名至实归,水到渠成。作为一个无需承载一家公司未来的开源项目,Envoy 在 2017 年的表现,无可挑剔。
 
背负使命的 Istio
 
从 Google 和 IBM 联手决定推出 Istio 开始,Istio 就注定永远处于风头浪尖,无论成败。

Istio 背负了太多的使命:

建立 Google 和 IBM 在微服务市场的统治地位。

为 Google 和 IBM 的公有云打造杀手锏级特性。

在 k8s 的基础上,延续 Google 的战略布局。

Google 在企业市场的战略布局,是从底层开始,一步一步向上,一步一步靠近应用。刚刚大获全胜的 k8s 为 Istio 准备了一个非常好的基石,而 Istio 的历史使命,就是继 k8s 拿下容器编排之后,更进一步,拿下微服务!

2017 年,Istio 稳步向前,先后发布四个版本:

2017 年 5 月 24 日,Istio 0.1 release 版本发布。

2017 年 10 月 4 日,Istio 0.2 release 版本发布。

2017 年 11 月 30 日,Istio 0.3 release 版本发布。

2017 年 12 月 15 日,Istio 0.4 release 版本发布。

在社区方面,Istio 借助 Google 和 IBM 的大旗,外加自身过硬的实力、先进的理念,很快获得了社区的积极响应和广泛支持。包括 Oracle 和 Red Hat 在内的业界大佬都明确表示对支持 Istio。

在平台支持方面,Istio 的初期版本只支持 k8s 平台,从 0.3 版本开始提供对非 k8s 平台的支持。从策略上说,Istio 借助了 k8s,但是没有强行绑定在 k8s 上。

Istio 面世之后,赞誉不断,尤其是 Service Mesh 技术的爱好者,可以说是为之一振:以新一代 Service Mesh 之名横空出世的 Istio,对比 Linkerd,优势明显。同时产品路线图上有一大堆令人眼花缭乱的功能。假以时日,如果 Istio 能顺利地完成开发,稳定可靠,那么这会是一个非常美好、值得憧憬的大事件,它的意义重大:

重新定义微服务开发方式,让 Service Mesh 成为主流技术。

大幅降低微服务开发的入门门槛,让更多的企业和开发人员可以落地微服务。

统一微服务的开发流程,标准化开发 / 运维方式。

奈何,事情的发展总是不会这么简单地如人所愿。Istio 发布之后,试用中就被发现问题较多,0.1 版本时还比较容易被接受,但是接下来的 0.2、0.3 和 0.4,Istio 在可用性上并没有明显的改观,导致迄今在全球范围内都几乎没有听到 Istio 上生产的案例,公司都将其停留在简单试用阶段。

此时再看 Istio 琳琅满目的各种功能,不禁让人疑惑 Istio 的产品策略:为什么一开场就将摊子铺的如此之大?以至于开发时间长达一年 (注意,虽然开源才半年多,但是开源前已经在开发),却无法得到一个稳定可用的版本。

这有悖于互联网产品的开发理念。下边这个经典图片相信大家并不陌生:

从目前情景看,Istio 已经在图上“不应该”的产品迭代路径上走了一年。从 5 月份 0.1 版本发布开始,我们就满心期待,却陷入“过尽千帆皆不是”的尴尬境地:每一次新版本试用后的结果,都不理想。

身处局外,无法了解 Istio 项目开发的背景和真实情况,也自然无法得知为何会如此,我们只能由衷地希望,Istio 能在 2018 年尽快完成计划中的产品开发,实现生产可用。个人意见:哪怕推迟某些特性的实现,也希望能做到主体部分尽快完善。

2018 年 Service Mesh 的整体走势,很大程度取决于 Istio:如果 Istio 能在 2018 年上半年实现生产可用,哪怕是牺牲部分高级特性,也足以推动整个 Service Mesh 向前大步迈进。反之如果进展不顺,市场会呈现观望和等待的态势,也会给竞争对手机会,比如说,下面将要出场的 Conduit。
 
背水一战的 Conduit
 
2017 年底的 KubeConf,在 Service Mesh 成为大会热点、Istio 备受瞩目时,Buoyant 公司出人意料地给了踌躇满志又稍显拖沓的 Istio 重重一击:

2017 年 12 月 5 日,Conduit 0.1.0 版本发布,Istio 的强力竞争对手亮相 KubeConf。

Conduit 的整体架构和 Istio 一致,借鉴了 Istio 数据平面 + 控制平面的设计,同时别出心裁地选择了 Rust 编程语言来实现数据平面,以达成 Conduit 宣称的更轻、更快和超低资源占用。

继 Isito 之后,业界第二款第二代 Service Mesh 产品就此诞生。话说得有些拗口,但是一场大战就此浮出水面。Buoyant 在 Linkerd 不敌 Istio 的恶劣情况下,绝地反击,祭出全新设计的 Conduit 作为对抗 Istio 的武器。

需要额外指出的是,作为一家初创型企业,在第一款主力产品 Linkerd 被 Istio 强力阻击之后,Buoyant 已经身陷绝境,到了生死存亡之秋,作为背负公司期望,担负和 Istio 正面抗衡职责的 Conduit,可谓压力巨大。

从目前得到的信息分析,Conduit 明显是有备而来,针对 Istio 当前状况,针锋相对的:

编程语言:为了达成更轻、更快和更低资源消耗的目标,考虑到 Istio 的数据面板用的是基于 C++ 语言的 Envoy,Conduit 跳过了 Golang,直接选择了 Rust,颇有些剑走偏锋的意味。不过,单纯以编程语言而言,在能够完全掌握的前提下,Rust 的确是做 proxy 的最佳选择。考虑到 Envoy 在性能方面的良好表现,Conduit 要想更进一步,选择 Rust 也是可以理解。

架构设计:在借鉴 Istio 整体架构的同时,Conduit 做了一些改进。首先 Conduit 控制平面的各个组件是以服务的方式提供功能的,极富弹性。另外,控制平面特意为定制化需求进行了可扩展设计,可以通过编写 gPRC 插件来扩展 Conduit 的功能而无需直接修改 Conduit,这对于有定制化需求的客户是非常便利的。

产品演进:这是最重要的一点!Conduit 完全吸取了 Istio 的教训,因此它的产品迭代路径会是我们最期待的方式。在本文撰写期间,笔者特意和 Conduit 的 CEO William 深入探讨过这个话题,得到了一个非常令人欣慰的答复:Minimal feature set,prod ready as quickly as possible。

然而,要抗衡 Istio 和其身后的 Google 与 IBM,谈何容易。Conduit 2018 年的发展道路,注定是充满挑战的,艰难险阻可想而知。但是,不得不佩服 Buoyant 公司,以及以 CEO William 为首的那支充满挑战精神的团队,有理想、有追求、有魄力、有勇气!期待他们在 2018 年的表现。

让我们回到 Istio 和 Conduit 的竞争格局。从目前局面看,Istio 先天优势明显,但是产品策略上的选择给了 Conduit 一个难得的机会。接下来的 2018 年,在 Conduit 的威胁和刺激下,希望 Istio 能打起精神,给出一份令大家满意的答卷。期待 Istio 和 Conduit 能在 2018 年形成良性竞争,共同引领 Service Mesh 的大潮。
 
低调的参与者
 
2017 年的 Service Mesh,除了业界先驱 Linkerd/Envoy,和后起之秀 Istio/Conduit,还有一些其它的竞争者进入这个市场,只是它们都非常低调。

首先是 nginMesh,来自大名鼎鼎的 Nginx:

2017 年 9 月,在美国波特兰举行的 nginx.conf 大会上,Nginx 宣布了 nginMesh。随即在 GitHub 上发布了 0.1.6 版本。

2017 年 12 月 6 日,nginMesh 0.2.12 版本发布。

2017 年 12 月 25 日,nginMesh 0.3.0 版本发布。

nginMesh 的定位是作为 Istio 的服务代理,也就是替代 Envoy,思路和 Linkerd 之前和 Istio 集成很相似。nginMesh 在发布后的两个多月,GitHub 上提交非常少,直到最近突然发力,先后发布了 0.2 和 0.3 版本。不过 nginMesh 极度低调,GitHub 上的 star 也只有不到 100。

然后是 Kong,但是这个比默默无闻的 nginMesh 更加低调,只是曾经有传闻 Kong 有意 Service Mesh,但是后来没了下文。不过 Kong 的 GitHub 项目介绍里,悄悄地加上了 Service Mesh 的字样:Kong is a ××× Microservice Abstraction Layer (also known as an API Gateway, API Middleware or in some cases Service Mesh)。

在 2017 年,这些低调的参与者,几乎没有引起外界任何注意,也无法预期他们在 2018 年会如何表现。从社区的角度,还是希望有更多的参与者进入 Service Mesh 市场,以推动整个市场的健康发展。
 
 
快速升温的国内
 
2017 年,随着 Servic Mesh 的发展,国内技术社区也开始通过新闻报道 / 技术文章等接触 Service Mesh,但是传播范围和影响力都非常有限。直到年底才剧烈升温,开始被国内技术社区关注:

2017 年 10 月 16 日,在 2017 QCon 上海大会上,我做了一个“Service Mesh:下一代微服务”的演讲,成为 Service Mesh 技术在国内大型技术峰会上的第一次亮相。

2017 年 11 月,国内第一个 Service Mesh 技术社区“Service Mesh 中文网”(http://servicemesh.cn) 成立。

2017 年 12 月,在全球架构师峰会(ArchSummit)2017 北京站上,来自华为的田晓亮做了名为“Service Mesh 在华为云的实践”的分享。

2017 年 12 月 16 日,来自新浪微博的周晶做了名为“微博 Service Mesh 实践”的演讲,分享了 Service Mesh 在微博的落地情况。

此外,作为 Servic Mesh 国内最早的开发和实践者的华为和新浪微博,都积极参与开源。其中新浪微博 Service Mesh 的核心实现,跨语言通信和服务治理已经在 Motan 系列项目中提供,而华为也将稍后开源他们基于 Golang 的 Service Mesh 代码实现。

特别要指出的是,华为目前已经在公有云上将 Service Mesh 作为公共服务提供,这在国内公有云中是第一家。预计随着 Service Mesh 的落地和普及,公有云提供生产级别的 Service Mesh 服务将成为标配。在国外 Google/IBM/Amazon 等公有云都有提供 Service Mesh 的计划,相信国内公有云也会陆续跟进。
 
展望 2018
 
2017 年的 Service Mesh 市场,从 Linkerd 的风光无限开始,到 Istio 的横空出世,最后止于 Conduit 的绝地反击,可谓一波三折;产品也经历从第一代的 Linkerd/Envoy,跨越性的演化出第二代的 Istio/Conduit;同时,技术社区的态度也从年初的逐步接受发展到年底的热烈追捧,下面这张 KubeConf 上的图片非常有代表性地展示了社区的热切期望:

然而 Service Mesh 终究是一个新兴的技术,尤其作为未来主流的 Istio/Conduit 迄今还没有实现产品级别可用,因此 2018 年对 Service Mesh 而言,必然不是一帆风顺,必然是充满荆棘和坎坷的。如何实现从技术理念到产品落地,如何实实在在地解决实践中遇到的各种问题,将会是这一年中至关重要的事情。

衷心祝愿 Istio 和 Conduit(也许还有其他的产品)可以在 2018 年快速成长,实现社区期待的功能和可用性,可以真正地实现降低微服务门槛的目标,让 Service Mesh 成为名副其实的下一代微服务。

2018 年的 Service Mesh,值得期望!

深度解析Service Mesh中数据面板与控制面板

ServiceMesh小数 发表了文章 • 0 个评论 • 655 次浏览 • 2017-12-19 18:12 • 来自相关话题

翻译:郑学滢(易宝支付研发工程师) (易宝支付研发工程师)(易宝支付研发工程师)

转自:容器时代(CaaSOne)



服务网格:数据面板 VS  控制面板

近两年来,服务网格(Service Mesh)的思想越来越受欢迎,随着学习该技术的人数激增,我发现所有技术社区里都产生了大量关于如何比较不同工具间差异的问题。

这种情况可以用我在7月份写的一系列推特来总结:
 
服务网格的困惑#1:linkerd ~=nginx ~= haproxy ~= envoy.它们都不等同于 istio,istio完全是个别的东西
 
前面提到的只是数据面板,仅通过它们无法工作,需要将它们配置到其他工具中

istio是实现一致性控制面板的一个实例,可以在该面板的不同层次上,用一 致的方式将一些东西连接在一起
 
在上面的这些推特上,我提到几个不同的项目(Linkerd,NGINX,HAProxy,Envoy,和 Istio),但重点介绍了服务网格数据面板和控制面板。在这篇文章中,我会回顾一下,并深入讨论我对数据面板和控制面板的看法,以及它们是如何与我之前在推特中提到的其他项目相关联的。


什么才是真正的服务网格?







上图在基础层面上说明了服务网格的含义。图中有4个服务集群(A-D),每一个服务实例用sidecar网络代理进行部署。所有网络间的通信(HTTP,REST,gRPC,Redis等)都通过自己的服务实例,这些实例通过本地sidecar代理找到响应的目标实例。因此,外部网络对于服务实例是不可见的,它只知道本地代理的存在。实际上,分布式系统网络已经被服务程序设计人员抽象出来。


数据面板

在服务网格中,sidecar代理执行如下任务:

服务发现:在所有的前后端服务实例中,哪些是可用的?

健康检查:服务发现的前端服务实例是健康并且可以接受网络通信的么?这
可能包括主动(例如外部ping一个到/healthcheck   endpoint的连接)和被动(比如使用3个连续的5xx作为一个不健康声明的指示)的健康检查。

路由:向本地服务实例发送一个rest风格的请求/foo,路由决定该请求应该向
哪个前端服务集群发送。

负载均衡:一旦路由选择了一个提供前端服务的集群,那么请求应该发送给
哪个服务实例?怎么配置超时?熔断怎么设置?如果请求失败了需要重试么?

认证与授权:对于访问的请求,访问者需要使用mTLS或者其他方法加密验
证么?如果验证通过,访问者可以访问请求的endpoint或者收到一个未认证通过的响应么?

可观测性:对于每一个请求,都会生成详细的统计数据,日志信息,和分布式操作记录数据,以便操作者可以理解分布式通信流并对他们发现的问题进行调试。

以上这些都是服务网格数据面板的职责。实际上,sidecar代理本身就是数据面板。换句话说,数据面板对条件转换,转发,和监控每一个由服务实例提供并在服务间传递的网络包负责。


控制面板

sidecar代理数据面板提供的网络抽象是非常奇妙的。然而,这些代理怎么知道将/foo路由到服务B?怎么处理查询到的服务发现数据?负载均衡,超时,熔断机制等是如何按指定配置的?使用蓝/绿或者逐步通信移动语义是如何完成部署的?谁配置全系统的认证和授权?

这些都是服务网格控制面板的职责。控制面板将一些独立无状态的代理构成集合,并把它们转换成一个分布式系统。

我认为许多技术人员觉得数据面板和控制面板划分概念难以理解,是因为多数人熟悉数据面板,而对控制面板是陌生的。我们接触物理网络路由器和交换机已经有很长时间了。我们理解包/请求需要由节点A发送到节点B,这可以用硬件或软件来现实。软件代理这一新类型只是我们以前长期使用的工具的升级版。






然而,我们使用控制面板也已经很长时间了,尽管大多数的网络操作者可能不太知道系统模块的技术成分。原因很简单—现在使用控制面板的人大多数是我们自己。

上图描述了我所说的“人类控制面板”。这种类型的部署工作依旧非常普遍,一个(可能烦躁的)操作人员手动完成静态配置,可能会借助一些脚本工具,然后使用一些特定的进程部署到代理中。然后这些代理会更新配置并继续用它来处理数据面板的任务。






上图描述了一个高级的服务网格控制面板。它由下面的部分构成:


人:仍然存在一个(希望没那么烦躁)人在这个循环中,并由他制定整个系统的决策。

控制面板的用户界面:这个人与某些类型的用户界面交互来控制系统,可能是一个网站入口,一个命令行界面,或者其他一些接口。通过UI,操作者可以获取全局系统配置设置,比如部署控制(蓝/绿和(或者)通信移动),认证和授权设置,路由表详情(比如服务A何时访问/foo,会发生什么),和负载均衡设置(例如超时,重试,熔断机制等)。

任务调度器:服务通过一些调度系统(比如Kubernetes或者Nomad)来运行在设备上。调度器负责将一个服务连同它的sidecar代理绑定在一起。

服务发现:当调度器启动或停止服务实例时,它将服务的生命状态报告给一个服务发现系统。

sidecar代理配置APIs:在需要操作员参与下,sidecar代理能够以最终一致地方式动态地从系统组件中获取声明。整个系统由所有正在运行的服务实例和sidecar代理聚合组成。envoy的通用数据面板API就是这样一个应用于实践的例子。

控制面板的根本目的是设置最终由数据面板发布的策略。许多优秀的控制面板将把系统的更多部分对操作者抽象,且需要更少的操作(假定他们是正常工作的状态)。


数据面板 VS 控制面板小结

服务网格数据面板:接收系统中每一个包或请求。提供服务发现,健康检查,路由,负载均衡,保证服务认证/授权,以及监控的功能。

服务网格控制面板:为正在网格中运行的数据面板提供策略和配置。不接受系统中的任何包或请求。控制面板将所有的数据面板转变为一个分布式系统。


当前项目概览

经过上面的解释,现在看一下服务网格的现状

数据面板:Linked,NGINX,HAProxy,Envoy,Traefik

控制面板:Istio,Nelson,SmartStack

这里简要的讨论造成现在许多生态系统问题的一些因素,就不对每个产品进行深入的分析了。

Linkerd是2016年初第一批出现的服务网格数据面板代理之一,它在提高人们对服务网格设计模式的意识和积极性方面做出了很大的贡献。Envoy则在6个月后发布(虽然在2015年末已经开发完成)。Linkerd和Envoy是人们讨论服务网格时最多提到的2个项目。

Istio在2017年5月宣布完成。它的主要原理与上图描述的优秀控制面板很相似。Istio的默认代理是Envoy。因此,Istio是控制面板,而Envoy是数据面板。很快,Istio获得了许多人的青睐,其他的数据面板开始集成Istio作为Envoy的替代物(Linkerd和NGINX都集成了Istio)。事实上,单一的控制面板使用不同的数据面板可能意味着控制面板和数据面板并不必须紧密的组合使用。一个像Envoy通用数据面板API的API可以在2个系统间建立一个桥梁。

Nelson和SmartStack有利于更进一步地说明控制面板和数据面板的区别。Nelson使用Envoy作为它的代理,并且在HashiCorp堆栈旁构建了一个健壮的服务网格控制面板(Nomad等)。SmartStack也许是服务网格的首批新浪潮。SmartStack组成了像HAProxy或者NGINX这样的控制面板,进一步说明了服务网格控制面板和数据面板解耦的可能性。

服务网格微服务通信体系现在获得许多的关注(就是现在!),任何时刻都有很多项目和供应商参与进来。在接下来的几年内,我们将会看到数据面板和控制面板的许多创新,并更好的集成了不同的组件。最终的结果应该是微服务通信体系对操作者(希望不那么烦躁)来说更加令人惊讶并简单易懂。

要点

一个服务网格有两个不同部分组成:数据面板和控制面板。二者是必须的。缺少任何一个,系统都无法工作。

每个人都熟悉控制面板,虽然控制面板可能是你。

所有的数据面板比较是通过各自的特点,性能,可配置性和可扩展性。

所有的控制面板比较是通过各自的特点,可配置性,可扩展性和可用性。

单一的控制面板可能包含合适的抽象和APIs,以便更多的数据面板可以使用。
  查看全部
翻译:郑学滢(易宝支付研发工程师) (易宝支付研发工程师)(易宝支付研发工程师)

转自:容器时代(CaaSOne)



服务网格:数据面板 VS  控制面板

近两年来,服务网格(Service Mesh)的思想越来越受欢迎,随着学习该技术的人数激增,我发现所有技术社区里都产生了大量关于如何比较不同工具间差异的问题。

这种情况可以用我在7月份写的一系列推特来总结:
 
服务网格的困惑#1:linkerd ~=nginx ~= haproxy ~= envoy.它们都不等同于 istio,istio完全是个别的东西
 
前面提到的只是数据面板,仅通过它们无法工作,需要将它们配置到其他工具中

istio是实现一致性控制面板的一个实例,可以在该面板的不同层次上,用一 致的方式将一些东西连接在一起
 
在上面的这些推特上,我提到几个不同的项目(Linkerd,NGINX,HAProxy,Envoy,和 Istio),但重点介绍了服务网格数据面板和控制面板。在这篇文章中,我会回顾一下,并深入讨论我对数据面板和控制面板的看法,以及它们是如何与我之前在推特中提到的其他项目相关联的。


什么才是真正的服务网格?

11.jpg



上图在基础层面上说明了服务网格的含义。图中有4个服务集群(A-D),每一个服务实例用sidecar网络代理进行部署。所有网络间的通信(HTTP,REST,gRPC,Redis等)都通过自己的服务实例,这些实例通过本地sidecar代理找到响应的目标实例。因此,外部网络对于服务实例是不可见的,它只知道本地代理的存在。实际上,分布式系统网络已经被服务程序设计人员抽象出来。


数据面板

在服务网格中,sidecar代理执行如下任务:

服务发现:在所有的前后端服务实例中,哪些是可用的?

健康检查:服务发现的前端服务实例是健康并且可以接受网络通信的么?这
可能包括主动(例如外部ping一个到/healthcheck   endpoint的连接)和被动(比如使用3个连续的5xx作为一个不健康声明的指示)的健康检查。

路由:向本地服务实例发送一个rest风格的请求/foo,路由决定该请求应该向
哪个前端服务集群发送。

负载均衡:一旦路由选择了一个提供前端服务的集群,那么请求应该发送给
哪个服务实例?怎么配置超时?熔断怎么设置?如果请求失败了需要重试么?

认证与授权:对于访问的请求,访问者需要使用mTLS或者其他方法加密验
证么?如果验证通过,访问者可以访问请求的endpoint或者收到一个未认证通过的响应么?

可观测性:对于每一个请求,都会生成详细的统计数据,日志信息,和分布式操作记录数据,以便操作者可以理解分布式通信流并对他们发现的问题进行调试。

以上这些都是服务网格数据面板的职责。实际上,sidecar代理本身就是数据面板。换句话说,数据面板对条件转换,转发,和监控每一个由服务实例提供并在服务间传递的网络包负责。


控制面板

sidecar代理数据面板提供的网络抽象是非常奇妙的。然而,这些代理怎么知道将/foo路由到服务B?怎么处理查询到的服务发现数据?负载均衡,超时,熔断机制等是如何按指定配置的?使用蓝/绿或者逐步通信移动语义是如何完成部署的?谁配置全系统的认证和授权?

这些都是服务网格控制面板的职责。控制面板将一些独立无状态的代理构成集合,并把它们转换成一个分布式系统。

我认为许多技术人员觉得数据面板和控制面板划分概念难以理解,是因为多数人熟悉数据面板,而对控制面板是陌生的。我们接触物理网络路由器和交换机已经有很长时间了。我们理解包/请求需要由节点A发送到节点B,这可以用硬件或软件来现实。软件代理这一新类型只是我们以前长期使用的工具的升级版。

22.jpg


然而,我们使用控制面板也已经很长时间了,尽管大多数的网络操作者可能不太知道系统模块的技术成分。原因很简单—现在使用控制面板的人大多数是我们自己。

上图描述了我所说的“人类控制面板”。这种类型的部署工作依旧非常普遍,一个(可能烦躁的)操作人员手动完成静态配置,可能会借助一些脚本工具,然后使用一些特定的进程部署到代理中。然后这些代理会更新配置并继续用它来处理数据面板的任务。

33.jpg


上图描述了一个高级的服务网格控制面板。它由下面的部分构成:


人:仍然存在一个(希望没那么烦躁)人在这个循环中,并由他制定整个系统的决策。

控制面板的用户界面:这个人与某些类型的用户界面交互来控制系统,可能是一个网站入口,一个命令行界面,或者其他一些接口。通过UI,操作者可以获取全局系统配置设置,比如部署控制(蓝/绿和(或者)通信移动),认证和授权设置,路由表详情(比如服务A何时访问/foo,会发生什么),和负载均衡设置(例如超时,重试,熔断机制等)。

任务调度器:服务通过一些调度系统(比如Kubernetes或者Nomad)来运行在设备上。调度器负责将一个服务连同它的sidecar代理绑定在一起。

服务发现:当调度器启动或停止服务实例时,它将服务的生命状态报告给一个服务发现系统。

sidecar代理配置APIs:在需要操作员参与下,sidecar代理能够以最终一致地方式动态地从系统组件中获取声明。整个系统由所有正在运行的服务实例和sidecar代理聚合组成。envoy的通用数据面板API就是这样一个应用于实践的例子。

控制面板的根本目的是设置最终由数据面板发布的策略。许多优秀的控制面板将把系统的更多部分对操作者抽象,且需要更少的操作(假定他们是正常工作的状态)。


数据面板 VS 控制面板小结

服务网格数据面板:接收系统中每一个包或请求。提供服务发现,健康检查,路由,负载均衡,保证服务认证/授权,以及监控的功能。

服务网格控制面板:为正在网格中运行的数据面板提供策略和配置。不接受系统中的任何包或请求。控制面板将所有的数据面板转变为一个分布式系统。


当前项目概览

经过上面的解释,现在看一下服务网格的现状

数据面板:Linked,NGINX,HAProxy,Envoy,Traefik

控制面板:Istio,Nelson,SmartStack

这里简要的讨论造成现在许多生态系统问题的一些因素,就不对每个产品进行深入的分析了。

Linkerd是2016年初第一批出现的服务网格数据面板代理之一,它在提高人们对服务网格设计模式的意识和积极性方面做出了很大的贡献。Envoy则在6个月后发布(虽然在2015年末已经开发完成)。Linkerd和Envoy是人们讨论服务网格时最多提到的2个项目。

Istio在2017年5月宣布完成。它的主要原理与上图描述的优秀控制面板很相似。Istio的默认代理是Envoy。因此,Istio是控制面板,而Envoy是数据面板。很快,Istio获得了许多人的青睐,其他的数据面板开始集成Istio作为Envoy的替代物(Linkerd和NGINX都集成了Istio)。事实上,单一的控制面板使用不同的数据面板可能意味着控制面板和数据面板并不必须紧密的组合使用。一个像Envoy通用数据面板API的API可以在2个系统间建立一个桥梁。

Nelson和SmartStack有利于更进一步地说明控制面板和数据面板的区别。Nelson使用Envoy作为它的代理,并且在HashiCorp堆栈旁构建了一个健壮的服务网格控制面板(Nomad等)。SmartStack也许是服务网格的首批新浪潮。SmartStack组成了像HAProxy或者NGINX这样的控制面板,进一步说明了服务网格控制面板和数据面板解耦的可能性。

服务网格微服务通信体系现在获得许多的关注(就是现在!),任何时刻都有很多项目和供应商参与进来。在接下来的几年内,我们将会看到数据面板和控制面板的许多创新,并更好的集成了不同的组件。最终的结果应该是微服务通信体系对操作者(希望不那么烦躁)来说更加令人惊讶并简单易懂。

要点

一个服务网格有两个不同部分组成:数据面板和控制面板。二者是必须的。缺少任何一个,系统都无法工作。

每个人都熟悉控制面板,虽然控制面板可能是你。

所有的数据面板比较是通过各自的特点,性能,可配置性和可扩展性。

所有的控制面板比较是通过各自的特点,可配置性,可扩展性和可用性。

单一的控制面板可能包含合适的抽象和APIs,以便更多的数据面板可以使用。