From 4c776b5d83ca667a774f9de477c52af30979ac5f Mon Sep 17 00:00:00 2001 From: James Taylor Date: Tue, 30 Jan 2024 18:51:52 +0000 Subject: [PATCH] [WIP] Create doc site Resolves #66 Signed-off-by: James Taylor --- .devcontainer/devcontainer.json | 26 +++ .github/dependabot.yml | 12 ++ README.md | 161 ---------------- docs/assets/project-icon.png | Bin 0 -> 16206 bytes docs/assets/project-logo.png | Bin 0 -> 3770 bytes docs/index.md | 178 ++++++++++++++++++ .../fabric-operator.md} | 0 .../hlf-operator.md} | 0 .../test-network-k8s.md} | 0 .../test-network-nano.md} | 0 mkdocs.yml | 86 +++++++++ overrides/main.html | 8 + requirements.txt | 2 + 13 files changed, 312 insertions(+), 161 deletions(-) create mode 100644 .devcontainer/devcontainer.json create mode 100644 .github/dependabot.yml create mode 100644 docs/assets/project-icon.png create mode 100644 docs/assets/project-logo.png create mode 100644 docs/index.md rename docs/{FABRIC_OPERATOR.md => tutorials/fabric-operator.md} (100%) rename docs/{HLF_OPERATOR.md => tutorials/hlf-operator.md} (100%) rename docs/{TEST_NETWORK_K8S.md => tutorials/test-network-k8s.md} (100%) rename docs/{TEST_NETWORK_NANO.md => tutorials/test-network-nano.md} (100%) create mode 100644 mkdocs.yml create mode 100644 overrides/main.html create mode 100644 requirements.txt diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..fb66949 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,26 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/python +{ + "name": "Fabric k8s builder", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/python:1-3.12-bullseye", + + // Features to add to the dev container. More info: https://containers.dev/features. + "features": { + "ghcr.io/devcontainers-contrib/features/mkdocs:2": { + "plugins": "mkdocs-material mike" + } + } + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "pip3 install --user -r requirements.txt", + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..f33a02c --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for more information: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates +# https://containers.dev/guide/dependabot + +version: 2 +updates: + - package-ecosystem: "devcontainers" + directory: "/" + schedule: + interval: weekly diff --git a/README.md b/README.md index 50e8709..9513923 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,6 @@ Kubernetes [external chaincode builder](https://hyperledger-fabric.readthedocs.io/en/latest/cc_launcher.html) for Hyperledger Fabric. -With the k8s builder, the Fabric administrator is responsible for [preparing a chaincode image](#chaincode-docker-image), publishing to a container registry, and [preparing a chaincode package](#chaincode-package) with coordinates of the contract's immutable image digest. -When Fabric detects the installation of a `type=k8s` contract, the builder assumes full ownership of the lifecycle of pods, containers, and network linkages necessary to communicate securely with the peer. - - Advantages: 🚀 Chaincode runs _immediately_ on channel commit. @@ -19,160 +15,3 @@ Advantages: 🛡️ Pre-published chaincode images remove any and all dependencies on a root-level _docker daemon_. 🕵️ Pre-published chaincode images provide traceability and change management features (e.g. Git commit hash as image tag) - -The aim is for the builder to work as closely as possible with the existing [Fabric chaincode lifecycle](https://hyperledger-fabric.readthedocs.io/en/latest/chaincode_lifecycle.html), making sensible compromises for deploying chaincode on Kubernetes within those constraints. -(The assumption being that there are more people with Kubernetes skills than are familiar with the inner workings of Fabric!) - -For example: - -- The contents of the chaincode package must uniquely identify the chaincode functions executed on the ledger. - - In the case of the k8s builder the chaincode source code is not actually inside the package. In order not to break the Fabric chaincode lifecycle, the chaincode image must be specified using an immutable `@digest`, not a `:label` which can be altered post commit. - - See [Pull an image by digest (immutable identifier)](https://docs.docker.com/engine/reference/commandline/pull/#pull-an-image-by-digest-immutable-identifier) for more details. - - -- The Fabric peer manages the chaincode process, not Kubernetes. - - Running the chaincode in server mode, i.e. allowing the peer to initiate the gRPC connection, would make it possible to leave Kubernetes to manage the chaincode process by creating a chaincode deployment. - - Unfortunately due to limitations in Fabric's builder and launcher implementation, that is not possible and the peer expects to control the chaincode process. - - -**Status:** the k8s builder is [close to a version 1 release](https://github.com/hyperledger-labs/fabric-builder-k8s/milestone/1) and has been tested in a number of Kubernetes environments, deployment platforms, and provides semantic-revision aware [release tags](https://github.com/hyperledger-labs/fabric-builder-k8s/tags) for the external builder binaries. -The current status should be considered as STABLE and any bugs or enhancements delivered as GitHub Issues in conjunction with community PRs. - -## Usage - -The k8s builder can be run in cluster using the `KUBERNETES_SERVICE_HOST` and `KUBERNETES_SERVICE_PORT` environment variables, or it can connect using a `KUBECONFIG_PATH` environment variable. - -The following optional environment variables can be used to configure the k8s builder: - -- `FABRIC_K8S_BUILDER_DEBUG` whether to enable additional logging -- `FABRIC_K8S_BUILDER_NAMESPACE` specifies the namespace to deploy chaincode to -- `FABRIC_K8S_BUILDER_SERVICE_ACCOUNT` specifies the service account for the chaincode pod - -A `CORE_PEER_ID` environment variable is also currently required. - -External builders are configured in the `core.yaml` file, for example: - -``` - externalBuilders: - - name: k8s_builder - path: /opt/hyperledger/k8s_builder - propagateEnvironment: - - CORE_PEER_ID - - FABRIC_K8S_BUILDER_DEBUG - - FABRIC_K8S_BUILDER_NAMESPACE - - FABRIC_K8S_BUILDER_SERVICE_ACCOUNT - - KUBERNETES_SERVICE_HOST - - KUBERNETES_SERVICE_PORT -``` - -See [External Builders and Launchers](https://hyperledger-fabric.readthedocs.io/en/latest/cc_launcher.html) for details of Hyperledger Fabric builders. - -As well as configuring Fabric to use the k8s builder, you will need to [configure Kubernetes](docs/KUBERNETES_CONFIG.md) to allow the builder to start chaincode pods successfully. - -There are addition docs with more detailed usage instructions for specific Fabric network deployments: - -- [Kubernetes Test Network](docs/TEST_NETWORK_K8S.md) -- [Nano Test Network](docs/TEST_NETWORK_NANO.md) -- [Fabric Operator](docs/FABRIC_OPERATOR.md) -- [HLF Operator](docs/HLF_OPERATOR.md) - -## Chaincode Docker image - -Unlike the traditional chaincode language support for Go, Java, and Node.js, the k8s builder *does not* build a chaincode Docker image using Docker-in-Docker. -Instead, a chaincode Docker image must be built and published before it can be used with the k8s builder. - -The chaincode will have access to the following environment variables: - -- CORE_CHAINCODE_ID_NAME -- CORE_PEER_ADDRESS -- CORE_PEER_TLS_ENABLED -- CORE_PEER_TLS_ROOTCERT_FILE -- CORE_TLS_CLIENT_KEY_PATH -- CORE_TLS_CLIENT_CERT_PATH -- CORE_TLS_CLIENT_KEY_FILE -- CORE_TLS_CLIENT_CERT_FILE -- CORE_PEER_LOCALMSPID - -See the [sample contracts for Go, Java, and Node.js](samples/README.md) for basic docker images which will work with the k8s builder. - -## Chaincode package - -The k8s chaincode package file, which is installed by the `peer lifecycle chaincode install` command, must contain the Docker image name and digest of the chaincode being deployed. - -[Fabric chaincode packages](https://hyperledger-fabric.readthedocs.io/en/latest/cc_launcher.html#chaincode-packages) are `.tgz` files which contain two files: - -- metadata.json - the chaincode label and type -- code.tar.gz - source artifacts for the chaincode - -To create a k8s chaincode package file, start by creating an `image.json` file. -For example, - -```shell -cat << IMAGEJSON-EOF > image.json -{ - "name": "ghcr.io/hyperledger-labs/go-contract", - "digest": "sha256:802c336235cc1e7347e2da36c73fa2e4b6437cfc6f52872674d1e23f23bba63b" -} -IMAGEJSON-EOF -``` - -Note: the k8s chaincode package file uses digests because these are immutable, unlike tags. -The docker inspect command can be used to find the digest if required. - -``` -docker pull ghcr.io/hyperledger-labs/go-contract:v0.7.2 -docker inspect --format='{{index .RepoDigests 0}}' ghcr.io/hyperledger-labs/go-contract:v0.7.2 | cut -d'@' -f2 -``` - -Create a `code.tar.gz` archive containing the `image.json` file. - -```shell -tar -czf code.tar.gz image.json -``` - -Create a `metadata.json` file for the chaincode package. -For example, - -```shell -cat << METADATAJSON-EOF > metadata.json -{ - "type": "k8s", - "label": "go-contract" -} -METADATAJSON-EOF -``` - -Create the final chaincode package archive. - -```shell -tar -czf go-contract.tgz metadata.json code.tar.gz -``` - -Ideally the chaincode package should be created in the same CI/CD pipeline which builds the docker image. -There is an example [package-k8s-chaincode-action](https://github.com/hyperledgendary/package-k8s-chaincode-action) GitHub Action which can create the required k8s chaincode package. - -The GitHub Action repository includes a basic shell script which can also be used for automating the process above outside GitHub workflows. -For example, to create a basic k8s chaincode package using the `pkgk8scc.sh` helper script. - -```shell -curl -fsSL https://raw.githubusercontent.com/hyperledgendary/package-k8s-chaincode-action/main/pkgk8scc.sh -o pkgk8scc.sh && chmod u+x pkgk8scc.sh -./pkgk8scc.sh -l go-contract -n ghcr.io/hyperledger-labs/go-contract -d sha256:802c336235cc1e7347e2da36c73fa2e4b6437cfc6f52872674d1e23f23bba63b -``` - -## Chaincode deploy - -Deploy the chaincode package as usual, starting by installing the k8s chaincode package. - -```shell -peer lifecycle chaincode install go-contract.tgz -``` - -You can also use the `peer` command to get the chaincode package ID. - -```shell -export PACKAGE_ID=$(peer lifecycle chaincode calculatepackageid go-contract.tgz) && echo $PACKAGE_ID -``` diff --git a/docs/assets/project-icon.png b/docs/assets/project-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7266b044e26078cd482c174531cd65188e87b7f1 GIT binary patch literal 16206 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 literal 0 HcmV?d00001 diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..770e9da --- /dev/null +++ b/docs/index.md @@ -0,0 +1,178 @@ +# Introduction + +Kubernetes [external chaincode builder](https://hyperledger-fabric.readthedocs.io/en/latest/cc_launcher.html) for Hyperledger Fabric. + +With the k8s builder, the Fabric administrator is responsible for [preparing a chaincode image](#chaincode-docker-image), publishing to a container registry, and [preparing a chaincode package](#chaincode-package) with coordinates of the contract's immutable image digest. +When Fabric detects the installation of a `type=k8s` contract, the builder assumes full ownership of the lifecycle of pods, containers, and network linkages necessary to communicate securely with the peer. + + +Advantages: + +🚀 Chaincode runs _immediately_ on channel commit. + +✨ Avoids the complexity and administrative burdens associated with Chaincode-as-a-Service. + +🔥 Pre-published chaincode images avoid code-compilation errors at deployment time. + +🏗️ Pre-published chaincode images encourage modern, industry accepted CI/CD best practices. + +🛡️ Pre-published chaincode images remove any and all dependencies on a root-level _docker daemon_. + +🕵️ Pre-published chaincode images provide traceability and change management features (e.g. Git commit hash as image tag) + +The aim is for the builder to work as closely as possible with the existing [Fabric chaincode lifecycle](https://hyperledger-fabric.readthedocs.io/en/latest/chaincode_lifecycle.html), making sensible compromises for deploying chaincode on Kubernetes within those constraints. +(The assumption being that there are more people with Kubernetes skills than are familiar with the inner workings of Fabric!) + +For example: + +- The contents of the chaincode package must uniquely identify the chaincode functions executed on the ledger. + + In the case of the k8s builder the chaincode source code is not actually inside the package. In order not to break the Fabric chaincode lifecycle, the chaincode image must be specified using an immutable `@digest`, not a `:label` which can be altered post commit. + + See [Pull an image by digest (immutable identifier)](https://docs.docker.com/engine/reference/commandline/pull/#pull-an-image-by-digest-immutable-identifier) for more details. + + +- The Fabric peer manages the chaincode process, not Kubernetes. + + Running the chaincode in server mode, i.e. allowing the peer to initiate the gRPC connection, would make it possible to leave Kubernetes to manage the chaincode process by creating a chaincode deployment. + + Unfortunately due to limitations in Fabric's builder and launcher implementation, that is not possible and the peer expects to control the chaincode process. + + +**Status:** the k8s builder is [close to a version 1 release](https://github.com/hyperledger-labs/fabric-builder-k8s/milestone/1) and has been tested in a number of Kubernetes environments, deployment platforms, and provides semantic-revision aware [release tags](https://github.com/hyperledger-labs/fabric-builder-k8s/tags) for the external builder binaries. +The current status should be considered as STABLE and any bugs or enhancements delivered as GitHub Issues in conjunction with community PRs. + +## Usage + +The k8s builder can be run in cluster using the `KUBERNETES_SERVICE_HOST` and `KUBERNETES_SERVICE_PORT` environment variables, or it can connect using a `KUBECONFIG_PATH` environment variable. + +The following optional environment variables can be used to configure the k8s builder: + +- `FABRIC_K8S_BUILDER_DEBUG` whether to enable additional logging +- `FABRIC_K8S_BUILDER_NAMESPACE` specifies the namespace to deploy chaincode to +- `FABRIC_K8S_BUILDER_SERVICE_ACCOUNT` specifies the service account for the chaincode pod + +A `CORE_PEER_ID` environment variable is also currently required. + +External builders are configured in the `core.yaml` file, for example: + +``` + externalBuilders: + - name: k8s_builder + path: /opt/hyperledger/k8s_builder + propagateEnvironment: + - CORE_PEER_ID + - FABRIC_K8S_BUILDER_DEBUG + - FABRIC_K8S_BUILDER_NAMESPACE + - FABRIC_K8S_BUILDER_SERVICE_ACCOUNT + - KUBERNETES_SERVICE_HOST + - KUBERNETES_SERVICE_PORT +``` + +See [External Builders and Launchers](https://hyperledger-fabric.readthedocs.io/en/latest/cc_launcher.html) for details of Hyperledger Fabric builders. + +As well as configuring Fabric to use the k8s builder, you will need to [configure Kubernetes](docs/KUBERNETES_CONFIG.md) to allow the builder to start chaincode pods successfully. + +There are addition docs with more detailed usage instructions for specific Fabric network deployments: + +- [Kubernetes Test Network](../tutorials/test-network-k8s.md) +- [Nano Test Network](../tutorials/test-network-nano.md) +- [Fabric Operator](../tutorials/fabric-operator.md) +- [HLF Operator](../tutorials/hlf-operator.md) + +## Chaincode Docker image + +Unlike the traditional chaincode language support for Go, Java, and Node.js, the k8s builder *does not* build a chaincode Docker image using Docker-in-Docker. +Instead, a chaincode Docker image must be built and published before it can be used with the k8s builder. + +The chaincode will have access to the following environment variables: + +- CORE_CHAINCODE_ID_NAME +- CORE_PEER_ADDRESS +- CORE_PEER_TLS_ENABLED +- CORE_PEER_TLS_ROOTCERT_FILE +- CORE_TLS_CLIENT_KEY_PATH +- CORE_TLS_CLIENT_CERT_PATH +- CORE_TLS_CLIENT_KEY_FILE +- CORE_TLS_CLIENT_CERT_FILE +- CORE_PEER_LOCALMSPID + +See the [sample contracts for Go, Java, and Node.js](samples/README.md) for basic docker images which will work with the k8s builder. + +## Chaincode package + +The k8s chaincode package file, which is installed by the `peer lifecycle chaincode install` command, must contain the Docker image name and digest of the chaincode being deployed. + +[Fabric chaincode packages](https://hyperledger-fabric.readthedocs.io/en/latest/cc_launcher.html#chaincode-packages) are `.tgz` files which contain two files: + +- metadata.json - the chaincode label and type +- code.tar.gz - source artifacts for the chaincode + +To create a k8s chaincode package file, start by creating an `image.json` file. +For example, + +```shell +cat << IMAGEJSON-EOF > image.json +{ + "name": "ghcr.io/hyperledger-labs/go-contract", + "digest": "sha256:802c336235cc1e7347e2da36c73fa2e4b6437cfc6f52872674d1e23f23bba63b" +} +IMAGEJSON-EOF +``` + +Note: the k8s chaincode package file uses digests because these are immutable, unlike tags. +The docker inspect command can be used to find the digest if required. + +``` +docker pull ghcr.io/hyperledger-labs/go-contract:v0.7.2 +docker inspect --format='{{index .RepoDigests 0}}' ghcr.io/hyperledger-labs/go-contract:v0.7.2 | cut -d'@' -f2 +``` + +Create a `code.tar.gz` archive containing the `image.json` file. + +```shell +tar -czf code.tar.gz image.json +``` + +Create a `metadata.json` file for the chaincode package. +For example, + +```shell +cat << METADATAJSON-EOF > metadata.json +{ + "type": "k8s", + "label": "go-contract" +} +METADATAJSON-EOF +``` + +Create the final chaincode package archive. + +```shell +tar -czf go-contract.tgz metadata.json code.tar.gz +``` + +Ideally the chaincode package should be created in the same CI/CD pipeline which builds the docker image. +There is an example [package-k8s-chaincode-action](https://github.com/hyperledgendary/package-k8s-chaincode-action) GitHub Action which can create the required k8s chaincode package. + +The GitHub Action repository includes a basic shell script which can also be used for automating the process above outside GitHub workflows. +For example, to create a basic k8s chaincode package using the `pkgk8scc.sh` helper script. + +```shell +curl -fsSL https://raw.githubusercontent.com/hyperledgendary/package-k8s-chaincode-action/main/pkgk8scc.sh -o pkgk8scc.sh && chmod u+x pkgk8scc.sh +./pkgk8scc.sh -l go-contract -n ghcr.io/hyperledger-labs/go-contract -d sha256:802c336235cc1e7347e2da36c73fa2e4b6437cfc6f52872674d1e23f23bba63b +``` + +## Chaincode deploy + +Deploy the chaincode package as usual, starting by installing the k8s chaincode package. + +```shell +peer lifecycle chaincode install go-contract.tgz +``` + +You can also use the `peer` command to get the chaincode package ID. + +```shell +export PACKAGE_ID=$(peer lifecycle chaincode calculatepackageid go-contract.tgz) && echo $PACKAGE_ID +``` diff --git a/docs/FABRIC_OPERATOR.md b/docs/tutorials/fabric-operator.md similarity index 100% rename from docs/FABRIC_OPERATOR.md rename to docs/tutorials/fabric-operator.md diff --git a/docs/HLF_OPERATOR.md b/docs/tutorials/hlf-operator.md similarity index 100% rename from docs/HLF_OPERATOR.md rename to docs/tutorials/hlf-operator.md diff --git a/docs/TEST_NETWORK_K8S.md b/docs/tutorials/test-network-k8s.md similarity index 100% rename from docs/TEST_NETWORK_K8S.md rename to docs/tutorials/test-network-k8s.md diff --git a/docs/TEST_NETWORK_NANO.md b/docs/tutorials/test-network-nano.md similarity index 100% rename from docs/TEST_NETWORK_NANO.md rename to docs/tutorials/test-network-nano.md diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..4cd0831 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,86 @@ +site_name: Hyperledger Fabric Chaincode Builder for Kubernetes +repo_name: hyperledger-labs/fabric-builder-k8s +repo_url: https://github.com/hyperledger-labs/fabric-builder-k8s +theme: + name: material + custom_dir: overrides + logo: assets/project-logo.png + favicon: assets/project-icon.png + icon: + repo: fontawesome/brands/github + palette: + # Palette toggle for light mode + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/brightness-7 + name: Switch to dark mode + # Palette toggle for dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/brightness-4 + name: Switch to light mode + features: + - content.code.copy + - navigation.expand + - navigation.footer + - navigation.instant + - navigation.tabs + - navigation.tabs.sticky + - navigation.top + - navigation.tracking + - toc.follow + - toc.integrate +markdown_extensions: + - abbr + - admonition + - attr_list + - def_list + - footnotes + - md_in_html + - toc: + permalink: true + toc_depth: 3 + - pymdownx.arithmatex: + generic: true + - pymdownx.betterem: + smart_enable: all + - pymdownx.caret + - pymdownx.details + - pymdownx.emoji: + emoji_generator: !!python/name:materialx.emoji.to_svg + emoji_index: !!python/name:materialx.emoji.twemoji + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + - pymdownx.keys + - pymdownx.magiclink: + repo_url_shorthand: true + user: squidfunk + repo: mkdocs-material + - pymdownx.mark + - pymdownx.smartsymbols + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.tabbed: + alternate_style: true + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.tilde +plugins: + - search + - mike +extra: + version: + provider: mike +nav: + - Introduction: index.md + - Tutorials: + - Kubernetes Test Network: tutorials/test-network-k8s.md + - Nano Test Network: tutorials/test-network-nano.md + - Fabric Operator: tutorials/fabric-operator.md + - HLF Operator: tutorials/hlf-operator.md diff --git a/overrides/main.html b/overrides/main.html new file mode 100644 index 0000000..8d9f505 --- /dev/null +++ b/overrides/main.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} + +{% block outdated %} + You're not viewing the latest version. + + Click here to go to latest. + +{% endblock %} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..04ebb9b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +mkdocs-material +mike