大家好,歡迎來到《云原生核心技術》系列的最終章!
我們一起走過了漫長而充實的旅程。從 Docker 的集裝箱,到 K8s 這座自動化的數字港口;從部署單個 Pod,到構建復雜的有狀態應用。現在,我們站在了實現全自動化的最后一站。
在上一篇中,我們理解了 CI/CD 的核心理念——那條連接開發與運維、通往高效與可靠的自動化高速公路。今天,我們不再紙上談兵,而是要親手鋪設這條公路的每一塊磚石。
我們將使用一個強大且整合度極高的工具——GitLab CI/CD,為我們第十篇中的 Spring Boot + MySQL + Redis
應用項目,打造一條從代碼提交到自動部署至 Kubernetes 的完整流水線。
讀完并實踐本篇文章,你將獲得一項在現代軟件工程中極具價值的技能:將 DevOps 思想落地,實現應用的自動化、可靠化交付。
準備好,讓我們開始最后的施工,為這個系列畫上一個完美的句號!
第一步:環境準備與規劃
在開始之前,請確保你已經擁有:
- 一個 GitLab 賬號和項目:你可以使用
GitLab.com
的免費版,或者自建的 GitLab 實例。將我們第十篇的 Spring Boot 項目代碼推送到這個 GitLab 倉庫中。 - 一個運行中的 K8s 集群:繼續使用我們的 Minikube 集群。
minikube start
- 一個 Docker 鏡像倉庫:比如 Docker Hub。你需要一個可以推送鏡像的賬號。
kubectl
和helm
命令行工具:Helm 是 K8s 的包管理器,我們將用它來方便地安裝 GitLab Runner。
我們的流水線規劃如下:
test
階段:運行 Maven 測試,確保代碼質量。build
階段:使用 Docker 構建 Spring Boot 應用的鏡像。push
階段:將構建好的鏡像推送到 Docker Hub。deploy
階段:使用kubectl
命令更新 K8s 中對應 Deployment 的鏡像版本,觸發滾動更新。
第二步:在 K8s 中安裝 GitLab Runner
GitLab Runner 是執行 .gitlab-ci.yml
文件中定義任務的代理程序。最云原生的方式,就是把它直接安裝在我們的 K8s 集群里。
-
獲取 Runner 注冊信息:
- 打開你的 GitLab 項目,在左側導航欄找到
Settings
->CI/CD
。 - 展開
Runners
部分。你會看到一個 URL (https://gitlab.com/
) 和一個注冊令牌 (registration token),類似GR13489...
。把這兩項復制下來,后面會用到。
- 打開你的 GitLab 項目,在左側導航欄找到
-
使用 Helm 安裝 GitLab Runner:
- 添加 GitLab Helm 倉庫:
helm repo add gitlab https://charts.gitlab.io helm repo update
- 創建一個
values.yaml
配置文件,用于定制我們的 Runner。# values.yaml gitlabUrl: "https://gitlab.com/" # 填入你復制的 GitLab URL runnerRegistrationToken: "GR13489..." # 填入你復制的注冊令牌# Runner 的配置 runners:# Runner 的標簽,后面在 .gitlab-ci.yml 中會用它來選擇 Runnertags: "kubernetes,minikube"
- 執行 Helm 安裝命令:
helm install --namespace gitlab-runner --create-namespace gitlab-runner \ -f values.yaml \ gitlab/gitlab-runner
- 驗證安裝:稍等片刻,然后檢查 Pod 是否在
gitlab-runner
命名空間中成功運行。kubectl get pods -n gitlab-runner # 你應該能看到一個名為 gitlab-runner-gitlab-runner-xxxx 的 Pod 正在運行
- 回到 GitLab 項目的 Runner 設置頁面,你應該能看到一個新的 Runner 已經注冊成功并顯示為綠色可用狀態。
- 添加 GitLab Helm 倉庫:
第三步:配置 GitLab CI/CD 變量
為了安全,我們不能把敏感信息(如 Docker Hub 密碼、K8s 憑證)直接寫在 .gitlab-ci.yml
文件里。我們需要將它們存儲在 GitLab 的 CI/CD 變量中。
進入 Settings
-> CI/CD
,展開 Variables
部分。添加以下變量:
-
Docker Hub 憑證:
DOCKER_USER
: 你的 Docker Hub 用戶名。DOCKER_PASS
: 你的 Docker Hub 密碼或訪問令牌 (Access Token)。(建議設置為Masked
類型)
-
K8s 集群憑證 (
kubeconfig
):- 我們需要讓 GitLab Runner 能夠訪問我們的 Minikube 集群。
- 在你的本地電腦上,找到
~/.kube/config
文件,并將其內容完整復制下來。 - 在 GitLab 變量設置中,創建一個新變量:
- Key:
KUBE_CONFIG
- Type:
File
(這很重要,它會將變量內容作為文件提供給 Runner) - Value: 粘貼你剛才復制的
kubeconfig
全部內容。
- Key:
第四步:編寫 .gitlab-ci.yml
,定義流水線
這是最核心的一步。在你的 Spring Boot 項目根目錄下,創建 .gitlab-ci.yml
文件,內容如下:
# .gitlab-ci.yml# 定義流水線的各個階段,任務會按此順序執行
stages:- test- build- push- deploy# 定義一些全局變量
variables:# Maven 鏡像,用于測試階段MAVEN_IMAGE: maven:3.8-openjdk-17# Docker 鏡像名稱。$CI_PROJECT_NAME 是 GitLab 預定義變量,代表項目名IMAGE_NAME: $CI_REGISTRY_USER/$CI_PROJECT_NAME# 鏡像標簽。$CI_COMMIT_SHORT_SHA 是提交的短哈希值,確保每次構建的標簽唯一IMAGE_TAG: $CI_COMMIT_SHORT_SHA# --- 階段一:測試 ---
maven_test:stage: testimage: $MAVEN_IMAGEscript:- echo "Running Maven tests..."- ./mvnw testtags:- kubernetes # 指定使用我們安裝在 K8s 里的 Runner# --- 階段二:構建 Docker 鏡像 ---
docker_build:stage: build# 使用 Docker-in-Docker (dind) 鏡像,以便在容器內執行 Docker 命令image: docker:20.10.16services:- docker:20.10.16-dindscript:- echo "Building Docker image..."- docker build -t $IMAGE_NAME:$IMAGE_TAG .# 保存鏡像為 tar 文件,以便在后續階段使用- docker save $IMAGE_NAME:$IMAGE_TAG > image.tar# artifacts 用于在不同階段之間傳遞文件artifacts:paths:- image.tartags:- kubernetes# --- 階段三:推送 Docker 鏡像 ---
docker_push:stage: pushimage: docker:20.10.16services:- docker:20.10.16-dind# 需要上一個階段構建的鏡像文件needs:- docker_buildscript:- echo "Pushing Docker image..."# 加載鏡像文件- docker load < image.tar# 登錄 Docker Hub,使用我們之前定義的 CI/CD 變量- echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin- docker push $IMAGE_NAME:$IMAGE_TAGtags:- kubernetes# --- 階段四:部署到 Kubernetes ---
deploy_to_k8s:stage: deploy# 使用一個包含 kubectl 的鏡像image:name: bitnami/kubectl:latestentrypoint: [""]needs:- docker_pushscript:- echo "Deploying to Kubernetes..."# 配置 kubectl,讓它使用我們通過變量傳入的 KUBE_CONFIG- export KUBECONFIG=$KUBE_CONFIG# 使用 kubectl set image 命令來更新 Deployment 的鏡像,觸發滾動更新# 將 'springboot-app-deployment' 替換為你在 K8s 中實際的 Deployment 名稱- kubectl set image deployment/springboot-app-deployment springboot-app=$IMAGE_NAME:$IMAGE_TAG- echo "Deployment updated successfully!"tags:- kubernetes
請注意:
- 將
springboot-app-deployment
和容器名springboot-app
替換成你在第十篇中使用的實際名稱。 $CI_REGISTRY_USER
默認是你的 GitLab 用戶名,你也可以硬編碼為你的 Docker Hub 用戶名。
第五步:觸發流水線,見證自動化魔法!
現在,一切準備就緒。
-
提交并推送代碼:將包含
.gitlab-ci.yml
的項目推送到你的 GitLab 倉庫。git add . git commit -m "feat: Add GitLab CI/CD pipeline for automated deployment" git push
-
觀察流水線:
- 立刻打開你的 GitLab 項目頁面,進入
CI/CD
->Pipelines
。 - 你會看到一個新的流水線被觸發了,狀態為
running
。 - 點擊這個流水線,你可以看到我們定義的四個階段
test
,build
,push
,deploy
正在依次執行。你可以點擊每一個 job 查看詳細的實時日志輸出。
- 立刻打開你的 GitLab 項目頁面,進入
-
驗證部署:
- 當
deploy
階段成功完成后,打開你的終端。 - 檢查你的 Deployment,你會看到它的鏡像已經被更新為最新的版本(帶有新的 commit 哈希標簽)。
kubectl describe deployment springboot-app-deployment
- 檢查 Pod,你會看到 K8s 已經完成了滾動更新,新的 Pod 正在運行。
kubectl get pods
- 當
現在,嘗試修改一下 Spring Boot 代碼中的某個字符串,然后再次 git push
。你將再次看到整個自動化流程被觸發,幾分鐘后,你的線上應用就被無縫地更新了!
總結與展望:你的云原生之旅,才剛剛開始
恭喜你!你已經成功地走完了從 Docker 到 Kubernetes 再到自動化 CI/CD 的全過程!
回顧這12篇的旅程,我們從最基礎的概念開始,一步一個腳印,最終搭建起了一套現代、高效、自動化的云原生應用交付系統。你不再是一個簡單的代碼編寫者或服務器管理者,而是一個能夠掌控從代碼到生產完整生命周期的現代工程師。
但這并不是終點,而是一個全新的起點。 云原生的世界浩瀚無垠,還有更多激動人心的領域等待你去探索:
- 服務網格 (Service Mesh): 使用 Istio, Linkerd 來實現更高級的流量管理、可觀測性和安全性。
- 可觀測性 (Observability): 深入學習 Prometheus, Grafana, Jaeger,打造全方位的監控、日志和追蹤系統。
- Serverless/FaaS: 探索 Knative, OpenFaaS,讓你的應用真正做到按需運行,極致彈性。
- GitOps: 學習 ArgoCD, Flux,將 Git 作為管理基礎設施和應用的唯一真實來源。
希望這個系列能為你打開一扇通往云原生世界的大門。保持好奇,持續學習,愿你在這片廣闊的數字海洋中,乘風破浪,揚帆遠航!
感謝你的一路相伴,我們的系列到此結束。江湖再見!