この記事は、Node-REDのコンテナをビルドして、Kubernetesの上で他のサービスと連携させるまでの道のり解説の最終回です。 前回までに作ったNode-REDのコンテナをKubernetesにデプロイして、Cloudant、MySQL、REST APIの動作について、進めていきます。
Node-REDのコンテナのビルド、DockerHubへの登録は、Node-RED v0.18が動作するコンテナをビルドして Kubernetes で実行するまでを解説 (1/3)に解説しました。
そして、Node-REDコンテナから、IBM Cloudのサービスや、同じコンテナの CloudantやMySQLサーバーとの連携は、第2回目 Node-REDが動作するコンテナをビルドして Kubernetes で実行するまでを解説 (2/3) で解説しました。
第3回目は、無料で利用できるIBM Cloud Container Service (Kubernetes)のライトプランでの利用方法です。
- Node-REDが動作するコンテナをビルドして Kubernetes で実行するまでを解説 (1/3)
- Node-REDが動作するコンテナをビルドして Kubernetes で実行するまでを解説 (2/3)
- Node-REDが動作するコンテナをビルドして Kubernetes で実行するまでを解説 (3/3)
- Node-REDが動作するコンテナをビルドして Kubernetes で実行するまでを解説 (番外編)
無料で利用できるKubernetesのデプロイ
IBM Cloud にログインして、Container Serviceをクリックして、Kubernetesのクラスタのオーダー画面を開きます。
無料で利用できるk8sクラスタのオーダー
Regionによっては、無料プランを利用できない場所もある様です。 この例では米国南部を選択して、クラスタ・タイプに無料を選択しました。
Cluster name に名前をセットして、「クラスターの作成」をクリックして先へ進めます。 無料プランでは、ノードは1個に制限されています。また、ロードバランサーや永続ストレージも利用できないので、お試し用という位置づけです。 しかし、Node-REDの開発であれば十分利用できますので、無料プランで進めていきます。
デプロイ中画面
Kubernetesを利用できる様セットアップするには、ユーザー専用のマスタとノードを起動する必要があり、およそ20分〜30分くらい時間がかかります。 準備作業中は、プロビジョニング中と表示されていますので、待ちます。
準備完了状態
準備が完了したら次の画面の様に、状態欄に「準備完了」と表示されます。
kubectl コマンドのセットアップ
これで、Kubernetesを利用するクラウド側の準備が完了しました。 Kubernetesの利用には、コマンド・ライン・インタフェースが必須になりますので、以下2つのコマンドをインストールして、ログインします。
k8sの利用には必須のプラグインをインストールします。 このプラグインのサブコマンドで、k8sより下層部分の設定を行います。
bx plugin install container-service -r Bluemix
IBM Cloudにログインして、米国南部(us-south)のリージョンをセットします。
bx login -a https://api.ng.bluemix.net
bx cs region-set us-south
kubectlコマンドの認証情報をダウンロードするために、次のコマンドを実行します。 コマンドが正常終了すると、KUBECONFIG=
から始まる環境変数の雛形を表示しますので、コピペして環境変数にセットします。
bx cs cluster-config mycluster1
上記の操作で、kubectlが利用できる様になりました。 IBM Cloud 上の k8sマスタと接続ができるか、確認してみます。 次のコマンドでノードのリストを表示できます。 ライトプランですから、1個しかありません。 IPアドレスは、旧SoftLayerで良く知られた、プライベート側IPアドレスで、ユーザー専用のネットワークになります。 このIPを公開しても、他のユーザーは、一般のルートから、このアドレスへ到達できません。
kubectl get node
NAME STATUS ROLES AGE VERSION
10.76.193.109 Ready <none> 8h v1.8.8-2+9d6e0610086578
Node-REDコンテナ を k8s上にデプロイ
ここまでの作業で、kubectlコマンドが利用できる様になりましたので、k8sへコンテナをデプロイするためのYAMLのファイルを作成して、適用していきます。
YAMLファイルの作成
次は、Node-REDのコンテナをデプロイするためのYAMLです。 image項目のフィールに、DockerHubに登録したコンテナのイメージを入れます。それ以外は、そのまま、利用します。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: node-red
spec:
replicas: 1
template:
metadata:
labels:
app: node-red
spec:
containers:
- name: node-red
image: maho/node-red:1.0
ports:
- containerPort: 1880
kubectl create -f ファイル名
でファイルを適用します。 これでNode-REDコンテナを動作させるポッドが1個起動します。
kubectl create -f node-red-depoy.yaml
起動の確認には、kubectl get deploy node-red
を利用します。 AVAILABLEの値が1になれば、起動完了です。
$ kubectl get deploy node-red
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
node-red 1 1 1 1 1h
ここまでの状態では、k8sのクラスタネットワーク上だけに、コンテナを内包するポッドが繋がった状態ですから、どこからもアクセスできません。そこで、次のYAMLファイルを利用して、ポッドをホストしているノードにアクセスポートを開きます。 nodePortの値で 31880 が外部に解放されるNode-REDのポート番号になります。
apiVersion: v1
kind: Service
metadata:
name: node-red
spec:
type: NodePort
selector:
app: node-red
ports:
- protocol: TCP
port: 1880
nodePort: 31880
次のコマンドで、YAMLファイルを適用して、NodePortサービスを開始します。
kubectl create -f node-red-nodeport.yaml
公開先IPアドレスの確認
NodePortは、コンテナをホストするノードのIPアドレスを利用して、ポートを開いて、アクセスを提供するというものです。 そこで、ノードのパブリックIPアドレスを調べます。 これには、プラグインとして追加した bx cs
サブコマンドを利用していきます。 はじめに、k8sのクラスターの名前を取得します。
imac:k8s maho$ bx cs clusters
OK
Name ID State Created Workers Location Version
mycluster1 890f1e136a2f4054854059fa70ea0fca normal 10 hours ago 1 hou02 1.8.8_1507
次に、クラスタ名を指定して、workersで、ノードのリストを表示します。 k8sのプロジェクトでは、コンテナをホストするサーバーを単なるノードと読んでいるのですが、IBM Cloudeでは、同じノードを Worker node という呼び方をしているので、混乱しない様に覚えていると良いでしょう。
Public IPの欄にあるIPアドレスが、外部のインターネットからアクセスできるIPアドレスになります。
imac:k8s maho$ bx cs workers mycluster1
OK
ID Public IP Private IP Machine Type State Status Zone Version
kube-hou02-pa890f1e136a2f4054854059fa70ea0fca-w1 173.193.xxx.yyy 10.76.193.109 free normal Ready hou02 1.8.8_1507
k8s上のNode-REDコンテナへアクセス
ここまでで、ノードのIPアドレス、ポート番号が解りましたので、ブラウザからアクセスしてみます。 次の様なログイン画面が出てくれば成功です。
ユーザーIDとパスワードは、第一回目に記述していますので、参照願います。ログインして、先へ進めていきます。
現在のところ、ユーザーIDやパスワードを変更するには、設定ファイルにユーザーIDとパスワードのハッシュが書き込まれているため、コンテナの再ビルドが必要になります。 プロジェクトで利用する場合などは、Node-REDコンテナの再ビルドを検討してください。
k8s上のCloudantなど他のサービスと連動
ここまでで、Node-REDのコンテナが、k8sで動作する事が確認できましたので、次は、Node-REDとサービスと連携させていきます。 具体的なイメージは、次の図の様になります、 前章で立ち上げたのが、図中真ん中付近の、Node-REDコンテナとNodePortサービスになります。次に、ここから、CoudantのコンテナとClusterIPサービスを起動して、連携させます。
Cloudantコンテナのデプロイ
Cloudantのコンテナをk8sの上にデプロイして、他のデプロイメント(コンテナ)と連携できる様に、ClusterIPのサービスを起動します。
次のYAMLがCloudantのサーバーを起動するための定義です。 spec.containes.image
の値であるibmcom/cloudant-developer:2.0.1
は、DockerHubに登録されているコンテナのイメージです。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: cloudant
spec:
replicas: 1
template:
metadata:
labels:
app: cloudant
spec:
containers:
- name: cloudant
image: ibmcom/cloudant-developer:2.0.1
ports:
- containerPort: 80
Node-REDのコンテナと同様に、YAMLを提供して起動します。
$ kubectl create -f cloudant-deploy.yml
次のコマンドで起動を書くにします。 前回同様にAVAILABLEが 1 になれば、起動完了です。
$ kubectl get deploy cloudant
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
cloudant 1 1 1 1 1h
そして、Node-REDのコンテナからCloudantoをアクセスできる様にサービスを立ち上げます。 前回は外部に公開するものでしたが、今回は、spec.typeの値が ClusterIPとなっており、内部に公開するためのサービスです。
apiVersion: v1
kind: Service
metadata:
name: cloudant
spec:
type: ClusterIP
selector:
app: cloudant
ports:
- protocol: TCP
port: 8080
targetPort: 80
次のコマンドでk8sクラスタに適用します。 この適用によって、k8s内で動作するDNSに登録され、CloudantのDNS名でアクセスできる様になりますので、Node-REDに設定する場合は、k8sのDNS名で登録します。
$ kubectl create -f cloudant-service.yml
サービスの起動は、次のコマンドで確認できます。 元のコンテナが解放するポート番号は80番でしたが、サービスで8080番に変換して提供します。
$ kubectl get svc cloudant
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cloudant ClusterIP 172.21.175.93 <none> 8080/TCP 28m
疎通確認
ここでNode-REDのコンテナ(ポッド)にログインして、curlコマンド、Cloudantへアクセスできるか確認してみます。 必須の作業ではありませんから、参考程度に見てください。 興味があれば、kubectl get nodes
でCloudantのポッド名を調べて、ポッド名を置き換えて実行します。そして、curlコマンドで、http://cloudant:8080/ で Welcomeが帰ってくれば、疎通確認完了です。
$ kubectl exec -it node-red-64d45cfd95-nzx57 sh
/node-red # curl http://cloudant:8080/
{"couchdb":"Welcome","version":"2.0.0","vendor":{"name":"IBM Cloudant","version":"1.1.0","variant":"local"},"features":["geo"]}
Cloudantノードへの設定
k8sのNode-REDコンテナをアクセスして、フローエディタで、次の様にCloudantのノードを配置します。 TimestampノードとCloudantノードに空のFunctionノードを置く理由は、Cloudantにデータベースが作成されていない場合、自動的にFunctionがデータベースを作成してくれるためです。
Cloudantのノードをダブルクリックして、プロパティを設定していきます。 Serverの行の「えんぴつ」マークをクリックして、ホスト名などを設定します。 パスワードなどは、第2回目で記載していますので参照をお願いします。
ここで、ホスト名は、http://cloudant:8080/
とします。CloudantがRESTサービスであるので、URLのインプットが想定されているためです。 cloudantは、先に起動したcludantのサービス名で、Node-REDのコンテナからkube-dnsを介して、アドレスが解決されます。
Node-REDとCloudantの連携テスト
ここまでで、Node-REDコンテナとCloudantコンテナの連携の設定が完了したので、テストします。 次のフローは、Timestampノードをクリックして、デバック・ウィンドに、タイムスタンプの値が表示されると同時に、Cloudantへ登録されるものです。
Cloudant 管理画面を見るための設定
上記の操作で、正しく、Cloudantへデータが登録されているか、Cloudantの管理コンソールにアクセスして確かめたいと思います。 インターネット越しにアクセスできる様するには、次のYAMLでNodePortの設定を加えます。 これによって、nodePortの値、31080で Cloudantの管理画面のポートが開きます。
cloudant-nodeport.yml
apiVersion: v1
kind: Service
metadata:
name: cloudant-nodeport
spec:
type: NodePort
selector:
app: cloudant
ports:
- protocol: TCP
port: 80
nodePort: 31080
次のコマンドで適用します。
$ kubectl create -f cloudant-nodeportyml
設定の確認を実施ます。
$ kubectl get svc cloudant-nodeport
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
cloudant-nodeport NodePort 172.21.182.158 <none> 80:31080/TCP 38m
$ kubectl get node
NAME STATUS ROLES AGE VERSION
10.76.193.109 Ready <none> 12h v1.8.8-2+9d6e0610086578
$ bx cs workers mycluster1
OK
ID Public IP Private IP Machine Type State Status Zone Version
kube-hou02-pa890f1e136a2f4054854059fa70ea0fca-w1 173.193.xx.yyy 10.76.193.109 free normal Ready hou02 1.8.8_1507
それでは、ブラウザでアクセスします。 上記のアドレス http://173.193.xx.yyy:31080/となり、認証情報は、第2目に記載した通り、username: admin, password: pass です。
次の様にデータベース testdb1が作成され、3個のデータが登録されている事が確認できます。
最初の1個を開いて、登録されたデータとデバックウインドの表示値があっているか確認します。
注意
無料枠内で利用できる事、解りやすさ、目的への到達の早さを考慮して、下記の点を省略していますので、ご注意をお願いします。
- この例では、永続ストレージをマウントしていないので、ポッドが再起動されたり、削除されると、データを失います。
- コンテナのパスワードは、プロジェクト等で利用する場合は、変更が必要です。
k8s上のMySQLのサービスと連動
次は、MySQLとの連携を確認していきます。 Cloudantの様に確認用のコンソールが無いので、コマンドラインが利用できるポッド(コンテナ)を起動してMySQLクライアントを実行して、設定や確認を進めていきます。
今回は、最初に Node-REDコンテナとMySQLコンテナの連携をフローエディタで描いてから、進めます。function-2には、データをテーブルにインサートするためのSQL文を書く必要があります。 ノードの設定内容は、詳しくは第2回目を参照してください。
次は、MySQLサーバーのコンテナを起動するためのYAMLです。 DockerHubに登録された公式MySQLイメージを取得して、K8s上にデプロイします。このコンテナの詳しい説明は、DockerHub mysqlの説明を参照願います。 YAMLに環境変数を設定する事で、パスワード設定やcreate database
を実行してくれる良くできたコンテナです。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: mysql
spec:
replicas: 1
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
ports:
- containerPort: 3306
env:
- name: MYSQL_DATABASE
value: "testdb2"
- name: MYSQL_ROOT_PASSWORD
value: "password"
同じ要領で、デプロイの実行と、起動の確認をおこないます。
$ kubectl create -f mysql-deploy.yml
$ kubectl get deploy mysql
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
mysql 1 1 1 1 16m
これまで同様に、サービスを起動して、他のデプロイメント(コンテナ)からkube-dnsの名前解決でアクセスできる様にします。
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
type: ClusterIP
selector:
app: mysql
ports:
- protocol: TCP
port: 3306
同様に適用と起動の確認をします。
$ kubectl create -f mysql-service.yml
$ kubectl get svc mysql
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysql ClusterIP 172.21.247.189 <none> 3306/TCP 17m
MySQLサーバーには、testdb2というデータベースが作成されていますが、データを格納するテーブルがありません。そこで、コマンドライン用のポッド(コンテナ)を起動して、テーブルを作成します。
$ kubectl run -it --image mysql my-client bash
If you don't see a command prompt, try pressing enter.
上記で Enter キーを押すと、以下の様にmy-clientコンテナの中に入り、mysqlコマンドで、mysqlコンテナのMySQLサーバーへログインして、テーブルを作ります。
root@my-client-65bbd59569-x4v8t:/# mysql -h mysql -u root -ppassword testdb2
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.21 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show tables;
Empty set (0.00 sec)
mysql> CREATE TABLE payload (id MEDIUMINT NOT NULL AUTO_INCREMENT, msg CHAR(30) NOT NULL, PRIMARY KEY (id) );
Query OK, 0 rows affected (0.00 sec)
mysql> show tables;
+-------------------+
| Tables_in_testdb2 |
+-------------------+
| payload |
+-------------------+
1 row in set (0.00 sec)
mysql> desc payload;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | mediumint(9) | NO | PRI | NULL | auto_increment |
| msg | char(30) | NO | | NULL | |
+-------+--------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
mysql>
Node-REDの設定
次の図の様に、フリーエディタのMySQLノードをクリックして、MySQLのコンテナと接続するための設定を入力していきます。
IPアドレスではなく、サービス名を設定します。 コンテナのIPアドレスは、再起動すると再割り当てされるため、一定しません。このためmysqlというDNS名で設定が必要になるのです。
動作テスト
timestampノードをクリックして、タイムスタンプの値が、MySQLノードにセットされるか確認してみましょう。
先にログインしたmysqlクライアントで、select文を実行すると、デバックウインドに表示されたデータと同じ値が登録されている事がわかります。
これで、k8s上のNode-REDコンテナとMySQLコンテナの連携の解説は完了です。 dockerコマンドの代わりに、yamlを作成して適用する点、必ずサービスを起動する点など多少の差がありますが、コンテナを理解していれば、大きな違いが無い事が判ったと思います。
RESTサービスの雛形
最後にK8s上のNode-REDが提供するRESTサービスの設定方法とアクセス方法について、簡単に確認します。
次のフローは、RESTサービスで簡単な文字列を返すフローです。 このフローの作成は、第2回目の記事を参照願います。/recvをGETでアクセスすると、次のフローがコールバックされ、functionでセットされる文字列が返されます。
k8sではNodePortで開いていますから、URLのディレクトリ部分を前述の/recvに変更する事で、次の結果を得る事がきます。
まとめ
Node-REDは、コードを書かない人にも、プログラムが出来そうな気にさせる、凄く優れたツールだと思います。 そして、プログラミングの敷居を下げ、IoTなどの高速開発の道を開いた様に思います。 この優れたNode-REDをKubernetesのコンテナ上で動かして、他のコンテナと関連付けて、コンテナの再利用の効果によって、さらなる高い生産性を達成していく事ができる様に思います。 是非、試して体験して頂きと思います。