一、為什麼要遷移到 K8s?Docker Compose 的 3 個不可逾越瓶頸

1. Docker Compose vs K8s:核心能力對比(遷移的本質原因)

能力維度

Docker Compose(單機)

K8s(分佈式)

業務影響

部署範圍

僅支持單台主機

支持多節點集羣(幾十到幾千台)

單機無法承載高併發,需多節點擴容

服務可用性

容器掛了需手動重啓

自動重啓故障 Pod(自愈能力)

生產環境需 7×24 小時無間斷服務

擴縮容能力

需手動修改配置重啓服務

一鍵擴容(kubectl scale)+ 自動擴縮容

秒殺場景需快速擴容,流量降後自動縮容

網絡管理

依賴主機端口映射,衝突風險高

內置 Service 網絡(Pod 間通信用域名)

多服務通信無需暴露主機端口,更安全

資源調度

所有容器共享主機資源,無隔離

按服務需求分配 CPU / 內存,支持資源限制

避免單服務佔用過多資源導致整體卡頓

2. 典型遷移場景(你該何時動手?)

  • 場景 1:Docker Compose 單機運行 5 + 服務,CPU 使用率長期超 80%,無法再新增服務;
  • 場景 2:業務高峯期(如大促)需臨時擴容訂單服務,手動啓動容器來不及;
  • 場景 3:生產環境要求服務 “零停機更新”,Docker Compose 重啓服務會中斷業務。

二、K8s 核心概念入門:用 Docker Compose 知識映射(降低理解成本)

對習慣 Docker Compose 的開發者,K8s 概念無需從零學起 —— 核心是 “將 Compose 的服務配置拆分為更精細的 K8s 資源”,對應關係如下:

Docker Compose 概念

K8s 對應資源

核心作用

容器(Container)

Pod

K8s 最小部署單元,一個 Pod 可包含 1 個或多個容器(如業務容器 + 日誌收集容器)

服務配置(Service)

Deployment

定義 Pod 的 “部署規則”,如鏡像版本、副本數、重啓策略(對應 Compose 的 service 塊)

端口映射(ports)

Service(ClusterIP)

暴露 Pod 網絡,實現 Pod 間通信(對應 Compose 的ports,但不依賴主機端口)

外部訪問(ports)

Service(NodePort)

暴露服務到集羣外部,供外部請求訪問(類似 Compose 的-p 8080:8080)

數據卷(volumes)

PersistentVolume(PV)

持久化存儲數據,解決 Pod 刪除後數據丟失問題(對應 Compose 的volumes)

關鍵認知:K8s 的 “自愈” 與 “擴縮容” 依賴這兩個核心機制

  • 自愈:Deployment 配置restartPolicy: Always,當 Pod 因內存溢出、網絡故障崩潰時,K8s 會自動銷燬故障 Pod 並啓動新 Pod;
  • 擴縮容:Deployment 通過replicas: 3定義 Pod 副本數,執行kubectl scale deployment user-service --replicas=5可快速擴容到 5 個副本,流量會自動負載均衡到所有副本。

三、實戰 1:搭建 K8s 本地環境(用 Minikube,適合新手)

K8s 集羣部署複雜,本地測試推薦用Minikube(單節點 K8s 集羣,一鍵啓動,無需多台主機)。

1. 環境準備(需滿足以下條件)

  • 操作系統:Windows 10+(需開啓 WSL2)、macOS(需安裝 HyperKit)、Linux;
  • 資源:至少 2 核 CPU、4GB 內存(Minikube 默認要求);
  • 工具:已安裝 Docker(Minikube 可複用 Docker 環境)。

2. 安裝 Minikube 與 kubectl(K8s 命令行工具)

(1)安裝 kubectl(操作 K8s 集羣的核心工具)
# Linux/macOS(Windows用WSL2執行)curl -LO "https://dl.k8s.io/release/v1.28.3/bin/linux/amd64/kubectl"chmod +x ./kubectlsudo mv ./kubectl /usr/local/bin/kubectl# 驗證:kubectl version --client 輸出版本即成功
(2)安裝 Minikube 並啓動 K8s 集羣
# 安裝Minikube(Linux/macOS)curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64sudo install minikube-linux-amd64 /usr/local/bin/minikube# 啓動K8s集羣(指定用Docker驅動,複用本地Docker環境)minikube start --driver=docker --cpus=2 --memory=4g# 參數説明:--cpus=2(分配2核CPU),--memory=4g(分配4GB內存)# 驗證集羣狀態:minikube status 顯示「host: Running」「kubelet: Running」即成功
(3)查看 K8s 集羣信息
# 查看集羣節點(Minikube單節點,名為minikube)kubectl get nodes# 輸出示例:# NAME       STATUS   ROLES           AGE   VERSION# minikube   Ready    control-plane   5m    v1.28.3# 查看集羣命名空間(默認所有資源在default命名空間)kubectl get namespaces

四、實戰 2:微服務遷移核心步驟(以用户服務為例)

遷移邏輯:將 Docker Compose 的 user-service 配置,拆分為 K8s 的「Deployment(部署 Pod)」和「Service(暴露網絡)」,步驟如下:

1. 步驟 1:準備遷移前提(確保鏡像可訪問)

K8s 需能拉取用户服務鏡像(user-service:v1.0.1),本地鏡像需先推到鏡像倉庫(或用 Minikube 加載本地鏡像,避免拉取失敗):

# 方法1:Minikube加載本地鏡像(無需推到遠程倉庫,適合本地測試)minikube image load user-service:v1.0.1# 驗證:minikube image ls | grep user-service 能看到鏡像即成功

2. 步驟 2:編寫 K8s Deployment 配置(對應 Compose 的 service 塊)

創建user-service-deployment.yaml,定義 Pod 的部署規則(鏡像、環境變量、資源限制等):

apiVersion: apps/v1 # K8s API版本(Deployment屬於apps組)kind: Deployment # 資源類型:Deployment(管理Pod的部署與自愈)metadata:  name: user-service # Deployment名稱(唯一標識)  labels:    app: user-service # 標籤(用於和Service關聯)spec:  replicas: 2 # Pod副本數(初始2個,支持後續擴縮容)  selector:    matchLabels:      app: user-service # 選擇匹配標籤的Pod進行管理  template:    metadata:      labels:        app: user-service # Pod的標籤(需和selector.matchLabels一致)    spec:      containers: # 容器配置(一個Pod可多個容器,這裏僅業務容器)      - name: user-service # 容器名稱        image: user-service:v1.0.1 # 鏡像(Minikube已加載的本地鏡像)        imagePullPolicy: Never # 鏡像拉取策略:Never(僅用本地鏡像,不遠程拉取)        ports:        - containerPort: 8081 # 容器內部端口(和服務端口一致)        env: # 環境變量(對應Compose的environment)        - name: SPRING_CLOUD_NACOS_DISCOVERY_SERVER_ADDR          value: "nacos-service:8848" # Nacos的Service名稱(後續部署Nacos後可用)        - name: SPRING_DATASOURCE_URL          value: "jdbc:mysql://tidb-service:4000/test_db?useSSL=false&serverTimezone=Asia/Shanghai"        - name: SPRING_DATASOURCE_USERNAME          value: "root"        - name: SPRING_DATASOURCE_PASSWORD          value: ""        resources: # 資源限制(避免單Pod佔用過多資源)          limits: # 最大資源            cpu: "1" # 最多1核CPU            memory: "512Mi" # 最多512MB內存          requests: # 最小資源(K8s調度時確保分配)            cpu: "0.5"            memory: "256Mi"        livenessProbe: # 存活探針(檢測Pod是否存活,失敗則重啓)          httpGet:            path: /actuator/health # 健康檢查端點            port: 8081          initialDelaySeconds: 30 # 啓動30秒後開始探測          periodSeconds: 10 # 每10秒探測一次        readinessProbe: # 就緒探針(檢測Pod是否就緒,未就緒則不分配流量)          httpGet:            path: /actuator/health            port: 8081          initialDelaySeconds: 20          periodSeconds: 5

3. 步驟 3:編寫 K8s Service 配置(對應 Compose 的 ports+Nginx 轉發)

創建user-service-service.yaml,暴露 Pod 網絡,實現 Pod 間通信與外部訪問:

apiVersion: v1 # Service屬於v1組kind: Service # 資源類型:Servicemetadata:  name: user-service # Service名稱(Pod間通信用此名稱)spec:  type: NodePort # 服務類型:NodePort(暴露到集羣外部,適合測試)  selector:    app: user-service # 關聯標籤匹配的Pod(和Deployment的Pod標籤一致)  ports:  - port: 8081 # Service內部端口(Pod間通信用此端口)    targetPort: 8081 # 映射到Pod的端口(和containerPort一致)    nodePort: 30081 # 集羣節點暴露的端口(範圍30000-32767,外部訪問用)

4. 步驟 4:部署用户服務到 K8s 並驗證

# 1. 應用Deployment配置(創建Pod)kubectl apply -f user-service-deployment.yaml# 2. 應用Service配置(創建Service)kubectl apply -f user-service-service.yaml# 3. 查看Deployment狀態(確認Pod正在創建)kubectl get deployments# 輸出示例:# NAME           READY   UP-TO-DATE   AVAILABLE   AGE# user-service   2/2     2            2           1m# 説明:READY 2/2表示2個Pod均就緒# 4. 查看Pod狀態(確認Pod運行正常)kubectl get pods -l app=user-service # 按標籤篩選Pod# 輸出示例:# NAME                            READY   STATUS    RESTARTS   AGE# user-service-7f98d7c6b4-2xqzk   1/1     Running   0          1m# user-service-7f98d7c6b4-5r7k8   1/1     Running   0          1m# 5. 查看Service狀態(確認NodePort暴露)kubectl get services user-service# 輸出示例:# NAME           TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE# user-service   NodePort   10.96.123.45    <none>        8081:30081/TCP   1m# 説明:外部可通過「Minikube節點IP:30081」訪問服務# 6. 獲取Minikube節點IP並訪問服務minikube ip # 輸出Minikube節點IP,如192.168.49.2# 訪問服務:http://192.168.49.2:30081/user/get/1(返回用户數據即成功)# 7. 查看Pod日誌(排查問題用)kubectl logs user-service-7f98d7c6b4-2xqzk # 替換為實際Pod名稱

5. 步驟 5:遷移訂單服務(複用用户服務邏輯)

訂單服務遷移與用户服務類似,核心差異是環境變量中需配置 Feign 調用的用户服務地址(用 K8s Service 名稱):

# order-service-deployment.yaml 關鍵環境變量配置env:- name: FEIGN_CLIENT_USER_SERVICE_URL  value: "http://user-service:8081" # 用Service名稱通信,無需IP

部署命令與驗證步驟完全複用用户服務,最終實現「訂單服務 Pod 調用用户服務 Pod」的 K8s 內部通信。

五、實戰 3:K8s 部署 Nacos 與 TiDB(確保微服務依賴可用)

微服務依賴 Nacos(註冊中心)和 TiDB(數據庫),需先部署到 K8s(或用外部服務,這裏以 K8s 部署為例)。

1. 部署 Nacos 到 K8s(簡化版,適合測試)

創建nacos-deployment.yaml:

apiVersion: apps/v1kind: Deploymentmetadata:  name: nacos-servicespec:  replicas: 1  selector:    matchLabels:      app: nacos  template:    metadata:      labels:        app: nacos    spec:      containers:      - name: nacos        image: nacos/nacos-server:v2.2.3        ports:        - containerPort: 8848        env:        - name: MODE          value: "standalone" # 單機模式---# 同時創建Nacos的ServiceapiVersion: v1kind: Servicemetadata:  name: nacos-servicespec:  type: NodePort  selector:    app: nacos  ports:  - port: 8848    targetPort: 8848    nodePort: 30088

部署並驗證:

kubectl apply -f nacos-deployment.yaml# 訪問Nacos:http://MinikubeIP:30088/nacos(賬號nacos/nacos),確認用户/訂單服務已註冊

2. 部署 TiDB 到 K8s(用 TiDB Operator 簡化部署,可選)

生產環境推薦用 TiDB Operator 部署 TiDB 集羣,本地測試可簡化為單 Pod 部署(僅用於驗證):

# tidb-deployment.yamlapiVersion: apps/v1kind: Deploymentmetadata:  name: tidb-servicespec:  replicas: 1  selector:    matchLabels:      app: tidb  template:    metadata:      labels:        app: tidb    spec:      containers:      - name: tidb        image: pingcap/tidb:v7.0.0        ports:        - containerPort: 4000        env:        - name: TIDB_CONFIG          value: "log-level: info"---apiVersion: v1kind: Servicemetadata:  name: tidb-servicespec:  type: NodePort  selector:    app: tidb  ports:  - port: 4000    targetPort: 4000    nodePort: 30090

部署後,微服務通過tidb-service:4000訪問數據庫,與 Docker Compose 邏輯一致。

六、避坑指南:遷移過程中的 6 個高頻問題

1. 坑 1:K8s 拉取不到本地鏡像(報 ImagePullBackOff)

  • 現象:kubectl get pods顯示 Pod 狀態為ImagePullBackOff,日誌報 “ErrImagePull: image not found”;
  • 原因:K8s 默認從遠程倉庫拉取鏡像,本地鏡像未加載到 Minikube;
  • 解決:執行minikube image load 鏡像名:版本,並在 Deployment 中設置imagePullPolicy: Never。

2. 坑 2:Pod 間通信失敗(訂單服務調用用户服務報 Connection refused)

  • 現象:訂單服務日誌報 “connect to user-service:8081 failed”;
  • 原因 1:Service 未關聯 Pod(Deployment 的 Pod 標籤與 Service 的selector不匹配);
  • 原因 2:Service 未就緒(kubectl get services顯示 Service 的ENDPOINTS為空);
  • 解決
  1. 核對 Deployment 的template.metadata.labels與 Service 的selector.matchLabels是否一致;
  2. 執行kubectl describe service user-service查看 Service 關聯的 Pod,確保ENDPOINTS有值。

3. 坑 3:外部無法訪問 Service(報 Connection timed out)

  • 現象:訪問http://MinikubeIP:30081超時,無法連接;
  • 原因 1:NodePort 端口範圍錯誤(需在 30000-32767 之間,超出範圍 K8s 不生效);
  • 原因 2:Minikube 網絡模式問題(Windows 用 WSL2 時,需通過minikube service user-service --url獲取正確訪問地址);
  • 解決
  1. 確認 Service 的nodePort在 30000-32767 之間;
  2. 執行minikube service user-service --url,用輸出的臨時 URL 訪問(如http://127.0.0.1:51234)。

4. 坑 4:Pod 頻繁重啓(報 CrashLoopBackOff)

  • 現象:Pod 狀態頻繁從Running變為CrashLoopBackOff,日誌報 “Java out of memory”;
  • 原因:Deployment 的resources.limits.memory設置過小(如 256MB),服務啓動時內存不足;
  • 解決:增大內存限制,如memory: "512Mi",重新應用 Deployment:kubectl apply -f user-service-deployment.yaml。

5. 坑 5:健康檢查失敗(Pod 狀態為 Running 但 Ready 為 0/1)

  • 現象:kubectl get pods顯示user-service-xxx 0/1 Running,READY為 0;
  • 原因:就緒探針(readinessProbe)配置錯誤,如path寫錯(應為/actuator/health,而非/health);
  • 解決:核對探針的path和port,確保與服務的健康檢查端點一致,查看探針日誌:kubectl describe pod Pod名稱(在 Events 中查看失敗原因)。

6. 坑 6:擴縮容後流量未負載均衡

  • 現象:執行kubectl scale deployment user-service --replicas=3擴容到 3 個 Pod,但請求僅分發到 2 個;
  • 原因:K8s Service 的負載均衡依賴kube-proxy,需等待kube-proxy更新端點列表(約 10 秒);
  • 解決:等待 10-20 秒後再測試,或執行kubectl delete pod -l app=user-service重啓 Pod,觸發端點更新。

七、遷移總結:從 Docker 到 K8s 的核心步驟梳理

  1. 環境準備:用 Minikube 搭建本地 K8s 集羣,加載本地微服務鏡像;
  2. 配置轉換:將 Compose 的 service 拆分為 K8s 的 Deployment(部署規則)和 Service(網絡暴露);
  3. 依賴部署:部署 Nacos、TiDB 等依賴服務,確保微服務能正常連接;
  4. 服務遷移:先遷移無依賴的服務(如用户服務),再遷移有依賴的服務(如訂單服務);
  5. 驗證與優化:驗證 Pod 通信、外部訪問、擴縮容功能,根據問題調整資源配置與探針。

八、系列終章:從技術選型到 K8s 部署的全鏈路回顧

本系列從「Java 分佈式框架 + 國產數據庫 + Docker 部署」的技術選型出發,歷經 12 篇實戰,完成了從 “開發環境搭建” 到 “生產級 K8s 部署” 的全鏈路落地:

  1. 基礎篇:環境準備(JDK/MySQL/TiDB)、國產數據庫選型(TiDB/OceanBase/ 達夢);
  2. 框架篇:Spring Cloud Alibaba 整合(Nacos/Sentinel/OpenFeign/Gateway)、TiDB 優化;
  3. 部署篇:數據遷移(MySQL→TiDB)、微服務容器化(Docker 鏡像構建)、多服務編排(Docker Compose)、生產級優化(監控 / 日誌 / 灰度)、K8s 遷移;

通過這套技術棧,你已具備「分佈式微服務設計 + 國產數據庫落地 + 容器化部署」的完整能力,可支撐從中小項目到大型高併發系統的技術需求。後續可深入 K8s 高級特性(如 StatefulSet 部署有狀態服務、ConfigMap 管理配置、Ingress 替代 NodePort),進一步提升系統的可維護性與擴展性。