前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >15分钟连接Jetson Nano与K8s,轻松搭建机器学习集群

15分钟连接Jetson Nano与K8s,轻松搭建机器学习集群

作者头像
CNCF
发布2020-11-09 10:20:50
2K0
发布2020-11-09 10:20:50
举报
文章被收录于专栏:CNCF

在本文中我将展示如何将Jetson Nano开发板连接到Kubernetes集群以作为一个GPU节点。我将介绍使用GPU运行容器所需的NVIDIA docker设置,以及将Jetson连接到Kubernetes集群。在成功将节点连接到集群后,我还将展示如何在Jetson Nano上使用GPU运行简单的TensorFlow 2训练会话。

K3s还是K8s?

K3s是一个轻量级Kubernetes发行版,其大小不超过100MB。在我看来,它是单板计算机的理想选择,因为它所需的资源明显减少。你可以查看我们的往期文章,了解更多关于K3s的教程和生态。在K3s生态中,有一款不得不提的开源工具K3sup,这是由Alex Ellis开发的,用于简化K3s集群安装。你可以访问Github了解这款工具:

https://github.com/alexellis/k3sup

我们需要准备什么?

  • 一个K3s集群——只需要一个正确配置的主节点即可
  • NVIDIA Jetson Nano开发板,并安装好开发者套件 如果你想了解如何在开发板上安装开发者套件,你可以查看以下文档: https://developer.nvidia.com/embedded/learn/get-started-jetson-nano-devkit#write
  • K3sup
  • 15分钟的时间

计划步骤

  1. 设置NVIDIA docker
  2. 添加Jetson Nano到K3s集群
  3. 运行一个简单的MNIST例子来展示Kubernetes pod内GPU的使用

设置NVIDIA docker

在我们配置Docker以使用nvidia-docker作为默认的运行时之前,我需要先解释一下为什么要这样做。默认情况下,当用户在Jetson Nano上运行容器时,运行方式与其他硬件设备相同,你不能从容器中访问GPU,至少在没有黑客攻击的情况下不能。如果你想自己测试一下,你可以运行以下命令,应该会看到类似的结果:

代码语言:javascript
复制
root@jetson:~# echo "python3 -c 'import tensorflow'" | docker run -i icetekio/jetson-nano-tensorflow /bin/bash
2020-05-14 00:10:23.370761: W tensorflow/stream_executor/platform/default/dso_loader.cc:59] Could not load dynamic library 'libcudart.so.10.2'; dlerror: libcudart.so.10.2: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /usr/local/cuda-10.2/targets/aarch64-linux/lib:
2020-05-14 00:10:23.370859: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.
2020-05-14 00:10:25.946896: W tensorflow/stream_executor/platform/default/dso_loader.cc:59] Could not load dynamic library 'libnvinfer.so.7'; dlerror: libnvinfer.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /usr/local/cuda-10.2/targets/aarch64-linux/lib:
2020-05-14 00:10:25.947219: W tensorflow/stream_executor/platform/default/dso_loader.cc:59] Could not load dynamic library 'libnvinfer_plugin.so.7'; dlerror: libnvinfer_plugin.so.7: cannot open shared object file: No such file or directory; LD_LIBRARY_PATH: /usr/local/cuda-10.2/targets/aarch64-linux/lib:
2020-05-14 00:10:25.947273: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:30] Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.
/usr/lib/python3/dist-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters

如果你现在尝试运行相同的命令,但在docker命令中添--runtime=nvidia参数,你应该看到类似以下的内容:

代码语言:javascript
复制
root@jetson:~# echo "python3 -c 'import tensorflow'" | docker run --runtime=nvidia -i icetekio/jetson-nano-tensorflow /bin/bash
2020-05-14 00:12:16.767624: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcudart.so.10.2
2020-05-14 00:12:19.386354: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libnvinfer.so.7
2020-05-14 00:12:19.388700: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libnvinfer_plugin.so.7
/usr/lib/python3/dist-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters

nvidia-docker已经配置完成,但是默认情况下并没有启用。要启用docker运行nvidia-docker运行时作为默认值,需要将"default-runtime":"nvidia"添加到/etc/docker/daemon.json配置文件中,如下所示:

代码语言:javascript
复制
{
    "runtimes": {
        "nvidia": {
            "path": "nvidia-container-runtime",
            "runtimeArgs": []
        }
    },
    "default-runtime": "nvidia"
}

现在你可以跳过docker run命令中--runtime=nvidia参数,GPU将被默认初始化。这样K3s就会用nvidia-docker运行时来使用Docker,让Pod不需要任何特殊配置就能使用GPU。

将Jetson作为K8S节点连接

使用K3sup将Jetson作为Kubernetes节点连接只需要1个命令,然而要想成功连接Jetson和master节点,我们需要能够在没有密码的情况下同时连接到Jetson和master节点,并且在没有密码的情况下做sudo,或者以root用户的身份连接。

如果你需要生成SSH 密钥并复制它们,你需要运行以下命令:

代码语言:javascript
复制
ssh-keygen -t rsa -b 4096 -f ~/.ssh/rpi -P ""
ssh-copy-id -i .ssh/rpi user@host

默认情况下,Ubuntu安装要求用户在使用sudo命令时输入密码,因此,更简单的方法是用root账户来使用K3sup。要使这个方法有效,需要将你的~/.ssh/authorized_keys复制到/root/.ssh/目录下。

在连接Jetson之前,我们查看一下想要连接到的集群:

代码语言:javascript
复制
upgrade@ZeroOne:~$ kubectl get node -o wide
NAME      STATUS   ROLES    AGE   VERSION        INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
nexus     Ready    master   32d   v1.17.2+k3s1   192.168.0.12   <none>        Ubuntu 18.04.4 LTS   4.15.0-96-generic   containerd://1.3.3-k3s1
rpi3-32   Ready    <none>   32d   v1.17.2+k3s1   192.168.0.30   <none>        Ubuntu 18.04.4 LTS   5.3.0-1022-raspi2   containerd://1.3.3-k3s1
rpi3-64   Ready    <none>   32d   v1.17.2+k3s1   192.168.0.32   <none>        Ubuntu 18.04.4 LTS   5.3.0-1022-raspi2   containerd://1.3.3-k3s1

你可能会注意到,master节点是一台IP为192.168.0.12的nexus主机,它正在运行containerd。默认状态下,k3s会将containerd作为运行时,但这是可以修改的。由于我们设置了nvidia-docker与docker一起运行,我们需要修改containerd。无需担心,将containerd修改为Docker我们仅需传递一个额外的参数到k3sup命令即可。所以,运行以下命令即可连接Jetson到集群:

代码语言:javascript
复制
k3sup join --ssh-key ~/.ssh/rpi  --server-ip 192.168.0.12  --ip 192.168.0.40   --k3s-extra-args '--docker'

IP 192.168.0.40是我的Jetson Nano。正如你所看到的,我们传递了--k3s-extra-args'--docker'标志,在安装k3s agent 时,将--docker标志传递给它。多亏如此,我们使用的是nvidia-docker设置的docker,而不是containerd。

要检查节点是否正确连接,我们可以运行kubectl get node -o wide:

代码语言:javascript
复制
upgrade@ZeroOne:~$ kubectl get node -o wide
NAME      STATUS   ROLES    AGE   VERSION        INTERNAL-IP    EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
nexus     Ready    master   32d   v1.17.2+k3s1   192.168.0.12   <none>        Ubuntu 18.04.4 LTS   4.15.0-96-generic   containerd://1.3.3-k3s1
rpi3-32   Ready    <none>   32d   v1.17.2+k3s1   192.168.0.30   <none>        Ubuntu 18.04.4 LTS   5.3.0-1022-raspi2   containerd://1.3.3-k3s1
rpi3-64   Ready    <none>   32d   v1.17.2+k3s1   192.168.0.32   <none>        Ubuntu 18.04.4 LTS   5.3.0-1022-raspi2   containerd://1.3.3-k3s1
jetson    Ready    <none>   11s   v1.17.2+k3s1   192.168.0.40   <none>        Ubuntu 18.04.4 LTS   4.9.140-tegra       docker://19.3.6

简易验证

我们现在可以使用相同的docker镜像和命令来运行pod,以检查是否会有与本文开头在Jetson Nano上运行docker相同的结果。要做到这一点,我们可以应用这个pod规范:

代码语言:javascript
复制
apiVersion: v1
kind: Pod
metadata:
  name: gpu-test
spec:
  nodeSelector:
    kubernetes.io/hostname: jetson
  containers:
  - image: icetekio/jetson-nano-tensorflow
    name: gpu-test
    command:
    - "/bin/bash"
    - "-c"
    - "echo 'import tensorflow' | python3"
  restartPolicy: Never

等待docker镜像拉取,然后通过运行以下命令查看日志:

代码语言:javascript
复制
upgrade@ZeroOne:~$ kubectl logs gpu-test 
2020-05-14 10:01:51.341661: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcudart.so.10.2
2020-05-14 10:01:53.996300: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libnvinfer.so.7
2020-05-14 10:01:53.998563: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libnvinfer_plugin.so.7
/usr/lib/python3/dist-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters

如你所见,我们的日志信息与之前在Jetson上运行Docker相似。

运行MNIST训练

我们有一个支持GPU的运行节点,所以现在我们可以测试出机器学习的 "Hello world",并使用MNIST数据集运行TensorFlow 2模型示例。

要运行一个简单的训练会话,以证明GPU的使用情况,应用下面的manifest:

代码语言:javascript
复制
apiVersion: v1
kind: Pod
metadata:
  name: mnist-training
spec:
  nodeSelector:
    kubernetes.io/hostname: jetson
  initContainers:
    - name: git-clone
      image: iceci/utils
      command:
        - "git"
        - "clone"
        - "<https://github.com/IceCI/example-mnist-training.git>"
        - "/workspace"
      volumeMounts:
        - mountPath: /workspace
          name: workspace
  containers:
    - image: icetekio/jetson-nano-tensorflow
      name: mnist
      command:
        - "python3"
        - "/workspace/mnist.py"
      volumeMounts:
        - mountPath: /workspace
          name: workspace
  restartPolicy: Never
  volumes:
    - name: workspace
      emptyDir: {}

从下面的日志中可以看到,GPU正在运行:

代码语言:javascript
复制
...
2020-05-14 11:30:02.846289: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1697] Adding visible gpu devices: 0
2020-05-14 11:30:02.846434: I tensorflow/stream_executor/platform/default/dso_loader.cc:48] Successfully opened dynamic library libcudart.so.10.2
....

如果你在节点上,你可以通过运行tegrastats命令来测试CPU和GPU的使用情况:

代码语言:javascript
复制
upgrade@jetson:~$ tegrastats --interval 5000
RAM 2462/3964MB (lfb 2x4MB) SWAP 362/1982MB (cached 6MB) CPU [52%@1479,41%@1479,43%@1479,34%@1479] EMC_FREQ 0% GR3D_FREQ 9% PLL@23.5C CPU@26C PMIC@100C GPU@24C AO@28.5C thermal@25C POM_5V_IN 3410/3410 POM_5V_GPU 451/451 POM_5V_CPU 1355/1355
RAM 2462/3964MB (lfb 2x4MB) SWAP 362/1982MB (cached 6MB) CPU [53%@1479,42%@1479,45%@1479,35%@1479] EMC_FREQ 0% GR3D_FREQ 9% PLL@23.5C CPU@26C PMIC@100C GPU@24C AO@28.5C thermal@24.75C POM_5V_IN 3410/3410 POM_5V_GPU 451/451 POM_5V_CPU 1353/1354
RAM 2461/3964MB (lfb 2x4MB) SWAP 362/1982MB (cached 6MB) CPU [52%@1479,38%@1479,43%@1479,33%@1479] EMC_FREQ 0% GR3D_FREQ 10% PLL@24C CPU@26C PMIC@100C GPU@24C AO@29C thermal@25.25C POM_5V_IN 3410/3410 POM_5V_GPU 493/465 POM_5V_CPU 1314/1340

总 结

如你所见,将Jetson Nano连接到Kubernetes集群是一个非常简单的过程。只需几分钟,你就能利用Kubernetes来运行机器学习工作负载——同时也能利用NVIDIA袖珍GPU的强大功能。你将能够在Kubernetes上运行任何为Jetson Nano设计的GPU容器,这可以简化你的开发和测试。

作者:

Jakub Czapliński,Icetek编辑

原文链接:

https://medium.com/icetek/how-to-connect-jetson-nano-to-kubernetes-using-k3s-and-k3sup-c715cf2bf212

推荐阅读

简化公有云K3s部署体验,Rancher开源自动化工具AutoK3s

利用K3s低成本在流水线中添加测试

如何基于K3s构建云原生边缘基础设施?

About k3s

k3s 是首个进入 CNCF 沙箱项目的 K8S 发行版,同时也是当前全球用户量最大的 CNCF 认证轻量级 K8S 发行版。自2019年3月发布以来,备受全球开发者们关注,至今GitHub Star数已超过 14,600,成为了开源社区最受欢迎的边缘计算 K8S 解决方案。截至目前,K3s全球下载量超过100万次,每周平均被安装超过2万次,其中30%的下载量来自中国。

k3s 专为在资源有限的环境中运行 Kubernetes 的研发和运维人员设计,将满足日益增长的在边缘计算环境中运行在 x86、ARM64 和 ARMv7 处理器上的小型、易于管理的 Kubernetes 集群需求。k3s 的发布,为开发者们提供了以“Rancher 2.X + k3s”为核心的从数据中心到云到边到端的 K8S 即服务(Kubernetes-as-a-Service),推动 Kubernetes Everywhere。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-11-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CNCF 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档