聊聊k8s调试工具kt-connect的实现
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集群和本地的网络。
传送门: alibaba/kt-connect
它有3种模式
* Connect 本地网络直接访问k8s集群网络
* Exchange 转发集群流量到本地
* Service Mesh 支持
另外它提供了一个Dashboard可以查看k8s集群内的所有可访问的service资源以及正在进行调试的 Connect
和 Exchange
数量, 用处不大。
2. 使用介绍
这里萌叔只简单介绍 Connect
和 Exchange
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端口上。
总结: Connect
和 Exchange
模式都是单向的,一个是从集群外部到集群内部,一个是从集群内部到集群外部。
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内网。
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
内部会调用 iptables
或 pfctl
修改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
模式
3.2.1 ① 创建Pod & ② 删除原有Pod
实际上, 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端口。
参考资料
2. SSH的三种端口转发
打赏我
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK