Chaincode as an external service¶
Fabric v2.0 は、Fabric外部でのチェーンコードのデプロイと実行をサポートしており、ユーザーはピアから独立してチェーンコードのランタイムを管理できます。 これは、Kubernetesのようなクラウド環境にあるFabricにチェーンコードをデプロイすることを容易にするものです。 すべてのピアでチェーンコードをビルドして起動する代わりに、チェーンコードはFabricの外側でライフサイクルが管理されるサービスとして実行できるようになりました。 この機能は、Fabric v2.0の外部ビルダーとランチャーの機能を利用しており、運用者は、チェーンコードをビルド、起動、ディスカバリするためのプログラムでピアを拡張することができます。 このトピックを読む前に、External Builder and Launcher の内容をよく理解しておく必要があります。
外部ビルダーが利用可能になる前は、チェーンコードパッケージの内容は、チェーンコードバイナリとしてビルドして起動できる特定言語のソースコード・ファイルのセットであることが必要でした。 新しい外部ビルダーとランチャーの機能によって、ユーザーがオプションでビルドプロセスをカスタマイズすることができるようになりました。 チェーンコードを外部サービスとして実行することに関して、ビルドプロセスでは、チェーンコードが実行されているサーバーのエンドポイント情報を指定することができます。 従って、パッケージは単に外部で動いているチェーンコードサーバーのエンドポイント情報と、安全な接続のためのTLSアーティファクトから構成されます。 TLSはオプションですが、単純なテスト環境以外のすべての環境で強く推奨されます。
このトピックの残りの部分では、チェーンコードを外部サービスとして設定する方法について説明します。
- Packaging chaincode
- Configuring a peer to process external chaincode
- External builder and launcher sample scripts
- Writing chaincode to run as an external service
- Deploying the chaincode
- Running the chaincode as an external service
注意: この機能は高度なものであり、ピアイメージのカスタムパッケージが必要になる可能性があります。
例えば、以下のサンプルでは jq
と bash
を使用していますが、これらは現在の公式の fabric-peer
イメージには含まれていません。
Packaging chaincode¶
Fabric v2.0 のチェーンコードライフサイクルでは、チェーンコードは パッケージ化され、 .tar.gz
フォーマットでインストールされます。
以下の myccpackage.tgz
アーカイブは、必要な構造を示しています。
$ tar xvfz myccpackage.tgz
metadata.json
code.tar.gz
チェーンコードパッケージは、外部のビルダーとランチャープロセスに次の2つの情報を提供するために使用されます。
- チェーンコードが外部サービスであるかどうかを識別します。
bin/detect
セクションで、metadata.json
ファイルを使用したアプローチを説明します。 - release ディレクトリに置かれた
connection.json
ファイルで、チェーンコードのエンドポイント情報を提供します。bin/run
セクションで、connection.json
ファイルについて説明します。
上記の情報を収集するための柔軟性は十分にあります。 External builder and launcher sample scripts にあるサンプルスクリプトは、情報を提供するための簡単なアプローチを示しています。 柔軟性の例として、couchdb インデックスファイルのパッケージ化を考えてみましょう。 Add the index to your chaincode folder を参照してください。 以下のサンプルスクリプトは、ファイルを myccpackage.tar.gz にパッケージ化する方法を説明しています。
tar cfz code.tar.gz connection.json metadata
tar cfz myccpackage.tgz metadata.json code.tar.gz
Configuring a peer to process external chaincode¶
このセクションでは、必要な設定について説明します。
- チェーンコードパッケージが外部チェーンコードサービスを識別しているかどうかを検出します。
- リリースディレクトリに
connection.json
ファイルを作成します。
Modify the peer core.yaml to include the externalBuilder¶
スクリプトがピアの bin
ディレクトリに以下のように置かれていると仮定します。
<fully qualified path on the peer's env>
└── bin
├── build
├── detect
└── release
ピアの core.yaml
ファイルの chaincode
ブロックを変更し、externalBuilders
設定要素を追加します。
externalBuilders:
- name: myexternal
path: <fully qualified path on the peer's env>
External builder and launcher sample scripts¶
チェーンコードを外部サービスとして動作させる場合、それぞれのスクリプトが何を含む必要があるかを理解するために、このセクションでは bin/detect
bin/build
bin/release
bin/run
スクリプトのサンプルを掲載します。
注: これらのサンプルでは、json をパースするために jq
コマンドを使用します。
jq --version
を実行すると、インストールされているかどうか確認できます。
そうでない場合、 jq
をインストールするか、スクリプトを適切に修正してください。
bin/detect¶
bin/detect script
は、チェーンコードパッケージをビルドして起動するために buildpack を使用すべきかどうかを判断する役割を担っています。
チェーンコードが外部サービスである場合、サンプルスクリプトは metadata.json
ファイル内で external
に設定された type
プロパティを探します。
{"path":"","type":"external","label":"mycc"}
ピアは2つの引数でdetectを呼び出します。
bin/detect CHAINCODE_SOURCE_DIR CHAINCODE_METADATA_DIR
bin/detect
のサンプルスクリプトは以下のものを含みます。
#!/bin/bash
set -euo pipefail
METADIR=$2
#check if the "type" field is set to "external"
if [ "$(jq -r .type "$METADIR/metadata.json")" == "external" ]; then
exit 0
fi
exit 1
bin/build¶
チェーンコードを外部サービスとして利用する場合、サンプルのビルドスクリプトは チェーンコードパッケージの code.tar.gz
ファイルに connection.json
が含まれていると仮定し、それを BUILD_OUTPUT_DIR
にコピーします。
ピアは3つの引数でビルドスクリプトを呼び出します。
bin/build CHAINCODE_SOURCE_DIR CHAINCODE_METADATA_DIR BUILD_OUTPUT_DIR
A sample bin/build
script could contain:
#!/bin/bash
set -euo pipefail
SOURCE=$1
OUTPUT=$3
#external chaincodes expect connection.json file in the chaincode package
if [ ! -f "$SOURCE/connection.json" ]; then
>&2 echo "$SOURCE/connection.json not found"
exit 1
fi
#simply copy the endpoint information to specified output location
cp $SOURCE/connection.json $OUTPUT/connection.json
if [ -d "$SOURCE/metadata" ]; then
cp -a $SOURCE/metadata $OUTPUT/metadata
fi
exit 0
bin/release¶
外部サービスとしてのチェーンコードでは、 bin/release
スクリプトが connection.json
を RELEASE_OUTPUT_DIR
に配置してピアに提供する役割を担います。
connection.json
ファイルは以下のようなJSON構造になっています。
- address - ピアからアクセス可能なチェーンコード・サーバーのエンドポイントです。
<host>:<port>
形式で指定する必要があります。 - dial_timeout - 接続が完了するのを待つ時間。時間単位と一緒に文字列で指定します (例: "10s"、"500ms"、"1m")。指定しない場合、デフォルトは“3s”です。
- tls_required - trueまたはfalse。falseの場合、"client_auth_required"、"client_key"、"client_cert"、"root_cert" は必要ありません。デフォルトは "true "です。
- client_auth_required - trueの場合、"client_key "と "client_cert "は必要です。デフォルトはfalseです。tls_requiredがfalseの場合、無視されます。
- client_key - PEM形式でエンコードされたクライアント秘密鍵の文字列。
- client_cert - PEM形式でエンコードされたクライアント証明書の文字列。
- root_cert - PEM形式でエンコードされたサーバー(ピア)ルート証明書の文字列。
例:
{
"address": "your.chaincode.host.com:9999",
"dial_timeout": "10s",
"tls_required": "true",
"client_auth_required": "true",
"client_key": "-----BEGIN EC PRIVATE KEY----- ... -----END EC PRIVATE KEY-----",
"client_cert": "-----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----",
"root_cert": "-----BEGIN CERTIFICATE---- ... -----END CERTIFICATE-----"
}
bin/build
セクションで述べたように、このサンプルではチェーンコードパッケージが connection.json
ファイルを直接含んでおり、ビルドスクリプトが BUILD_OUTPUT_DIR
にコピーしているものと仮定しています。
ピアは2つの引数でリリーススクリプトを呼び出します。
bin/release BUILD_OUTPUT_DIR RELEASE_OUTPUT_DIR
bin/release
のサンプルスクリプトは以下のものを含みます。
#!/bin/bash
set -euo pipefail
BLD="$1"
RELEASE="$2"
if [ -d "$BLD/metadata" ]; then
cp -a "$BLD/metadata/"* "$RELEASE/"
fi
#external chaincodes expect artifacts to be placed under "$RELEASE"/chaincode/server
if [ -f $BLD/connection.json ]; then
mkdir -p "$RELEASE"/chaincode/server
cp $BLD/connection.json "$RELEASE"/chaincode/server
#if tls_required is true, copy TLS files (using above example, the fully qualified path for these fils would be "$RELEASE"/chaincode/server/tls)
exit 0
fi
exit 1
Writing chaincode to run as an external service¶
現在、外部サービスとしてのチェーンコードは、Go chaincode shimとNode.js chaincode shimでサポートされています。
Go¶
Fabric v2.0 では、Go shim API が ChaincodeServer
という型を提供するようになりました。
開発者はこれを用いてチェーンコードサーバを作成する必要があります。
Invoke
と Query
API は影響を受けません。
開発者は shim.ChaincodeServer
API を利用して、チェーンコードをビルドして、任意の外部環境で実行する必要があります。
以下は、このパターンを説明するためのシンプルなチェーンコードプログラムのサンプルです。
package main
import (
"fmt"
"github.com/hyperledger/fabric-chaincode-go/shim"
pb "github.com/hyperledger/fabric-protos-go/peer"
)
// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}
func (s *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
// init code
}
func (s *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
// invoke code
}
//NOTE - parameters such as ccid and endpoint information are hard coded here for illustration. This can be passed in in a variety of standard ways
func main() {
//The ccid is assigned to the chaincode on install (using the “peer lifecycle chaincode install <package>” command) for instance
ccid := "mycc:fcbf8724572d42e859a7dd9a7cd8e2efb84058292017df6e3d89178b64e6c831"
server := &shim.ChaincodeServer{
CCID: ccid,
Address: "myhost:9999"
CC: new(SimpleChaincode),
TLSProps: shim.TLSProperties{
Disabled: true,
},
}
err := server.Start()
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}
チェーンコードを外部サービスとして動作させるためのポイントは shim.ChaincodeServer
を使用することです。
これは新しい shim API shim.ChaincodeServer
と以下に説明するチェーンコードサービスのプロパティを使用します。
- CCID (string)- CCIDはピア上のチェーンコードのパッケージ名と一致する必要があります。
これは
peer lifecycle chaincode install <package>
CLI コマンドによって返される、インストールされたチェーンコードに関連付けられたCCID
です。 これはインストール後に "peer lifecycle chaincode queryinstalled" コマンドで取得することができます。 - Address (string) - アドレスは、チェーンコードサーバーのリッスンアドレスです。
- CC (Chaincode) - CCはInitとInvokeを処理するチェーンコードです。
- TLSProps (TLSProperties) - TLSPropsは、チェーンコードサーバーに渡されるTLSプロパティです。
- KaOpts (keepalive.ServerParameters) - KaOptsはキープアライブのオプションです。nil の場合、適切なデフォルトが提供されます。
以上により、各自のGo環境に適したチェーンコードをビルドします。
Node.js¶
Node.js のチェーンコードのための fabric-shim
パッケージは、チェーンコードを外部サービスとして動作させるための shim.server
APIを提供します。
コントラクトAPIを使用している場合、外部サービスモードでコントラクトを実行するには、 fabric-chaincode-node
CLI で提供されている server
コマンドを使用するとよいでしょう。
以下は fabric-shim
を使用したチェーンコードのサンプルです。
const shim = require('fabric-shim');
class SimpleChaincode extends shim.ChaincodeInterface {
async Init(stub) {
// ... Init code
}
async Invoke(stub) {
// ... Invoke code
}
}
const server = shim.server(new SimpleChaincode(), {
ccid: "mycc:fcbf8724572d42e859a7dd9a7cd8e2efb84058292017df6e3d89178b64e6c831",
address: "0.0.0.0:9999"
});
server.start();
fabric-contract
APIを用いてチェーンコードを外部サービスとして実行するには、 fabric-chaincode-node start
の代わりに fabric-chaincode-node server
を使用するだけです。
以下は package.json
のサンプルです。
{
"scripts": {
"start": "fabric-chaincode-node server"
},
...
}
fabric-chaincode-node server
を使用する場合、以下のオプションを引数または環境変数として設定する必要があります。
- CORE_CHAINCODE_ID (--chaincode-id): Goチェーンコードの CCID を参照してください。
- CORE_CHAINCODE_ADDRESS (--chaincode-address): Goチェーンコードの アドレス を参照してください。
TLSが有効な場合、以下の追加オプションが必要です。
- CORE_CHAINCODE_TLS_CERT_FILE (--chaincode-tls-cert-file): 証明書へのパス。
- CORE_CHAINCODE_TLS_KEY_FILE (--chaincode-tls-key-file): 秘密鍵へのパス。
相互TLSが有効な場合、 CORE_CHAINCODE_TLS_CLIENT_CACERT_FILE (--chaincode-tls-client-cacert-file) オプションを設定し、受け入れ可能なクライアント証明書に対するCA証明書のパスを指定する必要があります。
Deploying the chaincode¶
チェーンコードのデプロイの準備ができたら、Packaging chaincode で説明したようにチェーンコードをパッケージ化し、Fabric chaincode lifecycle で説明したようにチェーンコードをデプロイすることができます。
Running the chaincode as an external service¶
Writing chaincode to run as an external service セクションで説明されているように、チェーンコードを作成します。 ビルドした実行ファイルを、Kubernetesなどのお好みの環境で実行するか、ピアマシンのプロセスとして直接実行します。
このように、チェーンコードを外部サービスモデルとして使用すると、各ピアにチェーンコードをインストールする必要がなくなります。 その代わりにチェーンコードのエンドポイントをピアにデプロイして、チェーンコードが動作していると、チェーンコードの定義をチャネルにコミットしてチェーンコードを呼び出すという通常のプロセスを続けることができます。