Stories

Detail Return Return

Golang從手工編譯到CI/CD自動化部署 - Stories Detail

一、DevOps是什麼

  DevOps = Development(開發) + Operations(運維)。讓開發人員(Dev)和運維人員(Ops)能夠高效協作,通過自動化手段讓軟件更快、更穩定地交付上線。

階段

沒有 DevOps

有 DevOps 後

提交代碼

每人自己存

統一放到 GitLab

測試

測試員手動跑

Jenkins 自動跑測試

部署

運維手動 SSH 部署

自動構建 Docker 鏡像並推到服務器

出錯排查

日誌分散難查

統一監控+日誌系統(Grafana+ELK)

上線週期

幾天甚至一週

幾小時甚至幾十分鐘

 

二、CI/CD

(一)概念

1、持續集成:開發團隊中每個人完成一部分代碼後,會頻繁地把自己地改動合併到主分支。每次提交都會觸發一系列流程:拉取代碼、編譯構建、執行單元測試、代碼質量檢查等。如果流程通過,説明當前版本是穩定可運行的,如果失敗,系統會立即反饋,方便開發者快速修復。

  2、持續交付: 當代碼通過持續集成地構建和測試後,持續交付會讓系統自動生成可發佈的版本包,並自動部署到測試環境、預發佈環境中,確保一旦業務方或管理層決定上線,只需要一鍵發佈即可。

3、持續部署【慎重!!】:當 CI/CD 流水線跑完所有驗證後(構建、測試、靜態分析、部署到測試環境、驗證通過),系統會自動執行“部署生產”的 Pipeline 階段。

  • 打包鏡像:把代碼+運行環境+依賴庫打包成Docker鏡像
  • 把鏡像上傳到生產倉庫。
  • 假如我的線上服務運行在K8s上,持續部署系統會告訴集羣用新版本。(該過程中K8s會一邊啓動新容器、一邊逐步關閉舊容器,確保網站整個過程不宕機)。
  • 驗證健康檢查:K8s檢測新容器是否能成功啓動,接口是否正確返回200
  • 灰度發佈:新版本只在10%的用户上生效,確認沒問題再逐步擴大。
  • 藍綠髮布:兩套環境同時存在,切換流程時無中斷。
  • 若健康檢查失敗,系統會自動退回舊版本鏡像。

 (二)應用部署發展過程

  • 開發人員自行上傳代碼:早期沒有專業運維人員,運維工作由開發兼職完成,很容易出錯,也是最原始的方式。
  • 開發人員將代碼先發給運維,每次項目發佈都由運維人員一步一步手動實現,效率底下且容易出錯。
  • 由運維人員編寫Shell、Python等腳本或利用自動化運維工具,如Ansible等實現半自動化應用部署,效率很高,但對技術的專業性有較高要求。
  • 通過Web等GUI界面實現一鍵自動化部署。可以通過開源或自研的運維平台實現方便的應用部署,操作容易,但需要提前構建運維平台。

(三)CICD流程

 

在  Golang項目開發中,單測、靜態代碼分析是CI/CD的核心環節,而CI/CD最終服務於部署,四者通過Pipeline形成一個自動化閉環。  

  1、靜態代碼分析

  • 在代碼提交後,執行測試前,通過工具自動檢查(如golint等)代碼規範性和潛在風險。
  • 靜態分析是CI的前置步驟,若分析失敗,CI流程會直接終止,不進入測試階段。
  • Golang實踐:通過golangci-lint run命令集成到CI工具。

  2、單測

  • 通過自動化測試用例驗證代碼邏輯是否符合預期,確保新代碼不會破壞既有功能。
  • 單測是CI流程的核心驗證環節,需在靜態代碼分析通過後執行。若單測失敗(如測試用例斷言不通過、覆蓋率不達標),則CI流程終止,代碼無法進入構建階段。
  • Golang實踐:用go test ./... -cover執行全量單測並生成覆蓋率報告。通過testify等庫編寫斷言。結合race檢測排查併發場景下的競態條件。

  3、CI/CD:

  • CI:將代碼提交->靜態分析->單測->構建串聯為自動化流程。繼續上面的,如果單測通過後,會構建Golang項目(go build)生成二進制文件或Docker鏡像。
  • CD:將CI構建的產物(如Docker鏡像)自動部署到目標環境。
    • 開發環境:每次主分支代碼合併後自動部署,供開發團隊測試。
    • 生成環境:通過手動審批後部署(持續交付)或全自動部署(持續部署),如使用kubectl將Docker鏡像部署到K8S集羣。

  Pipeline是將上述環節按順序、有條件串聯起來的自動化腳本,定義了“從代碼提交到部署”的完整路徑。以下是典型Pipeline流程:

# GitHub Actions配置文件示例(.github/workflows/ci-cd.yml)  
name: Golang CI/CD Pipeline  
on: [push, pull_request]  # 觸發條件:代碼推送或PR提交  

jobs:  
  code-check:  # 任務1:靜態代碼分析  
    runs-on: ubuntu-latest  
    steps:  
      - uses: actions/checkout@v4  
      - name: Set up Go  
        uses: actions/setup-go@v5  
        with: { go-version: '1.21' }  
      - name: Run golangci-lint  
        uses: golangci/golangci-lint-action@v3  # 執行靜態分析  

  unit-test:  # 任務2:單元測試(依賴code-check成功)  
    needs: code-check  
    runs-on: ubuntu-latest  
    steps:  
      - uses: actions/checkout@v4  
      - name: Set up Go  
        uses: actions/setup-go@v5  
      - name: Run unit tests  
        run: go test ./... -coverprofile=coverage.txt  # 執行單測並生成覆蓋率報告  

  build-deploy:  # 任務3:構建與部署(依賴unit-test成功)  
    needs: unit-test  
    runs-on: ubuntu-latest  
    steps:  
      - uses: actions/checkout@v4  
      - name: Build binary  
        run: go build -o app main.go  # 構建Golang二進制文件  
      - name: Deploy to server  
        if: github.ref == 'refs/heads/main'  # 僅主分支觸發部署  
        uses: appleboy/scp-action@master  # 將二進制文件推送到生產服務器  
        with:  
          host: ${{ secrets.SERVER_HOST }}  
          username: ${{ secrets.SERVER_USER }}  
          key: ${{ secrets.SSH_KEY }}  
          source: "app"  
          target: "/opt/golang-app/"

三、 部署Gitlab

  準備五個機器

  開發機:10.0.0.8

  gitlab:10.0.0.100

  Jenkins:10.0.0.101

  Test1:10.0.0.102

  Test2:10.0.0.103

  1. 在對應的機器上安裝gitlab
  2. 把寫好的代碼上傳到gitlab上。
  • 把提前打包好的代碼壓縮包上傳到開發機。
  • yum -y install golang【rocky】:安裝go編譯環境
  • apt install golang【ubuntu】
  • go build編譯成二進制文件
  • ./ginweb:把二進制文件跑起來
  • 新建一個羣組->在羣組裏建一個新項目
    • 安裝git命令
    • 按那個新建的項目下面的命令去執行
    • 在開發機上做一個從IP到域名的映射操作,並且同步到其他機器上
    • git init:本地只有一個裸倉庫,不知道遠程在哪裏
    • git remote add origin http://gitlab.wang.org/magedu/ginweb.git:Git會在我的項目配置文件.git/config增加一段內容,意思是本地倉庫有一個叫origin的遠程倉庫,它在Gitlab上的地址是xxxx。這樣本地就和遠程倉庫建立了關聯。
    • git add .:加入到緩存區
    • git commit -m v1.0
    • git branch:查看分支
    • git push origin master
    • 去gitlab.wang.org刷新就能看到ginweb的代碼。

  至此我們完成了從開發把代碼傳到了gitlab上。

四、部署Jenkins

  兩大核心組成部分:插件和Pipeline

(一)基於Shell實現簡單代碼部署

  1. 【Jenkins機器】要先安裝Java,再安裝Jenkins(用腳本安裝)
  2. 【Jenkins網站】登陸進來之後要修改密碼
  3. 【Jenkins網站】修改安裝插件的地址為國內的鏡像網站
  4. 【Jenkins網站】安裝一個gitlab的插件,與gitlab關聯起來
  5. 【gitlab機器】在Jenkins中的權限改為root;生成密鑰ssh -keygen-->cat .ssh/id_rsa.pub找到公鑰信息。
  6. 【gitlab網站】SSH密鑰複製上面的
  7. 【Jenkins網站】把gitlab倉庫的SSH地址複製到Jenkins網站中正在進行的項目創建的Repository URL中。然後還要創建憑證:Manage Jenkins->Manage Credentials->創建全局憑證。在Jenkins機器中輸入cat .ssh/id_rsa查看私鑰信息,並且輸入到創建全局憑證這裏。
  8. 【Jenkins網站】點擊Build Now,Jenkins會從gitlab拉取代碼到服務器上,cd /var/lib/jenkins下多了一個目錄workspace/ginweb,這個就是最初的代碼。
  9. 【Jenkins機器】安裝go環境【腳本】-->go build這個項目。
  10. 【Jenkins機器】把代碼拷貝到兩台生產機上。在ginweb的文件夾下執行:scp -r * 10.0.0.102:/opt/、scp -r * 10.0.0.103:/opt/。
  11. 在兩台生產機上運行代碼:cd /opt/-->./ginweb,這樣就運行起來了。
  12. 在瀏覽器上訪問10.0.0.102和103。
  13. 新建一台機器(10.0.0.104)部署mysql和redis。修改mysql和redis 的遠程連接地址(修改配置文件)。vim /etc/redis/redis.conf,修改redis密碼和端口。重新啓動redis,redis-cli -a 123456 info。
  14. 【開發機】scp ginweb.sql 10.0.0.104
  15. 【數據庫機器】mysql -uginweb -p123456 -h 10.0.0.104 ginweb < ginweb.sql-->show tables,這時候就已經有表結構了。
  16. 【Jenkins網站】重新build Now,然後把文件同步到兩台生產機上。再在兩台生產機上跑起來ginweb。
  17. 以上都是手動部署。
  18. 【Jenkins機器】mkdir /data/jenkins-scripts、cd /data/jenkins-scripts/、vim ginweb.sh,添加兩台生產機的IP地址。ssh-copy-id 10.0.0.102、ssh-copy-id 10.0.0.103。->應用。

  1. 更新下版本,修改掉登錄頁的標題的笑臉->3.0。在開發機上提交代碼。
  2. 在Jenkins網站中重新點擊Build Now。

綜上,完成的一個工作就是開發把代碼提交到gitlab上,Jenkins從gitlab拉取代碼,然後部署到生產環境跟中。

(二)Pipeline

  Jenkins的流水線能自動化完成整個CI/CD流程,在Jenkins會顯示一條動態流水線:拉取代碼√->編譯打包√->代碼掃描√->部署√,哪個步驟出錯都會顯示紅色×。

  • 從gitlab中拉取代碼。
  • go build構建編譯
  • go test自動化測試驗證
  • SonarQube靜態掃描代碼
  • docker build構建Docker鏡像
  • subectl更新服務器/K8s
  • 構建成功或失敗提醒,郵件/企業微信/飛書。

 

五、利用webHook實現自動化部署

這裏將要實現當開發者提交代碼就會自動部署到生產環境中。

  • 配置->觸發遠程構建->下面會有一串URL
  • 【開發機】curl http://admin:xxx令牌【這個可以手動生成】@jenkins.wang.org:8080/job/ginweb/build?token=666666
  • 【gitlab網站】設置->網絡->出站請求:允許來自web hooks和服務對本地網絡的請求。
  • 【gitlab網站】設置->webhook->粘貼URL到網址部分->測試Push events->發現Jenkins上在執行。
  • 【開發機】修改html中的標題改為v6.0,提交代碼到gitlab:git commit -am 'v6.0':git push -u origin master。理論上這裏一提交就會觸發構建、觸發發佈。

 

 

 

參考:

https://www.bilibili.com/video/BV1co4y1772K?spm_id_from=333.788.videopod.episodes&vd_source=99ec55b57f4eeedd9ed62c43e87cb6ff&p=2

 

 

user avatar tongbo Avatar yian Avatar aipaobudeshoutao Avatar
Favorites 3 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.