まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:raspberrypi

先日紹介したこの記事の続き、というか、本命版です:
ラズベリーパイと鳩サブレ缶で docker swarm クラスタを構築する

豊島屋の鳩サブレ缶がちょうどラズベリーパイ(以下「ラズパイ」)を4つ格納できるような仕切りになっていることに気付いて、この鳩サブレ缶とラズパイでクラスタ環境を作れないか、と思い立ったことがきっかけでした。先日は docker swarm のクラスタを構築しましたが、今回は kubernetes のクラスタを構築します:
20190117


なお、構築手順の途中までは先日と全く同じです。具体的にはこのページでも紹介している3台のラズパイそれぞれに docker を導入する所までは同じ手続きを行います。なお、ここまでの作業が完了している前提で以下を紹介します。


【スワップメモリの無効化】
ここからが Kubernetes 環境のための手順となります。まず Kubernetes 1.8 以降ではスワップメモリが有効な環境下では kubelet が起動しないため、3台のラズパイそれぞれでスワップメモリを無効にします:
$ sudo dphys-swapfile swapoff

$ sudo dphys-swapfile uninstall

$ sudo update-rc.d dphys-swapfile remove


【kubeadm, kubectl, kubelet のインストール】
いよいよ Kubernetes をインストールします。具体的には kubeadm, kubectl, kubelet を導入するのですが、まずはリポジトリを登録&更新します:
$ curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg|sudo apt-key add -

$ echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kube.list

$ sudo apt-get update

そして kubeadm, kubectl, kubelet をインストールします。ただこちらで検証した限りでは kubernetes のバージョン 1.8 以下しか動作しませんでした。というわけでバージョン 1.8 を指定して kubernetes コマンド群をインストールします:
$ sudo apt-get install kubelet=1.8.14-00 kubeadm=1.8.14-00 kubectl=1.8.14-00 kubernetes-cni=0.5.1-00

これでラズパイノードに Kubernetes のコマンドが導入できました。ここまでの作業は3台それぞれで実施する必要があります。


【マスターノードの準備】
Kubernetes のマスターノードを作成します。今回は3台のラズパイの中の raspi001 をマスターノードとするので、以下のコマンドを raspi001 でのみ実施します。またその結果、この前に導入した docker のバージョンとの不整合が起きてしまうので、インストールコマンド時に「バージョンチェックをしない」ための --skip-preflight-checks オプションを指定します:
$ sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --skip-preflight-checks

成功したら、成功時の画面に表示される以下のコマンドを順次実行して pod network をデプロイします:
$ mkdir -p $HOME/.kube

$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

後は flannnel をデプロイします:
$ kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/bc79dd1505b0c8681ece4de4c0d86c5cd2643275/Documentation/kube-flannel.yml

これでマスターノードの準備は完了です。


【ワーカーノードの準備】

2台のワーカーノードをマスターノードに接続します。マスターノードの sudo kubeadm init コマンドを実行して成功した時に表示される kubeadm join コマンドを各ワーカーノードで実行します:
$ kubeadm join --token XXXXXX....XXXXXX 192.168.10.101:6443 --discovery-token-ca-cert-hash sha256:ZZZZZZZZZZZZ....ZZZZZZZZZZZZZZZ

【接続状態を確認】

マスターノードで "kubectl version" コマンドを実行してサーバーとクライアントのバージョンを、"kubectl get nodes" コマンドを実行して各ノードの状態が表示されることを確認します:
20190128


なんとかラズパイで kubernetes クラスタ環境が作れました。


 
(参考)
https://qiita.com/hatotaka/items/48a88ecb190e1f5e03c3

https://qiita.com/MahoTakara/items/2b39e06f077927bafa2c



ラズベリーパイに日本語の形態素解析エンジンである MeCab をインストールする方法を紹介します。

少しだけ補足をしておくと、ただ単にラズベリーパイに MeCab をインストールするだけであれば、普通に apt-get を使って、
$ sudo apt-get install mecab libmecab-dev mecab-ipadic

とかあれば導入できることは確認しました。ただこの方法で導入した MeCab を使うと、実行結果がことごとく文字化けしてしまうようでした(EUC-JP が指定されている?)。

という背景もあって、ラズパイでも文字化けせずに実行できる方法で、具体的にはソースコードからビルドする方法で MeCab を導入してみます。

まずは MeCab のダウンロードサイトから MeCab 本体と、MeCab とセットで一般的に使われている IPA 辞書のソースコードをダウンロードし、ラズベリーパイ内のファイルシステムに保存します:
2019012301


保存した2つのファイル(2019/01/23 時点では mecab-0.996.tar.gz と mecab-ipadic-2.7.0-20070801.tar.gz)を展開しておきます:
$ tar -xvf mecab-0.996.tar.gz

$ tar -xvf mecab-ipadic-2.7.0-20070801.tar.gz

まずは MeCab 本体をビルドしてインストールします。展開したフォルダで --with-charset=utf8 オプションを付けて configure し、その後でビルド&インストールします:
$ cd mecab-0.996

$ ./configure --with-charset=utf8

$ make

$ make check

$ sudo make install

$ cd ..

次に IPA 辞書をビルド&インストールします。こちらではビルド前に各種ファイルの文字コードを無理やり UTF-8 に変換し、かつ dicrc 内の config-charset 指定を UTF-8 にします。その後にソースコードをビルド&インストールします:
$ sudo apt-get install nkf

$ cd mecab-ipadic-2.7.0-20070801

$ nkf -w --overwrite *.csv

$ nkf -w --overwrite *.def

$ vi dicrc

config-charset = EUC-JPUTF-8   config-charset の値を UTF-8 に変更して保存

$ ./configure

$ make

$ sudo make install

$ cd ..

この方法で作成した MeCab と IPA 辞書はラズパイでも文字化けすることなく動作させることができます:
$ mecab -d /usr/local/lib/mecab/dic/ipadic
おはようございます
おはよう        感動詞,*,*,*,*,*,おはよう,オハヨウ,オハヨー
ござい  助動詞,*,*,*,五段・ラ行特殊,連用形,ござる,ゴザイ,ゴザイ
ます    助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
EOS




きっかけはこのツイートでも紹介した、豊島屋の鳩サブレ缶がちょうどラズベリーパイを4つ格納できるような仕切りになっていることに気付いたことでした:
20190117


面白そうなので、本当にラズパイのケースにしてみよう、それもせっかくなのでこの鳩サブレ缶の中だけでクラスタリング環境を作ることに挑戦してみよう、と思いたちました。ちなみに私自身はクラスタ化とか専門ではなく、あまり得意な方ではないです。思いついた時点では構築方法として Docker Swarm か、Kubernetes か、まあその辺りが動けばいいな、くらいに考えていました。。

当初は「さてとりあえずラズパイを4台買って・・」と思っていましたが、冷静に考えるとスイッチングハブとか、USBハブとか、電源周りとか、ラズパイ本体以外でもそこそこのサイズの機器を収納する必要がありそうだと気づきました。というわけで、それらをどこか1つにまとめるとして、ラズパイ本体は3台体制で行けるかな・・・ という想定でお買い物しました:
IMG_3782


購入したモノリスト:
買ったモノ個数目的
Raspberry Pi 3 Model B3クラスタノードになるホスト
マイクロ USB ケーブル上記ラズパイの電源ケーブル
マイクロSDカード(64GB)上記ラズパイのストレージ
ラズパイケースプラスチックの仕切りの上にラズパイ本体を直接載せるのは熱的にまずいかと思ったので・・・
LANケーブル3台のラズパイを同一ネットワークに接続(結局、今回は使わず※)
スイッチングハブ1LANケーブルのハブ(結局、今回は使わず※)
USB ハブ電源ケーブルのハブ(結局、今回は使わず※)


※今回は結局無線 LAN で接続することにしたので有線の LAN ケーブルとハブを使わずに構築しました。また USB ハブは購入したのですが、この USB ハブ1つに3台のラズパイを接続すると電流量が足りませんでした。というわけで別途 USB からの電源変換プラグ3つと、テーブルタップ1つを買い足しています。

上記に含まれていないものとして、マイクロ SD カードにイメージを書き込むための Windows PC と、マイクロ SD カードを読み書きするための USB アダプタ、USB -> 電源プラグの変換アダプタ、各ホストでネットワークが有効になるまでの操作用に LCD モニタ、HDMI ケーブル、USB キーボードと USB マウスを使います(これらは所有していたものをそのまま使います)。加えてケースとなる 18 枚入りの鳩サブレー缶を用意しました。

また構築する環境は最近流行り(遅い?)の Kubernetes 、にしたかったのですが、訳あって Docker Swarm にしました。コンテナ・オーケストレーションとしてはほぼデファクトスタンダートになった Kubernetes を選びたかったのですが、とりあえず 2019/01/21 時点ではマスターノードを初期化する kubeadm init コマンドを実行した際に再現率 100% で Timeout エラーになってしまうようでした。


どうもこの Issue に近い現象だと思っています:
2019012101


ただ Issue そのものは Closed になっていて、でもスレッドを見ていると本当に治っているのかなんとも微妙・・ 一方で成功例も報告されているのでラズパイで発生する環境依存問題なのか、タイミングが悪かったのか・・・ なんとも言えないのですが、仮に Kubernetes の障害であったとしてもその修正を待つのも変なので、Docker Swarm によるクラスタリング環境構築を優先することに決めました。

というわけで、改めて3台のラズパイを使った Docker Swarm 環境の構築を目標に作業を進めてみます:
2019012200



【構成図】
このような最終型を目指すことにします:
2018012201

raspi001, raspi002, raspi003 の3台のラズベリーパイを Docker Swarm でクラスタリングします。raspi001 を管理ノード、raspi002 と raspi003 をワーカーノードとします。



【ラズパイノードの準備】
Docker Swarm 環境の核となる3台のノードをラズパイで作ります。前提として最新版の Raspbian OS をマイクロ SD カードに書き込んで起動し、初回起動時のセットアップは3台ぶん済んでいるものとします。また SSH も有効にしておいてください。そして以下の手順を3台それぞれに対して行います。

【ホスト名の変更】
今回は3台のラズパイに raspi001, raspi002, raspi003 という3つの名前をそれぞれ付与して使いますこのため、まずは各ラズパイのホスト名をそれぞれ変更します。
$ sudo vi /etc/hostname

raspberrypiraspi001  raspberrypi をホスト名に変更して保存


また raspi001, raspi002, raspi003 の名前でアクセスできるよう、/etc/hosts も変更しておきます(DNS などが有効であればそちらで対応いただくのがいいと思います):
$ sudo vi /etc/hosts

127.0.1.1       raspberrypiraspi001  raspberrypi をホスト名に変更

192.168.10.101  raspi001
192.168.10.102  raspi002
192.168.10.103  raspi003   raspi00X の名前でアクセスできるよう IP アドレスを指定して追加し保存

【SSH 鍵の共有】
この3台のラズパイ間ではパスワードなしで SSH 接続ができるように SSH 鍵を共有しておきます:
$ ssh-keygen -t rsa
$ ssh-copy-id raspi001
$ ssh-copy-id raspi002
$ ssh-copy-id raspi003

【Docker のインストール】
こちらで紹介した手順でラズパイに Docker をインストールします:
$ curl -sSL https://get.docker.com | sh

$ sudo usermod -aG docker pi

(このコマンドの後、一度ログアウトして再ログインする)

以上、ここまでの手順は3台のラズパイ全てで共通に行っておく必要があります。ちと面倒ですが、全てのラズパイに Docker をインストールするところまで実行しておきます。


【管理ノードの作成】
ここからは3台のラズパイの役割ごとに作業が変わる部分になります。まずは管理ノードを作成します。raspi001 において、自分のアドレスを指定して以下のコマンドを実行します:
$ docker swarm init --advertise-addr 192.168.10.101

Swarm initialized: current node (xenxp2w34x5dhvtdmq0ndwolk) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-0dg4im1kvb41odjj9zmhwug0bcvg6n8tt0d8548jxho5cp8cvo-df89pmegbdf4a3vy37apftv8r 192.168.10.101:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.


↑コマンドが成功すると青字のような出力になります。この中の太字部分(docker swarm join で始まる行)は後でワーカーノードで実行することになるコマンドなのでコピペできるようにしておきましょう。


【ワーカーノードの接続】
次にワーカーノード側(raspi002, raspi003)から管理ノードに接続します。上記の管理ノード作成時に実行したコマンドの実行結果をそのまま入力して実行します:
$ docker swarm join --token SWMTKN-1-0dg4im1kvb41odjj9zmhwug0bcvg6n8tt0d8548jxho5cp8cvo-df89pmegbdf4a3vy37apftv8r 192.168.1.153:2377

コマンドの実行が成功すると "This node joined a swarm as a worker." といったメッセージが表示されます。これを raspi002 と raspi003 の両方で(4台以上で構成する場合は全てのワーカーノードで)実行します。


【ノードの状態を確認】
ここまでの作業でこの環境が作れています:

2018012201


ノードの状態を確認してみます。raspi001 から以下のコマンドを実行します:
2019012202

$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
xenxp2w34x5dhvtdmq0ndwolk *   raspi001            Ready               Active              Leader              18.09.0
hztpov7qya7y99m4oifx73ugt     raspi002            Ready               Active                                  18.09.0
wksx0mlyu9wsilk9c4jigvcib     raspi003            Ready               Active                                  18.09.0

実行結果↑の青字部分をみると raspi001, raspi002, raspi003 がリストされ、全て Active になっています。また raspi001 の MANAGER STATUS が Leader とマークされており、ここが管理ノードになっていることが確認できました。


あとはこの3つのラズパイと電源ケーブル等をつなげて鳩サブレー缶に押し込みます:
IMG_3802


鳩サブレ版の(?) docker swarm 環境が完成しました!
IMG_3800



(参考)
https://blog.ruanbekker.com/blog/2018/10/23/setting-up-a-docker-swarm-cluster-on-3-raspberrypi-nodes/


ラズベリーパイ(Raspbian OS)に NoSQL 型のデータベースである Apache CouchDB を導入する手順を紹介します:
2019011402


Apache CouchDB (以下、"CouchDB")はオープンソースで提供されている NoSQL データベースです。IBM Cloud の IBM Cloudant はこの CouchDB をベースに提供されているマネージド DBaaS です:
2019011401


なお、IBM Cloudant は分散データベース環境がはじめから提供されていますが、以下で紹介する例では CouchDB を1インスタンスで運用する前提での導入方法とさせていただきます。また導入する CouchDB のバージョンは 2019/01/14 時点での最新版である 2.3.0 を対象としています。

まずは準備作業としてリポジトリをアップデートしておきます:
$ sudo apt-get update -y

$ sudo apt-get dist-upgrade -y

続いて Erlang Solutions のリポジトリを追加し、再度アップデートします:
$ wget http://packages.erlang-solutions.com/debian/erlang_solutions.asc

$ sudo apt-key add erlang_solutions.asc

$ sudo apt-get update

追加したリポジトリを使って、ビルドに必要なライブラリ等を導入します:
$ sudo apt-get --no-install-recommends -y install build-essential pkg-config erlang libicu-dev libmozjs185-dev libcurl4-openssl-dev

またビルドしたバイナリを実行するユーザー(couchdb)と、そのホームディレクトリ(/home/couchdb/)をこの段階で作成しておきます:
$ sudo useradd -d /home/couchdb couchdb

$ sudo mkdir /home/couchdb

$ sudo chown couchdb:couchdb /home/couchdb

ではいよいよ CouchDB のビルドを行います。2.3.0 のソースコードをダウンロード&展開して、ビルドします:
$ cd

$ wget http://mirror.ibcp.fr/pub/apache/couchdb/source/2.3.0/apache-couchdb-2.3.0.tar.gz

$ tar -zxvf apache-couchdb-2.3.0.tar.gz

$ cd apache-couchdb-2.3.0/

$ ./configure

$ make release

ビルドが成功すると、完成したバイナリが ./rel/couchdb/ 以下に作成されています。このフォルダ以下を /home/couchdb/ 以下にコピーし、couchdb ユーザー向けに実行権限を変更します:
$ cd ./rel/couchdb/

$ sudo cp -Rp * /home/couchdb

$ sudo chown -R couchdb:couchdb /home/couchdb

これでビルドは完了です。不要であればソースコードやリポジトリのファイルは削除しても構いません(残しておいても構いません):
$ cd

$ rm -R apache-couchdb-2.3.0/

$ rm apache-couchdb-2.3.0.tar.gz

$ rm erlang_solutoins.asc

この段階で CouchDB を起動することは可能ですが、デフォルト設定のままだと CouchDB はローカルホストからのリクエストのみ受け付ける設定になっています。CouchDB を外部ホストから利用する場合や、管理者向けコンソールに外部ホストからアクセスする場合は外部アクセスを許可するよう、起動前に設定を変更しておく必要があります。

外部ホストからのアクセスを許可するには、/home/couchdb/etc/local.ini ファイルをテキストエディタで開き、
#bind_address = 127.0.0.1

となっている箇所を、以下のように書き換えて保存します:
bind_address = 0.0.0.0

そして couchdb ユーザーの権限で CouchDB を起動します:
$ sudo -i -u couchdb /home/couchdb/bin/couchdb

起動後、別のターミナルから以下の curl コマンドを実行して動作を確認します:
$ curl http://localhost:5984/

{"couchdb":"Welcome","version":"2.3.0","git_sha":"07ea0c7","uuid":"48b039b37b2b29236f33806d9a96c248","features":["pluggable-storage-engines","scheduler"],"vendor":{"name":"The Apache Software Foundation"}}


私自身はラズパイ3とラズパイゼロで動作を確認しましたが、ラズパイゼロでも CouchDB 程度であれば大した負荷にはならずに実行できました。




(参考)
https://www.hackster.io/mehealth-ch/installing-couchdb-on-raspbian-stretch-ccb2a7



ラズベリーパイをデスクトップ用途で使う場合のテキストエディタとしては現時点でこれが最適かなあ、と思うのが Visual Studio Code です。ラズベリーパイ環境にもインストールできるようになっていました。


導入にあたり、まずは GPG Key をインストールしておく必要があります:
$ wget -qO - https://packagecloud.io/headmelted/codebuilds/gpgkey | sudo apt-key add -

その後、root で Visual Studio Code の Community Build をインストールします:
$ sudo su
# . <( wget -O - https://code.headmelted.com/installers/apt.sh )
# exit

導入後はメニューから code-oss を選択するか、コマンドラインから以下を実行して起動します:
$ code-oss

2019-01-13-093932_1184x624_scrot
 

普段が vi 使いなので比較の対象としてアレですが、複数ファイルを開いて切り替える使いやすさとか、補完機能とか、いわゆる「モダンな」機能が満載で、それでいてそんなに重いわけでもなく、いい感じ。


このページのトップヘ