1. 程式人生 > 程式設計 >使用 Telepresence 在本地除錯 Kubernetes 微服務

使用 Telepresence 在本地除錯 Kubernetes 微服務

作者:喵叔
原文:blog.betacat.io/post/develo…

微服務作為一種全新的軟體架構現在正變得越來越火。基本原因我覺得有兩點:一方面軟體系統越做越複雜,通過拆分將一個大系統解耦成一個個獨立的子系統,我們就降低了整個系統的複雜性。另一方面,Kubernetes 的出現使得編排這麼多子系統變得簡單,可以說 Kubernetes 是目前為止微服務最好的載體。

Kubernetes 解決了微服務執行時的環境問題,但對開發環境就不那麼友好了。比方說如果我們要在本地開發除錯一個服務A,但服務A可能依賴服務B、C,而服務B又有一層依賴D,我們就需要在本地把服務B、C、D都搭建起來才能除錯服務A。這顯然是一個很痛苦的過程。

Microservices Dependency Hell

業界有朋友用 docker-compose 來模擬叢集中的場景。這個方案的不足之處在於它需要把 Kubernetes 的那一套邏輯用 docker-compose.yml 檔案重寫一遍,這給我們帶來了維護成本。另一方面,有的時候依賴樹太大,本地機器完全無法同時執行這麼多服務。

ratesvc:
  image: kubeapps/ratesvc:latest
  environment:
    - JWT_KEY=secret  # <------------------------ 手工維護
  command:
    - /ratesvc
    - --mongo-url=mongodb://root@mongodb
# <---- 手工維護 - --mongo-database=ratesvc mongodb: image: bitnami/mongodb:3 environment: - MONGODB_ROOT_PASSWORD=password123 auth: image: kubeapps/oauth2-bitnami:latest volumes: - ./config.yaml:/config/monocular.yaml # <-- 手工維護 ... volumnes: # <----------------------------------- 手工維護
monocular-data: 複製程式碼

另一種解決方案就是我這裡要介紹的 Telepresence 了,它能夠在不修改程式程式碼的情況下,讓本地應用程式無感的接入到 Kubernetes 叢集中,這樣你就可以直接在本地開發除錯微服務了。

簡介

Telepresence 是一個 CNCF [1] 基金會下的專案。它的工作原理是在本地和 Kubernetes 叢集中搭建一個透明的雙向代理,這使得我們可以在本地用熟悉的 IDE 和除錯工具來執行一個微服務,同時該服務還可以無縫的與 Kubernetes 叢集中的其他服務進行互動,好像它就執行在這個叢集中一樣。

這是一個 Telepresence 工作原理圖,它將叢集中的資料卷、環境變數、網路都代理到了本地(除了資料卷外,其他兩個對應用程式來說都是透明的):

Telepresence Proxies

有了這些代理之後:

  1. 本地的服務就可以完整的訪問到遠端叢集中的其他服務
  2. 本地的服務直接訪問到 Kubernetes 裡的各種資源,包括環境變數、secrets、config map等
  3. 甚至叢集中的服務還能直接訪問到本地暴露出來的介面

安裝

macOS:

brew cask install osxfuse  # required by sshfs to mount the pod's filesystem
brew install datawire/blackbird/telepresence
複製程式碼

其他平臺請參考:www.telepresence.io/reference/i…

如果官方的安裝包沒有覆蓋到你的平臺,其實也可以從原始碼安裝,因為它本身就是用 Python3 寫的,熟悉 Python 的朋友安裝這個程式應該不難,我自己就在 CentOS 7 上安裝成功了。

使用場景

假設我們有兩個服務 A 和 B,服務 A 是依賴於服務 B 的。下面分兩個場景來看看如何用 Telepresence 來除錯 A 和 B。

Service A&B

除錯服務 A

服務 A 在本地執行,服務 B 執行在遠端叢集中。藉助 Telepresence 搭建的代理,A 就能直接訪問到 B。比方說我們的服務 B 是這樣一個程式,它監聽在8000埠上。每當有人訪問時它就返回Hello,world!

$ kubectl run service-b --image=datawire/hello-world --port=8000 --expose
$ kubectl get service service-b
NAME        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
service-b   10.0.0.12    <none>        8000/TCP   1m
複製程式碼

現在在本地用預設引數啟動 Telepresence ,等它連線好叢集:

$ telepresence
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
T: can't use other VPNs. You may need to add cloud hosts and headless services with --also-proxy. For a full list of method limitations see
T: 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 Deployment telepresence-1566230249-7112632-14485

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
T: forward.

T: Setup complete. Launching your command.
@test_cluster|bash-4.2#
複製程式碼

這時候就可以開始除錯服務 A 了,因為服務 B 暴露出來的介面本地已經可以直接訪問到:

$ curl http://service-b:8000/
Hello,world!
複製程式碼

這裡要說明一下這背後發生的事情:

  1. 當執行 Telepresence 命令的時候,它建立了一個Deployment,這個Deployment又建立了一個用來做代理的 Pod ,我們可以這樣檢視到它 kubectl get pod -l telepresence
  2. 同時它還在本地建立了一個全域性的 VPN,使得本地的所有程式都可以訪問到叢集中的服務。 Telepresence 其實還支援其他的網路代理模式(使用--method切換),vpn-tcp是預設的方式,其他的好像用處不大,inject-tcp甚至要在後續的版本中取消掉
  3. 當本地的curl訪問http://service-b:8000/時,對應的 DNS 查詢和 HTTP 請求都被 VPN 路由到叢集中剛剛建立的 Pod 去處理。

除此之外 Telepresence 還將遠端的檔案系統通過sshfs掛載到本地$TELEPRESENCE_ROOT下面(你也可以用引數--mount <MOUNT_PATH>指定掛載的路徑)。這樣,我們的應用程式就可以在本地訪問到遠端的檔案系統:

$ ls $TELEPRESENCE_ROOT/var/run/secrets/kubernetes.io/serviceaccount
ca.crt  namespace  token
複製程式碼

如果我們退出 Telepresence 對應的 Shell,它也會做一些清理工作,比如取消本地 VPN、刪除剛剛建立的Deployment等。

除錯服務 B

服務 B 與剛才的不同之處在於,它是被別人訪問的,要除錯它,首先得要有真實的訪問流量。我們如何才能做到將別人對它的訪問路由到本地來,從而實現在本地捕捉到叢集中的流量呢?

Telepresence 提供這樣一個引數,--swap-deployment <DEPLOYMENT_NAME[:CONTAINER]>,用來將叢集中的一個Deployment替換為本地的服務。對於上面的service-b,我們可以這樣替換:

$ telepresence --swap-deployment service-b --expose 8000:8000
複製程式碼

這個時候叢集中的服務 A 再想訪問服務 B 的8000埠時,Telepresence 就會將這個請求轉發到本地的8000埠。它的工作原理就是將叢集中的service-b替換為 Telepresence 建立的 proxy ,然後這個 proxy 再將請求轉發到本地客戶端。

即,將原始的網路:

Service Listening on 8000

替換為這個結構:

Service Listening on Local 8000

這樣我們就有機會在本地檢視具體的請求資料,除錯邏輯,以及生成新的回覆。

總結

這篇文章裡我先提出了微服務開發中一個常見的問題,然後介紹了 Telepresence 專案,並且舉例說明瞭怎樣用它來除錯兩種常見的微服務場景。當然,Telepresence 還在不斷的演進,本文中使用的是v0.101版本,後續版本很可能有些不一樣的地方,也歡迎大家不斷指正。


  1. Cloud Native Computing Foundation,致力於推廣雲原生應用,旗下的代表專案有 Kubernetes,etcd等。 ↩︎