在不同容器中运行多个应用#
本节介绍如何在同一集群中使用不同的镜像在独立的容器中运行多个 Serve 应用。
此功能是实验性的,API 可能会更改。如果您有其他功能需求或遇到问题,请在 Github 上提交。
安装 Podman#
image_uri
运行时环境功能使用 Podman 来启动和运行容器。请遵循 Podman 安装说明 在所有 head 节点和 worker 节点的环境中安装 Podman。
注意
对于 Ubuntu,Podman 包仅在 Ubuntu 20.10 及更新版本的官方仓库中可用。要在 Ubuntu 20.04 或更早版本中安装 Podman,您需要首先将软件仓库添加为 debian 源。按照这些说明在 Ubuntu 20.04 或更早版本上安装 Podman。
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_20.04/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list"
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 4D64390375060AA4
sudo apt-get update
sudo apt-get install podman -y
在容器中运行 Serve 应用#
此示例在两个独立的容器中部署了两个应用:一个 Whisper 模型和一个 Resnet50 图像分类模型。
首先,在镜像中安装所需的依赖项。
警告
容器中的 Ray 版本和 Python 版本必须与主机环境中的完全匹配。请注意,对于 Python,版本必须精确匹配到补丁号。
将以下内容保存到名为 whisper.Dockerfile
和 resnet.Dockerfile
的文件中。
# Use the latest Ray GPU image, `rayproject/ray:latest-py38-gpu`, so the Whisper model can run on GPUs.
FROM rayproject/ray:latest-py38-gpu
# Install the package `faster_whisper`, which is a dependency for the Whisper model.
RUN pip install faster_whisper==0.10.0
RUN sudo apt-get update && sudo apt-get install curl -y
# Download the source code for the Whisper application into `whisper_example.py`.
RUN curl -O https://raw.githubusercontent.com/ray-project/ray/master/doc/source/serve/doc_code/whisper_example.py
# Add /home/ray path to PYTHONPATH avoid import module error
ENV PYTHONPATH "${PYTHONPATH}:/home/ray"
# Use the latest Ray CPU image, `rayproject/ray:latest-py38-cpu`.
FROM rayproject/ray:latest-py38-cpu
# Install the packages `torch` and `torchvision`, which are dependencies for the ResNet model.
RUN pip install torch==2.0.1 torchvision==0.15.2
RUN sudo apt-get update && sudo apt-get install curl -y
# Download the source code for the ResNet application into `resnet50_example.py`.
RUN curl -O https://raw.githubusercontent.com/ray-project/ray/master/doc/source/serve/doc_code/resnet50_example.py
# Add /home/ray path to PYTHONPATH avoid import module error
ENV PYTHONPATH "${PYTHONPATH}:/home/ray"
然后,构建相应的镜像并将其推送到您选择的容器注册中心。本教程使用 alice/whisper_image:latest
和 alice/resnet_image:latest
作为镜像的占位符名称,但请务必将 alice
替换为您选择的仓库名称。
# Build the image from the Dockerfile using Podman
export IMG1=alice/whisper_image:latest
podman build -t $IMG1 -f whisper.Dockerfile .
# Push to a registry. This step is unnecessary if you are deploying Serve locally.
podman push $IMG1
# Build the image from the Dockerfile using Podman
export IMG2=alice/resnet_image:latest
podman build -t $IMG2 -f resnet.Dockerfile .
# Push to a registry. This step is unnecessary if you are deploying Serve locally.
podman push $IMG2
最后,您可以在应用的运行时环境规范的 image_uri
字段中指定要运行每个应用的容器镜像。
注意
之前您可以通过运行时环境的 container
字段访问此功能。现在该 API 已被弃用,推荐使用 image_uri
。
以下 Serve 配置将使用镜像 IMG1
运行 whisper
应用,使用镜像 IMG2
运行 resnet
应用。可以使用 podman images
命令列出镜像名称。具体来说,应用中的所有部署副本都将在各自的镜像容器中启动和运行。
applications:
- name: whisper
import_path: whisper_example:entrypoint
route_prefix: /whisper
runtime_env:
image_uri: {IMG1}
- name: resnet
import_path: resnet50_example:app
route_prefix: /resnet
runtime_env:
image_uri: {IMG2}
发送查询#
>>> import requests
>>> audio_file = "https://storage.googleapis.com/public-lyrebird-test/test_audio_22s.wav"
>>> resp = requests.post("http://localhost:8000/whisper", json={"filepath": audio_file})
>>> resp.json()
{
"language": "en",
"language_probability": 1,
"duration": 21.775,
"transcript_text": " Well, think about the time of our ancestors. A ping, a ding, a rustling in the bushes is like, whoo, that means an immediate response. Oh my gosh, what's that thing? Oh my gosh, I have to do it right now. And dude, it's not a tiger, right? Like, but our, our body treats stress as if it's life-threatening because to quote Robert Sapolsky or butcher his quote, he's a Robert Sapolsky is like one of the most incredible stress physiologists of",
"whisper_alignments": [
[
0.0,
0.36,
" Well,",
0.3125
],
...
]
}
>>> link_to_image = "https://serve-resnet-benchmark-data.s3.us-west-1.amazonaws.com/000000000019.jpeg"
>>> resp = requests.post("http://localhost:8000/resnet", json={"uri": link_to_image})
>>> resp.text
ox
高级#
与其他运行时环境字段的兼容性#
目前,image_uri
字段仅支持与 config
和 env_vars
一起使用。如果您有将 image_uri
与其他运行时环境功能配对的用例,请在 Github 上提交功能请求。
环境变量#
在您的容器中,进程将按从高到低的优先级设置以下环境变量
在
runtime_env["env_vars"]
中指定的环境变量。所有以
RAY_
为前缀的环境变量(包括两个特殊变量RAY_RAYLET_PID
和RAY_JOB_ID`)在运行时由容器继承。
在 Docker 镜像中设置的任何环境变量。
在 Docker 容器中运行 Ray 集群#
如果 raylet 在容器内运行,则该容器需要必要的权限才能启动新容器。为了设置正确的权限,您需要使用 --privileged
标志启动运行 raylet 的容器。
故障排除#
权限被拒绝:‘/tmp/ray/session_2023-11-28_15-27-22_167972_6026/ports_by_node.json.lock’
此错误很可能是因为在 Podman 容器内运行的用户与启动 Ray 集群的主机用户不同。卷挂载到 podman 容器内的
/tmp/ray
文件夹归启动 Ray 的主机用户所有。另一方面,容器是使用--userns=keep-id
标志启动的,这意味着主机用户会映射到容器内作为其本身。因此,只有当容器内的用户与主机用户不同时,才会出现权限问题。例如,如果主机上的用户是root
,并且您使用的容器的基础镜像是标准的 Ray 镜像,那么默认情况下,容器将以用户ray(1000)
启动,该用户将无法访问挂载的/tmp/ray
卷。
ERRO[0000] ‘overlay’ 在 overlayfs 上不受支持:此图形驱动程序的后端文件系统不受支持
仅当您在容器内运行 Ray 集群时,才会出现此错误。如果在启动副本 Actor 时看到此错误,请尝试将
/var/lib/containers
卷挂载到运行 raylet 的容器中。也就是说,在启动 Docker 容器的命令中添加-v /var/lib/containers:/var/lib/containers
。
无法克隆:操作不允许;错误:无法重新执行进程
仅当您在容器内运行 Ray 集群时,才会出现此错误。此错误意味着您没有使用 Podman 启动容器的权限。您需要使用特权权限启动运行 raylet 的容器,即添加
--privileged
。