C

CHEGVA

让我们面对现实 让我们忠于理想

K8s HPA原理及最佳实践

在Kubernetes整个体系中,弹性伸缩是至关重要的功能,其分为两种:水平弹性伸缩(Horizontal Pod Autoscaling,简称HPA)和垂直弹性伸缩(Vertical Pod Autoscaler,简称VPA)。HPA可以根据观察到的资源实际使用情况(如CPU/内存)或其它自定义指标负载自动调整Pod副本数,VPA可以根据资源实际使用情况为其Pod中的容器设置最新的资源配额requests。这两者合理使用既可以满足业务对实例数的要求保证系统稳定性,同时又能充分提升集群资源的利用率。 一、HPA 原理 HPA (Horizontal Pod Autoscaler) 的核心原理可以概括为:定期查询监控指标,然后根据其目标值(Target Value) 和当前值(Current Value),通过特定的算法计算出所需的 Pod 副本数量,自动控制 Deployment、StatefulSet 等资源的副本数量,以使应用的平均资源利用率(如 CPU、内存)维持在你设定的目标值。 下面是图中涉及的核心组件及其作用的文字说明: HPA Controller:HPA 的“决策大脑”,是 kube-controller-manager 的一部分。它负责[定期循环](默认每隔 15秒)通过 API Server 查询其管理的所有 HPA 对象及其对应的监控指标,并根据指标数据计算是否需要扩缩容以及需要多少个 Pod 副本。 API Server:Kubernetes 的“信息枢纽”。HPA Controller 通过它查询 HPA 配置、获取监控指标,也是通过它来更新工作负载的副本数量。 Metrics API:指标数据的标准化接口。HPA Controller 只通过统一的 Metrics API 来获取指标数据,而不关心数据的具体来源。这层抽象使得 HPA 可以灵活地使用不同种类的指标。 resource.metrics.k8s.io:提供资源指标,如 Pod 的 CPU 和内存使用率,通常由 Metrics Server 实现。 custom.metrics.k8s.io:提供自定义指标,这些指标通常与特定应用或 Kubernetes 对象(如 Pod 的 QPS)相关。常用 Prometheus Adapter 来从 Prometheus 中获取并暴露这些指标。 external.metrics.k8s.io:提供外部指标,这些指标完全来自于 Kubernetes 集群之外的系统,如消息队列的长度、云服务的监控指标等。 Metrics Server:一个集群范围内的资源使用数据聚合器。它从每个节点上的 kubelet 收集核心资源指标(如 CPU 和内存),并通过 resource.metrics.k8s.io API 暴露它们,供 HPA 等组件使用。 Prometheus + Prometheus Adapter:一个常见的自定义指标方案。Prometheus 负责采集和存储丰富的监控数据。Prometheus Adapter 则作为一个桥梁,查询 Prometheus 中的数据,并将其转换为 Kubernetes 能够理解的格式,通过 custom.metrics.k8s.io API 暴露给 HPA Controller。 HPA 的工作流程是一个持续的控制循环,上图的数字编号也大致对应了这些步骤: 查询 HPA 配置:HPA Controller 定期(默认 15s,可通过 --horizontal-pod-autoscaler-sync-period 参数调整)通过 API Server 查询所有 HPA 对象的配置定义,包括目标工作负载、目标指标类型及其目标值、最小/最大副本数等。 获取监控指标:对于每个 HPA,Controller 通过对应的 Metrics API(资源、自定义或外部)来获取当前的监控指标值。 源指标(如 CPU、内存)由 Metrics Server 提供。Metrics Server 通过 Kubelet 从每个节点的 cAdvisor 中采集所有 Pod 的资源使用数据,并聚合到集群层面。 metrics.k8s.io: 主要提供Pod和Node的CPU和Memory相关的监控指标。 custom.metrics.k8s.io: 主要提供Kubernetes Object相关的自定义监控指标。 external.metrics.k8s.io:指标来源外部,与任何的Kubernetes资源的指标无关。 自定义指标(如 QPS、应用内部指标)由 Kubernetes Custom Metrics API 提供,这通常需要安装像 Prometheus Adapter 这样的组件来将 Prometheus 等监控系统的指标转换为 Kubernetes API 可以理解的格式。 计算所需副本数:Controller 使用获取到的当前指标值和 HPA 中定义的目标指标值,通过算法计算出期望的 Pod 副本数量。 计算公式:期望副本数 = ceil[当前副本数 * (当前指标值 / 目标指标值)]。 例如,当前有 2 个 Pod,CPU 使用率为 80%,HPA 目标 CPU 使用率为 40%,则期望副本数 = ceil[2 * (80 / 40)] = ceil[4] = 4。HPA 会考虑多种指标(选择计算结果中最大的副本数)并内置了容忍度(默认 0.1,即比率变化不超过 10% 则忽略)和冷却窗口等机制来防止副本数抖动 调整副本数:如果计算出的期望副本数与当前副本数不同,HPA Controller 会通过 API Server更新目标工作负载(如 Deployment)的 replicas 字段,为了避免副本数量因指标瞬时波动而剧烈变化(“抖动”),HPA 引入了冷却机制。 扩容:如果计算出的 期望副本数 > 当前副本数,HPA 就会增加副本数。 扩容冷却 (默认 3 分钟):扩容操作没有全局等待期,但快速连续扩容时,每次扩容后等待时间会逐渐增加。 缩容:如果计算出的 期望副本数 < 当前副本数,HPA 就会减少副本数。 缩容冷却 (--horizontal-pod-autoscaler-downscale-stabilization,默认 5 分钟):在一次缩容操作后,会等待一段时间(默认5分钟),再执行下一次缩容操作。 工作负载控制器响应:相应的工作负载控制器(如 Deployment Controller)检测到 replicas 字段变化,会开始创建或删除 Pod,以使实际运行的 Pod 数量等于期望值。 调度新 Pod:新创建的 Pod 会被 Scheduler 调度到合适的节点上运行。如果节点资源不足,这些 Pod 会处于 Pending 状态。 节点扩缩容(可选):如果集群中使用了 Cluster Autoscaler (CA),它会检测到因资源不足而无法调度的 Pod(Pending状态),然后自动扩容集群节点来提供更多资源。Pod 被成功调度和运行后,才能开始处理业务流量,此时指标数据也会随之变化,HPA 的下一个循环周期又会开始。 在实际应用中,基于原生HPA系统架构实现适配业务自定义特性的整体设计架构如下: 二、基于 CPU 和内存的最佳实践示例 前提条件 安装 Metrics Server: HPA 需要 Metrics Server 来获取 CPU/内存指标。 安装命令(对于大多数集群): kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml 验证安装:kubectl top nodes 为 Pod 设置资源请求: 这是最关键的一步! HPA 计算使用率的公式是:(Pod 当前实际使用量 / Pod 的资源请求值) * 100%。 如果 Pod 没有设置 spec.containers[].resources.requests,HPA 将无法进行有意义的计算。 示例:为 Nginx Deployment 配置同时基于 CPU 和内存的 HPA 1. 创建 Deployment (nginx-deployment.yaml) 这个 Deployment 明确设置了 CPU 和内存的 requests。 apiVersion: apps/v1 kind: Deployment metadata:   name: nginx-deployment   labels:     app: nginx spec:   replicas: 3 # 初始副本数   selector:     matchLabels:       app: nginx   template:     metadata:       labels:         app: nginx     spec:       containers:       - name: nginx         image: nginx:1.25         ports:         - containerPort: 80         resources:           requests:             cpu: "250m"   # 每个 Pod 请求 0.25 核 CPU             memory: "256Mi" # 每个 Pod 请求 256MiB 内存           limits:             cpu: "500m"             memory: "512Mi" 应用它:kubectl apply -f nginx-deployment.yaml 2. 创建 HPA (nginx-hpa.yaml) 我们使用 autoscaling/v2 API,它支持多指标和更丰富的配置。 apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata:   name: nginx-hpa spec:   scaleTargetRef:     apiVersion: apps/v1     kind: Deployment     name: nginx-deployment   minReplicas: 2   # 最小副本数   maxReplicas: 10  # 最大副本数   metrics:   - type: Resource     resource:       name: cpu       target:         type: Utilization # 目标类型为利用率         averageUtilization: 50 # CPU 平均使用率目标为 50%   - type: Resource     resource:       name: memory       target:         type: Utilization # 目标类型为利用率         averageUtilization: 70 # 内存平均使用率目标为 70%   behavior: # (可选) 高级伸缩行为控制     scaleDown:       stabilizationWindowSeconds: 300 # 缩容冷却期 300 秒 (5分钟)       policies:       - type: Pods         value: 2         periodSeconds: 60     scaleUp:       stabilizationWindowSeconds: 0       policies:       - type: Pods         value: 2         periodSeconds: 60 应用它:kubectl apply -f nginx-hpa.yaml HPA 行为解释 CPU 规则:HPA 会努力使所有 Pod 的 CPU 平均使用率 维持在 50%。 如果平均使用率是 75%,期望副本数 = ceil[3 * (75 / 50)] = ceil[3 * 1.5] = ceil[4.5] = 5。HPA 会将副本数扩容到 5。 内存规则:HPA 会努力使所有 Pod 的 内存平均使用率 维持在 70%。 如果平均使用率是 85%,期望副本数 = ceil[3 * (85 / 70)] = ceil[3 * 1.21] = ceil[3.63] = 4。 多指标决策:当同时配置了多个指标时,HPA 会分别计算每个指标所需的副本数,然后选择其中最大的那个值。 在上面的例子中,CPU 算出来需要 5 个,内存算出来需要 4 个,那么 HPA 最终会将副本数扩容到 5。 验证与监控 1.查看 HPA 状态: kubectl get hpa nginx-hpa -w 输出会显示当前的指标值、目标值、最小/最大副本数和当前的副本数。 NAME         REFERENCE                       TARGETS             MINPODS   MAXPODS   REPLICAS   AGE nginx-hpa    Deployment/nginx-deployment    50%/70%, 45%/65%    2         10        3          5m # TARGETS 列显示为 CPU目标%/内存目标%,当前CPU%/当前内存% 2.查看 HPA 详细信息: kubectl describe hpa nginx-hpa 这个命令会输出非常详细的信息,包括事件日志,帮助你诊断 HPA 为什么不伸缩。 三、最佳实践总结 必须设置 resources.requests:没有它,HPA 无法工作。 使用 autoscaling/v2 API:v2 比 v2beta2 更稳定,且功能强大。 谨慎设置目标值: 目标值设置过高(如 CPU 90%)可能导致 Pod 在触发扩容前就已过载。 目标值设置过低(如 CPU 10%)可能导致资源浪费和过多的副本。 建议:从保守值开始(如 CPU 50-70%),根据实际生产监控数据进行调整。 合理配置 minReplicas 和 maxReplicas: minReplicas 应保证应用的基本可用性。 maxReplicas 应避免因意外流量或程序 Bug 导致资源耗尽。 利用 behavior 字段控制伸缩速率和冷却:根据应用的启动和冷却特性,调整 scaleUp 和 scaleDown 策略,避免抖动。 结合就绪探针和存活探针:确保新扩容的 Pod 真正准备好接收流量后,才被纳入服务的负载均衡。 结合日志与事件:注意容忍度、冷却窗口对扩缩容的影响,关注 ScalingActive、ScalingLimited 等状态变化。 考虑使用自定义指标:对于 Web 服务,基于 HTTP QPS(每秒请求数)进行扩缩容通常比基于 CPU 更直接、更灵敏。这需要安装 Prometheus 和 Prometheus Adapter。 让应用支持平滑启动和终止:确保新 Pod 启动后能快速就绪(利用就绪探针),并在终止时能优雅处理完已有请求(处理 SIGTERM 信号),避免服务中断。 四、关于 HPA 的进阶思考 1. HPA 的局限性及与其他自动伸缩方案的搭配 HPA 主要负责 Pod 水平扩缩容,但它依赖于集群有足够的资源来调度新创建的 Pod。如果集群资源不足,即使 HPA 创建了新的 Pod,这些 Pod 也会因无法调度而处于 Pending 状态,无法提供服务。 因此,在生产环境中,HPA 通常需要与 Cluster Autoscaler (CA) 或 Karpenter 搭配使用: HPA: 负责应用层伸缩,根据业务负载调整 Pod 数量。 CA/Karpenter: 负责基础设施层伸缩,根据 Pod 的资源请求调整集群节点数量,为 HPA 创建的 Pod 提供运行资源。 2. 克服“弹性滞后”:AHPA 与预测性伸缩 传统 HPA 基于当前的监控指标进行反应式扩缩容,这存在一定的“弹性滞后”(Reactive Scaling)。即从流量增加到 HPA 完成扩容需要一定时间(指标采集、计算、Pod 启动、应用预热等),可能导致流量高峰时应用响应变慢。 为解决这个问题,出现了预测性弹性伸缩(Predictive Scaling)方案,如 Advanced Horizontal Pod Autoscaler (AHPA)。AHPA 能够分析历史指标数据(如过去几天的 CPU 负载、QPS 变化规律),预测未来的负载波动,并提前进行扩容。例如,对于每天早高峰流量明显增大的应用,AHPA 可以在高峰来临前就提前扩容,避免流量激增时的响应延迟。在业务低谷时,它也会定时回收资源,节约成本。 参考: Kubernetes Pod 水平自动扩缩 HorizontalPodAutoscaler 演练 HPA各关联组件流转关系以及建议 深入理解K8s HPA及增强特性设计实现

2026/1/12
articleCard.readMore

vLLM 部署Qwen2.5 LLM & VLM 大模型

Qwen2.5-32B 和 Qwen2.5-VL-32B 是通义千问(Qwen)系列中的两个大模型,分别对应纯语言模型(LLM)和多模态视觉-语言模型(VLM)。Docker环境安装与配置 NVIDIA Container Toolk,下载大模型参考 Docker部署bge-m3/bge-reranker模型。 模型简介 模型名称类型参数量特点 Qwen2.5-32B纯文本语言模型~32B支持中英文,推理、代码、对话能力强 Qwen2.5-VL-32B视觉-语言多模态模型~32B(含视觉编码器)支持图像理解、图文问答、多模态推理 注意:Qwen2.5-VL 基于 Qwen2.5 语言主干 + 视觉编码器(如 SigLIP 或 CLIP 变体),需同时加载视觉和语言组件。 部署前的硬件准备 部署前,需确认硬件环境满足基本要求。由于Qwen2.5-VL-32B是多模态模型,其显存需求通常高于纯文本模型。 资源Qwen2.5-32B (纯文本)Qwen2.5-VL-32B (多模态)说明 GPU显存建议 ≥ 24GB (单卡)建议 ≥ 32GB (单卡或多卡)使用量化版本(如GPTQ-Int4)可大幅降低显存需求。 系统内存建议 32GB+建议 64GB+避免模型加载时内存溢出(OOM)。 磁盘空间模型文件约需 60GB+模型文件约需 70GB+需预留额外空间存放Docker镜像和依赖。 OpenLLM - Qwen model    version                repo     required GPU RAM    platforms -------  ---------------------  -------  ------------------  ----------- qwen2.5  qwen2.5:0.5b           default  12G                 linux          qwen2.5:1.5b           default  12G                 linux          qwen2.5:3b             default  12G                 linux          qwen2.5:7b             default  24G                 linux          qwen2.5:14b            default  80G                 linux          qwen2.5:14b-ggml-q4    default                      macos          qwen2.5:14b-ggml-q8    default                      macos          qwen2.5:32b            default  80G                 linux          qwen2.5:32b-ggml-fp16  default                      macos          qwen2.5:72b            default  80Gx2               linux          qwen2.5:72b-ggml-q4    default                      macos 硬件要求 Qwen2.5-32B(纯文本): 推荐:2×A100 80GB(FP16)或 4×A10 24GB(INT4 量化) 最低:单卡 A100 80GB(INT4) Qwen2.5-VL-32B(多模态): 推荐:2×A100 80GB(FP16)或 4×A10 24GB(INT4) 需额外加载视觉编码器(如 ViT),显存需求略高 基于vLLM的Docker部署通用流程 下面以 vLLM框架 为例,介绍在Docker中部署这两个模型的通用步骤。vLLM是一个高效的推理和服务框架。 步骤一:准备环境与下载模型 1.安装依赖:确保系统已安装Docker、NVIDIA驱动和NVIDIA Container Toolkit(使Docker支持GPU)。 2.下载模型:推荐使用国内镜像源(如ModelScope)下载模型到本地目录。 # 示例:通过ModelScope下载Qwen2.5-32B-Instruct pip install modelscope modelscope download --model Qwen/Qwen2.5-32B-Instruct --local_dir /your/local/model/path 3.拉取Docker镜像:拉取官方vLLM镜像。 docker pull vllm/vllm-openai:latest 步骤二:启动Docker容器并运行模型 使用以下命令启动容器。请务必将命令中的 /your/local/model/path 和 Qwen2.5-32B-Instruct 替换为你实际部署的模型路径和名称(例如,部署VL模型时需替换为Qwen2.5-VL-32B-Instruct)。 docker run -d \   --gpus all \   -p 8000:8000 \   -v /your/local/model/path:/model \  # 将宿主机模型目录挂载到容器   --name vllm-qwen \   vllm/vllm-openai:latest \   --model /model \  # 容器内的模型路径   --served-model-name Qwen2.5-32B \  # 服务名称,可按需修改   --tensor-parallel-size 1 \  # 使用的GPU数量,单卡设为1   --gpu-memory-utilization 0.9 \  # GPU内存利用率,可调整以防OOM   --max-model-len 8192 \  # 最大序列长度,可根据需要调整   --trust-remote-code  # Qwen模型需要此参数 部署 Qwen2.5-VL-32B-Instruct docker run -d \   --gpus all \  # 允许容器使用所有GPU   -p 8000:8000 \  # 映射端口(主机端口:容器端口)   -v /your/local/model/path:/model \  # 挂载模型目录到容器内   --name vllm-qwen-vl \  # 容器名称   vllm/vllm-openai:latest \  # 使用的镜像   --model /model \  # 容器内模型路径 外部调用时入参model 需要与此处相同 注意此处有 /   --served-model-name Qwen2.5-VL-32B \  # 服务名称,可按需修改   --port 8000 \  # 容器内服务端口   --host 0.0.0.0 \  # 允许外部访问   --tensor-parallel-size 1 \  # 若单卡则设1,多卡按实际数量调整   --gpu-memory-utilization 0.9 \  # 允许使用90%的GPU内存(避免OOM)   --trust-remote-code  # 信任远程模型代码(Qwen模型需要) 关键参数说明: --tensor-parallel-size:根据你使用的GPU数量设置。例如,单卡设为1,双卡可设为2。 --gpu-memory-utilization:控制显存使用率。如果启动时出现内存不足(OOM)错误,可以尝试降低此值(如调整为0.8)。 --max-model-len:根据模型支持的上下文长度和你的需求调整。 --dtype float16:模型运行的数据类型:float16 是半精度浮点类型,相比 float32 可减少 GPU 内存占用(约节省一半),同时保持较好的推理精度。Qwen2.5 模型支持 float16,推荐使用(若 GPU 支持 bfloat16,也可改为 bfloat16)。 测试与验证部署 服务启动后,可以通过以下方式验证模型是否正常工作: 1.检查服务状态: curl http://localhost:8000/health 如果返回 {"status":"OK"} 或类似信息,说明服务已就绪。 2.发送推理请求进行测试: Qwen2.5-32B (文本):直接向其 /v1/completions 或 /v1/chat/completions 端点发送文本Prompt。 1. 测试聊天接口(推荐) curl http://localhost:8000/v1/chat/completions \   -H "Content-Type: application/json" \   -d '{     "model": "Qwen2.5-32B",     "messages": [       {"role": "user", "content": "你好,请介绍一下你自己。"}     ],     "max_tokens": 100,     "temperature": 0.7   }' 2. 测试流式输出(streaming) curl http://localhost:8000/v1/chat/completions \   -H "Content-Type: application/json" \   -d '{     "model": "Qwen2.5-32B",     "messages": [{"role": "user", "content": "写一首关于春天的诗。"}],     "stream": true,     "max_tokens": 150   }' Qwen2.5-VL-32B (多模态):需要构建一个包含图像和文本的多模态请求。可以参考官方GitHub仓库中的示例代码。 自定义 FastAPI + Transformers 1. Dockerfile(多模态) # Dockerfile(多模态) FROM nvcr.io/nvidia/pytorch:24.06-py3 RUN pip install --upgrade pip && \     pip install "transformers>=4.40" "accelerate" "torch" "torchvision" \     "pillow" "fastapi" "uvicorn" "einops" "timm" "qwen-vl-utils" \     -i https://pypi.tuna.tsinghua.edu.cn/simple COPY app_vl.py /app/app.py WORKDIR /app EXPOSE 8000 CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"] 2.app_vl.py(简化版) from fastapi import FastAPI, HTTPException from pydantic import BaseModel from PIL import Image import base64 import io from transformers import AutoModelForVision2Seq, AutoTokenizer app = FastAPI() # 加载模型(启动时加载) model = AutoModelForVision2Seq.from_pretrained(     "Qwen/Qwen2.5-VL-32B",     device_map="auto",     trust_remote_code=True,     torch_dtype="auto" ) processor = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-VL-32B", trust_remote_code=True) class VLRequest(BaseModel):     image_b64: str  # Base64 编码的图片     question: str @app.post("/vl") async def vision_language(request: VLRequest):     try:         # 解码图片         image_data = base64.b64decode(request.image_b64)         image = Image.open(io.BytesIO(image_data)).convert("RGB")         # 构造消息         messages = [{             "role": "user",             "content": [                 {"type": "image", "image": image},                 {"type": "text", "text": request.question}             ]         }]         # 预处理         inputs = processor(messages, return_tensors="pt", padding=True)         inputs = {k: v.to(model.device) for k, v in inputs.items()}         # 生成         output = model.generate(**inputs, max_new_tokens=256)         response = processor.decode(output[0], skip_special_tokens=True)         return {"response": response}     except Exception as e:         raise HTTPException(status_code=500, detail=str(e)) 3. 构建并运行 docker build -t qwen25-vl-32b -f Dockerfile.vl . docker run -d --gpus all -p 8001:8000 qwen25-vl-32b 4.curl 测试(需 Base64 图片) # 先将图片转为 base64 base64_image=$(base64 -i cat.jpg | tr -d '\n') curl http://localhost:8001/vl \   -H "Content-Type: application/json" \   -d "{     \"image_b64\": \"$base64_image\",     \"question\": \"图片中有什么动物?\"   }" 参考: NVIDIA GPU架构演进及使用场景 英伟达GPU参数速查表 常用AI模型介绍及多模型组合使用场景 大语言模型级别划分及使用场景 Docker部署bge-m3/bge-reranker模型 vLLM/Docker 部署Qwen2.5-VL-32B模型

2026/1/5
articleCard.readMore

奔波2025

如2024年终总结预想的一样,2025确实是奔波的一年,虽然结束北漂回到二线城市工作,但是在这一年里大多数时间都是在上海、广州等一线做项目交付,只是base在二线而已,相当于出差去一线干活,工作模式也与之前的工作有所区别,需要一个人将整个项目交付搞定,自己给自己兜底,之前至少还是有backup。工作上今年最大的收获算是从0到1将AI项目落地交付,2B项目交付这块也积累了很多宝贵的经验。生活上陪伴小孩和亲人的时间多了些,但是也仅仅是周末和节假日,不过也算比之前好多了。个人提升这块,这一年奔波来奔波去,尤其12月赶项目上线连续加了一个月班,周末都没休,加班加得都有点想吐了🤮。总体来说个人提升、学习这块今年是有所懈怠,退步了,一个是长期出差,加班没时间,一个是来回奔波比较累,有时也懒得学习了,这块2026年还得提起来。 苦功、内功、外功,苦功其实对于个人来说是收益最低的,但是为了工作生活大多时候又不得不做,而且做得多,最后的效果也不一定好,当然这其中也有些是个人性格、工作习惯原因。工作已然十多年了,人生也已过半,还记得当时去小米面试,经理问我喜欢做什么样的工作,我回答的是有挑战性的工作,后面的工作大抵都是如此。后来接触佛学,禅宗后,明白了发愿,承诺都不是件简单的事。信愿证行,人是自我的主宰,心是天地的主宰,求锤得锤,所求必应。正所谓“祸福无门,唯人自召;善恶之报,如影随形。”这让我想起了《西游记》里的那首诗“人心生一念,天地悉皆知,善恶若无报,乾坤必有私”。 2026对个人来说大概率是伏吟局,还是多学习,多提升,多行善积德,干就完事了。“天行健,君子以自强不息;地势坤,君子以厚德载物”。如何在逆境中跃升?如何自利自他?如何修齐治平?“破山中贼易,破心中贼难”,人生尔尔,也不过如些而已。最后就以一首诗——《道心》,一首歌作为2025年,也是人生上半生的总结吧。在新的征途里,祝诸君武运昌隆,所求皆如愿,所行化坦途,多喜乐,长安宁。 [hermit autoplay="false" mode="circulation" preload="none"]remote#:610[/hermit] 参考: 转折2024 周易《大象传》详解

2025/12/31
articleCard.readMore

《道心》

《道心》 半生清贫半生缘, 心无归处道未明, 轮回路上日夜苦, 回首已是万千年。                   -- 2025.12.11

2025/12/29
articleCard.readMore

多个模型复用同一张GPU卡方案

上一篇我们使用 Docker部署bge-m3/bge-reranker模型,由于测试环境GPU卡资源紧张,基于成本考虑,需要在同一张卡上运行多个模型。现在以 bge-m3/bge-reranker 模型为例,将两个模型部署在同一张英伟达 L20 GPU卡上。 🎯 同时运行的方案 方案1:使用不同端口分别部署(推荐) 这是最直接和稳定的方式: # 启动 embedding 模型(使用端口 8080) docker run -d --name bge-embedding --runtime nvidia --gpus '"device=0"' \   -v /path/to/embedding-model:/mnt/models \   -p 8080:8080 --ipc=host \   --entrypoint=text-embeddings-router \   ghcr.io/huggingface/text-embeddings-inference:1.6 \   --model-id /mnt/models --port 8080 \   --max-batch-tokens 16384 --max-concurrent-requests 256 \   --max-client-batch-size 16 # 启动 rerank 模型(使用端口 8081) docker run -d --name bge-reranker --runtime nvidia --gpus '"device=0"' \   -v /path/to/reranker-model:/mnt/models \   -p 8081:8080 --ipc=host \   --entrypoint=text-embeddings-router \   ghcr.io/huggingface/text-embeddings-inference:1.6 \   --model-id /mnt/models --port 8080 \   --max-batch-tokens 8192 --max-concurrent-requests 128 \   --max-client-batch-size 8 方案2:使用不同GPU内存限制 如果担心资源竞争,可以为每个容器设置GPU内存限制: # 为embedding模型分配较多显存 docker run -d --name bge-embedding --runtime nvidia --gpus '"device=0"' \   -e NVIDIA_VISIBLE_DEVICES=1 \   -e NVIDIA_DRIVER_CAPABILITIES=compute,utility \   --memory=8g --memory-swap=10g \   -p 8080:8080 \   # ... 其他参数 # 为reranker模型分配较少显存 docker run -d --name bge-reranker --runtime nvidia --gpus '"device=0"' \   -e NVIDIA_VISIBLE_DEVICES=1 \   -e NVIDIA_DRIVER_CAPABILITIES=compute,utility \   --memory=4g --memory-swap=6g \   -p 8081:8080 \   # ... 其他参数 📊 资源规划建议 GPU显存需求估算 模型类型基础模型大小显存需求(近似)批处理大小影响 Embedding模型110M-335M1-3GB+0.5-1GB(批处理) Reranker模型110M-278M1-2.5GB+0.3-0.8GB(批处理) NVIDIA L20有48GB显存,同时运行两个模型绰绰有余。 性能优化配置 # Embedding模型(通常需要更高吞吐量) --max-concurrent-requests 256 --max-client-batch-size 16 --max-batch-tokens 16384 # Reranker模型(通常延迟更敏感) --max-concurrent-requests 128   --max-client-batch-size 8 --max-batch-tokens 8192 🔧 验证同时运行状态 1. 检查容器状态 docker ps | grep -E "(bge-embedding|bge-reranker)" 2. 监控GPU使用情况 # 实时监控GPU使用 watch -n 1 nvidia-smi # 或使用更详细的监控 nvidia-smi --query-gpu=index,name,utilization.gpu,utilization.memory,memory.used,memory.total --format=csv -l 2 3. 分别测试两个服务 # 测试embedding服务 curl -X POST http://localhost:8080/embed \   -H "Content-Type: application/json" \   -d '{"inputs": "测试文本"}' # 测试rerank服务   curl -X POST http://localhost:8081/rerank \   -H "Content-Type: application/json" \   -d '{     "query": "测试查询",     "texts": ["文档1", "文档2"]   }' ⚠️ 注意事项 显存竞争:虽然可以同时运行,但在高并发时可能会有显存竞争 性能隔离:一个模型的负载高峰可能影响另一个模型的响应时间 故障隔离:一个容器崩溃不会影响另一个容器 资源监控:建议设置监控告警,及时发现资源瓶颈 🚀 生产环境建议 对于生产环境,推荐: 使用Kubernetes进行资源管理和弹性伸缩 设置资源限制确保公平性 实现健康检查和自动恢复 使用负载均衡在多个实例间分发请求 总结:在L20 GPU上同时运行embedding和reranker模型是完全可行的,只需合理分配端口和调整资源参数即可,对于多个模型利用同一张GPU卡,生产环境还是慎用。 参考: 常用AI模型介绍及多模型组合使用场景 英伟达GPU参数速查表

2025/12/26
articleCard.readMore