作者: 哗啦啦 mesh团队,热衷于kubernetes、devops、apollo、istio、linkerd、openstack、calico 等领域技术。
linkerd2介绍
Linkerd由控制平面
和数据平面
组成:
控制平面
是在所属的Kubernetes命名空间
(linkerd默认情况下)中运行的一组服务,这些服务可以完成汇聚遥测数据
,提供面向用户的API,并向数据平面
代理提供控制数据
等,它们共同驱动
数据平面。数据平面
用Rust编写的轻量级代理,该代理安装在服务的每个pod
中,并成为数据平面的一部分,它接收Pod的所有接入
流量,并通过initContainer
配置iptables
正确转发流量的拦截所有传出流量,因为它是附加工具,并且拦截服务的所有传入和传出
流量,所以不需要更改代码,甚至可以将其添加到正在运行
的服务中。
借用官方的图:
proxy由rust开发完成,其内部的异步运行时采用了Tokio框架,服务组件用到了tower。
本文主要关注proxy与destination组件交互相关的整体逻辑,分析proxy内部的运行逻辑。
流程分析
初始化
proxy启动后:
app::init
初始化配置app::Main::new
创建主逻辑main
,main.run_until
内新加一任务ProxyParts::build_proxy_task
。
在ProxyParts::build_proxy_task
中会进行一系列的初始化工作,此处只关注dst_svc
,其创建代码为:
dst_svc = svc::stack(connect::svc(keepalive)).push(tls::client::layer(local_identity.clone())).push_timeout(config.control_connect_timeout).push(control::client::layer()).push(control::resolve::layer(dns_resolver.clone())).push(reconnect::layer({let backoff = config.control_backoff.clone();move |_| Ok(backoff.stream())})).push(http_metrics::layer::<_, classify::Response>(ctl_http_metrics.clone(),)).push(proxy::grpc::req_body_as_payload::layer().per_make()).push(control::add_origin::layer()).push_buffer_pending(config.destination_buffer_capacity,config.control_dispatch_timeout,).into_inner().make(config.destination_addr.clone())
dst_svc
一共有2处引用,一是crate::resolve::Resolver
的创建会涉及;另一个就是ProfilesClient
的创建。
Resolver
api_resolve::Resolve::new(dst_svc.clone())
创建resolver
对象- 调用
outbound::resolve
创建map_endpoint::Resolve
类型对象,并当做参数resolve
传入outbound::spawn
函数开启出口线程
在outbound::spawn
中,resolve
被用于创建负载均衡控制层,并用于后续路由控制:
let balancer_layer = svc::layers().push_spawn_ready().push(discover::Layer::new(DISCOVER_UPDATE_BUFFER_CAPACITY,resolve,)).push(balance::layer(EWMA_DEFAULT_RTT, EWMA_DECAY));
在discover::Layer::layer
中:
let from_resolve = FromResolve::new(self.resolve.clone());
let make_discover = MakeEnd