Kubernetes的service mesh – 第二部分:以DaemonSet方式运行linkerd

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 在我们发表的上一篇关于linkerd的文章中提到过,linkerd是使用DaemonSet而非sidecar来安装的。在本文中,我们将解释我们为什么(怎么样)这么做。 注意:这是关于Linkerd、Kubernetes和service mesh的系列文章其中一篇,其余部分包括: Top-line .

在我们发表的上一篇关于linkerd的文章中提到过,linkerd是使用DaemonSet而非sidecar来安装的。在本文中,我们将解释我们为什么(怎么样)这么做。
注意:这是关于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以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 mesh

service 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。

Kubernetes的service mesh – 第二部分:以DaemonSet方式运行linkerd

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
3月前
|
JSON Kubernetes Shell
【Azure K8S | AKS】在不丢失文件/不影响POD运行的情况下增加PVC的大小
【Azure K8S | AKS】在不丢失文件/不影响POD运行的情况下增加PVC的大小
|
13天前
|
Kubernetes 监控 调度
【赵渝强老师】K8s的DaemonSet控制器
DaemonSet控制器确保每个节点上运行一个Pod副本,适用于监控、日志收集等场景。通过示例创建DaemonSet并查看Pod信息,展示了其自动扩展和回收的能力。视频讲解和代码示例详细说明了DaemonSet的使用方法和调度机制。
|
2月前
|
Kubernetes 容器
K8S的Service的LoadBanlance之Metallb解决方案
本文介绍了如何在Kubernetes中使用MetalLB来实现Service的LoadBalancer功能,包括MetalLB的部署、配置、以及通过创建地址池和部署服务来测试MetalLB的过程。
123 1
K8S的Service的LoadBanlance之Metallb解决方案
|
28天前
|
Kubernetes 监控 Cloud Native
|
3月前
|
Kubernetes 网络安全 容器
在K8S中,有个服务使用service的nodeport进行暴露,发现访问不到如何排查?
在K8S中,有个服务使用service的nodeport进行暴露,发现访问不到如何排查?
|
3月前
|
Kubernetes 负载均衡 网络协议
在K8S中,Service的类型有哪几种,请说⼀下他们的用途?
在K8S中,Service的类型有哪几种,请说⼀下他们的用途?
|
3月前
|
Kubernetes API Perl
在K8S中,如何让Pod运行一次?如何解决一次性任务?
在K8S中,如何让Pod运行一次?如何解决一次性任务?
|
3月前
|
Prometheus Kubernetes 监控
在K8S中,DaemonSet类型的资源特性有哪些?
在K8S中,DaemonSet类型的资源特性有哪些?
|
3月前
|
Kubernetes 负载均衡 网络协议
在K8S中,Service的类型有哪些?
在K8S中,Service的类型有哪些?
|
3月前
|
Kubernetes API 容器
在K8S中,Service的Nodeport端口范围?
在K8S中,Service的Nodeport端口范围?