2

【原创】K8S环境下研发如何本地调试?kt-connect使用详解 - yeyu456

 2 years ago
source link: https://www.cnblogs.com/yeyu456/p/16600498.html
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.
neoserver,ios ssh client

K8S环境下研发如何本地调试?kt-connect使用详解

注:背景有点啰嗦,讲讲一路走来研发本地调试的变化,嫌烦的可以直接跳过,不影响阅读。

2019年

我在的公司当时是个什么情况,只有两个Java应用,还都跑在一个Tomcat Servlet容器。

image

当时是如何本地调试?都是研发自己电脑装个Mysql,装个Tomcat,自己电脑运行调试,好处嘛就是后端研发互不干扰,想怎么改就怎么改,APP端研发就直连后端的笔记本调试。上线部署嘛就是一个研发手动编译个Jar包丢到云服务器上面,大体就是个草台班子,能干活,但是也就那样。

2020年

到了2020年,公司买了一台服务器,Centos的系统,给装上了Mysql、Tomcat,用上了Redis缓存,RabbitMQ消息队列,有了独立的测试环境,用上了Jenkins自动打包并部署应用,也算鸟枪换炮,起码不用自己打包了。

image

这个时候是如何本地调试呢?起码不用自己电脑装Mysql了,后面框架由SpringMVC和Struts2都改成Spring Boot,外置的Tomcat也可以去掉了。后端研发本地运行Spring Boot时直连服务器的Mysql进行调试,APP端再也不用连后端研发的笔记本了,有了相对稳定的调试环境。代价就是各个后端的数据库更新结构要保持兼容性,避免影响他人。

2021年

随着业务增长,后端框架由Spring Boot进化为Spring Cloud全家桶,应用运行环境由Linux直接运行改为了Docker镜像部署,各类中间件同样也使用了Docker镜像。产品线增加,单一的开发分支已经不能满足需求,为此又开辟了另外一条后端代码分支,同样的开发测试环境也多了一份。

image

这个时候的本地调试,对于APP端来说变化不大,区别连接后端不同环境使用不同域名而已。对于后端的研发同学就不一样了,每次本地调试自己电脑要常驻一个Eureka和一个Config Server,如果本地调试的微服务依赖比较多,没个大内存真是顶不住。

2022年

业务量继续增加,产品同事数量增加了,那个需求量真是堆积如山,两个分支已经不能满足要求了,又开了第三个分支,还是不够。每次增加新的分支运行环境,后端研发同学也很痛苦,一堆环境和第三方平台回调需要配置。为了能动态扩容缩容,Spring Cloud全家桶继续演进,抛弃了Zuul网关和Eureka,改为使用Spring Cloud Kubernetes,运行环境全面向K8S靠拢。在此期间公司又采购了一台服务器用于开发测试,内存CPU磁盘满上!

image

进入K8S时代,后端研发本地的电脑没办法随意连接Linux服务器上面的各种中间件,每个新分支环境里面的每个POD都是一个新的ip,也不可能像之前那样开放指定几个中间件的端口给后端连接,那么多环境每个都做设置的话,运维同学整天不用干别的事了。也由此引出了今天要说的kt-connect工具,通过这个工具,后端研发本地的电脑可以代理访问到各个分支环境,也就是K8S里面的命名空间的所有服务,并且只需要启动需要调试的服务,大大节省了电脑CPU内存占用。

在选择代理访问K8S环境以便于本地调试的工具中,网上有几种。

1. 端口转发

使用Ingress、NodePort、LoadBalancer之类的将流量转发到指定端口,如上文所说,会让运维同学工作量比较大,也不便于分支环境的自动创建和回收,只适合需要暴露端口数量不多的场景。

2. VPN

通过在K8S每个命名空间里面设置一个运行有VPN服务的POD,后端研发笔记本通过VPN客户端连接代理进入到指定命名空间,可以正常访问和解析集群内各类服务,基本能满足日常的要求,缺点是每个命名空间都常驻了一个VPN服务的运行资源。

3. Telepresence

在搜索的过程中发现了这个代理工具,几乎可以说9成的中英文技术文章都推荐使用这个工具,功能非常强大,不但提供了VPN所具有的代理功能,可以访问到命名空间内所有服务,还能指定各种规则拦截指定服务的流量到本地机器,相当于本地机器也能作为一个普通的POD提供对外服务。大体设计原理如下:

image

在研发本地电脑执行如下命令

telepresence helm install --kubeconfig .\kubeconfig
telepresence connect ---kubeconfig .\kubeconfig

就会自动在K8S集群创建一个命名空间ambassador,并且部署一个traffic-manager的pod,用于流量管理,而在研发笔记本本地则会启动2个daemon服务,其中一个叫Root Daemon,用于建立一条双向代理通道,并管理本地电脑与K8S集群之间的流量,另外一个User Daemon则是负责与Traffic Manager通信,设置拦截规则,如果登录后还负责与Ambassador Cloud进行通信。
通过配置拦截规则,拦截的POD里面会安装一个traffic-agent,官方文档说明是类似K8S集群的sidecar模式,对注入POD进行流量劫持,所有流量出入通过traffic-manager进行重新路由。

The Traffic Agent is a sidecar container that facilitates intercepts. When an intercept is first started, the Traffic Agent container is injected into the workload's pod(s).

虽然他的功能很强大,但是在目前2.5版本的使用过程中,为了使用他的拦截和Preview Url功能必须在他家的商业云平台Ambassador Cloud进行注册登陆(注:不知道为什么网上技术文章都没提到这点,测试的时候非得要登录他家云平台),并且拦截规则的配置是通过云平台的网页进行操作的,联网的要求,包括可能存在的安全,泄露之类的隐患,我觉得是不可接受,也因此不得不放弃使用这个工具。
还有一个不得不说的缺点就是,老版本使用后可以清理掉自动创建的命名空间(namespace)和pod、拦截agent的功能(telepresence uninstall)也没了,在2.5版本的命令参数里面完全消失了,这就导致每次使用后,如果想保持环境干净,还得麻烦运维同学去清理掉,非常麻烦,简直逼死洁癖患者。

4. kt-connect

所幸开源社区又找到了另外一款类似Telepresence的工具,名为kt-connect,使用版本为v0.3.6(顺便说下我们使用的K8S版本是1.24),并且它无需联网登陆什么账号,结束命令执行默认还会自动清理。阿里出品,不确定是不是又一个KPI开源项目,但是至少这一刻我对这个工具是非常满意的。

同Telepresence类似,但不同的是,kt-connect只会在指定连接的命名空间(namespace)里面新建一个自用的pod,然后部署一个kt-connect-shadow的镜像。相比Telepresence,它在模式进行了细分扩展,分为四大模式:

1. Connect模式

ktctl.exe connect --kubeconfig .\kubeconfig --namespace feature-N --debug

这个模式下,kt-connect起到的是一个类似于VPN的作用,研发本地电脑可以访问到连接的命名空间(namespace)内的所有服务,但是并没有加到集群里面其他服务里面,其他服务的流量并不会转发到本地电脑。

注1:与telepresence类似,kt-connect所有命令都要带上--kubeconfig,确保有足够权限和能正确连接K8S集群的API Server,很多文章都很少提到这点,假如K8S集群限制权限,或者与研发不在同一个网络,必须确保使用运维同学提供的有足够权限的授权文件kubeconfig来进行连接。
注2:

Failed to setup port forward local:28344 -> pod kt-connect-shadow-gseak:53 error="error upgrading connection: error sending request: Post "https://10.0.8.101:8443/api/v1/namespaces/feature-N/pods/kt-connect-shadow-gseak/portforward": dial tcp 10.0.8.101:8443: connectex: A socket operation was attempted to an unreachable host.",

如果出现以上报错的话,有可能是kt-connect路由BUG,可能本地电脑的路由与新加的通往API Server的路由有冲突,增加参数--excludeIps 10.0.8.101/32即可,如果网段冲突比较多,可以扩大网段范围,例如--excludeIps 10.0.8.0/24 参考issue-302

ktctl.exe connect --kubeconfig .\kubeconfig --namespace feature-N --excludeIps 10.0.8.101/32 --debug

2. Exchange模式

ktctl.exe exchange serviceA --kubeconfig .\kubeconfig --namespace feature-N --expose 12001 --debug

这个模式类似于Telepresence拦截模式,将指定服务的所有流量拦截下来转发到研发本地电脑的端口,使用这个模式能对环境里的访问请求直接进行调试。
具体原理就是将service里面的pod替换成一个serviceA-kt-exchange的pod。

注1:Exchange模式的流量方向是单向的,并不会将本地电脑主动发起的请求代理过去,如果K8S集群跟研发本地电脑不在一个网段内,需要另外开一个命令行运行Connect模式,确保本地服务可以正常连接K8S集群的其他服务,参考issue-216
注2:Exchange模式是通过拦截service进行流量转发,假如集群的请求没有经过service,例如直接解析到pod之类,可能就会出现拦截失败的情况(同理Mesh模式也是如此),所以出现问题记得跟运维同学确认K8S集群内的路由情况。

3. Mesh模式

kctl.exe mesh serviceA --kubeconfig .\kubeconfig --namespace feature-N --expose 12001 --debug

执行命令后可以看到输出日志里面包含类似文字:

2:30PM INF Now you can access your service by header 'VERSION: xxxxx'

这个模式本地电脑的服务和K8S集群里面相同的服务同时对外响应请求,但是只有通过指定的http请求头VERSION: xxxx的请求才会转发到本地电脑,相比Exchange模式,保证了其他人服务正常使用,同时研发又能进行本地调试。每次生成的请求头VERSION的值都是动态生成的,如果要固定这个值,可以通过参数--versionMark写死,例如固定值为test-version,命令如下:

kctl.exe mesh serviceA --kubeconfig .\kubeconfig --namespace feature-N --expose 12001 --debug --versionMark test-version

具体原理就是将serviceA里面的Pod替换成一个serviceA-kt-router的路由镜像,负责根据请求头进行流量代理转发,另外生成一个serviceA-kt-stuntman服务,这个就是线上正常运行的serviceA,还有一个serviceA-kt-mesh-xxxxx服务,这个就负责将代理流量到本地电脑。

4. Preview模式

kctl.exe preview serviceB --kubeconfig .\kubeconfig --namespace feature-N --expose 12001

不同于Exchange和Mesh模式要求K8S集群有一个在运行的服务,Preview模式可以将本地电脑运行的程序部署到K8S集群中作为一个全新的Service对外提供服务,非常便于新建服务的开发调试、预览等作用。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK