轻量K8s部署AI大模型 私有化服务器攻略

阿木 发布于 1 天前 1 次阅读


真实来讲,你不要去看当下到处都是在谈论大模型、算力池的情况,一旦真正涉及到钱的时候,问题就发生了变化。

上周,跟一位,从事金融行当的,朋友进行了交流,他们,根本就不敢,将核心数据,投放至公有云当中,去开展推理。

并非技术存在欠缺,而是合规方面的那根弦被绷得极为紧促,倘若客户交易数据“不经意间”飘移到境外服务器之上,罚单将会把一年获利全部吞噬。

所以呀,你瞧,私有化部署这个事物,听起来好似在开倒车,实际上却是众多行业所必需的需求。

但真的要在分公司的那台破服务器上跑Kubernetes ,那台服务器动不动就会断电,而且其配置还停留在5年之前 ,这样做行不行呢?

开什么玩笑。

那个传统的、庞大的K8s集群,倘若没有4核8G的配置,你根本就无法正常运转起来,而且这还没有把你一直以来动不动就需要消耗显存的AI模型计算在内呢。

  1. # Master节点初始化(禁用Traefik等非必要组件)
  2. curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--disable traefik --disable servicelb" sh -
  3. # Worker节点加入集群
  4. curl -sfL https://get.k3s.io | K3S_URL=https://<master-ip>:6443 K3S_TOKEN=<token> sh -

在这个时候,K3s的价值便显现出来了,其单节点的二进制包唯有60MB,内存占用能够被压低到512MB以下,它简直就是专门为那种“既要马儿奔跑,又不让马儿吃草”的场景所预备的。

  1. kubectl get nodes -o wide
  2. # 输出示例
  3. NAME STATUS ROLES AGE VERSION INTERNAL-IP
  4. master01 Ready control-plane 5d3h v1.28.4+k3s1 192.168.1.10
  5. worker01 Ready <none> 5d2h v1.28.4+k3s1 192.168.1.11

别被“轻量级”三个字骗了

很多人一听轻量级,就觉得是玩具,只能跑跑Nginx。

真不是。

CNCF认证这东西不是白拿的,生产环境它真能扛事儿 。

  1. # values.yaml 关键配置项
  2. persistence:
  3. storageClass: "local-path" # 匹配K3s默认StorageClass
  4. common:
  5. mysqlVolumeSize: 20Gi # 数据库存储配置

我们实际测验过,在一个具备三个节点的K3s集群之上,使用那种像是乞丐版的配置,具体而言服务器是从旧机房淘换来的,CPU是至强银牌型号,内存总共给予了16G,然而就是在这样的条件下,硬是成功运行起来了7B的量化模型。

  1. kubectl logs -n kubesphere-system $(kubectl get pod -n kubesphere-system -l app=ks-install -o jsonpath='{.items[0].metadata.name}') -f
  2. # 成功日志应包含:
  3. # "KubeSphere has been installed successfully"

并非是表现出玩一玩就会出现内存溢出的那种糟糕模样,而是具备能够稳定地在每秒处理五十多个推理请求的能力,并且将延迟控制在二百毫秒以内。

当然,你需要进行一些操作,比如说,模型要采用4bit量化,在部署之际,需将GPU与CPU的工作区分开来。

  1. resources:
  2. limits:
  3. nvidia.com/gpu: 1 # 需提前安装GPU Operator
  4. requests:
  5. memory: "16Gi"
  6. cpu: "4"

GPU是个金贵玩意儿,得供着

  1. # 使用K3s支持的HostPath(生产环境建议改用NFS)
  2. mkdir -p /models/deepseek
  3. chown -R 1000:1000 /models # 匹配容器内用户ID

在边缘环境里,GPU那就是个宝贝疙瘩。

千万别想着把所有Pod都跟GPU沾上边,得划清界限。

用节点池把事儿分清楚:

GPU节点池,将标签标记为 gpu=on,专门用于运行推理;CPU节点池,负责执行那些预处理以及后处理的繁杂琐事;还需要有一个存储池,磁盘容量要大,专门用来挂载模型文件。

  1. ### 监控体系构建
  2. 1. **Prometheus配置**:
  3. ```yaml
  4. # ServiceMonitor示例
  5. apiVersion: monitoring.coreos.com/v1
  6. kind: ServiceMonitor
  7. metadata:
  8. name: deepseek-monitor
  9. spec:
  10. selector:
  11. matchLabels:
  12. app: deepseek
  13. endpoints:
  14. - port: http
  15. path: /metrics
  16. interval: 30s

因为这样,就算你这儿有一个节点出现了故障而停止运行,模型文件却仍然安放在NAS或者Longhorn这类起到分布式存储作用的地方,处于一种闲置状态,然后,只要将另一个节点启动带动运转起来,它就能接着开展工作,不会出现那种连模型都必须再次进行下载的情况。

网络那点破事,得服软

边缘环境最恶心的就是网络。

  1. # /var/lib/rancher/k3s/agent/etc/storageclass.yaml
  2. apiVersion: storage.k8s.io/v1
  3. kind: StorageClass
  4. metadata:
  5. name: local-path
  6. provisioner: rancher.io/local-path
  7. parameters:
  8. block-cleaner-command: ["/sbin/wipefs", "-f", "-a", "$(DEVICE)"]
  9. volume-type: "directory"

要么跨子网,要么跨地域,甚至可能跨云厂商。

  1. # 对于SSD存储
  2. echo deadline > /sys/block/sdX/queue/scheduler
  3. # 对于HDD存储
  4. echo cfq > /sys/block/sdX/queue/scheduler

K3s在这点上想得相当透彻,其内部设置了对wireguard的支持,能够直接运用 --flannel-backend=wireguard-native 这个参数,于公网上为你牵引出一条加密的通道,将节点与节点之间如同搓绳子那样联结在一起。

倘若你觉着麻烦,那还能够借由Tailscale集成,大体上算是毫无察觉地融入集群,感受颇为不错。

安全?

别裸奔

很多人觉得内网部署就不需要安全了,这是最大的错觉。

  1. # Nginx Ingress Controller配置
  2. controller:
  3. config:
  4. keep-alive: "300"
  5. client-header-buffer-size: "16k"
  6. large-client-header-buffers: "4 32k"

金融、能源这种行业,等保测评的时候能把你查个底掉。

  1. # 检查kubelet日志
  2. journalctl -u k3s -n 100 --no-pager
  3. # 常见原因:
  4. # - CNI插件未正确安装
  5. # - 防火墙阻止6443端口
  6. # - 资源不足导致OOM

一定要看CIS加固指南,此指南内那个名为protect-kernel-defaults的参数,必须设置为true状态,否则kubelet将会因为内核参数不符合规定要求而直接完全停止运行。

并且,PodSecurityPolicy(PSP)或者新版的Pod Security Admissions(PSA)要使其开放启用,将那些提权、hostNetwork的权限予以封禁,不让黑客在打入容器之后能够直接接触到宿主机。

  1. # 调整超时参数
  2. import requests
  3. response = requests.post(
  4. "http://deepseek-service/predict",
  5. json={"text": "hello"},
  6. timeout=300 # 默认60秒可能不足
  7. )

其实没那么玄乎

  1. # Filebeat配置示例
  2. filebeat.inputs:
  3. - type: container
  4. paths:
  5. - /var/log/containers/*.log
  6. processors:
  7. - add_kubernetes_metadata:
  8. in_cluster: true
  9. output.elasticsearch:
  10. hosts: ["elasticsearch:9200"]

说了这么多,真搞起来其实没那么难。

找一份文档,运用curl获取一下K3s的安装脚本,几分钟就能获取一个集群了。

后面的运维是困难的,在于你要摸清你那个模型的习性,它何时消耗内存,何时耗费算力,网络中断时能否自行恢复连接。

做技术工作的多数情况下便是如此,并非处于编写代码的状态,而是在为各类意想不到的状况收拾残局。

昨天一个哥们还在群里吐槽,说搞了三天,最后发现是网线松了。

  1. apiVersion: networking.k8s.io/v1
  2. kind: NetworkPolicy
  3. metadata:
  4. name: deepseek-isolation
  5. spec:
  6. podSelector:
  7. matchLabels:
  8. app: deepseek
  9. policyTypes:
  10. - Ingress
  11. ingress:
  12. - from:
  13. - namespaceSelector:
  14. matchLabels:
  15. name: monitoring
  16. ports:
  17. - protocol: TCP
  18. port: 8080