作者:槐佳輝。Sealos maintainer
在 Kubernetes 的世界中,命令行工具(如 kubectl
和 helm
)是我們與集羣交互的主要方式。然而,有時候,我們可能希望能夠在 Web 頁面中直接打開一個終端,執行這些命令,而不需要在本地環境中安裝和配置這些工具。本文將深入探討如何通過 Kubernetes 自定義資源定義(CRD)實現這個功能,並通過一個真實的示例展示其設計和實現過程。
Sealos 中的 App Launchpad 和 Database 等應用爲我們屏蔽掉了 kubernetes 資源層面的邏輯,抽象爲應用層,但是對應更爲複雜的情況,可能需要我們更原生的操作 kubernetes。
如下所示,在 Terminal 中與 K8s API Server 交互:
查看 Pod 資源(kubernetes 最小調度單位,真正運行容器的資源):
$ kubectl get pod
查看存儲 pvc 資源(容器掛載的存儲資源,如 App Launchpad 中指定的存儲):
$ kubectl get pvc
Terminal 高級用法
Terminal 還支持更爲複雜的操作。
Terminal + App Launchpad 一鍵交互
可以直接通過終端 App 進入每個應用所在容器的終端。假設你在應用管理中部署了一個應用 Nginx,可以直接進入 Nginx 應用的詳情頁面,依次點擊詳情右側的三個點,再點擊「終端」,便進入了 Nginx 應用的終端。
Terminal + Database 一鍵直連
在終端中一鍵直連數據庫 App 中創建的數據庫。
進入數據庫詳情頁面,點擊左側的「一鍵連接」:
跳轉到 Terminal 並直連數據庫:
功能描述
這個功能的核心是一個名爲 Terminal
的 Kubernetes CRD。用戶可以在 Web 頁面中創建一個新的 Terminal
CRD,然後頁面會打開一個新的 Terminal。這個 Terminal 具有指定 Kubernetes Namespace 的訪問權限,可以執行 kubectl
,helm
等命令。
下面是一個 Terminal
CRD 的示例:
spec:
apiServer: https://kubernetes.default.svc.cluster.local:443
ingressType: nginx
keepalived: 4h
replicas: 1
token: xxxxx
status:
availableReplicas: 1
domain: https://xxxxxx.cloud.sealos.io
CRD 字段說明
在 Terminal
CRD 的 spec
部分,以下是各字段的說明:
apiServer
: Kubernetes API 服務器的地址。Terminal 使用這個地址與 Kubernetes API 服務器通信。ingressType
: Ingress 控制器的類型,可以是nginx
或apisix
。keepalived
: Terminal 的生存時間。例如,4h
表示 Terminal 在被創建 4 小時後會被自動刪除。replicas
: Terminal 的副本數。目前只支持1
。token
: Kubernetes API 服務器的訪問令牌。Terminal 使用此令牌進行鑑權。
在 status
部分,以下是各字段的說明:
availableReplicas
: 可用副本數量。domain
: 用於在 Web 中與 Terminal 交互的地址。
創建 Terminal
CRD 後,Web 頁面中就會打開一個新的 Terminal。用戶可以在這個 Terminal 中執行 kubectl
,helm
等命令。
設計與實現
Terminal
功能的設計與實現包括以下幾個關鍵部分:
Terminal Controller
Terminal
Controller 是 Terminal
功能的核心部分。它負責監聽 Terminal
CRD 的創建、更新和刪除事件,並響應這些事件。
Terminal Pod
Terminal
Pod 是實際運行的 Terminal。它運行一個特殊的 Docker 鏡像,這個鏡像包含了 kubectl
,helm
等命令行工具,以及一個 Web 終端服務器(例如 ttyd)。Pod 內的 Web 終端服務器監聽 8080 端口,並提供 Web 終端服務。
Service 和 Ingress
Terminal
Controller 爲每個 Terminal
CRD 創建一個對應的 Kubernetes Service 和 Ingress。Service 將網絡流量路由到 Terminal
Pod,Ingress 將外部訪問請求路由到 Service。
Terminal Docker 鏡像
Terminal
Docker 鏡像是 Terminal
Pod 運行的鏡像。它基於 Ubuntu 20.04,包含了 kubectl
,helm
等命令行工具,以及一個 Web 終端服務器 ttyd。此外,該鏡像還包含了 MySQL,MongoDB,Redis 的客戶端,以便用戶能夠直接在 Terminal 中連接和操作這些數據庫。
這個 Docker 鏡像的構建過程如下:
-
安裝必要的軟件包,包括
kubectl
,helm
,vim
等。 -
將 Web 終端服務器
ttyd
和一個啓動腳本start-terminal.sh
添加到鏡像中。 -
設置
ttyd
服務器監聽 8080 端口,並配置ttyd
服務器的啓動參數,包括 Kubernetes API 服務器的地址和訪問令牌。
這個 Docker 鏡像的 Dockerfile 如下:
FROM ubuntu:20.04
LABEL org.opencontainers.image.authors="labring"
USER root
ENV HOME /root
ARG kubeVersion=1.25.6
ARG ttydVersion=1.7.3
ARG helmVersion=3.12.0
ARG ARCH
ARG DEBIAN_FRONTEND=noninteractive
WORKDIR /root
COPY ./inline.html ./index.html
COPY vim/ .
COPY scripts/start-terminal.sh /usr/bin/
COPY scripts/ttyd-kubectl.sh /usr/bin/
RUN arch && \
apt-get update && \
apt-get install -y --no-install-recommends -o Acquire::http::No-Cache=True \
ca-certificates curl wget bind9-utils git g++ gcc libc6-dev make pkg-config vim \
ncurses-dev libtolua-dev exuberant-ctags gdb dnsutils iputils-ping net-tools postgresql-client && \
apt-get clean && rm -rf /var/lib/apt/lists/* && \
chmod a+x /usr/bin/ttyd-kubectl.sh && \
bash /usr/bin/ttyd-kubectl.sh && \
vim +PlugInstall +qall && \
chmod a+x /usr/bin/start-terminal.sh
ENV USER_TOKEN ""
ENV APISERVER "https://apiserver.cluster.local:6443"
ENV USER_NAME "admin"
ENV NAMESPACE "default"
EXPOSE 8080
CMD ["sh","/usr/bin/start-terminal.sh"]
鏡像 Dockerfile:https://github.com/labring-actions/cluster-image/blob/main/dockerimages/terminal/latest/Dockerfile
鏡像託管 GitHub 自動化構建倉庫:https://github.com/labring-actions/cluster-image
Terminal 刪除和生存時間
Terminal
Controller 使用 Kubernetes 的 Finalizer 機制來處理 Terminal
CRD 的刪除事件。當 Terminal
CRD 被刪除時,Finalizer 會阻止 Kubernetes 立即刪除 CRD,而是等待 Terminal
Controller 清理與 Terminal
CRD 相關的資源(如 Deployment,Service 和 Ingress)後再刪除 CRD。
此外,Terminal
Controller 還使用 Keepalive 機制來自動刪除過期的 Terminal
。Terminal
的生存時間由 keepalived
字段指定,當 Terminal
存在的時間超過 keepalived
指定的時間後,Terminal
Controller 會自動刪除 Terminal
。
前後端交互流程
下面是用戶從點擊 Terminal 按鈕到進入 Terminal 的具體流程:
-
用戶在 Web 頁面中點擊 Terminal 按鈕,頁面會發送一個請求到後端,請求中包含了 Terminal 的配置信息(如 Kubernetes Namespace 和生存時間)。
-
後端接收到請求後,會創建一個新的
Terminal
CRD,CRD 中包含了 Terminal 的配置信息。 -
Terminal
Controller 監控到新的Terminal
CRD 被創建,會創建一個對應的Terminal
Pod,Pod 運行的 Docker 鏡像包含了kubectl
,helm
等命令行工具,以及一個 Web 終端服務器。 -
Terminal
Controller 還會創建一個對應的 Kubernetes Service 和 Ingress,Service 將網絡流量路由到Terminal
Pod,Ingress 將外部訪問請求路由到 Service。 -
後端會從
Terminal
CRD 的status
字段中獲取到 Terminal 的域名,並將這個域名返回給前端。 -
前端接收到 Terminal 的域名後,會在新的標籤頁中打開這個域名,用戶就可以看到一個新的 Terminal,並可以在這個 Terminal 中執行
kubectl
,helm
等命令。
自定義配置
多種 Ingress 控制器支持
Terminal
支持多種 Ingress 控制器,包括 Nginx 和 Apisix。用戶可以根據自己的實際情況選擇合適的 Ingress 控制器。
生存時間設置
用戶可以設置 Terminal
的生存時間。Terminal
在被創建一段時間後會被自動刪除,這樣可以防止 Terminal
長時間未使用而佔用系統資源。
未來的改進
更多的命令行工具支持
在 Terminal
Docker 鏡像中添加更多的命令行工具,如 istioctl
,kn
等,這樣用戶就可以在 Terminal
中執行更多的操作。
更多的 Ingress 控制器支持
支持更多的 Ingress 控制器,如 Traefik,HAProxy 等,用戶可以根據自己的實際情況選擇合適的 Ingress 控制器。
使用 WebSocket 通信
通過 Ingress 暴露 WebSocket 服務。用戶可以在 Web 頁面中打開一個終端,通過 WebSocket 與 Kubernetes 集羣進行交互。相比於 HTTP 協議,WebSocket 提供了更高效、實時的雙向通信能力,極大地提升了用戶的使用體驗。
權限控制
增加權限控制功能,後續增加企業協作功能,多用戶共享 namespace,terminal 通過獲取相應權限來獲得對應用戶空間的權限,如 manager, developer 等。
集成更多開發工具
除了 kubectl
和 helm
外,還可以在 Terminal
中集成更多的開發和調試工具,如 git
,curl
,jq
等。
個性化配置
用戶可以根據自己的需要,配置 Terminal 的外觀,如主題顏色,字體大小等。也可以配置 Terminal 的行爲,如命令歷史記錄的長度,鍵盤快捷鍵等。
結論
通過 Kubernetes 的 CRD 功能,我們可以輕鬆地在 Web 頁面中添加一個功能強大的 Terminal。用戶可以在這個 Terminal 中執行各種命令,更好地與 Kubernetes 集羣交互。這不僅提高了用戶的工作效率,也極大地提升了用戶的使用體驗。