CI/CD流水线:GitHub Actions,GitLab CI
CI/CD流水线: GitHub Actions,GitLab CI
1) CI/CD任务和平台位置
CI/CD是从存储库到工作环境的连续组装,测试和交付更改。目标是:- 发行速度和可预测性(短时间领先)。
- 质量(自动测试,静态/动态分析)。
- 供应链安全(文物签名,出入控制)。
- 可靠性(加那利群岛,快速回滚)。
- 可观察性(每个阶段的跟踪和度量)。
关键原则是:"pipeline as code",固定工件,"build once-run many","shift-left security","least privilege",确定性组件。
2)输送机的建筑模式
Stage-gate: build → test → security → package → deploy → post-deploy checks.
Fan-out/Fan-in:并行矩阵集合(语言/平台)与结果组合。
Promotion:相同的人工制品通过周围环境(dev → stage → prod)前进而不是越过。
基于Trunk+的短分支:最大限度地减少漂移,自动检查公关/MR。
可重复性: 重新使用的工作流/模式(行动:可重复的工作流;GitLab: includes/child-pipelines).
GitOps(可选):拆分"装配"和"交付"(Argo CD/Flux监控环境声明回购)。
3)供应链安全(供应链)
识别:从跑步者到云的OIDC联盟(没有长寿密钥)。
秘密:集中存储,上下文限制,禁止撤回日志。
工件/容器签名(cosign/Sigstore),在管理控制中验证签名。
SBOM(CycloneDX/SPDX)和SCA,SAST/DAST/Container Scan是"必修门"。
政策:OPA/Conftest for IaC/manifests,"no latest",禁止特权容器。
隔离跑步者:在私人网络中启动跑步者,将出站访问与公共互联网分开。
4) GitHub Actions-结构和实践
4.1工作流结构
`.github/workflows/.yml` — триггеры (`on: push, pull_request, schedule, workflow_call`).
用于标准化的Reusable workflows(linter,SCA,容器装配,deploy)。
4.2示例:带有OIDC和映像签名的多阶段管线
yaml name: ci-cd
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
permissions:
id-token: write # для OIDC contents: read packages: write
jobs:
build_test_matrix:
runs-on: ubuntu-latest strategy:
matrix:
node: [18, 20]
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4 with: { node-version: ${{ matrix. node }} }
- name: Cache npm uses: actions/cache@v4 with:
path: ~/.npm key: npm-${{ runner. os }}-${{ matrix. node }}-${{ hashFiles('/package-lock. json') }}
- run: npm ci
- run: npm run lint && npm test -- --ci
docker_build_sign:
runs-on: ubuntu-latest needs: build_test_matrix steps:
- uses: actions/checkout@v4
- name: Login to GHCR uses: docker/login-action@v3 with:
registry: ghcr. io username: ${{ github. actor }}
password: ${{ secrets. GITHUB_TOKEN }}
- name: Build image run:
docker build --pull --no-cache -t ghcr. io/org/app:${{ github. sha }}.
docker push ghcr. io/org/app:${{ github. sha }}
- name: Generate SBOM uses: anchore/syft-action@v0 with:
image: ghcr. io/org/app:${{ github. sha }}
format: cyclonedx-json output-file: sbom. json
- name: Cosign sign (OIDC)
uses: sigstore/cosign-installer@v3
- name: Sign image run:
cosign sign ghcr. io/org/app:${{ github. sha }} \
--yes \
--identity-token $ACTIONS_ID_TOKEN_REQUEST_TOKEN \
--rekor-url https://rekor. sigstore. dev
deploy_stage:
runs-on: ubuntu-latest needs: docker_build_sign environment:
name: stage url: https://stage. example. com steps:
- uses: actions/checkout@v4
- name: Assume cloud role via OIDC uses: aws-actions/configure-aws-credentials@v4 with:
role-to-assume: arn:aws:iam::123456789012:role/github-deployer aws-region: eu-central-1
- name: Helm deploy (canary 10%)
run:
helm upgrade --install app charts/app \
--set image. tag=${{ github. sha }} \
--set canary. enabled=true --set canary. traffic=10
- name: Smoke checks run:./scripts/smoke. sh
promote_prod:
runs-on: ubuntu-latest needs: deploy_stage environment:
name: production url: https://app. example. com concurrency: prod-release steps:
- name: Manual approval gate run: echo "Requires environment approvers in repo settings"
- name: Promote canary → 100% (blue-green)
run:
helm upgrade --install app charts/app \
--set image. tag=${{ github. sha }} \
--set canary. enabled=false
- name: Post-deploy checks & rollback on SLO breach run:./scripts/verify_or_rollback. sh
钥匙:
- "permissions"被最小化,包括OIDC的"id-token: write"。
- 具有approvers和URL的环境"concurrency"可以防止比赛。
- 金丝雀交通启用和SLO自动回滚。
4.3 Reusable工作流(呼叫示例)
yaml jobs:
security_suite:
uses: org/.github/.github/workflows/security. yml@v1 with:
severity_threshold: high
5) GitLab CI-结构和实践
5.1基本结构
`.gitlab-ci.yml"根本;关键实体:"stages","jobs","rules","needs","artifacts","environments","manual"。
Reuse: 'include:'(本地/远程模板),儿童/母公司管道,用于复杂的monocrepo。
5.2示例:矩阵、缓存、签名、环境和approvals
yaml stages: [lint, test, build, security, deploy]
variables:
DOCKER_TLS_CERTDIR: "" # docker: dind acceleration
IMAGE_TAG: $CI_COMMIT_SHA
lint:
stage: lint image: node:20 script:
- npm ci
- npm run lint cache:
key: "npm-${CI_COMMIT_REF_SLUG}"
paths: [node_modules/]
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
test:
stage: test image: node:20 parallel:
matrix:
- NODE_VERSION: ["18", "20"]
script:
- nvm install $NODE_VERSION true
- npm ci
- npm test -- --ci artifacts:
when: always reports:
junit: report. xml
build_image:
stage: build image: docker:26. 1 services: [ "docker:26. 1-dind" ]
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE:$IMAGE_TAG.
- docker push $CI_REGISTRY_IMAGE:$IMAGE_TAG artifacts:
expire_in: 1 week paths: [ "sbom. json" ]
after_script:
- syft $CI_REGISTRY_IMAGE:$IMAGE_TAG -o cyclonedx-json > sbom. json
security_scans:
stage: security image: alpine:3. 20 script:
- trivy image --exit-code 0 --severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:$IMAGE_TAG rules:
- if: '$CI_COMMIT_BRANCH == "main"'
deploy_stage:
stage: deploy image: bitnami/kubectl:1. 30 environment:
name: stage url: https://stage. example. com on_stop: stop_stage script:
- kubectl set image deploy/app app=$CI_REGISTRY_IMAGE:$IMAGE_TAG -n stage
-./scripts/smoke. sh needs: [build_image, security_scans]
when: manual allow_failure: false
stop_stage:
stage: deploy image: bitnami/kubectl:1. 30 environment:
name: stage action: stop script:
- kubectl rollout undo deploy/app -n stage
deploy_prod:
stage: deploy image: alpine/k8s:1. 30. 2 environment:
name: production url: https://app. example. com rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: manual allow_failure: false script:
-./scripts/canary_traffic. sh 10
-./scripts/verify_or_rollback. sh
钥匙:
- `parallel.matrix"模彷矩阵组件。
- 'artifacts'+测试报告。
- Environments带有"on_stop",手动的"when:manual"用于approvals。
- 用于映像组装的DIND(最好是k8s runner中的Kaniko/BuildKit)。
5.3儿童管道和include for monorepo
yaml include:
- local:.gitlab/ci/includes/security. yml
- project: org/platform/pipelines file: /k8s/deploy. yml ref: v1
stages: [prepare, component_a, component_b, deploy]
component_a:
stage: component_a trigger:
include:.gitlab/ci/component_a. yml strategy: depend
component_b:
stage: component_b trigger:
include:.gitlab/ci/component_b. yml strategy: depend
6)单存储和多服务
基于目录的ownership:CODEOWNERS和scoped路径测试。
Incremental builds:定义受影响的软件包/图表;路径密钥缓存和锁定文件。
Dynamic pipelines: child-pipelines /'workflow_call'仅针对修改后的组件运行。
转化:每个模块的semver,发布阶段的changelog。
7)缓存和加速
内容地址缓存(hashFiles/lockfile)。
依赖项和工件的分离缓存。
Pre-warm runner images (toolchains, SDK).
本地数据包镜像(npm/pip/maven)和容器注册表。
8)发布策略和回滚
金丝雀:逐步增加流量百分比;SLO降解时的自动停止。
Blue-Green:并行堆栈,即时切换。
影子:不影响客户端的重复请求。
Feature flags:在标志级别而不是版本上滚动。
Rollback:一键清晰脚本,工件版本存储在发布元数据中。
9)基础设施和GitOps
IaC:Terraform/Ansible/Helm在单独的回购中管理;policy-as-code作为大门。
GitOps轮廓:Argo CD/Flux用随行人员清单观看回购;流水线仅在Git中创建工件并更新版本。
优点:环境变化的明确历史,等效性,标准回滚通过Git。
10)CI/CD可观察性
DORA度量:去重播频率,从商品到生产时间,故障百分比,MTTR。
Telemetry:工作队列时间,阶段持续时间,高速缓存命中率,flaky测试频率。
安全日志:谁启动了发布,通过了哪些大门,发布了哪些例外。
11)访问控制和approvals
分支保护和强制性检查。
Environment-approvals: stage/prod上的单独的approvers列表。
手动步骤的JIT访问,会话日志。
职责分工:"编写代码","批准","发布"的不同角色。
12)经常出错(反模式)
长寿的云密钥是回购秘密而不是OIDC角色。
为舞台和舞台(违反"build once")组装不同的工件。
"最新"标签和可变图像。
在步骤日志中发布秘密(未合并的掩码)。
Prod Deploe的一个通用公共跑步者。
没有"门户"安全性(SAST/SCA/Policy)和部署后检查。
13)实施清单(0-60天)
0-15天
配置基于trunk, PR/MR的规则,强制静态检查。
在云中启用OIDC联盟;最小的"permissions"。
分开runner's:公共为CI,私人为CD。
16-30天
添加SBOM,映像签名;群集-签名验证。
引入金丝雀/蓝绿色;SLO上的自动回滚。
依赖项和工件缓存,预扭曲映像。
31-60天
拆分装配和交付(GitOps),策略即代码门。
建立DORA度量标准和Alerta piplines降解。
为所有服务模板化pipline (reusable/child)。
14)实用可靠性提示
支持小型、快速的管线(公关信号前10-12分钟)。
杀死flaky测试:quarantine标签+并行小玩意。
不要溷合CI文物和释放文物;存储元数据(commit、时间、SBOM、签名)。
为开发人员提供与传送带步骤相同的本地脚本(dev-prod parity)。
15)重新使用模板
15.1 GitHub Actions-安全可重复的工作流(简化)
yaml name: security-suite on:
workflow_call:
inputs:
severity_threshold:
type: string required: false default: high jobs:
sast_sca:
runs-on: ubuntu-latest steps:
- uses: actions/checkout@v4
- run:./sec/sast. sh --threshold ${{ inputs. severity_threshold }}
- run:./sec/sca. sh --format cyclonedx-json --out sbom. json artifacts: # if using actions/upload-artifact
- sbom. json
15.2 GitLab-包含的deploy模板(简化)
yaml
.deployment_template:
image: alpine/k8s:1. 30 script:
- helm upgrade --install $APP charts/$APP --set image. tag=$IMAGE_TAG rules:
- if: '$CI_COMMIT_BRANCH == "main"'
16)结论
GitHub Actions和GitLab CI提供了成熟的机制,可快速安全地进行"pr → od代码"循环。成功的关键是标准化和安全性:OIDC代替钥匙,签名和SBOM,质量门,具有晋升的单个人工制品,GitOps交付以及通过DORA的可观察性。将管线构建为产品:测量,简化,加速-发行版将成为例行公事而不是事件。