CI/CD 入门 — 用 GitLab CI 构建自动化部署流水线

📖 知识点简介

运维手工部署等于慢性自杀。CI/CD(持续集成/持续部署)将代码从提交到上线的流程自动化:

  • CI(Continuous Integration):每次代码提交自动触发构建、测试、代码扫描
  • CD(Continuous Deployment/Delivery):通过验证后自动部署到测试/预发布/生产环境

对运维来说,CI/CD 的意义不仅是"省去手动敲命令",更是标准化流程 ------每一次部署都有日志、可追溯、可回滚。GitLab CI 是自建运维体系中很受欢迎的选择:与 GitLab 深度集成,.gitlab-ci.yml 即配置,runner 可部署在任何机器上。


🔧 核心概念/配置整理

1. GitLab CI 核心概念

术语 说明
Pipeline 一次 CI/CD 执行的全流程,包含多个 Stage
Stage 阶段(如 build → test → deploy),顺序执行
Job 阶段内的具体任务,同 Stage 的 Job 并行执行
Runner 执行 Job 的 Agent,可注册到 GitLab
Artifact Job 产出的文件(如 jar 包),可传递到后续 Stage

2. .gitlab-ci.yml 基本结构

yaml 复制代码
stages:
  - build
  - test
  - deploy

# 变量(所有 Job 共享)
variables:
  DOCKER_IMAGE: registry.company.com/myapp
  DEPLOY_DIR: /opt/myapp

build-job:
  stage: build
  script:
    - docker build -t $DOCKER_IMAGE:$CI_COMMIT_SHORT_SHA .
    - docker push $DOCKER_IMAGE:$CI_COMMIT_SHORT_SHA
  only:
    - main

test-job:
  stage: test
  script:
    - docker run --rm $DOCKER_IMAGE:$CI_COMMIT_SHORT_SHA npm test
  only:
    - main

deploy-staging:
  stage: deploy
  script:
    - ansible-playbook -i inventory/staging deploy.yml
  environment:
    name: staging
  only:
    - main

deploy-production:
  stage: deploy
  script:
    - echo "Deploying to production..."
    - ansible-playbook -i inventory/prod deploy.yml
  environment:
    name: production
  when: manual          # 生产环境需要手动确认
  only:
    - main

3. 注册 GitLab Runner

bash 复制代码
# 安装 Runner
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | sudo bash
sudo yum install -y gitlab-runner

# 注册(需要 GitLab 项目的注册令牌)
sudo gitlab-runner register
# 输入 GitLab 实例 URL → https://gitlab.company.com
# 输入 Registration Token → 从项目 Settings → CI/CD → Runners 获取
# 输入描述 → prod-deploy-runner
# 选择执行器 → shell (简单场景) 或 docker

# 验证注册状态
sudo gitlab-runner list

4. 常用内置变量

yaml 复制代码
# 在 .gitlab-ci.yml 中可直接使用
$CI_COMMIT_SHORT_SHA    # 提交的短哈希(如 a1b2c3d)
$CI_COMMIT_REF_NAME     # 分支名(如 main, feature/xxx)
$CI_PIPELINE_ID         # Pipeline 唯一 ID
$CI_JOB_ID              # Job 唯一 ID
$CI_ENVIRONMENT_NAME    # 环境名称(staging / production)

🧪 实操示例:Docker 应用一键构建部署

场景:前后端分离项目,Push 到 main 分支后自动构建镜像并部署到测试服务器

yaml 复制代码
# .gitlab-ci.yml
stages:
  - build
  - test
  - deploy-staging

variables:
  REGISTRY: registry.company.com
  PROJECT: myapp
  TAG: $CI_COMMIT_SHORT_SHA

cache:
  paths:
    - node_modules/

before_script:
  - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $REGISTRY

build-frontend:
  stage: build
  script:
    - cd frontend
    - docker build -t $REGISTRY/$PROJECT/frontend:$TAG .
    - docker push $REGISTRY/$PROJECT/frontend:$TAG
  artifacts:
    paths:
      - frontend/dist/

build-backend:
  stage: build
  script:
    - cd backend
    - docker build -t $REGISTRY/$PROJECT/backend:$TAG .
    - docker push $REGISTRY/$PROJECT/backend:$TAG

test-backend:
  stage: test
  script:
    - docker run --rm $REGISTRY/$PROJECT/backend:$TAG pytest
  needs:
    - build-backend

deploy-staging:
  stage: deploy-staging
  script:
    - ssh deploy@staging-server "
        docker pull $REGISTRY/$PROJECT/frontend:$TAG &&
        docker pull $REGISTRY/$PROJECT/backend:$TAG &&
        docker-compose -f /opt/$PROJECT/docker-compose.yml up -d
      "
  environment:
    name: staging
    url: https://staging.company.com
  only:
    - main

配套:在部署目标服务器上提前准备

bash 复制代码
# 部署服务器需要:
# 1. 安装 Docker + docker-compose
# 2. 创建 deploy 用户
useradd -m deploy
usermod -aG docker deploy

# 3. 配置 SSH 免密(GitLab Runner 所在机器生成密钥)
ssh-keygen -t ed25519
ssh-copy-id deploy@staging-server

# 4. 在 GitLab 项目 Settings → CI/CD → Variables 中设置:
# CI_REGISTRY_USER --- 镜像仓库账号
# CI_REGISTRY_PASSWORD --- 镜像仓库密码

快速验证流水线

bash 复制代码
# 本地调试 .gitlab-ci.yml(需要安装 gitlab-ci-local)
# 或使用 GitLab 自带的 CI Lint
# 项目 → CI/CD → Editor → CI Lint

⚠️ 常见坑点/注意事项

1. Runner 安全风险

  • shell 执行器 :Runner 直接在宿主机执行脚本,权限极高。生产环境建议用 docker 执行器,每次 Job 运行在隔离容器中
  • 不要在公共仓库暴露 CI_REGISTRY_PASSWORD 等敏感变量,务必使用 GitLab 的 Settings → CI/CD → Variables(masked 标记)

2. 部署密钥管理

yaml 复制代码
# ❌ 错误:在 yml 中硬编码密钥
script:
  - sshpass -p '123456' ssh user@server deploy.sh

# ✅ 正确:使用 SSH 密钥 + GitLab Variables
# 在 CI Variables 中添加 SSH_PRIVATE_KEY(Type: File)
before_script:
  - eval $(ssh-agent -s)
  - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
  - mkdir -p ~/.ssh
  - chmod 700 ~/.ssh

3. 流水线速度优化

  • 利用 cache 缓存依赖(npm、pip、maven)
  • 用 needs 控制 Job 依赖,避免等待不相关的 Job
  • 合理设置 only/except,避免每次 push 都跑全量流水线

4. 回滚策略

每一次 CD 部署成功后,建议将上一版本保留为 Docker Tag(如 stable),方便快速回退:

yaml 复制代码
deploy-production:
  script:
    - docker tag $REGISTRY/$PROJECT:$TAG $REGISTRY/$PROJECT:stable
    - docker push $REGISTRY/$PROJECT:stable
    - # 执行部署
  # 回滚时只需 docker pull 回 stable 标签

5. 环境隔离

  • 始终区分 staging 和 production 环境
  • 生产环境部署推荐加 when: manual + 审批人配置
  • 每个环境使用独立的 Variables,不要在流水线中混用

一句话总结:CI/CD 把"人肉运维"变成"代码运维"------配置即文档,流水线即流程,每一次部署都有据可查。

相关推荐
子兮曰4 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰4 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
爱勇宝4 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
胡写代码4 天前
别再前后端各写一套表单校验了
java·后端
大勇前进4 天前
原生 PHP 还是 Laravel?小项目到底要不要上框架
后端
yuzhi_liu4 天前
我用 LangGraph4j 实现 Multi-Agent Supervisor
后端
alsmile4 天前
Node-RED 之外,国产规则引擎的新方案:基于标准语法,Go 先行实现
后端·开源·go
大白804 天前
PHP 内存溢出排查思路:看懂报错日志,精准定位问题
后端
二月龙4 天前
PHP 接口返回统一响应封装,让前后端对接更省心
后端
盖伦发发4 天前
软件工程SOLID 五大设计原则
后端·软件工程