GitLab CI/CD流水线实战:.gitlab-ci.yml配置与Runner注册部署

GitLab CI/CD是内置于GitLab的持续集成/持续交付系统,通过仓库根目录的.gitlab-ci.yml文件定义流水线,由GitLab Runner执行具体任务。相比Jenkins的插件式架构,GitLab CI与代码仓库深度集成,配置即代码,无需额外维护CI服务。对于已有GitLab基础设施的团队,GitLab CI是成本最低的CI/CD落地方案。

Runner安装注册与Executor选型

GitLab Runner是流水线任务的执行器,支持多种Executor类型。Shell Executor直接在Runner主机上执行命令,适合简单场景;Docker Executor在容器中执行,隔离性好且支持指定镜像版本,是生产环境推荐方案。

# 安装GitLab Runner(Ubuntu/Debian)
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
apt-get install gitlab-runner

# 注册Runner
gitlab-runner register
# 输入GitLab URL: https://gitlab.example.com/
# 输入Registration Token: 从GitLab项目Settings -> CI/CD -> Runners获取
# 输入Executor: docker
# 输入Default Docker Image: node:20-alpine

注册后Runner配置文件位于/etc/gitlab-runner/config.toml,可调整并发数和缓存目录:

concurrent = 4  # 最大并发任务数

[[runners]]
  name = "docker-runner"
  executor = "docker"
  [runners.docker]
    image = "node:20-alpine"
    volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]
    pull_policy = "if-not-present"  # 避免每次都拉取镜像
  [runners.cache]
    Type = "s3"
    ServerAddress = "minio.internal:9000"
    BucketName = "runner-cache"
    AccessKey = "minioadmin"
    SecretKey = "minioadmin"

pull_policy = "if-not-present"优先使用本地镜像,仅当本地不存在时才拉取,可大幅减少流水线启动时间。缓存配置使用S3兼容存储(如MinIO),将构建缓存与Runner主机解耦,多Runner共享缓存。

.gitlab-ci.yml流水线结构

一个完整的前端项目流水线配置:

image: node:20-alpine

variables:
  NPM_CONFIG_CACHE: "$CI_PROJECT_DIR/.npm-cache"
  CYPRESS_CACHE_FOLDER: "$CI_PROJECT_DIR/.cypress-cache"

cache:
  key: ${CI_COMMIT_REF_SLUG}
  paths:
    - .npm-cache/
    - .cypress-cache/
  policy: pull-push

stages:
  - install
  - test
  - build
  - deploy

install:
  stage: install
  script:
    - npm ci --cache .npm-cache --prefer-offline
  artifacts:
    paths:
      - node_modules/
    expire_in: 1 hour

lint:
  stage: test
  needs: [install]
  script:
    - npm run lint
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

unit-test:
  stage: test
  needs: [install]
  script:
    - npm run test:unit -- --coverage --reporter=json
  coverage: '/Lines.*: (\d+\.\d+)%/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml
    paths:
      - coverage/
    expire_in: 7 days

build:
  stage: build
  needs: [lint, unit-test]
  script:
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 1 day
  rules:
    - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "develop"

deploy-staging:
  stage: deploy
  needs: [build]
  script:
    - rsync -avz --delete dist/ /var/www/staging/
  environment:
    name: staging
    url: https://staging.example.com
  rules:
    - if: $CI_COMMIT_BRANCH == "develop"

deploy-production:
  stage: deploy
  needs: [build]
  script:
    - rsync -avz --delete dist/ /var/www/production/
  environment:
    name: production
    url: https://www.example.com
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  when: manual  # 需要手动触发生产部署

needs关键字定义任务间的显式依赖,允许同一stage的任务并行执行,无需等待同stage其他任务完成。rules替代旧版only/except,基于表达式条件控制任务是否执行。when: manual使生产部署需要人工确认,防止误发布。

Docker镜像构建与推送到Registry

使用Docker-in-Docker(dind)或Kaniko构建镜像。Kaniko无需Docker守护进程,安全性更好:

build-image:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:v1.23.0-debug
    entrypoint: [""]
  script:
    - mkdir -p /kaniko/.docker
    - echo "{"auths":{"${CI_REGISTRY}":{"auth":"$(echo -n ${CI_REGISTRY_USER}:${CI_REGISTRY_PASSWORD} | base64)"}}}" > /kaniko/.docker/config.json
    - /kaniko/executor
      --context "${CI_PROJECT_DIR}"
      --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
      --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}"
      --destination "${CI_REGISTRY_IMAGE}:latest"
      --cache=true
      --cache-repo "${CI_REGISTRY_IMAGE}/cache"
      --cache-ttl=168h

--cache=true启用Kaniko层缓存,未变更的Dockerfile层直接复用缓存镜像层,构建时间从分钟级降至秒级。--cache-repo指定缓存存储仓库,需提前创建。

环境变量管理与Secret保护

GitLab CI支持项目级、环境级和组的变量管理。敏感信息(API密钥、数据库密码)应通过CI/CD Variables配置,而非硬编码在.gitlab-ci.yml中:

deploy-production:
  stage: deploy
  script:
    - |
      ssh -o StrictHostKeyChecking=no deploy@prod-server << 'EOF'
        cd /app
        docker compose pull
        DATABASE_URL=$DATABASE_URL docker compose up -d
      EOF
  variables:
    DATABASE_URL: $PROD_DATABASE_URL
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

在GitLab项目Settings -> CI/CD -> Variables中定义PROD_DATABASE_URL,勾选Masked选项使其在日志中显示为[MASKED]。勾选Protected选项使变量仅在受保护分支(如main)的流水线中可用,防止在feature分支中泄漏。

对于需要动态生成的密钥(如临时数据库密码),可在流水线中生成并通过GitLab API传递:

generate-secrets:
  stage: deploy
  script:
    - DB_PASSWORD=$(openssl rand -hex 16)
    - |
      curl --request PUT --header "PRIVATE-TOKEN: $CI_JOB_TOKEN"         --data "value=$DB_PASSWORD"         "$CI_API_V4_URL/projects/$CI_PROJECT_ID/variables/DEPLOY_DB_PASSWORD"

并行测试与流水线性能优化

测试套件耗时较长时,利用parallel关键字拆分为多个并行任务:

test:
  stage: test
  parallel: 4
  script:
    - |
      NODE_INDEX=$((CI_NODE_INDEX - 1))
      NODE_TOTAL=$CI_NODE_TOTAL
      npx jest --shard=$NODE_INDEX/$NODE_TOTAL
  artifacts:
    reports:
      junit: test-results/junit.xml

parallel: 4将测试拆分为4个并行任务,CI_NODE_INDEXCI_NODE_TOTAL由GitLab自动注入。Jest的--shard参数支持测试文件级别的分片分配。4个并行任务可将测试时间降低约60%(考虑任务调度开销)。

Junit测试报告通过artifacts.reports.junit上传,GitLab自动在Merge Request中显示测试结果摘要,包括失败用例数和新增失败用例数。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/gitlabcicd-liu-shui-xian-shi-zhan-gitlabciyml-pei-zhi-yu/

(0)
小编小编
上一篇 22小时前
下一篇 22小时前

相关推荐