在不同容器中运行多个应用程序#
本节将介绍如何在同一集群中,在具有不同映像的独立容器中运行多个 Serve 应用程序。
此功能尚处于实验阶段,API 可能会发生更改。如果您有其他功能请求或遇到问题,请在 Github 上提交。
安装 Podman#
runtime environment 的 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
最后,您可以在应用程序的 runtime environment 规范的 image_uri 字段中指定要在其中运行每个应用程序的容器映像。
注意
以前,您可以通过 runtime environment 的 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("https://: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("https://:8000/resnet", json={"uri": link_to_image})
>>> resp.text
ox
高级#
与其他 runtime environment 字段的兼容性#
目前,image_uri 字段仅支持与 config 和 env_vars 一起使用。如果您有将 image_uri 与其他 runtime environment 功能配对的用例,请在 Github 上提交功能请求。
环境变量#
以下环境变量将在您的容器中的进程中设置,优先级从高到低:
runtime_env["env_vars"]中指定的环境变量。所有以
RAY_前缀开头的环境变量(包括RAY_RAYLET_PID和RAY_JOB_ID这两个特殊变量)都会在运行时被容器继承。在 docker 映像中设置的任何环境变量。
在 Docker 容器中运行 Ray 集群#
如果 raylet 在容器内运行,那么该容器需要有权限启动新容器。要设置正确的权限,您需要使用 --privileged 标志来启动运行 raylet 的容器。
故障排除#
Permission denied: ‘/tmp/ray/session_2023-11-28_15-27-22_167972_6026/ports_by_node.json.lock’
此错误很可能发生,因为在 Podman 容器中运行的用户与启动 Ray 集群的主机用户不同。文件夹
/tmp/ray是 volume 挂载到 podman 容器中的,它属于启动 Ray 的主机用户。另一方面,容器是以--userns=keep-id标志启动的,这意味着主机用户被映射到容器中作为它自己。因此,除非容器内的用户与主机用户不同,否则不应出现权限问题。例如,如果主机上的用户是root,而您使用的是标准 Ray 映像作为基础映像的容器,那么默认情况下,容器将以用户ray(1000)身份启动,而该用户无法访问挂载的/tmp/rayvolume。
ERRO[0000] ‘overlay’ is not supported over overlayfs: backing file system is unsupported for this graph driver
当您在容器内运行 Ray 集群时,应该只会遇到此错误。如果您在启动 replica actor 时遇到此错误,请尝试将
/var/lib/containersvolume 挂载到运行 raylet 的容器中。也就是说,在启动 Docker 容器的命令中添加-v /var/lib/containers:/var/lib/containers。
cannot clone: Operation not permitted; Error: cannot re-exec process
当您在容器内运行 Ray 集群时,应该只会遇到此错误。此错误表明您没有权限使用 Podman 启动容器。您需要通过添加
--privileged来以特权模式启动运行 raylet 的容器。