仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

ラズパイとJetson Nanoが混在したKubernetes環境をk3sで作る

前回はJetson NanoでK3sを用いたKubernetesクラスターを動かしてみました。

tech.virtualtech.jp

今回はラズパイ4とJetson Nanoの混在したクラスターを作ってみたいと思います。

f:id:virtualtech:20200727141647p:plain

構成について

ラズパイ側は

ラズパイはRaspberry Pi 4 8GBモデルを用意しました。K3s自体は512MBのメモリーを実装したラズパイで動作しますので、Raspberry Pi 4の2GBモデルでも4GBモデルでも同じように動作すると思います。今回は手元にあったのが8GBモデルだったということと、クラスターを組んだ後、そのノードもWorkerノードとして使う前提だったのでメモリが多めのものを使うことにしました。メモリー2GB未満だといろいろきついと思います。

OSはRaspberry Pi OS 64bitを最新のバージョンにアップデートします。 2020/07/27時点のイメージで起動した場合、Linux Kernel 5.4ベースの最新版に更新されます。 また、cgroupの設定も事前に行っておきます(未確認ですが、Raspberry Pi 3Bではcgroupの設定がうまくいかないようです。バグかも?)。

cgroupの設定は、 /boot/cmdline.txt の末尾に cgroup_memory=1 cgroup_enable=memory を書いて再起動するだけです。

今回はCRIとしてDockerを使いたいため、Dockerをインストールしておきます。

~$ sudo apt update && sudo apt install docker.io

Jetson Nano側は

Jetson Nanoは以下の手順に従い、セットアップします。OSは「Jetson Nano Developer Kit SD Card Image」を使い、最新のアップデートを適用します。 2020/07/27時点のイメージで起動した場合、Linux Kernel 4.9のUbuntu 18.04.4ベースです。

使い始める前にシステムアップデートして再起動してからセットアップすることをおすすめします。

各ノードのIPアドレスを設定します。

developer.nvidia.com

「Jetson Nano Developer Kit SD Card Image」を使った場合はDockerやGPUを使うための色々なライブラリーはセットアップ済みです。

前回の記事同様に、デフォルトランタイムを nvidiaにする設定だけ行っておきます。

~$ sudo docker info | grep Runtime
 Runtimes: nvidia runc
 Default Runtime: runc

~$ sudo vi /etc/docker/daemon.json
{
    "default-runtime": "nvidia",     <-追記
    "runtimes": {
        "nvidia": {
            "path": "nvidia-container-runtime",
            "runtimeArgs": []
        }
    }
}

~$ sudo systemctl restart docker
~$ sudo docker info | grep Runtime
 Runtimes: nvidia runc
 Default Runtime: nvidia

ところで混在できて何が嬉しいのか

全てのアプリケーションの実行にGPUが必要ないが、GPUを使ったコンテナーアプリケーションを実行したい時にGPUユニットが載ったマシンで動かしたい。 GPUクラスターと非GPUクラスターを別々に持つ必要がないので管理コストも半分。 そんなメリットがあります。

Raspberry Pi側の設定

Raspberry Piは今回はMasterノード兼Workerノードとして使います。 以下のようにセットアップを行います。

~$ curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--docker" sh -s -

コマンドを実行して、クラスターが正常に実行されていることを確認します。

~$ sudo kubectl get no 
NAME      STATUS   ROLES    AGE    VERSION
raspi4    Ready    master   117m   v1.18.6+k3s1

クラスターが起動したら、トークンキーを確認します。

~$ sudo cat  /var/lib/rancher/k3s/server/node-token
K10022ca9e54ffa73dedd71dfd3983603adc7befcfb517a6ccbc356b7578316edca::server:1188c86cc84aeceedf48d9523f0948ae

Jetson Nano

Jetson Nanoは今回はWorkerノードとして使います。 以下のようにセットアップを行います。

~$ curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--docker" K3S_URL=https://192.168.1.71:6443 K3S_TOKEN=K10022ca9e54ffa73dedd71dfd3983603adc7befcfb517a6ccbc356b7578316edca::server:1188c86cc84aeceedf48d9523f0948ae sh -

コマンドを実行して、クラスターにJetsonが追加されていることを確認します。

f:id:virtualtech:20200727142259p:plain

[7/28 注記] 上記スクリーンショットではDebian 10となっていますが、Raspberry Pi OS 10 64bit版です。Raspberry Pi OS 10の32bit版はRaspbianベースですが、64bit版はDebian 10 arm64ベースであるため、Debian 10と認識されます。

Masterノードで実行

次のようなYAMLを用意します。 nodeSelector でホスト名として kubectl get node で表示される名前を指定します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginxapp1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginxapp1
  template:
    metadata:
      labels:
        app: nginxapp1
    spec:
      containers:
      - name: nginxapp1
        image: nginx:alpine
        ports:
        - containerPort: 80
      nodeSelector:
        kubernetes.io/hostname: jetson1

Podが作成できることを確認します。

~$ sudo kubectl create -f nginx.yaml 
deployment.apps/nginxapp1 created

~$ sudo kubectl get -f nginx.yaml 
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
nginxapp1   1/1     1            1           5s

次に、以下のYAMLを作成して、サービスを定義します。

apiVersion: v1
kind: Service
metadata:
  name: nginxapp1-nodeport
  labels:
    app: nginxapp1
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
  selector:
    app: nginxapp1

Serviceが作成できることを確認します。

~$ sudo kubectl create -f nginx-svc.yaml 
service/nginxapp1-nodeport created

~$ sudo kubectl get -f nginx-svc.yaml 
NAME                 TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
nginxapp1-nodeport   NodePort   10.43.139.49   <none>        80:30080/TCP   14s

NGINXアプリケーションにアクセスできることを確認します。

~$ sudo kubectl get po -o wide
NAME                         READY   STATUS    RESTARTS   AGE     IP          NODE      NOMINATED NODE   READINESS GATES
nginxapp1-6489c458b8-xwsxx   1/1     Running   0          4m27s   10.42.1.7   jetson1   <none>           <none>

~$ curl --head http://192.168.1.71:30080
HTTP/1.1 200 OK
Server: nginx/1.19.1
Date: Mon, 27 Jul 2020 04:59:29 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Fri, 10 Jul 2020 20:32:43 GMT
Connection: keep-alive
ETag: "5f08d06b-264"
Accept-Ranges: bytes