如何像 Sealos 一樣在瀏覽器中打造一個 Kubernetes 終端?

作者:槐佳輝。Sealos maintainer

在 Kubernetes 的世界中,命令行工具(如 kubectlhelm)是我們與集羣交互的主要方式。然而,有時候,我們可能希望能夠在 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 的訪問權限,可以執行 kubectlhelm 等命令。

下面是一個 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 控制器的類型,可以是 nginxapisix
  • keepalived: Terminal 的生存時間。例如,4h 表示 Terminal 在被創建 4 小時後會被自動刪除。
  • replicas: Terminal 的副本數。目前只支持 1
  • token: Kubernetes API 服務器的訪問令牌。Terminal 使用此令牌進行鑑權。

status 部分,以下是各字段的說明:

  • availableReplicas: 可用副本數量。
  • domain: 用於在 Web 中與 Terminal 交互的地址。

創建 Terminal CRD 後,Web 頁面中就會打開一個新的 Terminal。用戶可以在這個 Terminal 中執行 kubectlhelm 等命令。

設計與實現

Terminal 功能的設計與實現包括以下幾個關鍵部分:

Terminal Controller

Terminal Controller 是 Terminal 功能的核心部分。它負責監聽 Terminal CRD 的創建、更新和刪除事件,並響應這些事件。

Terminal Pod

Terminal Pod 是實際運行的 Terminal。它運行一個特殊的 Docker 鏡像,這個鏡像包含了 kubectlhelm 等命令行工具,以及一個 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,包含了 kubectlhelm 等命令行工具,以及一個 Web 終端服務器 ttyd。此外,該鏡像還包含了 MySQL,MongoDB,Redis 的客戶端,以便用戶能夠直接在 Terminal 中連接和操作這些數據庫。

這個 Docker 鏡像的構建過程如下:

  1. 安裝必要的軟件包,包括 kubectlhelmvim 等。

  2. 將 Web 終端服務器 ttyd 和一個啓動腳本 start-terminal.sh 添加到鏡像中。

  3. 設置 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 機制來自動刪除過期的 TerminalTerminal 的生存時間由 keepalived 字段指定,當 Terminal 存在的時間超過 keepalived 指定的時間後,Terminal Controller 會自動刪除 Terminal

前後端交互流程

下面是用戶從點擊 Terminal 按鈕到進入 Terminal 的具體流程:

  1. 用戶在 Web 頁面中點擊 Terminal 按鈕,頁面會發送一個請求到後端,請求中包含了 Terminal 的配置信息(如 Kubernetes Namespace 和生存時間)。

  2. 後端接收到請求後,會創建一個新的 Terminal CRD,CRD 中包含了 Terminal 的配置信息。

  3. Terminal Controller 監控到新的 Terminal CRD 被創建,會創建一個對應的 Terminal Pod,Pod 運行的 Docker 鏡像包含了 kubectlhelm 等命令行工具,以及一個 Web 終端服務器。

  4. Terminal Controller 還會創建一個對應的 Kubernetes Service 和 Ingress,Service 將網絡流量路由到 Terminal Pod,Ingress 將外部訪問請求路由到 Service。

  5. 後端會從 Terminal CRD 的 status 字段中獲取到 Terminal 的域名,並將這個域名返回給前端。

  6. 前端接收到 Terminal 的域名後,會在新的標籤頁中打開這個域名,用戶就可以看到一個新的 Terminal,並可以在這個 Terminal 中執行 kubectlhelm 等命令。

自定義配置

多種 Ingress 控制器支持

Terminal 支持多種 Ingress 控制器,包括 Nginx 和 Apisix。用戶可以根據自己的實際情況選擇合適的 Ingress 控制器。

生存時間設置

用戶可以設置 Terminal 的生存時間。Terminal 在被創建一段時間後會被自動刪除,這樣可以防止 Terminal 長時間未使用而佔用系統資源。

未來的改進

更多的命令行工具支持

Terminal Docker 鏡像中添加更多的命令行工具,如 istioctlkn 等,這樣用戶就可以在 Terminal 中執行更多的操作。

更多的 Ingress 控制器支持

支持更多的 Ingress 控制器,如 Traefik,HAProxy 等,用戶可以根據自己的實際情況選擇合適的 Ingress 控制器。

使用 WebSocket 通信

通過 Ingress 暴露 WebSocket 服務。用戶可以在 Web 頁面中打開一個終端,通過 WebSocket 與 Kubernetes 集羣進行交互。相比於 HTTP 協議,WebSocket 提供了更高效、實時的雙向通信能力,極大地提升了用戶的使用體驗。

權限控制

增加權限控制功能,後續增加企業協作功能,多用戶共享 namespace,terminal 通過獲取相應權限來獲得對應用戶空間的權限,如 manager, developer 等。

集成更多開發工具

除了 kubectlhelm 外,還可以在 Terminal 中集成更多的開發和調試工具,如 gitcurljq 等。

個性化配置

用戶可以根據自己的需要,配置 Terminal 的外觀,如主題顏色,字體大小等。也可以配置 Terminal 的行爲,如命令歷史記錄的長度,鍵盤快捷鍵等。

結論

通過 Kubernetes 的 CRD 功能,我們可以輕鬆地在 Web 頁面中添加一個功能強大的 Terminal。用戶可以在這個 Terminal 中執行各種命令,更好地與 Kubernetes 集羣交互。這不僅提高了用戶的工作效率,也極大地提升了用戶的使用體驗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章