GitLab CI/CD 运维指南

目录

  1. GitLab 架构概述
  2. GitLab 安装与配置
  3. GitLab Runner 配置
  4. CI/CD 配置文件
  5. 流水线设计
  6. Docker 集成
  7. Kubernetes 集成
  8. 安全最佳实践
  9. 监控与维护

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
# 添加 GitLab 仓库
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | bash

# 安装 GitLab CE
apt-get install -y gitlab-ce

# 或安装 GitLab EE
apt-get install -y gitlab-ee

# 配置 GitLab
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
# Ubuntu/Debian
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | bash
apt-get install -y gitlab-runner

# CentOS/RHEL
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | bash
yum install -y gitlab-runner

# Docker 安装
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 URL: https://gitlab.example.com
# Registration token: <从 GitLab 获取>
# Description: my-runner
# Tags: docker,production
# Executor: docker
# Docker image: alpine:latest

# 非交互式注册
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
# /etc/gitlab-runner/config.toml
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
# 查看 Runner
gitlab-runner list

# 验证 Runner
gitlab-runner verify

# 删除 Runner
gitlab-runner unregister --name runner-name

# 重启 Runner
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
# .gitlab-ci.yml
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: # 每个 job 之前执行
after_script: # 每个 job 之后执行
script: # 执行命令
image: # Docker 镜像
services: # Docker 服务
cache: # 缓存配置
artifacts: # 构建产物
dependencies: # 依赖关系
tags: # Runner 标签
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

# 受保护变量(在 GitLab UI 中设置)
# Settings → CI/CD → Variables
# 勾选 Protected 和 Masked

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
# rules 语法
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

# only/except 语法
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 # 或 finish

# 包含其他配置文件
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
# 使用 dind 服务
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

# Dockerfile 示例
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
# 创建 Service Account
kubectl create namespace gitlab
kubectl create serviceaccount gitlab-deployer -n gitlab

# 绑定权限
kubectl create clusterrolebinding gitlab-deployer \
--clusterrole=cluster-admin \
--serviceaccount=gitlab:gitlab-deployer

# 获取 Token
kubectl get secret $(kubectl get serviceaccount gitlab-deployer -n gitlab -o jsonpath='{.secrets[0].name}') -n gitlab -o jsonpath='{.data.token}' | base64 -d

# 在 GitLab 中设置变量
# Settings → CI/CD → Variables
# KUBE_CONTEXT: production
# KUBE_NAMESPACE: myapp
# KUBE_TOKEN: <上面获取的 token>
# KUBE_CA_CERT: <k8s CA 证书>

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
# 使用 GitLab Variables(加密存储)
# Settings → CI/CD → Variables
# 勾选:Protected, Masked

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
# 限制 Runner 权限
[[runners]]
executor = "docker"
[runners.docker]
privileged = false
disable_cache = false
cap_drop = ["ALL"]
cap_add = ["NET_BIND_SERVICE"]

# 使用受保护的分支
# Settings → Repository → Protected Branches
# main: Maintainers + Allowed to merge
# develop: Developers + Maintainers

# 使用受保护的标签
# Settings → Repository → Protected Tags

8.3 安全扫描

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 包含 GitLab 安全模板
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
# GitLab 内置监控
# Admin → Monitoring → Metrics

# Prometheus 端点
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

# Runner 日志
journalctl -u gitlab-runner -f

# 日志轮转
# /etc/gitlab/gitlab.rb
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
# /etc/gitlab/gitlab.rb

# Puma 配置
puma['worker_processes'] = 4
puma['worker_timeout'] = 60

# Sidekiq 配置
sidekiq['max_concurrency'] = 20
sidekiq['job_timeout'] = 60

# PostgreSQL 配置
postgresql['shared_buffers'] = "256MB"
postgresql['max_connections'] = 400

# Redis 配置
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-backup.sh

# 备份
/opt/gitlab/bin/gitlab-backup create

# 清理 7 天前的备份
find /var/opt/gitlab/backups -name "*.tar" -mtime +7 -delete

# 同步到远程存储
rsync -avz /var/opt/gitlab/backups/ backup-server:/backup/gitlab/

# crontab
0 2 * * * /opt/gitlab-backup.sh

文档版本: 1.0
最后更新: 2026-02-27
适用版本: GitLab 15.x+, GitLab Runner 15.x+