作为我们上个月发布的Linkerd1.0的一部分,我们已经悄悄地看到了很少有人注意的东西——Linkerd的服务网格API。随着1.0版本的发布,我们认为我们需要花些时间来解释这个API的作用,以及它对Linkerd的未来意味着什么。我们还将展示这个API的即将发布的一个功能——动态控制Linkerd的每项服务的通信策略。
今天早上在Gluecon,Buoyant CTO Oliver Gould发表了题为“The Service Mesh”的主题演讲 。在这个主题中,他概述了服务网格的视野,如Linkerd所示例。尽管Linkerd经常被添加到构建在Kubernetes上的增加弹性的系统上,但是服务网格的完整视野远不止于此 。正如William Morgan在他的博客文章"什么是服务网格?"表明的:
服务网格的明确目标是将服务通信从隐形的基础设施领域中转移到生态系统的重要一员 - 在这里可以对其进行监控,管理和控制。
对于Linkerd来说,这意味着它行为的每个方面不应该仅被检测和观察,而是在运行时同样可以控制。理想情况下,应该使用这种可更改性替换旧的版本,不是通过编辑配置文件和热重载,而是通过一个统一的,设计良好的运行时API来实现。
简言之,这就是Linkerd的服务网格API的目的。为此,我们引入了io.l5d.mesh
解释器和 a new gRPC API for Namerd。这些功能一起提供了动态控制路由策略的能力,并形成了Linkerd服务网格API的核心。这是实现对Linkerd行为的每个方面提供统一的全球控制模式的最终目标的第一步。
Linkerd 1.0还引入了一种还没通过服务网格API揭露的新策略——每个服务通信的略。在这篇文章中,我们将展示如何配置这个策略,并且我们将介绍后续将此控件添加到Linkerd的服务网格API所需的工作。
本文是关于Linkerd,Kubernetes和服务网格的一系列文章之一 。本系列的其他部分包括:
Linkerd的新的每项服务 通信政策 是一个经常要求的功能。通信策略涵盖了Linkerd如何代理请求的各个方面,包括:在超时之前我们应该等待服务处理请求多久?哪种请求可以安全重试?我们是否应该加密与TLS的通信,以及我们应该使用哪个证书?等等。
让我们来看看现在如何使用这个策略,以两个具有截然不同的延迟的服务为例。
从一个新的Kubernetes集群开始,让我们部署两个具有不同延迟的服务。我们以hello world
从本系列的其他文章中部署我们熟悉的微服务,只需稍作调整:hello
服务将在配置中添加500ms
人工延迟。
-name:service
image: buoyantio/helloworld:0.1.2
args:
- "-addr=:7777"
- "-text=Hello"
- "-target=world"
- "-latency=500ms"
使用以下命令将其部署到你的Kubernetes集群:
kubectl apply -f https://raw.githubusercontent.com/BuoyantIO/linkerd-examples/master/k8s-daemonset/k8s/hello-world-latency.yml
(注意,在这些博客文章的例子假设Kubernetes在像GKE这种外部负载均衡器IP可用并且不需要使用CNI插件的环境中运行,其他环境中微小的修正-见我们的 Flavors of Kubernetes forum posting 一文介绍如何使用Calico / Weave处理Minikube或用Calico/Weave配置CNI。)
我们下一步将部署Linkerd服务网格。我们希望添加一个超时,以便能中止(并可能重连)时间过长的请求,但是我们遇到了一个问题。该world
服务很快,响应时间在 100ms
以内,但 hello
服务很慢,响应时间超过500ms
。如果我们仅仅设置超时时间100ms
,那么对world
服务的请求将会成功,但是对hello
服务的请求将会超时。另一方面,如果我们设置超时时间超过 500ms
那么我们需要给worl
服务一个比所需的更长的超时时间,这可能会给我们的调用者带来问题 。
为了给每个服务一个适当的超时时间,我们可以使用Linkerd 1.0为每个服务设置精确的新配置为每个服务设置一个单独的通信策略:
service:
kind: io.l5d.static
configs:
- prefix: /svc/hello
totalTimeoutMs: 600ms
- prefix: /svc/world
totalTimeoutMs: 100ms
该配置会建立以下超时:
我们可以使用这个命令来配置Linkerd服务网格:
kubectl apply -f https://raw.githubusercontent.com/BuoyantIO/linkerd-examples/master/k8s-daemonset/k8s/linkerd-latency.yml
一旦Kubernetes为Linkerd提供了一个外部的负载均衡 IP,我们就可以用它测试hello
和 world
两个服务的请求,并确保两者在各自的超时时间内处理。
$ L5D_INGRESS_LB=$(kubectl get svc l5d -o jsonpath="{.status.loadBalancer.ingress[0].*}")
$ curl $L5D_INGRESS_LB:4140 -H "Host: hello"
Hello (10.196.1.242) world (10.196.1.243)!!
$ curl $L5D_INGRESS_LB:4140 -H "Host: world"
world (10.196.1.243)!!
(注意,前几个请求会比较慢,因为它们必须建立连接并可能超时,后续请求都会成功。)
我们还可以手动地增加hello
和world
服务的等待时间直到他们超时为止来检查它们的超时时间。我们将将增加hello
服务的手动延迟到600ms
。考虑到hello
服务的超时时间是600ms
这留给hello服务的开销为零,因此每个请求都该设置超时如下:
$ curl "$L5D_INGRESS_LB:4140/setLatency?latency=600ms" -X POST -H "Host: hello"
ok
$ curl $L5D_INGRESS_LB:4140 -H "Host: hello"
exceeded 600.milliseconds to unspecified while waiting for a response for the request, including retries (if applicable). Remote Info: Not Available
同样,我们可以 给 world
服务添加100ms
人为延迟,这将导致所有请求到 world
服务违反100ms
超时。
$ curl "$L5D_INGRESS_LB:4140/setLatency?latency=100ms" -X POST -H "Host: world"
ok
$ curl $L5D_INGRESS_LB:4140 -H "Host: world"
exceeded 100.milliseconds to unspecified while waiting for a response for the request, including retries (if applicable). Remote Info: Not Available
一切顺利!我们为每个服务设置了合适的超时时间,并且证明了这些超时有(或者)没有违反预期。
在这个例子中,我们只是配置超时,但是,正如你所期望的那样,可以使用相同的模式来配置任何类型的每项服务通信策略,包括响应分类或重估预算。
在这篇文章中,我们已经看到了一个使用Linkerd的处理两个有很大不同预估延迟的服务的新的策略。每个服务通信策略的引入为Linkerd用户解决了一些直接的用例。但是我们在这里看到的仅仅是Linkerd中通信策略控制的开始——这个策略是从一开始就可以动态更新的,并且明确的目标是使其成为服务网格API的一部分。
在接下来的几个月中,我们将把这个通信策略和路由策略一起添加到Linkerd的服务网格API中。更长远来看,其他形式的策略(包括速率限制,请求分支策略和安全策略 )都在 Linkerd路线图上,并将形成更多Linkerd的服务网格API。Linkerd运行时行为的全面控制,是一个一致统一的,设计良好的服务网格API,是我们将Linkerd作为云本地应用服务网格的核心。