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

关于

本文介绍了如何使用Docker文件在IBM Cloud上运行ROS 2。首先简要概述了Docker镜像及其在本地的工作原理,然后探讨了IBM Cloud以及用户如何在其中部署容器。接下来,提供了用户如何在IBM Cloud上使用自己的自定义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

在本教程中,我们将展示如何轻松将ROS 2与自定义软件包集成并在IBM Cloud上运行。

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

以下说明假定您使用的是Linux系统,并已经在Ubuntu 18.04(Bionic Beaver)上进行了测试。

步骤1:设置您的系统

在我们详细介绍具体过程之前,让我们先确保所有所需软件已正确安装。我们将指引您到适当的来源以设置您的系统,并仅强调与我们使用场景相关的细节。

a) Docker文件?

Docker文件是一种容器形式,可以独立于您的系统运行。这样,您可以设置可能有数百个不同项目而彼此不受影响。您甚至可以在一台机器上设置不同版本的Linux,而无需使用虚拟机。Docker文件具有节省空间和仅在运行时利用您的系统资源的优势。此外,Docker具有灵活和可转移的特性。它们包含所有运行所需的预设条件,这意味着您可以轻松地为特定的系统或服务使用Docker文件,而无需进行任何复杂的步骤!

感到兴奋了吗?让我们从按照以下 链接 安装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镜像

ROS于2019年1月发布了`官方Docker镜像 <https://discourse.ros.org/t/announcing-official-docker-images-for-ros2/7381/2>`__,包括几个ROS发行版的镜像容器。有关如何使用ROS 2 Docker镜像的更详细说明,请参阅`此处 <https://hub.docker.com/_/ros/>`__。

让我们跳过这些,直接开始真正的部分;立即创建一个本地ROS 2 Docker。我们将创建自己的Dockerfile(而不是使用现成的镜像),因为我们将需要此方法来在IBM Cloud上部署。首先,创建一个新目录,其中将包含我们的Dockerfile和稍后需要的任何其他文件,并导航到该目录。使用您选择的$EDITOR,打开一个名为*Dockerfile*的新文件(确保文件命名正确):

$ mkdir ~/ros2_docker

$ cd ~/ros2_docker

$ $EDITOR Dockerfile

将以下内容插入*Dockerfile*中,并保存它(也可以在 此处 找到):

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 <https://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28c%2B%2B%29>`__中找到的发布者-订阅者示例非常相似。

现在,我们准备构建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。如果没有,请首先查看此 `链接 <https://cloud.ib

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

$ ibmcloud plugin install container-registry

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

$ ibmcloud login --sso

从这里开始,让我们创建一个容器注册表命名空间。确保使用一个既独特又能描述其用途的名称。在这里,我使用了 ros2nasr

$ ibmcloud cr namespace-add ros2nasr

IBM Cloud 提供了许多快捷方式,可以帮助我们立即将容器部署到云端。下面的命令会构建容器,并将其标记为名称为 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 镜像。同样,如果遇到 permission denied 错误,请使用 sudo 权限执行该命令。然后按照下面的示例运行您的 Dockerfile。

$ 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
  1. 使用 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镜像:

$ 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

第四步:Kubernetes

a) 创建集群

使用控制台创建集群。指令可以在`此处 <https://cloud.ibm.com/docs/containers?topic=containers-clusters#clusters_ui>`__找到。下面详细介绍了使用的设置。这些仅为建议,如果需要,可以进行更改。然而,请确保您理解所做选择的影响:

  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>),并等待进度条显示创建的工作节点已经准备就绪,集群名称旁边显示*Normal*。您也可以从IBM Cloud控制台内部的Kubernetes界面访问此屏幕。

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>

您应该根据此处描述的方式替换*"<" ">"*之间显示的标签。在我的情况下,文件的内容将类似于以下内容:

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。同样,您也可以使用自己的本地软件包。