📖 知识点简介
运维手工部署等于慢性自杀。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 基本结构
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
# 安装 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. 常用内置变量
# 在 .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 分支后自动构建镜像并部署到测试服务器
# .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
配套:在部署目标服务器上提前准备
# 部署服务器需要:
# 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 — 镜像仓库密码
快速验证流水线
# 本地调试 .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. 部署密钥管理
# ❌ 错误:在 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),方便快速回退:
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 把"人肉运维"变成"代码运维"——配置即文档,流水线即流程,每一次部署都有据可查。