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的可觀察性。將管線構建為產品:測量,簡化,加速-發行版將成為例行公事而不是事件。