Kubernetes的service mesh – 第二部分:以DaemonSet方式运行linkerd
在我们发表的上一篇关于linkerd的文章中提到过,linkerd是使用DaemonSet而非sidecar来安装的。在本文中,我们将解释我们为什么(怎么样)这么做。
注意:这是关于Linkerd、Kubernetes和service mesh的系列文章其中一篇,其余部分包括:
- Top-line service metrics
- Pods are great, until they’re not(本文)
- Encrypting all the things
- Continuous deployment via traffic shifting
- Dogfood environments, ingress, and edge routing
- Staging microservices without the tears
- Distributed tracing made easy
- Linkerd as an ingress controller
- gRPC for fun and profit
- The Service Mesh API
- Egress
- Retry budgets, deadline propagation, and failing gracefully
- 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
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Kubernetes的service mesh – 第三部分:将一切加密
在本文中,我们将讲述如何使用linkerd作为service mesh在不需要修改任何应用代码的情况下,也能添加TLS至所有的“服务到服务”HTTP请求中。 注意:这是关于Linkerd、Kubernetes和service mesh的系列文章其中一篇,其余部分包括: Top-line service metrics Pods are great, until they’re not Encrypting all the things (本文) Continuous deployment via traffic shifting Dogfood environments, ingress, and edge routing Staging microservices without the tears Distributed tracing made easy Linkerd as an ingress controller gRPC for fun and profit The Service Mesh API Egress Retry budgets, deadline propa...
- 下一篇
Kubernetes1.7新特性:支持绕过Docker,直接通过Containerd管理容器
背景情况 从Docker1.11版本开始,Docker依赖于containerd和runC来管理容器,containerd是控制runC的后台程序,runC是docker公司按照OCI标准规范编写的一个操作容器的命令行工具,containerd这个后台程序还可以操作满足OCI标准规范的其他容器工具,也就意味着以后只要是按照OCI标准规范开发的容器工具,都可以被containerd使用起来。使用containerd好处是,当docker daemon或者containerd两个进程crash后,应用容器不会“死掉”,未来要是实现的功能是,当containerd daemon重新启动后可以同应用容器重新建立连接。 从Docker1.11版本开始,daemon模块调用关系图如下: 美国时间12月14日,Docker公司宣布将containerd从Docker Engine中分离,并捐赠到一个新的开源社区独立发展和运营,阿里云,AWS, Google,IBM和Microsoft作为初始成员,会为项目提供贡献和维护人员。 Kubernetes 1.7新特性-支持绕过Docker,直接通过Cont...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7,CentOS8安装Elasticsearch6.8.6
- 设置Eclipse缩进为4个空格,增强代码规范
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2更换Tomcat为Jetty,小型站点的福音