Гайд: ComfyUI на AWS SageMaker с CDK — автоматизация генерации изображений | AiManual
AiManual Logo Ai / Manual.
22 Июн 2026 Гайд

Автоматизация генерации контента с ComfyUI на AWS SageMaker: пошаговое руководство с AWS CDK

Пошаговое руководство по развертыванию ComfyUI на AWS SageMaker с AWS CDK: GPU-ускорение, batch-генерация, интеграция с S3. Для DevOps и MLOps.

Реклама
partv1

Генерация изображений через ComfyUI в одиночку — это боль. Особенно когда надо выдать сотню вариаций для A/B теста, а на RTX 4090 процесс занимает всю ночь. Перенос на AWS SageMaker превращает этот ад в конвейер: нажал кнопку — через 10 минут пачка картинок в S3. Но без правильного подхода ты просто утопишь бюджет в GPU инстансах. Я покажу, как собрать инфраструктуру на AWS CDK, чтобы ComfyUI работал как полноценный enterprise-сервис: автомасштабирование, отказоустойчивость, интеграция с пайплайнами.

Почему SageMaker, а не EC2 или Lambda?

Лямбда с GPU — пока миф (максимум 15 минут и холодный старт). EC2 — ручное управление: надо ставить NVIDIA драйверы, докер, мониторить загрузку. SageMaker съедает всю эту боль: встроенная обертка для инференса, автоскейлинг по метрикам GPU, автоматический роллинг апдейт модели. Это как перейти с самодельного велосипеда на Toyota Camry — разница колоссальная. Кстати, в SageMaker 2025 наконец-то добавили нормальные метрики GPU и rolling updates — теперь не надо изобретать костыли.

Структура решения: что и куда

У нас будет:

  • Docker-образ с ComfyUI (включая кастомные ноды, модели, контролнет).
  • SageMaker Model — точка входа, которая ссылается на этот образ в ECR.
  • Endpoint Configuration — выбор GPU инстанса (g5.xlarge, p4d.24xlarge), автоскейлинг.
  • Endpoint — сам сервис, который живет постоянно или просыпается по требованию.
  • S3 bucket для входных промптов (JSON) и выходных изображений.
  • CDK стек, который разворачивает всё это одной командой.

Зачем так сложно? А затем, что мы хотим не просто запустить ComfyUI, а встроить его в CI/CD для генерации контента. Чтобы любой участник команды мог дернуть API и получить результат, не думая о GPU.

Шаг 1: Собираем Docker-образ с ComfyUI (актуальный на июнь 2026)

Берем официальный образ ComfyUI (сейчас версия 2.3.1, последняя стабильная от мая 2026) и добавляем свистелки: кастомные ноды (ControlNet, IP-Adapter, AnimateDiff), модели Stable Diffusion 3.5 Medium и Flux.1 Pro. В теории можно ставить всё через скрипты, но на практике я предпочитаю зафиксировать версии в Dockerfile — меньше сюрпризов.

⚠️ Ловушка: Некоторые ноды (например, WAS Node Suite) требуют дополнительных зависимостей. Я потратил целый день, чтобы понять, что забыл установить torch.compile с triton. Просто добавьте RUN pip install torch==2.5.0+cu124 --index-url https://download.pytorch.org/whl/cu124 — и всё заработает.

FROM comfyanonymous/comfyui:2.3.1-cuda12.4

# Кастомные ноды
RUN git clone https://github.com/comfyanonymous/ComfyUI-Manager.git custom_nodes/ComfyUI-Manager
RUN git clone https://github.com/Fannovel16/comfyui_controlnet_aux.git custom_nodes/comfyui_controlnet_aux

# Скачиваем модели (предварительно залитые в EFS или S3)
COPY ./models /app/models

# Скрипт для запуска SageMaker-инференса
COPY inference.py /app/inference.py

CMD ["python3", "-u", "/app/inference.py"]

Лучше не хранить модели в образе — они весят гигабайты. Используйте EFS или S3 с монтированием через s3fs. Я предпочитаю EFS, потому что SageMaker умеет маунтить его прямо в контейнер без лишних костылей.

Шаг 2: Пишем inference.py на FastAPI

SageMaker требует, чтобы контейнер слушал порт 8080 и имел эндпоинты /invocations и /ping. Мы сделаем простой API, который принимает JSON с workflow (сохраненный из ComfyUI) и возвращает base64 изображения. Для batch-генерации просто передаём массив workflow с разными промптами.

import json
import base64
from fastapi import FastAPI, Request
from comfy_api import ComfyAPI  # наша обертка

app = FastAPI()
comfy = ComfyAPI(models_path="/app/models")

@app.post("/invocations")
async def invoke(request: Request):
    data = await request.json()
    workflow = data.get("workflow")
    images = comfy.generate(workflow)  # возвращает список PIL.Image
    results = []
    for img in images:
        buffer = BytesIO()
        img.save(buffer, format="PNG")
        results.append(base64.b64encode(buffer.getvalue()).decode())
    return {"images": results}
💡
Не забудьте закэшировать загрузку моделей при старте — иначе каждый холодный старт будет тратить минуты. Используйте глобальные переменные или синглтон.

Шаг 3: CDK-стек — инфраструктура как код

Пишем на TypeScript (хотя можно на Python CDK, TS удобнее для ресурсов AWS). Создаём стек с SageMaker Model, EndpointConfig и Endpoint. Указываем инстанс — g5.xlarge (16GB VRAM) для большинства задач, p4d.24xlarge для больших batch-ов.

import * as sagemaker from 'aws-cdk-lib/aws-sagemaker';

const model = new sagemaker.CfnModel(this, 'ComfyUIModel', {
    executionRoleArn: role.roleArn,
    primaryContainer: {
        image: ecrImageUri,
        modelDataUrl: 's3://bucket/models.tar.gz', // если модели не в образе
    },
});

const endpointConfig = new sagemaker.CfnEndpointConfig(this, 'ComfyUIConfig', {
    productionVariants: [{
        variantName: 'gpu',
        modelName: model.attrModelName,
        instanceType: 'ml.g5.xlarge',
        initialInstanceCount: 1,
        initialVariantWeight: 1.0,
        serverlessConfig: undefined, // для постоянной работы
        managedInstanceScaling: {
            minInstanceCount: 0,  // авто-включение при запросе
            maxInstanceCount: 2,
        },
    }],
});

new sagemaker.CfnEndpoint(this, 'ComfyUIEndpoint', {
    endpointConfigName: endpointConfig.attrEndpointConfigName,
});

Обратите внимание на managedInstanceScaling — это новинка 2025 года, которая позволяет инстансам засыпать при простое и просыпаться по запросу. Сэкономит вам 80% стоимости, если не гоняете генерацию 24/7. Подробнее про такие фичи я писал в статье про ModelOps без головной боли.

Шаг 4: Запускаем batch-генерацию через SageMaker Processing

Для массовой генерации (например, 10 000 вариаций) не стоит долбить REST API — слишком дорого и медленно. Используем SageMaker Processing Job: даём ему список JSON-файлов из S3, Job запускает контейнер с ComfyUI на GPU обрабатывает всё и складывает результаты обратно.

import * as sagemaker from 'aws-cdk-lib/aws-sagemaker';

const processingJob = new sagemaker.CfnProcessingJob(this, 'BatchGen', {
    processingResources: {
        clusterConfig: {
            instanceCount: 4,
            instanceType: 'ml.g5.xlarge',
        },
    },
    appSpecification: {
        imageUri: ecrImageUri,
        containerArguments: ['--batch-mode'],
    },
    processingInputs: [{
        inputName: 'prompts',
        s3Input: {
            s3Uri: 's3://bucket/prompts/',
            localPath: '/opt/ml/processing/input',
        },
    }],
    processingOutputConfig: {
        outputs: [{
            outputName: 'images',
            s3Output: {
                s3Uri: 's3://bucket/output/',
                localPath: '/opt/ml/processing/output',
            },
        }],
    },
});

Такая обработка параллелится автоматически — SageMaker распределяет файлы по инстансам. После завершения Job вы получаете папку с готовыми PNG. Теперь можно интегрировать это в пайплайн CI/CD, чтобы при каждом пуше в репозиторий с промптами автоматом генерились новые картинки для маркетинга.

Нюансы и грабли, на которые я наступил

1. Холодный старт: разбудить инстанс быстрее

Когда инстанс засыпает (managedInstanceScaling), при первом запросе он просыпается 3-5 минут — за это время клиент свалится по таймауту. Решение: сделайте health-check с периодическим легким запросом (например, раз в 5 минут отправляйте пустой ping). Или используйте Serverless Inference — но там GPU пока не поддерживается (на июнь 2026 всё еще так).

2. Стоимость GPU: как не прогореть

g5.xlarge стоит около $1.5/час на us-east-1. Если он работает 24/7 — это $1080/месяц. Неплохо для старта, но для серьёзных объемов выгоднее взять Reserved Instance на 1 год (скидка 40%). Или использовать Spot-инстансы для batch-задач — это копейки, но есть риск прерывания. Я комбинирую: эндпоинт для реального времени использует On-Demand, а batch-генерация — Spot.

3. Несовместимость кастомных нод

ComfyUI — дикий Запад. Ноды могут требовать определённую версию torch или python. Лучше всего собирать образ на основе официального, но с фиксированными версиями нод. Я советую после сборки прогонять тестовый workflow внутри контейнера в CI — это отлавливает 90% проблем.

Как это используют в Enterprise: пример Volkswagen

Компании вроде Volkswagen уже давно гоняют такие пайплайны: SageMaker + Bedrock для генерации тысяч вариантов рекламы, а ComfyUI для тонкого управления стилем. Они зашивают brand-guidelines прямо в workflow, и модель не выходит за рамки. Если нужно больше контроля, посмотрите нашу статью про Agentic AI на Bedrock — там описан похожий подход, но с LLM-агентами.

Автоматизация всего цикла: от Git push до готовых картинок

Final step: добавить GitHub Actions, который при коммите в ветку main запускает SageMaker Processing Job. Промпты хранятся в YAML файлах в репозитории, CI пакует их в JSON и шлёт в S3, затем стартует Job. Результаты автоматом публикуются на S3 bucket с CDN — дизайнеры открывают ссылку и видят свежие варианты.

Звучит сложно? На деле это 200 строк кода. Если хотите упростить себе жизнь, используйте SageMaker JumpStart — там есть готовые пресеты для Stable Diffusion, которые можно кастомизировать. Но если вам нужен полный контроль над workflow ComfyUI (а это даёт невероятную гибкость), то кастомный контейнер — единственный путь.

И неочевидный совет: не храните секреты и API-ключи в образе — используйте AWS Secrets Manager и передавайте через переменные окружения в SageMaker. Особенно если вы используете ноды, которые стучатся к внешним API (например, Replicate или Stability AI). Утечка ключей через образ — самая частая проблема, которую я вижу у новичков.

🔥 Бонус-трек: Можно добавить webhook от SageMaker Endpoint до Discord/Slack, чтобы при завершении batch-генерации автоматически приходило уведомление с превью. Делается через SNS + Lambda за 15 минут.

Подписаться на канал