Golang从手工编译到CI/CD自动化部署

一、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

 

 

posted @ 2025-10-20 11:17  筱倩  阅读(11)  评论(0)    收藏  举报