一、前言

文章《二十二:Service Mesh之在Kubernetes部署Linkerd2进行service mesh》介绍了Linkerd的部署和应用的部署以及mesh,本文对Linkerd2 v2.7.1的Linkerd proxy的工作原理进行分析,包括:

  • sidecar注入方法
  • 流量劫持方法
  • 数据流转方法

二、sidecar注入方法

2.1 注入方式

Linkerd sidecar的配置在名为linkerd-config的configmap中:

 

可以通过编辑deployment的annonation来修改这些默认的配置,具体可以参看:https://linkerd.io/2/reference/proxy-configuration/

 

a) 使用linkerd inject进行手动注入

cat deployment.yml | linkerd inject - | kubectl apply -f -

b) 使用webhook admission controller进行自动注入

需要先将一个namespace标记成可以注入的:

kubectl label namespace linkerd-test linkerd.io/inject=enabled

之后在这个namespace部署的POD会由Kubernetes自动按照注入的配置文件进行sidecar注入

2.2 注入效果

在执行sidecar注入之后,新启动的POD会启动sidecar,包含两个container,一个是初始化init容器,一个是proxy容器。最新的如果使用Linkerd CNI Plugin的话,就不会有init容器了。

a)初始化容器linkerd-init

 

该容器主要是进行POD network namespace sidecar iptables的写入,这些iptables规则主要是进行出站和入站数据的劫持转发。

b)数据流代理容器linkerd-proxy

该容器进行数据面数据流的转发和控制,实现servicemesh的所有数据流管控工作,包括目的地查找、负载均衡、熔断、服务发现、服务健康管理、metrics和trace等工作。该数据proxy Rust进行编码。

 

三、数据流量劫持方法

3.1 iptables规则插入

init容器通过proxy-init命令和指定的参数来插入iptables:

/usr/local/bin/proxy-init --incoming-proxy-port 4143 --outgoing-proxy-port 4140 --proxy-uid 2102 --inbound-ports-to-ignore 4190,4191

通过命令:

docker top docker ps|grep "k8s_linkerd-proxy_web"|cut -d " " -f1
nsenter -n --target 1429784

可以查看插入的iptables规则如下:

01: *nat
02: -A PREROUTING -m comment --comment "proxy-init/install-proxy-init-prerouting/1590476641" -j PROXY_INIT_REDIRECT
03: -A OUTPUT -m comment --comment "proxy-init/install-proxy-init-output/1590476641" -j PROXY_INIT_OUTPUT
04: -A PROXY_INIT_OUTPUT ! -d 127.0.0.1/32 -o lo -m owner --uid-owner 2102 -m comment --comment "proxy-init/redirect-non-loopback-local-traffic/1590476641" -j PROXY_INIT_REDIRECT
05: -A PROXY_INIT_OUTPUT -m owner --uid-owner 2102 -m comment --comment "proxy-init/ignore-proxy-user-id/1590476641" -j RETURN
06: -A PROXY_INIT_OUTPUT -o lo -m comment --comment "proxy-init/ignore-loopback/1590476641" -j RETURN
07: -A PROXY_INIT_OUTPUT -p tcp -m comment --comment "proxy-init/redirect-all-outgoing-to-proxy-port/1590476641" -j REDIRECT --to-ports 4140
08: -A PROXY_INIT_REDIRECT -p tcp -m multiport --dports 4190,4191 -m comment --comment "proxy-init/ignore-port-4190,4191/1590476641" -j RETURN
09: -A PROXY_INIT_REDIRECT -p tcp -m comment --comment "proxy-init/redirect-all-incoming-to-proxy-port/1590476641" -j REDIRECT --to-ports 4143
10: COMMIT

3.2 iptables规则解读

相比Istio proxy,linkerd proxy的iptables规则的comment里面描述还是比较清楚的:

  • 2,所有进展数据包在进行路由选择之前会被引导到PROXY_INIT_REDIRECT链表
  • 3,所有输出数据包会被引导到PROXY_INIT_OUTPUT链表
  • 4,POD1向POD所在的服务svc1发送请求,并且被Linkerd mesh到自己(POD1)的情况下,走正常的入站处理流程PROXY_INIT_REDIRECT,由proxy进行mesh处理
  • 5,linkerd proxy发出的包括控制面数据包和mesh/proxy之后的数据包,proxy不做处理
  • 6,通过localhost自己访问自己的数据包,proxy不做处理
  • 7,其余出站数据包进入proxy监听的出站端口4140,进行mesh/proxy
  • 8,入站数据包如果是控制面发给linkerd proxy 4190/4191端口的,不做处理
  • 9,其余入站数据进入proxy监听的入站端口4143,进行mesh/proxy

具体可以参看代码:

https://github.com/linkerd/linkerd2-proxy-init/blob/master/iptables/iptables.go

四、数据流转方法

可以看到Linkerd proxy的数据流量劫持规则基本和文章《二十四:Service Mesh之Istio proxy的流量劫持详细分析》里面分析的类似,在此不进行