Kubernetes的服务网格(第2部分):Pods目前看来还是很棒的

在我们最近关于Kubernetes的序列,Kubernetes的服务网格,第一部分:顶级服务质量一文中,细心的读者注意到,linkerd是使用DaemonSet而不是sidecar进程安装的。在这篇文章中,我们将解释我们为什么(以及如何)这样做。

作为服务网格,链接器被设计为与应用程序代码一起运行,管理和监视服务间通信,包括执行服务发现,重连,负载平衡和协议升级。

乍一看,这听起来非常适合Kubernetes的sidecar部署。毕竟,Kubernetes的一个特征就是它的pod模型。作为sidecar的部署理论上很简单,具有明确的失败语义,并且我们已经花费了大量时间来优化此用例的链接器

然而,sidecar模型也有一个缺点:每一个pod的部署将意味着每一个pod消耗的资源都将翻倍。如果你的服务是轻量级的,并且运行了许多实例,比如Monzo在linkerd和Kubernetes之上建立了一个完整的仓库),那么使用sidecars的成本将会相当高。

我们可以通过为每个主机部署链接器而不是每个pod来降低资源成本。这样使资源消耗以主机为规模,这显然比以pod来计数的增量级少得多。而且,幸运的是,Kubernetes为此提供了 DaemonSet

不幸的是,对于链接器,每个主机的部署比使用DaemonSet要复杂一些。以下是我们如何使用Kubernetes中部署每个主机来解决服务网格问题。

Kubernetes的服务网格

服务网格的一个定义特征是其将应用程序通信与传输通信分开的能力。例如,如果服务A和B使用HTTP,则服务网格可能会将其转换为HTTPS而不通知应用程序。服务网格也可以做连接池,准入控制或其他传输层功能,对应用程序也是透明的。

为了完全做到这一点,链接器必须在每个请求的发送端和接收端代理本地实例。例如,对于HTTP到HTTPS的升级,链接器必须能够启动和终止TLS。在DaemonSet中,通过链接器的请求路径如下图所示:

正如你所看到的,一个请求从主机1上的Pod A开始发往主机2上的Pod J必须通过Pod A上的本地主机链接实例,然后到主机2的链接实例,最后到Pod J。这条路径介绍了链接器必须解决的三个问题:

  • 应用程序如何识别它的本地主机链接器?
  • 链接器如何将传出请求路由到目标链接器?
  • 链接器如何将传入请求路由到目标应用程序?

以下是我们如何解决这三个问题的技术细节。如果您只想了解与Kubernetes DaemonSet一起使用的链接器,请参阅上一篇博客文章

应用程序如何识别其主机 - 本地链接器?

由于DaemonSet使用KuberneteshostPort,我们知道链接器在主机IP固定的端口上运行。因此,为了将请求发送到运行在同一台机器上的链接进程,我们需要确定其主机的IP地址。

在Kubernetes 1.4及更高版本中,这些信息可以通过下载的API直接获得。这里是一个除了hello-world.yml之外的例子,它显示了如何将节点名称传给应用程序:

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环境变量使其可以直接对所有通过本地主机链接器连接的HTTP调用可用。尽管这种方法适用于大多数HTTP应用程序,但是非HTTP应用程序仍然需要一些额外的步骤)。

在1.4版以前的Kubernetes版本中,这些信息仍然可用,但是不能直接使用。我们提供了一个简单的脚本查询Kubernetes API来获取主机IP; 这个脚本的输出可以被应用程序使用,或者用来构建一个如上个例子所示的http_proxy环境变量。

以下是来自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 0.8.0引入的一个强大的新特性,称之为转换器,它可以对链接到路由的目标地址进行任意的后续处理。在这种情况下,我们可以使用DaemonSet转换器自动将目标地址转换为目标主机上运行的DaemonSet pod的地址。例如,输出路由器的链接器配置会将所有请求像发送给目标app一样发送到与目标应用程序位于同一主机上的链接器:

routers:
- protocol: http
label: outgoing
interpreter:
kind: default
transformers:
- kind: io.l5d.k8s.daemonset
namespace: default
port: incoming
service: l5d
...

链接器如何将传入请求路由到目标应用程序?

当一个请求最终传输到目标pod的链接器实例时,它必须被正确地路由到pod本身。为此,我们使用localnode转换器将路由限制为仅在当前主机上运行的pod。链接器配置示例:

routers:
- protocol: http
label: incoming
interpreter:
kind: default
transformers:
- kind: io.l5d.k8s.localnode
...

将链接器部署为Kubernetes DaemonSet是两全其美的选择 - 它允许我们完成服务网格的所有目标(如透明TLS,协议升级,延迟感知负载平衡等),同时减少每个主机的链接器实例规模而不是每个pod。

有关完整的工作示例,请参阅上一篇博文,或下载示例应用程序。对于这个配置或其他关于链接器的帮助,请发送到我们活跃的Slack或者在linkerd话题上发表一个话题 。

本文的版权归 lemoon1993 所有,如需转载请联系作者。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏撸码那些事

使用缓存的正确姿势

缓存是现在系统中必不可少的模块,并且已经成为了高并发高性能架构的一个关键组件。这篇博客我们来分析一下使用缓存的正确姿势。

52960
来自专栏计算机视觉

Automatic Photo Adjustment Using Deep Neural Networks 论文实验训练测试部分

安装双系统ubuntu和cuda和 dl_image_enhance安装部分教程,这个小哥哥写的很好 我写下安装cuda_convent_plus和训练测试...

352100
来自专栏精讲JAVA

Java新一代网络编程模型AIO原理及Linux系统AIO介绍

从JDK 7版本开始,Java新加入的文件和网络io特性称为nio2(new io 2, 因为jdk1.4中已经有过一个nio了),包含了众多性能和功能上的改进...

29580

Kafka体系结构:日志压缩

这篇文章是从我们介绍Kafka 体系结构的一系列文章中获得的启发,包括Kafka topic架构,Kafka生产者架构,Kafka消费者架构和Kafka生态系统...

32530
来自专栏MoeLove

[译]Tornado4.3-用户指南

Tornado 4.3于2015年11月6日发布,该版本正式支持Python3.5的async/await关键字,并且用旧版本CPython编译Tornado同...

12140
来自专栏智能计算时代

Envoy架构概览(8):统计,运行时配置,追踪和TCP代理

统计 特使的主要目标之一是使网络可以理解。特使根据配置如何发出大量的统计数据。一般来说,统计分为两类: 下游:下游统计涉及传入的连接/请求。它们由侦听器,HTT...

45050
来自专栏cmazxiaoma的架构师之路

FastDFS蛋疼的集群和负载均衡(五)之tracker配置反向代理

14920
来自专栏马涛涛的专栏

Cookie与Session、LocalStorage与Sessionstorage 对比

SessionStorage 在用户关闭页面(准确的来说是会话(Session)结束)后就失效。其余的和localstorage一样

23220
来自专栏撸码那些事

使用缓存的正确姿势

15070
来自专栏phodal

如何以“正确的姿势”阅读开源软件代码

之前想过写这篇文章,但是没有想到一个好的内容、好的突破点。在《GitHub 漫游指南》指南里,我们提到过《如何在GitHub“寻找灵感(fork)”》,但是并不...

217100

扫码关注云+社区

领取腾讯云代金券