タイトルがいちいち長いシリーズ
ブロックチェーンネットワークをフルマネージドで構築・運用できるAmazon Managed Blockchain(AMB)ですが、実際にネットワーク構築するにはそこそこの手順と時間がかかります。
検証などで頻繁に構築していると、いい加減に手間になってきたのでAWS CloudFormation(CFn)を用いてさくっとHyperledger Fabricのブロックチェーンネットワークとクライアント(EC2インスタンス)を構築、ついでにブロックチェーンネットワークにサンプル用のチャネルやチェーンコードをデプロイして、スタック作成後すぐに利用できるようしてみました。
せっかくCFnを利用するのでAMBリソースの削除にも対応しています。
CFnでテンプレート作成するのは楽しいですがキリがないので困ります^^
AWS CLIでブロックチェーンネットワークを構築する手順は下記が参考になります。
Amazon Managed BlockchainでHyperledger Fabricのブロックチェーンネットワークを構築してみた – Qiita
https://cloudpack.media/46963
使い方
AWS CLIを用いてスタック作成する手順となります。
前提
- AWSアカウントがある
- AWSアカウントに以下の作成権限がある
- CFnスタック
- インターフェイスVPCエンドポイント
- セキュリティグループ
- AMBネットワーク
- EC2インスタンス
- EC2キーペア
- AWS CLIがインストールされている
aws configure
コマンドでアカウント設定済み
git
コマンドが利用可能pip
コマンドが利用可能
準備
CFnテンプレートのダウンロード
GitHubにCFnのテンプレートをアップしていますのでそれを利用します。
kai-kou/amazon-managed-blockchain-cfn-template
https://github.com/kai-kou/amazon-managed-blockchain-cfn-template
本テンプレートで作成するリソースは以下となります。CFnがAMBのリソース管理に対応していないので(2019/07/02時点)、AWS Lambda-backedカスタムリソースも利用しています。
- AMB(カスタムリソース)
- ネットワーク
- メンバー
- PeerNode
- セキュリティグループ
- AMBネットワーク用
- Hyperledger Fabricクライアント用
- インターフェイスVPCエンドポイント
- EC2インスタンス
> git clone https://github.com/kai-kou/amazon-managed-blockchain-cfn-template.git > cd amazon-managed-blockchain-cfn-template
EC2キーペアの作成
Hyperledger FabricのクライアントとしてEC2インスタンスを作成するためにキーペアを作成します。既存のキーペアを利用するのでもOKです。
> aws ec2 create-key-pair \ --key-name amb-client-ec2-key \ --query "KeyMaterial" \ --output text > amb-client-ec2-key.pem > chmod 400 amb-client-ec2-key.pem
最新のAWS SDK(boto3)をLambda Layerに登録する
AWS Lambda-backedカスタムリソースのLambda関数で利用できるAWS SDKはAMBがサポートされていないバージョンなので(2019/07/02時点)、Lambda Layersを利用して最新のAWS SDK(boto3)が利用できるようにします。詳細は下記をご参考ください。
AWS CloudFormationのAWS Lambda-backedカスタムリソースで最新のAWS SDKを利用する – Qiita
https://cloudpack.media/48058
> mkdir python > pip install -t ./python boto3 (略) Successfully installed boto3-1.9.180 botocore-1.12.180 docutils-0.14 jmespath-0.9.4 python-dateutil-2.8.0 s3transfer-0.2.1 six-1.12.0 urllib3-1.25.3 > zip -r python.zip ./python > aws lambda publish-layer-version \ --layer-name amb-boto3 \ --zip-file fileb://python.zip \ --compatible-runtimes python3.7 { "Content": { "Location": "https://prod-04-2014-layers.s3.amazonaws.com/snapshots/(略)", "CodeSha256": "r6d7CEpYmwrgQIb3642rTsMEquxDjTQCE9MWnk0Qjfw=", "CodeSize": 8608150 }, "LayerArn": "arn:aws:lambda:us-east-1:xxxxxxxxxxxx:layer:amb-boto3", "LayerVersionArn": "arn:aws:lambda:us-east-1:xxxxxxxxxxxx:layer:amb-boto3:1", "Description": "", "CreatedDate": "2019-07-01T04:49:38.540+0000", "Version": 1, "CompatibleRuntimes": [ "python3.7" ] }
各パラメータ値を取得する
ブロックチェーンネットワークを構築するのに必要となるパラメータを取得します。
VPCとサブネット
インターフェイスVPCエンドポイントやセキュリティグループ作成を行う先のVPCは既存のものを利用する前提です。新規作成する場合はCFnテンプレートにリソース定義を追加するか手動で作成しておく必要があります。
> aws ec2 describe-vpcs \ --query "Vpcs" [ { "CidrBlock": "172.31.0.0/16", "DhcpOptionsId": "dopt-b06bd8c8", "State": "available", "VpcId": "vpc-xxxxxxxx", "OwnerId": "xxxxxxxxxxxx", "InstanceTenancy": "default", "CidrBlockAssociationSet": [ { "AssociationId": "vpc-cidr-assoc-2b23e646", "CidrBlock": "172.31.0.0/16", "CidrBlockState": { "State": "associated" } } ], "IsDefault": true }, (略) ]
サブネットもインターフェイスVPCエンドポイントを作成するのに必要となります。
こちらも既存のものを利用する前提です。
> aws ec2 describe-subnets \ --query "Subnets" [ { "AvailabilityZone": "us-east-1a", "AvailabilityZoneId": "use1-az2", "AvailableIpAddressCount": 4088, "CidrBlock": "172.31.80.0/20", "DefaultForAz": true, "MapPublicIpOnLaunch": true, "State": "available", "SubnetId": "subnet-xxxxxxxx", "VpcId": "vpc-xxxxxxxx", "OwnerId": "xxxxxxxxxxxx", "AssignIpv6AddressOnCreation": false, "Ipv6CidrBlockAssociationSet": [], "SubnetArn": "arn:aws:ec2:us-east-1:xxxxxxxxxxxx:subnet/subnet-xxxxxxxx" }, ]
自身のグローバルIP
Hyperledger FabricのクライアントとなるEC2インスタンスへSSHでアクセスできるようにセキュリティグループを作成しています。そちらのCidrIp
を指定するのに自身のグローバルIPを取得します。
> curl ifconfig.io xxx.xxx.xxx.xxx
スタック作成
準備ができたらCFnでスタックを作成します。
AWS CLIのaws cloudformation create-stack
コマンドで作成していますが、AWSマネジメントコンソールを利用してもOKです。スタック作成に必要となるパラメータは最低限を指定しています。詳細はGitHubから取得したCFnテンプレートをご参考ください。
リージョンはAMBがバージニア北部のみに対応しているので、us-east-1
を指定します。
> aws cloudformation create-stack \ --stack-name amb-cfn-test \ --template-body file://hyperledger-fabric-network.yaml \ --capabilities CAPABILITY_IAM \ --region us-east-1 \ --parameters '[ { "ParameterKey": "VpcId", "ParameterValue": "vpc-xxxxxxxx" }, { "ParameterKey": "SubnetId", "ParameterValue": "subnet-xxxxxxxx" }, { "ParameterKey": "NetworkName", "ParameterValue": "FabricNetwork" }, { "ParameterKey": "NetworkDescription", "ParameterValue": "Hyperledger Fabric Network" }, { "ParameterKey": "AdminUsername", "ParameterValue": "AdminUser" }, { "ParameterKey": "AdminPassword", "ParameterValue": "Password123" }, { "ParameterKey": "OrgName", "ParameterValue": "org1" }, { "ParameterKey": "Boto3LambdaLayerArn", "ParameterValue": "arn:aws:lambda:us-east-1:xxxxxxxxxxxx:layer:amb-boto3:1" }, { "ParameterKey": "EC2KeyPairName", "ParameterValue": "amb-client-ec2-key" }, { "ParameterKey": "ClientSSHCidrIp", "ParameterValue": "xxx.xxx.xxx.xxx/32" } ]' { "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/amb-cfn-test/a1b77a10-9bdb-11e9-9649-0e8cdcc47538" }
スタック作成完了までに30分くらいかかります。
作成完了したらaws cloudformation describe-stacks
でスタック情報を取得して確認します。
> aws cloudformation describe-stacks \ --stack-name amb-cfn-test { "Stacks": [ { "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/amb-cfn-test/a1b77a10-9bdb-11e9-9649-0e8cdcc47538", "StackName": "amb-cfn-test", "Parameters": [ { "ParameterKey": "NetworkName", "ParameterValue": "FabricNetwork" }, { "ParameterKey": "InstanceProfileName", "ParameterValue": "" }, { "ParameterKey": "ClientSSHCidrIp", "ParameterValue": "xxx.xxx.xxx.xxx/32" }, { "ParameterKey": "Boto3LambdaLayerArn", "ParameterValue": "arn:aws:lambda:us-east-1:xxxxxxxxxxxx:layer:amb-boto3:1" }, { "ParameterKey": "OrgName", "ParameterValue": "org1" }, { "ParameterKey": "SubnetId", "ParameterValue": "subnet-xxxxxxxx" }, { "ParameterKey": "AdminUsername", "ParameterValue": "AdminUser" }, { "ParameterKey": "VpcId", "ParameterValue": "vpc-xxxxxxxx" }, { "ParameterKey": "EC2KeyPairName", "ParameterValue": "amb-client-ec2-key" }, { "ParameterKey": "AdminPassword", "ParameterValue": "Password123" }, { "ParameterKey": "NetworkDescription", "ParameterValue": "Hyperledger Fabric Network" } ], "CreationTime": "2019-07-01T08:38:42.505Z", "RollbackConfiguration": {}, "StackStatus": "CREATE_COMPLETE", "DisableRollback": false, "NotificationARNs": [], "Capabilities": [ "CAPABILITY_IAM" ], "Outputs": [ { "OutputKey": "MemberId", "OutputValue": "m-XXXXXXXXXXXXXXXXXXXXXXXXXX" }, { "OutputKey": "ClientPublicIp", "OutputValue": "xxx.xxx.xxx.xxx" }, { "OutputKey": "ClientInstanceId", "OutputValue": "i-xxxxxxxxxxxxxxxxx" }, { "OutputKey": "PeerNodeId", "OutputValue": "nd-XXXXXXXXXXXXXXXXXXXXXXXXXX" }, { "OutputKey": "NetworkId", "OutputValue": "n-XXXXXXXXXXXXXXXXXXXXXXXXXX" } ], "Tags": [], "EnableTerminationProtection": false, "DriftInformation": { "StackDriftStatus": "NOT_CHECKED" } } ] }
動作確認
CFnでリソース作成できたらEC2インスタンスにログインしてブロックチェーンネットワーク構築とHyperledger Fabricのチャネル作成、チェーンコードがデプロイができたかを確認します。
スタック情報のOutputs
にあるClientPublicIp
がEC2インスタンスのグローバルIPアドレスになりますので、最初に作成したキーペアファイルとでEC2インスタンスにSSHでログインします。
> ssh -i amb-client-ec2-key.pem ec2-user@xxx.xxx.xxx.xxx
EC2インスタンスのリソース作成で定義しているUserData
の実行ログは/var/log/cloud-init-output.log
で確認できます。
EC2インスタンス内
$ cat /var/log/cloud-init-output.log (略) + docker exec cli peer channel join -b mychannel.block -o orderer.n-xxxxxxxxxxxxxxxxxxxxxxxxxx.managedblockchain.us-east-1.amazonaws.com:30001 --cafile /opt/home/managedblockchain-tls-chain.pem --tls 2019-07-01 09:17:03.663 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 2019-07-01 09:17:03.903 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel + sleep 30s + docker exec cli peer chaincode install -n mycc -v v0 -p github.com/chaincode_example02/go 2019-07-01 09:17:34.076 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc 2019-07-01 09:17:34.076 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc 2019-07-01 09:17:34.490 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > + sleep 30s + docker exec cli peer chaincode instantiate -o orderer.n-xxxxxxxxxxxxxxxxxxxxxxxxxx.managedblockchain.us-east-1.amazonaws.com:30001 -C mychannel -n mycc -v v0 -c '{"Args":["init","a","100","b","200"]}' --cafile /opt/home/managedblockchain-tls-chain.pem --tls 2019-07-01 09:17:44.686 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc 2019-07-01 09:17:44.686 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc + sleep 30s + docker exec cli peer chaincode list --instantiated -o orderer.n-xxxxxxxxxxxxxxxxxxxxxxxxxx.managedblockchain.us-east-1.amazonaws.com:30001 -C mychannel --cafile /opt/home/managedblockchain-tls-chain.pem --tls Get instantiated chaincodes on channel mychannel: Name: mycc, Version: v0, Path: github.com/chaincode_example02/go, Escc: escc, Vscc: vscc + /opt/aws/bin/cfn-signal -e 0 --stack amb-cfn-test --resource BlockchainClient --region us-east-1 Cloud-init v. 0.7.6 finished at Mon, 01 Jul 2019 09:19:16 +0000. Datasource DataSourceEc2. Up 692.70 seconds
docker exec cli peer chaincode list --instantiated
コマンドでチェーンコードがデプロイされていることが確認できます。
EC2インスタンス内でcli peer chaincode query
コマンドが実行できるか確認します。
EC2インスタンス内
$ docker exec \ cli peer chaincode query \ -C mychannel \ -n mycc -c '{"Args":["query","a"]}' 100
やったぜ。
スタックの削除
ブロックチェーンネットワークが不要になったらCFnのスタック削除をすることで作成したリソースが削除できます。
Amazon CloudWatchに出力されるログや手動で作成したキーペア、Lmabda Layerは削除されないので適宜手動削除ください。
> aws cloudformation delete-stack \ --stack-name amb-cfn-test
まとめ
AMBを利用すると比較的容易にブロックチェーンネットワークが構築できますが、Hyperledger Fabricのチャネル作成やチェーンコードデプロイまでを含めると構築に手間がかかっていたので、CFnテンプレートを作成する意義はあったかなと思います。
ただ、CFnではまだAMBのリソースが対応しておらず、Lambda-Backedカスタムリソースを多用する必要があったので、テンプレート作成するにも思った以上にハマったり手間がかかりました。(白目
CFnのcfn-initヘルパースクリプトを利用すればEC2インスタンスで実行するコマンドなどもメタデータとしてテンプレートで管理できそうでしたが、おそらく相当にハマりそうだったので今回は踏み込みませんでした。
テンプレート作成する際のポイントは別記事にしてまとめようと思います。
参考
Amazon Managed BlockchainでHyperledger Fabricのブロックチェーンネットワークを構築してみた – Qiita
https://cloudpack.media/46963
AWS CloudFormationのAWS Lambda-backedカスタムリソースで最新のAWS SDKを利用する – Qiita
https://cloudpack.media/48058