ML Engineer's Hell: K8s Container Without NetWork😅
1. 写在前面
首先给大家推荐一本很不错的开源的机器学习/大模型相关的书,这是它的Github仓库:https://github.com/stas00/ml-engineering
里面也有编译好的PDF可供下载,这本书涵盖的内容非常广,从大模型的基础设施(GPU,网络等)到训练推理。
这本书开头有一段
ML Engineer's Heaven
ML Engineer's Hell
这也是我这篇文章标题的参考文献,记录一下我一周的部署历程。
2. 环境
部署Nvidia为企业提供的大模型推理框架NIM(需要API Key,没有企业邮箱的话大概率申请不到试用),self-host方案的话在官网的文档暂时只找到了Docker部署方式(一开始Nvidia对接的技术人员也是只给了我这一个文档):https://build.nvidia.com/meta/llama-3_1-8b-instruct?snippet_tab=Docker
NVNIM Docker
3. k8s
由于之前都没接触过k8s,所以这里就不是很熟悉先学习学习,还好创建工作负载和容器组都是在图形界面(也不可能给物理机权限),只要写写yaml配置文件就行了。首先就是把镜像在一台有网的机器上pull到本地,之后把镜像上传,再根据上面的docker启动命令配置一些如GPU、端口之类的东西。
配置文件里面有一个command配置项(重点),从这里开始我就一直参考其它的写成:
command: [sh, -c, "sleep infinity" ]
然后我进入容器(这里修改了几次配置文件才没报错,不过不是重点就跳过了)找到了它的启动脚本,然后启动,结果因为容器里面不是root权限(默认为nim),无法write一些路径,报错了。
4. 容器权限
容器里面没有权限,想了很多办法解决比如修改配置文件里的
securityContext:
runAsUser: 0
fsGroup: 0
无济于事。
这个时候我干脆把它需要写入的目录的那个环境变量改成我挂载的磁盘,这样就有权限了,改了两个变量,就这样当我再次启动容器运行启动服务的脚本时天塌了,它居然还要联网下载模型,而且我也不知道它的模型下载了那些东西(虽然是开源模型测试,但是这些模型文件目录结构和huggingface的不一样)。这个放到下一节去讲,这里我还是将docker镜像获取root权限的问题解决了。
如果是把容器重新打包成镜像的话,只需要:
docker commit --change="USER root" <container_id> <image>:<tag>
commit的时候加上--change="USER root"
就可以了,如果是将镜像重新打包的话,需要先写一个Dockerfile:
FROM <existing_image>:<tag>
USER root
然后在Dockerfile的目录下执行:
docker build -t <new_image>:<tag> .
就可以得到新的镜像了,检测:
docker run -it <image_name>:<tag> bash
用whoami
或者看命令提示前面是不是root就可以了。
以上都是在镜像所在的有网的物理机上进行的。
完成后push新的镜像然后修改k8s工作负载的配置文件里的镜像链接即可。
5. 本地上传模型
参考了NV的技术小姐姐给的文档:https://docs.nvidia.com/nim/large-language-models/latest/getting-started.html#serving-models-from-local-assets
参考里面下载模型到本地然后FTP上传到挂载的磁盘,修改模型cache所在目录的环境变量,运行脚本还是识别不到。。。
6. command
之前由于我找到了启动脚本,每次都是进到容器里面手动启动,但是我想有没有可能除了这个脚本启动还有其它步骤,于是我搜了下怎么让它运行容器默认的启动脚本,才发现不写自己的command配置就行了,这个会把原来的覆盖掉。删除然后重新开容器,果然成功了🎉🎉🎉!
7. 总结
这篇文章是我在mx-space shiro主题的博客上发的第一篇文章,已经过了两天周末我才来写,很多细节已经忽略的差不多了,而且写的也很简单实际上每一步都摸索了很久,不过还是希望大家看完能有所帮助。虽然浪费了很多时间不过也几天从k8s还未入门到基本掌握使用了🙃,不过还是希望每个ML Engineer都能得到一个可以联网的物理机的实验环境,不用把十几分钟的事情拖到好几天才弄完了。