数据科学

使用 Container Canary 在多个平台上测试容器图像

 

自带容器模型在当今的现代计算平台上得到广泛支持。换句话说,您可以在自定义软件环境中提供自己的容器映像。

然而,用户提供的容器必须满足每个平台的独特要求,这可能因平台而异。例如,您可能需要:

  • 使用特定的非 root 用户。
  • 将主目录放在某个位置。
  • 安装依赖软件包。
  • 在指定端口上运行 web 应用程序。

保持容器图像符合这些任意要求可能是一项挑战。因此,我们迫切希望引入一个名为 Container Canary 的新开源工具来捕获这些需求,并针对它们进行自动测试。 Container Canary 提供了一个规范,用于将这些需求记录为可检入版本控制的清单。然后,可以使用canary CLI 工具根据该清单验证容器。

这在测试和持续集成( CI )环境中非常有用,可以避免容器中的回归,同时允许容器开发人员快速移动。

$ canary validate --file somespec.yaml foo/bar:latest
Validating foo/bar: latest against somespec 📦 Required packages are installed [passed] 🤖 Expected services are running [passed] 🎉 Your container is awesome [passed]
validation passed

安装集 Container Canary

Container Canary 是用 Golang 编写的,并以静态二进制文件的形式分发,使其易于移植,易于在 CI 环境中安装。

要安装它,请转到 releases page 并下载适合您系统的发行版。例如,使用 x86 _ 64 处理器的 Linux 用户将使用canary_linux_amd64二进制文件。确保将以下命令中的VERSION替换为要安装的版本。

$ curl -L https://github.com/NVIDIA/container-canary/releases/download/VERSION/canary_linux_amd64 > canary_linux_amd64

Container Canary 还提供 sha256 总和来验证二进制文件。

$ curl -L https://github.com/NVIDIA/container-canary/releases/download/VERSION/canary_linux_amd64.sha256sum > canary_linux_amd64.sha256sum $ sha256sum --check --status canary_linux_amd64.sha256sum

现在,你可以把二进制文件放在你的路径上。

$ chmod +x canary_linux_amd64 $ mv canary_linux_amd64 /usr/local/bin/canary

最后,验证它是否有效。

$ canary version
Container Canary Version: VERSION ...

用 Kubeflow 示例验证容器

安装了 Container Canary 之后,就可以开始验证容器了。 /examples/ GitHub 目录包含一些流行容器平台的清单,包括 Kubeflow example 。您可以使用这些清单立即开始。

Kubeflow 是设计、培训和推断 machine learning 模型的流行平台。 Kubeflow Notebooks 服务使您能够在 Kubeflow 内部启动基于 web 的开发环境。虽然 Kubeflow 社区为运行 JupyterLabRStudioVisual Studio 代码(代码服务器) 等工具维护了默认容器,但您也可以使用自己的软件环境选择自己的容器映像。

要求清单 指定自定义容器必须满足哪些条件才能在 Kubeflow 笔记本上正确运行。该列表如下所示:

Kubeflow 笔记本电脑要使用容器映像,映像必须:

  • 在端口 8888 上公开 HTTP 接口:
    • kubeflow 在运行时设置一个环境变量 NB _ PREFIX ,其中包含我们希望容器监听的 URL 路径
    • kubeflow 使用 iFrame ,因此请确保您的应用程序集访问控制允许源代码:*在 HTTP 响应头中
  • 以名为 jovyan 的用户身份运行:
    • jovyan 的主目录应该是/ home / jovyan
    • 乔维安的 UID 应该是 1000
  • 在/ home / jovyan 安装一个空 PVC ,成功启动:
    • kubeflow 在/ home / jovyan 安装了一个 PVC ,以在 Pod 重启期间保持状态

对于 Container Canary ,我们已经在示例清单中列出了这些要求。如果您曾经编写过 Kubernetes 吊舱清单,那么您应该很熟悉这种语法。您可以看到,每个需求都以探针的形式写出来,Container Canary 对着您的容器运行,以检查是否满足了需求。

该过程如以下示例所示:

apiVersion: container-canary.nvidia.com/v1
kind: Validator
name: kubeflow
description: Kubeflow notebooks
documentation: https://www.kubeflow.org/docs/components/notebooks/container-images/#custom-images
env: - name: NB_PREFIX value: /hub/jovyan/
ports: - port: 8888 protocol: TCP
volumes: - mountPath: /home/jovyan
checks: - name: user description: 👩 User is jovyan probe: exec: command: - /bin/sh - -c - "[ $(whoami) = jovyan ]" - name: uid description: 🆔 User ID is 1000 probe: exec: command: - /bin/sh - -c - "id | grep uid=1000" - name: home description: 🏠 Home directory is /home/jovyan probe: exec: command: - /bin/sh - -c - "[ $HOME = /home/jovyan ]" - name: http description: 🌏 Exposes an HTTP interface on port 8888 probe: httpGet: path: / port: 8888 initialDelaySeconds: 10 - name: NB_PREFIX description: 🧭 Correctly routes the NB_PREFIX probe: httpGet: path: /hub/jovyan/lab port: 8888 initialDelaySeconds: 10 - name: allow-origin-all description: "🔓 Sets 'Access-Control-Allow-Origin: *' header" probe: httpGet: path: / port: 8888 responseHttpHeaders: - name: Access-Control-Allow-Origin value: "*" initialDelaySeconds: 10

既然有了清单,我就可以对容器进行测试了。首先,我选择了一个我知道不会通过要求的公共形象,比如 流行的 web 服务器 NGINX

$ canary validate --file https://github.com/NVIDIA/container-canary/raw/main/examples/kubeflow.yaml nginx:latest Cannot find nginx:latest, pulling…
Validating nginx:latest against kubeflow 🏠 Home directory is /home/jovyan [failed] 👩 User is jovyan [failed] 🆔 User ID is 1000 [failed] 🌏 Exposes an HTTP interface on port 8888 [failed] 🔓 Sets 'Access-Control-Allow-Origin: *' header [failed] 🧭 Correctly routes the NB_PREFIX [failed]
validation failed

毫不奇怪,这张图片没有通过验证。

接下来,我尝试了一款设计用于 Kubeflow 笔记本电脑的 官方 Kubeflow 图片

$ canary validate --file https://github.com/NVIDIA/container-canary/raw/main/examples/kubeflow.yaml public.ecr.aws/j1r0q0g6/notebooks/notebook-servers/jupyter-pytorch-cuda:v1.5.0 Cannot find public.ecr.aws/j1r0q0g6/notebooks/notebook-servers/jupyter-pytorch-cuda:v1.5.0, pulling…
Validating public.ecr.aws/j1r0q0g6/notebooks/notebook-servers/jupyter-pytorch-cuda:v1.5.0 against kubeflow 🏠 Home directory is /home/jovyan [passed] 👩 User is jovyan [passed] 🆔 User ID is 1000 [passed] 🔓 Sets 'Access-Control-Allow-Origin: *' header [passed] 🧭 Correctly routes the NB_PREFIX [passed] 🌏 Exposes an HTTP interface on port 8888 [passed]
validation passed

成功这张图片通过了验证。

如果要在 Kubeflow 上创建图像,可以用同样的方法验证它们,并确信当其他用户来运行它们时,所做的更改不会导致问题。

编写自己的验证清单

您还可以编写自己的清单来验证容器。 Container Canary 可以帮助您确保您的容器清单将在您自己的部署和第三方平台中运行。它还帮助您在容器构建上运行单元测试。

每个清单都是一个以一些元数据开头的 YAML 文件。

# Manifest versioning
apiVersion: container-canary.nvidia.com/v1
kind: Validator # Metadata
name: foo # The name of the platform that this manifest validates for
description: Foo runs containers for you # Optional, A description of that platform
documentation: https://example.com # Optional, A link to the documentation that defines the container requirements in prose

接下来,您可以为容器配置一些运行时选项。当 Container Canary 启动图像进行验证时,将使用这些选项,并应模仿在目标平台上设置的选项。其中包括环境变量、要公开的端口和要连接的卷。

env: - name: NB_PREFIX value: /hub/jovyan/
ports: - port: 8888 protocol: TCP
volumes: - mountPath: /home/jovyan

然后,指定支票。检查是针对容器运行的测试,以确保其符合要求。每个检查都包含一个与容器交互的探针。这些交互包括运行命令、发出 HTTP 请求和 ping TCP 套接字。

Container Canary 中的探针是 库伯内特斯的那些 的超集,因此如果您以前使用过这些探针,应该对它们很熟悉。

checks: - name: mycheck # Name of the check description: Ensuring a thing # Description of what is being checked (will be used in output) probe: ... # A probe to run

exec检查会在正在运行的容器中运行命令。如果命令以 0 退出,则检查通过。

checks: - name: uid description: User ID is 1234 probe: exec: command: - /bin/sh - -c - "id | grep uid=1234"

HTTP Get检查对您的容器执行HTTP GET请求。如果响应代码< 300 且可选响应标题匹配,则检查通过。

checks: - name: http description: Exposes an HTTP interface on port 80 probe: httpGet: path: / port: 80 httpHeaders: # Optional, headers to set in the request - name: Foo-Header value: "myheader" responseHttpHeaders: # Optional, headers that you expect to see in the response - name: Access-Control-Allow-Origin value: "*"

有关更多信息,请参阅 验证程序 API 参考

编写清单后,可以使用canary来测试带有清单的容器。

$ canary validate --file examples/awesome.yaml your/container:latest
Validating your/container:latest against awesome 📦 Required packages are installed [passed] 🤖 Expected services are running [passed] 🎉 Your container is awesome [passed]
validation passed

使用 GitHub 操作自动化容器 Canary 的示例

现在,我已经介绍了安装 Container Canary、验证容器和编写自己的清单,下面是一个快速的 CI 示例。

假设您想要构建一个容器,该容器应该在特定端口上运行 web 应用程序,并且还安装了 fastapi 。在新的存储库中,您可以使用 Python 创建一个名为app.py的小型 Python web 应用程序。

from fastapi import FastAPI
import uvicorn app = FastAPI() @app.get("/")
def read_root(): return {"Hello": "World"} @app.get("/foo")
def foo(): return {"foo": "bar"} if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=5000, log_level="info")

然后可以创建Dockerfile将应用程序打包到容器中。

FROM python COPY app.py /app.py RUN pip install fastapi uvicorn[standard] EXPOSE 5000 CMD python /app.py

现在,编写一个 Container Canary 验证器清单,测试容器映像,确保它在端口 5000 上运行 web 服务器,并且安装了 Python 。叫它canary-validator.yaml

apiVersion: container-canary.nvidia.com/v1
kind: Validator
name: example
description: Container Canary CI Example
env: []
ports: - port: 5000 protocol: TCP
volumes: []
checks: - name: http description: Exposes an HTTP interface on port 5000 probe: httpGet: path: /foo port: 5000 failureThreshold: 30 - name: python description: Has Python installed probe: exec: command: - /bin/sh - -c - "which python"

最后,创建一个 GitHub Actions 配置来在 CI 中运行它。我们在本例中选择 GitHub Actions 是因为它很受欢迎、免费且易于使用,但这种配置应该适用于所有 CI 系统。

创建一个名为.github/workflows/ci.yaml的文件。

name: ci on: push: pull_request: jobs: canary: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Install Container Canary run: | curl -L https://github.com/NVIDIA/container-canary/releases/download/v0.2.0/canary_linux_amd64 > /usr/local/bin/canary chmod +x /usr/local/bin/canary - name: Build Container run: docker build -t foo/canary-ci-example:latest . - name: Validate container run: canary validate --file canary-validator.yaml foo/canary-ci-example:latest

现在,当您将代码推送到 GitHub 时, Actions runner 会签出代码,安装容器 Canary ,构建容器映像,并使用canary validate对其进行验证。

Screenshot of Canary validation running successfully in a GitHub Actions workflow.
图 1 。在 GitHub 操作工作流中成功运行 Canary 验证

工作流程已经执行,我们的集装箱图像已经成功验证——而且很快!有关更多信息,请参阅 /jacobtomlinson/canary-ci-example GitHub repo 中此示例的所有代码。

应用你学到的东西

使用 Container Canary ,您可以为您的容器映像定义具体的接口,并验证它们,以确保您构建的映像始终符合定义的规范。

如果您经常构建容器映像, Container Canary 在测试和 CI 环境中非常有用,因此它是测试工具包中的必备工具。容器开发人员可以成功地避免容器中的倒退,并更快地完成项目以节省时间。

 

Tags