在 IBM Cloud Kubernetes 上部署 [社区贡献]

关于

本文介绍如何使用 Docker 文件在 IBM Cloud 上运行 ROS 2。它首先简要概述了 Docker 镜像及其在本地的工作方式,然后探讨了 IBM Cloud 以及用户如何在其上部署容器。 之后,简要介绍了用户如何在 IBM Cloud 上使用来自 github 的 ROS 2 自定义包。 提供了如何在 IBM Cloud 上创建集群和使用 Kubernetes 的演练,最后在集群上部署了 Docker 镜像。 最初发布于`此处 <https://github.com/mm-nasr/ros2_ibmcloud>`__ 和`此处 <https://medium.com/@mahmoud-nasr/running-ros2-on-ibm-cloud-1b1284cbd487>`__。

IBM Cloud 上的 ROS 2

在本教程中,我们将展示如何使用自定义包轻松地在 IBM Cloud 上集成和运行 ROS 2。

ROS 2 是新一代 ROS,可以更好地控制多机器人编队。随着云计算的发展,云机器人在当今时代变得越来越重要。在本教程中,我们将简要介绍如何在 IBM Cloud 上运行 ROS 2。在教程结束时,您将能够在 ROS 2 中创建自己的包并使用 docker 文件将它们部署到云中。

以下说明假设您使用的是 Linux,并且已经使用 Ubuntu 18.04(Bionic Beaver)进行了测试。

步骤 1:设置您的系统

在我们了解确切的流程之前,让我们首先确保正确安装了所有必需的软件。我们将为您指出适当的来源来设置您的系统,并仅突出显示与我们的用例相关的细节。

a) Docker 文件?

Docker 文件是一种可以独立于您的系统运行的容器,这样,您就可以设置数百个不同的项目而不会相互影响。您甚至可以在一台机器上设置不同版本的 Linux,而无需虚拟机。 Docker 文件具有节省空间的优势,运行时只利用您的系统资源。此外,docker 用途广泛且可转移。它们包含单独运行所需的所有先决条件,这意味着您可以轻松地将 docker 文件用于特定系统或服务,而无需任何繁琐的步骤!

兴奋了吗?让我们首先按照以下 link 将 docker 安装到您的系统中。 从本教程中,您应该已经进行了一些健全性检查,以确保 docker 已正确设置。不过,为了以防万一,让我们再次运行以下命令,该命令使用 hello-world docker 镜像:

$ sudo docker run hello-world

您应该获得以下输出:

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

b) ROS 2 Image

ROS 于 2019 年 1 月宣布为多个 ROS 发行版提供 镜像容器。有关使用 ROS 2 docker 镜像的更多详细说明,请访问 此处

让我们跳过这一步,立即开始实际操作;创建 本地 ROS 2 docker。我们将创建自己的 Dockerfile(而不是使用 现成的镜像),因为我们需要此方法在 IBM Cloud 上进行部署。 首先,我们创建一个新目录,该目录将保存我们的 Dockerfile 以及我们稍后需要的任何其他文件,然后导航到该目录。使用您最喜欢的 $EDITOR,打开一个名为 Dockerfile 的新文件(确保 文件命名正确):

$ mkdir ~/ros2_docker

$ cd ~/ros2_docker

$ $EDITOR Dockerfile

Dockerfile 中插入以下内容,然后保存(也可以找到 here):

FROM ros:foxy

# install ros package
RUN apt-get update && apt-get install -y \
      ros-${ROS_DISTRO}-demo-nodes-cpp \
      ros-${ROS_DISTRO}-demo-nodes-py && \
    rm -rf /var/lib/apt/lists/* && mkdir /ros2_home

WORKDIR /ros2_home

# launch ros package
CMD ["ros2", "launch", "demo_nodes_cpp", "talker_listener_launch.py"]
  • FROM:从 ros:foxy Docker 映像创建一个层

  • RUN:通过将 vim 安装到容器中并创建一个名为 /ros2_home 的目录来构建容器

  • WORKDIR:通知容器工作目录应该在哪里

当然,您可以自由更改 ROS 发行版(此处使用 foxy)或更改目录名称。上面的 docker 文件设置了 ROS-foxy 并安装了 C++ 和 Python 的演示节点。然后它启动一个运行 talker 和 listener 节点的文件。我们将在短短几行中看到它的实际作用,但它们的行为与 ROS wiki

现在,我们已准备好构建 docker 映像以在其中运行 ROS 2(是的,就是这么简单!)。

注意:如果由于权限不足或 权限被拒绝*而出现错误,请尝试使用 *sudo 权限运行该命令:

$ docker build .

# You will see a bunch of lines that execute the docker file instructions followed by:
Successfully built 0dc6ce7cb487

0dc6ce7cb487 对你来说很可能有所不同,因此请记下它并将其复制到某处以供参考。你可以随时返回并使用以下方法检查你系统上的 docker 镜像:

$ sudo docker ps -as

现在,使用以下命令运行 docker 文件:

$ docker run -it 0dc6ce7cb487
[INFO] [launch]: All log files can be found below /root/.ros/log/2020-10-28-02-41-45-177546-0b5d9ed123be-1
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [talker-1]: process started with pid [28]
[INFO] [listener-2]: process started with pid [30]
[talker-1] [INFO] [1603852907.249886590] [talker]: Publishing: 'Hello World: 1'
[listener-2] [INFO] [1603852907.250964490] [listener]: I heard: [Hello World: 1]
[talker-1] [INFO] [1603852908.249786312] [talker]: Publishing: 'Hello World: 2'
[listener-2] [INFO] [1603852908.250453386] [listener]: I heard: [Hello World: 2]
[talker-1] [INFO] [1603852909.249882257] [talker]: Publishing: 'Hello World: 3'
[listener-2] [INFO] [1603852909.250536089] [listener]: I heard: [Hello World: 3]
[talker-1] [INFO] [1603852910.249845718] [talker]: Publishing: 'Hello World: 4'
[listener-2] [INFO] [1603852910.250509355] [listener]: I heard: [Hello World: 4]
[talker-1] [INFO] [1603852911.249506058] [talker]: Publishing: 'Hello World: 5'
[listener-2] [INFO] [1603852911.250152324] [listener]: I heard: [Hello World: 5]
[talker-1] [INFO] [1603852912.249556670] [talker]: Publishing: 'Hello World: 6'
[listener-2] [INFO] [1603852912.250212678] [listener]: I heard: [Hello World: 6]

如果一切正常,您应该会看到类似于上面显示的内容。可以看出,有两个 ROS 节点(一个发布者和一个订阅者)正在运行,它们的输出通过 ROS INFO 提供给我们。

第 2 步:在 IBM Cloud 上运行映像

以下步骤假设您有一个 IBM Cloud 帐户并安装了 ibmcloud CLI。如果没有,请先检查此 link 以完成此操作。

我们还需要通过运行以下命令确保安装了 IBM Cloud Container Registry 的 CLI 插件

$ ibmcloud plugin install container-registry

之后,通过终端登录您的 ibmcloud 帐户:

$ ibmcloud login --sso

从这里开始,让我们创建一个容器注册表命名空间。确保使用一个唯一且能够描述其含义的名称。在这里,我使用了 ros2nasr

$ ibmcloud cr namespace-add ros2nasr

IBM 云有很多快捷方式可以帮助我们将容器立即放到云上。下面的命令构建容器并将其标记为名称 ros2foxy 和版本 1。请确保您使用了您创建的正确注册表名称,您可以随意更改容器名称。末尾的 . 表示 Dockerfile 位于当前目录中(这很重要),如果不是,请将其更改为指向包含 Dockerfile 的目录。

$ ibmcloud cr build --tag registry.bluemix.net/ros2nasr/ros2foxy:1 .

现在,您可以通过运行以下命令来确保容器已被推送到您创建的注册表

$ ibmcloud cr image-list
Listing images...

REPOSITORY               TAG   DIGEST         NAMESPACE   CREATED         SIZE     SECURITY STATUS
us.icr.io/ros2nasr/ros2foxy   1     031be29301e6   ros2nasr    36 seconds ago   120 MB   No Issues

OK

接下来,登录到您的注册表以运行 docker image 非常重要。同样,如果您遇到 权限被拒绝 错误,请使用 sudo 权限执行 命令。之后,按如下所示运行您的 docker 文件。

$ ibmcloud cr login
Logging in to 'registry.ng.bluemix.net'...
Logged in to 'registry.ng.bluemix.net'.
Logging in to 'us.icr.io'...
Logged in to 'us.icr.io'.

OK

$ docker run -v -it registry.ng.bluemix.net/ros2nasr/ros2foxy:1

其中 ros2nasr 是您创建的注册表的名称,而 ros2foxy:1 是 docker 容器的标签和版本,如前所述。

您现在应该看到您的 docker 文件正在运行并提供与您在机器上本地运行时看到的类似输出。

步骤 3:使用自定义 ROS 2 包

现在我们有了完整的工作流,从创建 Dockerfile, 一直到部署它并看到它在 IBM Cloud 上工作。但是,如果我们想使用我们(或其他人)创建的一组自定义包怎么办?

这一切都与您如何设置 Dockerfile 有关。让我们使用 ROS 2 此处 提供的示例。 使用新的 Dockerfile 创建一个新目录(或覆盖现有目录)并在其中添加以下内容(或从此处下载文件 <https://github.com/mm-nasr/ros2_ibmcloud/blob/main/dockers/git_pkgs_docker/Dockerfile>`__)

ARG FROM_IMAGE=ros:foxy
ARG OVERLAY_WS=/opt/ros/overlay_ws

# multi-stage for caching
FROM $FROM_IMAGE AS cacher

# clone overlay source
ARG OVERLAY_WS
WORKDIR $OVERLAY_WS/src
RUN echo "\
repositories: \n\
  ros2/demos: \n\
    type: git \n\
    url: https://github.com/ros2/demos.git \n\
    version: ${ROS_DISTRO} \n\
" > ../overlay.repos
RUN vcs import ./ < ../overlay.repos

# copy manifests for caching
WORKDIR /opt
RUN mkdir -p /tmp/opt && \
    find ./ -name "package.xml" | \
      xargs cp --parents -t /tmp/opt && \
    find ./ -name "COLCON_IGNORE" | \
      xargs cp --parents -t /tmp/opt || true

# multi-stage for building
FROM $FROM_IMAGE AS builder

# install overlay dependencies
ARG OVERLAY_WS
WORKDIR $OVERLAY_WS
COPY --from=cacher /tmp/$OVERLAY_WS/src ./src
RUN . /opt/ros/$ROS_DISTRO/setup.sh && \
    apt-get update && rosdep install -y \
      --from-paths \
        src/ros2/demos/demo_nodes_cpp \
        src/ros2/demos/demo_nodes_py \
      --ignore-src \
    && rm -rf /var/lib/apt/lists/*

# build overlay source
COPY --from=cacher $OVERLAY_WS/src ./src
ARG OVERLAY_MIXINS="release"
RUN . /opt/ros/$ROS_DISTRO/setup.sh && \
    colcon build \
      --packages-select \
        demo_nodes_cpp \
        demo_nodes_py \
      --mixin $OVERLAY_MIXINS

# source entrypoint setup
ENV OVERLAY_WS $OVERLAY_WS
RUN sed --in-place --expression \
      '$isource "$OVERLAY_WS/install/setup.bash"' \
      /ros_entrypoint.sh

# run launch file
CMD ["ros2", "launch", "demo_nodes_cpp", "talker_listener_launch.py"]

通过显示的行,我们可以看到如何通过 4 个步骤从 github 添加自定义包:

  1. 使用从 Github 克隆的自定义包创建一个覆盖:

ARG OVERLAY_WS
WORKDIR $OVERLAY_WS/src
RUN echo "\
repositories: \n\
  ros2/demos: \n\
    type: git \n\
    url: https://github.com/ros2/demos.git \n\
    version: ${ROS_DISTRO} \n\
" > ../overlay.repos
RUN vcs import ./ < ../overlay.repos

2.使用 rosdep 安装包依赖项

# install overlay dependencies
ARG OVERLAY_WS
WORKDIR $OVERLAY_WS
COPY --from=cacher /tmp/$OVERLAY_WS/src ./src
RUN . /opt/ros/$ROS_DISTRO/setup.sh && \
    apt-get update && rosdep install -y \
      --from-paths \
        src/ros2/demos/demo_nodes_cpp \
        src/ros2/demos/demo_nodes_py \
      --ignore-src \
    && rm -rf /var/lib/apt/lists/*
  1. 构建你需要的软件包

# build overlay source
COPY --from=cacher $OVERLAY_WS/src ./src
ARG OVERLAY_MIXINS="release"
RUN . /opt/ros/$ROS_DISTRO/setup.sh && \
    colcon build \
      --packages-select \
        demo_nodes_cpp \
        demo_nodes_py \
      --mixin $OVERLAY_MIXINS
  1. 运行启动文件

# run launch file
CMD ["ros2", "launch", "demo_nodes_cpp", "talker_listener_launch.py"]

同样,我们可以更改所使用的软件包,安装它们的依赖项,然后运行它们。

返回 IBM Cloud

有了这个 Dockerfile,我们可以按照之前的步骤在 IBM Cloud 上部署它。由于我们已经创建了注册表,并且

我们已经登录到 IBM Cloud,因此我们直接构建了新的 Dockerfile。

请注意,我保留了相同的标签,但更改了版本,这样我

就可以更新之前创建的 docker 映像。(如果您愿意,可以自由地创建一个全新的映像)

$ ibmcloud cr build --tag registry.bluemix.net/ros2nasr/ros2foxy:2 .

然后,确保您已登录到注册表并运行新的docker image:

$ ibmcloud cr login
Logging in to 'registry.ng.bluemix.net'...
Logged in to 'registry.ng.bluemix.net'.
Logging in to 'us.icr.io'...
Logged in to 'us.icr.io'.

OK

$ docker run -v -it registry.ng.bluemix.net/ros2nasr/ros2foxy:2

您应该再次看到相同的输出。但是,这次我们通过 github 中的自定义包完成了此操作,这使我们能够在 IBM Cloud 上使用我们个人为 ROS 2 创建的包。

附加:删除 Docker 映像

您可能会发现自己需要从 IBM Cloud 中删除特定的 docker 映像,您应该这样做!

1. 列出您拥有的所有图像,并找到所有共享 registry.ng.bluemix.net/ros2nasr/ros2foxy:2 对应的 IMAGE 名称的图像(在我的情况下)。然后 使用它们的 NAMES 删除它们

$ docker rm your_docker_NAMES
  1. 使用其 IMAGE 名称从 IBM Cloud 中删除 docker 镜像

$ docker rmi registry.ng.bluemix.net/ros2nasr/ros2foxy:2

步骤 4:Kubernetes

a) 创建集群

使用控制台创建集群。说明位于 此处。 使用的设置详述如下。这些只是建议, 如果需要,您可以更改。但是,请确保您了解所做选择的含义:

  1. 计划:标准

  2. 编排服务:Kubernetes v1.18.10

  3. 基础设施:经典

  4. 位置:

  • 资源组:默认

  • 地理位置:*北美*(您可以自由更改)

  • 可用性:*单区域*(您可以自由更改,但请确保通过查看 IBM Cloud 文档了解所做选择的影响。)

  • 工作区域:*多伦多 01*(选择物理上离您最近的位置)

  1. 工作池:

  • 虚拟 - 共享,Ubuntu 18

  • 内存:16 GB

  • 每个区域的工作节点:1

  1. 主服务端点:私有和公共端点

  2. 资源详细信息(完全灵活):

  • 集群名称: mycluster-tor01-rosibm

  • 标签:version:1

创建集群后,您将被重定向到一个页面,其中详细介绍了如何设置 CLI 工具和访问集群。请按照这些说明操作(或查看`此处 <https://github.com/mm-nasr/ros2_ibmcloud/blob/main/Kubernetes-Cluster-Set-up.md>`__ 的说明)并等待进度条显示您创建的工作节点已准备就绪,方法是在集群名称旁边指示 正常。您也可以从 Kubernetes 内的 IBM Cloud 控制台访问此屏幕。

b) 部署您的 Docker 映像 终于!

  1. 使用您最喜欢的 $EDITOR 创建一个名为 ros2-deployment.yaml* 的部署配置 yaml 文件,并在其中插入以下内容:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: <deployment>
spec:
  replicas: <number_of_replicas>
  selector:
    matchLabels:
      app: <app_name>
  template:
    metadata:
      labels:
        app: <app_name>
    spec:
      containers:
      - name: <app_name>
        image: <region>.icr.io/<namespace>/<image>:<tag>

您应该按照此处 <https://cloud.ibm.com/docs/containers?topic=containers-images#namespace> 所述替换 “<” “>“ 之间显示的标签。

在我的例子中,文件看起来如下所示:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ros2-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ros2-ibmcloud
  template:
    metadata:
      labels:
        app: ros2-ibmcloud
    spec:
      containers:
      - name: ros2-ibmcloud
        image: us.icr.io/ros2nasr/ros2foxy:2

使用以下命令部署文件

$ kubectl apply -f ros2-deployment.yaml
deployment.apps/ros2-deployment created

现在,您的 docker 镜像已完全部署到您的集群上!

第 5 步:使用 CLI 处理您的 Docker 镜像

  1. 通过 IBM Cloud 控制台 Kubernetes 导航到您的集群。

  2. 单击页面右上角的 Kubernetes 仪表板

您现在应该能够看到集群的所有不同参数以及其 CPU 和内存使用情况的完整列表。

  1. 导航到 Pods 并单击您的部署。

  2. 在右上角,单击 Exec into pod

现在您已进入 docker 镜像!您可以获取工作区(如果需要)并运行 ROS 2!例如:

root@ros2-deployment-xxxxxxxx:/opt/ros/overlay_ws# . install/setup.sh
root@ros2-deployment-xxxxxxxx:/opt/ros/overlay_ws# ros2 launch demo_nodes_cpp talker_listener_launch.py

最后的评论

此时,您可以使用 github 上的 ROS 2 包创建自己的 docker 镜像。也可以通过少量更改来使用本地 ROS 2 包。这可能是另一篇文章的主题。但是,我们鼓励您查看以下 Dockerfile,它使用了演示存储库的本地副本。同样,您可以使用自己的本地包。