Kubernetes环境下基于Telepresence开发调试实践
以Kubernetes为基础的微服务下开发本地调试面临的问题
微服务是随着领域驱动设计,持续交付,容器化技术,基础设施自动化,小型自治团队,大型集群系统的实践与流行,而总结出来的一种逐渐流行的模式;基于Kubernetes作为微服务应用载体的架构,Kubernetes提供了服务注册、配置管理、负载均衡、故障隔离、业务恢复、自动扩容等能力。相比于传统的Spring Cloud微服务体系,将更多的基础服务下层到基础设施上,让应用层更关注业务开发,同时对多平台语言有了更好的支持。
但是在以Kubernetes为基础的微服务下进行开发、调试;就会面临下面几个问题:
- 由于服务依赖关系复杂,服务众多,本地进行调试的话需要把关联的服务都搭建-启动起来
- 微服务依赖的基础设施也需要在本地环境进行搭建-启动,如消息队列、数据库、配置中心、调度中心…
一些解决方案
- 通过Docker Compose在本地运行整个多服务应用程序;这种方式并未在Kubernetes内部运行服务,一些基础设施也不容易在本地使用。
- 通过类似Telepresence的工具,通过将Kubernetes环境中的数据(连接、环境变量、volumes)代理到本地进程以方便本地进行调试。
Telepresence简介
Telepresence是CNCF 基金会下的一个项目,使用Telepresence可让您在本地运行单个服务,同时将该服务连接到远程Kubernetes群集。 这使在微服务下开发人员可以:
- 本地单个服务依赖于群集中的其他服务,也可以进行本地开发与调试
- 可以在本地使用IDE调试服务
- 使本地开发机器像Kubernetes集群一样运行
实现原理
Telepresence在Kubernetes集群中运行的Pod中部署了双向网络代理,将Kubernetes环境中的数据(连接、环境变量、volumes)代理到本地进程。本地进程的网络透明覆盖,因此DNS调用和TCP连接通过代理路由到远程Kubernetes集群。实现了:
- 本地服务具有对远程群集中其他服务的完全访问权限
- 本地服务可以访问Kubernetes的环境变量,secrets,ConfigMap
- 远程服务可以访问到本地服务
实现方式如下:
- 默认使用
--method vpn-tcp
,默认情况下,使用程序创建类似VPN的隧道程序sshuttle,sshuttle通过SSH连接建立数据包的隧道,并将DNS查询转发到群集中的DNS代理。 - 使用
--method inject-tcp
,使用在Linux / OSX上 机制来实现LD_PRELOAD
/DYLD_INSERT_LIBRARIES
,其中可以将共享库注入到进程中并覆盖库调用;会覆盖DNS解析和TCP连接,并通过SOCKS代理将它们路由到群集。
安装
- mac上安装Telepresence
brew install kubectl
# 配置相关的kube config...
brew cask install osxfuse
brew install datawire/blackbird/telepresence
Telepresence使用
连接到远程Kubernetes集群
场景
在context为dev的kubernetes集群内,服务A依赖于服务B,需要在本地对服务A进行调试。
操作
启动Telepresence,连接对应集群
telepresence --context dev
对应启动日志
T: Starting proxy with method 'vpn-tcp', which has the following limitations: All processes are affected, only one telepresence can run per machine, and you can't use other VPNs. You may need to add cloud hosts and headless services with --also-proxy. For a full list of
T: method limitations see https://telepresence.io/reference/methods.html
T: Volumes are rooted at $TELEPRESENCE_ROOT. See https://telepresence.io/howto/volumes.html for details.
T: Starting network proxy to cluster using new Pod telepresence-1611716361-290886-47290
T: No traffic is being forwarded from the remote Deployment to your local machine. You can use the --expose option to specify which ports you want to forward.
T: Connected. Flushing DNS cache.
T: Setup complete. Launching your command.
当运行 Telepresence 命令的时候,默认使用vpn-tcp模式;它创建了一个Deployment
,对应的 Spec 是负责转发流量的代理容器;对应的pod为上面启动日志的telepresence-1611716361-290886-47290
;同时Telepresence在本地创建了一个全局VPN;使得本地的所有程序都可以访问到集群中的服务。
这时候就可以把本地环境的Service A启动起来进行调试,所有的环境变量可以基于上文的dev环境配置。
远程Kubernetes集群内部服务与本地服务联调
场景
在context为dev的kubernetes集群内,服务A依赖于服务B,需要在本地对服务B进行调试;这里调试的前提是我们要有真实的来自服务A的调用流量。
操作
使用Telepresence提供的参数--swap-deployment DEPLOYMENT_NAME[:CONTAINER], -s DEPLOYMENT_NAME[:CONTAINER]
将集群中的一个 Deployment 替换为本地的服务;使用 --expose PORT[:REMOTE_PORT]
进行本地-集群Deployment绑定的端口转发。启动本地进程板顶对应expose的PORT进行调试。
# 这里替换了 context为dev、namespace为test的 service-a 到本地服务;并对集群内service-b:8080的流量转发到本地10080端口
telepresence --context dev --namespace test --swap-deployment service-b --expose 10080:8088
这里Telepresence操作的过程如下:
- 在集群中创建一个代理Deployment复制service-b的所有Label
- 建立一个路由通道,将代理容器的所有流量转发到本地 10080 端口
- 将service-b的 replicas 设置为0,kubernetes Service 的 selector 就只能匹配到刚刚创建的代理容器上
一些参数
- 帮助文档
telepresence --help
- 新建一个deployment用于测试本地服务访问远程服务
# --new-deployment:创建一个名为 server-c 的 deployment
telepresence --new-deployment server-c --run-shell --also-proxy