~xdavidwu/cskloudv3-thesis

8c379daa5fd99e7bebbccd1af89b98bb8f7546aa — Pinghao Wu 6 months ago 4625dce
Architecture: revisit
M Sections/2.Backgrounds.tex => Sections/2.Backgrounds.tex +1 -1
@@ 68,7 68,7 @@ Kubernetes 主要透過兩個機制達成使用者的存取控制,其一是 RB

Kubernetes 內建許多 admission controllers,其中一些用來實做基本功能並預設啟用,如資源配額的部份邏輯。另外也有些預設停用的 admission controllers,提供給管理者進行平台加固或者調整行為使用。

對於內建的 admission controllers 不敷使用的場合,Kubernetes 提供兩個機制讓管理者進一步自訂邏輯:webhooks 與 Common Expression Language (簡稱 CEL)。Webhooks 透過呼叫管理者提供的 HTTP API 達成,支援 mutating 與 validating,可以透過任何能架設 HTTP API 的語言編寫,在生態系上已經有多個框架可以協助開發,例如:Open Policy Agent 與 Kyverno 等。CEL 為一結構資料處理語言,常用以使軟體功能可程式化,Kubernetes 將其導入作為延伸 kube-apiserver 邏輯的手段。以 Kubernetes 1.31 而言,目前只有 validating 進入穩定狀態,對 mutating 的支援仍在測試階段 (alpha)。相對於 webhooks,使用 CEL 可以直接在 kube-apiserver 上執行邏輯,省略了呼叫 HTTP API 的網路溝通,減少造成的延遲影響與管理負擔,但能夠進行的操作受限於 Kubernetes 對其執行環境提供的函式庫。
對於內建的 admission controllers 不敷使用的場合,Kubernetes 提供兩個機制讓管理者進一步自訂邏輯:webhooks 與 Common Expression Language\cite{cel} (簡稱 CEL)。Webhooks 透過呼叫管理者提供的 HTTP API 達成,支援 mutating 與 validating,可以透過任何能架設 HTTP API 的語言編寫,在生態系上已經有多個框架可以協助開發,例如:Open Policy Agent 與 Kyverno 等。CEL 為一結構資料處理語言,常用以使軟體功能可程式化,Kubernetes 將其導入作為延伸 kube-apiserver 邏輯的手段。以 Kubernetes 1.31 而言,目前只有 validating 進入穩定狀態,對 mutating 的支援仍在測試階段 (alpha)。相對於 webhooks,使用 CEL 可以直接在 kube-apiserver 上執行邏輯,省略了呼叫 HTTP API 的網路溝通,減少造成的延遲影響與管理負擔,但能夠進行的操作受限於 Kubernetes 對其執行環境提供的函式庫。

\section{Helm}


M Sections/4.Architecture.tex => Sections/4.Architecture.tex +45 -48
@@ 99,7 99,7 @@ Kubernetes 中容器 images 的下載策略(\verb|imagePullPolicy| 欄位)
\section{權限開通實做}
\label{sec:provisioner}

使用者權限開通的主要流程為:建立一個 Namespace,增加 admission controllers 政策相關標記,對其設定配額,最終調整 RBAC 授予使用者此 Namespace 下的權限。為了將其自動化,我們規劃為拓展 Kubernetes API,使用自訂 resource 種類進行實做,此種類稱為 User。使用者登入網頁界面時會自動嘗試創立代表自身的 User,若已存在代表已開通完成不須另外動作。面對新創立的 User,我們撰寫的 controller 會實行上述的開通流程。
使用者權限開通的主要流程為:建立一個 Namespace,增加 admission controllers 政策相關標記,對其設定資源配額,最終調整 RBAC 授予使用者此 Namespace 下的權限。為了將其自動化,我們規劃為拓展 Kubernetes API,使用自訂 resource 種類進行實做,此種類稱為 User。使用者登入網頁界面時會自動嘗試創立代表自身的 User,若已存在代表已開通完成不須另外動作,而面對新創立的 User,我們撰寫的 controller 會實行上述的開通流程。

\begin{figure}[htb]
    \centering


@@ 107,58 107,57 @@ Kubernetes 中容器 images 的下載策略(\verb|imagePullPolicy| 欄位)
    \caption{權限開通自訂 resource 種類 User spec 範例}
\end{figure}

每個使用者會創立一個與其系計中帳號名稱相同的 User,其中 \verb|spec| 的 \verb|profile| 欄位帶有其身份組資訊,由網頁界面自動判斷填入。身份組影響對齊開放配額的大小。對於創立代表自身 User 所需的權限,我們透過 RBAC 允許所有使用者創立 User,再透過 admission control 將其限制名稱必須與身份相同。分兩階段設計有助於簡化 RBAC 實做,使 RBAC 實做上不須枚舉使用者名稱一一事先對應,同時也減少叢集上相關設定的 resources 個數,有助於減少管理上的負擔。對於 \verb|profile| 欄位的真實性,我們一樣透過 admission control 與身份資訊比對。
每個使用者會創立一個與其系計中帳號名稱相同的 User,其中 \verb|spec| 的 \verb|profile| 欄位帶有身份組資訊,影響資源配額的大小,由網頁界面自動判斷填入。對於創立代表自身 User 所需的權限,我們透過 RBAC 允許所有使用者創立 User,再透過 admission control 將其限制名稱必須與身份相同。兩階段的設計有助於簡化 RBAC 實做,使 RBAC 實做上不須枚舉使用者名稱一一事先對應,同時也大幅降低叢集上相關設定的 resources 個數,有助於減少管理上的負擔。對於 \verb|profile| 欄位的真實性,我們一樣透過 admission control 與身份資訊比對證實。

實際上以 \verb|profile| 欄位而言,還有一個可行的方法,即是以 mutating admission control 層由叢集端判斷寫入,而不用仰賴網頁界面邏輯。這個方式目前有個缺點:admission control 邏輯我們希望透過 CEL 實做,而以 CEL 實做 mutating 雖然已有相關機制,現今仍未進入穩定狀態。另外,透過網頁界面預填也使得 admission control 層只須實做 validating,相對於 mutating,validating 因不能修改 resource 內容,較為單純且有平行化處理的空間,在效能與管理上皆有些許優勢。
就 \verb|profile| 欄位而言,還有另一個可行的方法,即是以 mutating admission control 由叢集端判斷寫入,而不仰賴網頁界面邏輯。這個方式目前有個缺點:admission control 邏輯我們希望透過 CEL 實做,而以 CEL 實做 mutating 雖然已有相關機制,現今仍未進入穩定狀態。另外,透過網頁界面預填也使得 admission control 層只須實做 validating,相對於 mutating,validating 因不能修改 resource 內容,較為單純且有平行化處理的空間,在效能與管理上皆有些許優勢。

對於管理需求,我們在 admission control 實做保留了彈性,若操作者為管理者即不加以限制。管理者可以自行創立代表他人的 User,為其修改身份組,提供人工處理政策上例外的空間。另外,由 User 所產生的每個 resource 皆會採用 Kubernetes 的 \verb|ownerReferences| 機制。\verb|ownerReferences| 表現了一個 resource 被一個 owner resource 所管轄,當 owner resource 被刪除時,Kubernetes 的回收機制也會一併刪除此 resource。在我們的場景,由於使用者的資料皆為於個人專屬的 Namespace 底下,而 User 又為此 Namespace 的 owner resource,於是當使用者行為極端異常,管理者需要對其制裁時,只須刪除其 User 變可以徹底清除此使用者的所作所為。
對於管理需求,我們在 admission control 實做保留了彈性,若操作者為管理者即不加以限制。管理者可以自行創立代表他人的 User,為其修改身份組,提供人工處理政策上例外的空間。另外,由 User 所產生的每個 resource 皆會採用 Kubernetes 的 \verb|ownerReferences| 機制。\verb|ownerReferences| 表現了一個 resource 被一個 owner resource 所管轄,當 owner resource 被刪除時,Kubernetes 的回收機制也會一併刪除此 resource。在我們的場景,由於使用者的資料皆為於個人專屬的 Namespace 底下,而 User 又為此 Namespace 的 owner resource,於是當使用者行為極端異常,管理者需要對其制裁時,只須刪除其 User 便可徹底清除此使用者的所作所為。

在實做方面,User 種類的定義以及 controller 邏輯採取 kubebuilder 框架實做。kubebuilder 採用 Go 程式語言,以及 \verb|sig.k8s.io/controller-runtime| 函式庫開發,提供由 Go 語言的資料結構定義輔以註解擴充,搭配程式碼生成技術實現 Kubernetes resource 種類的定義,並且提供實做 controller 時所需的監控 resources 變更等基本邏輯。另外,\verb|sig.k8s.io/controller-runtime| 亦具備 \verb|envtest| 測試框架,自動化運行 kube-apiserver 等元件,在不需要架設完整叢集的前提下,提供 controller 較為完整的測試環境。
在實做方面,User 種類的定義以及 controller 邏輯採用 Kubebuilder\cite{kubebuilder} 框架撰寫。Kubebuilder 採用 Go 程式語言與 \verb|sig.k8s.io/controller-runtime| 函式庫開發,由 Go 語言的資料結構定義輔以註解補充,搭配程式碼生成技術實現 Kubernetes resource 種類的定義,並且提供實做 controller 時所需的監控 resources 變更等基本邏輯。另外,\verb|sig.k8s.io/controller-runtime| 亦具備 \verb|envtest| 測試框架,自動化運行 kube-apiserver 等元件,在不需要架設完整叢集的前提下,提供 controller 較為完整的測試環境。

\subsection{Namespace}

為了避免命名與叢集上既有、負責叢集本身運行的 Namespaces 衝突,我們將使用者的 Namespace 命名為 \verb|u-| 前綴加上系計中帳號名稱(即相關 User resource 的名稱)。

在創立 Namespace 時,根據個別的 admission controllers 設計,需要在 \verb|labels| 或 \verb|annotations| 上加註政策。\verb|labels| 與 \verb|annotations| 皆是 Kubernetes resources 共通的 key-value 標記,常用以輔助管理辨識,或是以較高的彈性提供次要的功能,其中 \verb|labels| 在透過 Kubernetes API 列舉時可以用來作為條件過濾 resources,但同時能夠儲存的內容也具有相關限制。需要設定的有 \ref{sec:PodSecurity} PodSecurity、\ref{sec:PodTolerationRestriction} PodTolerationRestriction 與 \ref{sec:CEL} 以 CEL 實做的域名使用權管控。為了方便管理者透過過濾進行清查,域名管控我們設計以 \verb|labels| 設定白名單,一個域名一條 label。平台預設開放如帳號名稱加上 \verb|.u.cloud.cs.nycu.edu.tw| 後綴的域名供使用者使用。
在創立 Namespace 時,根據個別的 admission controllers 設計,需要在 \verb|labels| 或 \verb|annotations| 上加註政策。\verb|labels| 與 \verb|annotations| 皆是 Kubernetes resources 共通的 key-value 標記欄位,常用於輔助管理辨識,或是以較高的修改彈性提供次要的功能,其中 \verb|labels| 在透過 Kubernetes API 列舉 resources 時可作為條件過濾,因此也常用於 resources 間的關聯建立,但能夠儲存的內容也具有相關限制。需要設定政策的有 \ref{sec:PodSecurity} \verb|PodSecurity|、\ref{sec:PodTolerationRestriction} \verb|PodTolerationRestriction| 與 \ref{sec:CEL} 以 CEL 實做的域名使用權管控。為了方便管理者透過過濾進行清查,域名管控我們設計以 \verb|labels| 設定白名單,一個域名一條 label。平台預設開放如帳號名稱加上 \verb|.u.cloud.cs.nycu.edu.tw| 後綴\footnote{平台有預先配置 *.u.cloud.cs.nycu.edu.tw 的 wildcard 域名紀錄與 TLS 憑證。}的域名供使用者使用。

Namespace 上 \verb|u-| 以及平台提供域名中 \verb|u.| 的命名切分設計使得平台可以進一步擴充,除了以使用者為單位以外,未來可以增加其他種類的命名切分,提供以如實驗室或課程為單位的服務。

\subsection{ResourceQuota}

ResourceQuota 是 Kubernetes 的一個 resource 種類,用來實做單一 Namespace 下的資源配額,其運作邏輯大致分兩大塊:admission controller 與一般的 controller。ResourceQuota 的 admission controller 屬於 validating,負責在創立或更新 resource 時推算其資源用量的變化值,並且拒絕用量會超出配額的請求。一般的 controller 端則是以更為全面的觀點,監控整體 resources 的變更,並且統計資源用量總額。
ResourceQuota 是 Kubernetes 的一個 resource 種類,用來實做單一 Namespace 下的資源配額,其運作邏輯大致分兩大塊:admission controller 與一般的 controller。ResourceQuota 的 admission controller 屬於 validating,負責在創立或更新 resource 時推算其資源用量的變化值,並且拒絕用量將超出配額的請求。一般的 controller 端則是以更為全面的觀點,監控整體 resources 的變更,並且統計資源用量總額。

ResourceQuota 所能管控的資源大致有兩種:運算資源以及 resources 的數量。運算資源具有量值,例如部屬容器時設定的 CPU 或者記憶體用量限制,以及 PersistentVolumeClaim (PVC)\footnote{PVC: Resource 種類,表示儲存空間請求,需自動或手動與 PersistentVolume(PV,分配實體)耦合。} 中的儲存用量請求。Resources 的數量則是滿足特定條件的 resources 的個數,例如正在運行的 Pods。

除了使用 ResourceQuota 來限制運算資源用量,我們運用其中部份特定條件來限制 resource 內容,最為代表性的是 Service。Service 作為具備負載均衡的網路存取點,根據其 \verb|spec| 的 \verb|type| 欄位,主要又分為 \verb|ClusterIP|、\verb|NodePort|、\verb|LoadBalancer| 三大類別。\verb|ClusterIP| 為最單純、最常見的叢集內部存取點,\verb|NodePort| 額外在每個節點宿主端的網路環境提供存取點,\verb|LoadBalancer| 則是進一步串接叢集外部的負載均衡器。由於在我們的叢集規劃下,節點架設於內部網路,使用者無法直接存取節點,\verb|NodePort| 對使用者來說並無用途,同時 \verb|NodePort| 使用叢集本身的有限網路資源,不適合對使用者開放。\verb|LoadBalancer| 則是需佔用外部負載均衡器的 IP 位址分配池,其大小非常有限,也不適合開放給使用者。ResourceQuota 正有根據類別分開統計 Service 數量的邏輯,我們利用此特性,設置相關配額為零,防止使用者使用 \verb|NodePort| 與 \verb|LoadBalancer|。
除了使用 ResourceQuota 來限制運算資源用量,我們運用個數特定條件邏輯來限制 resource 內容,其中最為代表性的是 Service。Service 作為具備負載均衡的網路存取點,根據其 \verb|spec| 的 \verb|type| 欄位,主要又分為 \verb|ClusterIP|、\verb|NodePort|、\verb|LoadBalancer| 三大型別。\verb|ClusterIP| 為最基本、最常見的叢集內部存取點,\verb|NodePort| 額外在每個節點宿主端的網路環境提供存取點,\verb|LoadBalancer| 則是進一步串接叢集外部的負載均衡器。在我們的叢集規劃下,節點架設於內部網路,使用者無法直接存取節點,\verb|NodePort| 對使用者來說並無用途,同時 \verb|NodePort| 使用節點的有限網路資源,不適合對使用者開放。\verb|LoadBalancer| 則是需佔用外部負載均衡器的 IP 位址分配池,其大小非常有限,也不適合開放給使用者。ResourceQuota 正有根據型別分開統計 Service 數量的邏輯,我們利用此特性,設置對應配額為零,防止使用者使用 \verb|NodePort| 與 \verb|LoadBalancer|。

除了運算資源,以及上述針對 resource 內容的管控,我們也對所有使用者能夠創立的 resource 種類進行總量限制,避免濫用。在其限額設計上,我們仍盡量保持讓使用者可以在運算資源限制合理地自由運用。
除了運算資源,以及上述針對 resource 內容的管控,我們也對所有使用者能夠創立的 resource 種類進行總量限制,避免濫用。對其限額設計,我們仍盡量保持讓使用者可以在運算資源限制內合理地自由運用。

\subsection{LimitRange}

在有使用 ResourceQuota 限制總運算資源用量的情況,所有的 Pods 必須設定容器的相關資源限制。這點十分容易影響使用者體驗,資源限制在 API 上並非必填,以 Kubernetes 通常經由高層次 resources (如 Deployment)去控管 Pods 的方式,如果在高層次 resources 中的 Pod 模板並未填寫資源限制,創立當下並沒有影響,而是在相關 controller 創立 Pod 時才發生錯誤,對使用者來說較難除錯。另外,部份常用代為呼叫 API 的手段如 \verb|kubectl create deployment| 也沒有途徑可以填寫限制。
在使用 ResourceQuota 限制總運算資源用量的情境,所有 Pods 必須設定容器的相關資源限制。這點十分容易影響使用者體驗,資源限制在 API 上並非必填,以 Kubernetes 通常經由高層次 resources (如 Deployment)去控管 Pods 的方式,如果在高層次 resources 中的 Pod 模板並未填寫資源限制,創立當下並不受限制,而是在相關 controller 創立 Pod 時才發生錯誤,對使用者來說較難除錯。另外,部份常用代為呼叫 API 的手段如 \verb|kubectl create deployment| 也沒有途徑可以填寫限制。

對於這個場景,我們可以使用 LimitRange resource 種類。LimitRange 透過 LimitRanger admission controller 限制使用者能夠填寫的資源限制大小範圍,同時也能夠在未填寫的狀況下套用預設值協助補足。LimitRange 如同 ResourceQuota,以單一 Namespace 為作用範圍。我們使用 LimitRange 實做資源限制預設值,以提昇使用者體驗。
面對這個場景,我們使用 LimitRange resource 種類。LimitRange 透過 \verb|LimitRanger| admission controller 限制使用者能夠填寫的資源限制大小範圍,同時也能夠在未填寫的狀況下套用預設值協助補足。LimitRange 如同 ResourceQuota,以單一 Namespace 為作用範圍。我們使用 LimitRange 實做資源限制的欄位預設值,以提昇使用者體驗。

\subsection{測試}

由於權限開通過程較為複雜,並且牽涉多個 admission control 安全性相關設定,因此這方面的測試顯得相當重要。\verb|envtest| 提供的環境涵蓋 kube-apiserver,足以讓我們測試 admission control 的行為,我們用其來實做測試,以整體的行為作為測試目標,例如開通後,使用者應能在其 Namespace 下創立 Pods,但不能帶有關閉隔離措施的設定等。同樣測試流程我們也進一步重複利用,將 \verb|envtest| 抽離,提供可以直接對真實叢集進行的行為測試。
由於權限開通過程較為複雜,並且牽涉多個 admission control 安全性相關設定,因此這方面的測試顯得相當重要。\verb|envtest| 提供的環境涵蓋 kube-apiserver,足以讓我們測試 admission control 的行為,我們用其實做整合測試,以整體的行為作為測試目標,例如開通後,使用者應能在其 Namespace 下創立 Pods,但不能帶有關閉隔離措施的設定等。同樣測試流程我們也進一步重複利用,將 \verb|envtest| 抽離,提供可以直接對真實叢集測試的變種,適用於完整部屬後的驗證場合。

相對於一般用途的 Kubernetes 叢集,CSKloud 也需要額外進行如啟用特定 admission controller 等設定,對此我們也撰寫叢集設定驗證測試,確保相關功能有被啟用,且其設定有經過儲存,以避免安裝上的人為疏失。
相對於一般用途的 Kubernetes 叢集,CSKloud 也需要額外進行如啟用特定 admission controller 等設定。高層次的行為測試雖然可以直觀地撰寫,對於失敗的除錯卻需要對系統有相當深入的認知。對此,我們也撰寫叢集設定驗證測試,確保相關功能有被啟用,且其設定有經過儲存,以底層的角度防止安裝上的人為疏失。

\section{網頁界面實做}

進一步對網頁界面的需求分析,可以將網頁界面切分為兩大塊:支援 Helm 的通用 Kubernetes 網頁型客戶端,以及 CSKloud 特定的部份,包含權限開通元件的整合以及 CSKloud 平台面向使用者的文件等。其中 Kubernetes 客戶端很容易的就可以利用於其他場景,我們採取 open core 的策略,將其 Kubernetes 客戶端開放原始碼,以 MIT 授權條款\footnote{MIT license: 一個在網頁技術場域廣受歡迎的寬鬆型開放原始碼條款。}釋出,命名為 Sparkles\footnote{Sparkles 釋出於 \url{https://github.com/xdavidwu/sparkles} 。},回饋於社會,使得非平台使用者也能受益,同時可以也利用開放原始碼社群的力量來茁壯平台的發展。
進一步對網頁界面的需求分析,可以將網頁界面切分為兩大塊:支援 Helm 的通用 Kubernetes 網頁型客戶端,以及 CSKloud 特定的部份,包含權限開通元件的整合以及 CSKloud 平台面向使用者的文件等。其中 Kubernetes 客戶端很容易的就可以利用於其他場景,我們採取 open-core 的策略,將其開放原始碼,以 MIT 授權條款\footnote{MIT license: 一個在網頁技術場域廣受歡迎的寬鬆型開放原始碼條款。}釋出,命名為 Sparkles\footnote{Sparkles 釋出於 \url{https://github.com/xdavidwu/sparkles} 。},回饋於社會,使得非平台使用者也能受益,同時也利用開放原始碼社群的力量來茁壯平台的發展。

\begin{figure}[htb]
\begin{figure}[thb]
    \centering
    \includegraphics{assets/sparkles-and-web.png}
    \caption{CSKloud v3 網頁界面與 Sparkles 關係示意圖}
\end{figure}

% TODO 可以加一坨 webpage ref :p
網頁界面採用 Vue.js 框架,以 TypeScript 語言\footnote{TypeScript: 一個轉譯為 JavaScript 的語言,比起 JavaScript 多了型別標示以利開發。}撰寫,使用 Vuetify 做為元件庫。Vuetify 的元件設計採用基於 Google 提出的 Material Design 設計語彙,同時 Kubernetes 也是由 Google 發跡的,在些許程度上,選擇 Vuetify 帶給了 Kubernetes 使用者更契合的親切感。由於界面希望帶有在容器內執行指令的功能,所需的終端機傳統上採用黑底白字配色,為避免其元件顯得突兀,整體界面亦採暗色系設計。在流行上,近期資訊界生產力相關的網頁服務也有逐漸導入暗色系設計的趨勢。
網頁界面採用 Vue.js\cite{vue} 框架,以 TypeScript 語言\footnote{TypeScript: 一個轉譯為 JavaScript 的語言,比起 JavaScript 多了型別標示以利開發。}撰寫,使用 Vuetify 做為元件庫。Vuetify 的元件設計採用基於 Google 提出的 Material Design 設計語彙,同時 Kubernetes 也是由 Google 發跡的,在些許程度上,選擇 Vuetify 帶給了 Kubernetes 使用者更契合的親切感。由於界面希望帶有在容器內執行指令的功能,所需的終端機傳統上採用黑底白字配色,為避免其元件顯得突兀,整體界面亦採暗色系設計。在流行上,近期資訊界生產力相關的網頁服務也有逐漸導入暗色系設計的趨勢。

對於 Kubernetes API 的操作,我們採用由 Kubernetes 提供的 OpenAPI\footnote{OpenAPI: 一種用於描述 RESTful API 行為的框架。} 定義檔,透過 openapi-generator\footnote{openapi-generator: 由 OpenAPI 定義檔產生適用於各種不同語言的函式庫的工具。} 自動產生的函式庫輔助開發。在網頁的各個功能,我們皆有採用 Kubernetes 的 watch 機制達到資料的即時更新。Kubernetes 的 watch 是一個特有的 HTTP API 呼叫方法,透過維持長期不中斷的 HTTP response,藉由 HTTP 的 chunked transfer\footnote{Chunked transfer: 一個將內容分塊傳送的 HTTP 編碼機制,常用於串流等持續產生資料的場合。} 編碼,即時的將一個 resources 列表的內容更新以新增、移除、修改 resource 等事件傳出,並且每個事件帶有一個版本號,如果 HTTP 通訊意外中止,客戶端可以透過這個版本號代表對目前 resources 列表的認知,向 Kubernetes 重發一個 watch 呼叫獲取由該版本後的變更。這個機制也廣泛運用在 Kubernetes 元件內部的溝通。
對於 Kubernetes API 的操作,我們採用由 Kubernetes 提供的 OpenAPI\footnote{OpenAPI: 一種用於描述 RESTful API 行為的框架。} 定義檔,透過 openapi-generator\footnote{openapi-generator: 由 OpenAPI 定義檔產生適用於各種不同語言的函式庫的工具。} 自動產生的函式庫輔助開發。在網頁的各個功能,我們皆有採用 Kubernetes 的 watch 機制達到資料的即時更新。Kubernetes 的 watch 是一個特有的 HTTP API 呼叫方法,透過維持長期不中斷的 HTTP response,藉由 HTTP 的 chunked transfer\footnote{Chunked transfer: 一個將內容分塊傳送的 HTTP 編碼機制,常用於串流等持續產生資料的場合。} 編碼,即時的將一個 resources 列表的內容更新以新增、移除、修改 resource 等事件傳出,並且每個事件帶有一個版本號,如果 HTTP 通訊意外中止,客戶端可以透過這個版本號代表目前對 resources 列表的認知,向 Kubernetes 重發一個 watch 呼叫獲取由該版本後的變更。這個機制也廣泛運用在 Kubernetes 元件內部的溝通。

\begin{figure}[htb]
    \centering


@@ 166,7 165,7 @@ ResourceQuota 所能管控的資源大致有兩種:運算資源以及 resource
    \caption{CSKloud v3 網頁界面導覽設計}
\end{figure}

網頁界面設計以單一 Kubernetes Namespace 為主軸,符合 CSKloud 對使用者提供獨立 Namespace 使用的場景。網頁的導覽透過頁面左方的導覽列達成,由此存取各個子功能,並且顯示目前所操作的 namespace。在 Sparkles 上,Namespace 可由可搜尋的下拉式選單選擇,在 CSKloud 上,則是固定為使用者對應的 Namespace 而停用選單,保留在界面上是為了往後開發出使用者群組功能後,切換至群組所對應的 Namespace 使用。
網頁界面設計以單一 Kubernetes Namespace 為主軸,符合 CSKloud 對使用者提供獨立 Namespace 的場景。網頁的導覽透過頁面左方的導覽列達成,由此存取各個子功能,並且顯示目前所操作的 Namespace。在 Sparkles 上,Namespace 可由可搜尋的下拉式選單選擇,在 CSKloud 上,則是固定為使用者對應的 Namespace 而停用選單,保留在界面上是為了往後開發出使用者以外的服務單位時,切換對應的 Namespace 使用。

\subsection{Pods 頁面與 Web Terminal 功能實做}
\label{sec:web-terminal}


@@ 186,7 185,7 @@ ResourceQuota 所能管控的資源大致有兩種:運算資源以及 resource

Pods 作為 Kubernetes 中的重要角色之一,表示叢集上運行的容器組合,我們特別為其提供了特製一覽頁面,也展示了網頁在資料呈現與互動上的顯著優於 kubectl 的 CLI 界面。網頁界面可以很容易的繪製較複雜的表格結構,也可以透過顏色幫助使用者快速的分辨異同。同時也能夠在資料上進一步的提供互動,例如點擊容器的 image 連結會導向至相關的資訊頁面,也可以針對項目顯示功能按鈕。

在容器的功能按鈕中,有瀏覽容器的運行紀錄 (log) 以及在容器中動態執行指令的功能。執行指令需要有雙向的即時資料流來傳送輸入與輸出,在這方面 Kubernetes 提供兩個解決方案:SPDY 與 WebSocket。SPDY 是 Google 早期提出的協定,用來改善 HTTP 1.x 的效能,如今在 HTTP 的場域已經被為廣泛的 HTTP/2 取代,Kubernetes 則是持續利用其雙向即時傳輸的功能。WebSocket 是特別設計在網頁場景提供雙向即時資料流的協定,並且連線由 HTTP 請求觸發進行進一步的協定轉移,對於 HTTP 既有的代理生態有一定的相容性而被廣泛採納。Kubernetes 原先以 SPDY 為主,因長期發展考量逐步轉換為 WebSocket。因為瀏覽器支援因素,我們採用 WebSocket 進行實做。
在容器的功能按鈕中,有瀏覽容器的運行紀錄 (log) 以及在容器中動態執行指令的功能。執行指令需要有雙向的即時資料流來傳送輸入與輸出,在這方面 Kubernetes 提供兩個解決方案:SPDY 與 WebSocket。SPDY 是 Google 早期提出的協定,用來改善 HTTP 1.x 的效能,如今在 HTTP 的場域已經被為廣泛的 HTTP/2 取代,Kubernetes 則是持續利用其雙向即時傳輸的功能。WebSocket\cite{fette2011websocket} 是特別設計在網頁場景提供雙向即時資料流的協定,並且連線由 HTTP 請求觸發進行進一步的協定轉移,對於 HTTP 既有的代理生態有一定的相容性而被廣泛採納。Kubernetes 原先以 SPDY 為主,因長期發展考量逐步轉換為 WebSocket。因為瀏覽器支援因素,我們採用 WebSocket 進行實做。

% 或許可以來個架構圖, 沒有很重要但文字偏抽象, 要避免牽扯到前面都沒提的 kubernetes components
有了雙向的資料流,我們還需要一個終端機模擬器負責進一步的處理,與叢集上的 pty\footnote{pty: Unix-like 系統常見的元件,主要負責處理文字行編輯、訊號快捷鍵(如 Ctrl+C)等。} 溝通。終端機模擬器繪製整個文字界面,並且處理 pty 輸出中的控制訊息,達到文字界面的顏色與游標位置等的控制。這部份我們使用既有的 Xterm.js 開源函式庫達成。


@@ 194,11 193,11 @@ Pods 作為 Kubernetes 中的重要角色之一,表示叢集上運行的容器
\subsection{Helm 頁面與 Helm 功能實做}
\label{sec:helm}

對於 Helm 功能,我們希望保持 SPA 架構將部份邏輯推往瀏覽器端在運行成本上優勢,規劃在瀏覽器內實做。起初我們將 Helm 的函式庫直接透過 WebAssembly 包裝,並提供其以指令操作為切分單位的函式接口與 TypeScript 串接,但我們發現以此方式實做效能不佳,於列出已安裝的 Helm Release 等基本操作在低資料量下已產生足以影響使用者體驗的延遲。
對於 Helm 功能,我們希望保持 SPA 架構中,將部份邏輯推往瀏覽器端在運行成本上的優勢,規劃將其在瀏覽器內實做。起初我們將 Helm 的函式庫直接透過 WebAssembly 包裝,並提供其以指令操作為切分單位的函式接口與 TypeScript 串接,但我們發現以此方式實做效能不佳,於列出已安裝的 Helm Releases 等基本操作,在低資料量下已產生足以影響使用者體驗的延遲。

Helm Release 一般的儲存格式需要經過 Base64\footnote{Base64: 一個編碼格式,可將任何形式資料轉為文字表示。} 與 gzip\footnote{gzip: 一個被廣泛利用的資料壓縮演算法。} 等操作,如果將 Helm Release 的解讀透過 WebAssembly 處理,在不經調整的情況下呼叫的會是來自 Go 語言基本函式庫編譯成 WebAssembly 的 Base64 與 gzip 實做。WebAssembly 雖然設計上已經較為接近硬體,但仍是虛擬機架構,在運算上仍然有額外負擔。而 Base64 與 gzip 作為常用的算法,瀏覽器本身有提供高效能的實做。另外將資料傳送進出 WebAssembly 環境也有一定的執行成本。
Helm Release 預設的 Secret 儲存方式需要經過 Base64\footnote{Base64: 一個編碼格式,可將任何形式資料轉為文字表示。} 與 gzip\footnote{gzip: 一個被廣泛利用的資料壓縮演算法。} 等操作,如果將 Helm Release 的解讀透過 WebAssembly 處理,在不經調整的情況下,呼叫的是來自 Go 語言基本函式庫的 Base64 與 gzip 實做。WebAssembly 雖然設計上已經較為接近硬體,但仍是虛擬機架構,在運算上仍然有額外負擔。而 Base64 與 gzip 作為常用的算法,瀏覽器本身有提供高效能的實做,卻未被利用。另外將資料傳送進出 WebAssembly 環境也有一定的執行成本。

面對這個情景,我們面臨兩個可能的解法:抽換 Go 語言基本函式庫相關演算法改為呼叫瀏覽器的實做,或者將容易影響使用者體驗的區塊以 TypeScript 重新實做。抽換的方法仍然無法避免資料傳輸的負擔。而分析 Helm 架構可發現,除了模板引擎因為基於 Go 基本函式庫的模板框架,其設計容易牽涉語言特性而不易重新實做外,剩餘的區塊皆為一般的資料處理與 Kubernetes API 的串接。其中需要模板引擎的操作只有安裝、升級等使用者會預期需要時間的情景,不包含對使用者體驗影響重大的列出 Helm Release。綜上考量,我們將 Helm 模板引擎外的部份由 TypeScript 重新實做。
關於這個情景,我們面臨兩個可能的解法:抽換相關演算法改為呼叫瀏覽器的實做,或者將容易影響使用者體驗的區塊以 TypeScript 重新實做。抽換的方法不但無法避免資料傳輸的負擔,反而會增加傳送的次數,不甚理想。而分析 Helm 架構可發現,除了模板引擎因基於 Go 基本函式庫的模板框架,設計容易牽涉語言特性而不易重新實做外,剩餘的區塊皆為一般的資料處理與 Kubernetes API 的串接。其中需要模板引擎的操作只有安裝、升級等使用者傾向預期需要時間的情景,不包含對使用者體驗影響重大的列出 Helm Releases。綜上考量,我們將 Helm 模板引擎外的部份抽離,由 TypeScript 重新實做。

\begin{figure}[htb]
    \centering


@@ 206,7 205,9 @@ Helm Release 一般的儲存格式需要經過 Base64\footnote{Base64: 一個編
    \caption{CSKloud v3 網頁界面實做 Helm 原理示意圖}
\end{figure}

除此之外,瀏覽器執行程式碼的方式主要為單執行緒,不論 JavaScript 或 WebAssembly 邏輯皆是在與畫面繪製相同的執行緒執行,唯 JavaScript 語言上具有異步 IO 的特性,使得一般負擔主要在 IO 與事件處理的網頁程式碼具備可接受的效能。但我們的場景不同,Helm 的模板引擎運算量較多,在執行時容易拖累到畫面繪製,造成卡頓。對此,我們進一步採用 WebWorker 技術。WebWorker 提供一個較侷限的執行環境,但在獨立的執行緒運行,可以避面上述影響繪製的窘境,使用上開發者需自行處理 WebWorker 與瀏覽器的一般執行緒間的溝通。我們將安裝、升級、回滾、解除安裝的耗時的操作,包含 WebAssembly 的使用,在 WebWorker 環境下實做以改善使用者體驗。
除此之外,瀏覽器執行程式碼的方式主要為單執行緒,不論 JavaScript 或 WebAssembly 邏輯皆是在與畫面繪製相同的執行緒執行,唯 JavaScript 語言上具有異步 IO 相關設計,使得一般負擔主要在 IO 與事件處理的網頁程式碼具備可接受的效能。但我們的場景不同,Helm 的模板引擎運算量較多,在執行時容易拖累到畫面繪製,造成卡頓。對此,我們進一步採用 Web Workers 技術。Web Workers 提供一個較侷限的執行環境,但在獨立的執行緒運行,可以避面上述影響繪製的窘境,使用上開發者需自行處理 Web Workers 與瀏覽器一般執行緒間的溝通。我們將安裝、升級、回滾、解除安裝的耗時的操作,包含 WebAssembly 的使用,在 Web Workers 環境下實做以改善使用者體驗。

在安裝的部份,由於我們是在瀏覽器內實做,能存取的 HTTP 服務受到對端的跨域政策影響。除非對端主動的表示允許,瀏覽器會限制網頁邏輯對其他域名服務的存取,作為增強安全性的一個手段。由於 Helm 傳統上並非在瀏覽器環境執行,Helm Repositories 大多不會特別放寬跨域政策,因此我們無法直接使用市面上大多數的 Helm Repositories。針對 CSKloud 的場景,因為可以預期部份 Charts 會受到平台加固等策略影響而無法安裝,我們採用自行架設 Helm Repositories,並只納入批量測試成功安裝的 Helm Charts,目前共提供 32 個來自 Bitnami 的 Helm Charts。

\begin{figure}[htb]
    \centering


@@ 216,18 217,18 @@ Helm Release 一般的儲存格式需要經過 Base64\footnote{Base64: 一個編

\begin{figure}[htb]
    \centering
    \begin{subfigure}{0.5\textwidth}
    \begin{subfigure}{0.49\textwidth}
        \centering
        \includegraphics[width=\textwidth]{assets/web-helm-install-repo.png}
        \caption{選擇 Helm Chart}
    \end{subfigure}%
    ~
    \begin{subfigure}{0.5\textwidth}
    \begin{subfigure}{0.49\textwidth}
        \centering
        \includegraphics[width=\textwidth]{assets/web-helm-install-values.png}
        \caption{填寫 Helm Values}
    \end{subfigure}
    \begin{subfigure}{0.5\textwidth}
    \begin{subfigure}{0.49\textwidth}
        \centering
        \includegraphics[width=\textwidth]{assets/web-helm-install-name.png}
        \caption{命名 Helm Release}


@@ 235,11 236,9 @@ Helm Release 一般的儲存格式需要經過 Base64\footnote{Base64: 一個編
    \caption{CSKloud v3 網頁界面 Helm Releases 安裝流程}
\end{figure}

界面上以 Helm Releases 表格呈現為主,可以展開觀看版本歷史,在每個項目旁有解除安裝、回滾、更新等按鈕,解除安裝會保留歷史,仍然可以將其裝回,也可以選擇刪除歷史。在畫面的右下角則是有浮動式的按鈕,可以觸發安裝新 Helm Release 的流程。
界面上以 Helm Releases 表格呈現為主,可以展開觀看版本歷史,在每個項目旁有解除安裝、回滾、更新等按鈕,解除安裝會保留歷史,仍然可以將其裝回,也可以事後刪除歷史。畫面的右下角則是有浮動式的按鈕,可以觸發安裝新 Helm Release 的流程。

在安裝的部份,由於我們是在瀏覽器內實做,能存取的 HTTP 服務受到對端的跨域政策影響。除非對端主動的表示允許,瀏覽器預設會限制網頁邏輯對其他域名服務的存取,作為增強安全性的一個手段。由於 Helm 傳統上並非在瀏覽器環境執行,Helm Repositories 大多不會特別放寬跨域政策,因此我們無法直接使用市面上大多數的 Helm Repositories。針對 CSKloud 的場景,因為可以預期部份 Charts 會因為平台加固等策略影響無法安裝,我們採用自行架設 Helm Repositories,並且只納入批量測試過可以安裝的 Helm Charts,目前共提供 32 個來自 Bitnami 的 Helm Charts。

對於安裝的流程,在按下浮動式按鈕後,會跳出對話框進行三個步驟。第一是選擇要安裝的 Helm Chart,由一個可搜尋的列表選取。第二是填入 Helm Values,如同 Helm CLI 以 YAML\footnote{YAML: 一個資料標記語言,在 Kubernetes 生態系頗為常用,尤其是用來表達 Kubernetes resources。} 的形式填入,這裡界面上提供三個頁簽,一是填 Helm Values 的編輯器,二是顯示來自 Helm Chart 的 README 檔案,通常會在此提供常用選項的說明,三是 Helm Chart 內的 Helm Values 預設值檔案,慣例在此以註解的形式完整地對選項欄位說明。以 CSKloud 的場景,在編輯器上,會自動帶入針對 CSKloud 的第二層預設值,這個預設值來自測試安裝時所帶入的參數,調整如資源配額用量等選項,以確保在平台的限制下得以安裝,使用者也可以進一步進行修改。最後的步驟則是為此 Helm Release 命名,界面會自動預設一個隨機的名字。
對於安裝的流程,按下浮動式按鈕後,會跳出對話框進行三個步驟:第一步是選擇要安裝的 Helm Chart,由一個可搜尋的列表選取。第二步是填入 Helm Values,如同 Helm CLI 以 YAML\footnote{YAML: 一個資料標記語言,在 Kubernetes 生態系頗為常用,尤其是用來表達 Kubernetes resources。} 的形式填入,界面上提供三個頁簽,一是填寫 Helm Values 的編輯器,二是來自 Helm Chart 的 README 檔案,通常會在此提供常用選項的說明,三是 Helm Chart 內的 Helm Values 預設值檔案,慣例在此以註解的形式完整地對選項欄位說明。以 CSKloud 的場景,編輯器會自動帶入針對 CSKloud 的第二層預設值,這個預設值來自測試安裝時所帶入的參數,調整如資源配額用量等選項,以確保在平台的限制下得以安裝,使用者也可以進一步進行修改。最後的步驟則是為此 Helm Release 命名,界面會自動預設一個隨機的名字。

調整 Helm Values 的編輯器採用 CodeMirror 開源編輯器專案,除了 YAML 的基本語法高亮以外,我們採用 codemirror-json-schema 擴充元件提供進一步的資料驗證、欄位說明與名稱自動補全。codemirror-json-schema 收取 JSON Schema 作為欄位定義,JSON Schema 是一個描述 JSON\footnote{JSON: 資料標記語言,與 YAML 的模型類似,語法較為容易以程式解析。} 資料的定義框架,但由於大多數 YAML 應用場景描述的資料也都可以由 JSON 的形式表達,也常用來描述 YAML 資料。部份 Helm Chart 會提供對其 Helm Values 的 JSON Schema 定義檔。



@@ 247,43 246,43 @@ Helm Release 一般的儲存格式需要經過 Base64\footnote{Base64: 一個編

\begin{figure}[htb]
    \centering
    \includegraphics[width=0.75\textwidth]{assets/web-quotas.png}
    \includegraphics[width=0.7\textwidth]{assets/web-quotas.png}
    \caption{CSKloud v3 網頁界面 Quotas 頁面}
\end{figure}

此頁面針對平台透過 ResourceQuota 對 Namespace 下實行的資源配額進行視覺化,使用圓餅圖顯示每個取用單位(如 Pod 下的一個容器)在相關資源(如記憶體)允許配額下所佔用的比例。使用者可以透過將游標移動到圓餅區塊上,查看取用單位的名稱以及佔用量,方便使用者了解何處取用最多。在總取用比例高到一定程度時,會改以黃色或紅色顯示提醒使用者注意。

在實做上,由於 ResourceQuota 只帶有配額與佔用總量資訊,須以程式邏輯另外獲取相關取用單位資訊才能自行判斷細項。另外,圓餅圖的繪製透過 Chart.js 開源函式庫實做。
在實做上,由於 ResourceQuota 只帶有配額與佔用總量資訊,須以程式邏輯額外列舉相關 resources,解析取用單位資訊以判斷細項。另外,圓餅圖的繪製透過 Chart.js 開源函式庫實做。

\subsection{Tokens 管理}
\label{sec:tokens-mgmt}

CSKloud 開放使用者直接存取 API,並且提供 kubectl 連線設定檔。因為叢集本身使用 OIDC 驗證方式,客戶端需要有相關 OIDC 流程邏輯,在網頁界面我們可以直接實做,而對於 kubectl 的場景,我們則是使用 kubelogin 擴充程式,在 kubectl 發出 Kubernetes API 請求時,kubelogin 會檢查是否持有有效的 token,並且在有必要時執行 OIDC 流程。OIDC 需要透過瀏覽器進行網頁登入,導致這個驗證方式雖然在使用者的互動使用時可行且較為安全,在自動化場景卻相當不方便。
CSKloud 開放使用者直接存取 Kubernetes API,並且提供 kubectl 連線設定檔。因為叢集本身使用 OIDC 驗證方式,客戶端需要有相關 OIDC 流程邏輯,在網頁界面我們可以直接實做,而對於 kubectl 的場景,我們則是使用 kubelogin 擴充程式,在 kubectl 發出 Kubernetes API 請求時,kubelogin 會檢查當下是否持有有效的 token,在有必要時執行 OIDC 流程。OIDC 需要透過瀏覽器進行網頁登入,導致這個驗證方式雖然在使用者的互動使用時可行且較為安全,在自動化場景卻相當不方便。

對此,我們採用 ServiceAccount tokens 彌補對自動化場景的不足。Tokens 管理頁面幫助使用者設定一個具有當下 Namespace 權限的 ServiceAccount,再經由此 ServiceAccount,簽發綁定 Secret 的 token。使用者在簽發 token 時需指定效期,並且可以紀錄相關的用途筆記,存放在對應的 Secret 內。這些 Secrets 使得網頁界面可以紀錄簽發的 tokens,同時作為撤銷 tokens 的手段。
對此,我們採用 ServiceAccount tokens 彌補對自動化場景的不足。Tokens 管理頁面幫助使用者設定一個具有當下 Namespace 權限的 ServiceAccount,再經由此 ServiceAccount 簽發指定效期、綁定 Secret 的 token。使用者可以紀錄相關的用途筆記,存放在對應的 Secret 內。這些 Secrets 使得網頁界面可以紀錄追蹤簽發的 tokens,同時作為撤銷 tokens 的手段。

\subsection{Resource Explorer}

\begin{figure}[htb]
    \centering
    \begin{subfigure}{0.5\textwidth}
    \begin{subfigure}{0.49\textwidth}
        \centering
        \includegraphics[width=\textwidth]{assets/web-resources-list.png}
        \caption{Resources 列表}
    \end{subfigure}%
    ~
    \begin{subfigure}{0.5\textwidth}
    \begin{subfigure}{0.49\textwidth}
        \centering
        \includegraphics[width=\textwidth]{assets/web-resources-single.png}
        \caption{單一 resource 檢視}
    \end{subfigure}
    \begin{subfigure}{0.5\textwidth}
    \begin{subfigure}{0.49\textwidth}
        \centering
        \includegraphics[width=\textwidth]{assets/web-resources-single-menu.png}
        \caption{單一 resource 檢視功能表}
    \end{subfigure}%
    ~
    \begin{subfigure}{0.5\textwidth}
    \begin{subfigure}{0.49\textwidth}
        \centering
        \includegraphics[width=\textwidth]{assets/web-resources-single-new.png}
        \caption{創立 resource 的模板預填}


@@ 291,24 290,22 @@ CSKloud 開放使用者直接存取 API,並且提供 kubectl 連線設定檔
    \caption{CSKloud v3 網頁界面 Resource Explorer 頁面}
\end{figure}

Resource Explorer 提供對 Kubernetes resource 的基本列出、創立、編輯、刪除的功能,作為使用者與 Kubernetes 互動中最基礎的功能。這個頁面採用 Kubernetes API discovery 機制,在運行時會從 Kubernetes API 查詢所有支援的 resource 種類,未來如果隨著 Kubernetes 演進而有所增減,這個頁面不須經過修改可以直接沿用。
Resource Explorer 提供對 Kubernetes resource 列舉、創立、編輯、刪除的操作界面,作為使用者與 Kubernetes 互動中最基礎的功能。這個頁面採用 Kubernetes API discovery 機制,在運行時會查詢叢集所有支援的 resource 種類,未來如果隨著 Kubernetes 演進而對種類有所增減,這個頁面不須經過修改可以直接沿用。

在列表的部份,這個頁面採用 Kubernetes API 本身的製表功能,可以對 resources 產出基本的概要,kubectl 的表格呈現亦是採用此機制。使用者可以將游標移動到表格欄位名稱上方,透過提示框了解欄位意義,也可以點擊針對欄位排序。右下方的浮動按鈕可以撰寫新的 resource,點擊表格列則是查看對應的 resource 的完整內容,以 YAML 的形式呈現。在單一 resource 完整呈現中右下方的浮動按鈕功能列表,也有編輯與刪除等功能。
這個頁面採用 Kubernetes API 本身的製表功能,可以對 resources 產出基本的概要,kubectl 的表格呈現亦是基於此機制。使用者可以將游標移動到表格欄位名稱上方,透過提示框了解欄位意義,也可以點擊針對欄位排序。右下方的浮動按鈕可以撰寫新的 resource,點擊表格列則是查看對應的 resource 的完整內容,以 YAML 的形式呈現。在單一 resource 完整呈現中右下方的浮動按鈕功能列表,也有編輯與刪除等功能。

在 YAML 檢視與編輯的方面,則與 \ref{sec:helm} Helm 頁面功能相似,基於 CodeMirror,並且一樣有基於 JSON Schema 的資料驗證、欄位提示與名稱補全。這裡的欄位定義則是來自於 Kubernetes API 的 OpenAPI 定義檔。Kubernetes 具有 OpenAPI Discovery 功能,可以從 API 獲取定義檔,如同 API Discovery,這樣的機制使得網頁不須修改,即可適用於未來的 Kubernetes 版本。
在 YAML 檢視與編輯的方面,則與 \ref{sec:helm} Helm 頁面功能相似,採用 CodeMirror,並且一樣有基於 JSON Schema 的資料驗證、欄位提示與名稱補全。這裡的欄位定義則是來自於 Kubernetes API 的 OpenAPI 定義檔,由相關 API endpoint 的定義萃取轉換而成。Kubernetes 具有 OpenAPI Discovery 功能,可以從 API 獲取定義檔,如同 API Discovery,這樣的機制使得網頁不須修改,即可適用於未來的 Kubernetes 版本。

在創立新 resource 時,網頁會針對目前選擇的 resource 種類,預先填好必填或者常用的欄位,也會取好一個暫定名稱。預填欄位較為難以進行自動判斷,因此採用人工逐一事先設計的方式。如果未先設計,仍會自動預填 Kubernetes resource 共通的 \verb|apiVersion|、\verb|kind|、\verb|metadata| 欄位。
創立新 resource 時,網頁會針對目前選擇的 resource 種類,預先填好必填或者常用的欄位,也會取好一個暫定名稱。預填欄位較為難以進行動態判斷,因此採用人工逐一事先設計的方式。如果選定的種類未先設計模板,仍會自動預填 Kubernetes resource 共通的 \verb|apiVersion|、\verb|kind|、\verb|metadata| 欄位。

這個頁面功能可以涵蓋 Kubernetes 上的大多數操作,但仍然有限制,主要為並不支援 subresources。Subresources 為單一一個 resource 實例下的額外 API endpoints,使 Kubernetes 得以跳脫基本 resource 讀寫操作的框架,並且不具有固定的形式,其中較為代表的有:Pod 的 log subresource,用以查看 Pod 下容器的運行紀錄;Pod 的 exec subresources,用以在 Pod 下容器執行指令;ServiceAccount 的 tokens subresource,用以簽發 tokens。由於 subresources 的形式、用途皆不固定,我們無法直接提供通用的操作界面,而是經由如 \ref{sec:web-terminal} Pod 頁面等,針對不同場景另外實做。
這個頁面功能可以涵蓋 Kubernetes 上的大多數操作,但仍然有限制,主要為不支援 subresources。Subresources 為單一 resource 實例下的額外 API endpoints,使 Kubernetes 得以跳脫 resource 讀寫操作的框架,並且不具有固定的形式,其中較為代表的有:Pod 的 log subresource,用以查看 Pod 下容器的運行紀錄;Pod 的 exec subresources,用以在 Pod 下容器執行指令;ServiceAccount 的 tokens subresource,用以簽發 tokens。由於 subresources 的形式、用途皆不固定,我們無法直接提供通用的操作界面,而是經由如 \ref{sec:web-terminal} Pod 頁面等,針對不同場景另外實做。

\subsection{kubectl shell 功能}

隨著 Kubernetes 的更迭,即使我們盡力擴增網頁界面對應的功能,難免還是會有跟不上的時候。即使是現在,雖然我們已經實做了通用型的 Resource Explorer,仍然有少數 Kubernetes 功能無法直接透過網頁界面使用。對此,我們提供一個逃生口 (escape hatch):在網頁界面直接使用 kubectl 指令。雖然使用者可以自行安裝設定 kubectl,在網頁界面直接提供這個功能還是有免安裝、隨時帶著走的優勢。
隨著 Kubernetes 的更迭,即使我們盡力擴增網頁界面對應的功能,難免還是會有跟不上的時候。就算是現在,雖然我們已經實做了通用型的 Resource Explorer,仍然有少數 Kubernetes 功能無法直接透過網頁界面使用。對此,我們提供一個逃生口 (escape hatch):在網頁界面直接使用 kubectl 指令。雖然使用者可以自行安裝設定 kubectl,在網頁界面直接提供這個功能還是有免安裝、隨時帶著走的優勢。

實做這個功能有兩個可行方向:使用 WebAssembly 將 kubectl 移植到瀏覽器,或者在叢集內執行 kubectl。前者實際上除了移植 kubectl 指令外,還需提供一個 shell 環境以便使用,在需將環境內各種工具一一移植的前提下,容易產生缺漏使用者想要的項目的窘境,開發成本相當高,於是我們選擇了後者。

kubectl shell 頁面類似於 \ref{sec:tokens-mgmt} Tokens 管理頁面,都會先產生一個具有當下 Namespace 權限的 ServiceAccount,但取用的方式不同。接著會採用 Kubernetes 設計上將 ServiceAccount 對 Pod 做的特殊整合,創立一個使用該 ServiceAccount 的 Pod 時,Kubernetes 會自動簽發綁定此 Pod 的 token,並且將 token 與相關連線資訊放置至 Pod 內容器的檔案系統中。容器內具備的 kubectl 指令會自動採用檔案系統內的這些資訊進行連線。再來只須重複利用 \ref{sec:web-terminal} 所述的虛擬終端機連線機制,便可以讓使用者操作容器內的 kubectl 指令。
kubectl shell 頁面類似於 \ref{sec:tokens-mgmt} Tokens 管理頁面,都會先產生一個具有當下 Namespace 權限的 ServiceAccount,但取用的方式不同。接著會採用 Kubernetes 設計上將 ServiceAccount 對 Pod 做的特殊整合,創立一個使用該 ServiceAccount 的 Pod 時,叢集會自動簽發綁定此 Pod 的 token,並將 token 與相關連線資訊放置於 Pod 內容器的檔案系統中。容器內具備的 kubectl 指令會自動採用這些資訊進行連線。再來只須重複利用 \ref{sec:web-terminal} 所述的虛擬終端機連線機制,便可讓使用者操作容器內的 kubectl 指令。

這個方式雖然因為在叢集內執行容器,會佔用到使用者的資源配額,但實際此場景預期的資源使用極小,對於使用者權益的影響不大。運作機制主要又是基於其他既有的功能做組合,實際開發成本極低,卻十分有效。圖 \ref{fig:kubectl-get-pods} 即是來自於此功能。

\subsection{Node Metrics 視覺化}

M assets/kubectl-pods.png => assets/kubectl-pods.png +0 -0
M assets/provisioner-user-spec.png => assets/provisioner-user-spec.png +0 -0
M assets/web-helm-install-name.png => assets/web-helm-install-name.png +0 -0
M assets/web-helm-install-repo.png => assets/web-helm-install-repo.png +0 -0
M assets/web-helm-install-values.png => assets/web-helm-install-values.png +0 -0
M assets/web-helm-list.png => assets/web-helm-list.png +0 -0
M assets/web-pods.png => assets/web-pods.png +0 -0
M ref.bib => ref.bib +36 -5
@@ 3,7 3,6 @@
    author	= {周詳},
    year	= {2021},
    month	= {January},
    % TODO available where?
    school	= {國立交通大學},
    type	= {Master's thesis},
}


@@ 13,13 12,15 @@
    author	= {李宗緯},
    year	= {2022},
    month	= {August},
    % TODO available where?
    school	= {國立陽明交通大學},
    type	= {Master's thesis},
}

% XXX quotes missing on online/electornic in IEEEtran
% TODO dot position, urldate

@online{kubernetes,
    title 	= {{Kubernetes}},
    title 	= {``{Kubernetes}''},
    author	= {{The Kubernetes Authors}},
    year	= {2024},
    url		= {https://kubernetes.io/},


@@ 27,7 28,7 @@
}

@online{helm,
    title	= {{Helm}},
    title	= {``{Helm}''},
    author	= {{Helm Authors}},
    year	= {2024},
    url		= {https://helm.sh/},


@@ 35,9 36,39 @@
}

@inproceedings{haas2017bringing,
    title	= {Bringing the web up to speed with WebAssembly},
    title	= {Bringing the web up to speed with {WebAssembly}},
    author	= {Haas, Andreas and Rossberg, Andreas and Schuff, Derek L and Titzer, Ben L and Holman, Michael and Gohman, Dan and Wagner, Luke and Zakai, Alon and Bastien, JF},
    booktitle	= {Proceedings of the 38th ACM SIGPLAN Conference on Programming Language Design and Implementation},
    pages	= {185--200},
    year	= {2017},
}

@online{cel,
    title	= {``{CEL}''},
    author	= {{Google LLC}},
    year	= {2024},
    url		= {https://cel.dev/},
    urldate	= {2024-09-24},
}

@online{kubebuilder,
    title	= {``{Introduction} - The {Kubebuilder} Book''},
    author	= {{The Kubernetes Authors}},
    year	= {2024},
    url		= {https://book.kubebuilder.io/introduction},
    urldate	= {2024-09-23},
}

@online{vue,
    title	= {``{Vue.js} - The Progressive {JavaScript} Framework''},
    author	= {Evan You},
    year	= {2024},
    url		= {https://vuejs.org/},
    urldate	= {2024-09-23},
}

@techreport{fette2011websocket,
    title	= {The websocket protocol},
    author	= {Fette, Ian and Melnikov, Alexey},
    year	= {2011},
}