前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Kubernetes的服务网格(第2部分):Pod是最基本的操作单元,但不是最好的部署单元

Kubernetes的服务网格(第2部分):Pod是最基本的操作单元,但不是最好的部署单元

作者头像
Techeek
发布2018-01-11 16:25:23
1.2K0
发布2018-01-11 16:25:23
举报
文章被收录于专栏:云计算云计算

在本系列文章的上一篇中,细心的读者注意到,linkerd是使用DaemonSet而不是作为挎斗(SideCar)进程安装的(关于SideCar的概念及翻译引用自Azure技术社区的文档)。在这篇文章中,我们将解释为什么这样做以及怎样做。

作为服务网格,linkerd被设计为与应用程序代码一起运行,管理和监视服务间通信(具体包括执行服务发现,重试,负载均衡和协议升级)。

乍一看,Kubernetes的挎斗方式部署非常适合。毕竟,Kubernetes的一个标志性特点就是就是它的pod模型。作为挎斗部署概念简单且失败语义明确,并且我们之前已经花费了大量时间来优化linkerd在这种场景下的性能

然而,挎斗模型也有一个缺点:每个Pod的部署意味增加部署一个Pod对应的资源成本的开销。如果你的服务是轻量级的,并且需要运行许多实例,比如 Monzo它基于linkerd和Kubernetes建立了一个完整的数字移动银行),这种场景下使用sidecars的成本就会相当高。

我们可以通过为每个主机而不是每个pod部署linker来降低资源成本。这样可以使资源消耗按主机为单位进行扩展,资源的开销一般要比pod慢得多。而且幸运的是Kubernetes专门为此提供了 DaemonSet

但是麻烦的是,对于linkerd,以主机为单元的部署要比使用DaemonSet要复杂一些。请阅读我们如何解决Kubernetes中按主机为单元部署的服务网格问题。

Kubernetes的服务网格

衡量服务网格的一个特征是其将应用通信与传输通信拆分的能力。例如,如果服务A和B使用HTTP,则服务网格可以在不影响应用的情况下将其转换为HTTPS。服务网格也可以实现连接池,准入控制或其他传输层功能,对应用同样是透明的。

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

通过linkerd的请求路径,Host代表主机,每个Pod内封装着各自的应用
通过linkerd的请求路径,Host代表主机,每个Pod内封装着各自的应用

正如你所看到的,从主机1上的Pod A到主机2上的Pod J的请求必须通过Pod A的 host-local linkerd实例,然后到达Host 2的linkerd实例,最后到Pod J。要完成这条路径,linkerd必须解决三个问题:

  • 应用程序如何识别它的 host-local linkerd?
  • linkerd如何将传出的请求路由到目标的链接器?
  • linkerd如何将传入的请求路由到目标应用程序?

以下是我们解决这三个问题的技术细节。如果您只需要实现让 linkerd 与 Kubernetes DaemonSets搭配使用而不想了解细节,请参阅上一篇文章

应用程序如何识别它的 Host-local linkerd?

由于DaemonSets使用了Kubernetes的 hostPort ,我们知道linkerd是在主机IP的固定端口上运行的。为了将请求发送到运行在同一台机器上的 linkerd 进程,我们需要确定其主机的IP地址。

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

代码语言:javascript
复制
        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调用通过 host-local linkerd 实例, 虽然这种方法适用于大多数HTTP应用程序,但是非HTTP应用程序需要做一些不同的事情)。

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

以下是hello-world-legacy.yml的代码片段, 其中包括将主机IP传递到应用程序中的配置:

代码语言:javascript
复制
        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的name和namespace与为pod中的环境变量相一致。

linkerd如何将传出请求路由到目标的 linkerd ?

在我们的服务网格部署中,传出请求不应直接发送到目标应用程序,而应该发送到在该应用程序的主机上运行的linkerd。为此,我们可以利用linkerd 0.8.0引入的一个强大的新特性——transformers,它可以对链接到路由的目标地址的请求进行任意的后处理。在这种情况下,我们可以使用DaemonSet transformer自动将目标地址替换为目标主机上运行的DaemonSet pod的地址。例如,下面的输出路由linkerd 配置会将所有请求发送到与目标应用程序位于同一主机上的linkerd的传入端口:

代码语言:javascript
复制
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 配置示例:

代码语言:javascript
复制
routers:
- protocol: http
  label: incoming
  interpreter:
    kind: default
    transformers:
    - kind: io.l5d.k8s.localnode
  ...

由上可知,将 linkerd 部署为Kubernetes DaemonSet是一件一举两得的好事 - 它既不影响我们使用服务网格要达到的所有目标(如透明TLS,协议升级,支持延迟感知的负载均衡等),又将让linkerd以主机为单元而不是以pod为单元部署 。

如果需要完整的示例,请参阅 上一篇博文,或下载 示例。对于有对这个配置或其他于linkerd相关的问题,欢迎到我们非常活跃的Slack提问, 或者在linkerd discourse下发表话题讨论 。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Kubernetes的服务网格
    • 应用程序如何识别它的 Host-local linkerd?
      • linkerd如何将传出请求路由到目标的 linkerd ?
        • linkerd如何将传入请求路由到目标应用程序?
        相关产品与服务
        服务网格
        服务网格(Tencent Cloud Mesh, TCM),一致、可靠、透明的云原生应用通信网络管控基础平台。全面兼容 Istio,集成腾讯云基础设施,提供全托管服务化的支撑能力保障网格生命周期管理。IaaS 组网与监控组件开箱即用,跨集群、异构应用一致发现管理加速云原生迁移。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档