Telepresence

介绍

Telepresence是Apache 2.0 下的一个开源工具,它允许开发者在本地运行单个服务,并将这个服务连接到远端的k8s集群中。这使得那些致力于多个服务应用程序开发的团队,通过使用双向网络代理的方式,在本地运行调试程序来取代在K8S集群中运行的pod,从而实现Kubernetes微服务的快速本地开发。

Telepresence

实践

K8S中访问本地服务(替换deployment)

该实践的场景是我们已经在k8s环境上运行了某个服务,比如以下是一个名叫hello-world的deployment。为了对这个服务做一些debug或者功能的更新,我们在本地已经修改好了代码,并编译成了可执行文件。

  • 按照原来的开发流程,我们需要借助CI流水线打包镜像,然后部署到K8S环境,滚动升级之前的deployment;而该流程较繁琐、耗时(哪怕使用了流水线,由于网络的一些原因,镜像上传下载是一个耗时的操作)。
  • 而通过Telepresence,我们只需要在本地执行几条命令,就可以让K8S段的其他服务正常访问本地运行的测试程序。对于其他服务来,目标服务运行在本地这个行为是无感知的。这就相当于使用本地运行的服务,替换掉了K8S中运行的deployment。

先在k8s上部署一个名叫hello-world的deployment:

1
2
$ kubectl run hello-world --image=datawire/hello-world --port=8000
$ kubectl expose deployment hello-world --type=LoadBalancer --name=hello-world

然后在本地电脑上执行:

1
2
3
4
mkdir /tmp/telepresence-test
cd /tmp/telepresence-test
echo "hello from your laptop" > file.txt
telepresence --swap-deployment hello-world --expose 8000 --run python3 -m http.server 8000 &

该操作后,telepresence内部的过程包括:

  • 启动一个类似VPN的进程,将查询发送到适当的DNS和IP范围到群集。
  • --swap-deployment 告知Telepresence将现有的hello-world pod替换为一个Telepresence代理pod。当本地的Telepresence退出时,之前的pod将恢复运行。
  • --run 告知Telepresence运行本地Web服务,并将其连接到网络代理(Telepresence代理pod)。

执行之后,系统会将k8s中旧的hello-world停掉,同时启动了新的pod(其实运行的应该是telepresence proxy镜像)

1
2
3
$ kubectl get pod | grep hello-world
hello-world-2169952455-874dd 1/1 Running 0 1m
hello-world-3842688117-0bzzv 1/1 Terminating 0 4m

当结束调试的时候,只需要从本地的后台唤醒进程

1
fg

然后执行ctrl+C来退出。可以看到,k8s之前的pod又恢复了运行。所有流程可以通过执行访问服务的URL来验证。

K8S中访问本地服务(新建deployment)

我们将如下python程序保存到本地helloworld.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env python3

from http.server import BaseHTTPRequestHandler, HTTPServer

class RequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.end_headers()
self.wfile.write(b"Hello, world!\n")
return

httpd = HTTPServer(('', 8080), RequestHandler)
httpd.serve_forever()

在本地执行telepresence,这次使用的是--new-deployment 并在本地运行程序来通过8080端口,对外提供服务:

1
2
$ telepresence --new-deployment hello-world --expose 8080
$ python3 helloworld.py

该命令对应在K8S上创建deployment和service hello-world;接下来我们可以在K8S上可以直接访问该服务的 cluster-ip:8080 来验证。

如果要在本地debug程序,只需要修改代码并重新执行:

1
2
3
4
5
6
python3 helloworld.py
^C
localhost$ sed s/Hello/Goodbye/g -i helloworld.py
localhost$ grep Goodbye helloworld.py
self.wfile.write(b"Goodbye, world!\n")
localhost$ python3 helloworld.py

k8s上的服务对外提供的API的返回内容立刻生效。

本地访问K8S服务

先在K8s上创建deployment并暴露service端口,如下:

1
2
3
4
$ kubectl run myservice --image=datawire/hello-world --port=8000 --expose
$ kubectl get service myservice
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
myservice 10.0.0.12 <none> 8000/TCP 1m

在本地执行telepresence命令:

1
2
$ telepresence --run curl http://myservice:8000/
Hello, world!

该流程中,telepresence在k8s中启动了一个 proxy pod,用于代理到k8s pod网络内部,然后访问dns并请求目标服务。当curl结束的时候,该pod会自动退出。

1
2
3
4
root@ubuntu:~# kubectl get pod
NAME READY STATUS RESTARTS AGE
hello-world-74556688f-gd78c 1/1 Running 0 46m
telepresence-1527136988-31514-26798-7489f99c9d-pvvj5 1/1 Terminating 0 24s
0%