アセンブリの最適化とキャッシュ
(セクション: 技術とインフラ)
簡単な要約
iGamingのCI/CD速度は、ピーク負荷時のリリースレート、分コスト、およびp99安定性に直接影響します。キーは、正しいキャッシュ(依存関係、アーティファクト、コンテナ層、中間コンパイル結果)、増分ビルド、および決定性です。「良い」ビルドは変更されていない入力で素早く繰り返され、キャッシュ障害は予測可能で制御可能です。
1)キャッシュマップとキャッシュするもの
依存関係:NPM/pnpmパッケージ、pip wheels/Poetry、 Maven/Gradle、 Go mods、 Cargo crates、 NuGet。
中間コンパイル成果物:'~/。cache/pip'、 '~/。m2'、 '。gradle'、 '~/。cargo/registry/'、'$GOMODCACHE'、'target/'、 'build/'、' node_modules/。pnpm-store'。
コンテナレイヤー:Dockerレイヤーキャッシュ(BuildKit/GHAキャッシュ)、レジストリベースのキャッシュ、マルチステージ。
ツールとSDK:ツールチェーン/マイクロイメージ(JDK、ノード、Python、 Rustupターゲット)。
Mono/polyrepo-meta:タスクのNx/Turborepo/Bazelリモートキャッシュキャッシュ(lint/test/build)。
テストデータとe2e修正:UIバンドルによってコンパイルされたデータベーススナップショット。
ML/data:準備されたデータセット、埋め込み、コンパイルされたエンジン(TensorRT/ONNX)。
2)速く、予測可能なアセンブリの原則
1.確定性:バージョン(lockfiles)、ピンベースイメージ、密閉プラグイン→再現可能な出力を修正します。
2.Idempotence:同じアセンブリ→同じアーティファクトとハッシュ。
3.増分:変更されたもののみを再構築します(DAG/needs/matrix/affected)。
4.局所性と「熱」:ランナーの横/レジストリ内のキャッシュ、ピーク前にウォームアップ。
5.明示的な無効性:lockfile/configurationファイルとコンテンツハッシュによるキャッシュキー。
6.衛生:TTL/' expire_in'、自動クリーニング、キャッシュサイズ制御およびアーティファクト。
7.サプライチェーンセキュリティ:秘密のためのキャッシュ≠ゴミ箱;SBOM/アーティファクト署名は必須です。
3) Docker/OCI: 再構成のない速いイメージ
[パターン]
マルチステージ(ビルダー→ランタイム)。
最小ランタイム(distroless/ubi-micro、 so/ca-certsのみ必要)。
画層順序:最初はめったに変更(deps)、次にコード。
'。dockerignore': '。git'、テスト/フィクスチャ、ローカルキャッシュを除外します。
BuildKit: 'cache-from/to'→ジョブとブランチ間の共有キャッシュ。
Dockerfileの例(Node+pnpm)
dockerfile syntax=docker/dockerfile:1.7
FROM node:20-bookworm AS deps
WORKDIR /app
COPY pnpm-lock.yaml./
RUN corepack enable && pnpm fetch
FROM node:20-bookworm AS builder
WORKDIR /app
COPY --from=deps /root/.cache/pnpm /root/.cache/pnpm
COPY package.json pnpm-lock.yaml./
RUN corepack enable && pnpm install --offline
COPY..
RUN pnpm build
FROM gcr.io/distroless/nodejs20 AS runtime
WORKDIR /app
COPY --from=builder /app/dist./dist
USER 10001
CMD ["dist/server.js"]
BuildKit-CI (GitHubアクション)
yaml
- uses: docker/setup-buildx-action@v3
- uses: actions/cache@v4 with:
path: /tmp/.buildx-cache key: buildx-${{ github.ref }}-${{ github.sha }}
restore-keys: buildx-${{ github.ref }}-
- uses: docker/build-push-action@v6 with:
push: true tags: ${{ env.IMAGE }}
cache-from: type=gha cache-to: type=gha,mode=max
4)言語エコシステム: キャッシュするものとどのように
Java/Kotlin (Maven/Gradle)
リモートキャッシュグラドル、並行性、コンフィギュレーションオンデマンド。
キャッシュキー:hash 'build。gradle [。kts]'+lockfiles+'gradle-wrapper。プロパティ'。
ビルドキャッシュノードをオブジェクトストレージ/HTTPにパブリッシュします。
インクリメンタルコンパイルとテストをパッケージごとに分割します。
yaml
GitLab CI cache:
key: gradle-${CI_COMMIT_REF_SLUG}
paths: [.gradle/caches,.gradle/wrapper ]
script:
-./gradlew --build-cache --parallel build
ノード。js (npm/pnpm/yarn)
ローカルストアキャッシュ('~/。npm'、 '~/。cache/pnpm')、 lockfileキー。
タスク(lint/test/build)のNx/Turborepoリモートキャッシュ(S3/Redis)。
'turbo run build --cache-dir=。turbo'とモノレポの「影響を受ける」モード。
Python(ピップ/詩)
キャッシュホイール+virtualenv;'requirementsによってキー。'/'詩をロックします。ロックして'.
別の段階でホイールを組み立て、行列の間を再利用します。
C拡張の場合-ビルダーイメージの'pip wheel'+'auditwheel'。
Go(移動)
Кэш 'GOMODCACHE'、 'GOCACHE';'GOTOOLCHAIN'/バージョンを修正しました。
手順を分割します:'modダウンロードに移動'→コードのコピー→'ビルドに移動'。
大きなモノレールの場合-レイヤービルドでBazel/Bazeliskまたは'mage'。
Rust(ラスト)
'~/。cargo/registry'、 '~/。cargo/git'、 'target/';sccache(リモート/ローカル)
「Cargo」のブランチ間でキャッシュを共有します。ロックして'.
C/C++
コンパイラフラグとSDKバージョンによるccache/sccache+key。
別の基本イメージでツールチェーンを取り出します。
5) Bazel/Nx/Turborepo: タスクとグラフキャッシュ
Bazelリモートキャッシュ(HTTP/Cloud)-content-addressable;厳密な堅さ、砂箱。
Nx/Turborepo-タスク出力のキャッシュとモノレポでの「唯一の影響を受ける」実行。
無効:ステップ入力(ファイル/フラグ/変数)によって異なります。
6)キャッシュ障害戦略
キー=入力のハッシュ:lockfiles、コンパイラコンフィギュレーション、マニフェスト。
軽度の障害:'restore-keys' (GHA)/接頭辞(GLCI)。
ハードディスアビリティ:重要な変更のために名前空間/キーを回転させます。
レイヤー分離:deps vs sources-重い依存関係を破ることなくコードを変更します。
7)増分ビルドと行列
DAG/needs:依存ジャブを並列で実行し、シーケンスを待たないでください。
Paths-filter-影響を受けるコンポーネントのみをトリガーします。
シャードテスト:ディレクトリ/シードで、時間を調整します。
ウォームプールランナー:ピーク前に予熱された画像/キャッシュ(トーナメント/キャンペーン)。
8)アーティファクトとキャッシュ: どのように異なる
キャッシュ:再利用された入力/中間結果、汚れた領域、TTL short/medium。
アーティファクト:最終アセンブリ(イメージ、バイナリ、チャート)、変更不可、署名済み、SBOM付き。
ルール:キャッシュは積極的にクリーニングされ、アーティファクトはリリースポリシーに従って保存されます。
9)観測可能性、KPIおよびFinOps
メトリック(パイプライン/リポによる):- キャッシュのヒットレート(%)、ウォームスタートとコールドスタート時間、ステージの平均/中央値。
- パイプライン/ジョブあたりのコスト、キャッシュ/アーティファクトサイズ、スループット(ジョブ/時間)。
- モノレポの「影響を受けた実行」のシェア、変更されていない再構築(廃棄物)。
- ヒットレートはしきい値を下回り、ビルドイメージ時間が上昇し、アーティファクトが膨らみ、SLOミスが発生します。
10)キャッシュセキュリティとサプライチェーン
キャッシュ/アーティファクトに秘密はありません。マスクバルス秘密のスキャン。
Pin SHA外部アクション/プラグイン、信頼できるランナーのみ。
コンテナ/バイナリ(cosign)、 SBOM (CycloneDX/SPDX)に署名し、CDをチェックします。
Isolation: 'dev/stage/prod'の別々のキャッシュ名前空間、外部ブランチの読み取り専用の権利。
11)実用的なテンプレート
GitHubアクション-言語+コンテナ
yaml name: ci on: [push, pull_request]
concurrency: { group: ${{ github.ref }}, cancel-in-progress: true }
jobs:
build:
runs-on: ubuntu-latest steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4 with: { node-version: '20' }
- uses: actions/cache@v4 with:
path: ~/.cache/pnpm key: pnpm-${{ hashFiles('pnpm-lock.yaml') }}
- run: corepack enable && pnpm i --frozen-lockfile
- run: pnpm build
- uses: docker/build-push-action@v6 with:
tags: ${{ env.IMAGE }}
cache-from: type=gha cache-to: type=gha,mode=max
GitLab CI-Gradleリモートキャッシュ
yaml variables:
GRADLE_USER_HOME: ".gradle"
cache:
key: gradle-${CI_COMMIT_REF_SLUG}
paths: [.gradle/wrapper,.gradle/caches ]
build:
stage: build script:
-./gradlew --build-cache --no-daemon build artifacts:
paths: [ "build/libs/.jar" ]
expire_in: 3 days
Jenkins-キャッシュ/sccache
groovy pipeline {
agent { label 'cpp' }
environment { CCACHE_DIR = '/cache/ccache' }
stages {
stage('Build') {
steps {
sh 'ccache -M 10G'
sh 'cmake -B build -S. && cmake --build build -j$(nproc)'
}
}
}
post { always { sh 'ccache -s' } }
}
12) ML/データ: 重いアセンブリのスピードアップ
ローカルNVMeランナーのモデル/埋め込み/データセットのキャッシュ;ハッシュバージョニング。
リリースのアーティファクトとして事前アセンブリTensorRT/ONNXエンジン。推論で再利用する。
大きいモデルのためのChunkedアーティファクト(分割);TTLおよび遅延されたクリーニング。
13)実装チェックリスト
1.ロックファイルとベースイメージをコミットします。BuildKitを有効にします。
2.別のDockerレイヤー:deps→code;'。dockerignore'を追加します。
3.リモートキャッシュを上げる(Gradle/Bazel/Nx/Turbo);依存関係プロキシを開始します。
4.lockfileでCI内の依存性キャッシュを設定します。行列と'paths-filter'を含む。
5.モノレポにインクリメンタルビルドと「影響を受けるのみ」を入力します。
6.ヒットレート、暖かい/冷たい時間、費用を測定して下さい;警報を出して。
7.SBOM/signatureを有効にし、キャッシュ内のシークレットを拒否します。
8.ピークリリースの前にキャッシュをウォームアップします。TTL/保持を調整します。
9.ドキュメントキャッシュの障害とランブックを「キャッシュが壊れた」と表示します。
10.定期的に「永遠の」キャッシュを清掃し、重いアーティファクトをアーカイブします。
14) Antipatterns
非圧縮版のツール→「cache is、 but not repeated」
depsをインストールする前に頻繁にステップを変更する巨大なDockerfile。
キー/TTL→フレークとゴミのない「永久」キャッシュを共有します。
アーティファクトとキャッシュの混在;署名なし/SBOM。
各PRの「すべてのための」行列;'並行性の欠如。キャンセル'。
ワームキャッシュなし、依存性プロキシなしのシングルランナー。
[結果]
アセンブリの最適化は、キャッシュ、インクリメンタリティ、決定性を持つ体系的な作業です。正しいDockerfile構造、ビルド用のリモートキャッシュ、依存性プロキシおよび障害の規律は、高速で安価で再現性のあるパイプラインを提供します。観測性と安全性のルールを追加すると、リリースは頻繁に安定して経済的になります。