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

简介: 在我们发表的上一篇关于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

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
JSON Kubernetes Shell
【Azure K8S | AKS】在不丢失文件/不影响POD运行的情况下增加PVC的大小
【Azure K8S | AKS】在不丢失文件/不影响POD运行的情况下增加PVC的大小
295 0
|
Kubernetes 监控 调度
【赵渝强老师】K8s的DaemonSet控制器
DaemonSet控制器确保每个节点上运行一个Pod副本,适用于监控、日志收集等场景。通过示例创建DaemonSet并查看Pod信息,展示了其自动扩展和回收的能力。视频讲解和代码示例详细说明了DaemonSet的使用方法和调度机制。
226 1
|
Kubernetes 容器
K8S的Service的LoadBanlance之Metallb解决方案
本文介绍了如何在Kubernetes中使用MetalLB来实现Service的LoadBalancer功能,包括MetalLB的部署、配置、以及通过创建地址池和部署服务来测试MetalLB的过程。
888 2
K8S的Service的LoadBanlance之Metallb解决方案
|
存储 监控 对象存储
ACK 容器监控存储全面更新:让您的应用运行更稳定、更透明
针对本地存储和 PVC 这两种容器存储使用方式,我们对 ACK 的容器存储监控功能进行了全新升级。此次更新完善了对集群中不同存储类型的监控能力,不仅对之前已有的监控大盘进行了优化,还针对不同的云存储类型,上线了全新的监控大盘,确保用户能够更好地理解和管理容器业务应用的存储资源。
731 269
|
存储 监控 对象存储
ACK 容器监控存储全面更新:让您的应用运行更稳定、更透明
ACK 容器监控存储全面更新:让您的应用运行更稳定、更透明
385 0
ACK 容器监控存储全面更新:让您的应用运行更稳定、更透明
|
存储 监控 对象存储
ACK 容器监控存储全面更新:让您的应用运行更稳定、更透明
ACK 容器监控存储全面更新:让您的应用运行更稳定、更透明
294 1
|
存储 监控 对象存储
ACK容器监控存储全面更新:让您的应用运行更稳定、更透明
介绍升级之后的ACK容器监控体系,包括各大盘界面展示和概要介绍。
|
运维 分布式计算 Kubernetes
ACK One多集群Service帮助大批量应用跨集群无缝迁移
ACK One多集群Service可以帮助您,在无需关注服务间的依赖,和最小化迁移风险的前提下,完成跨集群无缝迁移大批量应用。
|
Kubernetes 监控 Cloud Native
|
Kubernetes 网络安全 容器
在K8S中,有个服务使用service的nodeport进行暴露,发现访问不到如何排查?
在K8S中,有个服务使用service的nodeport进行暴露,发现访问不到如何排查?

推荐镜像

更多