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

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

ラズベリーパイネタシリーズです。

今回はオープンソースのブロックチェーン基盤である Hyperledger Fabric を一通り Raspbian OS に導入して実行する手順を紹介します。まあラズパイの 1GB 物理メモリでどこまで実用的に動くか、というのはあまり期待できないし、また現時点では Hyperledger Fabric はともかく、Hyperledger Composer を使った動作は 32bit OS である Raspbian OS ではどうやら難しいのかもしれない・・・と感じていることを最初に申し上げておきます。 なお以下で紹介する手順はこの環境で確認しています:

モデル: Raspberry Pi 3B+
OS: Raspbian 2018-11-13 (Stretch Full) ※最新版はこちら
SD カード: 128GB

※ページ最下の【参考】でも参照しているリンク先では Docker Swarm 環境で3台のラズパイを使った Hyperledger Fabric 環境構築を紹介しています。実用面ではこちらのほうが現実的かもしれません。



【導入手順】
基本方針として、このブログエントリ最下段の【参考】で記した2つのページの情報をあわせた方法で導入しています。

おおまかには以下の順序で Hyperledger Fabric 環境を構築します:
0. 事前準備
1. Docker 導入
2. Docker Compose 導入
3. Docker Image ダウンロード
4. 起動


今回は1台のラズパイの中に Docker 環境を構築し、その Docker の中で各種 Hyperledger Fabric のイメージを1インスタンスずつ動かして環境構築します。そのため上記のような順序でインストールする必要があります。


【0. 事前準備】
今回 Hyperledger Fabric を Docker 上で動かします。そのためラズパイに Docker 等を導入することになるのですが、そのための前提ライブラリ等を用意しておきます。ラズパイのターミナル等を開いて、以下のコマンドを順次実行します:
リポジトリ更新
$ sudo apt-get update && sudo apt-get upgrade -y

依存ライブラリを導入
$ sudo apt-get install git curl gcc libc6-dev libltdl3-dev python-setuptools -y

python pip インストーラーを更新
$ sudo -H pip install pip --upgrade

ここまでの操作が完了すると、ラズパイ用の Docker がインストールできるようになります。


【1. Docker 導入】

上記に続いて以下のコマンドを実行します:
Docker 導入
$ curl -sSL get.docker.com | sh

Docker の実行権限設定
$ sudo usermod -aG docker pi

ここまで完了したら一度ログアウトし、再度ログインします(最後の実行権限設定が有効になります)。ここまで正しく実行できていると、sudo なしで docker コマンドを実行することができるようになっているはずです:
Docker バージョン確認
$ docker -v
↑ Docker のバージョンが表示されれば、ここまでの手順は完了です。


【2. Docker Compose 導入】

引き続き Docker Compose を導入します。こちらは pip を使って導入し、導入後はすぐにコマンドを実行することが可能です:
Docker Compose 導入
$ sudo pip install docker-compose

Docker Compose バージョン確認
$ docker-compose -v
↑ Docker Compose のバージョンが表示されれば、ここまでの手順は完了です。


【3. Docker イメージダウンロード】

こちらのサイトで提供されている、ラズパイ用にビルド済みの Hyperledger Fabric (v1.0.7) の Docker イメージ群を docker pull コマンドでダウンロードします:
$ docker pull jmotacek/fabric-baseos:armv7l-0.3.2

$ docker pull jmotacek/fabric-basejvm:armv7l-0.3.2

$ docker pull jmotacek/fabric-baseimage:armv7l-0.3.2

$ docker pull jmotacek/fabric-ccenv:armv7l-1.0.7

$ docker pull jmotacek/fabric-javaenv:armv7l-1.0.7

$ docker pull jmotacek/fabric-peer:armv7l-1.0.7

$ docker pull jmotacek/fabric-orderer:armv7l-1.0.7

$ docker pull jmotacek/fabric-buildenv:armv7l-1.0.7

$ docker pull jmotacek/fabric-testenv:armv7l-1.0.7

$ docker pull jmotacek/fabric-zookeeper:armv7l-1.0.7

$ docker pull jmotacek/fabric-kafka:armv7l-1.0.7

$ docker pull jmotacek/fabric-couchdb:armv7l-1.0.7

$ docker pull jmotacek/fabric-tools:armv7l-1.0.7

自分でビルドする方法もあるようなのですが、あまりに面倒そうなので出来合いのものを使わせていただきました。 jmotacek 様、ありがとうございます。


これで Hyperledger Fabric 環境を動かすために必要な準備が完了しました。


【4. 起動】
Hyperledger Fabric の準備が整ったので起動します。ラズパイ1台で(物理メモリ 1GB で)この環境を起動するのは、できるか/できないかで言えばできそうですが、実用には厳しいかもしれません。環境に応じてスワップメモリを増やしておきましょう。方法はこちらを参照ください(私自身はスワップを 2GB に設定して以下を実行しました)。

Hyperledger Fabric の起動スクリプトの元となるキット(通称「サポートツール」)をダウンロード&展開します。以下の例ではホームディレクトリ以下に fabric/ というフォルダを作り、その中に展開しています:
$ mkdir ~/fabric

$ cd ~/fabric

$ curl -O https://raw.githubusercontent.com/hyperledger/composer-tools/master/packages/fabric-dev-servers/fabric-dev-servers.zip

$ unzip fabric-dev-servers.zip

この中の docker-compose.yml ファイルを上記で用意したラズパイ向け Docker イメージ用に書き換えます。具体的には ~/fabric/fabric-scripts/hlfv12/composer/docker-compose.yml を以下のように編集しました(変更部分をにしています):
version: '2'

services:
#  ca.org1.example.com:
#    image: jmotacek/fabric-ca:armv7l-1.0.7
#    environment:
#      - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
#      - FABRIC_CA_SERVER_CA_NAME=ca.org1.example.com
#
#    ports:
#      - "7054:7054"
#    command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/19ab65abbb04807dad12e4c0a9aaa6649e70868e3abd0217a322d89e47e1a6ae_sk -b admin:adminpw -d'
#    volumes:
#      - ./crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config
#    container_name: ca.org1.example.com
#
  orderer.example.com:
    container_name: orderer.example.com
    image: jmotacek/fabric-orderer:armv7l-1.0.7
    environment:
      - ORDERER_GENERAL_LOGLEVEL=debug
      - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
      - ORDERER_GENERAL_GENESISMETHOD=file
      - ORDERER_GENERAL_GENESISFILE=/etc/hyperledger/configtx/composer-genesis.block
      - ORDERER_GENERAL_LOCALMSPID=OrdererMSP
      - ORDERER_GENERAL_LOCALMSPDIR=/etc/hyperledger/msp/orderer/msp
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric
    command: orderer
    ports:
      - 7050:7050
    volumes:
        - ./:/etc/hyperledger/configtx
        - ./crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/etc/hyperledger/msp/orderer/msp

  peer0.org1.example.com:
    container_name: peer0.org1.example.com
    image: jmotacek/fabric-peer:armv7l-1.0.7
    environment:
      - CORE_LOGGING_LEVEL=debug
      - CORE_CHAINCODE_LOGGING_LEVEL=DEBUG
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_PEER_ID=peer0.org1.example.com
      - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=composer_default
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/msp
      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric
    command: peer node start
    ports:
      - 7051:7051
      - 7053:7053
    volumes:
        - /var/run/:/host/var/run/
        - ./:/etc/hyperledger/configtx
        - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/peer/msp
        - ./crypto-config/peerOrganizations/org1.example.com/users:/etc/hyperledger/msp/users
    depends_on:
      - orderer.example.com
      - couchdb

  couchdb:
    container_name: couchdb
    image: jmotacek/fabric-couchdb:armv7l-1.0.7
    ports:
      - 5984:5984
    environment:
      DB_URL: http://localhost:5984/member_db

そして起動コマンドを実行します:
$ cd ~/fabric

$ ./startFabric.sh

↓こんな感じで Docker 内でイメージがコンテナ化され、実行されていきます:
2019011003


少し時間がかかりますが(1分くらい?)コマンドが完了すると、こんな画面になってプロンプトが戻ります:
2019011004


以下のコマンドで起動中のコンテナの状態を確認し、Hyperledger Fabric の各種コンテナが実行されていることを確認します:
$ docker ps

↓docker-compose.yml で指定されたイメージが起動していることが確認できます。Hyperledger Fabric の起動に成功しました!:
2019011002


ちなみに、この「Hyperledger Fabric が起動しただけ」の段階で使用メモリを確認してみました。起動しただけであれば意外と余裕あるようにも見えますね・・・
2019011006



【(途中まで)使ってみる】
Hyperledger Fabric の導入と起動までであれば上記までで完了していますが、せっかくなのでこの環境を使ってみることにします(といっても、以下で紹介しているのはカードファイルのインポートまでですが・・)。

具体的には「サポートツールで提供されているスクリプトを使って管理者用のカードファイルを作成する」ところまでを紹介します。といってもここから先はラズパイ特有の部分はなく、通常の方法と一緒というか、通常と同じ方法でできる所までを紹介する、というスタンスです。

そのために composer コマンドと呼ばれる、Hyperledger Composer のコマンドラインツールを導入するのですが、その前提として Node.js v8.x 環境(node と npm)が必要になります。ここがちとややこしいのですが、今回の導入に使った Raspbian OS 2018-11-13 (Stretch Full) でははじめから V8 の node コマンドは使えるようになっていますが、npm が導入されていません。というわけで今後のことも考えて node のバージョン管理ツール(n package)と合わせて Node.js v8.x を導入しておくことにします:
一旦 npm を導入
$ sudo apt-get install npm

キャッシュを更新
$ sudo npm cache clean

n package をインストール
$ sudo npm install n -g

n package で導入できる Node.js のバージョン(8.xx.xx の最新バージョン)を確認
$ sudo n list

(8.xx.xx の中では 8.15.0 が最新であったと仮定)
Node.js V8.15.0 を指定してインストール $ sudo n 8.15.0

一度ログアウト&ログインし直して、改めて node コマンドと npm コマンドのバージョンを確認します:
$ node -v
v8.15.0

$ npm -v
6.4.1
↑ Node.js V8.x と対応する npm が導入できたことを確認


Node.js 環境が整ったので、改めて composer コマンドをインストールします。今回用意した Hyperledger Fabric のバージョンが v1.0.7 のイメージなので、このバージョンに合う composer-cli v0.16 を指定してインストールします(※):
$ sudo npm install --unsafe-perm -g composer-cli@0.16

※ラズパイ環境だからかもしれませんが、上記の --unsafe-perm オプションを付けないと実行結果がエラーになってしまうようでした。こちらを参照。


そしてサポートツール内の createPeerAdminCard.sh を実行して、PeerAdmin@hlfv1 のカードを作成します:
$ cd ~/fabric/fabric-scripts/hlfv1

$ ./createPeerAdminCard.sh

composer のコマンドで、PeerAdmin@hlfv1 カードが作成されていることを確認します:
$ composer card list
2019011101


とりあえず動作確認できたのはここまでです。2019/01/11 時点でこの先に進もうとして BNA ファイルを用意して composer runtime install し(ここまでは成功)、composer network start させようとすると、以下のようなエラーになりました:
Error: Error trying to instantiate composer runtime. Error: No valid responses from any peers.
Response from attempted peer comms was an error: Error: Error starting container: API error (400): {"message":"Minimum memory limit allowed is 4MB"}
2019011102


このエラーの原因がまだわかっていないのですが、調べた範囲ではもしかすると 32bit OS である Raspbian OS に原因があるような気もしていて、そうだとすると現時点で Hyperledger Composer のこの先を動かすのは厳しいのかなあ・・・ とも思っています。

この辺りは引き続き調査もしますが、情報求む(苦笑)。


【Hyperledger Fabric を終了する】
起動した Hyperledger Fabric を終了するには startFabric.sh と同じフォルダにある stopFabric.sh を実行します:
$ ./stopFabric.sh

↓終了できました:
2019011005



実メモリ 1GB の制約はどうにもならないので実用的な使い方は難しいかもしれませんが、とりあえず1台のラズパイで Hyperledger Fabric が起動できることは確認できました。CouchDB などを使わずに、既存のビジネスネットワークに Peer だけ動かして接続するような使い方であればもう少し余裕を持って使えるかもしれません。


秋葉原の最安値で済ませることができれば、
 本体 5000 円 + ケース 1000 円 + Micro SDカード 2000 円
8000 円程度で Hyperledger Fabric のブロックチェーン環境が一台確保できる、ということになりますね。安っ!


【参考】
https://stackoverflow.com/questions/45800167/hyperledger-fabric-on-raspberry-pi-3
https://www.joemotacek.com/hyperledger-fabric-v1-0-on-a-raspberry-pi-docker-swarm-part-2/

久しぶりのラズベリーパイネタです。

これまであまり意識することなかったんですが、ラズパイ(Raspbian) をデフォルトのまま使っている時のスワップサイズって 100MB しかないんですね。。
2019011001


ラズパイのメインメモリは 1GB 固定です。サーバー用途メインで、あまり重い作業をしなければこれで足りるのかもしれませんが、デスクトップ用途で使ってブラウザでタブをたくさん開いて・・・という使い方をしていると、結構な確率でメモリ不足になると思います。 というわけで、スワップファイル容量を変更する手順を調べたので以下に紹介します。

Raspbian の場合、スワップファイル容量は /etc/dphys-swapfile というテキストファイルで管理されています。スワップファイル容量を変更するにはこのファイルをテキストエディタで開いて、CONF_SWAPSIZE という変数の値を(メガバイト単位で)指定します。例えば以下の例では 2GB に指定しています:
CONF_SWAPFILE=2048

ただし、2GB 以上の値を指定する場合は同ファイル内にある CONF_MAXSWAP の値も変更する必要があります(32 bit カーネルを考慮しているせいか、この値を変更せずに CONF_SWAPFILE の値だけを 2048 より大きな値に変更してもスワップファイルサイズは 2048 に設定されてしまうようです)。例えば 4GB に設定する場合は以下のようにします:
CONF_SWAPFILE=4096
CONF_MAXSWAP=4096

設定変更後に以下のコマンドで dphys-swapfile を再起動すると、スワップファイルのサイズが変更されます:
$ sudo systemctl stop dphys-swapfile
$ sudo systemctl start dphys-swapfile

2019011002


当たり前ですがスワップファイルはマイクロ SD カード内に作られるため、マイクロ SD カードの容量とも相談して設定する必要があります。またあまり頻繁にスワップが発生するような使い方だと、ただでさえストレージとしては比較的寿命の短いマイクロ SD カードの劣化を意識する必要が出てくるかもしれません。

その場合はラズパイに USB メモリを挿してマウントし、上記の /etc/dphys-swapfile ファイル内の CONF_SWAPFILE でスワップファイルを USB メモリ内に作成するようにしてマイクロ SD カードから退避させる、という方法もあるようです(未確認)。


2019 年最初のブログ投稿に、普段感じる事が多いけどあまり触れていなかった点について書いてみようと思います。ちょっとだけマジメな話です。


拙作「マンホールマップ」は 2010 年からサービスの開発を始めて、ほぼ同時期からサービスを開始しています。色んな人のアイデアを参考にさせていただくことはありますが、基本的には私一人で開発を行い、管理を含めた運営を行っています。もう8年以上続けていることになります。今は当時と比べてもクラウドをはじめとする時代背景が大きく変化し、個人でウェブサービスを開発・管理・運営する環境が整っていると感じていますが、そういった業務で開発・運営するのは異なる部分について、一度まとめておこうと思いました。


【背景】
まずはいい意味での違いを。ここ数年のクラウド環境の充実、そして低価格化によって、個人がウェブサービスを運営しやすくなったと感じています。

後述もしますが、ウェブサービスを「作る」ことに関しては開発環境さえ整えればいい話ですが、それを公開して運営するにはドメインの取得に加え、インターネット上に公開された24時間稼働が可能なサーバー機を用意する必要があります。企業で運営する場合、専用サーバーや専用回線を調達する方法もありましたが、個人には(主にコスト面で)敷居の高いものでした。また以前から「ホスティングサービス」と呼ばれるサービスでインターネット上のサーバーを借りることはできましたが、技術的な制約も大きく、開発上のハードルが上がってしまうものでした。

この点において、世の中でクラウドが広まり、特に PaaS 環境が広まってきたことで、サーバー環境の準備や構築だけでなく、(標準で用意されているものを使うことで)ドメインや証明書の取得まで不要になる時代になったことを実感します。こうなると個人でもサービス/アプリケーションを開発できれば、その運用を開始するまでのハードルはぐんと低くなっていると感じます。


以上のように個人がウェブサービスの運営を開始するまでのハードルは低くなりましたが、一方で実際に運営する段になると業務で行う場合とは異なる点を意識する必要があることも実感するようになりました。そんな背景における違いを、実際に運営する中で気付いた範囲で言及してみようと思います。



【個人で開発・運営するのは業務で行う場合と何が違うのか?】
一言でいえば個人運営だと「全部自分でやる」点が違います。何を作るのか、どこまで作るのか、いつまでに作るのか、どんな画面にするのか、どんな実装で実現するのか、プログラミング言語は、データベースは、OS は、どこで動かすのか、ドメイン名/ホスト名は、コストはいくらまで出せるのか、問い合わせ対応は、フィードバック対応は、・・・ 決めるのも実行するのも自分一人です。

一方、業務で行う場合、もちろんその企業の規模とかにもよると思いますが、多くのケースで分業制が考えられます。開発部分ひとつ取っても、デザインと実装は担当分野が分かれるケースが多いですし、インフラの構築とアプリの開発は別チームというケースも少なくありません。が、個人だと分ける相手がいません。「UIデザインは苦手」とか言ってられないのです。

また開発後の運用やサポートも自分で行います。業務だと電話サポート窓口があったりしますが、普段は本業を持つ個人開発者がサポート業務に従事することはできません。サーバーが止まっていても気づける人がいない※のです。 となると「なるべくサポートが不要になるような設計」をはじめから意識して作る必要があります。マンホールマップの例だと不適切な画像を投稿する人がいたらどうするか?という問題がありました。ここは Twitter アカウントとの連携で不適切な画像を投稿しにくくする、という形にしました。要は投稿時には Twitter アカウントによるログインが必要で、不適切な画像を投稿すると Twitter 側にもバレる、というリスクを利用者に課したのです。そうすることで、そういった愉快犯的に不適切画像を投稿する人を少しでも減らそうという試みでした。幸いにしてサービス開始から悪質な投稿をする人はほとんど表れていません。ある程度の効果はあったのかもしれませんが、こういったサービス設計段階における考慮も必要になるのでした。

※ちなみに上述の「サーバーが止まっている場合も気づける人がいない」問題は Google Search Console のサーバーエラーをメールで通知する機能で解決できます。自分で解決する必要はないのですが、こういった世の中のツールを知っていたり、調べたりする能力も必要になってきます。


【ドメインの問題】
自分でサービスを作るだけならずっと以前から(自分の手元のPCに開発環境を用意すれば)できたことです。以前はいざ公開・運営するとなった場合に「どこで」公開するか、という問題がありました。何というホスト名(ドメイン名)で公開するか、という問題です。 試験的・限定的に公開するだけなら IP アドレスでも(特殊なポート番号でも)いいと思うのですが、公開するとなるとそうも言えません。

加えて SSL 証明書の問題もあります。最近は外部 API と連携する際の条件として https 通信が可能なことが求められることも珍しくなくなりました。ドメインを取得した上で SSL 証明書を取得し、https 通信を有効にすることが必須となることもあります。

もちろんオレオレ証明書でも NG ではないし、最近は SSL 証明書も安く取得できるようになってはいますが、ドメインの取得は無料というわけにはいきません。つまりいくばくかの運用コストが無視できなくなってしまいます(コストについて詳しくは後述します)。またその手続や設定を運用開始までに済ませて置かなければならないのだとすると(上述の「一人でやらなければならない」という条件も考慮して)運用開始までの負担が大きくなってしまうのでした。

ただ、この辺りも昨今のクラウド環境の、特に PaaS と呼ばれるサービスを利用することで、特に存在を意識しなくても使える DNS やドメイン名があったり、はじめから SSL が利用可能になっていたりするものもあります。こういう環境が広まっていくことは個人開発者としても大歓迎です。


【コストの問題】
クラウドはウェブサービスの運用を開始するまでの技術的なハードルを大幅に下げてくれることを上述しました。では難しいところはクラウドにおまかせする形で、クラウドベンダーの環境で公開することに問題はないのでしょうか?

現実問題としては「コスト」が問題となるケースがあると思っています。アプリケーションサーバー1台とデータベースサーバー1台での運用であれば、最悪1台の IaaS の中に同居させてしまう形にして、理論上はこの1台ぶん最低限のサーバーの月額コストだけで運用することができます(月 500 円程度から可能です)。

ただ実際には「最低限のサーバーの月額コスト」ではまかなえないケースが多くなると思っています。その最低限のサーバー1台に搭載されたメモリ量で動くのか? IaaS の中にデータベースを同居させたディスクの容量は足りるのか? 足りたとしてもデータのバックアップをどう考えるか? 上述のドメインに関わるコストも無視できません。  ・・いずれもクラウドサービスにコストをかけることで解決できることが多いのですが、そのコストは経費ではなく個人負担なのです。クラウドのデータベースって、冗長性とかバックアップとか考えなくていいのは確かに便利ですが、(安価な仮想サーバーほど)安くはないですよね。。それを個人で、しかも毎月負担できるのか、、という問題です。とはいえ万が一バックアップがないサーバーが死んでしまったら・・・と考えると、公開する以上は考慮しないといけない問題なわけで、、、


これも私の話で恐縮ですが、自作ウェブサービスのほとんどはクラウドで公開していますが、マンホールマップは 2019 年1月時点で自宅サーバー運用しています。一番に理由はコストで、上述の要素を考慮してクラウドサーバーを用意すると毎月コストが結構な額になってしまい、それなら自宅に安いサーバー(というかPC)を買ってなんとかしたほうが現実的、という判断に至ったのでした。


【で、結局・・・】
まとめると、こんな感じでしょうか:

- 昨今のクラウド環境の充実によって、開発したウェブサービスを公開して運用するのは安価かつ容易になった。
- 非機能要件を無視できる間はそれでもよいが、ある程度データが溜まってくると万が一の際のバックアップなどを無視できなくなる。
- その辺りまで考慮しはじめると「クラウドが安い」と言い切れなくなってくる。がんばって自宅ネットワーク内のサーバーを公開したほうが安上がりになるケースも。
- 自分一人で管理する前提でサービスレベルを考慮/設計する必要がある。
- 個人ウェブサービスは開発/運営するのは(一通り全てをある程度のレベルでこなさないといけない、という意味で)すごくいい勉強になる。



↑実は最後の一文を言いたくてこの長いブログエントリを書きました。業務経験としては個人開発や個人運用は評価しにくいのかもしれませんが、これを一人でこなせることも、一人でもこなせるような設計をしていることも、本当はもっと高く評価されてもいいんじゃないかなあ、、、と思っているのでした。

クラウド環境が広まったことで個人ウェブサービスを運用するハードルは確実に下がっています。この環境を活用して、色々な人がウェブサービス運営に興味を持ってもらえると嬉しいし、それは技術者としての(業務にも関わる)スキルアップに確実につながると思っています。

このページのトップヘ