前言
隨著 Kubernetes 的普及,越來越多的應用被容器化,並部署到 Kubernetes 上。隨之而來的問題是當容器中發生錯誤時,對錯誤的定位和調試也變得很複雜。當一個工具給你帶來便利時,它也可能給你帶來另一些麻煩。
那麼有沒有工具可以在本地聯通 Kubernetes 集群並進行調試呢?當然是有的,這裡就介紹一款研發側利器:Kt Connect
Kt Connect
Kt Connect
是阿里巴巴開源的一款雲原生協同開發測試解決方案,目前的功能包括:
- 直接訪問 Kubernetes 集群
- 轉發集群流量到本地
- Service Mesh 支持
- 基於 SSH 的輕量級 VPN 網絡
- 作為 kubectl 插件,集成到 Kubectl
(以上內容來自官方文檔)
目前使用下來最實用的功能就是直接連接 Kubernetes 網絡實現在本地使用 k8s 內網域名調用 Kubernetes 集群內的服務以及將 Kubernetes 集群中的流量轉發到本地,作用類似於一個 VPN,將本地網絡與 Kubernetes 集群網絡連接。
安裝
Kt Connect
使用 Go 開發,支持 Mac、Linux 和 Windows,安裝方式也很簡單
前往Github Releases 下載可執行文件
Mac
安裝sshuttle
brew install sshuttle
下載並安裝KT
$ curl -OL https://rdc-incubators.oss-cn-beijing.aliyuncs.com/stable/ktctl_darwin_amd64.tar.gz
$ tar -xzvf ktctl_darwin_amd64.tar.gz
$ mv ktctl_darwin_amd64 /usr/local/bin/ktctl
$ ktctl -h
Linux
安裝sshuttle
pip install sshuttle
下載並安裝KT
$ curl -OL https://rdc-incubators.oss-cn-beijing.aliyuncs.com/stable/ktctl_linux_amd64.tar.gz
$ tar -xzvf ktctl_linux_amd64.tar.gz
$ mv ktctl_linux_amd64 /usr/local/bin/ktctl
$ ktctl -h
Windows
下載並解壓可執行文件,並確保ktctl在PATH路徑下
本地連接集群
以MacOS為例
使用 ktctl connect
命令,啟動的時候需要 admin 權限,需要輸入密碼
$ ktctl --namespace=default connect
1:51PM INF Connect Start At 69444
1:51PM INF Client address 192.168.7.121
1:51PM INF deploy shadow deployment kt-connect-daemon-rcacy in namespace default
1:51PM INF pod label: kt=kt-connect-daemon-rcacy
1:51PM INF pod: kt-connect-daemon-rcacy-fd4c587f-zmn4z is running,but not ready
1:51PM INF pod: kt-connect-daemon-rcacy-fd4c587f-zmn4z is running,but not ready
1:51PM INF Shadow pod: kt-connect-daemon-rcacy-fd4c587f-zmn4z is ready.
Forwarding from 127.0.0.1:2222 -> 22
Forwarding from [::1]:2222 -> 22
1:51PM INF port-forward start at pid: 69445
[local sudo] Password: 1:51PM INF vpn(sshuttle) start at pid: 69449
1:51PM INF KT proxy start successful
# 這裡需要輸入密碼
Handling connection for 2222
Warning: Permanently added '[127.0.0.1]:2222' (ECDSA) to the list of known hosts.
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
client: Connected.
這裡可以看到在 namespace:default
中部署了一個 kt-connect-daemon-*
的 Deployment
,如果這個 Deployment
啟動正常,就可以直接在本地訪問 Kubernetes 集群內的服務了。
$ kubectl get deploy | grep kt
kt-connect-daemon-rcacy 1/1 1 1 5m35s
訪問集群服務,可以使用 curl
或者直接在瀏覽器訪問。(這裡使用之前文章《使用 Grafana 展示肺炎疫情動態》中部署的服務)
使用 curl
$ curl kk-feiyan
UP
直接使用瀏覽器
轉發集群流量到本地
使用 ktctl exchange
命令,這個命令的前提條件是 Kubernetes 集群中必須有已經已經存在的 Deployment
,在運行該命令時,將會起一個 shadow 容器,來代替已存在的 Deployment,調用該容器的流量,都會被轉發到本地的指定端口。
要注意的是:該命令會將其代替的 Deployment 的 replicas 設置為0,可能會導致業務的暫停,請勿在生產環境中使用!
本地啟動一個服務
運行命令
$ ktctl exchange kk-feiyan --expose 8088
2:13PM INF 'KT Connect' is runing, you can access local app from cluster and localhost
2:13PM INF Client address 192.168.7.121
2:13PM INF deploy shadow deployment kk-feiyan-kt-yssnq in namespace default
2:13PM INF pod label: kt=kk-feiyan-kt-yssnq
2:13PM INF pod: kk-feiyan-kt-yssnq-6464bbf74d-smvhc is running,but not ready
2:13PM INF pod: kk-feiyan-kt-yssnq-6464bbf74d-smvhc is running,but not ready
2:13PM INF Shadow pod: kk-feiyan-kt-yssnq-6464bbf74d-smvhc is ready.
2:13PM INF create exchange shadow kk-feiyan-kt-yssnq in namespace default
2:13PM INF scale deployment kk-feiyan to 0
2:13PM INF * kk-feiyan (0 replicas) success
2:13PM INF remote 172.22.1.166 forward to local 8088
Forwarding from 127.0.0.1:2266 -> 22
Forwarding from [::1]:2266 -> 22
2:13PM INF exchange port forward to local start at pid: 70269
2:13PM INF redirect request from pod 172.22.1.166 22 to 127.0.0.1:2266 starting
Handling connection for 2266
Warning: Permanently added '[127.0.0.1]:2266' (ECDSA) to the list of known hosts.
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
2:13PM INF ssh remote port-forward start at pid: 70270
查看 Deployment
$ kubectl get deploy | grep kk-feiyan
kk-feiyan 0/0 0 0 39d # 原服務
kk-feiyan-kt-eclcc 1/1 1 1 89s # 轉發流量服務
這樣的話,集群內調用 kk-feiyan
這個服務的流量都會被轉發到本地
集群內調用:
$ curl kk-feiyan
UP
可以看到流量被抓發到了本地
將本地服務暴露到 Kubernetes 集群
有些時候,我們並不想使用 exchange
來代替已經存在的 Deployment,只想在集群內新建一個服務來將流量轉發到本,以完成調試。
這個時候使用 ktctl run
,就可以滿足需求,該命令會在 Kubernetes 集群中新建一個服務,並將訪問該服務的流量被轉發到本地的指定端口。
$ ktctl run localservice --port 8088 --expose
2:33PM INF Client address 192.168.7.121
2:33PM INF deploy shadow deployment localservice in namespace default
2:33PM INF pod label: kt=localservice
2:33PM INF pod: localservice-77d565c488-64hpp is running,but not ready
2:33PM INF pod: localservice-77d565c488-64hpp is running,but not ready
2:33PM INF Shadow pod: localservice-77d565c488-64hpp is ready.
2:33PM INF create shadow pod localservice-77d565c488-64hpp ip 172.22.1.74
2:33PM INF expose deployment localservice to localservice:8088
2:33PM INF remote 172.22.1.74 forward to local 8088
Forwarding from 127.0.0.1:2274 -> 22
Forwarding from [::1]:2274 -> 22
2:33PM INF exchange port forward to local start at pid: 70899
2:33PM INF redirect request from pod 172.22.1.74 22 to 127.0.0.1:2274 starting
Handling connection for 2274
Warning: Permanently added '[127.0.0.1]:2274' (ECDSA) to the list of known hosts.
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
2:33PM INF ssh remote port-forward start at pid: 70903
2:33PM INF forward remote 172.22.1.74:8088 -> 127.0.0.1:8088
可以看到該服務已經被拉起了
$ kubectl get deploy localservice
NAME READY UP-TO-DATE AVAILABLE AGE
localservice 1/1 1 1 86s
訪問該服務
$ curl localservice:8088
UP
可以看到流量被轉發到了本地
總結
本地訪問 k8s 內網,將 k8s 流量轉發到本地,靠著這兩大功能 Kt Connect
可以稱之為研發側的利器,我們可以輕鬆的在本地調用集群服務,或者讓集群調用本地的服務,這就讓開發/測試 k8s 集群中發起調用的服務,在本地斷點 debug 成為了現實,非常好用。同時還有其他一些沒有介紹的功能,比如:
- Service Mesh 支持,可以支持用戶可以基於Service Mesh的能力做更多自定義的流量規則定義
- Dashboard 功能,管理所以使用 kt 連入集群的用戶等等
值得一提的是,ktctl run
功能是我提出該場景並希望能實現,該 issue 提出僅一天就通過並完成了開發。給高效的開發人員點贊。