Решения

CI/CD для GPU‑нагрузок: контейнеры и пайплайны

Задача страницы. Инженерный гид по построению контейнеров и CI/CD‑пайплайнов для GPU‑нагрузок: обучение и инференс (LLM/ASR/CV/DIFF), RAPIDS‑ETL, сервисы на FastAPI/Gradio и Triton. Разберём паттерны сборки, кеши, тесты с GPU, миграцию моделей, канареечные релизы, метрики качества/латентности, экономику и безопасные практики. Соседние разделы: https://cloudcompute.ru/solutions/triton-inference-server/, https://cloudcompute.ru/solutions/gradio-fastapi/, https://cloudcompute.ru/solutions/rapids/, https://cloudcompute.ru/solutions/spark-rapids/, https://cloudcompute.ru/solutions/mig/, https://cloudcompute.ru/solutions/interruptible-patterns/, https://cloudcompute.ru/solutions/performance-tuning/, https://cloudcompute.ru/solutions/throughput-vs-latency/.

TL;DR

  • Контейнеры: multi‑stage, CUDA‑совместимость, BuildKit‑кеши (—mount=type=cache), reproducible сборки (пинning по digest).
  • Модели: версионируйте как артефакты (OCI‑слои / модельные пакеты) с model.yaml; прогрев на NVMe.
  • CI: быстрые стадии CPU (lint/tests) → GPU‑smoke (≤ 60–120 с) → перф‑гейты (p95/throughput/VRAM headroom).
  • CD: canary/blue‑green, readiness/liveness, rollback по SLO; трафик‑гейты.
  • Экономика: кеши и слойность дают 2–10× экономию build‑времени; GPU‑тесты — под On‑Demand, длительные тренировки — под Interruptible.
  • Наблюдаемость: build_time, image_size, cache_hit, p95_latency, gpu_util/HBM, fail_rate.

Сценарии (когда это нужно)

Архитектуры/пайплайны (общая схема)

				
					Git push/tag
  └─ CI:
       ├─ Lint/Unit (CPU)
       ├─ Build Docker (BuildKit + caches)
       ├─ SBOM/Scan + Sign
       ├─ GPU-SMOKE (≤ 120 s: nvidia-smi, torch.cuda, mini batch)
       ├─ PERF-GATES (p95 latency, VRAM headroom, throughput)
       └─ Publish (registry, model artifacts)
  └─ CD:
       ├─ Staging deploy (K8s, readiness)
       ├─ Canary 1-5% traffic (SLO guard)
       ├─ Promote to 100% (blue/green)
       └─ Rollback on SLO breach


				
			

Профили GPU и ориентиры для CI‑тестов

Оценка smoke/perf‑гейтов на 1 GPU при U≈0.6–0.75. Используйте минимально достаточный профиль.

Профиль

Память

Smoke‑тест (сек)

Перф‑замер (мин)

Типовые задачи

24 ГБ (Compact)

24 ГБ

20–60

2–5

Torch/CUDA init, 1–2 микробатча LLM/CV, простые RAPIDS

48 ГБ (Balanced)

48 ГБ

20–60

3–8

Средние модели (ASR/TTS), Triton model‑repo проверка

80 ГБ (HQ)

80 ГБ

20–60

5–10

Крупные LLM/DIFF/батчи ETL, стабильные p95

Подбор пула и экономику см. https://cloudcompute.ru/solutions/throughput-vs-latency/ и https://cloudcompute.ru/solutions/cost-planner/

Контейнеры: паттерны Dockerfile

1) Torch/LLM Inference (multi‑stage + BuildKit кеши)

				
					# syntax=docker/dockerfile:1.6
ARG CUDA_VER=12.4.1
ARG BASE_OS=ubuntu22.04
FROM nvidia/cuda:${CUDA_VER}-cudnn-runtime-${BASE_OS} AS base

ENV DEBIAN_FRONTEND=noninteractive \
    PIP_NO_CACHE_DIR=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    TORCH_CUDA_ARCH_LIST="8.0;8.6;8.9" \
    HF_HUB_DISABLE_TELEMETRY=1

RUN --mount=type=cache,target=/var/cache/apt \
    apt-get update && apt-get install -y --no-install-recommends \
      git curl ca-certificates python3 python3-pip libsndfile1 \
      && rm -rf /var/lib/apt/lists/*

# Wheelhouse (кешируем pip)
FROM base AS wheel
COPY requirements.txt /tmp/requirements.txt
RUN --mount=type=cache,target=/root/.cache/pip \
    python3 -m pip install -U pip && \
    pip wheel -r /tmp/requirements.txt -w /wheels

# Runtime
FROM base AS runtime
WORKDIR /app
COPY --from=wheel /wheels /wheels
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install --no-index --find-links=/wheels -r /wheels/requirements.txt
COPY . /app
# Неблокирующий прогрев токенайзеров/весов на NVMe (смонтируйте /nvme/models)
ENV MODELS_DIR=/nvme/models PRECISION=fp16
CMD ["python","serve.py"]


				
			

Рекомендации: фиксируйте digest базового образа, держите requirements.txt отсортированным (минимум диффа), вынесите большие зависимости в wheelhouse‑кеш.

2) RAPIDS‑ETL job

				
					FROM rapidsai/rapidsai-core:24.06-cuda12.2-runtime-ubuntu22.04
ENV RMM_POOL_SIZE=70% UCX_TLS=tcp,cuda_copy,cuda_ipc
WORKDIR /job
COPY etl_job.py /job/etl_job.py
CMD ["python","etl_job.py","--input","/data","--out","/out"]


				
			

3) Triton model repository (минимальный runtime)

				
					FROM nvcr.io/nvidia/tritonserver:24.05-py3
COPY models/ /models/                 # репозиторий моделей (config.pbtxt, версии)
CMD ["tritonserver","--model-repository=/models","--log-verbose=0"]


				
			

Модели как артефакты: model.yaml и OCI‑слои

Храните модели отдельно от кода, как версионируемые артефакты, публикуйте вместе с SBOM и метаданными:

				
					model:
  name: "llm-small-ru"
  version: "1.4.2"
  format: "hf"            # hf|onnx|triton
  precision: "fp16"
  files:
    - path: "pytorch_model.bin"
    - path: "tokenizer.json"
  metrics:
    token_rate_tok_s: 650
    vram_peak_gb: 14.3
  compatibility:
    cuda: ">=12.2"
    arch: ["8.0","8.6","8.9"]
promote:
  tests:
    - "smoke_llm_hello_world"
    - "perf_token_rate >= 500"
  rollout:
    canary_traffic: 0.05
    rollback_slo:
      latency_p95_ms: 1200
      error_rate: 0.5


				
			

CI: пайплайны (GitHub Actions / GitLab CI)

GitHub Actions (.github/workflows/ci.yml)

				
					name: ci
on:
  push: { branches: ["main"] }
  pull_request:
jobs:
  lint-test:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4
      - run: pipx install ruff && ruff check .
      - run: pipx install pytest && pytest -q

  build-image:
    needs: lint-test
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with: { registry: ${{ secrets.REGISTRY }}, username: ${{ secrets.USER }}, password: ${{ secrets.PASSWORD }} }
      - name: Build & push
        run: |
          docker buildx build --push \
            --build-arg CUDA_VER=12.4.1 \
            --cache-to=type=registry,ref=${{ secrets.REGISTRY }}/proj/cache,mode=max \
            --cache-from=type=registry,ref=${{ secrets.REGISTRY }}/proj/cache \
            -t ${{ secrets.REGISTRY }}/proj/app:${{ github.sha }} .

  gpu-smoke:
    needs: build-image
    runs-on: self-hosted-gpu              # раннер с GPU
    steps:
      - name: Pull image
        run: docker pull ${{ secrets.REGISTRY }}/proj/app:${{ github.sha }}
      - name: Smoke (≤120s)
        timeout-minutes: 5
        run: |
          docker run --rm --gpus 1 \
            -e MODELS_DIR=/nvme/models \
            -v /nvme/models:/nvme/models \
            ${{ secrets.REGISTRY }}/proj/app:${{ github.sha }} \
            python -c "import torch; assert torch.cuda.is_available(); print(torch.cuda.get_device_name(0))"

  perf-gates:
    needs: gpu-smoke
    runs-on: self-hosted-gpu
    steps:
      - name: Perf test
        run: |
          docker run --rm --gpus 1 ${{ secrets.REGISTRY }}/proj/app:${{ github.sha }} \
            python perf_gate.py --p95-ms 1200 --vram-headroom-gb 2.0

				
			

GitLab CI (.gitlab-ci.yml)

				
					stages: [lint, build, smoke, perf, deploy]

lint:
  stage: lint
  image: python:3.11
  script:
    - pip install ruff pytest
    - ruff check .
    - pytest -q

build:
  stage: build
  image: docker:24.0.5
  services: [docker:dind]
  script:
    - docker buildx create --use
    - docker login -u "$REG_USER" -p "$REG_PASS" $REGISTRY
    - docker buildx build --push -t $REGISTRY/proj/app:$CI_COMMIT_SHA .

smoke:
  stage: smoke
  tags: ["gpu"]                 # GitLab Runner с GPU
  script:
    - docker run --rm --gpus 1 $REGISTRY/proj/app:$CI_COMMIT_SHA python smoke.py

perf:
  stage: perf
  tags: ["gpu"]
  script:
    - docker run --rm --gpus 1 $REGISTRY/proj/app:$CI_COMMIT_SHA python perf_gate.py --p95-ms 1200


				
			

CD: канареечные релизы и промоушн

K8s Deployment (readiness/liveness + canary)

				
					apiVersion: apps/v1
kind: Deployment
metadata: { name: llm-serving, labels: { app: llm, channel: stable } }
spec:
  replicas: 6
  selector: { matchLabels: { app: llm, channel: stable } }
  template:
    metadata: { labels: { app: llm, channel: stable } }
    spec:
      containers:
        - name: api
          image: registry.local/proj/app:sha-abcdef
          ports: [{ containerPort: 9090 }]
          env:
            - { name: PRECISION, value: "fp16" }
          readinessProbe: { httpGet: { path: /healthz, port: 9090 } }
          livenessProbe:  { httpGet: { path: /livez,  port: 9090 } }
          resources: { limits: { nvidia.com/gpu: 1, cpu: "4", memory: "32Gi" } }
---
apiVersion: apps/v1
kind: Deployment
metadata: { name: llm-serving-canary, labels: { app: llm, channel: canary } }
spec:
  replicas: 1
  selector: { matchLabels: { app: llm, channel: canary } }
  template:
    metadata: { labels: { app: llm, channel: canary } }
    spec:
      containers:
        - name: api
          image: registry.local/proj/app:${NEW_SHA}
          ports: [{ containerPort: 9090 }]
          env: [ { name: PRECISION, value: "fp16" } ]
          readinessProbe: { httpGet: { path: /healthz, port: 9090 } }
          resources: { limits: { nvidia.com/gpu: 1, cpu: "4", memory: "32Gi" } }

				
			

Маршрутизация трафика (ingress/сервис) отдаёт 1–5% на channel=canary. Гейты промоушна: latency_p95, error_rate, gpu_mem_peak/HBM, token_rate.

Наблюдаемость/метрики/алерты

CI/Build:

  • ci_build_time_seconds, image_size_bytes, cache_hit_ratio, sbom_vuln_count, build_fail_rate.
  • wheelhouse_hit_ratio, layer_reuse_ratio.

GPU‑тесты/перф‑гейты:

  • gpu_smoke_time_seconds, latency_p95_ms, token_rate_tok_s/fps, vram_peak_gb, gpu_utilization, gpu_copy_util.
  • perf_gate_pass_total, perf_gate_fail_total.

CD/Прод:

  • latency_seconds{route}, timeouts_total, errors_total, queue_depth, HBM_peak, packing_efficiency (для MIG).

Алерты (примеры):

  • cache_hit_ratio < 0.6 — проверьте BuildKit‑кеш/слои, вынесите зависимости в отдельный этап.
  • latency_p95_ms > SLO — уменьшить max_tokens/steps, увеличить реплики/GPU, см. https://cloudcompute.ru/solutions/throughput-vs-latency/
  • vram_peak/HBM > 0.9 — FP16/BF16, микробатч ≤ 4, профиль побольше/MIG‑переупаковка. См. https://cloudcompute.ru/solutions/mig/
  • sbom_vuln_count ↑ — обновите базу, пересоберите образ, фиксируйте digest.
  • gpu_copy_util ≈100% при низком SM — упор в PCIe/копировщики: pinned/zero‑copy, фьюзинг препроцесса. См. https://cloudcompute.ru/solutions/performance-tuning/

Детали по логам и метрикам: https://cloudcompute.ru/solutions/monitoring-logging/, https://cloudcompute.ru/solutions/llm-inference/observability/

Экономика и формулы

Обозначения: c_gpu — цена GPU‑часа, c_cpu — CPU‑часа, U — целевая загрузка, t_b — build‑время, t_smoke, t_perf, n_prompts — тестовые запросы.

  • Стоимость сборки:
    Cost_build ≈ c_cpu × t_b_cpu + c_gpu × t_b_gpu / U. (обычно t_b_gpu ~ 0, если тесты отдельной стадией)
  • Стоимость тестов:
    Cost_tests ≈ c_gpu × (t_smoke + t_perf) / U.
  • Экономия от кешей:
    Пусть hit — доля кеш‑попаданий, t_b0 — сборка без кеша.
    t_b ≈ t_b0 × (1 — hit × k), где k∈[0.5;0.9] — «сила» кеша.
    ΔCost ≈ c_cpu × (t_b0 — t_b).
  • Canary‑стоимость:
    При qps, доле p и времени проверки T:
    Cost_canary ≈ c_gpu × p × qps × T × t_infer / U.
  • On‑Demand vs Interruptible:
    Онлайн‑сервисы → On‑Demand, офлайн‑тренировки/ETL → Interruptible (см. https://cloudcompute.ru/solutions/interruptible-patterns/). Итоговая стоимость = сумма по пулам.

Планирование бюджета: https://cloudcompute.ru/solutions/cost-planner/

Безопасность/политики (supply chain)

  • Пиннинг базовых образов по digest, reproducible сборки (фиксированные версии).
  • SBOM и скан уязвимостей на этапе CI; gate по критичности.
  • Подпись и проверка образов при CD; политика доверенных реестров.
  • Секреты только через секрет‑хранилища/ENV; не в образах.
  • Rootless/USER невысоких привилегий; readOnlyRootFilesystem.
  • Политики PII: без сырых данных/ключей в логах/артефактах; хранение моделей и датасетов в приватных бакетах. См. https://cloudcompute.ru/solutions/security/, https://cloudcompute.ru/solutions/storage-data/

Траблшутинг

Симптом

Возможная причина

Решение

CUDA driver mismatch

Драйвер на узле < runtime CUDA

Обновить драйвер, подобрать базовый образ под версию драйвера

invalid device function

Сборка/библиотеки под другую arch

Указать TORCH_CUDA_ARCH_LIST, пересобрать/переустановить колеса

PTX‑JIT задержки

Нет SASS под вашу arch

Предпрогреть модель, добавить целевые arch, кэш на NVMe

Медленная сборка

Отсутствие кешей/большие COPY

BuildKit cache‑mounts, split‑слои, уменьшить контекст

Большой образ

Неочищенные apt/pip, dev‑зависимости

—no-install-recommends, wheelhouse + runtime layer

Тесты «плавают»

Нестабильные seeds/режимы CUDNN

Фиксировать сиды, отключить benchmark при сравнениях SLA

CUDA OOM в перф‑гейтах

Батч/токены/разрешения

FP16/BF16, микробатч ≤ 4, уменьшить входные размеры

Triton не видит модель

Нарушен layout model‑repo

Проверить config.pbtxt/версии, права/пути

MIG‑под не стартует

Неверный resourceName

Использовать nvidia.com/mig-*.**gb, проверить device‑plugin

Развалился rollback

Нет immutable‑тегов/диджестов

Промоушн по digest, хранить N‑версий для отката

Как запустить в cloudcompute.ru

  1. Откройте Шаблоны запусков: https://cloudcompute.ru/solutions/templates/ — выберите CI/CD GPU Runner, Triton, FastAPI GPU API, RAPIDS job.
  2. Разведите пулы: On‑Demand (онлайн‑сервисы/канарейки) и Interruptible (тренировки/ETL). См. https://cloudcompute.ru/solutions/interruptible-patterns/
  3. Смонтируйте NVMe: /nvme/models (веса), /nvme/cache (wheelhouse/артефакты).
  4. Настройте BuildKit‑кеши и wheelhouse; зафиксируйте base‑image digest.
  5. Добавьте GPU‑smoke (≤ 120 с) и перф‑гейты (p95/VRAM/token_rate) в CI.
  6. Настройте CD: readiness/liveness, canary 1–5%, автопромоушн по SLO, rollback.
  7. Подключите дашборды: сборка/размер образов/кеш, прод‑метрики p95/QPS/HBM. См. https://cloudcompute.ru/solutions/monitoring-logging/, https://cloudcompute.ru/solutions/llm-inference/observability/

Чек‑лист перед продом

  • Dockerfile: multi‑stage, BuildKit‑кеши, pinned digests, малый runtime‑слой.
  • Модели как артефакты: model.yaml, версии, прогрев на NVMe.
  • CI: lint/unit, build, SBOM/scan/sign, GPU‑smoke (≤120 с), перф‑гейты.
  • CD: staging → canary → promote → rollback; readiness/liveness.
  • Метрики: build_time, image_size, cache_hit, latency_p95, HBM_peak, token_rate.
  • Политики безопасности/PII/секретов; USER/rootless; приватные реестры.
  • Пулы On‑Demand/Interruptible и/или MIG‑раскладка согласованы.
  • Нагрузочный прогон ≥ 30 мин под целевым трафиком; план отката проверен.