5

聊聊k8s调试工具kt-connect的实现

 3 years ago
source link: http://vearne.cc/archives/39439
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | http://vearne.cc

1. 引言

kt-connect是阿里开源的k8s的调试工具,它的作用类似于VPN,能够打通k8s集群和本地的网络。

byUbemm.jpg!mobile

传送门: alibaba/kt-connect

它有3种模式

* Connect 本地网络直接访问k8s集群网络

* Exchange 转发集群流量到本地

* Service Mesh 支持

另外它提供了一个Dashboard可以查看k8s集群内的所有可访问的service资源以及正在进行调试的 ConnectExchange 数量, 用处不大。

q6BBzij.jpg!mobile

2. 使用介绍

这里萌叔只简单介绍 ConnectExchange 2种模式,更详细的使用说明见参考资料1

2.1 Connect 模式

sudo ktctl -i ik8share/kt-connect-shadow:stable connect

注意: kt-connect 依赖 sshuttle , 且运行时必须拥有root权限。另外 sshuttle 又依赖了iptables(linux操作系统), ptctl(macOS)

-i 参数指定镜像的地址

这里 ik8share/kt-connect-shadow:stable 是镜像的名字,阿里默认提供的镜像地址 rdc-incubator/kt-connect-shadow 在萌叔的测试k8s集群中无法正常拉取。这里提供了一个docker hub的镜像地址。

2.2 Exchange 模式

sudo ktctl -n test -i ik8share/kt-connect-shadow:stable exchange dm-backend-v0-0-1 --expose 3000

注意: 这里的 dm-backend-v0-0-1 是k8s集群中 Deployment 资源的名称。

该命令会将所有发往 dm-backend-v0-0-1 所属 Pod 的3000端口的请求都转发到本地的3000端口上。

总结: ConnectExchange 模式都是单向的,一个是从集群外部到集群内部,一个是从集群内部到集群外部。

3. 原理和实现

kt-connect 设计巧妙,且最大限度的避免了重复发明轮子,值得称赞。

3.1 Connect 模式

我们先来看看 Connect 模式要达到的目标

假定

Namespace : test

Service : sv-backend-v0-0-1

Pod 的IP: 172.20.1.29

curl http://sv-backend-v0-0-1.test.svc.cluster.local/info
curl 172.20.1.29:3000/info

那么显然,

对于场景1: kt-connect 需要知道sv-backend-v0-0-1.test.svc.cluster.local是k8s集群内的域名,针对此类域名的请求,需要转发到k8s内网

对于场景1: kt-connect 需要知道 172.20.1.29,是k8s集群的内网IP,请求需要转发到k8s内网

kt-connect 需要能够自动捕获这两类流量,然后转发到k8s内网。

nARNBnB.jpg!mobile

3.1.1 ① 创建Pod

此Pod镜像为 rdc-incubator/kt-connect-shadow ,并且暴露SSH端口

3.1.2 ② 在Local和K8s之间建立通道

kubectl -n default port-forward kt-connect-daemon-dnwvy-5dbf9cb9c6-l96g6 2222:22

3.1.3 ③ 捕获请求,并重新路由

sshuttle --dns --to-ns 172.20.3.25 -v -e ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -r [email protected]:2222 -x 127.0.0.1 172.20.0.0/24 172.20.2.0/24 172.20.1.0/24 172.20.3.0/24 10.68.0.0/16

sshuttle 内部会调用 iptablespfctl 修改NAT规则

–dns –to-ns 172.20.3.25表示DNS解析使用172.20.3.25,实时上这个IP就是 Pod kt-connect-daemon-dnwvy-5dbf9cb9c6-l96g6的IP

规则形如

iptables -t nat -A sshuttle-12300 -j REDIRECT --dest 10.68.0.0/16  -p tcp --to-ports 2222

3.1.4 ④ sshuttle重建对目标的连接

我们再来梳理一遍流程。当使用curl请求接口时,域名解析会使用自定义的DNS服务器172.20.3.25,因此能够成功解析 sv-backend-v0-0-1.test.svc.cluster.local ,解析得到的A记录是10.68.54.179, 显然命中了 shuttle 创建的NAT规则(10.68.0.0/16),于是请求被转发到127.0.0.1:2222端口, 请求又经过 port-forward 转发到 kt-connect-daemon-dnwvy-5dbf9cb9c6-l96g6 的22端口。在这个Pod中, sshuttle 重建对目标的连接,请求会被转发。

3.2 Exchange 模式

Jn2UBnA.jpg!mobile

3.2.1 ① 创建Pod & ② 删除原有Pod

AJrMRvY.jpg!mobile 实际上, kt-connect 将原来的 Deployment dm-backend-v0-0-1的 replicas 置为0,变相删除了 Pod
创建了一个新的 Deployment dm-backend-v0-0-1-kt-dfoje, 注意看它使用的镜像是 kt-connect-shadow 。由它创建的 Pod ,使用的 Label 和原先的一模一样,这样它就能欺骗k8s,使得对 Service backend的请求都转发到它这里来。

3.2.2 ③在Local和K8s之间建立通道

kubectl -n test port-forward dm-backend-v0-0-1-kt-dfoje-7ff5d9564-kmklv 2226:22

访问本地的2226端口,相当于访问了dm-backend-v0-0-1-kt-dfoje-7ff5d9564-kmklv的22端口

3.2.3 ④ssh 远程转发

ssh -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -R 3000:127.0.0.1:3000 [email protected] -p2226 sh loop.sh

ssh自带远程转发功能,它会在dm-backend-v0-0-1-kt-dfoje-7ff5d9564-kmklv中监听3000端口,然后把所有发到3000端口的请求转发到127.0.0.1:3000(见参考资料2)

我们再来梳理一遍流程。当其他服务访问 Service backend时,由于

labels:
    app: backend

只剩由 kt-connect 伪造的1个 Pod dm-backend-v0-0-1-kt-dfoje-7ff5d9564-kmklv了,所以流量会被转发到这个 Pod 中。请求的3000端口的流量会被SSH的远程转发功能转发给本地的3000端口。

参考资料

1. Kt Connect Docs

2. SSH的三种端口转发

打赏我

ZzaQjmz.jpg!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK