kubernetes上のNode-REDでもBLEビーコンを受信したい

#はじめに
いつでも最新版のNode-REDを使いたいのでコンテナ版の利用に切り替えたかったのですが、環境センサー(EnOcean)のビーコンを取得するための「node-red-contrib-blebeacon-scanner」が公式のコンテナイメージでは使えませんでした。

https://flows.nodered.org/node/node-red-contrib-blebeacon-scanner

#前提環境

Raspberry Pi4で、kubernetesのバージョンはv1.20.0〜5くらいです。(揃えてません)

```shell-session:
# kubectl get nodes -o wide
NAME    STATUS   ROLES           AGE    VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE                       KERNEL-VERSION   CONTAINER-RUNTIME
chino   Ready    control-plane   233d   v1.20.5   10.0.0.1      <none>        Debian GNU/Linux 10 (buster)   5.4.83-v8+       docker://20.10.5
chiya   Ready    worker          233d   v1.20.0   10.0.0.5      <none>        Debian GNU/Linux 10 (buster)   5.4.65-v8+       docker://20.10.1
cocoa   Ready    worker          227d   v1.20.0   10.0.0.2      <none>        Debian GNU/Linux 10 (buster)   5.4.65-v8+       docker://20.10.1
maya    Ready    worker          90d    v1.20.1   10.0.0.7      <none>        Debian GNU/Linux 10 (buster)   5.4.65-v8+       cri-o://1.20.0
megu    Ready    worker          125d   v1.20.1   10.0.0.8      <none>        Debian GNU/Linux 10 (buster)   5.4.83-v8+       cri-o://1.20.0
rize    Ready    worker          227d   v1.20.0   10.0.0.3      <none>        Debian GNU/Linux 10 (buster)   5.4.65-v8+       docker://20.10.1
syaro   Ready    worker          227d   v1.20.0   10.0.0.4      <none>        Debian GNU/Linux 10 (buster)   5.4.65-v8+       docker://20.10.1
```

#構築
Node-REDの構築手順からすると、node.jsからnpmでインストールするのが一般的なので、node.jsの公式イメージを使えば手っ取り早そうです。
コンテナでbluetoothを使う方法を検索するとdockerでの解決策が「hostnetworkを使う」という事なので、kubernetesでもhostNetworkを使うようにします。

##コンテナ作成
できればOSディストリビューションを合わせてサイズも最小にしたいので、ベースは「node:buster-slim」のarm64を使うことにします。
内容はOS側のパッケージで、コンパイルできる環境とpython3、あと今回必要になるbluetoothとudevの開発環境をインストールしておきます。
(ちなみに、公式イメージは「node-red-contrib-blebeacon-scanner」のインストール中に"../libusb/libusb/os/linux_udev.c:40:10: fatal error: libudev.h: No such file or directory"となり失敗します。)

```:Dockerfile
FROM node:14-buster-slim
WORKDIR /root
RUN apt update && \
  apt -y install g++ make python3 libbluetooth-dev libudev-dev && \
  npm install -g --unsafe-perm node-red
```

podman | docker でbuildしてpushします。
私の環境ではkubernetes内にregistryをNodePortで立てているので、kubernetesのnodeでは「localhost:30500」で使えるようにしています。
registryをどこにも持ってない方は、デプロイしたいノードにイメージをコピーしてください。

```shell-session:
# podman build -t localhost:30500/node-red:latest .
# podman push --tls-verify=false localhost:30500/node-red:latest
```

##Podのマニフェスト作成
ポイントとなるのは、デプロイさせるNodeを「nodeName:」に指定する事と、「hostNetwork: true」にする事です。
node-redコマンドの引数「--userDir」でフローなどを保存するディレクトリを指定できて、フローのファイル名を指定できるので、永続ストレージなどを指定します。
(以下のマニフェストでは永続ストレージを使うようにしていません。ご自身の環境に合った設定にしてください。)

```yaml:node-red.yaml
apiVersion: v1
kind: Pod
metadata:
  name: node-red
spec:
  containers:
  - name: node-red
    image: localhost:30500/node-red:latest
    command: ['sh','-c']
    args:
    - |
      node-red --userDir /root/.node-red flows.json
    env:
    - name: TZ
      value: "Asia/Tokyo"
    ports:
    - name: node-red
      containerPort: 1880
  nodeName: maya
  hostNetwork: true
```

サービスは適当に作りましょう。

```yaml:node-red-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: node-red
  labels:
    app: node-red
spec:
  type: NodePort
  ports:
    - port: 1880
      targetPort: 1880
      nodePort: 31880
      protocol: TCP
  selector:
    app: node-red
```

マニフェストができたらデプロイしましょう。

```shell-session:
# kubectl apply -f node-red.yaml
# kubectl apply -f node-red-service.yaml
```

# node-red-contrib-blebeacon-scannerのインストール

npmで「noble」のインストールをしておきます。

```shell-session:
# kubectl exec -it node-red -- /bin/bash
root@megu:~# cd /root/.node-red
root@megu:~/.node-red# npm install @abandonware/noble
```

インストールできるお膳立てはしてあるので、Node-REDのパレットの管理から「ノードを追加」します。

![スクリーンショット 2021-05-05 23.33.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410957/f41783f0-e86d-88cf-91fb-ed6383cedd89.png)

エラーが出ていないか、Podのログからも確認します。

```shell-session:
# kubectl logs node-red -f
(node:8) [DEP0128] DeprecationWarning: Invalid 'main' field in '/usr/local/lib/node_modules/node-red/node_modules/@node-red/editor-client/package.json' of './lib/index.js'. Please either fix that or report it to the module author
(Use `node --trace-deprecation ...` to show where the warning was created)
5 May 23:31:29 - [info] 

Welcome to Node-RED
===================

5 May 23:31:29 - [info] Node-RED version: v1.3.4
5 May 23:31:29 - [info] Node.js  version: v16.0.0
5 May 23:31:29 - [info] Linux 5.4.83-v8+ arm64 LE
5 May 23:31:30 - [info] Loading palette nodes
5 May 23:31:31 - [info] Settings file  : /root/.node-red/settings.js
5 May 23:31:31 - [info] Context store  : 'default' [module=memory]
5 May 23:31:31 - [info] User directory : /root/.node-red
5 May 23:31:31 - [warn] Projects disabled : editorTheme.projects.enabled=false
5 May 23:31:31 - [info] Flows file     : /root/.node-red/flows.json
5 May 23:31:31 - [info] Creating new flow file
5 May 23:31:31 - [warn] 

---------------------------------------------------------------------
Your flow credentials file is encrypted using a system-generated key.

If the system-generated key is lost for any reason, your credentials
file will not be recoverable, you will have to delete it and re-enter
your credentials.

You should set your own key using the 'credentialSecret' option in
your settings file. Node-RED will then re-encrypt your credentials
file using your chosen key the next time you deploy a change.
---------------------------------------------------------------------

5 May 23:31:31 - [info] Server now running at http://127.0.0.1:1880/
5 May 23:31:31 - [info] Starting flows
5 May 23:31:31 - [info] Started flows
5 May 23:33:35 - [info] モジュール node-red-contrib-blebeacon-scanner, バージョン: 1.0.1 をインストールします
5 May 23:33:36 - [info] モジュール node-red-contrib-blebeacon-scanner をインストールしました
5 May 23:33:37 - [info] 追加したノード:
5 May 23:33:37 - [info]  - node-red-contrib-blebeacon-scanner:BLE Beacon Scanner
```

問題なさそうです。

#おわりに
Node-REDはデバイスを直接扱う事が多いのですが、bluetoothデバイスについてもkubernetesからでも利用できる事が確認できました。
以前にカメラを利用した事もあったのですが、今回の方がやや面倒でした。

https://qiita.com/Y-Shikase/items/eea9b8b3320ffd7a55bb

ご興味あれば見てあげてください。