Telepresence开源工具使用
一、概述
telepresence是一款为kubernetes微服务框架提供快速本地化开发功能的开源软件。
目前国内很少关于该软件的介绍,本文内容全部基于官网文档: https://www.telepresence.io/
kubernetes集群内部的微服务的特点是,各微服务之间在集群内可以互相访问,集群外部没有很好的方法来获取集群内部的功能,比如获取数据库中的数据。(实际上借助于service的nodePort可以实现)
此外,当前的CICD流程步骤为: 提交代码 -> jenkins 拉取源码 -> maven编译 -> docker编译 -> 部署
多个步骤,虽然该过程由jenkins自动完成,但是每次调试均需要经历该步骤,降低效率。
而通过telepresence,则可以实现在本机运行本地代码,本地代码能够获取远端k8s集群的各项资源。
直白一点,telepresence就是给本机提供了k8s集群的代理,使本机直连到远程k8s集群,能够访问集群内部资源。
实际调试中发现,telepresence最新版本(0.92)中存在一些bug与限制,下文中体现
- 本文中涉及k8s与docker中的概念,不再展开
- 本文内容若结合IDEA的Source Synchronizer插件,可以提高效率。
- 该插件可以将代码改动部分或指定文件同步到指定的linux环境
二、安装
telepresence提供对多种操作系统或提供商的支持,本文重点说明centos版本linux的安装与使用
1. OS X
brew cask install osxfuse
brew install socat datawire/blackbird/telepresence
2. Ubuntu 16.04 or later
curl -s https://packagecloud.io/install/repositories/datawireio/telepresence/script.deb.sh | sudo bash
sudo apt install --no-install-recommends telepresence
3. Fedora 26 or later
curl -s https://packagecloud.io/install/repositories/datawireio/telepresence/script.rpm.sh | sudo bash
sudo dnf install telepresence
4. Arch Linux
其它linux版本只能通过源码包的方式来安装,这种方式所依赖的其它软件均需要安装:

4.1 python3.7
$ yum install -y yum-utils
$ yum-builddep python
$ curl -O https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tgz
$ tar xf Python-3.7.0.tgz
$ cd Python-3.7.0
$ ./configure
$ make
$ make install
4.2 其它依赖软件
$ yum install -y sshfs conntrack torsocks socat git docker
$ systemctl start docker
$ systemctl enable docker
4.3 kubectl
从k8s集群的master节点拷贝 /usr/local/bin/kubectl 与 /root/.kube/config 到本机相应目录
4.4 telepresence
$ git clone https://github.com/telepresenceio/telepresence
$ cd telepresence
`修改源码 telepresence/telepresence/outbound/local.py 中第59行'google.com'为'baidu.com'`
$ env PREFIX=/usr/local ./install.sh

修改源码这步至关重要,否则后文使用的inject-tcp方式将不可用
此外,k8s集群中需要运行相应的telepresence服务,客户端不需要如下操作
$ kubectl run -n dev --expose --port 80 nginx --image=nginx
$ kubectl run -n dev --port 8080 telepresence --image=datawire/telepresence-k8s:0.92
$ kubectl expose -n dev deployment telepresence --name=telepresence-svc
5.windows
windows 10 Creators Edition (released April 2017) 支持本地安装 Subsystem for Linux
安装方式及限制,参考https://www.telepresence.io/reference/windows
windows方式的本质是在windows上运行linux子系统,再通过这个linux去完成剩下的工作
三、原理
telepresence的原理,本质上是后台调用kubectl与docker命令,因为kube-config中定义了集群地址及访问方式,因此达到直连k8s集群的目的。
客户端在使用telepresence命令时,它会在远端集群中以特定的镜像(datawire/telepresence-k8s)启动deployment和service资源,
并且监听参数中指定的一个端口。
每个telepresence实例都在集群启动的容器资源被限制在cpu(25m~100m),内存(64M~256M)。
当本地启动一个应用程序,并且暴露的是上述监听的端口号,则telepresence将本地该端口上的流量代理到k8s集群中,
就好像这个应用是运行在集群内部一样,可以直接使用集群中其它service名称来访问。
telepresence提供了三种方式来建立代理通道,各有限制:
- vpn-tcp: 使用叫sshuttle的程序,通过SSH连接来建立一种类VPN通道。
限制: 一台机子只能使用一个telepresence实例;
只能解析诸如 *servicename\servicename.namespace* 这种域名,而无法解析k8s中的完整域名如*servicename.namespace.svc.cluster.local*
单台机子只能单实例运行的限制,官网建议通过 inject-tcp 的方式来运行多实例
- inject-tcp: 使用一种叫 LD_PRELOAD/DYLD_INSERT_LIBRARIES 的机制,通过TCP连接来注入一些共享库。
限制: suid特权的二进制文件无法运行生效;
静态链接二进制文件无法运行生效;
需要解析文件*/etc/resolv.conf*的命令无法生效,如ping,nslookup等;
Golang程序无法运行,以你为Go使用了自带的dns解析器;官网建议Golang通过vpn-tcp方式代理;
- container: 基于vpn-tcp,sshuttle运行于容器内部。
详见:https://www.telepresence.io/discussion/how-it-works
四、使用
客户端通过telepresence命令在本地打开一个代理通道,该命令的参数及使用方法可查询
telepresence --help
官网地址https://www.telepresence.io/tutorials/docker 通过一个简单的例子,描述了在本地通过代理通道启动的程序,能够访问到远端集群中的其它服务。
下文以一个spring-boot的java程序来讲解如何使用telepresence,以及验证集群中其它服务可以访问到本地程序。
现有一个叫 itcast-springboot.jar 的jar包,一个简单的http-server程序

该程序在8088端口提供了"/hello"路径下的http请求,返回简单的字符串。
1. vpn-tcp方式启动代理
本地终端输入如下命令
telepresence -n java --expose 8088

参数含义:
-n java: '-n'是'--new-deployment'的缩写,新建一个实例的意思;'java' 则是新建的实例名称
--expose: telepresence监听该参数暴露的端口号;官方说法支持类似 '--expose 8088:80' 的用法,实测不可用
--method vpn-tcp: 默认代理方式,所以可以省略
此时linux的提示端编程 @kubernetes|bash-4.2#,代表已建立代理连接。
这时切换到k8s集群的终端,则可以查看到名为java的deployment和service

代理启动完毕之后,再在本地另一个终端启动8088端口的java程序
java -jar itcast-springboot.jar


实际上,telepresence也支持一条命令指定启动方式和代理方式
telepresence -n java --expose 8088 --run java -jar itcast-springboot.jar

两种启动方式主要带来以下差异,主要体现在,当修改源码后需要运行新jar包时:
- 第一种方式只需要终止运行java命令的终端,再用 *java -jar * 运行新包即可
- 第二中方式在终止原java命令的同时,也会停止telepresence实例,再次运行将启动一个新的实例
下面验证k8s集群中其它服务能够访问到这个本地运行的程序
切换到k8s集群的终端,进入一个busyboxplus容器,使用curl命令模拟http请求

可以看到,示例在容器中通过 java 这个service名称,
可以成功访问到这个非集群中的本地linux上运行的程序。
缺陷验证
下面为了验证vpn-tcp代理方式的缺陷,即一个机器只能启用一个telepresence实例
修改原java程序,仅改变端口号为8089,再生成一个jar包,叫itcast-springboot-8089.jar
根据上述步骤,再次使用telepresence命令和启动java程序


此时,新建的示例名称为spring,(不能与上个名称相同),端口暴露8089
再到原busybox容器内部验证能否访问到这个8089端口

- 通过nslookup命令,可以看到能够dns解析spring这个域名,说明集群中已经产生新的deployment和service
- 容器内仍能访问到原java:8088的内容
- 通过本地 ip+port 的方式访问到8089端口上的内容
- 但是多次都不能访问这个新实例 spring:8089 上的内容
2. inject-tcp方式启动代理
telepresence --method inject-tcp --namespace dev -n java --expose 8088 --run java -jar itcast-springboot.jar

参数含义:
--method inject-tcp: 以inject-tcp代理方式启动telepresence
--namespace: 选择实例运行的命名空间,不指定默认为default;当前集群dev为开发环境,uat为测试环境
再开一个终端,尝试使用8089端口的jar包建立一个新的实例
telepresence --method inject-tcp --namespace dev -n hello --expose 8089 --run java -jar itcast-springboot-8089.jar

最后,切换到k8s集群的一个终端,尝试访问两个本地程序

大功告成
单个机器上同时允许运行多个telepresence实例
3. container方式启动代理
以容器的方式运行,必然离不开docker镜像,此处简单将上述java程序制作成一个叫java的镜像

此时的 java 为docker镜像名称,8088 为镜像的标签。
再以此镜像来运行一个叫 hello 的实例
telepresence --method container --namespace dev -n hello --expose 8088 --docker-run --rm -it java:8088
参数含义:
--method: 当包含启动参数--docker-run时,以container代理方式
--namespace: 选择实例运行的命名空间,不指定默认为default;当前集群dev为开发环境,uat为测试环境
--docker-run: 实例通过docker容器的方式运行,后续参数为 'docker run' 命令自带参数

程序启动成功,java程序在容器内部运行
以容器方式启动的另一个好处是,docker命令非常灵活,完全可以自定义是否暴露宿主机端口,资源限制,持久卷挂载等
再次回到k8s集群的终端,通过default命名空间下的busybox容器来验证container方式启动的服务是否可以访问

注意图中几个细节
busyboxplus容器位于default命名空间,hello实例位于dev命名空间
不同命名空间不能直接通过service name来访问服务
不通命名空间之间可以通过serviceName.namespace的方式访问到服务内容
若busyboxplus容器位于dev命名空间,则不需要加 .dev 参数
如图所示,container方式可以正常访问到本地以容器方式启动的java程序
因为 container 方式是基于 vpn-tcp 实现,所以同样存在缺陷,一个机子无法启动多个telepresence实例
4. 快速本地开发
本小节内容根据官网描述编写,但是实测不可用。相同的功能根据第1小节的第一种方式即可实现
开发模式下,本地代码快速迭代,很多时候需要不断更新环境中运行的实例进行调试。
telepresence支持在本地进行快速开发
假设集群环境中已经运行了一个java实例
telepresence --method vpn-tcp --namespace dev -n java --expose 8088 --run java -jar itcast-springboot.jar
现更新本地代码,生成新的jar包名为itcast-springboot-new.jar,更改如下:
- 修改地址 /hello 返回内容
- 增加了一条路由地址 /tool
端口号更改为8090,端口号不可更改
则可以通过如下方式更替本地实例
telepresence --method vpn-tcp --namespace dev -s java --expose 8088 --run java -jar itcast-springboot-new.jar
参数含义:
-s java: -s是 --swap-deployment 的缩写,用新的程序替换已存在的实例
5. 其它用法
① 容器内编译并运行代码
可以通过telepresence的'--mount'参数或者docker的'-v'参数,
将maven仓库和源码分别挂载到容器内部,再通过maven命令编译、运行程序
假设本机maven仓库为'$HOME/.m2/repository', 源码为'$HOME/code'
telepresence -n java --docker-run --rm -v $HOME/code:/build -v $HOME/.m2/repository:/m2 -p 8080:8080 harbor.devops.com/devops/maven:3.5.4-jdk-8-alpine mvn -Dmaven.repo.local=/m2 -f /build spring-boot:run
参数含义:
harbor.devops.com/devops/maven:3.5.4-jdk-8-alpine: 包含maven与jdk8的docker镜像
-v $HOME/code:/build: 本地的源码映射到容器内部地址/build
-v $HOME/.m2/repository:/m2: 本堤的maven仓库地址映射到容器内部地址/m2
-p 8080:8080: docker命令参数,容器暴露8080端口,同时映射到宿主机的8080端口
mvn -Dmaven.repo.local=/m2 -f /build spring-boot:run: maven命令,利用spring boot内置的tomcat运行spring boot应用
② 代码热更新
需要持有 JRebel Licence
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)