Webchat Kubernetes 完整部署 Demo

這篇文章記錄一次完整的 Webchat Kubernetes 部署體驗:從本機 Minikube 建立基礎服務、部署 Spring Boot API 與 WebSocket/STOMP 服務,到最後開啟前端頁面,實際用兩個使用者測試公開聊天室的即時訊息。

Webchat 是一個即時公開聊天室範例專案,包含純 HTML/CSS/JavaScript 前端、REST API 服務、WebSocket/STOMP 服務,以及 MySQL、Redis、RabbitMQ 這三個後端基礎設施。使用者登入後會取得 JWT,前端透過 REST API 送出訊息,再由 RabbitMQ 將事件分送到 WebSocket 節點,最後推播給已連線的聊天室使用者。

本文會以 webchatk8s/ 內的 Kubernetes manifest 為主,將整套服務部署到 Minikube 上,並用瀏覽器確認聊天室功能是否正常。


專案架構

這次沒有附上完整原始碼,所以這裡只簡單說明系統組成與部署方向。Webchat 大致可以分成三個應用端:前端頁面、REST API 服務,以及 WebSocket/STOMP 服務;後端則搭配 MySQL、Redis 與 RabbitMQ,分別處理資料保存、即時狀態與訊息事件轉送。

整體流程可以簡單理解為:使用者登入後由前端取得 token,接著連線到 WebSocket 服務;當使用者送出聊天訊息時,API 會處理訊息並透過 RabbitMQ 發布事件,再由 Socket 服務推播給聊天室中的其他使用者。本文後續會著重在 Kubernetes 部署與實際驗證過程,不會深入介紹各服務的程式碼實作。


部署前準備

這次 Demo 使用的環境如下:

項目 說明
Kubernetes 環境 Minikube
操作工具 kubectlk9s
後端服務 webchatapiwebchatsocket
基礎服務 MySQL 8.0、Redis 7、RabbitMQ 4
對外測試方式 kubectl port-forward

在開始前,先確認 kubectl 目前連線到 Minikube:

1
kubectl config current-context

正常情況下會看到:

1
minikube

接著確認節點狀態:

1
kubectl get nodes

如果 Minikube 還沒啟動,可以先執行:

1
minikube start --driver=docker

步驟 1:部署基礎設施

Webchat 需要 MySQL、Redis 與 RabbitMQ 才能完整運作。這些資源集中定義在 webchatk8s/infra-kit.yml,內容包含:

  • webchat namespace
  • webchat-infra-secret Secret
  • mysql-init-sql ConfigMap
  • MySQL ClusterIP Service 與 StatefulSet
  • Redis ClusterIP Service 與 StatefulSet
  • RabbitMQ ClusterIP Service 與 StatefulSet

進入 Kubernetes manifest 目錄後,先套用基礎設施設定:

1
2
cd webchatk8s
kubectl apply -f infra-kit.yml

套用完成後,可以觀察 webchat namespace 內的 Pod 是否陸續啟動:

1
kubectl get pods -n webchat -w

等待 MySQL、Redis、RabbitMQ 都變成 Running,並且 READY 顯示為 1/1 後,再進入下一步。


步驟 2:部署 Webchat 應用程式

基礎服務啟動後,接著部署 Webchat 的 API 與 Socket 服務。應用程式相關設定集中在 webchatk8s/webchat-deploy.yml,主要包含:

  • webchat-app-config ConfigMap:保存 Spring profile、MySQL、Redis、RabbitMQ 等非敏感設定
  • webchat-runtime-secret Secret:保存 MySQL 密碼、RabbitMQ 密碼與 JWT secret
  • gitlab-registry-secret Secret:用於拉取私有 GitLab Container Registry 映像
  • webchatapi-deployment Deployment
  • webchatapi-clusterip Service
  • webchatsocket-deployment Deployment
  • webchatsocket-loadbalancer Service

如果映像放在自己的私有 Registry,請先確認 gitlab-registry-secret 已改成自己的 Registry 認證。正式環境建議用 kubectl create secret docker-registry 或外部 Secret 管理工具產生,不要把可用憑證直接提交到版本庫。

套用 Webchat 應用程式設定:

1
kubectl apply -f webchat-deploy.yml

確認所有資源是否正常建立:

1
kubectl get all -n webchat

畫面中可以看到 MySQL、RabbitMQ、Redis 三個 StatefulSet,以及 webchatapi-deploymentwebchatsocket-deployment 兩個 Deployment 都已經進入 Running。右側則可以看到 webchatapi-clusteripwebchatsocket-loadbalancer 服務已建立。

這裡也可以搭配 k9s 觀察 Pod 與容器 log。從截圖可以看到 API 服務正在處理登入查詢與 RabbitMQ 連線,Socket 服務也持續收到 health check 訊息,代表後端服務、訊息 broker 與 WebSocket 節點之間已經能正常互動。


步驟 3:確認 Service 與對外連線方式

在這個 Demo 中,API 使用 ClusterIP,Socket 使用 LoadBalancer

Service 類型 用途
webchatapi-clusterip ClusterIP 提供叢集內部 API 存取入口。
webchatsocket-loadbalancer LoadBalancer 提供 WebSocket 對外入口。

由於是在本機 Minikube Demo,最直接的測試方式是使用 kubectl port-forward,將 Kubernetes Service 轉到本機連接埠:

1
kubectl port-forward --address 0.0.0.0 svc/webchatapi-clusterip -n webchat 9091:9091

另開一個終端機,轉發 WebSocket 服務:

1
kubectl port-forward --address 0.0.0.0 svc/webchatsocket-loadbalancer -n webchat 9092:9092

如果想更完整體驗 MetalLB 的 LoadBalancer 對外分流方式,也可以不直接 port-forward 到 Socket Service,而是讓 socat 監聽主機的 9092,再轉送到 MetalLB 分配給 webchatsocket-loadbalancer 的 external IP。以前面的截圖為例,Socket Service 取得的 external IP 是 192.168.49.100,因此可以執行:

1
sudo socat TCP-LISTEN:9092,fork,reuseaddr,bind=0.0.0.0 TCP:192.168.49.100:9092

這樣前端連到主機的 9092 時,流量會先進入 socat,再轉送到 MetalLB 提供的 LoadBalancer IP,最後由 Kubernetes Service 分流到後方的 webchatsocket Pod。這種方式比單純 kubectl port-forward 更接近實際測試 LoadBalancer 對外入口的情境。

完成後,前端就可以透過以下位址連線:

  • REST API base URL:http://localhost:9091
  • WebSocket URL:ws://localhost:9092/ws

步驟 4:開啟前端頁面

Webchat 前端是純 HTML/CSS/JavaScript,可以直接開啟 webchatclient/index.html。這次 Demo 使用 VS Code Live Preview 開啟,因此網址會類似:

1
http://127.0.0.1:3001/webchatclient/index.html

一開始尚未登入時,Socket 狀態會顯示 Idle。左側可以切換 Login 與 Register,畫面中央的 Public room 也會提示需要登入並連線後才能開始聊天。

這張截圖同時開了兩個瀏覽器視窗,分別準備登入或註冊不同使用者。這樣做的好處是可以直接驗證公開聊天室是否真的能把訊息推播到不同 session。


步驟 5:登入、連線並測試聊天室

登入成功後,前端會保存 session token,並顯示 REST API base URL 與 WebSocket URL。按下 Connect 後,前端會連到 webchatsocket,Socket 狀態會從 Idle 變成 Connected

成功連線後,畫面上方可以看到幾個診斷資訊:

欄位 說明
Online 目前線上 session 數量。
Health WebSocket health check 回應時間。
Node 目前連線到的 Socket Pod 節點識別。
Session 目前瀏覽器連線的 session id。

左側 Members 區塊會列出目前在線上的使用者與 session 數量;Public room 則會顯示使用者進出聊天室的事件,以及實際傳送的聊天訊息。

從畫面中可以看到 pcion123dust789 兩個使用者已經連線,聊天室事件也記錄了 join、left 等狀態變化。接著兩個視窗互相送出 hihellohow are youfine 等訊息,左右兩邊都能即時看到對方的訊息,表示 API、RabbitMQ 與 Socket 推播流程已串接成功。


這次部署實際驗證了什麼?

這個 Demo 不只是把 Pod 跑起來而已,而是完整走過一次聊天室系統在 Kubernetes 裡的端到端流程:

  1. MySQL 成功初始化資料庫與帳號資料表。
  2. Redis 可供服務保存即時狀態。
  3. RabbitMQ 可在 API 與 Socket 服務之間傳遞聊天事件。
  4. webchatapi 可以處理註冊、登入與訊息送出。
  5. webchatsocket 可以驗證連線、維護線上狀態並推播訊息。
  6. 前端可以透過 port-forward 連到 Kubernetes 內的服務。
  7. 兩個使用者可以在公開聊天室中即時互相收到訊息。

對於練習 Kubernetes 部署來說,這個範例涵蓋了幾個很常見的主題:Namespace、Secret、ConfigMap、StatefulSet、Deployment、ClusterIP、LoadBalancer、readiness probe、liveness probe,以及本機開發常用的 port-forward。


常用檢查指令

部署過程中,可以用以下指令快速檢查狀態:

1
kubectl get all -n webchat

查看 Pod 詳細資訊:

1
kubectl describe pod -n webchat <pod-name>

查看 API log:

1
kubectl logs -n webchat deployment/webchatapi-deployment -f

查看 Socket log:

1
kubectl logs -n webchat deployment/webchatsocket-deployment -f

重新套用基礎設施:

1
kubectl apply -f infra-kit.yml

重新套用應用程式:

1
kubectl apply -f webchat-deploy.yml

如果要清除整個 Demo 環境,可以刪除 webchat namespace:

1
kubectl delete namespace webchat

小結

這次 Webchat Demo 透過 Kubernetes 將前端、REST API、WebSocket、MySQL、Redis 與 RabbitMQ 串成一個完整的即時聊天室環境。從部署結果來看,所有 Pod 都正常啟動,Service 也能透過 port-forward 對外提供測試入口;最後再透過兩個瀏覽器 session 實際送出訊息,確認聊天事件能從 API 進入 RabbitMQ,再由 Socket 服務推播回前端。

這類範例很適合用來練習從單機開發環境走向 Kubernetes 部署,因為它同時包含狀態服務、無狀態服務、內部服務發現、外部連線入口與即時訊息推播。只要把映像版本、Secret 與 Service 暴露方式整理好,後續也可以延伸成更接近正式環境的部署流程。