在專案開發中,Docker Compose 是一種常見的工具,能夠幫助開發者在本地輕鬆啟動多容器應用。然而,當應用擴充套件到生產環境,單節點的 Docker Compose 可能無法滿足高可用性、容錯和擴充套件需求。這時候,我們可以考慮將 Docker Compose 部署遷移到 Kubernetes 這樣的叢集環境中,實現應用的叢集化管理。
本文將以我之前開發的一個 Node.js 應用(一個線上流程圖系統)為例,使用 PostgreSQL
、Adminer
管理資料庫,介紹如何將單節點的 Docker Compose 部署轉化為 Kubernetes 叢集部署。
Docker Compose 配置
這是一個典型的 docker-compose.yml
檔案,它定義了一個使用 PostgreSQL 作為資料庫,Adminer 作為資料庫管理介面,Node.js 應用作為服務的環境。
version: "3.8" services: db: image: postgres volumes: - pg_data:/var/lib/postgresql/data restart: always ports: - 5432:5432 environment: POSTGRES_DB: pro POSTGRES_USER: admin POSTGRES_PASSWORD: example adminer: image: adminer restart: always ports: - 8080:8080 app: image: maqi1520/cloneprocesson ports: - "3000:3000" environment: DATABASE_URL: "postgresql://admin:example@db:5432/pro?schema=public" JWT_SECRET: "xxxx" GITHUB_CLIENT_ID: "xxxx" GITHUB_CLIENT_SECRET: "xxxx" DOMAIN: "http://localhost:3000" EMAIL_USER: "xxxx@163.com" EMAIL_USER_NAME: "xxxxx" EMAIL_HOST: "smtp.163.com" EMAIL_PASS: "xxxx" depends_on: - db volumes: pg_data:
此配置可以在本地使用 docker-compose up -d
命令啟動,但如果要將其部署在生產環境中並確保高可用性,則需要遷移到 Kubernetes。接下來,我們將介紹如何完成這一轉化。
Kubernetes 叢集化部署概述
在 Kubernetes 中,使用多個資源來管理應用的不同元件。與 Docker Compose 的單一檔案不同,Kubernetes 使用 Deployment
、StatefulSet
、Service
、ConfigMap
、Secret
等多個配置檔案來描述和管理容器化應用。
爲了將上述 Docker Compose 配置轉移到 Kubernetes,我們需要以下幾種關鍵元件:
PostgreSQL StatefulSet:用於管理資料庫容器,保證資料永續性。
Deployment:用於部署 Node.js 應用和 Adminer,確保應用的可擴充套件性。
Service:為應用提供叢集內外的訪問介面。
Secret:用於儲存敏感資訊(如資料庫憑證、API 金鑰等)。
Step 1: 將 PostgreSQL 部署為 StatefulSet
在 Kubernetes 中,StatefulSet
用於管理有狀態應用(例如資料庫),它確保資料庫例項的永續性和穩定性。我們首先需要建立一個用於儲存資料庫憑證的 Secret
,然後再建立 StatefulSet
。
PostgreSQL Secret
apiVersion: v1 kind: Secret metadata: name: postgres-secret type: Opaque data: DATABASE_URL: cG9zdGdyZXNxbDovL2FkbWluOmV4YW1wbGVAcG9zdGdyZXM6NTQzMi9wcm8/c2NoZW1hPXB1YmxpYw== # base64編碼的 "postgresql://admin:example@postgres:5432/pro?schema=public" POSTGRES_DB: "cHJv" # "pro" encoded in base64 POSTGRES_USER: "YWRtaW4=" # "admin" encoded in base64 POSTGRES_PASSWORD: "ZXhhbXBsZQ==" # "example" encoded in base64
在 Kubernetes 中,Secret 中的資料可以使用 base64 編碼是一種常見的做法,但不是必須的。
在 Linux 和 macOS 系統中,可以使用 base64 命令。例如,要對字串 “postgresql://admin:example@postgres:5432/pro?schema=public” 進行編碼,可以在終端中執行以下命令:
echo -n "postgresql://admin:example@postgres:5432/pro?schema=public" | base64
在 Windows 系統中,可以使用 PowerShell 中的[Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("postgresql://admin:example@postgres:5432/pro?schema=public"))
命令。
Kubernetes 的 Secret 物件可以儲存任意資料,但爲了確保資料的安全性和可讀性,通常會進行某種形式的編碼或加密。
PostgreSQL StatefulSet
apiVersion: apps/v1 kind: StatefulSet metadata: name: postgres spec: serviceName: "postgres" replicas: 1 selector: matchLabels: app: postgres template: metadata: labels: app: postgres spec: containers: - name: postgres image: postgres:latest ports: - containerPort: 5432 env: - name: POSTGRES_DB valueFrom: secretKeyRef: name: postgres-secret key: POSTGRES_DB - name: POSTGRES_USER valueFrom: secretKeyRef: name: postgres-secret key: POSTGRES_USER - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: postgres-secret key: POSTGRES_PASSWORD volumeMounts: - name: pg-data mountPath: /var/lib/postgresql/data volumeClaimTemplates: - metadata: name: pg-data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 1Gi
透過 StatefulSet
,我們確保了資料庫資料的持久化儲存和穩定的網路標識。每個副本都可以訪問持久儲存卷。
PostgreSQL Service
apiVersion: v1 kind: Service metadata: name: postgres spec: ports: - port: 5432 selector: app: postgres
Service
用於暴露 PostgreSQL 服務,使得應用可以透過叢集內部的 DNS 名稱 postgres
訪問資料庫。
Step 2: Node 應用程式的 Deployment 和 Secret
接下來,我們為 Node.js 應用建立一個 Deployment
,並透過 Secret
管理敏感資料,例如資料庫 URL、JWT 金鑰和 GitHub API 憑證。
應用程式的 Secret
apiVersion: v1 kind: Secret metadata: name: app-secret type: Opaque data: jwt-secret: "YOUR_ENCODED_JWT_SECRET" github-client-id: "YOUR_ENCODED_GITHUB_CLIENT_ID" github-client-secret: "YOUR_ENCODED_GITHUB_CLIENT_SECRET"
應用程式 Deployment
apiVersion: apps/v1 kind: Deployment metadata: name: app spec: replicas: 1 selector: matchLabels: app: app template: metadata: labels: app: app spec: containers: - name: app image: maqi1520/cloneprocesson:latest ports: - containerPort: 3000 env: - name: DATABASE_URL valueFrom: secretKeyRef: name: app-secret key: DATABASE_URL - name: JWT_SECRET valueFrom: secretKeyRef: name: app-secret key: jwt-secret - name: GITHUB_CLIENT_ID valueFrom: secretKeyRef: name: app-secret key: github-client-id - name: GITHUB_CLIENT_SECRET valueFrom: secretKeyRef: name: app-secret key: github-client-secret
應用程式 Service
apiVersion: v1 kind: Service metadata: name: app spec: type: LoadBalancer ports: - port: 3000 selector: app: app
Step 3: Adminer Deployment 和 Service
最後,Adminer 作為資料庫管理介面,也需要用 Deployment
和 Service
部署。
Adminer Deployment
apiVersion: apps/v1 kind: Deployment metadata: name: adminer spec: replicas: 1 selector: matchLabels: app: adminer template: metadata: labels: app: adminer spec: containers: - name: adminer image: adminer:latest ports: - containerPort: 8080
Adminer Service
apiVersion: v1 kind: Service metadata: name: adminer spec: type: LoadBalancer ports: - port: 8080 selector: app: adminer
Step 4: 部署步驟
將
Secret
和Deployment
等資源應用到 Kubernetes 叢集:kubectl apply -f postgres-secret.yml kubectl apply -f postgres-statefulset.yml kubectl apply -f postgres-service.yml kubectl apply -f app-secret.yml kubectl apply -f app-deployment.yml kubectl apply -f app-service.yml kubectl apply -f adminer-deployment.yml kubectl apply -f adminer-service.yml
這將會啟動 PostgreSQL 資料庫例項,併爲資料庫提供持久儲存,應用程式將透過
Secret
獲取敏感資訊,並連線到 PostgreSQL 資料庫。Service
將會為外部客戶端提供訪問 Node.js 應用的入口。 Adminer 將作為資料庫管理介面透過叢集的LoadBalancer
公開出來,允許你直接管理 PostgreSQL 資料。
Step 5: 驗證和監控
完成部署後,你可以透過以下方式驗證叢集的執行情況:
檢視所有資源是否成功建立:
kubectl get pods kubectl get services kubectl get statefulsets
驗證 PostgreSQL 連線:
可以透過訪問 Adminer 服務,驗證 PostgreSQL 資料庫是否正常工作。你可以使用瀏覽器訪問
http://<LoadBalancer_IP>:8080
,然後使用 Secret 中的資料庫憑證登入。驗證應用程式連線:
訪問 Node.js 應用的
Service
地址,檢視應用是否能正常連線 PostgreSQL 資料庫,併成功啟動。
如果使用本地部署可以使用minikube service app
看到應用地址,他會自動開啟部署 url 埠。
Kubernetes 部署的優勢
相比於 Docker Compose 單節點部署,Kubernetes 的叢集化部署具備以下幾個顯著優勢:
高可用性和容錯:Kubernetes 提供了原生的自動重啟、容器健康檢查、橫向擴充套件等機制,使得應用能夠在出現問題時自動恢復。
自動擴充套件:你可以根據負載的變化,透過 Kubernetes 自動或手動擴充套件應用的副本數,保證應用能夠處理更多請求。
滾動更新:透過 Kubernetes,你可以實現應用的滾動更新,逐步替換舊版本的容器,而不會導致服務中斷。
資源分配和最佳化:Kubernetes 允許更精細地控制資源的使用,如 CPU 和記憶體,確保叢集資源的合理利用。
Secret 和 ConfigMap:透過 Secret 和 ConfigMap,Kubernetes 提供了更安全和動態的方式來管理應用的配置和敏感資訊,避免將敏感資料硬編碼在映象或程式碼中。
總結
將 Docker Compose 的單節點部署遷移到 Kubernetes,不僅能夠使應用從本地開發階段順利過渡到生產環境,還可以透過 Kubernetes 提供的叢集管理能力來提高系統的高可用性、彈性擴充套件和安全性。
在本文中,我們透過將 Docker Compose 配置中的 PostgreSQL、Adminer 和自定義 Node.js 應用遷移到 Kubernetes,學習瞭如何利用 StatefulSet
、Deployment
、Secret
和 Service
等 Kubernetes 資源來管理和部署複雜的叢集化應用。這種方式可以幫助你在生產環境中實現更加靈活、安全和可擴充套件的容器管理。