Qwen2.5-1.5B部署实操Kubernetes集群中部署Qwen2.5-1.5B微服务架构1. 项目概述为什么要在K8s里部署轻量级大模型如果你正在寻找一个能在自己服务器上快速跑起来的智能对话助手Qwen2.5-1.5B-Instruct模型是个不错的选择。它只有15亿参数对硬件要求不高但对话能力却相当不错日常问答、写点文案、解答技术问题都能胜任。但直接在一台服务器上部署总会遇到些麻烦服务重启了怎么办想同时服务多个用户怎么扩展怎么管理日志和监控这时候Kubernetes简称K8s的价值就体现出来了。把Qwen2.5-1.5B打包成微服务放到K8s集群里运行能带来几个实实在在的好处高可用容器挂了K8s会自动重启一个新的服务基本不会中断。弹性伸缩用户多了自动多开几个副本用户少了自动收缩节省资源。统一管理日志、监控、配置、网络全部通过K8s来管理运维起来省心。资源隔离每个服务实例都在独立的容器里互不干扰更稳定安全。这篇文章我就带你一步步把Qwen2.5-1.5B这个本地对话助手从单机脚本变成一个能在K8s集群里稳定运行的微服务。整个过程清晰直白即便你对K8s不是特别熟跟着做也能搞定。2. 从单机脚本到微服务容器化改造原来的项目是一个基于Streamlit的单文件应用。要上K8s第一步就是把它装进“集装箱”——也就是Docker容器里。2.1 编写Dockerfile构建应用镜像我们需要创建一个Dockerfile告诉Docker如何构建我们的应用镜像。核心思路是选择一个轻量的基础镜像安装必要的依赖复制我们的代码和模型文件设置好启动命令。# 使用带有Python和CUDA的轻量级官方镜像如果只用CPU可换成python:3.10-slim FROM nvcr.io/nvidia/pytorch:23.10-py3 # 设置工作目录 WORKDIR /app # 复制依赖文件并安装 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple # 复制应用代码 COPY app.py . # 假设模型文件通过其他方式如持久化卷挂载到 /model 目录 # 这里创建一个目录实际运行时会由K8s的Volume挂载真实模型数据 RUN mkdir -p /model # 暴露Streamlit默认端口 EXPOSE 8501 # 设置健康检查可选但推荐 HEALTHCHECK --interval30s --timeout10s --start-period30s --retries3 \ CMD python -c import requests; requests.get(http://localhost:8501/_stcore/health) # 启动命令设置服务器地址和端口以便集群内访问 CMD [streamlit, run, app.py, --server.port8501, --server.address0.0.0.0]关键点说明基础镜像选择了NVIDIA官方的PyTorch镜像已经包含了CUDA环境。如果你的集群没有GPU或者想用CPU推理换成python:3.10-slim会更小。依赖安装通过requirements.txt文件管理依赖并用国内镜像源加速。模型文件注意我们没有把巨大的模型文件可能好几个GB直接打包进镜像那样会导致镜像臃肿且难以更新。这里只是创建了一个/model目录模型文件将通过K8s的“持久化存储卷”在容器启动时挂载进去。这是生产环境的最佳实践。健康检查添加了HEALTHCHECK指令K8s可以利用这个信息判断容器是否健康并做出重启等决策。启动命令--server.address0.0.0.0很重要让Streamlit服务监听所有网络接口才能被集群内其他服务访问。2.2 准备requirements.txt创建一个requirements.txt文件列出项目所需的所有Python包。streamlit1.28.0 torch2.0.0 transformers4.35.0 accelerate0.24.0 sentencepiece # Qwen分词器可能需要 tiktoken # 某些版本Qwen可能用到2.3 改造app.py适应容器化环境原来的app.py需要做一点小调整主要是让模型路径可以灵活配置而不是写死在代码里。import os import streamlit as st from transformers import AutoModelForCausalLM, AutoTokenizer import torch # 从环境变量读取模型路径默认为 /model MODEL_PATH os.getenv(MODEL_PATH, /model/qwen1.5b) # 使用Streamlit缓存机制避免每次交互重复加载模型 st.cache_resource def load_model_and_tokenizer(): st.write(f 正在从 {MODEL_PATH} 加载模型...) # 自动选择设备和数据类型 model AutoModelForCausalLM.from_pretrained( MODEL_PATH, torch_dtypeauto, device_mapauto, trust_remote_codeTrue # Qwen模型需要此参数 ) tokenizer AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_codeTrue) st.success(✅ 模型加载完成) return model, tokenizer # 后续的Streamlit界面代码保持不变... # 包括侧边栏、聊天历史、生成逻辑等改动说明关键的一行是MODEL_PATH os.getenv(MODEL_PATH, /model/qwen1.5b)。现在模型路径可以从环境变量MODEL_PATH读取。这样我们在K8s的配置文件中就可以灵活指定模型文件实际挂载的位置而不用修改代码。2.4 构建并推送镜像在本地或者CI/CD服务器上执行以下命令构建镜像并推送到你的容器镜像仓库如Docker Hub、阿里云容器镜像服务、Harbor等。# 构建镜像 docker build -t your-registry/your-namespace/qwen-chat:1.0 . # 登录镜像仓库 docker login your-registry # 推送镜像 docker push your-registry/your-namespace/qwen-chat:1.0到这里我们的应用就已经完成了容器化改造准备好了上云的原型。3. Kubernetes部署实战编写YAML清单接下来是核心部分编写K8s的部署配置文件。我们主要需要三个YAML文件一个用于配置模型存储一个用于部署应用一个用于对外暴露服务。3.1 模型存储配置PersistentVolumeClaim (PVC)模型文件很大我们需要一个持久化的存储来存放它并在Pod中挂载。这里以使用K8s集群的本地存储Local PersistentVolume为例如果你的集群在云上可以使用云盘如AWS EBS Azure Disk。首先创建一个pvc-model.yaml文件。这里假设集群管理员已经创建了名为local-model-storage的StorageClass。apiVersion: v1 kind: PersistentVolumeClaim metadata: name: qwen-model-pvc namespace: ai-services # 指定命名空间建议单独创建 spec: storageClassName: local-model-storage # 替换为你的StorageClass accessModes: - ReadOnlyMany # 多个Pod可以只读挂载适合模型文件 resources: requests: storage: 10Gi # 根据Qwen2.5-1.5B模型实际大小调整通常3-4GB足够3.2 应用部署配置Deployment这是最重要的文件定义了如何运行我们的容器。创建deployment.yaml。apiVersion: apps/v1 kind: Deployment metadata: name: qwen-chat-deployment namespace: ai-services labels: app: qwen-chat spec: replicas: 2 # 启动2个副本实现负载均衡和基础高可用 selector: matchLabels: app: qwen-chat template: metadata: labels: app: qwen-chat spec: # 如果节点有GPU可以添加以下节点选择器和资源限制 # nodeSelector: # accelerator: nvidia-gpu containers: - name: qwen-chat-container image: your-registry/your-namespace/qwen-chat:1.0 # 替换为你的镜像地址 imagePullPolicy: IfNotPresent ports: - containerPort: 8501 env: - name: MODEL_PATH value: /mnt/model # 与下面volumeMount的路径对应 resources: # 资源请求和限制根据模型推理实际消耗调整 requests: memory: 4Gi cpu: 1 limits: memory: 8Gi cpu: 2 volumeMounts: - name: model-storage mountPath: /mnt/model readOnly: true # 配置存活探针和就绪探针提升服务可靠性 livenessProbe: httpGet: path: /_stcore/health port: 8501 initialDelaySeconds: 60 # 给模型加载留出足够时间 periodSeconds: 30 readinessProbe: httpGet: path: /_stcore/health port: 8501 initialDelaySeconds: 60 periodSeconds: 10 volumes: - name: model-storage persistentVolumeClaim: claimName: qwen-model-pvc # 使用上面创建的PVC配置详解replicas: 2启动两个相同的Pod实例。如果一个出问题另一个还能继续服务K8s也会自动补齐副本数。resources非常重要。这里定义了容器需要和最多能使用的CPU/内存资源。requests是调度依据limits是硬性上限。一定要根据你模型加载和推理时的实际内存占用可以用nvidia-smi或top命令观察来设置设置太小会导致Pod被KillOOM设置太大会浪费资源。volumeMounts将名为model-storage的卷挂载到容器的/mnt/model路径。这样容器里就能访问到模型文件了。livenessProbereadinessProbe健康检查。livenessProbe失败K8s会重启容器readinessProbe失败K8s会将该Pod从服务负载均衡中移除。它们能有效处理模型加载失败或应用假死的情况。nodeSelector注释中如果你的集群部分节点有GPU可以用这个标签选择将Pod调度到有GPU的节点上加速推理。3.3 服务暴露配置ServicePod的IP地址是不固定的我们需要一个固定的入口。创建service.yaml定义一个Service来暴露我们的Deployment。apiVersion: v1 kind: Service metadata: name: qwen-chat-service namespace: ai-services spec: selector: app: qwen-chat # 选择标签为app: qwen-chat的Pod ports: - port: 80 # Service对集群内暴露的端口 targetPort: 8501 # 容器内部的端口 protocol: TCP type: ClusterIP # 类型为ClusterIP仅在集群内部可访问现在在K8s集群内部其他服务就可以通过http://qwen-chat-service.ai-services.svc.cluster.local这个域名来访问我们的对话助手了。3.4 对外访问配置Ingress (可选)如果想让集群外部的用户通过浏览器访问就需要配置Ingress。这需要一个Ingress Controller如Nginx Ingress Controller。创建ingress.yaml。apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: qwen-chat-ingress namespace: ai-services annotations: # 以下注解根据你使用的Ingress Controller类型调整 nginx.ingress.kubernetes.io/rewrite-target: / nginx.ingress.kubernetes.io/proxy-body-size: 50m # 允许较大的请求体 spec: rules: - host: qwen.yourcompany.com # 你的域名 http: paths: - path: / pathType: Prefix backend: service: name: qwen-chat-service port: number: 80配置好DNS解析将域名qwen.yourcompany.com指向你的K8s集群Ingress Controller的公网IP用户就能通过这个网址访问服务了。4. 部署与验证让服务跑起来配置文件准备好了接下来就是执行和验证。4.1 按顺序部署资源在拥有kubectl命令行工具并配置好集群连接的机器上执行以下命令。# 1. 创建命名空间如果不存在 kubectl create namespace ai-services # 2. 部署存储声明PVC kubectl apply -f pvc-model.yaml -n ai-services # 3. 部署应用Deployment kubectl apply -f deployment.yaml -n ai-services # 4. 部署内部服务Service kubectl apply -f service.yaml -n ai-services # 5. 部署外部访问Ingress如果需要 kubectl apply -f ingress.yaml -n ai-services4.2 检查部署状态使用以下命令检查各个资源的创建和运行状态。# 查看Pod状态应该看到2个Running的Pod kubectl get pods -n ai-services -l appqwen-chat # 查看Deployment状态 kubectl get deployment qwen-chat-deployment -n ai-services # 查看Service kubectl get service qwen-chat-service -n ai-services # 查看Ingress如果部署了 kubectl get ingress qwen-chat-ingress -n ai-services # 查看Pod的详细信息和日志特别是初始化时的日志检查模型是否加载成功 kubectl logs -n ai-services deployment/qwen-chat-deployment --tail504.3 验证服务功能集群内访问在集群内另一个Pod里用curl命令测试。# 获取Service的集群内域名 kubectl run test-curl --imagecurlimages/curl -it --rm --restartNever -- /bin/sh # 进入临时容器后执行 curl http://qwen-chat-service.ai-services.svc.cluster.local你应该能看到Streamlit的HTML页面内容。端口转发临时访问如果你想在本地浏览器快速测试可以将Service端口转发到本地。kubectl port-forward -n ai-services service/qwen-chat-service 8501:80然后在浏览器访问http://localhost:8501。通过Ingress访问如果配置了Ingress和域名直接在浏览器访问你的域名如http://qwen.yourcompany.com应该就能看到熟悉的Streamlit聊天界面了。尝试输入问题看看模型是否能正常回复。5. 生产环境进阶考量把服务跑起来只是第一步要用于生产还需要考虑更多。5.1 配置管理使用ConfigMap将环境变量、配置文件等与镜像解耦。例如可以把模型路径、生成参数temperature,top_p放到ConfigMap里。apiVersion: v1 kind: ConfigMap metadata: name: qwen-chat-config namespace: ai-services data: MODEL_PATH: /mnt/model GENERATION_MAX_LENGTH: 1024 GENERATION_TEMPERATURE: 0.7然后在Deployment中通过configMapKeyRef引用。5.2 密钥管理使用Secret如果模型文件存放在需要认证的私有存储如S3或者应用需要访问数据库账号密码等敏感信息必须用Secret管理。apiVersion: v1 kind: Secret metadata: name: model-store-secret namespace: ai-services type: Opaque data: access-key: base64编码的密钥 secret-key: base64编码的密钥5.3 自动伸缩HPA根据CPU或内存使用率自动调整Pod的数量。你需要部署Metrics Server。apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: qwen-chat-hpa namespace: ai-services spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: qwen-chat-deployment minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 # 当CPU平均使用率超过70%时扩容5.4 日志与监控日志确保应用日志输出到标准输出stdout和标准错误stderrK8s会自动收集。可以使用EFKElasticsearch, Fluentd, Kibana或LokiGrafana套件进行集中日志管理。监控为Pod定义Prometheus格式的指标暴露端点或使用Sidecar模式。然后通过Prometheus采集用Grafana展示。监控模型推理延迟、QPS、错误率、资源使用率等关键指标。6. 总结通过以上步骤我们成功地将一个单机的Qwen2.5-1.5B对话助手部署成了一个高可用、可扩展、易管理的Kubernetes微服务。我们来回顾一下关键点容器化是基础编写Dockerfile将应用及其依赖打包成标准镜像实现环境一致性。分离模型与镜像使用PVC持久化存储模型文件避免镜像臃肿方便模型更新。Deployment是核心定义应用的副本数、资源需求、健康检查、存储挂载等运行规格。Service提供稳定访问为动态的Pod提供一个固定的网络端点。Ingress实现外部访问将集群内部服务暴露给公网用户。生产化配置通过ConfigMap、Secret、HPA、监控日志等手段提升服务的可靠性、安全性和可运维性。这套方案不仅适用于Qwen2.5-1.5B也适用于其他类似的轻量级AI模型服务。K8s的生态让AI模型的部署、运维和规模化变得前所未有的清晰和高效。你可以在此基础上继续探索服务网格Istio、GPU共享、模型版本管理Kserve/Knative等更高级的主题构建更强大的AI服务平台。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。
Qwen2.5-1.5B部署实操:Kubernetes集群中部署Qwen2.5-1.5B微服务架构
发布时间:2026/6/18 14:30:05
Qwen2.5-1.5B部署实操Kubernetes集群中部署Qwen2.5-1.5B微服务架构1. 项目概述为什么要在K8s里部署轻量级大模型如果你正在寻找一个能在自己服务器上快速跑起来的智能对话助手Qwen2.5-1.5B-Instruct模型是个不错的选择。它只有15亿参数对硬件要求不高但对话能力却相当不错日常问答、写点文案、解答技术问题都能胜任。但直接在一台服务器上部署总会遇到些麻烦服务重启了怎么办想同时服务多个用户怎么扩展怎么管理日志和监控这时候Kubernetes简称K8s的价值就体现出来了。把Qwen2.5-1.5B打包成微服务放到K8s集群里运行能带来几个实实在在的好处高可用容器挂了K8s会自动重启一个新的服务基本不会中断。弹性伸缩用户多了自动多开几个副本用户少了自动收缩节省资源。统一管理日志、监控、配置、网络全部通过K8s来管理运维起来省心。资源隔离每个服务实例都在独立的容器里互不干扰更稳定安全。这篇文章我就带你一步步把Qwen2.5-1.5B这个本地对话助手从单机脚本变成一个能在K8s集群里稳定运行的微服务。整个过程清晰直白即便你对K8s不是特别熟跟着做也能搞定。2. 从单机脚本到微服务容器化改造原来的项目是一个基于Streamlit的单文件应用。要上K8s第一步就是把它装进“集装箱”——也就是Docker容器里。2.1 编写Dockerfile构建应用镜像我们需要创建一个Dockerfile告诉Docker如何构建我们的应用镜像。核心思路是选择一个轻量的基础镜像安装必要的依赖复制我们的代码和模型文件设置好启动命令。# 使用带有Python和CUDA的轻量级官方镜像如果只用CPU可换成python:3.10-slim FROM nvcr.io/nvidia/pytorch:23.10-py3 # 设置工作目录 WORKDIR /app # 复制依赖文件并安装 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple # 复制应用代码 COPY app.py . # 假设模型文件通过其他方式如持久化卷挂载到 /model 目录 # 这里创建一个目录实际运行时会由K8s的Volume挂载真实模型数据 RUN mkdir -p /model # 暴露Streamlit默认端口 EXPOSE 8501 # 设置健康检查可选但推荐 HEALTHCHECK --interval30s --timeout10s --start-period30s --retries3 \ CMD python -c import requests; requests.get(http://localhost:8501/_stcore/health) # 启动命令设置服务器地址和端口以便集群内访问 CMD [streamlit, run, app.py, --server.port8501, --server.address0.0.0.0]关键点说明基础镜像选择了NVIDIA官方的PyTorch镜像已经包含了CUDA环境。如果你的集群没有GPU或者想用CPU推理换成python:3.10-slim会更小。依赖安装通过requirements.txt文件管理依赖并用国内镜像源加速。模型文件注意我们没有把巨大的模型文件可能好几个GB直接打包进镜像那样会导致镜像臃肿且难以更新。这里只是创建了一个/model目录模型文件将通过K8s的“持久化存储卷”在容器启动时挂载进去。这是生产环境的最佳实践。健康检查添加了HEALTHCHECK指令K8s可以利用这个信息判断容器是否健康并做出重启等决策。启动命令--server.address0.0.0.0很重要让Streamlit服务监听所有网络接口才能被集群内其他服务访问。2.2 准备requirements.txt创建一个requirements.txt文件列出项目所需的所有Python包。streamlit1.28.0 torch2.0.0 transformers4.35.0 accelerate0.24.0 sentencepiece # Qwen分词器可能需要 tiktoken # 某些版本Qwen可能用到2.3 改造app.py适应容器化环境原来的app.py需要做一点小调整主要是让模型路径可以灵活配置而不是写死在代码里。import os import streamlit as st from transformers import AutoModelForCausalLM, AutoTokenizer import torch # 从环境变量读取模型路径默认为 /model MODEL_PATH os.getenv(MODEL_PATH, /model/qwen1.5b) # 使用Streamlit缓存机制避免每次交互重复加载模型 st.cache_resource def load_model_and_tokenizer(): st.write(f 正在从 {MODEL_PATH} 加载模型...) # 自动选择设备和数据类型 model AutoModelForCausalLM.from_pretrained( MODEL_PATH, torch_dtypeauto, device_mapauto, trust_remote_codeTrue # Qwen模型需要此参数 ) tokenizer AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_codeTrue) st.success(✅ 模型加载完成) return model, tokenizer # 后续的Streamlit界面代码保持不变... # 包括侧边栏、聊天历史、生成逻辑等改动说明关键的一行是MODEL_PATH os.getenv(MODEL_PATH, /model/qwen1.5b)。现在模型路径可以从环境变量MODEL_PATH读取。这样我们在K8s的配置文件中就可以灵活指定模型文件实际挂载的位置而不用修改代码。2.4 构建并推送镜像在本地或者CI/CD服务器上执行以下命令构建镜像并推送到你的容器镜像仓库如Docker Hub、阿里云容器镜像服务、Harbor等。# 构建镜像 docker build -t your-registry/your-namespace/qwen-chat:1.0 . # 登录镜像仓库 docker login your-registry # 推送镜像 docker push your-registry/your-namespace/qwen-chat:1.0到这里我们的应用就已经完成了容器化改造准备好了上云的原型。3. Kubernetes部署实战编写YAML清单接下来是核心部分编写K8s的部署配置文件。我们主要需要三个YAML文件一个用于配置模型存储一个用于部署应用一个用于对外暴露服务。3.1 模型存储配置PersistentVolumeClaim (PVC)模型文件很大我们需要一个持久化的存储来存放它并在Pod中挂载。这里以使用K8s集群的本地存储Local PersistentVolume为例如果你的集群在云上可以使用云盘如AWS EBS Azure Disk。首先创建一个pvc-model.yaml文件。这里假设集群管理员已经创建了名为local-model-storage的StorageClass。apiVersion: v1 kind: PersistentVolumeClaim metadata: name: qwen-model-pvc namespace: ai-services # 指定命名空间建议单独创建 spec: storageClassName: local-model-storage # 替换为你的StorageClass accessModes: - ReadOnlyMany # 多个Pod可以只读挂载适合模型文件 resources: requests: storage: 10Gi # 根据Qwen2.5-1.5B模型实际大小调整通常3-4GB足够3.2 应用部署配置Deployment这是最重要的文件定义了如何运行我们的容器。创建deployment.yaml。apiVersion: apps/v1 kind: Deployment metadata: name: qwen-chat-deployment namespace: ai-services labels: app: qwen-chat spec: replicas: 2 # 启动2个副本实现负载均衡和基础高可用 selector: matchLabels: app: qwen-chat template: metadata: labels: app: qwen-chat spec: # 如果节点有GPU可以添加以下节点选择器和资源限制 # nodeSelector: # accelerator: nvidia-gpu containers: - name: qwen-chat-container image: your-registry/your-namespace/qwen-chat:1.0 # 替换为你的镜像地址 imagePullPolicy: IfNotPresent ports: - containerPort: 8501 env: - name: MODEL_PATH value: /mnt/model # 与下面volumeMount的路径对应 resources: # 资源请求和限制根据模型推理实际消耗调整 requests: memory: 4Gi cpu: 1 limits: memory: 8Gi cpu: 2 volumeMounts: - name: model-storage mountPath: /mnt/model readOnly: true # 配置存活探针和就绪探针提升服务可靠性 livenessProbe: httpGet: path: /_stcore/health port: 8501 initialDelaySeconds: 60 # 给模型加载留出足够时间 periodSeconds: 30 readinessProbe: httpGet: path: /_stcore/health port: 8501 initialDelaySeconds: 60 periodSeconds: 10 volumes: - name: model-storage persistentVolumeClaim: claimName: qwen-model-pvc # 使用上面创建的PVC配置详解replicas: 2启动两个相同的Pod实例。如果一个出问题另一个还能继续服务K8s也会自动补齐副本数。resources非常重要。这里定义了容器需要和最多能使用的CPU/内存资源。requests是调度依据limits是硬性上限。一定要根据你模型加载和推理时的实际内存占用可以用nvidia-smi或top命令观察来设置设置太小会导致Pod被KillOOM设置太大会浪费资源。volumeMounts将名为model-storage的卷挂载到容器的/mnt/model路径。这样容器里就能访问到模型文件了。livenessProbereadinessProbe健康检查。livenessProbe失败K8s会重启容器readinessProbe失败K8s会将该Pod从服务负载均衡中移除。它们能有效处理模型加载失败或应用假死的情况。nodeSelector注释中如果你的集群部分节点有GPU可以用这个标签选择将Pod调度到有GPU的节点上加速推理。3.3 服务暴露配置ServicePod的IP地址是不固定的我们需要一个固定的入口。创建service.yaml定义一个Service来暴露我们的Deployment。apiVersion: v1 kind: Service metadata: name: qwen-chat-service namespace: ai-services spec: selector: app: qwen-chat # 选择标签为app: qwen-chat的Pod ports: - port: 80 # Service对集群内暴露的端口 targetPort: 8501 # 容器内部的端口 protocol: TCP type: ClusterIP # 类型为ClusterIP仅在集群内部可访问现在在K8s集群内部其他服务就可以通过http://qwen-chat-service.ai-services.svc.cluster.local这个域名来访问我们的对话助手了。3.4 对外访问配置Ingress (可选)如果想让集群外部的用户通过浏览器访问就需要配置Ingress。这需要一个Ingress Controller如Nginx Ingress Controller。创建ingress.yaml。apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: qwen-chat-ingress namespace: ai-services annotations: # 以下注解根据你使用的Ingress Controller类型调整 nginx.ingress.kubernetes.io/rewrite-target: / nginx.ingress.kubernetes.io/proxy-body-size: 50m # 允许较大的请求体 spec: rules: - host: qwen.yourcompany.com # 你的域名 http: paths: - path: / pathType: Prefix backend: service: name: qwen-chat-service port: number: 80配置好DNS解析将域名qwen.yourcompany.com指向你的K8s集群Ingress Controller的公网IP用户就能通过这个网址访问服务了。4. 部署与验证让服务跑起来配置文件准备好了接下来就是执行和验证。4.1 按顺序部署资源在拥有kubectl命令行工具并配置好集群连接的机器上执行以下命令。# 1. 创建命名空间如果不存在 kubectl create namespace ai-services # 2. 部署存储声明PVC kubectl apply -f pvc-model.yaml -n ai-services # 3. 部署应用Deployment kubectl apply -f deployment.yaml -n ai-services # 4. 部署内部服务Service kubectl apply -f service.yaml -n ai-services # 5. 部署外部访问Ingress如果需要 kubectl apply -f ingress.yaml -n ai-services4.2 检查部署状态使用以下命令检查各个资源的创建和运行状态。# 查看Pod状态应该看到2个Running的Pod kubectl get pods -n ai-services -l appqwen-chat # 查看Deployment状态 kubectl get deployment qwen-chat-deployment -n ai-services # 查看Service kubectl get service qwen-chat-service -n ai-services # 查看Ingress如果部署了 kubectl get ingress qwen-chat-ingress -n ai-services # 查看Pod的详细信息和日志特别是初始化时的日志检查模型是否加载成功 kubectl logs -n ai-services deployment/qwen-chat-deployment --tail504.3 验证服务功能集群内访问在集群内另一个Pod里用curl命令测试。# 获取Service的集群内域名 kubectl run test-curl --imagecurlimages/curl -it --rm --restartNever -- /bin/sh # 进入临时容器后执行 curl http://qwen-chat-service.ai-services.svc.cluster.local你应该能看到Streamlit的HTML页面内容。端口转发临时访问如果你想在本地浏览器快速测试可以将Service端口转发到本地。kubectl port-forward -n ai-services service/qwen-chat-service 8501:80然后在浏览器访问http://localhost:8501。通过Ingress访问如果配置了Ingress和域名直接在浏览器访问你的域名如http://qwen.yourcompany.com应该就能看到熟悉的Streamlit聊天界面了。尝试输入问题看看模型是否能正常回复。5. 生产环境进阶考量把服务跑起来只是第一步要用于生产还需要考虑更多。5.1 配置管理使用ConfigMap将环境变量、配置文件等与镜像解耦。例如可以把模型路径、生成参数temperature,top_p放到ConfigMap里。apiVersion: v1 kind: ConfigMap metadata: name: qwen-chat-config namespace: ai-services data: MODEL_PATH: /mnt/model GENERATION_MAX_LENGTH: 1024 GENERATION_TEMPERATURE: 0.7然后在Deployment中通过configMapKeyRef引用。5.2 密钥管理使用Secret如果模型文件存放在需要认证的私有存储如S3或者应用需要访问数据库账号密码等敏感信息必须用Secret管理。apiVersion: v1 kind: Secret metadata: name: model-store-secret namespace: ai-services type: Opaque data: access-key: base64编码的密钥 secret-key: base64编码的密钥5.3 自动伸缩HPA根据CPU或内存使用率自动调整Pod的数量。你需要部署Metrics Server。apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: qwen-chat-hpa namespace: ai-services spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: qwen-chat-deployment minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 # 当CPU平均使用率超过70%时扩容5.4 日志与监控日志确保应用日志输出到标准输出stdout和标准错误stderrK8s会自动收集。可以使用EFKElasticsearch, Fluentd, Kibana或LokiGrafana套件进行集中日志管理。监控为Pod定义Prometheus格式的指标暴露端点或使用Sidecar模式。然后通过Prometheus采集用Grafana展示。监控模型推理延迟、QPS、错误率、资源使用率等关键指标。6. 总结通过以上步骤我们成功地将一个单机的Qwen2.5-1.5B对话助手部署成了一个高可用、可扩展、易管理的Kubernetes微服务。我们来回顾一下关键点容器化是基础编写Dockerfile将应用及其依赖打包成标准镜像实现环境一致性。分离模型与镜像使用PVC持久化存储模型文件避免镜像臃肿方便模型更新。Deployment是核心定义应用的副本数、资源需求、健康检查、存储挂载等运行规格。Service提供稳定访问为动态的Pod提供一个固定的网络端点。Ingress实现外部访问将集群内部服务暴露给公网用户。生产化配置通过ConfigMap、Secret、HPA、监控日志等手段提升服务的可靠性、安全性和可运维性。这套方案不仅适用于Qwen2.5-1.5B也适用于其他类似的轻量级AI模型服务。K8s的生态让AI模型的部署、运维和规模化变得前所未有的清晰和高效。你可以在此基础上继续探索服务网格Istio、GPU共享、模型版本管理Kserve/Knative等更高级的主题构建更强大的AI服务平台。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。