├── CONTRIBUTING.md ├── DEBUGGING.md ├── LICENSE ├── MAINTAINERS.md ├── README-cn.md ├── README-ko.md ├── README.md ├── artifacts ├── chaincode │ └── chaincode_example02 │ │ └── chaincode_example02.go ├── configtx.yaml └── crypto-config.yaml ├── configFiles ├── blockchain-services.yaml ├── chaincode_install.yaml ├── chaincode_instantiate.yaml ├── copyArtifactsJob.yaml ├── createVolume-paid.yaml ├── createVolume.yaml ├── create_channel.yaml ├── docker-volume.yaml ├── docker.yaml ├── generateArtifactsJob.yaml ├── join_channel.yaml └── peersDeployment.yaml ├── deleteNetwork.sh ├── images ├── architecture.png ├── cluster-status.png ├── create-service.png ├── error1.png ├── error2.png ├── error3.png ├── error4.png ├── error5.png ├── first-query.png ├── gain-access-to-cluster.png ├── invoke.png ├── kdashboardonibmcloud.png ├── kubernetes-dashboard.png ├── provide-token-for-dashboard.png ├── second-query.png └── third-query.png ├── setup_blockchainNetwork_v1.sh └── setup_blockchainNetwork_v2.sh /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | This is an open source project, and we appreciate your help! 4 | 5 | We use the GitHub issue tracker to discuss new features and non-trivial bugs. 6 | 7 | In addition to the issue tracker, [#journeys on 8 | Slack](https://dwopen.slack.com) is the best way to get into contact with the 9 | project's maintainers. 10 | 11 | To contribute code, documentation, or tests, please submit a pull request to 12 | the GitHub repository. Generally, we expect two maintainers to review your pull 13 | request before it is approved for merging. For more details, see the 14 | [MAINTAINERS](MAINTAINERS.md) page. 15 | -------------------------------------------------------------------------------- /DEBUGGING.md: -------------------------------------------------------------------------------- 1 | Troubleshooting 2 | =============== 3 | 4 | * Always start your network fresh. Use the script `deleteNetwork.sh` to delete any pre-existing jobs/pods etc. 5 | 6 | * If you see below error, then environment is not set properly and therefore kubectl commands will not work. Ensure you have logged into IBM Cloud and have set your KUBECONFIG environment variable. 7 | ``` 8 | $ kubectl get pods 9 | The connection to the server localhost:8080 was refused - did you specify the right host or port? 10 | ``` 11 | 12 | * If you see the error 13 | ```error: SchemeError(io.k8s.apimachinery.pkg.apis.meta.v1.APIGroup): invalid object doesn't have additional properties``` 14 | 15 | We have seen this problem when the server version is latest 1.12.x or greater but client version is 1.10.x. You need to upgrade kubectl version at client side then it will work as expected. 16 | 17 | You can issue the following command 18 | 19 | ```brew link --overwrite kubernetes-clicd 2019``` 20 | 21 | * If you see below error, it means this peer has not joined the channel and so your query will not work. 22 | 23 | ![](images/error1.png) 24 | 25 | You may need to run the following command: 26 | 27 | ``` 28 | $ ibmcloud ks cluster-config --cluster 29 | $ export KUBECONFIG=/kube-config-hou02-mycluster.yml 30 | 31 | ``` 32 | 33 | * If you see something similar to the following: 34 | 35 | ![](images/error2.png) 36 | 37 | It shows there is some error in command. For example, in this snapshot `-c` is missing before passing arguments. 38 | 39 | * If you see the below error, 40 | 41 | ![](images/error3.png) 42 | 43 | There is something wrong with the setup. You would like to do setup from a fresh. 44 | 45 | * For debugging purposes, if you want to inspect the logs of any container, then run the following command. 46 | 47 | ``` 48 | $ kubectl get pods --show-all # Get the name of the pod 49 | $ kubectl logs [pod name] # if pod has one container 50 | $ kubectl logs [pod name] [container name] # if pod has more than one container 51 | ``` 52 | 53 | * If you see something like this for chaincode instantiation, 54 | 55 | ![](images/error4.png) 56 | 57 | It means chaincode has been instantiated already on the peer. Retrying of the same will fail with this error. You can ignore 58 | this message and continue with your transactions (invoke/query). 59 | 60 | * If you see error as shown below: 61 | 62 | ![](images/error5.png) 63 | 64 | It is intermittent issue and might occur because of network. Delete the network and retry afresh after sometime. 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | # Maintainers Guide 2 | 3 | This guide is intended for maintainers - anybody with commit access to one or 4 | more Code Pattern repositories. 5 | 6 | ## Methodology 7 | 8 | This repository does not have a traditional release management cycle, but 9 | should instead be maintained as a useful, working, and polished reference at 10 | all times. While all work can therefore be focused on the master branch, the 11 | quality of this branch should never be compromised. 12 | 13 | The remainder of this document details how to merge pull requests to the 14 | repositories. 15 | 16 | ## Merge approval 17 | 18 | The project maintainers use LGTM (Looks Good To Me) in comments on the pull 19 | request to indicate acceptance prior to merging. A change requires LGTMs from 20 | two project maintainers. If the code is written by a maintainer, the change 21 | only requires one additional LGTM. 22 | 23 | ## Reviewing Pull Requests 24 | 25 | We recommend reviewing pull requests directly within GitHub. This allows a 26 | public commentary on changes, providing transparency for all users. When 27 | providing feedback be civil, courteous, and kind. Disagreement is fine, so long 28 | as the discourse is carried out politely. If we see a record of uncivil or 29 | abusive comments, we will revoke your commit privileges and invite you to leave 30 | the project. 31 | 32 | During your review, consider the following points: 33 | 34 | ### Does the change have positive impact? 35 | 36 | Some proposed changes may not represent a positive impact to the project. Ask 37 | whether or not the change will make understanding the code easier, or if it 38 | could simply be a personal preference on the part of the author (see 39 | [bikeshedding](https://en.wiktionary.org/wiki/bikeshedding)). 40 | 41 | Pull requests that do not have a clear positive impact should be closed without 42 | merging. 43 | 44 | ### Do the changes make sense? 45 | 46 | If you do not understand what the changes are or what they accomplish, ask the 47 | author for clarification. Ask the author to add comments and/or clarify test 48 | case names to make the intentions clear. 49 | 50 | At times, such clarification will reveal that the author may not be using the 51 | code correctly, or is unaware of features that accommodate their needs. If you 52 | feel this is the case, work up a code sample that would address the pull 53 | request for them, and feel free to close the pull request once they confirm. 54 | 55 | ### Does the change introduce a new feature? 56 | 57 | For any given pull request, ask yourself "is this a new feature?" If so, does 58 | the pull request (or associated issue) contain narrative indicating the need 59 | for the feature? If not, ask them to provide that information. 60 | 61 | Are new unit tests in place that test all new behaviors introduced? If not, do 62 | not merge the feature until they are! Is documentation in place for the new 63 | feature? (See the documentation guidelines). If not do not merge the feature 64 | until it is! Is the feature necessary for general use cases? Try and keep the 65 | scope of any given component narrow. If a proposed feature does not fit that 66 | scope, recommend to the user that they maintain the feature on their own, and 67 | close the request. You may also recommend that they see if the feature gains 68 | traction among other users, and suggest they re-submit when they can show such 69 | support. 70 | -------------------------------------------------------------------------------- /README-cn.md: -------------------------------------------------------------------------------- 1 | _本文讲解内容是基于 2018-04-06 版本,了解后续更新内容,请参考 [English](README.md)。_ 2 | 3 | # 使用 IBM Cloud 上的 Kubernetes API 部署区块链网络 4 | 5 | 区块链是一个不可改变的共享分类账,用于记录交易历史信息。Linux 基金会的 Hyperledger Fabric 是 IBM 致力于的区块链软件实现,是一种许可网络。无论开发何种区块链用例,首先都要为创建和部署应用建立一个 Hyperledger Fabric 开发环境。Hyperledger Fabric 网络可通过多种方式进行设置。 6 | * [Hyperledger Fabric 网络内部部署](http://hyperledger-fabric.readthedocs.io/en/release-1.0/build_network.html) 7 | * 使用托管在 [IBM Cloud](https://console.bluemix.net/) 上的[区块链即服务](https://console.bluemix.net/catalog/services/blockchain)。IBM Cloud 通过 Starter Membership Plan 和 Enterprise Membership Plan 为您提供区块链即服务。 8 | * 使用 [IBM Cloud Container Service](https://console.bluemix.net/containers-kubernetes/catalog/cluster) 上的 Kubernetes API 的 Hyperledger Fabric 网络 9 | 10 | 本 Code Pattern 演示**使用 IBM Cloud Container Service 上的 Kubernetes API 在 Hyperledger Fabric 上**设置业务网络所涉及的步骤。 11 | 12 | 在 IBM Cloud 上托管 Hyperledger Fabric 网络可为您提供诸多好处,比如,多个用户可以在同一设置下工作,该设置可以用于不同的区块链应用,以及可以重复使用设置等等。请注意,Kubernetes 上的区块链网络设置适用于演示方案,但是对于生产,推荐使用 IBM Cloud 上托管的 IBM 区块链即服务。 13 | 14 | #### Kubernetes 集群 15 | 16 | [IBM Cloud Container Service](https://console.bluemix.net/containers-kubernetes/catalog/cluster) 支持创建免费集群,配备 2 个 CPU、4 GB 内存和 1 个工作节点。可用于熟悉并测试 Kubernetes 功能。但是,它们缺乏 NFS 文件持久存储以及持久卷等功能。 17 | 18 | 要设置集群以获得最大的可用性和容量,IBM Cloud 支持您创建完全可定制的生产就绪型集群,即 _标准集群_。_标准集群_ 支持高度可用的集群配置,比如,在不同地区运行两个集群,每个集群设有多个工作节点。请访问 https://console.bluemix.net/docs/containers/cs_planning.html#cs_planning_cluster_config, 查看其他高度可用的集群配置选项。 19 | 20 | 本 Code Pattern 使用 IBM Cloud 提供的 _免费集群_,可用于进行概念验证。它还为您提供了脚本,可自动执行使用 IBM Cloud 上的 Kubernetes API 设置 Hyperledger Fabric 网络的流程。 21 | 22 | 读者完成本 Code Pattern 之后,将会掌握如何: 23 | 24 | * 根据网络拓扑结构修改配置文件 25 | * 在 Kubernetes 集群上部署 Hyperledger Fabric 网络 26 | 27 | ## 操作流程 28 | 29 | ![](images/architecture.png) 30 | 31 | 1. 登录到 IBM Cloud CLI,对 IBM Cloud Container Service 插件进行初始化。 32 | 2. 利用 CLI 设置 Kubernetes 集群环境,下载 Kubernetes 配置文件。下载完配置文件后,设置 KUBECONFIG 环境变量。 33 | 3. 运行脚本以在 Kubernetes 集群上部署 Hyperledger Fabric 网络。 34 | 4. 访问 Kubernetes 仪表板。 35 | 36 | ## 包含的组件 37 | 38 | * [Hyperledger Fabric](https://hyperledger-fabric.readthedocs.io/):Hyperledger Fabric 是适用于分布式分类账解决方案的平台,由模块化的架构提供支持,可交付高水平的机密性、灾备能力、灵活性和可扩展性。 39 | 40 | * [IBM Cloud Container Service](https://console.bluemix.net/containers-kubernetes/catalog/cluster):IBM Container Service 支持编排智能调度、自我修复以及水平伸缩功能。 41 | 42 | ## 包含的技术 43 | 44 | * [区块链](https://en.wikipedia.org/wiki/Blockchain):区块链是一种数字化、去中心化的公共分类账,涵盖网络中的所有交易。 45 | 46 | * [Kubernetes 集群](https://kubernetes.io/docs):在 Kubernetes 引擎中,容器集群包含至少一个集群主节点和多个工作节点。容器集群是 Kubernetes 引擎的基础。 47 | 48 | ## 观看视频 49 | 50 | [![](http://img.youtube.com/vi/DFYk6XaMHc0/0.jpg)](http://v.youku.com/v_show/id_XMzY0NDg0OTU1Ng==.html) 51 | 52 | ## 使用的 Kubernetes 概念 53 | * [Kubernetes Pod](https://kubernetes.io/docs/concepts/workloads/pods/pod/) - Pod 表示 Kubernetes 集群中可部署的最小单元,用于对必须被视为单个单元的容器进行分组。 54 | * [Kubernetes 作业](https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/) - 一个作业可创建一个或多个 Pod,并确保成功终止指定数量的 Pod。Pod 成功完成之后,该作业会跟踪成功完成情况。 55 | * [Kubernetes 部署](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) - 部署是一种 Kubernetes 资源,您可以在此指定运行应用所需的容器和其他 Kubernetes 资源,比如持久存储、服务或注释。 56 | * [Kubernetes 服务](https://kubernetes.io/docs/concepts/services-networking/service/) - Kubernetes 服务集合了一系列的 Pod,并为集群中面向其他服务的 Pod 提供网络连接,无需公开每个 Pod 的真实私有 IP 地址。 57 | * [Kubernetes 持久卷 (PV)](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) - 持久卷是用户*请求获得*持久存储(比如 NFS 文件存储)的一种方式。 58 | 59 | ## 步骤 60 | 61 | 按照这些步骤来设置并运行本 Code Pattern。 62 | 63 | 1. [在 IBM Cloud 上创建 Kubernetes 集群](#1-create-a-kubernetes-cluster-on-ibm-cloud) 64 | 2. [设置 CLI](#2-setting-up-clis) 65 | 3. [获得 Kubernetes 集群访问权限](#3-gain-access-to-your-kubernetes-cluster) 66 | 4. [将 Hyperledger Fabric 网络部署到 Kubernetes 集群](#4-deploy-hyperledger-fabric-network-into-kubernetes-cluster) 67 | 5. [测试已部署的网络](#5-test-the-deployed-network) 68 | 6. [查看 Kubernetes 仪表板](#6-view-the-kubernetes-dashboard) 69 | 70 | ### 1. 在 IBM Cloud 上创建 Kubernetes 集群 71 | 72 | * 使用 GUI 通过 [IBM Cloud Container Service](https://console.bluemix.net/containers-kubernetes/catalog/cluster) 创建 Kubernetes 集群。本 Code Pattern 使用 _免费集群_。 73 | 74 | ![](images/create-service.png) 75 | 76 | 注意:设置和配置集群最长需要 15 分钟。 77 | 78 | 79 | ### 2. 设置 CLI 80 | 81 | * 安装 [IBM Cloud CLI](https://console.bluemix.net/docs/cli/reference/bluemix_cli/get_started.html#getting-started)。使用 IBM Cloud CLI 运行命令的前缀为 `bx`。 82 | 83 | * 安装 [Kubernetes CLI](https://kubernetes.io/docs/tasks/tools/install-kubectl/)。使用 Kubernetes CLI 运行命令的前缀为 `kubectl`。 84 | 85 | * 使用以下命令安装容器服务插件。 86 | ``` 87 | bx plugin install container-service -r Bluemix``` 88 | 89 | ### 3. 获得 Kubernetes 集群访问权限 90 | 91 | 访问 [IBM Cloud Dashboard](https://console.bluemix.net/dashboard/apps)。选择创建集群所在的 Cloud Foundry 组织和 Cloud Foundry 空间。 92 | 93 | * 检查集群的状态:`IBM Cloud Dashboard -> -> Worker Nodes`。如果状态不是 `ready`,那么您需要等待一段时间才能继续。 94 | 95 | ![](images/cluster-status.png) 96 | 97 | * 集群准备就绪之后,打开 Access 选项卡:`IBM Cloud Dashboard -> -> Access`,如快照所示。 98 | 99 | ![](images/gain-access-to-cluster.png) 100 | 101 | * 执行 `Gain access to your cluster` 部分提供的步骤。 102 | 103 | * 通过检查 Kubernetes CLI 服务器版本,验证是否对您的集群正确运行了 kubectl 命令。 104 | 105 | ``` 106 | $ kubectl version --short 107 | Client Version: v1.9.2 108 | Server Version: v1.8.6-4+9c2a4c1ed1ee7e 109 | ``` 110 | 111 | ### 4. 将 Hyperledger Fabric 网络部署到 Kubernetes 集群 112 | 113 | #### 了解网络拓扑结构 114 | 115 | 本 Code Pattern 提供一个可自动配置 Hyperledger Fabric 样本网络的脚本,该网络包含四个组织,每个组织维护一个对等节点和一个单独的订购服务。同时,该脚本还会创建一个名为 `channel1` 的通道,将所有对等节点连接到 `channel1` 通道上,在所有对等节点上安装链码,并对通道上的链码进行实例化。本 Code Pattern 也会帮助推动根据已部署的链码执行交易。 116 | 117 | #### 复制 Kubernetes 配置脚本 118 | 119 | 克隆 Kubernetes 配置脚本或将其下载到用户主目录。 120 | ``` 121 | $ git clone https://github.com/IBM/blockchain-network-on-kubernetes.git 122 | ``` 123 | 124 | 浏览至源目录。 125 | ``` 126 | $ cd blockchain-network-on-kubernetes 127 | $ ls 128 | ``` 129 | 在源目录中, 130 | * `configFiles` 包含 Kubernetes 配置文件 131 | * `artifacts` 包含网络配置文件 132 | * `*.sh` 脚本用于部署和删除网络 133 | 134 | #### 修改 Kubernetes 配置脚本 135 | 136 | 如果网络拓扑结构中存在任何变更,就需要相应地修改配置文件(.yaml 文件)。配置文件位于 `artifacts` 和 `configFiles` 目录中。例如,如果决定增加/减少持久卷的容量,那么就需要修改 `createVolume.yaml`。 137 | 138 | #### 运行脚本以部署 Hyperledger Fabric 网络 139 | 140 | 完成配置文件变更(如有)之后,您即准备好部署网络。执行脚本以部署 Hyperledger Fabric 网络。 141 | 142 | ``` 143 | $ chmod +x setup_blockchainNetwork.sh 144 | $ ./setup_blockchainNetwork.sh 145 | ``` 146 | 147 | 注意:在运行脚本前,请检查您的环境。您应当能够按照第 3 步所述,对您的集群正确运行 `kubectl 命令`。 148 | 149 | #### 删除网络 150 | 151 | 如有需要,您可以使用 `deleteNetwork.sh` 脚本删除 Hyperledger Fabric 网络。该脚本将从 Kubernetes 集群中删除您的所有 Pod、作业、部署等等。 152 | 153 | ``` 154 | $ chmod +x deleteNetwork.sh 155 | $ ./deleteNetwork.sh 156 | ``` 157 | 158 | ### 5. 测试已部署的网络 159 | 160 | `setup_blockchainNetwork.sh` 脚本成功执行之后,检查 Pod 的状态。 161 | 162 | ``` 163 | $ kubectl get pods 164 | NAME READY STATUS RESTARTS AGE 165 | blockchain-ca-7848c48d64-2cxr5 1/1 Running 0 4m 166 | blockchain-orderer-596ccc458f-thdgn 1/1 Running 0 4m 167 | blockchain-org1peer1-747d6bdff4-4kzts 1/1 Running 0 4m 168 | blockchain-org2peer1-7794d9b8c5-sn2qf 1/1 Running 0 4m 169 | blockchain-org3peer1-59b6d99c45-dhtbp 1/1 Running 0 4m 170 | blockchain-org4peer1-6b6c99c45-wz9wm 1/1 Running 0 4m 171 | ``` 172 | 173 | 如上所述,该脚本将所有对等节点连接到一个通道 `channel1` 上,在所有对等节点上安装链码,并对通道上的链码进行实例化。这意味着,我们可以在任何对等节点上执行调用/查询命令,并且所有对等节点上的响应均应相同。请注意,为避免复杂性,在本 Code Pattern 中禁用 TLS 证书。在本 Code Pattern 中,CLI 命令用于测试网络。为了针对任何对等节点运行查询,需要进入对等节点的 Bash Shell,运行查询并从对等容器中退出。 174 | 175 | 使用以下命令进入对等节点的 Bash Shell: 176 | 177 | ``` 178 | $ kubectl exec -it bash 179 | ``` 180 | 181 | 用于从对等容器中退出的命令为: 182 | 183 | ``` 184 | # exit 185 | ``` 186 | 187 | **查询** 188 | 189 | 使用值将链码实例化为 `{ a: 100, b: 200 }`。我们对 `org1peer1` 进行查询,获取 `a` 的值,确保链码已被正确实例化。 190 | 191 | ![](images/first-query.png) 192 | 193 | **调用** 194 | 195 | 现在,我们向 `org2peer1` 提交请求,要求从 `a` 向 `b` 移动 20。新的交易将会生成,交易成功完成之后,将会更新状态。 196 | 197 | ![](images/invoke.png) 198 | 199 | **查询** 200 | 201 | 我们来确认下前面的调用已正确执行。我们使用值 100 对关键字 `a` 进行实例化,并且通过前面的调用仅移除 20。因此,针对 `a` 的查询应当显示 80,而针对 `b` 的查询应当显示 220。现在,向 `org3peer1` 和 `org4peer1` 发出查询请求,如下所示。 202 | 203 | ![](images/second-query.png) 204 | 205 | ![](images/third-query.png) 206 | 207 | ### 6. 查看 Kubernetes 仪表板 208 | 209 | 使用以下命令获取令牌,针对 Kubernetes 仪表板进行认证。 210 | 211 | ``` 212 | $ kubectl config view -o jsonpath='{.users[0].user.auth-provider.config.id-token}' 213 | ``` 214 | 215 | 复制令牌。通过缺省端口 8001 启动 Kubernetes 仪表板。 216 | 217 | ``` 218 | $ kubectl proxy 219 | ``` 220 | 221 | 在 Web 浏览器中打开 URL http://localhost:8001/ui, 查看 Kubernetes 仪表板。系统会提示需要认证。 222 | 223 | ![](images/provide-token-for-dashboard.png) 224 | 225 | 提供令牌和 `SIGN-IN`。在 Workloads 选项卡中,您可以看到通过脚本创建的资源。 226 | 227 | ![](images/kubernetes-dashboard.png) 228 | 229 | Hyperledger Fabric 网络可供使用。您可以使用节点 SDK 或 Hyperledger Composer,开始为这个部署的网络开发区块链应用。 230 | 231 | ## 故障排除 232 | 233 | [参见 DEBUGGING.md。](DEBUGGING.md) 234 | 235 | ## 许可 236 | 237 | [Apache 2.0](LICENSE) 238 | -------------------------------------------------------------------------------- /README-ko.md: -------------------------------------------------------------------------------- 1 | # Kubernetes API를 사용하여 IBM 클라우드에 블록체인 네트워크 배포하기 2 | 3 | *Read this in other languages: [English](README.md)* 4 | 5 | 블록체인은 거래 내역의 무결성이 보장된 공유 원장입니다. 리눅스 재단의 Hyperledger Fabric은 IBM이 구현한 Permissioned 네트워크입니다. 블록체인의 활용 예제를 개발할 때 가장 먼저해야 할 일은 Hyperledger Fabric의 응용 프로그램 개발 및 배포 환경을 갖추는 것입니다. Hyperledger Fabric 네트워크를 구성하는 방법은 여러 가지가 있습니다. 6 | * [Hyperledger Fabric 네트워크 온프레미스](http://hyperledger-fabric.readthedocs.io/en/release-1.0/build_network.html)에 구성하기 7 | * [IBM 클라우드](https://console.bluemix.net/)의 [블록체인 서비스](https://console.bluemix.net/catalog/services/blockchain). IBM 클라우드는 스타터 및 엔터프라이즈 멤버십 플랜으로 블록체인 서비스를 활용하기 8 | * [IBM 클라우드 컨테이너 서비스](https://console.bluemix.net/containers-kubernetes/catalog/cluster)에서 제공하는 [Kubernetes API](https://console.bluemix.net/containers-kubernetes/catalog/cluster)를 사용한 Hyperledger Fabric 네트워크를 활용하기 9 | 10 | 이번 코드 패턴에서는 **Hyperledger Fabric에서 IBM 클라우드 컨테이너 서비스의 Kubernetes API를 활용**하여 비즈니스 네트워크를 설정하는 방법을 알아봅니다. 11 | 12 | Hyperledger Fabric 네트워크를 IBM 클라우드에서 호스팅하면 여러 사용자가 같은 환경에서 작업이 가능하고, 다른 블록체인 애플리케이션에 환경을 재사용하는 등 다양한 이점이 있습니다. Kubernetes의 블록체인 네트워크 설정은 데모 시나리오 목적으로는 충분하지만, 비즈니스 용도로는 IBM 클라우드에서 호스팅하는 블록체인 서비스를 추천합니다. 13 | 14 | #### Kubernetes 클러스터 15 | 16 | [IBM 클라우드 컨테이너 서비스](https://console.bluemix.net/containers-kubernetes/catalog/cluster)는 Kubernetes 기능을 익히고 테스트할 수 있도록 2개의 CPU, 4GB 메모리 및 1 개의 worker 노드로 이루어진 무료 클러스터 구성을 제공합니다. 그러나 NFS처럼 볼륨 기반의 파일 저장소 기능은 제공하지 않습니다. 17 | 18 | IBM 클라우드는 클러스터의 최대 가용성과 기능성을 이끌어내기 위해 즉시 비즈니스용으로 사용 가능하며 완벽한 커스터마이징을 지원하는 _Standard Cluster_ 를 제공합니다. _Standard Cluster_ 는 서로 다른 영역에서 실행되는 다중 작업노드를 포함한 클러스터 구성과 같은 고가용성 클러스터 설정이 가능합니다. 고가용성 클러스터 구성에 대한 다른 옵션을 검토하려면 https://console.bluemix.net/docs/containers/cs_planning.html#cs_planning_cluster_config 를 참조하세요. 19 | 20 | 이 코드 패턴은 IBM 클라우드에서 제공하는 _free cluster_ 를 사용하며, PoC(proof-of-concept) 용도로 활용할 수 있습니다. 또한, IBM 클라우드의 Kubernetes API를 사용하여 Hyperledger Fabric 네트워크를 설정하는 프로세스를 자동화하는 스크립트를 제공합니다. 21 | 22 | 이 패턴을 완료하시면 다음을 배울 수 있습니다: 23 | 24 | * 네트워크 토폴로지에 따른 설정 파일 수정하기 25 | * Kubernetes 클러스터에 Hyperledger Fabric 네트워크 배포하기 26 | 27 | ## 다음 순서를 따라하세요. 28 | 29 | ![](images/architecture.png) 30 | 31 | 1. IBM 클라우드 CLI에 접속하여 IBM 클라우드 컨테이너 서비스 플러그인을 초기화합니다. 32 | 2. CLI를 사용하여 Kubernetes 클러스터에 대한 context를 변경하고 Kubernetes 설정 파일을 다운로드하세요. 설정 파일을 다운로드한 후 KUBECONFIG 환경 변수를 설정하세요. 33 | 3. 스크립트를 실행하여 Kubernetes 클러스터에 Hyperledger Fabric 네트워크를 배포합니다. 34 | 4. Kubernetes의 대시보드로 이동하세요. 35 | 36 | ## 구성 요소 37 | 38 | * [Hyperledger Fabric](https://hyperledger-fabric.readthedocs.io/): Hyperledger Fabric은 고도의 기밀성, 탄력성, 유연성 및 확장성을 제공하는 모듈러 아키텍처 기반의 분산원장 솔루션을 위한 플랫폼입니다. 39 | * [IBM 클라우드 컨테이너 서비스](https://console.bluemix.net/containers-kubernetes/catalog/cluster): IBM 컨테이너 서비스는 지능형 스케줄링, 자가 치유 및 수평 확장을 조화롭게 관리합니다. 40 | 41 | ## 주요 기술 42 | 43 | * [블록체인](https://en.wikipedia.org/wiki/Blockchain): 블록체인은 네트워크의 모든 거래 내역이 분산된 디지털 공개 원장입니다. 44 | * [Kubernetes Cluster](https://kubernetes.io/docs): Kubernetes Engine에서 컨테이너 클러스터는 최소 하나의 마스터 클러스터와 노드라고 불리는 여러 작업 시스템으로 구성됩니다. 컨테이너 클러스터는 Kubernetes 엔진의 기반입니다. 45 | 46 | ## 참조 동영상 47 | 48 | [![](http://img.youtube.com/vi/DFYk6XaMHc0/0.jpg)](https://youtu.be/DFYk6XaMHc0) 49 | 50 | ## Kubernetes의 개념 정의 51 | 52 | * [Kubernetes Pods](https://kubernetes.io/docs/concepts/workloads/pods/pod/) - Pod는 Kubernetes 클러스터에서 배포 가능한 최소 단위를 뜻하며, 단일로 처리해야 하는 여러 컨테이너를 그룹화하는 데 사용됩니다. 53 | * [Kubernetes Jobs](https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/) - Job은 하나 이상의 Pod를 생성하고 지정된 수의 Pod가 성공적으로 종료하도록 합니다. Pod를 가 성공적으로 완료되면 Job은 이를 기록합니다. 54 | * [Kubernetes Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) - Deployment는 저장장치, 서비스 및 어노테이션 등 애플리케이션을 실행하기 위해 필요한 기타 리소스와 컨테이너를 지정하는 Kubernetes 리소스입니다. 55 | * [Kubernetes Services](https://kubernetes.io/docs/concepts/services-networking/service/) - Kubernetes service는 여러 Pod를 그룹화하고 클러스터 내 다른 서비스를 위해 개별 Pod의 IP 주소를 은폐하면서 네트워크 연결을 제공합니다. 56 | * [Kubernetes Persistent Volumes (PV)](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) - Persistent Volume은 사용자가 NFS와 같은 파일 저장소를 요청하는 방법입니다. 57 | 58 | ## 순서 59 | 60 | 다음 순서를 따라 환경을 설정하고 코드를 실행합니다. 61 | 62 | 1. [IBM 클라우드에 Kubernetes 클러스터 생성](#1-ibm-클라우드에-kubernetes-클러스터-생성) 63 | 2. [CLI 설치](#2-cli-설치) 64 | 3. [Kubernetes 클러스터에 접근 권한 얻기](#3-kubernetes-클러스터에-접근-권한-얻기) 65 | 4. [Kubernetes 클러스터에 Hyperledger Fabric 네트워크 배포](#4-kubernetes-클러스터에-hyperledger-fabric-네트워크-배포) 66 | 5. [배포된 네트워크 테스트](#5-배포된-네트워크-테스트) 67 | 6. [Kubernetes 대시보드 확인](#6-kubernetes-대시보드-확인) 68 | 69 | ### 1. IBM 클라우드에 Kubernetes 클러스터 생성 70 | 71 | * [IBM 클라우드 컨테이너 서비스](https://console.bluemix.net/containers-kubernetes/catalog/cluster) GUI를 사용하여 Kubernetes 클러스터를 생성합니다. 이 패턴에서는 _free cluster_ 을 사용합니다. 72 | 73 | ![](images/create-service.png) 74 | 75 | 주의: 클러스터를 설정하고 준비하는 데에는 최대 15분이 걸릴 수 있습니다. 76 | 77 | 78 | ### 2. CLI 설치 79 | 80 | * [IBM 클라우드 CLI](https://console.bluemix.net/docs/cli/reference/bluemix_cli/get_started.html#getting-started)를 설치하세요. Bluemix CLI로 명령을 실행하려면 `bx` 를 사용합니다. 81 | 82 | * [Kubernetes CLI](https://kubernetes.io/docs/tasks/tools/install-kubectl/)를 설치하세요. Kubernetes CLI로 명령을 실행하려면 `kubectl` 을 사용합니다. 83 | 84 | * 다음 명령을 실행하여 컨테이너 서비스 플러그인을 설치하세요. 85 | ``` 86 | bx plugin install container-service -r Bluemix 87 | ``` 88 | 89 | ### 3. Kubernetes 클러스터에 접근 권한 얻기 90 | 91 | [IBM 클라우드 대시보드](https://console.bluemix.net/dashboard/apps)에서 클러스터가 생성된 동일한 클라우드 파운드리 조직 및 클라우드 파운드리 공간을 선택하세요. 92 | 93 | * 클러스터의 상태를 확인합니다. `IBM Cloud Dashboard -> -> Worker Nodes` 상태가 `ready`로 바뀔 때까지 계속 기다립니다. 94 | 95 | ![](images/cluster-status.png) 96 | 97 | * 클러스터가 준비되면 아래 스냅샷에 보이는대로 Access 탭을 엽니다. `IBM Cloud Dashboard -> -> Access` 98 | 99 | ![](images/gain-access-to-cluster.png) 100 | 101 | * `Gain access to your cluster`에 제공된 가이드를 따라 순서대로 진행합니다. 102 | 103 | * Kubernetes CLI 서버 버전을 확인하여 kubectl 명령이 클러스터에서 제대로 실행되는지 확인합니다. 104 | 105 | ``` 106 | $ kubectl version --short 107 | Client Version: v1.9.2 108 | Server Version: v1.8.6-4+9c2a4c1ed1ee7e 109 | ``` 110 | 111 | ### 4. Kubernetes 클러스터에 Hyperledger Fabric 네트워크 배포 112 | 113 | #### 네트워크 토폴로지 이해하기 114 | 115 | 이 패턴은 각 1개의 피어와 '솔로' 주문 서비스로 구성된, 총 4개의 조직을 포함한 Hyperledger Fabric 네트워크 샘플을 자동으로 준비하는 스크립트를 제공합니다. 스크립트는 또한 `channel1`이란 이름의 채널을 생성하고 모든 피어를 이 채널로 연결합니다. 그 다음, 체인코드를 모든 피어에게 설치하여 채널에 인스턴스화합니다. 이 패턴은 배포된 체인코드에 대해 트랜잭션 실행이 이루어지도록 도움을 줍니다. 116 | 117 | #### Kubernetes 설정 스크립트 복사하기 118 | 119 | Kubernetes 설정 스크립트를 사용자의 홈 디렉토리에 복사 또는 다운로드합니다. 120 | ``` 121 | $ git clone https://github.com/IBM/blockchain-network-on-kubernetes.git 122 | ``` 123 | 124 | 소스 디렉토리로 이동합니다. 125 | ``` 126 | $ cd blockchain-network-on-kubernetes 127 | $ ls 128 | ``` 129 | 소스 디렉토리 안에, 130 | * `configFiles` 디렉토리는 Kubernetes 설정 파일을 포함하고 있습니다. 131 | * `artifacts` 디렉토리는 네트워크 설정 파일을 포함하고 있습니다. 132 | * `*.sh` 파일은 네트워크를 배포 또는 삭제하는 스크립트입니다. 133 | 134 | #### Kubernetes 설정 스크립트 수정하기 135 | 136 | 네트워크 토폴로지가 변경되면 구성 파일 (.yaml 파일)을 적절하게 수정해야 합니다. 설정 파일은 `artifacts`와 `configFiles` 디렉토리에 있습니다. 예를 들어, 볼륨의 용량을 늘리거나 줄이려면 `createVolume.yaml` 파일을 수정해야 합니다. 137 | 138 | #### 스크립트를 실행하여 Hyperledger Fabric 네트워크 배포하기 139 | 140 | 설정 파일이 완성되면 네트워크를 배포할 준비가 된 것입니다. 스크립트를 실행하여 Hyperledger Fabric 네트워크를 배포하세요. 141 | 142 | ``` 143 | $ chmod +x setup_blockchainNetwork.sh 144 | $ ./setup_blockchainNetwork.sh 145 | ``` 146 | 147 | 주의: 스크립트를 실행하기 전에 실행환경을 먼저 확인하세요. 3번째 순서에서 설명한 대로 클러스터에서 kubectl 명령을 올바르게 실행할 수 있어야 합니다. 148 | 149 | #### 네트워크 삭제하기 150 | 151 | 필요한 경우, `deleteNetwork.sh` 스크립트 파일을 실행하여 네트워크를 종료하세요. 이 스크립트는 Kubernetes 클러스터에서 모든 Pod, Job, Deployment 등을 삭제합니다. 152 | 153 | ``` 154 | $ chmod +x deleteNetwork.sh 155 | $ ./deleteNetwork.sh 156 | ``` 157 | 158 | ### 5. 배포된 네트워크 테스트 159 | 160 | `setup_blockchainNetwork.sh` 스크립트 파일 실행이 성공하면 Pod의 상태를 확인합니다. 161 | 162 | ``` 163 | $ kubectl get pods 164 | NAME READY STATUS RESTARTS AGE 165 | blockchain-ca-7848c48d64-2cxr5 1/1 Running 0 4m 166 | blockchain-orderer-596ccc458f-thdgn 1/1 Running 0 4m 167 | blockchain-org1peer1-747d6bdff4-4kzts 1/1 Running 0 4m 168 | blockchain-org2peer1-7794d9b8c5-sn2qf 1/1 Running 0 4m 169 | blockchain-org3peer1-59b6d99c45-dhtbp 1/1 Running 0 4m 170 | blockchain-org4peer1-6b6c99c45-wz9wm 1/1 Running 0 4m 171 | ``` 172 | 173 | 위에서 언급했듯이, 이 스크립트는 모든 피어를 하나의 채널 `channel1`에 연결하고, 그 피어에 체인코드를 설치하여 채널에서 체인코드를 인스턴스화합니다. 이는 모든 피어에 대해 invoke / query 명령을 실행할 수 있음을 의미하며 응답은 모든 피어에서 동일해야 합니다. 이 코드 패턴에서는 손쉬운 진행을 위해 TLS 인증서를 배제하였음을 유의하시기 바랍니다. CLI 명령은 네트워크를 테스트하는데 사용됩니다. 모든 피어에 대해 쿼리를 실행하려면 피어의 bash 셸에서 쿼리를 실행하고 피어 컨테이너에서 나와야 합니다. 174 | 175 | 피어의 bash 쉘에 들어가려면 다음 명령을 사용하세요: 176 | ``` 177 | $ kubectl exec -it bash 178 | ``` 179 | 180 | 피어 컨테이너에서 나가는 명령은 다음과 같습니다: 181 | ``` 182 | # exit 183 | ``` 184 | 185 | **쿼리** 186 | 187 | 체인 코드는 `{a : 100, b : 200}` 값으로 인스턴스화 되었습니다. 체인코드가 제대로 인스턴스화 되었는지 확인하기 위해 `org1peer1`에 쿼리를 요청하여 `a`의 값을 확인해 봅니다. 188 | 189 | ![](images/first-query.png) 190 | 191 | **반영** 192 | 193 | 이제 `org2peer1`에 `a`에서 `b`로 20을 이동하라는 요청을 보냅니다. 새로운 트랜잭션이 생성되고 트랜잭션이 성공적으로 완료되면 상태가 업데이트됩니다. 194 | 195 | ![](images/invoke.png) 196 | 197 | **쿼리** 198 | 199 | 우리의 이전 변경이 제대로 반영되었는지 확인합시다. 우리는 `a`키를 100으로 초기화 하고, 이전 호출로 20을 제거했습니다. 그러므로 `a`에 대한 결과는 80이어야 하며 `b`의 결과는 220이어야 합니다. 이제 아래 그림과 같이 `org3peer1`와 `org4peer1`에 쿼리 요청을 보냅니다. 200 | 201 | ![](images/second-query.png) 202 | 203 | ![](images/third-query.png) 204 | 205 | ### 6. Kubernetes 대시보드 확인 206 | 207 | Kubernetes 대시보드 인증을 위해 다음 명령을 사용하여 토큰을 얻습니다. 208 | 209 | ``` 210 | $ kubectl config view -o jsonpath='{.users[0].user.auth-provider.config.id-token}' 211 | ``` 212 | 213 | 토큰을 복사하고 기본 포트를 8001로 설정하여 Kubernetes 대시보드를 시작합니다. 214 | 215 | ``` 216 | $ kubectl proxy 217 | ``` 218 | 219 | 웹브라우져에서 http://localhost:8001/ui URL을 열어 Kubernetes 대시보드로 이동하면 인증을 요구하는 프롬프트가 표시됩니다. 220 | 221 | ![](images/provide-token-for-dashboard.png) 222 | 223 | 토큰과 `SIGN-IN`을 입력합니다. Workloads탭에서 스크립트를 통해 생성된 리소스를 확인할 수 있습니다. 224 | 225 | ![](images/kubernetes-dashboard.png) 226 | 227 | 이제 Hyperledger Fabric 네트워크가 준비되었습니다. 이 배포된 네트워크에 노드 SDK 또는 Hyperledger Composer를 사용하여 블록체인 애플리케이션을 개발해보세요. 228 | 229 | ## 문제해결 230 | 231 | [DEBUGGING.md 참조](DEBUGGING.md) 232 | 233 | ## 라이센스 234 | 235 | [Apache 2.0](LICENSE) 236 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deploy Hyperledger Fabric network on IBM Cloud 2 | 3 | ### Set up your business network using Kubernetes APIs on IBM Cloud Container Service 4 | 5 | *Read this in other languages: [한국어](README-ko.md).* 6 | 7 | Blockchain is a shared, immutable ledger for recording the history of transactions. The Linux Foundation’s Hyperledger Fabric, the software implementation of blockchain IBM is committed to, is a permissioned network. For developing any blockchain use-case, the very first thing is to have a development environment for Hyperledger Fabric to create and deploy the application. Hyperledger Fabric network can be setup in multiple ways. 8 | * [Hyperledger Fabric network On-Premise](https://hyperledger-fabric.readthedocs.io/en/release-1.0/build_network.html) 9 | * Using [IBM Blockchain Platform](https://cloud.ibm.com/catalog/services/blockchain) hosted on [IBM Cloud](https://cloud.ibm.com/). IBM Cloud provides you Blockchain as a service. 10 | * Hyperledger Fabric network using [Kubernetes APIs]((https://cloud.ibm.com/containers-kubernetes/catalog/cluster)) on [IBM Cloud Kubernetes Service](https://cloud.ibm.com/containers-kubernetes/catalog/cluster) 11 | 12 | This code pattern demonstrates the steps involved in setting up your business network on **Hyperledger Fabric using Kubernetes APIs on IBM Cloud Kubernetes Service**. 13 | 14 | Hosting the Hyperledger Fabric network on IBM Cloud provides you many benefits like multiple users can work on the same setup, the setup can be used for different blockchain applications, the setup can be reused and so on. Please note that the blockchain network setup on Kubernetes is good to use for demo scenarios but for production, it is recommended to use IBM Blockchain Platform hosted on IBM Cloud. 15 | 16 | #### Kubernetes Cluster 17 | 18 | [IBM Cloud Kubernetes Service](https://cloud.ibm.com/containers-kubernetes/catalog/cluster) allows you to create a free cluster that comes with 2 CPUs, 4 GB memory, and 1 worker node. It allows you to get familiar with and test Kubernetes capabilities. However they lack capabilities like persistent NFS file-based storage with volumes. 19 | 20 | To setup your cluster for maximum availability and capacity, IBM Cloud allows you to create a fully customizable, production-ready cluster called _standard cluster_. _Standard clusters_ allow highly available cluster configurations such as a setup with two clusters that run in different regions, each with multiple worker nodes. Please see https://cloud.ibm.com/docs/containers?topic=containers-cs_ov#cluster_types to review other options for highly available cluster configurations. 21 | 22 | This pattern uses a _free cluster_ provided by IBM Cloud and it can be used for proof-of-concept purpose. This pattern provides you the scripts to automate the process for setting up Hyperledger Fabric network using Kubernetes APIs on IBM Cloud. 23 | 24 | When the reader has completed this pattern, they will understand how to: 25 | 26 | * modify configuration files according to their network topology 27 | * deploy the hyperledger fabric network on Kubernetes cluster 28 | 29 | ## Flow 30 | 31 | ![](images/architecture.png) 32 | 33 | 1. Log in to IBM Cloud CLI and initialize IBM Cloud Kubernetes Service plugin. 34 | 2. Set context for Kubernetes cluster using CLI and download Kubernetes configuration files. After downloading configuration files, set KUBECONFIG environment variable. 35 | 3. Run script to deploy your hyperledger fabric network on Kubernetes cluster. 36 | 4. Access Kubernetes dashboard. 37 | 38 | ## Included components 39 | 40 | * [Hyperledger Fabric](https://hyperledger-fabric.readthedocs.io/): Hyperledger Fabric is a platform for distributed ledger solutions underpinned by a modular architecture delivering high degrees of confidentiality, resiliency, flexibility and scalability. 41 | 42 | * [IBM Cloud Kubernetes Service](https://cloud.ibm.com/containers-kubernetes/catalog/cluster): IBM Kubernetes Service enables the orchestration of intelligent scheduling, self-healing, and horizontal scaling. 43 | 44 | ## Featured technologies 45 | 46 | * [Blockchain](https://en.wikipedia.org/wiki/Blockchain): A blockchain is a digitized, decentralized, public ledger of all transactions in a network. 47 | 48 | * [Kubernetes Cluster](https://kubernetes.io/docs/home/): In Kubernetes Engine, a container cluster consists of at least one cluster master and multiple worker machines called nodes. A container cluster is the foundation of Kubernetes Engine. 49 | 50 | ## Watch the Video 51 | 52 | [![](https://img.youtube.com/vi/DFYk6XaMHc0/0.jpg)](https://youtu.be/DFYk6XaMHc0) 53 | 54 | ## Kubernetes Concepts Used 55 | * [Kubernetes Pods](https://kubernetes.io/docs/concepts/workloads/pods/pod/) - Pods represent the smallest deployable units in a Kubernetes cluster and are used to group containers that must be treated as a single unit. 56 | * [Kubernetes Jobs](https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/) - A job creates one or more pods and ensures that a specified number of them successfully terminate. As pods successfully complete, the job tracks the successful completions. 57 | * [Kubernetes Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) - A deployment is a Kubernetes resource where you specify your containers and other Kubernetes resources that are required to run your app, such as persistent storage, services, or annotations. 58 | * [Kubernetes Services](https://kubernetes.io/docs/concepts/services-networking/service/) - A Kubernetes service groups a set of pods and provides network connection to these pods for other services in the cluster without exposing the actual private IP address of each pod. 59 | * [Kubernetes Persistent Volumes (PV)](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) - PersistentVolumes are a way for users to *claim* durable storage such as NFS file storage. 60 | 61 | ### Prerequisites 62 | 63 | - [IBM Cloud account](https://cloud.ibm.com/registration/?target=%2Fdashboard%2Fapps) 64 | - [Node v8.x or greater and npm v5.x or greater](https://nodejs.org/en/download/) 65 | 66 | 67 | ## Steps 68 | 69 | Follow these steps to setup and run this code pattern. 70 | 71 | 1. [Create a Kubernetes Cluster on IBM Cloud](#1-create-a-kubernetes-cluster-on-ibm-cloud) 72 | 2. [Setting up CLIs](#2-setting-up-clis) 73 | 3. [Gain access to your Kubernetes Cluster](#3-gain-access-to-your-kubernetes-cluster) 74 | 4. [Deploy Hyperledger Fabric Network into Kubernetes Cluster](#4-deploy-hyperledger-fabric-network-into-kubernetes-cluster) 75 | 5. [Test the deployed network](#5-test-the-deployed-network) 76 | 6. [View the Kubernetes Dashboard](#6-view-the-kubernetes-dashboard) 77 | 7. [Connect the network using client SDK](#7-connect-the-network-using-client-sdk) 78 | 79 | ### 1. Create a Kubernetes Cluster on IBM Cloud 80 | 81 | * Create a Kubernetes cluster with [IBM Cloud Kubernetes Service](https://cloud.ibm.com/containers-kubernetes/catalog/cluster) using GUI. This pattern uses the _free cluster_. 82 | 83 | ![](images/create-service.png) 84 | 85 | Note: It can take up to 15 minutes for the cluster to be set up and provisioned. 86 | 87 | 88 | ### 2. Setting up CLIs 89 | 90 | * Install [IBM Cloud CLI](https://cloud.ibm.com/docs/cli?topic=cloud-cli-install-ibmcloud-cli). The prefix for running commands by using the Bluemix CLI is `ibmcloud`. 91 | 92 | * Install [Kubernetes CLI](https://kubernetes.io/docs/tasks/tools/install-kubectl/). The prefix for running commands by using the Kubernetes CLI is `kubectl`. 93 | 94 | * Install the kubernetes service plugin using the following command 95 | `ibmcloud plugin install container-service -r Bluemix` 96 | 97 | 98 | ### 3. Gain access to your Kubernetes Cluster 99 | 100 | Access the [IBM Cloud Dashboard](https://cloud.ibm.com/dashboard/apps). Choose the same cloud foundry org and cloud 101 | foundry space where cluster is created. 102 | 103 | * Check the status of your cluster `IBM Cloud Dashboard -> -> Worker Nodes`. If status is not `normal`, then 104 | you need to wait for some more time to proceed further. 105 | 106 | ![](images/cluster-status.png) 107 | 108 | * Once your cluster is ready, open the access tab `IBM Cloud Dashboard -> -> Access` as shown in snapshot. 109 | 110 | ![](images/gain-access-to-cluster.png) 111 | 112 | * Perform the steps provided under the section `Gain access to your cluster`. 113 | 114 | * Verify that the kubectl commands run properly with your cluster by checking the Kubernetes CLI server version. 115 | 116 | ``` 117 | $ kubectl version --short 118 | Client Version: v1.14.6 119 | Server Version: v1.16.8+IKS 120 | ``` 121 | 122 | ### 4. Deploy Hyperledger Fabric Network into Kubernetes Cluster 123 | 124 | #### Understand the network topology 125 | 126 | This pattern provides a script which automatically provisions a sample Hyperledger Fabric network consisting of four organizations, each maintaining one peer node, and a 'solo' ordering service. Also, the script creates a channel named as `channel1`, joins all peers to the channel `channel1`, install chaincode on all peers and instantiate chaincode on channel. The pattern also helps to drive execution of transactions against the deployed chaincode. 127 | 128 | #### Copy Kubernetes configuration scripts 129 | 130 | Clone or download the Kubernetes configuration scripts to your user home directory. 131 | ``` 132 | $ git clone https://github.com/IBM/blockchain-network-on-kubernetes 133 | ``` 134 | 135 | Navigate to the source directory 136 | ``` 137 | $ cd blockchain-network-on-kubernetes 138 | $ ls 139 | ``` 140 | In the source directory, 141 | * `configFiles` contains Kubernetes configuration files 142 | * `artifacts` contains the network configuration files 143 | * `*.sh` scripts to deploy and delete the network 144 | 145 | #### Modify the Kubernetes configuration scripts 146 | 147 | If there is any change in network topology, need to modify the configuration files (.yaml files) appropriately. The configuration files are located in `artifacts` and `configFiles` directory. For example, if you decide to increase/decrease the capacity of persistent volume then you need to modify `createVolume.yaml`. 148 | 149 | The Kubernetes Server version v1.11.x or above uses `containerd` as its container runtime therefore using `docker.sock` of the worker node is not possible. You need to deploy and use a Docker daemon in a container. In case, your Kubernetes server version is smaller than 1.11.x then you need to modify the `configFiles/peersDeployment.yaml` file to point to a Docker service. Change instances of `tcp://docker:2375` to `unix:///host/var/run/docker.sock` with a text editor. 150 | 151 | #### Run the script to deploy your Hyperledger Fabric Network 152 | 153 | Once you have completed the changes (if any) in configuration files, you are ready to deploy your network. 154 | 155 | Check your kubectl CLI version as: 156 | 157 | ``` 158 | $ kubectl version --short 159 | ``` 160 | 161 | This command will give you `Client Version` and `Server Version`. 162 | If the `Client version > v1.11.x` i.e. 1.12.x or more then use `setup_blockchainNetwork_v2.sh` to set up the network. Run the following command: 163 | 164 | ``` 165 | cp setup_blockchainNetwork_v2.sh setup_blockchainNetwork.sh 166 | ``` 167 | 168 | If the `Client version <= v1.11.x` then use `setup_blockchainNetwork_v1.sh` to setup the network. Copy the script as shown. 169 | ``` 170 | cp setup_blockchainNetwork_v1.sh setup_blockchainNetwork.sh 171 | ``` 172 | 173 | Now execute the script to deploy your hyperledger fabric network. 174 | 175 | ``` 176 | $ chmod +x setup_blockchainNetwork.sh 177 | $ ./setup_blockchainNetwork.sh 178 | ``` 179 | 180 | > If you are using a Standard IKS cluster with multiple workers nodes, do `./setup_blockchainNetwork.sh --paid` so that the shared volume of the blockchain containers would work properly. 181 | 182 | Note: Before running the script, please check your environment. You should able to run `kubectl commands` properly with your cluster as explained in step 3. 183 | 184 | #### Delete the network 185 | 186 | If required, you can bring your hyperledger fabric network down using the script `deleteNetwork.sh`. This script will delete all your pods, jobs, deployments etc. from your Kubernetes cluster. 187 | 188 | ``` 189 | $ chmod +x deleteNetwork.sh 190 | $ ./deleteNetwork.sh 191 | ``` 192 | 193 | ### 5. Test the deployed network 194 | 195 | After successful execution of the script `setup_blockchainNetwork.sh`, check the status of pods. 196 | 197 | ``` 198 | $ kubectl get pods 199 | NAME READY STATUS RESTARTS AGE 200 | blockchain-ca-7848c48d64-2cxr5 1/1 Running 0 4m 201 | blockchain-orderer-596ccc458f-thdgn 1/1 Running 0 4m 202 | blockchain-org1peer1-747d6bdff4-4kzts 1/1 Running 0 4m 203 | blockchain-org2peer1-7794d9b8c5-sn2qf 1/1 Running 0 4m 204 | blockchain-org3peer1-59b6d99c45-dhtbp 1/1 Running 0 4m 205 | blockchain-org4peer1-6b6c99c45-wz9wm 1/1 Running 0 4m 206 | ``` 207 | 208 | As mentioned above, the script joins all peers on one channel `channel1`, install chaincode on all peers and instantiate chaincode on channel. It means we can execute an invoke/query command on any peer and the response should be same on all peers. Please note that in this pattern tls certs are disabled to avoid complexity. In this pattern, the CLI commands are used to test the network. For running a query against any peer, need to get into a bash shell of a peer, run the query and exit from the peer container. 209 | 210 | Use the following command to get into a bash shell of a peer: 211 | 212 | ``` 213 | $ kubectl exec -it bash 214 | ``` 215 | 216 | And the command to be used to exit from the peer container is: 217 | 218 | ``` 219 | # exit 220 | ``` 221 | 222 | **Note:** Stay logged into your peer to complete these commands. 223 | 224 | **Query** 225 | 226 | Chaincode was instantiated with the values as `{ a: 100, b: 200 }`. Let’s query to `org1peer1` for the value of `a` to make sure the chaincode was properly instantiated. 227 | ``` 228 | peer chaincode query -C channel1 -n cc -c '{"Args":["query","a"]}' 229 | ``` 230 | 231 | ![](images/first-query.png) 232 | 233 | **Invoke** 234 | 235 | Now let’s submit a request to `org2peer1` to move 20 from `a` to `b`. A new transaction will be generated and upon successful completion of transaction, state will get updated. 236 | ``` 237 | peer chaincode invoke -o blockchain-orderer:31010 -C channel1 -n cc -c '{"Args":["invoke","a","b","20"]}' 238 | ``` 239 | 240 | ![](images/invoke.png) 241 | 242 | **Query** 243 | 244 | Let’s confirm that our previous invocation executed properly. We initialized the key `a` with a value of 100 and just removed 20 with our previous invocation. Therefore, a query against `a` should show 80 and a query against `b` should show 220. Now issue the query request to `org3peer1` and `org4peer1` as shown. 245 | ``` 246 | peer chaincode query -C channel1 -n cc -c '{"Args":["query","a"]}' 247 | peer chaincode query -C channel1 -n cc -c '{"Args":["query","b"]}' 248 | ``` 249 | 250 | ![](images/second-query.png) 251 | 252 | ![](images/third-query.png) 253 | 254 | ### 6. View the Kubernetes Dashboard 255 | 256 | Go to the `IBM Cloud dashboard -> Clusters -> ` 257 | 258 | Click on the button entitled `Kubernetes Dashboard`, 259 | 260 | ![](images/kdashboardonibmcloud.png) 261 | 262 | you will see the dashboard as shown. 263 | 264 | ![](images/kubernetes-dashboard.png) 265 | 266 | The hyperledger fabric network is ready to use. You can start developing your blockchain applications using node sdk for this deployed network. 267 | 268 | ### 7. Connect the network using client SDK 269 | 270 | To develop your blockchain application on this deployed network, you need to connect to this network using client SDK. To connect to the network: 271 | 272 | * Get the public IP of your kubernetes cluster from IBM Cloud Dashboard. 273 | * Connect using this public IP and the ports exposed using [services](https://github.com/IBM/blockchain-network-on-kubernetes/blob/master/configFiles/blockchain-services.yaml). 274 | For example: The node port for CA is `30054` hence CA Client url will be `http://< public IP of your cluster >:30054/` 275 | 276 | In this way, the CA client using node SDK can be created as: 277 | 278 | ``` 279 | fabric_ca_client = new Fabric_CA_Client('http://< public IP of your cluster >:30054/', tlsOptions , 'CA1', crypto_suite); 280 | ``` 281 | Similarly the following code can be used to setup the fabric network. 282 | 283 | ``` 284 | // setup the fabric network 285 | var fabric_client = new Fabric_Client(); 286 | 287 | var channel = fabric_client.newChannel('channel1'); 288 | var peer = fabric_client.newPeer('grpc://< public IP of your cluster >:30110'); 289 | channel.addPeer(peer); 290 | var order = fabric_client.newOrderer('grpc://< public IP of your cluster >:31010') 291 | channel.addOrderer(order); 292 | ``` 293 | 294 | ## Troubleshooting 295 | 296 | [See DEBUGGING.md.](DEBUGGING.md) 297 | 298 | ## Reference Links 299 | 300 | * [Hyperledger Fabric](https://hyperledger-fabric.readthedocs.io/en/release-1.1/) 301 | * [Kubernetes Concepts](https://kubernetes.io/docs/concepts/) 302 | 303 | ## License 304 | 305 | This code pattern is licensed under the Apache Software License, Version 2. Separate third party code objects invoked within this code pattern are licensed by their respective providers pursuant to their own separate licenses. Contributions are subject to the [Developer Certificate of Origin, Version 1.1 (DCO)](https://developercertificate.org/) and the [Apache Software License, Version 2](https://www.apache.org/licenses/LICENSE-2.0.txt). 306 | 307 | [Apache Software License (ASL) FAQ](https://www.apache.org/foundation/license-faq.html#WhatDoesItMEAN) 308 | -------------------------------------------------------------------------------- /artifacts/chaincode/chaincode_example02/chaincode_example02.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright IBM Corp. 2016 All Rights Reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | //WARNING - this chaincode's ID is hard-coded in chaincode_example04 to illustrate one way of 20 | //calling chaincode from a chaincode. If this example is modified, chaincode_example04.go has 21 | //to be modified as well with the new ID of chaincode_example02. 22 | //chaincode_example05 show's how chaincode ID can be passed in as a parameter instead of 23 | //hard-coding. 24 | 25 | import ( 26 | "fmt" 27 | "strconv" 28 | 29 | "github.com/hyperledger/fabric/core/chaincode/shim" 30 | pb "github.com/hyperledger/fabric/protos/peer" 31 | ) 32 | 33 | // SimpleChaincode example simple Chaincode implementation 34 | type SimpleChaincode struct { 35 | } 36 | 37 | func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { 38 | fmt.Println("ex02 Init") 39 | _, args := stub.GetFunctionAndParameters() 40 | var A, B string // Entities 41 | var Aval, Bval int // Asset holdings 42 | var err error 43 | 44 | if len(args) != 4 { 45 | return shim.Error("Incorrect number of arguments. Expecting 4") 46 | } 47 | 48 | // Initialize the chaincode 49 | A = args[0] 50 | Aval, err = strconv.Atoi(args[1]) 51 | if err != nil { 52 | return shim.Error("Expecting integer value for asset holding") 53 | } 54 | B = args[2] 55 | Bval, err = strconv.Atoi(args[3]) 56 | if err != nil { 57 | return shim.Error("Expecting integer value for asset holding") 58 | } 59 | fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval) 60 | 61 | // Write the state to the ledger 62 | err = stub.PutState(A, []byte(strconv.Itoa(Aval))) 63 | if err != nil { 64 | return shim.Error(err.Error()) 65 | } 66 | 67 | err = stub.PutState(B, []byte(strconv.Itoa(Bval))) 68 | if err != nil { 69 | return shim.Error(err.Error()) 70 | } 71 | 72 | return shim.Success(nil) 73 | } 74 | 75 | func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { 76 | fmt.Println("ex02 Invoke") 77 | function, args := stub.GetFunctionAndParameters() 78 | if function == "invoke" { 79 | // Make payment of X units from A to B 80 | return t.invoke(stub, args) 81 | } else if function == "delete" { 82 | // Deletes an entity from its state 83 | return t.delete(stub, args) 84 | } else if function == "query" { 85 | // the old "Query" is now implemtned in invoke 86 | return t.query(stub, args) 87 | } 88 | 89 | return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"") 90 | } 91 | 92 | // Transaction makes payment of X units from A to B 93 | func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response { 94 | var A, B string // Entities 95 | var Aval, Bval int // Asset holdings 96 | var X int // Transaction value 97 | var err error 98 | 99 | if len(args) != 3 { 100 | return shim.Error("Incorrect number of arguments. Expecting 3") 101 | } 102 | 103 | A = args[0] 104 | B = args[1] 105 | 106 | // Get the state from the ledger 107 | // TODO: will be nice to have a GetAllState call to ledger 108 | Avalbytes, err := stub.GetState(A) 109 | if err != nil { 110 | return shim.Error("Failed to get state") 111 | } 112 | if Avalbytes == nil { 113 | return shim.Error("Entity not found") 114 | } 115 | Aval, _ = strconv.Atoi(string(Avalbytes)) 116 | 117 | Bvalbytes, err := stub.GetState(B) 118 | if err != nil { 119 | return shim.Error("Failed to get state") 120 | } 121 | if Bvalbytes == nil { 122 | return shim.Error("Entity not found") 123 | } 124 | Bval, _ = strconv.Atoi(string(Bvalbytes)) 125 | 126 | // Perform the execution 127 | X, err = strconv.Atoi(args[2]) 128 | if err != nil { 129 | return shim.Error("Invalid transaction amount, expecting a integer value") 130 | } 131 | Aval = Aval - X 132 | Bval = Bval + X 133 | fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval) 134 | 135 | // Write the state back to the ledger 136 | err = stub.PutState(A, []byte(strconv.Itoa(Aval))) 137 | if err != nil { 138 | return shim.Error(err.Error()) 139 | } 140 | 141 | err = stub.PutState(B, []byte(strconv.Itoa(Bval))) 142 | if err != nil { 143 | return shim.Error(err.Error()) 144 | } 145 | 146 | return shim.Success(nil) 147 | } 148 | 149 | // Deletes an entity from state 150 | func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response { 151 | if len(args) != 1 { 152 | return shim.Error("Incorrect number of arguments. Expecting 1") 153 | } 154 | 155 | A := args[0] 156 | 157 | // Delete the key from the state in ledger 158 | err := stub.DelState(A) 159 | if err != nil { 160 | return shim.Error("Failed to delete state") 161 | } 162 | 163 | return shim.Success(nil) 164 | } 165 | 166 | // query callback representing the query of a chaincode 167 | func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response { 168 | var A string // Entities 169 | var err error 170 | 171 | if len(args) != 1 { 172 | return shim.Error("Incorrect number of arguments. Expecting name of the person to query") 173 | } 174 | 175 | A = args[0] 176 | 177 | // Get the state from the ledger 178 | Avalbytes, err := stub.GetState(A) 179 | if err != nil { 180 | jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}" 181 | return shim.Error(jsonResp) 182 | } 183 | 184 | if Avalbytes == nil { 185 | jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}" 186 | return shim.Error(jsonResp) 187 | } 188 | 189 | jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}" 190 | fmt.Printf("Query Response:%s\n", jsonResp) 191 | return shim.Success(Avalbytes) 192 | } 193 | 194 | func main() { 195 | err := shim.Start(new(SimpleChaincode)) 196 | if err != nil { 197 | fmt.Printf("Error starting Simple chaincode: %s", err) 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /artifacts/configtx.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | ################################################################################ 3 | # 4 | # Section: Organizations 5 | # 6 | # - This section defines the different organizational identities which will 7 | # be referenced later in the configuration. 8 | # 9 | ################################################################################ 10 | Organizations: 11 | 12 | # SampleOrg defines an MSP using the sampleconfig. It should never be used 13 | # in production but may be used as a template for other definitions 14 | - &OrdererOrg 15 | # DefaultOrg defines the organization which is used in the sampleconfig 16 | # of the fabric.git development environment 17 | Name: OrdererOrg 18 | 19 | # ID to load the MSP definition as 20 | ID: OrdererMSP 21 | 22 | # MSPDir is the filesystem path which contains the MSP configuration 23 | MSPDir: crypto-config/ordererOrganizations/example.com/msp 24 | 25 | # AdminPrincipal dictates the type of principal used for an organization's Admins policy 26 | # Today, only the values of Role.ADMIN ad Role.MEMBER are accepted, which indicates a principal 27 | # of role type ADMIN and role type MEMBER respectively 28 | AdminPrincipal: Role.MEMBER 29 | 30 | - &Org1 31 | # DefaultOrg defines the organization which is used in the sampleconfig 32 | # of the fabric.git development environment 33 | Name: Org1MSP 34 | 35 | # ID to load the MSP definition as 36 | ID: Org1MSP 37 | 38 | MSPDir: crypto-config/peerOrganizations/org1.example.com/msp 39 | 40 | # AdminPrincipal dictates the type of principal used for an organization's Admins policy 41 | # Today, only the values of Role.ADMIN ad Role.MEMBER are accepted, which indicates a principal 42 | # of role type ADMIN and role type MEMBER respectively 43 | AdminPrincipal: Role.MEMBER 44 | 45 | AnchorPeers: 46 | # AnchorPeers defines the location of peers which can be used 47 | # for cross org gossip communication. Note, this value is only 48 | # encoded in the genesis block in the Application section context 49 | - Host: blockchain-org1peer1 50 | Port: 30110 51 | 52 | - &Org2 53 | # DefaultOrg defines the organization which is used in the sampleconfig 54 | # of the fabric.git development environment 55 | Name: Org2MSP 56 | 57 | # ID to load the MSP definition as 58 | ID: Org2MSP 59 | 60 | MSPDir: crypto-config/peerOrganizations/org2.example.com/msp 61 | 62 | # AdminPrincipal dictates the type of principal used for an organization's Admins policy 63 | # Today, only the values of Role.ADMIN ad Role.MEMBER are accepted, which indicates a principal 64 | # of role type ADMIN and role type MEMBER respectively 65 | AdminPrincipal: Role.MEMBER 66 | 67 | AnchorPeers: 68 | # AnchorPeers defines the location of peers which can be used 69 | # for cross org gossip communication. Note, this value is only 70 | # encoded in the genesis block in the Application section context 71 | - Host: blockchain-org2peer1 72 | Port: 30210 73 | 74 | - &Org3 75 | # DefaultOrg defines the organization which is used in the sampleconfig 76 | # of the fabric.git development environment 77 | Name: Org3MSP 78 | 79 | # ID to load the MSP definition as 80 | ID: Org3MSP 81 | 82 | MSPDir: crypto-config/peerOrganizations/org3.example.com/msp 83 | 84 | # AdminPrincipal dictates the type of principal used for an organization's Admins policy 85 | # Today, only the values of Role.ADMIN ad Role.MEMBER are accepted, which indicates a principal 86 | # of role type ADMIN and role type MEMBER respectively 87 | AdminPrincipal: Role.MEMBER 88 | 89 | AnchorPeers: 90 | # AnchorPeers defines the location of peers which can be used 91 | # for cross org gossip communication. Note, this value is only 92 | # encoded in the genesis block in the Application section context 93 | - Host: blockchain-org3peer1 94 | Port: 30310 95 | 96 | - &Org4 97 | # DefaultOrg defines the organization which is used in the sampleconfig 98 | # of the fabric.git development environment 99 | Name: Org4MSP 100 | 101 | # ID to load the MSP definition as 102 | ID: Org4MSP 103 | 104 | MSPDir: crypto-config/peerOrganizations/org4.example.com/msp 105 | 106 | # AdminPrincipal dictates the type of principal used for an organization's Admins policy 107 | # Today, only the values of Role.ADMIN ad Role.MEMBER are accepted, which indicates a principal 108 | # of role type ADMIN and role type MEMBER respectively 109 | AdminPrincipal: Role.MEMBER 110 | 111 | AnchorPeers: 112 | # AnchorPeers defines the location of peers which can be used 113 | # for cross org gossip communication. Note, this value is only 114 | # encoded in the genesis block in the Application section context 115 | - Host: blockchain-org4peer1 116 | Port: 30410 117 | 118 | ################################################################################ 119 | # 120 | # SECTION: Orderer 121 | # 122 | # - This section defines the values to encode into a config transaction or 123 | # genesis block for orderer related parameters 124 | # 125 | ################################################################################ 126 | Orderer: &OrdererDefaults 127 | 128 | # Orderer Type: The orderer implementation to start 129 | # Available types are "solo" and "kafka" 130 | OrdererType: solo 131 | 132 | Addresses: 133 | - blockchain-orderer:31010 134 | 135 | # Batch Timeout: The amount of time to wait before creating a batch 136 | BatchTimeout: 2s 137 | 138 | # Batch Size: Controls the number of messages batched into a block 139 | BatchSize: 140 | 141 | # Max Message Count: The maximum number of messages to permit in a batch 142 | MaxMessageCount: 10 143 | 144 | # Absolute Max Bytes: The absolute maximum number of bytes allowed for 145 | # the serialized messages in a batch. 146 | AbsoluteMaxBytes: 99 MB 147 | 148 | # Preferred Max Bytes: The preferred maximum number of bytes allowed for 149 | # the serialized messages in a batch. A message larger than the preferred 150 | # max bytes will result in a batch larger than preferred max bytes. 151 | PreferredMaxBytes: 512 KB 152 | 153 | Kafka: 154 | # Brokers: A list of Kafka brokers to which the orderer connects 155 | # NOTE: Use IP:port notation 156 | Brokers: 157 | - 127.0.0.1:9092 158 | 159 | # Organizations is the list of orgs which are defined as participants on 160 | # the orderer side of the network 161 | Organizations: 162 | 163 | ################################################################################ 164 | # 165 | # SECTION: Application 166 | # 167 | # - This section defines the values to encode into a config transaction or 168 | # genesis block for application related parameters 169 | # 170 | ################################################################################ 171 | Application: &ApplicationDefaults 172 | 173 | # Organizations is the list of orgs which are defined as participants on 174 | # the application side of the network 175 | Organizations: 176 | 177 | ################################################################################ 178 | # 179 | # Profile 180 | # 181 | # - Different configuration profiles may be encoded here to be specified 182 | # as parameters to the configtxgen tool 183 | # 184 | ################################################################################ 185 | Profiles: 186 | 187 | FourOrgsOrdererGenesis: 188 | Orderer: 189 | <<: *OrdererDefaults 190 | Organizations: 191 | - *OrdererOrg 192 | Consortiums: 193 | SampleConsortium: 194 | Organizations: 195 | - *Org1 196 | - *Org2 197 | - *Org3 198 | - *Org4 199 | FourOrgsChannel: 200 | Consortium: SampleConsortium 201 | Application: 202 | <<: *ApplicationDefaults 203 | Organizations: 204 | - *Org1 205 | - *Org2 206 | - *Org3 207 | - *Org4 208 | -------------------------------------------------------------------------------- /artifacts/crypto-config.yaml: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------- 2 | # "OrdererOrgs" - Definition of organizations managing orderer nodes 3 | # --------------------------------------------------------------------------- 4 | OrdererOrgs: 5 | # --------------------------------------------------------------------------- 6 | # Orderer 7 | # --------------------------------------------------------------------------- 8 | - Name: Orderer 9 | Domain: example.com 10 | # --------------------------------------------------------------------------- 11 | # "Specs" - See PeerOrgs below for complete description 12 | # --------------------------------------------------------------------------- 13 | Specs: 14 | - Hostname: orderer 15 | # --------------------------------------------------------------------------- 16 | # "PeerOrgs" - Definition of organizations managing peer nodes 17 | # --------------------------------------------------------------------------- 18 | PeerOrgs: 19 | # --------------------------------------------------------------------------- 20 | # Org1 21 | # --------------------------------------------------------------------------- 22 | - Name: Org1 23 | Domain: org1.example.com 24 | # --------------------------------------------------------------------------- 25 | # "Specs" 26 | # --------------------------------------------------------------------------- 27 | # Uncomment this section to enable the explicit definition of hosts in your 28 | # configuration. Most users will want to use Template, below 29 | # 30 | # Specs is an array of Spec entries. Each Spec entry consists of two fields: 31 | # - Hostname: (Required) The desired hostname, sans the domain. 32 | # - CommonName: (Optional) Specifies the template or explicit override for 33 | # the CN. By default, this is the template: 34 | # 35 | # "{{.Hostname}}.{{.Domain}}" 36 | # 37 | # which obtains its values from the Spec.Hostname and 38 | # Org.Domain, respectively. 39 | # --------------------------------------------------------------------------- 40 | # Specs: 41 | # - Hostname: foo # implicitly "foo.org1.example.com" 42 | # CommonName: foo27.org5.example.com # overrides Hostname-based FQDN set above 43 | # - Hostname: bar 44 | # - Hostname: baz 45 | # --------------------------------------------------------------------------- 46 | # "Template" 47 | # --------------------------------------------------------------------------- 48 | # Allows for the definition of 1 or more hosts that are created sequentially 49 | # from a template. By default, this looks like "peer%d" from 0 to Count-1. 50 | # You may override the number of nodes (Count), the starting index (Start) 51 | # or the template used to construct the name (Hostname). 52 | # 53 | # Note: Template and Specs are not mutually exclusive. You may define both 54 | # sections and the aggregate nodes will be created for you. Take care with 55 | # name collisions 56 | # --------------------------------------------------------------------------- 57 | Template: 58 | Count: 2 59 | # Start: 5 60 | # Hostname: {{.Prefix}}{{.Index}} # default 61 | # --------------------------------------------------------------------------- 62 | # "Users" 63 | # --------------------------------------------------------------------------- 64 | # Count: The number of user accounts _in addition_ to Admin 65 | # --------------------------------------------------------------------------- 66 | Users: 67 | Count: 1 68 | # --------------------------------------------------------------------------- 69 | # Org2: See "Org1" for full specification 70 | # --------------------------------------------------------------------------- 71 | - Name: Org2 72 | Domain: org2.example.com 73 | Template: 74 | Count: 2 75 | Users: 76 | Count: 1 77 | # --------------------------------------------------------------------------- 78 | # Org3: See "Org1" for full specification 79 | # --------------------------------------------------------------------------- 80 | - Name: Org3 81 | Domain: org3.example.com 82 | Template: 83 | Count: 2 84 | Users: 85 | Count: 1 86 | # --------------------------------------------------------------------------- 87 | # Org4: See "Org1" for full specification 88 | # --------------------------------------------------------------------------- 89 | - Name: Org4 90 | Domain: org4.example.com 91 | Template: 92 | Count: 2 93 | Users: 94 | Count: 1 -------------------------------------------------------------------------------- /configFiles/blockchain-services.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: blockchain-ca 6 | labels: 7 | run: blockchain-ca 8 | spec: 9 | type: NodePort 10 | selector: 11 | name: ca 12 | ports: 13 | - protocol: TCP 14 | nodePort: 30054 15 | targetPort: 7054 16 | port: 30054 17 | name: grpc 18 | --- 19 | apiVersion: v1 20 | kind: Service 21 | metadata: 22 | name: blockchain-orderer 23 | labels: 24 | run: blockchain-orderer 25 | spec: 26 | type: NodePort 27 | selector: 28 | name: orderer 29 | ports: 30 | - protocol: TCP 31 | nodePort: 31010 32 | targetPort: 31010 33 | port: 31010 34 | name: grpc 35 | --- 36 | apiVersion: v1 37 | kind: Service 38 | metadata: 39 | name: blockchain-org1peer1 40 | labels: 41 | run: blockchain-org1peer1 42 | spec: 43 | type: NodePort 44 | selector: 45 | name: org1peer1 46 | ports: 47 | - protocol: TCP 48 | nodePort: 30110 49 | targetPort: 30110 50 | port: 30110 51 | name: grpc 52 | - protocol: TCP 53 | nodePort: 30111 54 | targetPort: 30111 55 | port: 30111 56 | name: events 57 | --- 58 | apiVersion: v1 59 | kind: Service 60 | metadata: 61 | name: blockchain-org2peer1 62 | labels: 63 | run: blockchain-org2peer1 64 | spec: 65 | type: NodePort 66 | selector: 67 | name: org2peer1 68 | ports: 69 | - protocol: TCP 70 | nodePort: 30210 71 | targetPort: 30210 72 | port: 30210 73 | name: grpc 74 | - protocol: TCP 75 | nodePort: 30211 76 | targetPort: 30211 77 | port: 30211 78 | name: events 79 | 80 | --- 81 | apiVersion: v1 82 | kind: Service 83 | metadata: 84 | name: blockchain-org3peer1 85 | labels: 86 | run: blockchain-org3peer1 87 | spec: 88 | type: NodePort 89 | selector: 90 | name: org3peer1 91 | ports: 92 | - protocol: TCP 93 | nodePort: 30310 94 | targetPort: 30310 95 | port: 30310 96 | name: grpc 97 | - protocol: TCP 98 | nodePort: 30311 99 | targetPort: 30311 100 | port: 30311 101 | name: events 102 | 103 | --- 104 | apiVersion: v1 105 | kind: Service 106 | metadata: 107 | name: blockchain-org4peer1 108 | labels: 109 | run: blockchain-org4peer1 110 | spec: 111 | type: NodePort 112 | selector: 113 | name: org4peer1 114 | ports: 115 | - protocol: TCP 116 | nodePort: 30410 117 | targetPort: 30410 118 | port: 30410 119 | name: grpc 120 | - protocol: TCP 121 | nodePort: 30411 122 | targetPort: 30411 123 | port: 30411 124 | name: events -------------------------------------------------------------------------------- /configFiles/chaincode_install.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: batch/v1 3 | kind: Job 4 | metadata: 5 | name: chaincodeinstall 6 | spec: 7 | backoffLimit: 1 8 | template: 9 | metadata: 10 | name: chaincodeinstall 11 | spec: 12 | restartPolicy: "Never" 13 | volumes: 14 | - name: sharedvolume 15 | persistentVolumeClaim: 16 | claimName: shared-pvc 17 | containers: 18 | - name: chaincodeinstall1 19 | image: hyperledger/fabric-tools:1.4 20 | imagePullPolicy: Always 21 | command: ["sh", "-c", "echo $GOPATH; cp -r /shared/artifacts/chaincode $GOPATH/src/; ls $GOPATH/src; peer chaincode install -n ${CHAINCODE_NAME} -v ${CHAINCODE_VERSION} -p chaincode_example02/"] 22 | env: 23 | - name: CHAINCODE_NAME 24 | value: "cc" 25 | - name: CHAINCODE_VERSION 26 | value: "1.0" 27 | - name: FABRIC_CFG_PATH 28 | value: /etc/hyperledger/fabric 29 | - name: CORE_PEER_MSPCONFIGPATH 30 | value: /shared/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 31 | - name: CORE_PEER_LOCALMSPID 32 | value: Org1MSP 33 | - name: CORE_PEER_ADDRESS 34 | value: blockchain-org1peer1:30110 35 | - name: GODEBUG 36 | value: "netdns=go" 37 | volumeMounts: 38 | - mountPath: /shared 39 | name: sharedvolume 40 | 41 | - name: chaincodeinstall2 42 | image: hyperledger/fabric-tools:1.4 43 | imagePullPolicy: Always 44 | command: ["sh", "-c", "echo $GOPATH; cp -r /shared/artifacts/chaincode $GOPATH/src/; ls $GOPATH/src; peer chaincode install -n ${CHAINCODE_NAME} -v ${CHAINCODE_VERSION} -p chaincode_example02/"] 45 | env: 46 | - name: CHAINCODE_NAME 47 | value: "cc" 48 | - name: CHAINCODE_VERSION 49 | value: "1.0" 50 | - name: FABRIC_CFG_PATH 51 | value: /etc/hyperledger/fabric 52 | - name: CORE_PEER_MSPCONFIGPATH 53 | value: /shared/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp 54 | - name: CORE_PEER_LOCALMSPID 55 | value: Org2MSP 56 | - name: CORE_PEER_ADDRESS 57 | value: blockchain-org2peer1:30210 58 | - name: GODEBUG 59 | value: "netdns=go" 60 | volumeMounts: 61 | - mountPath: /shared 62 | name: sharedvolume 63 | 64 | - name: chaincodeinstall3 65 | image: hyperledger/fabric-tools:1.4 66 | imagePullPolicy: Always 67 | command: ["sh", "-c", "echo $GOPATH; cp -r /shared/artifacts/chaincode $GOPATH/src/; ls $GOPATH/src; peer chaincode install -n ${CHAINCODE_NAME} -v ${CHAINCODE_VERSION} -p chaincode_example02/"] 68 | env: 69 | - name: CHAINCODE_NAME 70 | value: "cc" 71 | - name: CHAINCODE_VERSION 72 | value: "1.0" 73 | - name: FABRIC_CFG_PATH 74 | value: /etc/hyperledger/fabric 75 | - name: CORE_PEER_MSPCONFIGPATH 76 | value: /shared/crypto-config/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp 77 | - name: CORE_PEER_LOCALMSPID 78 | value: Org3MSP 79 | - name: CORE_PEER_ADDRESS 80 | value: blockchain-org3peer1:30310 81 | - name: GODEBUG 82 | value: "netdns=go" 83 | volumeMounts: 84 | - mountPath: /shared 85 | name: sharedvolume 86 | 87 | - name: chaincodeinstall4 88 | image: hyperledger/fabric-tools:1.4 89 | imagePullPolicy: Always 90 | command: ["sh", "-c", "echo $GOPATH; cp -r /shared/artifacts/chaincode $GOPATH/src/; ls $GOPATH/src; peer chaincode install -n ${CHAINCODE_NAME} -v ${CHAINCODE_VERSION} -p chaincode_example02/"] 91 | env: 92 | - name: CHAINCODE_NAME 93 | value: "cc" 94 | - name: CHAINCODE_VERSION 95 | value: "1.0" 96 | - name: FABRIC_CFG_PATH 97 | value: /etc/hyperledger/fabric 98 | - name: CORE_PEER_MSPCONFIGPATH 99 | value: /shared/crypto-config/peerOrganizations/org4.example.com/users/Admin@org4.example.com/msp 100 | - name: CORE_PEER_LOCALMSPID 101 | value: Org4MSP 102 | - name: CORE_PEER_ADDRESS 103 | value: blockchain-org4peer1:30410 104 | - name: GODEBUG 105 | value: "netdns=go" 106 | volumeMounts: 107 | - mountPath: /shared 108 | name: sharedvolume 109 | -------------------------------------------------------------------------------- /configFiles/chaincode_instantiate.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: batch/v1 3 | kind: Job 4 | metadata: 5 | name: chaincodeinstantiate 6 | spec: 7 | backoffLimit: 1 8 | template: 9 | metadata: 10 | name: chaincodeinstantiate 11 | spec: 12 | restartPolicy: "Never" 13 | volumes: 14 | - name: sharedvolume 15 | persistentVolumeClaim: 16 | claimName: shared-pvc 17 | 18 | containers: 19 | - name: chaincodeinstantiate 20 | image: hyperledger/fabric-tools:1.4 21 | imagePullPolicy: Always 22 | command: ["sh", "-c", "peer chaincode instantiate -o blockchain-orderer:31010 -C ${CHANNEL_NAME} -n ${CHAINCODE_NAME} -v ${CHAINCODE_VERSION} -c '{\"Args\":[\"init\",\"a\",\"100\",\"b\",\"200\"]}'"] 23 | env: 24 | - name: CHANNEL_NAME 25 | value: channel1 26 | - name: CHAINCODE_NAME 27 | value: "cc" 28 | - name: CHAINCODE_VERSION 29 | value: "1.0" 30 | - name: FABRIC_CFG_PATH 31 | value: /etc/hyperledger/fabric 32 | - name: CORE_PEER_MSPCONFIGPATH 33 | value: /shared/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 34 | - name: CORE_PEER_LOCALMSPID 35 | value: Org1MSP 36 | - name: CORE_PEER_ADDRESS 37 | value: blockchain-org1peer1:30110 38 | - name: GODEBUG 39 | value: "netdns=go" 40 | volumeMounts: 41 | - mountPath: /shared 42 | name: sharedvolume 43 | -------------------------------------------------------------------------------- /configFiles/copyArtifactsJob.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: batch/v1 3 | kind: Job 4 | metadata: 5 | name: copyartifacts 6 | spec: 7 | backoffLimit: 1 8 | template: 9 | metadata: 10 | name: copyartifacts 11 | spec: 12 | restartPolicy: "Never" 13 | volumes: 14 | - name: sharedvolume 15 | persistentVolumeClaim: 16 | claimName: shared-pvc 17 | - name: dockersocket 18 | hostPath: 19 | path: /var/run/docker.sock 20 | containers: 21 | - name: copyartifacts 22 | image: alpine:3.7 23 | imagePullPolicy: Always 24 | command: ["sh", "-c", "ls -l /shared; rm -rf /shared/*; ls -l /shared; while [ ! -d /shared/artifacts ]; do echo Waiting for artifacts to be copied; sleep 2; done; sleep 10; ls -l /shared/artifacts; "] 25 | volumeMounts: 26 | - mountPath: /shared 27 | name: sharedvolume 28 | -------------------------------------------------------------------------------- /configFiles/createVolume-paid.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: shared-pvc 5 | labels: 6 | app: blockchain 7 | spec: 8 | accessModes: 9 | - ReadWriteMany 10 | resources: 11 | requests: 12 | storage: 20Gi 13 | storageClassName: "ibmc-file-bronze" 14 | -------------------------------------------------------------------------------- /configFiles/createVolume.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: PersistentVolume 3 | apiVersion: v1 4 | metadata: 5 | name: shared-pv 6 | labels: 7 | type: local 8 | name: sharedvolume 9 | spec: 10 | capacity: 11 | storage: 1Gi 12 | accessModes: 13 | - ReadWriteMany 14 | hostPath: 15 | path: "/tmp" 16 | 17 | --- 18 | kind: PersistentVolumeClaim 19 | apiVersion: v1 20 | metadata: 21 | name: shared-pvc 22 | spec: 23 | accessModes: 24 | - ReadWriteMany 25 | resources: 26 | requests: 27 | storage: 1Gi 28 | storageClassName: "" 29 | selector: 30 | matchLabels: 31 | name: sharedvolume 32 | -------------------------------------------------------------------------------- /configFiles/create_channel.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: batch/v1 3 | kind: Job 4 | metadata: 5 | name: createchannel 6 | spec: 7 | backoffLimit: 1 8 | template: 9 | metadata: 10 | name: createchannel 11 | spec: 12 | restartPolicy: "Never" 13 | volumes: 14 | - name: sharedvolume 15 | persistentVolumeClaim: 16 | claimName: shared-pvc 17 | containers: 18 | - name: createchanneltx 19 | image: hyperledger/fabric-tools:1.4 20 | imagePullPolicy: Always 21 | command: ["sh", "-c", "cd /shared && pwd && ls && export FABRIC_CFG_PATH=$PWD && configtxgen -profile FourOrgsChannel -outputCreateChannelTx ${CHANNEL_NAME}.tx -channelID ${CHANNEL_NAME} && touch /shared/status_channeltx_complete "] 22 | env: 23 | - name: CHANNEL_NAME 24 | value: channel1 25 | - name: GODEBUG 26 | value: "netdns=go" 27 | volumeMounts: 28 | - mountPath: /shared 29 | name: sharedvolume 30 | 31 | - name: createchannel 32 | image: hyperledger/fabric-peer:1.4 33 | imagePullPolicy: Always 34 | command: ["sh", "-c", "while [ ! -f /shared/status_channeltx_complete ]; do echo Waiting for channeltx; sleep 2; done; peer channel create -o ${ORDERER_URL} -c ${CHANNEL_NAME} -f /shared/${CHANNEL_NAME}.tx && rm /shared/status_channeltx_complete && touch /shared/status_channelcreate_complete"] 35 | env: 36 | - name: CHANNEL_NAME 37 | value: channel1 38 | - name: ORDERER_URL 39 | value: blockchain-orderer:31010 40 | - name: CORE_PEER_ADDRESSAUTODETECT 41 | value: "false" 42 | - name: CORE_PEER_NETWORKID 43 | value: nid1 44 | - name: CORE_PEER_LOCALMSPID 45 | value: Org1MSP 46 | - name: CORE_PEER_MSPCONFIGPATH 47 | value: /shared/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp/ 48 | - name: FABRIC_LOGGING_SPEC 49 | value: debug 50 | - name: FABRIC_CFG_PATH 51 | value: /etc/hyperledger/fabric 52 | - name: GODEBUG 53 | value: "netdns=go" 54 | volumeMounts: 55 | - mountPath: /shared 56 | name: sharedvolume 57 | -------------------------------------------------------------------------------- /configFiles/docker-volume.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | kind: PersistentVolume 3 | apiVersion: v1 4 | metadata: 5 | name: docker-pv 6 | labels: 7 | type: local 8 | name: dockervolume 9 | spec: 10 | capacity: 11 | storage: 10Gi 12 | accessModes: 13 | - ReadWriteMany 14 | hostPath: 15 | path: "/tmp-docker-pv" 16 | 17 | --- 18 | kind: PersistentVolumeClaim 19 | apiVersion: v1 20 | metadata: 21 | name: docker-pvc 22 | spec: 23 | accessModes: 24 | - ReadWriteMany 25 | resources: 26 | requests: 27 | storage: 10Gi 28 | storageClassName: "" 29 | selector: 30 | matchLabels: 31 | name: dockervolume -------------------------------------------------------------------------------- /configFiles/docker.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: docker 6 | labels: 7 | run: docker 8 | spec: 9 | selector: 10 | name: docker 11 | ports: 12 | - protocol: TCP 13 | targetPort: 2375 14 | port: 2375 15 | --- 16 | apiVersion: apps/v1 17 | kind: Deployment 18 | metadata: 19 | name: docker-dind 20 | spec: 21 | replicas: 1 22 | selector: 23 | matchLabels: 24 | name: docker 25 | template: 26 | metadata: 27 | labels: 28 | name: docker 29 | spec: 30 | volumes: 31 | - name: dockervolume 32 | persistentVolumeClaim: 33 | claimName: docker-pvc 34 | containers: 35 | - name: docker 36 | securityContext: 37 | privileged: true 38 | image: "docker:18.05.0-dind" 39 | ports: 40 | - containerPort: 2375 41 | volumeMounts: 42 | - mountPath: /var/lib/docker 43 | name: dockervolume -------------------------------------------------------------------------------- /configFiles/generateArtifactsJob.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: batch/v1 3 | kind: Job 4 | metadata: 5 | name: utils 6 | spec: 7 | backoffLimit: 1 8 | template: 9 | metadata: 10 | name: utils 11 | spec: 12 | restartPolicy: "Never" 13 | volumes: 14 | - name: sharedvolume 15 | persistentVolumeClaim: 16 | claimName: shared-pvc 17 | - name: dockersocket 18 | hostPath: 19 | path: /var/run/docker.sock 20 | containers: 21 | - name: cryptogen 22 | image: hyperledger/fabric-tools:1.4 23 | imagePullPolicy: Always 24 | command: ["sh", "-c", "echo 'Cryptogen Starts'; ls -l /shared/artifacts; while [ ! -d /shared/artifacts ]; do echo Waiting for configFiles; sleep 1; done; cryptogen generate --config /shared/artifacts/crypto-config.yaml && cp -r crypto-config /shared/ && for file in $(find /shared/ -iname *_sk); do echo $file; dir=$(dirname $file); echo ${dir}; mv ${dir}/*_sk ${dir}/key.pem; done && find /shared -type d | xargs chmod a+rx && find /shared -type f | xargs chmod a+r && touch /shared/status_cryptogen_complete;"] 25 | volumeMounts: 26 | - mountPath: /shared 27 | name: sharedvolume 28 | - name: configtxgen 29 | image: hyperledger/fabric-tools:1.4 30 | imagePullPolicy: Always 31 | command: ["sh", "-c", "echo 'Configtxgen Starts'; ls -l /shared; sleep 1 && while [ ! -f /shared/status_cryptogen_complete ]; do echo Waiting for cryptogen; sleep 1; done; cp /shared/artifacts/configtx.yaml /shared/; cd /shared/; export FABRIC_CFG_PATH=$PWD; configtxgen -profile FourOrgsOrdererGenesis -outputBlock genesis.block && find /shared -type d | xargs chmod a+rx && find /shared -type f | xargs chmod a+r && touch /shared/status_configtxgen_complete && rm /shared/status_cryptogen_complete;"] 32 | volumeMounts: 33 | - mountPath: /shared 34 | name: sharedvolume 35 | 36 | -------------------------------------------------------------------------------- /configFiles/join_channel.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: batch/v1 3 | kind: Job 4 | metadata: 5 | name: joinchannel 6 | spec: 7 | backoffLimit: 1 8 | template: 9 | metadata: 10 | name: joinchannel 11 | spec: 12 | restartPolicy: "Never" 13 | volumes: 14 | - name: sharedvolume 15 | persistentVolumeClaim: 16 | claimName: shared-pvc 17 | containers: 18 | - name: joinchannel1 19 | image: hyperledger/fabric-peer:1.4 20 | imagePullPolicy: Always 21 | command: ["sh", "-c", "peer channel fetch newest -o ${ORDERER_URL} -c ${CHANNEL_NAME} && peer channel join -b ${CHANNEL_NAME}_newest.block "] 22 | env: 23 | - name: CHANNEL_NAME 24 | value: channel1 25 | - name: CORE_PEER_NETWORKID 26 | value: nid1 27 | - name: ORDERER_URL 28 | value: blockchain-orderer:31010 29 | - name: CORE_PEER_ADDRESS 30 | value: blockchain-org1peer1:30110 31 | - name: CORE_PEER_LOCALMSPID 32 | value: Org1MSP 33 | - name: CORE_PEER_MSPID 34 | value: Org1MSP 35 | - name: FABRIC_LOGGING_SPECL 36 | value: debug 37 | - name: CORE_PEER_MSPCONFIGPATH 38 | value: /shared/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp 39 | - name: FABRIC_CFG_PATH 40 | value: /etc/hyperledger/fabric 41 | - name: GODEBUG 42 | value: "netdns=go" 43 | volumeMounts: 44 | - mountPath: /shared 45 | name: sharedvolume 46 | 47 | - name: joinchannel2 48 | image: hyperledger/fabric-peer:1.4 49 | imagePullPolicy: Always 50 | command: ["sh", "-c", "peer channel fetch newest -o ${ORDERER_URL} -c ${CHANNEL_NAME} && peer channel join -b ${CHANNEL_NAME}_newest.block "] 51 | env: 52 | - name: CHANNEL_NAME 53 | value: channel1 54 | - name: CORE_PEER_NETWORKID 55 | value: nid1 56 | - name: ORDERER_URL 57 | value: blockchain-orderer:31010 58 | - name: CORE_PEER_ADDRESS 59 | value: blockchain-org2peer1:30210 60 | - name: CORE_PEER_LOCALMSPID 61 | value: Org2MSP 62 | - name: CORE_PEER_MSPID 63 | value: Org2MSP 64 | - name: FABRIC_LOGGING_SPEC 65 | value: debug 66 | - name: CORE_PEER_MSPCONFIGPATH 67 | value: /shared/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp 68 | - name: FABRIC_CFG_PATH 69 | value: /etc/hyperledger/fabric 70 | - name: GODEBUG 71 | value: "netdns=go" 72 | volumeMounts: 73 | - mountPath: /shared 74 | name: sharedvolume 75 | 76 | - name: joinchannel3 77 | image: hyperledger/fabric-peer:1.4 78 | imagePullPolicy: Always 79 | command: ["sh", "-c", "peer channel fetch newest -o ${ORDERER_URL} -c ${CHANNEL_NAME} && peer channel join -b ${CHANNEL_NAME}_newest.block "] 80 | env: 81 | - name: CHANNEL_NAME 82 | value: channel1 83 | - name: CORE_PEER_NETWORKID 84 | value: nid1 85 | - name: ORDERER_URL 86 | value: blockchain-orderer:31010 87 | - name: CORE_PEER_ADDRESS 88 | value: blockchain-org3peer1:30310 89 | - name: CORE_PEER_LOCALMSPID 90 | value: Org3MSP 91 | - name: CORE_PEER_MSPID 92 | value: Org3MSP 93 | - name: FABRIC_LOGGING_SPEC 94 | value: debug 95 | - name: CORE_PEER_MSPCONFIGPATH 96 | value: /shared/crypto-config/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp 97 | - name: FABRIC_CFG_PATH 98 | value: /etc/hyperledger/fabric 99 | - name: GODEBUG 100 | value: "netdns=go" 101 | volumeMounts: 102 | - mountPath: /shared 103 | name: sharedvolume 104 | 105 | - name: joinchannel4 106 | image: hyperledger/fabric-peer:1.4 107 | imagePullPolicy: Always 108 | command: ["sh", "-c", "peer channel fetch newest -o ${ORDERER_URL} -c ${CHANNEL_NAME} && peer channel join -b ${CHANNEL_NAME}_newest.block "] 109 | env: 110 | - name: CHANNEL_NAME 111 | value: channel1 112 | - name: CORE_PEER_NETWORKID 113 | value: nid1 114 | - name: ORDERER_URL 115 | value: blockchain-orderer:31010 116 | - name: CORE_PEER_ADDRESS 117 | value: blockchain-org4peer1:30410 118 | - name: CORE_PEER_LOCALMSPID 119 | value: Org4MSP 120 | - name: CORE_PEER_MSPID 121 | value: Org4MSP 122 | - name: FABRIC_LOGGING_SPEC 123 | value: debug 124 | - name: CORE_PEER_MSPCONFIGPATH 125 | value: /shared/crypto-config/peerOrganizations/org4.example.com/users/Admin@org4.example.com/msp 126 | - name: FABRIC_CFG_PATH 127 | value: /etc/hyperledger/fabric 128 | - name: GODEBUG 129 | value: "netdns=go" 130 | volumeMounts: 131 | - mountPath: /shared 132 | name: sharedvolume 133 | 134 | -------------------------------------------------------------------------------- /configFiles/peersDeployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: blockchain-orderer 6 | spec: 7 | replicas: 1 8 | selector: 9 | matchLabels: 10 | name: orderer 11 | template: 12 | metadata: 13 | labels: 14 | name: orderer 15 | spec: 16 | volumes: 17 | - name: sharedvolume 18 | persistentVolumeClaim: 19 | claimName: shared-pvc 20 | 21 | containers: 22 | - name: orderer 23 | image: hyperledger/fabric-orderer:1.4 24 | command: ["sh", "-c", "sleep 5 && while [ ! -f /shared/status_configtxgen_complete ]; do echo Waiting for configtxgen; sleep 1; done; orderer"] 25 | env: 26 | - name: ORDERER_CFG_PATH 27 | value: /shared/ 28 | - name: ORDERER_GENERAL_LEDGERTYPE 29 | value: file 30 | - name: ORDERER_FILELEDGER_LOCATION 31 | value: /shared/ledger/orderer 32 | - name: ORDERER_GENERAL_BATCHTIMEOUT 33 | value: 1s 34 | - name: ORDERER_GENERAL_BATCHSIZE_MAXMESSAGECOUNT 35 | value: "10" 36 | - name: ORDERER_GENERAL_MAXWINDOWSIZE 37 | value: "1000" 38 | - name: ORDERER_GENERAL_ORDERERTYPE 39 | value: solo 40 | - name: ORDERER_GENERAL_LISTENADDRESS 41 | value: 0.0.0.0 42 | - name: ORDERER_GENERAL_LISTENPORT 43 | value: "31010" 44 | - name: ORDERER_GENERAL_LOGLEVEL 45 | value: debug 46 | - name: ORDERER_GENERAL_LOCALMSPDIR 47 | value: /shared/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp 48 | - name: ORDERER_GENERAL_LOCALMSPID 49 | value: OrdererMSP 50 | - name: ORDERER_GENERAL_GENESISMETHOD 51 | value: file 52 | - name: ORDERER_GENERAL_GENESISFILE 53 | value: /shared/genesis.block 54 | - name: ORDERER_GENERAL_GENESISPROFILE 55 | value: initial 56 | - name: ORDERER_GENERAL_TLS_ENABLED 57 | value: "false" 58 | - name: GODEBUG 59 | value: "netdns=go" 60 | volumeMounts: 61 | - mountPath: /shared 62 | name: sharedvolume 63 | 64 | --- 65 | apiVersion: apps/v1 66 | kind: Deployment 67 | metadata: 68 | name: blockchain-ca 69 | spec: 70 | replicas: 1 71 | selector: 72 | matchLabels: 73 | name: ca 74 | template: 75 | metadata: 76 | labels: 77 | name: ca 78 | spec: 79 | volumes: 80 | - name: sharedvolume 81 | persistentVolumeClaim: 82 | claimName: shared-pvc 83 | 84 | containers: 85 | - name: ca 86 | image: hyperledger/fabric-ca:1.4 87 | command: ["sh", "-c", "sleep 1 && while [ ! -f /shared/status_configtxgen_complete ]; do echo Waiting for configtxgen; sleep 1; done; fabric-ca-server start -b admin:adminpw -d"] 88 | env: 89 | - name: FABRIC_CA_SERVER_CA_NAME 90 | value: "CA1" 91 | - name: FABRIC_CA_SERVER_CA_CERTFILE 92 | value: /shared/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem 93 | - name: FABRIC_CA_SERVER_CA_KEYFILE 94 | value: /shared/crypto-config/peerOrganizations/org1.example.com/ca/key.pem 95 | - name: FABRIC_CA_SERVER_DEBUG 96 | value: "true" 97 | - name: FABRIC_CA_SERVER_TLS_ENABLED 98 | value: "false" 99 | - name: FABRIC_CA_SERVER_TLS_CERTFILE 100 | value: /certs/ca0a-cert.pem 101 | - name: FABRIC_CA_SERVER_TLS_KEYFILE 102 | value: /certs/ca0a-key.pem 103 | - name: GODEBUG 104 | value: "netdns=go" 105 | volumeMounts: 106 | - mountPath: /shared 107 | name: sharedvolume 108 | 109 | --- 110 | apiVersion: apps/v1 111 | kind: Deployment 112 | metadata: 113 | name: blockchain-org1peer1 114 | spec: 115 | replicas: 1 116 | selector: 117 | matchLabels: 118 | name: org1peer1 119 | template: 120 | metadata: 121 | labels: 122 | name: org1peer1 123 | spec: 124 | volumes: 125 | - name: sharedvolume 126 | persistentVolumeClaim: 127 | claimName: shared-pvc 128 | - name: dockersocket 129 | hostPath: 130 | path: /var/run/docker.sock 131 | 132 | containers: 133 | - name: org1peer1 134 | image: hyperledger/fabric-peer:1.4 135 | command: ["sh", "-c", "sleep 1 && while [ ! -f /shared/status_configtxgen_complete ]; do echo Waiting for configtxgen; sleep 1; done; peer node start"] 136 | env: 137 | - name: CORE_PEER_ADDRESSAUTODETECT 138 | value: "true" 139 | - name: CORE_PEER_NETWORKID 140 | value: nid1 141 | - name: CORE_PEER_ID 142 | value: org1peer1 143 | - name: CORE_PEER_ADDRESS 144 | value: blockchain-org1peer1:30110 145 | - name: CORE_PEER_LISTENADDRESS 146 | value: 0.0.0.0:30110 147 | - name: CORE_PEER_EVENTS_ADDRESS 148 | value: 0.0.0.0:30111 149 | - name: CORE_PEER_GOSSIP_BOOTSTRAP 150 | value: blockchain-org1peer1:30110 151 | - name: CORE_PEER_GOSSIP_ORGLEADER 152 | value: "false" 153 | - name: CORE_PEER_GOSSIP_SKIPHANDSHAKE 154 | value: "true" 155 | - name: CORE_PEER_COMMITTER_ENABLED 156 | value: "true" 157 | - name: CORE_PEER_PROFILE_ENABLED 158 | value: "true" 159 | - name: CORE_VM_ENDPOINT 160 | value: tcp://docker:2375 161 | - name: CORE_PEER_LOCALMSPID 162 | value: Org1MSP 163 | - name: CORE_PEER_MSPCONFIGPATH 164 | value: /shared/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp/ 165 | - name: FABRIC_LOGGING_SPEC 166 | value: debug 167 | - name: CORE_LOGGING_PEER 168 | value: debug 169 | - name: CORE_LOGGING_CAUTHDSL 170 | value: debug 171 | - name: CORE_LOGGING_GOSSIP 172 | value: debug 173 | - name: CORE_LOGGING_LEDGER 174 | value: debug 175 | - name: CORE_LOGGING_MSP 176 | value: info 177 | - name: CORE_LOGGING_POLICIES 178 | value: debug 179 | - name: CORE_LOGGING_GRPC 180 | value: debug 181 | - name: CORE_PEER_TLS_ENABLED 182 | value: "false" 183 | - name: CORE_LEDGER_STATE_STATEDATABASE 184 | value: goleveldb 185 | - name: FABRIC_CFG_PATH 186 | value: /etc/hyperledger/fabric/ 187 | - name: ORDERER_URL 188 | value: blockchain-orderer:31010 189 | - name: GODEBUG 190 | value: "netdns=go" 191 | - name: CORE_VM_DOCKER_ATTACHSTDOUT 192 | value: "true" 193 | volumeMounts: 194 | - mountPath: /shared 195 | name: sharedvolume 196 | - mountPath: /host/var/run/docker.sock 197 | name: dockersocket 198 | --- 199 | apiVersion: apps/v1 200 | kind: Deployment 201 | metadata: 202 | name: blockchain-org2peer1 203 | spec: 204 | replicas: 1 205 | selector: 206 | matchLabels: 207 | name: org2peer1 208 | template: 209 | metadata: 210 | labels: 211 | name: org2peer1 212 | spec: 213 | volumes: 214 | - name: sharedvolume 215 | persistentVolumeClaim: 216 | claimName: shared-pvc 217 | - name: dockersocket 218 | hostPath: 219 | path: /var/run/docker.sock 220 | 221 | containers: 222 | - name: org2peer1 223 | image: hyperledger/fabric-peer:1.4 224 | command: ["sh", "-c", "sleep 1 && while [ ! -f /shared/status_configtxgen_complete ]; do echo Waiting for configtxgen; sleep 1; done; peer node start"] 225 | env: 226 | - name: CORE_PEER_ADDRESSAUTODETECT 227 | value: "true" 228 | - name: CORE_PEER_ID 229 | value: org2peer1 230 | - name: CORE_PEER_NETWORKID 231 | value: nid1 232 | - name: CORE_PEER_ADDRESS 233 | value: blockchain-org2peer1:30210 234 | - name: CORE_PEER_LISTENADDRESS 235 | value: 0.0.0.0:30210 236 | - name: CORE_PEER_EVENTS_ADDRESS 237 | value: 0.0.0.0:30211 238 | - name: CORE_PEER_GOSSIP_BOOTSTRAP 239 | value: blockchain-org2peer1:30210 240 | - name: CORE_PEER_GOSSIP_ORGLEADER 241 | value: "false" 242 | - name: CORE_PEER_GOSSIP_SKIPHANDSHAKE 243 | value: "true" 244 | - name: CORE_PEER_COMMITTER_ENABLED 245 | value: "true" 246 | - name: CORE_PEER_PROFILE_ENABLED 247 | value: "true" 248 | - name: CORE_VM_ENDPOINT 249 | value: tcp://docker:2375 250 | - name: CORE_PEER_LOCALMSPID 251 | value: Org2MSP 252 | - name: CORE_PEER_MSPCONFIGPATH 253 | value: /shared/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp/ 254 | - name: FABRIC_LOGGING_SPEC 255 | value: debug 256 | - name: CORE_LOGGING_PEER 257 | value: debug 258 | - name: CORE_LOGGING_CAUTHDSL 259 | value: debug 260 | - name: CORE_LOGGING_GOSSIP 261 | value: debug 262 | - name: CORE_LOGGING_LEDGER 263 | value: debug 264 | - name: CORE_LOGGING_MSP 265 | value: debug 266 | - name: CORE_LOGGING_POLICIES 267 | value: debug 268 | - name: CORE_LOGGING_GRPC 269 | value: debug 270 | - name: CORE_PEER_TLS_ENABLED 271 | value: "false" 272 | - name: CORE_LEDGER_STATE_STATEDATABASE 273 | value: goleveldb 274 | - name: FABRIC_CFG_PATH 275 | value: /etc/hyperledger/fabric/ 276 | - name: ORDERER_URL 277 | value: blockchain-orderer:31010 278 | - name: GODEBUG 279 | value: "netdns=go" 280 | - name: CORE_VM_DOCKER_ATTACHSTDOUT 281 | value: "true" 282 | volumeMounts: 283 | - mountPath: /shared 284 | name: sharedvolume 285 | - mountPath: /host/var/run/docker.sock 286 | name: dockersocket 287 | 288 | --- 289 | apiVersion: apps/v1 290 | kind: Deployment 291 | metadata: 292 | name: blockchain-org3peer1 293 | spec: 294 | replicas: 1 295 | selector: 296 | matchLabels: 297 | name: org3peer1 298 | template: 299 | metadata: 300 | labels: 301 | name: org3peer1 302 | spec: 303 | volumes: 304 | - name: sharedvolume 305 | persistentVolumeClaim: 306 | claimName: shared-pvc 307 | - name: dockersocket 308 | hostPath: 309 | path: /var/run/docker.sock 310 | 311 | containers: 312 | - name: org3peer1 313 | image: hyperledger/fabric-peer:1.4 314 | command: ["sh", "-c", "sleep 1 && while [ ! -f /shared/status_configtxgen_complete ]; do echo Waiting for configtxgen; sleep 1; done; peer node start"] 315 | env: 316 | - name: CORE_PEER_ADDRESSAUTODETECT 317 | value: "true" 318 | - name: CORE_PEER_ID 319 | value: org3peer1 320 | - name: CORE_PEER_NETWORKID 321 | value: nid1 322 | - name: CORE_PEER_ADDRESS 323 | value: blockchain-org3peer1:30310 324 | - name: CORE_PEER_LISTENADDRESS 325 | value: 0.0.0.0:30310 326 | - name: CORE_PEER_EVENTS_ADDRESS 327 | value: 0.0.0.0:30311 328 | - name: CORE_PEER_GOSSIP_BOOTSTRAP 329 | value: blockchain-org3peer1:30310 330 | - name: CORE_PEER_GOSSIP_ORGLEADER 331 | value: "false" 332 | - name: CORE_PEER_GOSSIP_SKIPHANDSHAKE 333 | value: "true" 334 | - name: CORE_PEER_COMMITTER_ENABLED 335 | value: "true" 336 | - name: CORE_PEER_PROFILE_ENABLED 337 | value: "true" 338 | - name: CORE_VM_ENDPOINT 339 | value: tcp://docker:2375 340 | - name: CORE_PEER_LOCALMSPID 341 | value: Org3MSP 342 | - name: CORE_PEER_MSPCONFIGPATH 343 | value: /shared/crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/msp/ 344 | - name: FABRIC_LOGGING_SPEC 345 | value: debug 346 | - name: CORE_LOGGING_PEER 347 | value: debug 348 | - name: CORE_LOGGING_CAUTHDSL 349 | value: debug 350 | - name: CORE_LOGGING_GOSSIP 351 | value: debug 352 | - name: CORE_LOGGING_LEDGER 353 | value: debug 354 | - name: CORE_LOGGING_MSP 355 | value: debug 356 | - name: CORE_LOGGING_POLICIES 357 | value: debug 358 | - name: CORE_LOGGING_GRPC 359 | value: debug 360 | - name: CORE_PEER_TLS_ENABLED 361 | value: "false" 362 | - name: CORE_LEDGER_STATE_STATEDATABASE 363 | value: goleveldb 364 | - name: FABRIC_CFG_PATH 365 | value: /etc/hyperledger/fabric/ 366 | - name: ORDERER_URL 367 | value: blockchain-orderer:31010 368 | - name: GODEBUG 369 | value: "netdns=go" 370 | - name: CORE_VM_DOCKER_ATTACHSTDOUT 371 | value: "true" 372 | volumeMounts: 373 | - mountPath: /shared 374 | name: sharedvolume 375 | - mountPath: /host/var/run/docker.sock 376 | name: dockersocket 377 | 378 | --- 379 | apiVersion: apps/v1 380 | kind: Deployment 381 | metadata: 382 | name: blockchain-org4peer1 383 | spec: 384 | replicas: 1 385 | selector: 386 | matchLabels: 387 | name: org4peer1 388 | template: 389 | metadata: 390 | labels: 391 | name: org4peer1 392 | spec: 393 | volumes: 394 | - name: sharedvolume 395 | persistentVolumeClaim: 396 | claimName: shared-pvc 397 | - name: dockersocket 398 | hostPath: 399 | path: /var/run/docker.sock 400 | 401 | containers: 402 | - name: org4peer1 403 | image: hyperledger/fabric-peer:1.4 404 | command: ["sh", "-c", "sleep 1 && while [ ! -f /shared/status_configtxgen_complete ]; do echo Waiting for configtxgen; sleep 1; done; peer node start"] 405 | env: 406 | - name: CORE_PEER_ADDRESSAUTODETECT 407 | value: "true" 408 | - name: CORE_PEER_ID 409 | value: org4peer1 410 | - name: CORE_PEER_NETWORKID 411 | value: nid1 412 | - name: CORE_PEER_ADDRESS 413 | value: blockchain-org4peer1:30410 414 | - name: CORE_PEER_LISTENADDRESS 415 | value: 0.0.0.0:30410 416 | - name: CORE_PEER_EVENTS_ADDRESS 417 | value: 0.0.0.0:30411 418 | - name: CORE_PEER_GOSSIP_BOOTSTRAP 419 | value: blockchain-org4peer1:30410 420 | - name: CORE_PEER_GOSSIP_ORGLEADER 421 | value: "false" 422 | - name: CORE_PEER_GOSSIP_SKIPHANDSHAKE 423 | value: "true" 424 | - name: CORE_PEER_COMMITTER_ENABLED 425 | value: "true" 426 | - name: CORE_PEER_PROFILE_ENABLED 427 | value: "true" 428 | - name: CORE_VM_ENDPOINT 429 | value: tcp://docker:2375 430 | - name: CORE_PEER_LOCALMSPID 431 | value: Org4MSP 432 | - name: CORE_PEER_MSPCONFIGPATH 433 | value: /shared/crypto-config/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/msp/ 434 | - name: FABRIC_LOGGING_SPEC 435 | value: debug 436 | - name: CORE_LOGGING_PEER 437 | value: debug 438 | - name: CORE_LOGGING_CAUTHDSL 439 | value: debug 440 | - name: CORE_LOGGING_GOSSIP 441 | value: debug 442 | - name: CORE_LOGGING_LEDGER 443 | value: debug 444 | - name: CORE_LOGGING_MSP 445 | value: debug 446 | - name: CORE_LOGGING_POLICIES 447 | value: debug 448 | - name: CORE_LOGGING_GRPC 449 | value: debug 450 | - name: CORE_PEER_TLS_ENABLED 451 | value: "false" 452 | - name: CORE_LEDGER_STATE_STATEDATABASE 453 | value: goleveldb 454 | - name: FABRIC_CFG_PATH 455 | value: /etc/hyperledger/fabric/ 456 | - name: ORDERER_URL 457 | value: blockchain-orderer:31010 458 | - name: GODEBUG 459 | value: "netdns=go" 460 | - name: CORE_VM_DOCKER_ATTACHSTDOUT 461 | value: "true" 462 | volumeMounts: 463 | - mountPath: /shared 464 | name: sharedvolume 465 | - mountPath: /host/var/run/docker.sock 466 | name: dockersocket 467 | -------------------------------------------------------------------------------- /deleteNetwork.sh: -------------------------------------------------------------------------------- 1 | 2 | KUBECONFIG_FOLDER=${PWD}/configFiles 3 | 4 | kubectl delete -f ${KUBECONFIG_FOLDER}/chaincode_instantiate.yaml 5 | kubectl delete -f ${KUBECONFIG_FOLDER}/chaincode_install.yaml 6 | 7 | kubectl delete -f ${KUBECONFIG_FOLDER}/join_channel.yaml 8 | kubectl delete -f ${KUBECONFIG_FOLDER}/create_channel.yaml 9 | 10 | kubectl delete --ignore-not-found=true -f ${KUBECONFIG_FOLDER}/docker.yaml 11 | 12 | kubectl delete -f ${KUBECONFIG_FOLDER}/peersDeployment.yaml 13 | kubectl delete -f ${KUBECONFIG_FOLDER}/blockchain-services.yaml 14 | 15 | kubectl delete -f ${KUBECONFIG_FOLDER}/generateArtifactsJob.yaml 16 | kubectl delete -f ${KUBECONFIG_FOLDER}/copyArtifactsJob.yaml 17 | 18 | kubectl delete -f ${KUBECONFIG_FOLDER}/createVolume.yaml 19 | kubectl delete --ignore-not-found=true -f ${KUBECONFIG_FOLDER}/docker-volume.yaml 20 | 21 | sleep 15 22 | 23 | echo -e "\npv:" 24 | kubectl get pv 25 | echo -e "\npvc:" 26 | kubectl get pvc 27 | echo -e "\njobs:" 28 | kubectl get jobs 29 | echo -e "\ndeployments:" 30 | kubectl get deployments 31 | echo -e "\nservices:" 32 | kubectl get services 33 | echo -e "\npods:" 34 | kubectl get pods 35 | 36 | echo -e "\nNetwork Deleted!!\n" 37 | 38 | -------------------------------------------------------------------------------- /images/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/architecture.png -------------------------------------------------------------------------------- /images/cluster-status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/cluster-status.png -------------------------------------------------------------------------------- /images/create-service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/create-service.png -------------------------------------------------------------------------------- /images/error1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/error1.png -------------------------------------------------------------------------------- /images/error2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/error2.png -------------------------------------------------------------------------------- /images/error3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/error3.png -------------------------------------------------------------------------------- /images/error4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/error4.png -------------------------------------------------------------------------------- /images/error5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/error5.png -------------------------------------------------------------------------------- /images/first-query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/first-query.png -------------------------------------------------------------------------------- /images/gain-access-to-cluster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/gain-access-to-cluster.png -------------------------------------------------------------------------------- /images/invoke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/invoke.png -------------------------------------------------------------------------------- /images/kdashboardonibmcloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/kdashboardonibmcloud.png -------------------------------------------------------------------------------- /images/kubernetes-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/kubernetes-dashboard.png -------------------------------------------------------------------------------- /images/provide-token-for-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/provide-token-for-dashboard.png -------------------------------------------------------------------------------- /images/second-query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/second-query.png -------------------------------------------------------------------------------- /images/third-query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IBM/blockchain-network-on-kubernetes/f861512787444923c64651a83f2b2fa572664f6a/images/third-query.png -------------------------------------------------------------------------------- /setup_blockchainNetwork_v1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -d "${PWD}/configFiles" ]; then 4 | KUBECONFIG_FOLDER=${PWD}/configFiles 5 | else 6 | echo "Configuration files are not found." 7 | exit 8 | fi 9 | 10 | # Create Docker deployment 11 | if [ "$(cat configFiles/peersDeployment.yaml | grep -c tcp://docker:2375)" != "0" ]; then 12 | echo "peersDeployment.yaml file was configured to use Docker in a container." 13 | echo "Creating Docker deployment" 14 | 15 | kubectl create -f ${KUBECONFIG_FOLDER}/docker-volume.yaml 16 | kubectl create -f ${KUBECONFIG_FOLDER}/docker.yaml 17 | sleep 5 18 | 19 | dockerPodStatus=$(kubectl get pods --selector=name=docker --output=jsonpath={.items..phase}) 20 | 21 | while [ "${dockerPodStatus}" != "Running" ]; do 22 | echo "Wating for Docker container to run. Current status of Docker is ${dockerPodStatus}" 23 | sleep 5; 24 | if [ "${dockerPodStatus}" == "Error" ]; then 25 | echo "There is an error in the Docker pod. Please check logs." 26 | exit 1 27 | fi 28 | dockerPodStatus=$(kubectl get pods --selector=name=docker --output=jsonpath={.items..phase}) 29 | done 30 | fi 31 | 32 | # Creating Persistant Volume 33 | echo -e "\nCreating volume" 34 | if [ "$(kubectl get pvc | grep shared-pvc | awk '{print $2}')" != "Bound" ]; then 35 | echo "The Persistant Volume does not seem to exist or is not bound" 36 | echo "Creating Persistant Volume" 37 | 38 | if [ "$1" == "--paid" ]; then 39 | echo "You passed argument --paid. Make sure you have an IBM Cloud Kubernetes - Standard tier. Else, remove --paid option" 40 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/createVolume-paid.yaml" 41 | kubectl create -f ${KUBECONFIG_FOLDER}/createVolume-paid.yaml 42 | sleep 5 43 | else 44 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/createVolume.yaml" 45 | kubectl create -f ${KUBECONFIG_FOLDER}/createVolume.yaml 46 | sleep 5 47 | fi 48 | 49 | if [ "kubectl get pvc | grep shared-pvc | awk '{print $3}'" != "shared-pv" ]; then 50 | echo "Success creating Persistant Volume" 51 | else 52 | echo "Failed to create Persistant Volume" 53 | fi 54 | else 55 | echo "The Persistant Volume exists, not creating again" 56 | fi 57 | 58 | # Copy the required files(configtx.yaml, cruypto-config.yaml, sample chaincode etc.) into volume 59 | echo -e "\nCreating Copy artifacts job." 60 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/copyArtifactsJob.yaml" 61 | kubectl create -f ${KUBECONFIG_FOLDER}/copyArtifactsJob.yaml 62 | 63 | pod=$(kubectl get pods --selector=job-name=copyartifacts --output=jsonpath={.items..metadata.name}) 64 | 65 | podSTATUS=$(kubectl get pods --selector=job-name=copyartifacts --output=jsonpath={.items..phase}) 66 | 67 | while [ "${podSTATUS}" != "Running" ]; do 68 | echo "Wating for container of copy artifact pod to run. Current status of ${pod} is ${podSTATUS}" 69 | sleep 5; 70 | if [ "${podSTATUS}" == "Error" ]; then 71 | echo "There is an error in copyartifacts job. Please check logs." 72 | exit 1 73 | fi 74 | podSTATUS=$(kubectl get pods --selector=job-name=copyartifacts --output=jsonpath={.items..phase}) 75 | done 76 | 77 | echo -e "${pod} is now ${podSTATUS}" 78 | echo -e "\nStarting to copy artifacts in persistent volume." 79 | 80 | #fix for this script to work on icp and ICS 81 | kubectl cp ./artifacts $pod:/shared/ 82 | 83 | echo "Waiting for 10 more seconds for copying artifacts to avoid any network delay" 84 | sleep 10 85 | JOBSTATUS=$(kubectl get jobs |grep "copyartifacts" |awk '{print $3}') 86 | while [ "${JOBSTATUS}" != "1" ]; do 87 | echo "Waiting for copyartifacts job to complete" 88 | sleep 1; 89 | PODSTATUS=$(kubectl get pods | grep "copyartifacts" | awk '{print $3}') 90 | if [ "${PODSTATUS}" == "Error" ]; then 91 | echo "There is an error in copyartifacts job. Please check logs." 92 | exit 1 93 | fi 94 | JOBSTATUS=$(kubectl get jobs |grep "copyartifacts" |awk '{print $3}') 95 | done 96 | echo "Copy artifacts job completed" 97 | 98 | 99 | # Generate Network artifacts using configtx.yaml and crypto-config.yaml 100 | echo -e "\nGenerating the required artifacts for Blockchain network" 101 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/generateArtifactsJob.yaml" 102 | kubectl create -f ${KUBECONFIG_FOLDER}/generateArtifactsJob.yaml 103 | 104 | JOBSTATUS=$(kubectl get jobs |grep utils|awk '{print $3}') 105 | while [ "${JOBSTATUS}" != "1" ]; do 106 | echo "Waiting for generateArtifacts job to complete" 107 | sleep 1; 108 | # UTILSLEFT=$(kubectl get pods | grep utils | awk '{print $2}') 109 | UTILSSTATUS=$(kubectl get pods | grep "utils" | awk '{print $3}') 110 | if [ "${UTILSSTATUS}" == "Error" ]; then 111 | echo "There is an error in utils job. Please check logs." 112 | exit 1 113 | fi 114 | # UTILSLEFT=$(kubectl get pods | grep utils | awk '{print $2}') 115 | JOBSTATUS=$(kubectl get jobs |grep utils|awk '{print $3}') 116 | done 117 | 118 | 119 | # Create services for all peers, ca, orderer 120 | echo -e "\nCreating Services for blockchain network" 121 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/blockchain-services.yaml" 122 | kubectl create -f ${KUBECONFIG_FOLDER}/blockchain-services.yaml 123 | 124 | 125 | # Create peers, ca, orderer using Kubernetes Deployments 126 | echo -e "\nCreating new Deployment to create four peers in network" 127 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/peersDeployment.yaml" 128 | kubectl create -f ${KUBECONFIG_FOLDER}/peersDeployment.yaml 129 | 130 | echo "Checking if all deployments are ready" 131 | 132 | NUMPENDING=$(kubectl get deployments | grep blockchain | awk '{print $5}' | grep 0 | wc -l | awk '{print $1}') 133 | while [ "${NUMPENDING}" != "0" ]; do 134 | echo "Waiting on pending deployments. Deployments pending = ${NUMPENDING}" 135 | NUMPENDING=$(kubectl get deployments | grep blockchain | awk '{print $5}' | grep 0 | wc -l | awk '{print $1}') 136 | sleep 1 137 | done 138 | 139 | echo "Waiting for 15 seconds for peers and orderer to settle" 140 | sleep 15 141 | 142 | 143 | # Generate channel artifacts using configtx.yaml and then create channel 144 | echo -e "\nCreating channel transaction artifact and a channel" 145 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/create_channel.yaml" 146 | kubectl create -f ${KUBECONFIG_FOLDER}/create_channel.yaml 147 | 148 | JOBSTATUS=$(kubectl get jobs |grep createchannel |awk '{print $3}') 149 | while [ "${JOBSTATUS}" != "1" ]; do 150 | echo "Waiting for createchannel job to be completed" 151 | sleep 1; 152 | if [ "$(kubectl get pods | grep createchannel | awk '{print $3}')" == "Error" ]; then 153 | echo "Create Channel Failed" 154 | exit 1 155 | fi 156 | JOBSTATUS=$(kubectl get jobs |grep createchannel |awk '{print $3}') 157 | done 158 | echo "Create Channel Completed Successfully" 159 | 160 | 161 | # Join all peers on a channel 162 | echo -e "\nCreating joinchannel job" 163 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/join_channel.yaml" 164 | kubectl create -f ${KUBECONFIG_FOLDER}/join_channel.yaml 165 | 166 | JOBSTATUS=$(kubectl get jobs |grep joinchannel |awk '{print $3}') 167 | while [ "${JOBSTATUS}" != "1" ]; do 168 | echo "Waiting for joinchannel job to be completed" 169 | sleep 1; 170 | if [ "$(kubectl get pods | grep joinchannel | awk '{print $3}')" == "Error" ]; then 171 | echo "Join Channel Failed" 172 | exit 1 173 | fi 174 | JOBSTATUS=$(kubectl get jobs |grep joinchannel |awk '{print $3}') 175 | done 176 | echo "Join Channel Completed Successfully" 177 | 178 | 179 | # Install chaincode on each peer 180 | echo -e "\nCreating installchaincode job" 181 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/chaincode_install.yaml" 182 | kubectl create -f ${KUBECONFIG_FOLDER}/chaincode_install.yaml 183 | 184 | JOBSTATUS=$(kubectl get jobs |grep chaincodeinstall |awk '{print $3}') 185 | while [ "${JOBSTATUS}" != "1" ]; do 186 | echo "Waiting for chaincodeinstall job to be completed" 187 | sleep 1; 188 | if [ "$(kubectl get pods | grep chaincodeinstall | awk '{print $3}')" == "Error" ]; then 189 | echo "Chaincode Install Failed" 190 | exit 1 191 | fi 192 | JOBSTATUS=$(kubectl get jobs |grep chaincodeinstall |awk '{print $3}') 193 | done 194 | echo "Chaincode Install Completed Successfully" 195 | 196 | 197 | # Instantiate chaincode on channel 198 | echo -e "\nCreating chaincodeinstantiate job" 199 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/chaincode_instantiate.yaml" 200 | kubectl create -f ${KUBECONFIG_FOLDER}/chaincode_instantiate.yaml 201 | 202 | JOBSTATUS=$(kubectl get jobs |grep chaincodeinstantiate |awk '{print $3}') 203 | while [ "${JOBSTATUS}" != "1" ]; do 204 | echo "Waiting for chaincodeinstantiate job to be completed" 205 | sleep 1; 206 | if [ "$(kubectl get pods | grep chaincodeinstantiate | awk '{print $3}')" == "Error" ]; then 207 | echo "Chaincode Instantiation Failed" 208 | exit 1 209 | fi 210 | JOBSTATUS=$(kubectl get jobs |grep chaincodeinstantiate |awk '{print $3}') 211 | done 212 | echo "Chaincode Instantiation Completed Successfully" 213 | 214 | sleep 15 215 | echo -e "\nNetwork Setup Completed !!" 216 | -------------------------------------------------------------------------------- /setup_blockchainNetwork_v2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ -d "${PWD}/configFiles" ]; then 4 | KUBECONFIG_FOLDER=${PWD}/configFiles 5 | else 6 | echo "Configuration files are not found." 7 | exit 8 | fi 9 | 10 | # Create Docker deployment 11 | if [ "$(cat configFiles/peersDeployment.yaml | grep -c tcp://docker:2375)" != "0" ]; then 12 | echo "peersDeployment.yaml file was configured to use Docker in a container." 13 | echo "Creating Docker deployment" 14 | 15 | kubectl create -f ${KUBECONFIG_FOLDER}/docker-volume.yaml 16 | kubectl create -f ${KUBECONFIG_FOLDER}/docker.yaml 17 | sleep 5 18 | 19 | dockerPodStatus=$(kubectl get pods --selector=name=docker --output=jsonpath={.items..phase}) 20 | 21 | while [ "${dockerPodStatus}" != "Running" ]; do 22 | echo "Wating for Docker container to run. Current status of Docker is ${dockerPodStatus}" 23 | sleep 5; 24 | if [ "${dockerPodStatus}" == "Error" ]; then 25 | echo "There is an error in the Docker pod. Please check logs." 26 | exit 1 27 | fi 28 | dockerPodStatus=$(kubectl get pods --selector=name=docker --output=jsonpath={.items..phase}) 29 | done 30 | fi 31 | 32 | # Creating Persistant Volume 33 | echo -e "\nCreating volume" 34 | if [ "$(kubectl get pvc | grep shared-pvc | awk '{print $2}')" != "Bound" ]; then 35 | echo "The Persistant Volume does not seem to exist or is not bound" 36 | echo "Creating Persistant Volume" 37 | 38 | if [ "$1" == "--paid" ]; then 39 | echo "You passed argument --paid. Make sure you have an IBM Cloud Kubernetes - Standard tier. Else, remove --paid option" 40 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/createVolume-paid.yaml" 41 | kubectl create -f ${KUBECONFIG_FOLDER}/createVolume-paid.yaml 42 | sleep 5 43 | else 44 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/createVolume.yaml" 45 | kubectl create -f ${KUBECONFIG_FOLDER}/createVolume.yaml 46 | sleep 5 47 | fi 48 | 49 | if [ "kubectl get pvc | grep shared-pvc | awk '{print $3}'" != "shared-pv" ]; then 50 | echo "Success creating Persistant Volume" 51 | else 52 | echo "Failed to create Persistant Volume" 53 | fi 54 | else 55 | echo "The Persistant Volume exists, not creating again" 56 | fi 57 | 58 | # Copy the required files(configtx.yaml, cruypto-config.yaml, sample chaincode etc.) into volume 59 | echo -e "\nCreating Copy artifacts job." 60 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/copyArtifactsJob.yaml" 61 | kubectl create -f ${KUBECONFIG_FOLDER}/copyArtifactsJob.yaml 62 | 63 | pod=$(kubectl get pods --selector=job-name=copyartifacts --output=jsonpath={.items..metadata.name}) 64 | 65 | podSTATUS=$(kubectl get pods --selector=job-name=copyartifacts --output=jsonpath={.items..phase}) 66 | 67 | while [ "${podSTATUS}" != "Running" ]; do 68 | echo "Wating for container of copy artifact pod to run. Current status of ${pod} is ${podSTATUS}" 69 | sleep 5; 70 | if [ "${podSTATUS}" == "Error" ]; then 71 | echo "There is an error in copyartifacts job. Please check logs." 72 | exit 1 73 | fi 74 | podSTATUS=$(kubectl get pods --selector=job-name=copyartifacts --output=jsonpath={.items..phase}) 75 | done 76 | 77 | echo -e "${pod} is now ${podSTATUS}" 78 | echo -e "\nStarting to copy artifacts in persistent volume." 79 | 80 | #fix for this script to work on icp and ICS 81 | kubectl cp ./artifacts $pod:/shared/ 82 | 83 | echo "Waiting for 10 more seconds for copying artifacts to avoid any network delay" 84 | sleep 10 85 | JOBSTATUS=$(kubectl get jobs |grep "copyartifacts" |awk '{print $2}') 86 | while [ "${JOBSTATUS}" != "1/1" ]; do 87 | echo "Waiting for copyartifacts job to complete" 88 | sleep 1; 89 | PODSTATUS=$(kubectl get pods | grep "copyartifacts" | awk '{print $3}') 90 | if [ "${PODSTATUS}" == "Error" ]; then 91 | echo "There is an error in copyartifacts job. Please check logs." 92 | exit 1 93 | fi 94 | JOBSTATUS=$(kubectl get jobs |grep "copyartifacts" |awk '{print $2}') 95 | done 96 | echo "Copy artifacts job completed" 97 | 98 | 99 | # Generate Network artifacts using configtx.yaml and crypto-config.yaml 100 | echo -e "\nGenerating the required artifacts for Blockchain network" 101 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/generateArtifactsJob.yaml" 102 | kubectl create -f ${KUBECONFIG_FOLDER}/generateArtifactsJob.yaml 103 | 104 | JOBSTATUS=$(kubectl get jobs |grep utils|awk '{print $2}') 105 | while [ "${JOBSTATUS}" != "1/1" ]; do 106 | echo "Waiting for generateArtifacts job to complete" 107 | sleep 1; 108 | # UTILSLEFT=$(kubectl get pods | grep utils | awk '{print $2}') 109 | UTILSSTATUS=$(kubectl get pods | grep "utils" | awk '{print $3}') 110 | if [ "${UTILSSTATUS}" == "Error" ]; then 111 | echo "There is an error in utils job. Please check logs." 112 | exit 1 113 | fi 114 | # UTILSLEFT=$(kubectl get pods | grep utils | awk '{print $2}') 115 | JOBSTATUS=$(kubectl get jobs |grep utils|awk '{print $2}') 116 | done 117 | 118 | 119 | # Create services for all peers, ca, orderer 120 | echo -e "\nCreating Services for blockchain network" 121 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/blockchain-services.yaml" 122 | kubectl create -f ${KUBECONFIG_FOLDER}/blockchain-services.yaml 123 | 124 | 125 | # Create peers, ca, orderer using Kubernetes Deployments 126 | echo -e "\nCreating new Deployment to create four peers in network" 127 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/peersDeployment.yaml" 128 | kubectl create -f ${KUBECONFIG_FOLDER}/peersDeployment.yaml 129 | 130 | echo "Checking if all deployments are ready" 131 | 132 | NUMPENDING=$(kubectl get deployments | grep blockchain | awk '{print $5}' | grep 0 | wc -l | awk '{print $1}') 133 | while [ "${NUMPENDING}" != "0" ]; do 134 | echo "Waiting on pending deployments. Deployments pending = ${NUMPENDING}" 135 | NUMPENDING=$(kubectl get deployments | grep blockchain | awk '{print $5}' | grep 0 | wc -l | awk '{print $1}') 136 | sleep 1 137 | done 138 | 139 | echo "Waiting for 15 seconds for peers and orderer to settle" 140 | sleep 15 141 | 142 | 143 | # Generate channel artifacts using configtx.yaml and then create channel 144 | echo -e "\nCreating channel transaction artifact and a channel" 145 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/create_channel.yaml" 146 | kubectl create -f ${KUBECONFIG_FOLDER}/create_channel.yaml 147 | 148 | JOBSTATUS=$(kubectl get jobs |grep createchannel |awk '{print $2}') 149 | while [ "${JOBSTATUS}" != "1/1" ]; do 150 | echo "Waiting for createchannel job to be completed" 151 | sleep 1; 152 | if [ "$(kubectl get pods | grep createchannel | awk '{print $3}')" == "Error" ]; then 153 | echo "Create Channel Failed" 154 | exit 1 155 | fi 156 | JOBSTATUS=$(kubectl get jobs |grep createchannel |awk '{print $2}') 157 | done 158 | echo "Create Channel Completed Successfully" 159 | 160 | 161 | # Join all peers on a channel 162 | echo -e "\nCreating joinchannel job" 163 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/join_channel.yaml" 164 | kubectl create -f ${KUBECONFIG_FOLDER}/join_channel.yaml 165 | 166 | JOBSTATUS=$(kubectl get jobs |grep joinchannel |awk '{print $2}') 167 | while [ "${JOBSTATUS}" != "1/1" ]; do 168 | echo "Waiting for joinchannel job to be completed" 169 | sleep 1; 170 | if [ "$(kubectl get pods | grep joinchannel | awk '{print $3}')" == "Error" ]; then 171 | echo "Join Channel Failed" 172 | exit 1 173 | fi 174 | JOBSTATUS=$(kubectl get jobs |grep joinchannel |awk '{print $2}') 175 | done 176 | echo "Join Channel Completed Successfully" 177 | 178 | 179 | # Install chaincode on each peer 180 | echo -e "\nCreating installchaincode job" 181 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/chaincode_install.yaml" 182 | kubectl create -f ${KUBECONFIG_FOLDER}/chaincode_install.yaml 183 | 184 | JOBSTATUS=$(kubectl get jobs |grep chaincodeinstall |awk '{print $2}') 185 | while [ "${JOBSTATUS}" != "1/1" ]; do 186 | echo "Waiting for chaincodeinstall job to be completed" 187 | sleep 1; 188 | if [ "$(kubectl get pods | grep chaincodeinstall | awk '{print $3}')" == "Error" ]; then 189 | echo "Chaincode Install Failed" 190 | exit 1 191 | fi 192 | JOBSTATUS=$(kubectl get jobs |grep chaincodeinstall |awk '{print $2}') 193 | done 194 | echo "Chaincode Install Completed Successfully" 195 | 196 | 197 | # Instantiate chaincode on channel 198 | echo -e "\nCreating chaincodeinstantiate job" 199 | echo "Running: kubectl create -f ${KUBECONFIG_FOLDER}/chaincode_instantiate.yaml" 200 | kubectl create -f ${KUBECONFIG_FOLDER}/chaincode_instantiate.yaml 201 | 202 | JOBSTATUS=$(kubectl get jobs |grep chaincodeinstantiate |awk '{print $2}') 203 | while [ "${JOBSTATUS}" != "1/1" ]; do 204 | echo "Waiting for chaincodeinstantiate job to be completed" 205 | sleep 1; 206 | if [ "$(kubectl get pods | grep chaincodeinstantiate | awk '{print $3}')" == "Error" ]; then 207 | echo "Chaincode Instantiation Failed" 208 | exit 1 209 | fi 210 | JOBSTATUS=$(kubectl get jobs |grep chaincodeinstantiate |awk '{print $2}') 211 | done 212 | echo "Chaincode Instantiation Completed Successfully" 213 | 214 | sleep 15 215 | echo -e "\nNetwork Setup Completed !!" 216 | --------------------------------------------------------------------------------