前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kubernetes的服务网格(第6部分):简单轻松的分期微服务

Kubernetes的服务网格(第6部分):简单轻松的分期微服务

作者头像
Techeek
发布2018-01-15 09:52:00
7530
发布2018-01-15 09:52:00
举报
文章被收录于专栏:云计算云计算

在将代码暴露给生产流量之前,分期新代码是构建可靠的,低故障停机时间软件的关键部分。然而不幸的是,对于微服务来说,每个新服务的添加都提升了分期过程的复杂性,因为服务之间的依赖关系图与服务数量会成正比地增长。在本文中,我们将向您展示linkerd最强大的功能之一,按请求路由,可以让您灵巧地回避这个问题。

本文是关于linkerd,Kubernetes和服务网格一系列文章中的其中一篇文章。本系列的其他部分包括:

  1. 顶层服务指标
  2. 以DaemonSet方式运行linkerd
  3. 加密所有的东西
  4. 通过流量切换进行连续部署
  5. Dogfood环境,入口和边缘路由
  6. 简单轻松的分期微服务(本文)
  7. 如何使分布式跟踪变得容易
  8. 使用Linkerd作为入口控制器
  9. gRPC的乐趣和增益
  10. 服务网格的API
  11. 出口
  12. 重试预算,截止日期传播,且如何优雅失败
  13. 通过顶级指标自动缩放

以下是本文中描述相关概念的视频:

Linkerd是一个原生云应用程序的服务网格。它可以充当一个透明的请求代理,通过包含具有延迟感知负载平衡,重试预算,截止日期和断路等功能的跨服务调用,为应用程序增加一层弹性。

除了提高应用程序的弹性外,linkerd还提供了强大的路由语言,可以在运行时改变服务之间的请求流量。在这篇文章中,我们将演示linkerd在进行路由时候的能力,因为它的能力不仅仅是全局性的,而且还是基于每个请求的。我们将展示如何使用 按请求路由 这个功能来创建特别的分期环境,使我们能够在生产应用程序的环境中测试新的代码,而不必将整个新的代码直接暴露给生产流量。最后,我们将展示这个(通过与使用专用分期环境进行分期作对比)特别的分期环境是如何既不需要与其他团队进行协调,也不需要一个高成本过程来使多个部署环境保持同步的。

为什么我们要进行分期?

为什么分期这么重要?在现代软件开发过程中,代码经过了一系列严格的实践用来评估代码的正确性:代码审查,单元测试,集成测试等。通过这些测试后,我们将转向评估代码的行为:比如新代码的速度有多快?它在负载下是怎样表现的?它如何与运行时的依赖性以及其他的服务进行交互的?

其实这些都是分期环境可以解决的问题。分期的基本原则是,开发环境越接近生产环境,分期就越接近实际。因此,尽管模拟和存根实现对于测试是有意义的,但对于分期来说,我们会希望它能运行实际的服务。这就是为什么我们说最好的分期环境就是它周围的环境和生产环境完全一样。

为什么对于微服务来说分期变得很困难?

当您的应用程序包含许多服务时,这些服务之间的交互会成为端到端应用程序行为的关键组件。而且事实上,应用程序越是被分解到服务中,应用程序运行时的行为就越不仅仅取决于服务本身,还取决于它们之间的交互。

不幸的是,增加服务的数量不光增加了正确分期的重要性,而且还增加了正确分期的难度。让我们来看看几种常见的分期方式,来了解一下为什么它们在多服务环境中会有这些困难。

对于分段来说,常见的选择是共享分期群集,这代表其中您的分期服务与其他分段服务会一起部署到专用的分期环境中。这种方法的问题是在分期过程之中没有开发隔离。举个例子来说,如下图所示,Alex在部署他的Foo服务过程中看到了很奇怪的行为,他会很难确定这个行为的来源 - 因为这可能是由于Alex,Alice或Bob的分期部署引起的,也可能仅仅是数据库中的模拟数据造成的。所以说随着服务,团队和版本的数量都开始增加,保持分期环境与生产同步也会变得非常困难。

那么我们如何解决这个问题呢?解决共享环境中缺乏隔离这个问题的替代方案是“私人的”分期集群或基于每个开发人员的分期集群。在这个集群模型中,每个开发人员都可以根据需要创建一个分期集群。我们为了保持分期的有效性,分期一个服务的同时还需要分期其上游和下游的依赖关系。(例如,在下图中,Alex需要部署Web FE和API,以确保他对Foo服务所做的更改能够正确地反映出来)。不过,在这种情况下,保持部署应用程序拓扑的任意子集所需要的能力也会变得非常复杂,特别是随着应用拓扑变得更大,并且服务具有独立的部署模型的时候。

最后,还有一种方法可以选择(它很普遍但却不是什么好事),就是只要将新代码部署到生产环境中,并在发现缺陷时进行回滚就可以了。当然,这是相当危险的,尤其是对于处理例如金融交易这样一些重要应用的时候可能不是一种特别好的选择。其实还有很多其他的方法可以获得分期环境,但在本文中,我们将描述一个非常直接并且简单的方法。

更好的路径

幸运的是,通过linkerd,我们可以通过创建专门的分段环境来进行升级,而不会产生上述的成本。事实上,在Finagle(linkerd的基本库)中,路由层的主要动机之一就是在Twitter上解决这个问题!

我们再来考虑一下Alex的Foo服务的目标。如果不是为了部署到一个单独的环境,而是为了一个特定的请求,我们是否可以简单地用Foo-staging来代替Foo-production?这可以使我们在不需要除Foo分期之外的任何部署的情况下,安全地分期Foo并同时对抗生产环境。这也是特别分期环境的本质。我们继续通过这个例子来看,对于开发人员来说,他们的负担已经大大缓解了:因为Alex只需简单地安排他的新代码,并在入口请求中设置一个报头,就可以完成了!

linkerd的按请求路由允许我们做到这一点是一件非常值得高兴的事情。我们可以通过链接代理流量的方法,使用l5d-dtab报头为特定的请求设置路由“覆盖” 。这个报头允许您设置路由规则(用Finagle的说法叫做“ Dtabs ”)。例如,dtab规则 /s/foo => /srv/alex-foo 可能会覆盖Foo的生产路线规则。而将此更改附加到单个请求将会允许我们到达Alex的Foo服务,但这样操作也仅限于当前请求。之后,Linkerd会传播这个规则,因此,在这个请求的生命周期中,Alex的Foo服务的任何用法都将在应用程序拓扑的任何地方被正确地处理。

在家里尝试

Kubernetes服务网格这个系列的读者将会注意到,我们已经可以在dogfood的博客文章中看到这个例子。我们部署了一个world-v2 服务,并且我们能够通过该服务中一个包含路由覆盖的简单报头来发送单个的dogfood请求。现在,我们可以使用相同的机制来建立一个专用的分期环境。

接下来让我们部署两个版本的服务,并在生产环境中使用它之前用linkerd的路由功能来测试我们的新服务。我们将把我们的服务helloworld-v1作为我们正在运行的产品服务来部署,然后我们将创建一个专门的临时环境来演示和测试新的世界版本 world-v2

第1步:部署Linkerd和我们的Hello-World服务

我们将使用以前博客文章中的hello world服务,这包含一个调用世界服务的hello服务。

让我们来部署我们的prod环境(linkerd,hello和world服务):

代码语言:javascript
复制
$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/linkerd-ingress.yml
代码语言:javascript
复制
$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/hello-world.yml

我们还要部署我们想要分期的服务,world-v2,它将返回“earth”一词而不是“world”。

代码语言:javascript
复制
$ kubectl apply -f https://raw.githubusercontent.com/linkerd/linkerd-examples/master/k8s-daemonset/k8s/world-v2.yml

第2步:在我们的专用分段环境中使用每个请求进行覆盖

所以,现在我们有了一个运行当中的world-v2,我们会通过运行一个生产拓扑的请求来测试它,它不会命中 world-v1,而是会命中 world-v2。首先,我们通过默认拓扑来运行一个未经修改的请求(您可能需要等待l5d的外部IP出现):

代码语言:javascript
复制
$ INGRESS_LB = $(kubectl get svc l5d -o jsonpath =“{.status.loadBalancer.ingress [0]。*}”)
代码语言:javascript
复制
$ curl  -H  “Host:www.hello.world”  $ INGRESS_LB
代码语言:javascript
复制
Hello(10.196.2.232)world(10.196.2.233)!!

正如我们所期望的那样,Hello (......) World (.....) 将从我们的生产拓扑中返回。

现在,我们应该要如何进行分期环境呢?其实我们所要做的就是传递下面的dtab覆盖,然后通过prod拓扑的请求就会去往 world-v2!dtab覆盖是我们在请求中使用标头传递的另一个dtab条目。因为稍后我们将会首先应用dtab规则,因此这一规则将更换(或覆盖)我们目前的“/host/world=> / srv /world-V1”规则转而通过另外一个发送 /host/world 请求到 /srv/world-v2 的规则代替。

代码语言:javascript
复制
$ curl  -H  “Host:www.hello.world”  -H  “l5d -dtab:/host/world="/srv/world-v2;”  $ INGRESS_LB
代码语言:javascript
复制
Hello(10.196.2.232)earth(10.196.2.234)!!

我们现在会看到“earth”代替了“world”!从和我们现有的生产拓扑结构相连的world-V2服务中,我们成功地获得了该请求,并且没有更改代码或进行额外的部署。这样我们就成功了!正因为这样,分期现在变得非常有趣而且容易。

linkerd的Dtabs路由 都会有很好的文档记录。在开发过程中,您也可以通过http://$INGRESS_LB:9990/delegator使用linkerd的“dtab操场”。通过转到“传出”路由器测试请求名称,例如 /http/1.1/GET/world,您就可以看到linkerd的路由策略正在运行。

在实践中

实际上,使用这种方法还有一些注意事项。首先,我们必须要解决写入生产数据库的问题。相同的dtab覆盖机制可以将任何写入数据发送到临时数据库,或者通过某些应用程序级别的智能手段来将其写入/ dev / null。然而我们建议不要手动创建这些规则,因为这样做可能会发生重大的生产数据错误!

其次,你的应用程序需要转发linkerd的环境头文件才能工作。

最后,我们要确保l5d-dtab 标题不能从外部被设置,这非常重要!在我们“关于在Kubernetes建立dogfood环境”的这篇文章中,我们给出了一个NGINX配置入口的例子,这是一个非常好的例子因为这个配置可以从外部去除未知的头文件。

结论

我们已经演示了如何通过设置按请求路由规则来创建带有linkerd的专用分期环境。使用这种方法,我们可以在无需修改现有代码的情况下,在生产环境中使用分期服务,为我们的分期环境(分期实例本身之外)或为并行环境进行生产和临时调配提供额外的资源。对于具有更复杂应用拓扑的微服务而言,这种方法可以在我们将代码推送到生产阶段之前提供一种简单,低成本的方式来进行分期服务。

有关于在Kubernetes中运行linkerd的更多信息,或者您在设置配置入口时遇到任何问题,请随时访问我们的Linkerd社区Slack,发送邮件到我们的邮件列表或者直接与我们进行联系!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么我们要进行分期?
  • 为什么对于微服务来说分期变得很困难?
  • 更好的路径
  • 在家里尝试
  • 第1步:部署Linkerd和我们的Hello-World服务
  • 第2步:在我们的专用分段环境中使用每个请求进行覆盖
  • 在实践中
  • 结论
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档