- Published on
高度なCI/CDパイプライン構築ガイド — GitHub Actions、ArgoCD、Tekton、セキュリティパイプライン
- Authors

- Name
- Youngju Kim
- @fjvbn20031
はじめに
CI/CDを「コードをプッシュしたら自動でデプロイされるもの」程度に理解している段階を超え、プロダクションレベルのパイプラインとは何かを考えたことがあるだろうか。実際のプロダクション環境では、セキュリティスキャン、静的解析、コンテナイメージ署名、マルチクラスタデプロイ、自動ロールバックまで数十のステージが有機的に連携する必要がある。
本記事では、CI/CD成熟度モデルからGitHub Actionsの高度なパターン、ArgoCD GitOps、Tektonクラウドネイティブパイプライン、DevSecOpsセキュリティパイプライン、デプロイ戦略の深掘りまで包括的に解説する。
1. CI/CD成熟度モデル
組織のCI/CDレベルを客観的に評価するための5段階成熟度モデルである。各レベルは前のレベルの能力の上に構築される。
Level 1 - 手動 (Manual)
ビルドとデプロイを開発者が手動で実行する段階。ローカルでビルドし、FTPやSCPでサーバーに直接デプロイする。「自分のマシンでは動くのに」が日常的に発生し、デプロイサイクルは月単位であることが多い。
特徴: ドキュメント化された手順は存在するかもしれないが、自動化はほとんどない。デプロイ時のヒューマンエラーが頻繁で、ロールバックは前のバージョンを手動で再デプロイする方式である。
Level 2 - 基本自動化 (Basic Automation)
CIサーバーが導入され、コードプッシュ時に自動ビルドとテストが実行される。Jenkins、GitHub Actions、GitLab CIなどのツールを使用するが、パイプラインは単純なビルド-テスト-デプロイの直線構造である。
# Level 2: 基本パイプライン例
name: Basic CI/CD
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm install
- run: npm test
- run: npm run build
- run: ./deploy.sh
Level 3 - 標準化 (Standardized)
パイプラインが組織全体で標準化され、再利用可能なパイプラインテンプレートが存在する。テストカバレッジゲート、コード品質チェック、セキュリティスキャンがデフォルトで含まれる。環境別(dev、staging、prod)のデプロイパイプラインが分離されている。
Level 4 - 高度な自動化 (Advanced Automation)
GitOpsベースの宣言的デプロイ、カナリア/ブルーグリーンデプロイ戦略、自動化されたセキュリティパイプライン(SAST、DAST、コンテナスキャン)、SBOM生成とアーティファクト署名がパイプラインに統合される。デプロイサイクルは日単位以下に短縮される。
Level 5 - 自己修復 (Self-Healing)
メトリクスベースの自動ロールバック、SLO違反時の自動復旧、MLベースの異常検知、プロダクションフィードバックがパイプラインに自動反映される。デプロイが完全に自動化され、開発者がデプロイを意識しない。
| レベル | デプロイサイクル | ロールバック方式 | セキュリティ | テスト |
|---|---|---|---|---|
| L1 手動 | 月単位 | 手動再デプロイ | なし | 手動 |
| L2 基本 | 週単位 | 手動トリガー | なし | 自動ユニット |
| L3 標準 | 日単位 | ワンクリック | 基本スキャン | ユニット+結合 |
| L4 高度 | 時間単位 | 自動カナリア | 全パイプライン | ユニット+結合+E2E |
| L5 修復 | 継続的デプロイ | SLOベース自動 | 継続的検証 | カオス含む |
2. GitHub Actionsの高度なパターン
GitHub Actionsの基本を超える高度なパターンを解説する。
2-1. 再利用可能なワークフロー (Reusable Workflows)
複数のリポジトリで同一のパイプラインロジックを共有するには、再利用可能なワークフローを活用する。呼び出し側ではusesキーワードで外部ワークフローを参照する。
# .github/workflows/reusable-build.yml(共有リポジトリ)
name: Reusable Build
on:
workflow_call:
inputs:
node-version:
required: false
type: string
default: '20'
registry-url:
required: true
type: string
secrets:
npm-token:
required: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
registry-url: ${{ inputs.registry-url }}
- run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.npm-token }}
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: build-output
path: dist/
# 呼び出しワークフロー
name: App CI
on: [push]
jobs:
call-build:
uses: my-org/shared-workflows/.github/workflows/reusable-build.yml@v2
with:
node-version: '20'
registry-url: 'https://npm.pkg.github.com'
secrets:
npm-token: ${{ secrets.NPM_TOKEN }}
2-2. Composite Actions
一つのアクション内に複数のステップをまとめて再利用するパターンである。再利用可能なワークフローと異なり、単一ジョブのステップとして挿入される。
# .github/actions/setup-and-test/action.yml
name: 'Setup and Test'
description: 'Node.js環境セットアップ後テスト実行'
inputs:
node-version:
description: 'Node.js version'
required: false
default: '20'
runs:
using: 'composite'
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: 'npm'
- run: npm ci
shell: bash
- run: npm test -- --coverage
shell: bash
- uses: actions/upload-artifact@v4
with:
name: coverage
path: coverage/
2-3. マトリクスビルド戦略
複数の環境の組み合わせを並列でテストしつつ、不要な組み合わせを除外する高度なマトリクス設定である。
jobs:
test:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node: [18, 20, 22]
exclude:
- os: macos-latest
node: 18
include:
- os: ubuntu-latest
node: 22
experimental: true
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.experimental || false }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
- run: npm ci
- run: npm test
2-4. OIDCによるクラウド認証
長期シークレット(Access Key)の代わりにOIDC(OpenID Connect)トークンを使用してクラウドに安全に認証する方式である。AWS、GCP、Azureすべてに対応している。
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/github-actions-role
aws-region: ap-northeast-1
- run: aws s3 sync ./dist s3://my-bucket
- run: aws cloudfront create-invalidation --distribution-id E1234 --paths "/*"
OIDCの最大のメリットはシークレット管理が不要になることである。GitHubが発行した短期トークンをAWS STSが検証し、一時的な認証情報を発行する。トークンはワークフロー実行中のみ有効であり、漏洩しても悪用が困難である。
3. GitOpsとArgoCD
3-1. GitOpsの原則
GitOpsはGitを単一の真実の源(Single Source of Truth)として使用し、インフラストラクチャとアプリケーションの宣言的な状態を管理する運用モデルである。4つのコア原則がある。
宣言的設定: システムの望ましい状態を宣言的に記述する。「何を」望むかを定義し、「どのように」達成するかを命令しない。
Gitを真実の源として: すべての変更はGitを通じて行われ、Git履歴がそのまま監査ログとなる。
自動適用: Gitの宣言的状態が変更されると、自動的にシステムに適用される。
継続的調整: エージェントが実際の状態と望ましい状態を継続的に比較し、差分(ドリフト)を修正する。
3-2. ArgoCDアーキテクチャ
ArgoCDはKubernetes向けの宣言的GitOps継続的デリバリーツールである。
# ArgoCD Applicationリソース
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/my-org/k8s-manifests.git
targetRevision: main
path: apps/my-app/overlays/production
destination:
server: https://kubernetes.default.svc
namespace: my-app
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
retry:
limit: 5
backoff:
duration: 5s
factor: 2
maxDuration: 3m
syncPolicy.automatedを設定すると、Gitの変更が自動的にクラスタに反映される。selfHeal: trueは、誰かが手動でクラスタの状態を変更しても、自動的にGitの状態に復元する機能である。
3-3. App of Appsパターン
大規模環境では数十から数百のApplicationを管理する必要がある。App of Appsパターンは、一つのルートApplicationが他のすべてのApplicationを管理する構造である。
# root-app.yaml - 他のApplicationを管理するルート
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/my-org/argocd-apps.git
targetRevision: main
path: apps
destination:
server: https://kubernetes.default.svc
namespace: argocd
# apps/frontend.yaml - ルートが管理する子Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: frontend
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/my-org/k8s-manifests.git
path: apps/frontend/overlays/production
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: frontend
3-4. ApplicationSetによるマルチクラスタデプロイ
ApplicationSetは一つのテンプレートから複数のApplicationを自動生成するArgoCDの機能である。クラスタリスト、Gitディレクトリ、PRイベントなどに基づいて動的に生成する。
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
name: my-app-set
namespace: argocd
spec:
generators:
- clusters:
selector:
matchLabels:
env: production
template:
metadata:
name: 'my-app-{{name}}'
spec:
project: default
source:
repoURL: https://github.com/my-org/k8s-manifests.git
targetRevision: main
path: 'apps/my-app/overlays/{{metadata.labels.region}}'
destination:
server: '{{server}}'
namespace: my-app
4. Tekton Pipelines
4-1. Tektonとは
TektonはKubernetesネイティブのCI/CDフレームワークである。GitHub ActionsやJenkinsと異なり、パイプラインのすべてのコンポーネントがKubernetesカスタムリソース(CRD)として定義される。各タスクが別々のPodとして実行されるため、完全な分離とスケーラビリティを提供する。
コアコンポーネント:
- Task: 一つ以上のStepで構成される実行単位。Pod一つにマッピングされる。
- Pipeline: 複数のTaskを接続したDAG(有向非巡回グラフ)構造のワークフロー。
- TaskRun / PipelineRun: TaskやPipelineの実行インスタンス。Kubernetesリソースとして追跡可能。
- Workspace: Task間のデータ共有のためのボリューム。
4-2. Taskの定義
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: build-and-push
spec:
params:
- name: image-url
type: string
- name: image-tag
type: string
default: latest
workspaces:
- name: source
steps:
- name: build
image: gcr.io/kaniko-project/executor:latest
args:
- --dockerfile=Dockerfile
- --context=$(workspaces.source.path)
- --destination=$(params.image-url):$(params.image-tag)
- --cache=true
- --cache-ttl=24h
4-3. Pipelineの定義
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: ci-pipeline
spec:
params:
- name: repo-url
type: string
- name: image-url
type: string
workspaces:
- name: shared-workspace
tasks:
- name: fetch-source
taskRef:
name: git-clone
workspaces:
- name: output
workspace: shared-workspace
params:
- name: url
value: $(params.repo-url)
- name: run-tests
taskRef:
name: npm-test
runAfter:
- fetch-source
workspaces:
- name: source
workspace: shared-workspace
- name: build-image
taskRef:
name: build-and-push
runAfter:
- run-tests
workspaces:
- name: source
workspace: shared-workspace
params:
- name: image-url
value: $(params.image-url)
- name: security-scan
taskRef:
name: trivy-scan
runAfter:
- build-image
params:
- name: image-url
value: $(params.image-url)
4-4. PipelineRunで実行
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
generateName: ci-pipeline-run-
spec:
pipelineRef:
name: ci-pipeline
params:
- name: repo-url
value: https://github.com/my-org/my-app.git
- name: image-url
value: ghcr.io/my-org/my-app
workspaces:
- name: shared-workspace
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
5. セキュリティパイプライン(DevSecOps)
5-1. セキュリティパイプラインの構成要素
プロダクションレベルのセキュリティパイプラインは、以下のステージを自動的に実行する。
| ステージ | ツール | 目的 |
|---|---|---|
| SAST(静的解析) | SonarQube, Semgrep, CodeQL | ソースコードの脆弱性検出 |
| SCA(依存関係解析) | Snyk, Dependabot, OWASP DC | OSS依存関係の脆弱性検出 |
| シークレットスキャン | GitLeaks, TruffleHog | コードに含まれる秘密情報の検出 |
| コンテナスキャン | Trivy, Grype | コンテナイメージの脆弱性検出 |
| DAST(動的解析) | OWASP ZAP, Nuclei | 実行中アプリケーションの脆弱性検出 |
| SBOM生成 | Syft, CycloneDX | ソフトウェア構成要素リストの生成 |
| アーティファクト署名 | Cosign, Notation | ビルドアーティファクトの完全性保証 |
5-2. SAST - SonarQubeの統合
# GitHub ActionsでのSonarQube解析
name: Security Pipeline
on: [push, pull_request]
jobs:
sast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: SonarSource/sonarqube-scan-action@v3
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
with:
args: >
-Dsonar.projectKey=my-project
-Dsonar.sources=src/
-Dsonar.tests=tests/
-Dsonar.coverage.exclusions=**/*.test.ts
- uses: SonarSource/sonarqube-quality-gate-check@v1
timeout-minutes: 5
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
5-3. コンテナイメージスキャン - Trivy
container-scan:
runs-on: ubuntu-latest
needs: [build]
steps:
- uses: aquasecurity/trivy-action@master
with:
image-ref: 'ghcr.io/my-org/my-app:latest'
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
exit-code: '1'
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: 'trivy-results.sarif'
TrivyはOSパッケージと言語固有の依存関係の両方をスキャンする。exit-code: '1'を設定すると、CRITICALまたはHIGHの脆弱性が検出された場合にパイプラインが失敗する。
5-4. SBOM生成とCosign署名
SBOM(Software Bill of Materials)はソフトウェアに含まれるすべてのコンポーネントのリストである。米国大統領令14028以降、サプライチェーンセキュリティの必須要素となった。
sbom-and-sign:
runs-on: ubuntu-latest
needs: [container-scan]
permissions:
id-token: write
packages: write
steps:
- name: Generate SBOM
uses: anchore/sbom-action@v0
with:
image: ghcr.io/my-org/my-app:latest
format: spdx-json
output-file: sbom.spdx.json
- name: Install Cosign
uses: sigstore/cosign-installer@v3
- name: Sign Container Image
run: |
cosign sign --yes \
ghcr.io/my-org/my-app:latest
- name: Attach SBOM to Image
run: |
cosign attach sbom \
--sbom sbom.spdx.json \
ghcr.io/my-org/my-app:latest
CosignはSigstoreプロジェクトの一部で、キーレス(keyless)署名をサポートする。OIDCトークンを使用して、別途の署名鍵管理なしにイメージに署名できる。
5-5. シークレットスキャン - GitLeaks
secret-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6. テスト自動化戦略
6-1. テストピラミッド
プロダクションCI/CDでは、テストの種類と比率が重要である。
ユニットテスト(70%): 最も高速で最も多くあるべきテスト。個別の関数、メソッド、コンポーネントを分離テストする。
結合テスト(20%): 複数のモジュールが連携して正しく動作することを検証する。DB、API、メッセージキューなど外部依存関係との相互作用をテストする。
E2Eテスト(10%): ユーザーシナリオを最初から最後まで検証する。最も遅く不安定であるため、コアフローのみテストする。
6-2. 並列テストとテスト分割
大規模テストスイートの実行時間を短縮するための戦略である。
jobs:
test:
strategy:
matrix:
shard: [1, 2, 3, 4]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- name: Run Tests (Shard ${{ matrix.shard }}/4)
run: |
npx jest --shard=${{ matrix.shard }}/4 \
--ci --coverage --forceExit
- uses: actions/upload-artifact@v4
with:
name: coverage-${{ matrix.shard }}
path: coverage/
merge-coverage:
needs: [test]
runs-on: ubuntu-latest
steps:
- uses: actions/download-artifact@v4
with:
pattern: coverage-*
merge-multiple: true
- name: Merge Coverage Reports
run: npx istanbul-merge --out merged-coverage.json coverage-*/coverage-final.json
6-3. Playwright E2Eテスト
e2e:
runs-on: ubuntu-latest
needs: [deploy-staging]
steps:
- uses: actions/checkout@v4
- run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run E2E Tests
run: npx playwright test --reporter=html
env:
BASE_URL: https://staging.my-app.com
- uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-report
path: playwright-report/
7. デプロイ戦略の深掘り
7-1. Argo Rolloutsによるカナリアデプロイ
Argo RolloutsはKubernetesで高度なデプロイ戦略を実装するコントローラである。標準のDeploymentを置き換えるRolloutリソースを提供する。
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app
spec:
replicas: 10
strategy:
canary:
canaryService: my-app-canary
stableService: my-app-stable
trafficRouting:
istio:
virtualServices:
- name: my-app-vsvc
routes:
- primary
steps:
- setWeight: 5
- pause:
duration: 5m
- setWeight: 20
- pause:
duration: 5m
- setWeight: 50
- pause:
duration: 10m
- setWeight: 80
- pause:
duration: 5m
analysis:
templates:
- templateName: success-rate
startingStep: 2
args:
- name: service-name
value: my-app-canary
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: ghcr.io/my-org/my-app:v2.0.0
ports:
- containerPort: 8080
7-2. AnalysisTemplate - メトリクスベースの自動判断
カナリアデプロイ中にPrometheusメトリクスを照会し、自動的にプロモート(昇格)またはアボート(ロールバック)を判断する。
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: success-rate
spec:
args:
- name: service-name
metrics:
- name: success-rate
interval: 60s
successCondition: result[0] >= 0.95
failureLimit: 3
provider:
prometheus:
address: http://prometheus.monitoring:9090
query: |
sum(rate(http_requests_total{
service="{{args.service-name}}",
status=~"2.."
}[5m])) /
sum(rate(http_requests_total{
service="{{args.service-name}}"
}[5m]))
成功率が95%未満の解析が3回連続で発生すると、自動的にロールバックする。これがLevel 5自己修復パイプラインの核心である。
7-3. ブルーグリーンデプロイ
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: my-app-bluegreen
spec:
replicas: 5
strategy:
blueGreen:
activeService: my-app-active
previewService: my-app-preview
autoPromotionEnabled: false
prePromotionAnalysis:
templates:
- templateName: smoke-test
postPromotionAnalysis:
templates:
- templateName: success-rate
scaleDownDelaySeconds: 300
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: ghcr.io/my-org/my-app:v2.0.0
ブルーグリーンデプロイでは、新バージョン(グリーン)が完全に準備された後、トラフィックを一度に切り替える。prePromotionAnalysisで切り替え前にスモークテストを実行し、scaleDownDelaySecondsで旧バージョンを一定時間維持して迅速なロールバックを可能にする。
7-4. トラフィックミラーリング(シャドウトラフィック)
実際のプロダクショントラフィックを新バージョンに複製して実際の負荷でテストするが、新バージョンのレスポンスはユーザーに配信しない方式である。
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: my-app
spec:
hosts:
- my-app.example.com
http:
- route:
- destination:
host: my-app-stable
port:
number: 80
mirror:
host: my-app-canary
port:
number: 80
mirrorPercentage:
value: 100.0
8. マルチ環境管理
8-1. 環境構造の設計
プロダクションパイプラインは最低3つの環境を運用する。
- dev: 開発者のfeatureブランチデプロイ。不安定でも問題ない。
- staging: mainブランチデプロイ。プロダクションと同一の設定でなければならない。
- production: 実際のユーザートラフィックを処理する環境。
8-2. Kustomize Overlays
KustomizeはKubernetesマニフェストを環境ごとにカスタマイズするツールである。ベース設定の上に環境別のオーバーレイを適用する。
k8s/
base/
deployment.yaml
service.yaml
kustomization.yaml
overlays/
dev/
kustomization.yaml
replica-patch.yaml
staging/
kustomization.yaml
replica-patch.yaml
production/
kustomization.yaml
replica-patch.yaml
hpa.yaml
# k8s/base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
# k8s/overlays/production/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
- hpa.yaml
patches:
- path: replica-patch.yaml
namePrefix: prod-
commonLabels:
env: production
# k8s/overlays/production/replica-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 5
template:
spec:
containers:
- name: my-app
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
8-3. Helm Valuesの環境別管理
# values-dev.yaml
replicaCount: 1
image:
tag: latest
resources:
requests:
cpu: 100m
memory: 128Mi
ingress:
host: dev.my-app.internal
autoscaling:
enabled: false
# values-production.yaml
replicaCount: 5
image:
tag: v2.0.0
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 1000m
memory: 1Gi
ingress:
host: my-app.example.com
tls: true
autoscaling:
enabled: true
minReplicas: 5
maxReplicas: 20
targetCPU: 70
# 環境ごとのデプロイ
helm upgrade --install my-app ./chart \
-f values-production.yaml \
--namespace production \
--wait --timeout 5m
9. モニタリングとロールバック
9-1. デプロイ後モニタリングチェックリスト
デプロイ直後に確認すべきコアメトリクスである。
即時確認(0〜5分):
- Podステータス:すべてのPodがRunning/Ready状態か
- エラーログ:新バージョンで例外が急増していないか
- ヘルスチェック:readiness/livenessプローブが正常か
短期確認(5〜30分):
- 応答時間:p50、p95、p99レイテンシが前バージョンと同等か
- エラー率:5xx比率が閾値以内か
- スループット:リクエスト処理量が予想範囲内か
中期確認(30分〜数時間):
- メモリ使用量:メモリリークの兆候がないか
- CPU使用量:CPU使用が安定しているか
- ビジネスメトリクス:注文数、コンバージョン率などが正常か
9-2. Prometheusベースの自動ロールバック
# PrometheusRule - 自動ロールバックトリガー
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: deployment-rollback-rules
spec:
groups:
- name: deployment-health
rules:
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))
> 0.05
for: 2m
labels:
severity: critical
action: rollback
annotations:
summary: "Error rate above 5 percent for 2 minutes"
- alert: HighLatency
expr: |
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket[5m])) by (le)
) > 2
for: 3m
labels:
severity: critical
action: rollback
annotations:
summary: "p99 latency above 2 seconds for 3 minutes"
9-3. SLOベースのデプロイゲート
サービスレベル目標(SLO)をデプロイ判断の基準として活用する。エラーバジェットが消耗した場合、デプロイを停止する戦略である。
# SLO定義例
apiVersion: sloth.slok.dev/v1
kind: PrometheusServiceLevel
metadata:
name: my-app-slo
spec:
service: my-app
labels:
team: platform
slos:
- name: requests-availability
objective: 99.9
sli:
events:
errorQuery: sum(rate(http_requests_total{status=~"5.."}[5m]))
totalQuery: sum(rate(http_requests_total[5m]))
alerting:
name: MyAppAvailability
pageAlert:
labels:
severity: critical
ticketAlert:
labels:
severity: warning
エラーバジェットの計算方法は以下の通りである。SLOが99.9%の場合、1ヶ月あたり約43分のダウンタイムが許容される。すでに30分を消耗している場合、残り13分のエラーバジェットではリスクの高いデプロイを進めるべきではない。
10. 実践:プロダクションパイプラインアーキテクチャ
10-1. 全体アーキテクチャ
プロダクションレベルの完全なCI/CDパイプラインは以下の構造を持つ。
開発者コードPush
|
v
[CIステージ - GitHub Actions]
|-- コードチェックアウト
|-- 依存関係インストール(キャッシュ活用)
|-- リント + フォーマットチェック
|-- ユニットテスト(並列4シャード)
|-- 結合テスト
|-- SAST(SonarQube)
|-- シークレットスキャン(GitLeaks)
|-- 依存関係脆弱性スキャン(Snyk)
|-- コンテナビルド(Kaniko)
|-- コンテナスキャン(Trivy)
|-- SBOM生成(Syft)
|-- イメージ署名(Cosign)
|-- イメージレジストリPush
|
v
[CDステージ - ArgoCD / GitOps]
|-- マニフェストリポジトリ自動更新
|-- ArgoCD同期
|-- dev環境自動デプロイ
|-- staging環境自動デプロイ
|-- E2Eテスト(Playwright)
|-- DAST(OWASP ZAP)
|
v
[プロダクションデプロイ - Argo Rollouts]
|-- カナリア5%デプロイ
|-- メトリクス分析(AnalysisTemplate)
|-- カナリア20%増加
|-- 再分析
|-- カナリア50%増加
|-- 最終分析
|-- 100%プロモーションまたは自動ロールバック
|
v
[モニタリング - Prometheus / Grafana]
|-- SLOダッシュボード
|-- エラーバジェット追跡
|-- 自動ロールバックアラート
10-2. パイプライン最適化のコツ
キャッシュ戦略: 依存関係インストール、Dockerレイヤー、テスト結果をキャッシュすることで、パイプライン時間を50%以上短縮できる。
- uses: actions/cache@v4
with:
path: |
~/.npm
node_modules
key: deps-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
deps-
条件付き実行: 変更されたファイルに応じて関連するタスクのみ実行し、不要なビルドを防止する。
- uses: dorny/paths-filter@v3
id: changes
with:
filters: |
backend:
- 'src/api/**'
- 'src/models/**'
frontend:
- 'src/components/**'
- 'src/pages/**'
infra:
- 'terraform/**'
- 'k8s/**'
並列化: 独立したタスクは並列に実行する。リント、テスト、セキュリティスキャンは相互に依存しないため、同時実行が可能である。
10-3. パイプラインメトリクス
パイプライン自体のパフォーマンスも測定する必要がある。
| メトリクス | 説明 | 目標 |
|---|---|---|
| Lead Time | コミットからプロダクションデプロイまでの時間 | 1時間以下 |
| デプロイ頻度 | 1日のプロダクションデプロイ回数 | 日10回以上 |
| 変更失敗率 | デプロイ後のロールバック比率 | 5%以下 |
| MTTR | 障害発生後の復旧時間 | 30分以下 |
| パイプライン実行時間 | CI全体の所要時間 | 15分以下 |
| テストカバレッジ | コードカバレッジ比率 | 80%以上 |
これがDORAメトリクス(Lead Time、デプロイ頻度、変更失敗率、MTTR)の核心である。Eliteレベルのチームはこの4つのメトリクスすべてで最高ランクを達成する。
まとめ
CI/CDパイプラインは単純な自動化ツールではなく、ソフトウェアの品質と開発速度を決定する重要なインフラストラクチャである。本記事で取り上げた内容を要約すると以下の通りである。
- 成熟度モデルを基準に現在のレベルを把握せよ。 一度にLevel 5を目指さず、段階的に能力を構築せよ。
- 再利用可能なパイプラインを設計せよ。 GitHub Actionsの再利用可能なワークフローとComposite Actionsを活用して、組織全体のパイプラインを標準化せよ。
- GitOpsを導入せよ。 ArgoCDなどのツールで宣言的デプロイを実装すれば、監査証跡、自動復旧、一貫性をすべて確保できる。
- セキュリティをパイプラインに組み込め。 DevSecOpsは別のステージではなく、パイプラインのすべてのステージにセキュリティが溶け込むことである。
- メトリクスベースで意思決定せよ。 SLOとエラーバジェットを活用して、デプロイリスクを定量的に管理せよ。
- DORAメトリクスを追跡せよ。 パイプライン自体のパフォーマンスを継続的に改善せよ。
プロダクションレベルのCI/CDは一朝一夕に完成するものではない。しかし、各構成要素を理解し段階的に導入すれば、チームのデプロイ能力は確実に変わるだろう。