Stable-Diffusion-v1-5-archive跨平台部署:Docker镜像在K8s集群中水平扩展实践
Stable-Diffusion-v1-5-archive跨平台部署:Docker镜像在K8s集群中水平扩展实践
1. 引言
如果你正在寻找一个稳定、经典且功能齐全的文生图模型,Stable Diffusion v1.5 Archive 绝对是一个绕不开的选择。这个归档版本保留了SD1.5模型的核心能力,在通用图像生成、创意草图和风格化出图方面表现依然出色。对于个人开发者或小团队来说,在单台服务器上部署一个Web界面来使用它,已经足够方便。
但当我们面对的是企业级应用场景时,比如一个需要为大量用户同时提供AI绘画服务的平台,或者一个内部创意工具需要应对业务高峰期的集中使用,单点部署的局限性就暴露出来了。服务可能因为单点故障而中断,也可能因为并发请求过多而响应缓慢甚至崩溃。
这时候,我们就需要更强大的部署方案。本文将带你深入实践,如何将 stable-diffusion-v1-5-archive 这个开箱即用的Docker镜像,部署到Kubernetes集群中,并实现服务的水平扩展。我们将从零开始,一步步搭建一个高可用、可弹性伸缩的AI绘画服务集群,让你不仅能体验到SD1.5的经典魅力,更能享受到现代云原生技术带来的稳定与高效。
2. 为什么要在K8s中部署Stable Diffusion?
在深入部署细节之前,我们先来聊聊为什么要把一个AI绘画模型放到Kubernetes(简称K8s)里。这不仅仅是技术上的“炫技”,而是为了解决实实在在的工程问题。
2.1 单点部署的痛点
传统的单机或单容器部署方式,简单直接,但也存在几个明显的短板:
- 资源瓶颈:一台服务器的GPU算力、内存和网络带宽都是有限的。当大量用户同时请求生成图片时,服务很容易达到瓶颈,导致请求排队、超时甚至失败。
- 单点故障:服务器硬件故障、系统崩溃、或者容器异常退出,都会导致整个服务不可用。对于线上业务来说,这是不可接受的。
- 难以维护和升级:更新模型、调整参数或者修复漏洞,通常需要重启服务,这会造成服务中断。在单点部署下,做到平滑升级和无感更新非常困难。
- 资源利用率低:在业务低谷期,昂贵的GPU服务器可能处于闲置状态,造成资源浪费;在高峰期,又可能因为资源不足而影响用户体验。
2.2 K8s带来的核心价值
将 stable-diffusion-v1-5-archive 部署到K8s集群,正是为了解决上述问题:
- 高可用性:通过部署多个副本(Pod),即使某个副本所在的节点发生故障,K8s会自动在其他节点上拉起新的副本,确保服务不中断。
- 水平扩展:这是K8s的“杀手锏”。我们可以根据服务的CPU、GPU或内存使用率,或者根据每秒的请求量(QPS),自动增加或减少运行中的副本数量。流量高峰时自动扩容,低谷时自动缩容,既保证了服务能力,又优化了成本。
- 简化运维:K8s提供了统一的声明式API来管理应用。部署、更新、回滚、配置管理都变得标准化和自动化。一次编写YAML文件,即可在任何符合标准的K8s集群上运行。
- 资源隔离与调度:K8s可以精确地为每个Pod分配和限制CPU、内存乃至GPU资源,避免单个服务耗尽整个节点的资源,影响其他服务。
简单来说,K8s让我们的AI绘画服务从一个“单兵作战”的个体,变成了一个“协同作战”的军团,具备了弹性、韧性和可观测性。
3. 部署前准备:理解我们的“武器”
在开始构建军团之前,我们先要熟悉手中的“武器”—— stable-diffusion-v1-5-archive Docker镜像。
3.1 镜像核心特点
这个镜像已经为我们做了很多繁重的工作,使其非常适合在K8s中运行:
- 开箱即用的Web界面:基于Gradio构建,用户无需接触命令行,通过浏览器即可进行文生图操作。这为我们后续通过Ingress或Service暴露服务提供了便利。
- 内置服务守护:镜像内部使用Supervisor来管理Web服务进程。这意味着即使进程意外退出,Supervisor也会尝试自动重启它,增加了容器内进程的稳定性。不过,在K8s层面,我们还需要配置健康检查来确保整个Pod的健康。
- 标准化的输出:服务不仅返回生成的图片,还会返回推理所用的所有参数(以JSON格式)。这对于结果复现、调试和审计非常有帮助。
- 明确的资源需求:作为一个文生图模型,其核心依赖是GPU。这提醒我们在K8s中部署时,必须为Pod声明GPU资源请求和限制。
3.2 模型与参数回顾
为了让后续的配置更清晰,我们快速回顾一下关键信息:
- 模型路径:
Comfy-Org/stable-diffusion-v1-5-archive - 服务端口:
7860(这是镜像内Web服务监听的端口) - 关键参数:
Steps: 采样步数,影响细节和速度。Guidance Scale: 提示词遵循强度。Seed: 随机种子,-1表示随机,固定值可复现结果。Negative Prompt: 负向提示词,用于排除不想要的元素。
一个重要的实践提示:尽管服务支持中文提示词,但SD1.5模型对英文的语义理解能力更强。为了获得更稳定、更符合预期的效果,强烈建议先将中文构思翻译成英文再输入。例如,想要“一个雨夜街道上的红色复古汽车”,可以输入:a red vintage car on a rainy night street, cinematic lighting, ultra detailed, 35mm film。
4. 实战:构建K8s部署清单
理论讲完,我们进入实战环节。我们将创建几个关键的K8s YAML文件,来定义我们的AI绘画服务。
假设我们有一个已经安装好NVIDIA GPU驱动和nvidia-container-toolkit的K8s集群,并且配置了GPU相关的Device Plugin。
4.1 创建命名空间和配置
首先,为我们的应用创建一个独立的命名空间,实现资源隔离。
# 1-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: ai-painting
接下来,我们可以将一些可变的配置,如副本数量、镜像版本等,放入ConfigMap,方便管理。但更常见的做法是直接写在Deployment里,这里我们先展示一个简单的ConfigMap,用于存储一些应用级别的配置(非敏感信息)。
# 2-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: sd15-archive-config
namespace: ai-painting
data:
# 这里可以放一些环境变量,但该镜像主要参数通过Web界面调整
# 例如可以设置一些默认的启动参数,如果镜像支持的话
APP_NAME: "Stable Diffusion v1.5 Archive"
4.2 核心:创建Deployment
Deployment是K8s中定义无状态应用的核心对象。它负责创建和管理一组相同的Pod副本。
# 3-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: stable-diffusion-v15-archive
namespace: ai-painting
labels:
app: stable-diffusion-v15-archive
spec:
replicas: 2 # 初始副本数,后续可由HPA自动调整
selector:
matchLabels:
app: stable-diffusion-v15-archive
template:
metadata:
labels:
app: stable-diffusion-v15-archive
spec:
# 节点选择器:确保Pod被调度到有GPU的节点上
nodeSelector:
accelerator: nvidia-gpu # 这个标签需要提前打到GPU节点上
containers:
- name: sd15-web
image: csdnmirrors/stable-diffusion-v1-5-archive:latest # 使用CSDN镜像加速地址
ports:
- containerPort: 7860 # 容器内服务端口
resources:
limits:
# 关键:声明需要GPU资源,这里请求1张GPU卡
nvidia.com/gpu: 1
memory: "8Gi"
cpu: "2"
requests:
nvidia.com/gpu: 1
memory: "6Gi"
cpu: "1"
# 健康检查:确保Pod内的服务是真正可用的
livenessProbe:
httpGet:
path: / # 尝试访问Web服务的根路径
port: 7860
initialDelaySeconds: 120 # 镜像启动较慢,给予足够初始化时间
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /
port: 7860
initialDelaySeconds: 30
periodSeconds: 5
failureThreshold: 1
# 环境变量(如果需要)
env:
- name: NVIDIA_VISIBLE_DEVICES
value: all # 让容器内可以看到所有GPU
# 挂载点(如果需要持久化模型或日志,但模型已内置在镜像中)
# volumeMounts: ...
# volumes: ...
restartPolicy: Always
关键点解析:
replicas: 2:我们一开始就启动2个副本,实现最基本的负载均衡和高可用。nodeSelector:通过标签选择器,将Pod强制调度到带有accelerator: nvidia-gpu标签的GPU节点上。resources.limits/requests:这是声明GPU资源的核心。nvidia.com/gpu: 1表示该Pod需要独占1张GPU卡。同时我们也限制了CPU和内存,防止单个Pod占用过多资源。livenessProbe&readinessProbe:健康检查是生产级部署的必备项。livenessProbe失败,K8s会重启容器;readinessProbe失败,K8s会将该Pod从Service的负载均衡池中移除,直到它恢复健康。我们设置了较长的initialDelaySeconds,因为Stable Diffusion模型加载需要时间。image:使用了csdnmirrors/前缀的镜像地址,通常在国内网络环境下拉取更快。
4.3 暴露服务:创建Service
Deployment管理了Pod,但Pod的IP是不固定的。我们需要一个Service来为这组Pod提供一个稳定的访问入口和负载均衡。
# 4-service.yaml
apiVersion: v1
kind: Service
metadata:
name: stable-diffusion-v15-archive-svc
namespace: ai-painting
spec:
selector:
app: stable-diffusion-v15-archive # 选择我们Deployment创建的Pod
ports:
- port: 80 # Service对外的端口
targetPort: 7860 # 转发到Pod的端口
protocol: TCP
type: ClusterIP # 默认类型,仅在集群内部可访问
现在,在K8s集群内部,其他应用可以通过stable-diffusion-v15-archive-svc.ai-painting.svc.cluster.local:80这个域名来访问我们的AI绘画服务。
4.4 对外暴露:创建Ingress(可选)
如果我们需要让集群外部的用户通过浏览器访问Web界面,就需要创建Ingress资源,并配合Ingress Controller(如Nginx Ingress Controller)使用。
# 5-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: stable-diffusion-v15-archive-ingress
namespace: ai-painting
annotations:
# 以下注解取决于你使用的Ingress Controller
nginx.ingress.kubernetes.io/proxy-body-size: "50m" # 允许上传大图片(如果需要图生图等功能)
nginx.ingress.kubernetes.io/proxy-read-timeout: "300" # 生成图片可能耗时较长,调大超时时间
spec:
ingressClassName: nginx # 指定Ingress Class
rules:
- host: sd15.yourdomain.com # 你的域名
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: stable-diffusion-v15-archive-svc
port:
number: 80
这样,用户访问 https://sd15.yourdomain.com 就能看到Stable Diffusion的Web界面了。
5. 实现水平扩展:配置HPA
水平扩展是K8s的精华所在。我们将配置Horizontal Pod Autoscaler(HPA),让副本数量能够根据负载自动调整。
5.1 基于CPU/内存的自动扩缩容
首先,我们需要确保Deployment中定义的容器设置了resources.requests,HPA需要根据这个值来计算资源利用率。
# 6-hpa-cpu.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: stable-diffusion-v15-archive-hpa
namespace: ai-painting
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: stable-diffusion-v15-archive
minReplicas: 1 # 最少副本数
maxReplicas: 5 # 最多副本数,受限于集群GPU数量
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70 # 目标CPU平均使用率70%
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80 # 目标内存平均使用率80%
这个HPA会监控所有Pod的CPU和内存使用率。当任意一个指标超过目标值时,就会触发扩容,直到所有指标都低于目标值,才会考虑缩容。
5.2 基于自定义指标(QPS)的扩缩容(进阶)
对于Web服务,并发请求数(QPS)可能是比CPU更直接的扩缩容依据。这需要集群安装Metrics Server和Prometheus Adapter等组件来提供自定义指标。
假设我们已经有了一个名为http_requests_per_second的指标,可以按以下方式配置HPA:
# 7-hpa-custom.yaml (示例)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: stable-diffusion-v15-archive-hpa-custom
namespace: ai-painting
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: stable-diffusion-v15-archive
minReplicas: 1
maxReplicas: 5
metrics:
- type: Pods
pods:
metric:
name: http_requests_per_second
target:
type: AverageValue
averageValue: 10 # 目标是每个Pod平均每秒处理10个请求
这意味着,当所有Pod平均每秒处理的请求数超过10个时,HPA就会增加副本;当低于10个时,就会减少副本。
重要提醒:GPU资源的自动扩缩容在K8s中是一个复杂话题。标准的HPA无法直接基于nvidia.com/gpu的使用率进行扩缩。通常的实践是基于业务指标(如请求队列长度、平均响应时间)或与GPU利用率强相关的CPU指标来间接控制。最根本的限制是集群中可用的GPU节点数量。
6. 部署与管理操作
所有YAML文件准备好后,就可以开始部署了。
# 1. 应用所有配置
kubectl apply -f 1-namespace.yaml
kubectl apply -f 2-configmap.yaml
kubectl apply -f 3-deployment.yaml
kubectl apply -f 4-service.yaml
kubectl apply -f 5-ingress.yaml # 如果需要对外暴露
kubectl apply -f 6-hpa-cpu.yaml
# 2. 查看部署状态
kubectl get pods -n ai-painting -w # 使用-w参数实时观察Pod创建过程
kubectl describe pod -n ai-painting <pod-name> # 查看某个Pod的详细信息
# 3. 查看服务
kubectl get svc -n ai-painting
kubectl get ingress -n ai-painting
# 4. 查看HPA状态
kubectl get hpa -n ai-painting -w
# 5. 查看日志(类似于原单机部署的supervisorctl logs)
kubectl logs -f deployment/stable-diffusion-v15-archive -n ai-painting
# 6. 扩容/缩容(也可以让HPA自动做)
kubectl scale deployment stable-diffusion-v15-archive --replicas=3 -n ai-painting
# 7. 更新镜像版本(滚动更新)
kubectl set image deployment/stable-diffusion-v15-archive sd15-web=csdnmirrors/stable-diffusion-v1-5-archive:new-tag -n ai-painting
kubectl rollout status deployment/stable-diffusion-v15-archive -n ai-painting # 查看更新状态
7. 总结
通过这一系列的实践,我们已经成功地将一个单体的 stable-diffusion-v1-5-archive Docker镜像,部署成了一个运行在Kubernetes集群中的、高可用且可水平扩展的AI绘画微服务。
我们来回顾一下这个方案带来的核心提升:
- 从单点到集群:服务不再依赖于单台机器,多个副本同时运行,任何一个副本或节点故障都不会导致服务中断。
- 从手动到自动:通过HPA,我们可以根据实际负载(CPU、内存或自定义QPS)自动调整服务实例的数量,从容应对流量波动,实现成本与性能的最优平衡。
- 从复杂到标准:所有的部署、配置、更新操作都通过声明式的YAML文件完成,并通过
kubectl命令统一管理,极大地简化了运维复杂度,也便于纳入CI/CD流程。 - 资源管理精细化:通过K8s的资源请求和限制,我们可以精确控制每个服务实例消耗的GPU、CPU和内存,实现集群资源的公平、高效利用。
当然,这个方案是一个起点,你可以在此基础上继续深化:
- 持久化存储:如果需要保存用户生成的图片或日志,可以挂载PersistentVolume。
- 服务网格:集成Istio等服务网格,实现更细粒度的流量管理、熔断和观测。
- GPU共享:探索MIG、vGPU或时间切片等技术,在多个Pod间更高效地共享单张GPU卡。
Stable Diffusion v1.5 Archive是一个经典而强大的工具,而Kubernetes为我们提供了驾驭这个工具、并将其转化为稳定可靠生产力的最佳平台。希望这篇实践指南能帮助你顺利搭建起自己的AI绘画服务集群。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐



所有评论(0)