GitLab CI/CD 运维指南
目录
- GitLab 架构概述
- GitLab 安装与配置
- GitLab Runner 配置
- CI/CD 配置文件
- 流水线设计
- Docker 集成
- Kubernetes 集成
- 安全最佳实践
- 监控与维护
1. GitLab 架构概述
1.1 核心组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| GitLab Server ├── GitLab Rails (应用层) ├── GitLab Shell (SSH/Git) ├── GitLab Workhorse (反向代理) ├── PostgreSQL (数据库) ├── Redis (缓存) └── Gitaly (Git RPC)
GitLab Runner ├── Executor (Docker/Shell/Kubernetes) ├── Cache (缓存管理) └── Artifacts (构建产物)
Registry ├── Docker Registry └── Package Registry
|
1.2 CI/CD 流程
1 2 3 4 5 6 7 8 9
| 代码提交 → Webhook 触发 → 创建 Pipeline ↓ Stage 1: Build (编译构建) ↓ Stage 2: Test (测试) ↓ Stage 3: Deploy (部署) ↓ Stage 4: Review (审查)
|
2. GitLab 安装与配置
2.1 Omnibus 安装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | bash
apt-get install -y gitlab-ce
apt-get install -y gitlab-ee
vi /etc/gitlab/gitlab.rb
external_url 'https://gitlab.example.com' gitlab_rails['gitlab_shell_ssh_port'] = 2222 gitlab_rails['gitlab_https_certificate'] = '/etc/ssl/certs/gitlab.crt' gitlab_rails['gitlab_https_key'] = '/etc/ssl/private/gitlab.key'
gitlab-ctl reconfigure
gitlab-ctl status
cat /etc/gitlab/initial_root_password
|
2.2 Docker 安装
1 2 3 4 5 6 7 8 9 10 11 12
| docker run -d \ --hostname gitlab.example.com \ -p 443:443 \ -p 80:80 \ -p 2222:22 \ --name gitlab \ --restart always \ --volume $GITLAB_HOME/config:/etc/gitlab \ --volume $GITLAB_HOME/logs:/var/log/gitlab \ --volume $GITLAB_HOME/data:/var/opt/gitlab \ --shm-size 256m \ gitlab/gitlab-ce:latest
|
2.3 备份与恢复
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| gitlab-backup create
ls /var/opt/gitlab/backups/
gitlab-ctl stop unicorn gitlab-ctl stop sidekiq
gitlab-backup restore BACKUP=1234567890_2024_01_01_1.0.0
gitlab-ctl start
crontab -e 0 2 * * * /opt/gitlab/bin/gitlab-backup create CRON=1
|
3. GitLab Runner 配置
3.1 安装 Runner
1 2 3 4 5 6 7 8 9 10 11 12 13
| curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | bash apt-get install -y gitlab-runner
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | bash yum install -y gitlab-runner
docker run -d --name gitlab-runner --restart always \ -v /srv/gitlab-runner/config:/etc/gitlab-runner \ -v /var/run/docker.sock:/var/run/docker.sock \ gitlab/gitlab-runner:latest
|
3.2 注册 Runner
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| gitlab-runner register
gitlab-runner register \ --non-interactive \ --url "https://gitlab.example.com/" \ --registration-token "YOUR_TOKEN" \ --executor "docker" \ --description "docker-runner" \ --docker-image "alpine:latest" \ --tag-list "docker,production" \ --run-untagged="true" \ --locked="false"
|
3.3 Runner 配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| concurrent = 10 check_interval = 0
[[runners]] name = "docker-runner" url = "https://gitlab.example.com/" token = "RUNNER_TOKEN" executor = "docker" limit = 10 [runners.docker] tls_verify = false image = "alpine:latest" privileged = true disable_cache = false volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"] shm_size = 0 [runners.cache] Type = "s3" Shared = true [runners.cache.s3] ServerAddress = "s3.amazonaws.com" AccessKey = "ACCESS_KEY" SecretKey = "SECRET_KEY" BucketName = "gitlab-runner-cache"
|
3.4 Runner 管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| gitlab-runner list
gitlab-runner verify
gitlab-runner unregister --name runner-name
systemctl restart gitlab-runner
journalctl -u gitlab-runner -f
|
4. CI/CD 配置文件
4.1 基础配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| stages: - build - test - deploy
variables: APP_NAME: myapp DOCKER_DRIVER: overlay2
before_script: - echo "Before each job"
after_script: - echo "After each job"
build_job: stage: build script: - echo "Building..." - npm install - npm run build artifacts: paths: - dist/ expire_in: 1 week
test_job: stage: test script: - echo "Testing..." - npm run test dependencies: - build_job
deploy_job: stage: deploy script: - echo "Deploying..." - ./deploy.sh only: - main when: manual
|
4.2 关键字说明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| stages: variables: before_script: after_script: script: image: services: cache: artifacts: dependencies: tags: only/except: rules: when: allow_failure: timeout: retry:
|
4.3 变量使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| variables: CI_COMMIT_SHA: $CI_COMMIT_SHA CI_COMMIT_BRANCH: $CI_COMMIT_BRANCH CI_PROJECT_NAME: $CI_PROJECT_NAME CI_REGISTRY_IMAGE: $CI_REGISTRY_IMAGE
variables: DATABASE_URL: "postgresql://user:pass@db:5432/mydb" NODE_ENV: "production"
variables: TLS_CERT: file: certs/tls.crt TLS_KEY: file: certs/tls.key
|
5. 流水线设计
5.1 多阶段流水线
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| stages: - lint - build - test - security - deploy
lint: stage: lint script: - npm run lint
build: stage: build script: - npm install - npm run build artifacts: paths: - dist/
unit_test: stage: test script: - npm run test:unit
integration_test: stage: test script: - npm run test:integration services: - postgres:13
security_scan: stage: security script: - npm audit - snyk test allow_failure: true
deploy_staging: stage: deploy script: - ./deploy.sh staging environment: name: staging only: - develop
deploy_production: stage: deploy script: - ./deploy.sh production environment: name: production only: - main when: manual
|
5.2 并行与矩阵
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| test: stage: test parallel: 5 script: - npm run test -- --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL
build: stage: build parallel: matrix: - NODE_VERSION: [14, 16, 18] OS: [ubuntu-latest, macos-latest] image: node:$NODE_VERSION script: - npm install - npm run build
|
5.3 条件执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| deploy: script: - ./deploy.sh rules: - if: $CI_COMMIT_BRANCH == "main" when: always - if: $CI_COMMIT_BRANCH == "develop" when: manual - if: $CI_PIPELINE_SOURCE == "schedule" when: always - when: never
deploy_prod: script: - ./deploy.sh only: - main - tags except: - schedules
|
5.4 子流水线
1 2 3 4 5 6 7 8 9 10 11 12 13
| trigger_downstream: stage: deploy trigger: project: group/sub-project branch: main strategy: depend
include: - local: '.gitlab-ci-template.yml' - remote: 'https://example.com/.gitlab-ci.yml' - template: Auto-DevOps.gitlab-ci.yml
|
6. Docker 集成
6.1 Docker in Docker
1 2 3 4 5 6 7 8 9 10 11 12 13
| variables: DOCKER_HOST: tcp://docker:2375 DOCKER_DRIVER: overlay2
services: - docker:20.10.16-dind
build: image: docker:20.10.16 script: - docker build -t myapp:$CI_COMMIT_SHA . - docker push myapp:$CI_COMMIT_SHA
|
6.2 Docker 构建与推送
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| variables: DOCKER_REGISTRY: registry.gitlab.example.com DOCKER_IMAGE: $DOCKER_REGISTRY/$CI_PROJECT_PATH
stages: - build - deploy
build_image: stage: build image: docker:latest services: - docker:dind script: - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY - docker build -t $DOCKER_IMAGE:$CI_COMMIT_SHA . - docker build -t $DOCKER_IMAGE:latest . - docker push $DOCKER_IMAGE:$CI_COMMIT_SHA - docker push $DOCKER_IMAGE:latest only: - main - develop
deploy: stage: deploy image: bitnami/kubectl:latest script: - kubectl set image deployment/myapp myapp=$DOCKER_IMAGE:$CI_COMMIT_SHA only: - main
|
6.3 多阶段构建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| build: stage: build image: docker:latest services: - docker:dind script: - docker build --target production -t myapp:$CI_COMMIT_SHA . - docker push myapp:$CI_COMMIT_SHA
FROM node:16 AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build
FROM node:16-alpine AS production WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules CMD ["node", "dist/server.js"]
|
7. Kubernetes 集成
7.1 配置 Kubernetes 访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| kubectl create namespace gitlab kubectl create serviceaccount gitlab-deployer -n gitlab
kubectl create clusterrolebinding gitlab-deployer \ --clusterrole=cluster-admin \ --serviceaccount=gitlab:gitlab-deployer
kubectl get secret $(kubectl get serviceaccount gitlab-deployer -n gitlab -o jsonpath='{.secrets[0].name}') -n gitlab -o jsonpath='{.data.token}' | base64 -d
|
7.2 部署到 Kubernetes
1 2 3 4 5 6 7 8 9 10 11 12
| deploy: stage: deploy image: bitnami/kubectl:latest script: - kubectl config set-cluster k8s --server=$KUBE_SERVER --certificate-authority=$KUBE_CA_CERT - kubectl config set-credentials deployer --token=$KUBE_TOKEN - kubectl config set-context default --cluster=k8s --user=deployer --namespace=$KUBE_NAMESPACE - kubectl config use-context default - kubectl set image deployment/$APP_NAME $APP_NAME=$DOCKER_IMAGE:$CI_COMMIT_SHA - kubectl rollout status deployment/$APP_NAME only: - main
|
7.3 Helm 部署
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| deploy_helm: stage: deploy image: alpine/helm:latest before_script: - apk add --no-cache curl - curl -LO https://get.kubectl.io/$(curl -s https://get.kubectl.io)/bin/linux/$(curl -s https://get.kubectl.io)/kubectl - chmod +x ./kubectl - mv ./kubectl /usr/local/bin/kubectl script: - helm repo add myrepo https://charts.example.com - helm upgrade --install myapp myrepo/myapp \ --set image.tag=$CI_COMMIT_SHA \ --set replicaCount=3 \ --namespace $KUBE_NAMESPACE \ --wait only: - main
|
8. 安全最佳实践
8.1 凭证管理
1 2 3 4 5 6 7 8 9 10 11 12 13
|
deploy: script: - echo $DATABASE_PASSWORD - aws deploy --token $AWS_TOKEN
deploy: script: - curl -H "X-Vault-Token: $VAULT_TOKEN" $VAULT_ADDR/v1/secret/data/app | jq '.data.data'
|
8.2 权限控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| [[runners]] executor = "docker" [runners.docker] privileged = false disable_cache = false cap_drop = ["ALL"] cap_add = ["NET_BIND_SERVICE"]
|
8.3 安全扫描
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| include: - template: Security/SAST.gitlab-ci.yml - template: Security/Dependency-Scanning.gitlab-ci.yml - template: Security/Container-Scanning.gitlab-ci.yml - template: Security/DAST.gitlab-ci.yml
security_scan: stage: test script: - npm audit - snyk test - trivy image myapp:$CI_COMMIT_SHA allow_failure: true
|
9. 监控与维护
9.1 监控指标
1 2 3 4 5 6 7 8 9 10 11
|
curl https://gitlab.example.com/-/metrics
- gitlab_ci_pipelines_total - gitlab_ci_builds_total - gitlab_runner_jobs_total - gitlab_http_requests_total
|
9.2 日志管理
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| gitlab-ctl tail gitlab-ctl tail nginx gitlab-ctl tail sidekiq gitlab-ctl tail gitlab-rails
journalctl -u gitlab-runner -f
logrotate['enable'] = true logrotate['max_size'] = "100M" logrotate['rotate'] = 30
|
9.3 性能优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
puma['worker_processes'] = 4 puma['worker_timeout'] = 60
sidekiq['max_concurrency'] = 20 sidekiq['job_timeout'] = 60
postgresql['shared_buffers'] = "256MB" postgresql['max_connections'] = 400
redis['maxclients'] = 10000
gitlab-ctl reconfigure
|
9.4 备份策略
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #!/bin/bash
/opt/gitlab/bin/gitlab-backup create
find /var/opt/gitlab/backups -name "*.tar" -mtime +7 -delete
rsync -avz /var/opt/gitlab/backups/ backup-server:/backup/gitlab/
0 2 * * * /opt/gitlab-backup.sh
|
文档版本: 1.0
最后更新: 2026-02-27
适用版本: GitLab 15.x+, GitLab Runner 15.x+