hyperledger-labs / fabric-builder-k8s

Kubernetes chaincode builder for Hyperledger Fabric
https://labs.hyperledger.org/fabric-builder-k8s/
Apache License 2.0
27 stars 20 forks source link

Implement Just-In-Time building and execution of chaincode within a Kubernetes job #127

Open y12studio opened 3 months ago

y12studio commented 3 months ago

Is it possible to enhance the developer experience by implementing Just-In-Time (JIT) compilation and execution of chaincode within a Kubernetes job? Below is some pseudocode for OCI artifacts, though using an HTTP URL might be acceptable as well.

cat << IMAGEJSON-EOF > image.json
{
  "name": "ghcr.io/hyperledger-labs/jit-chaincode",
  "digest": "sha256:802c336235cc1e7347e2da36c73fa2e4b6437cfc6f52872674d1e23f23bba63b"
}
IMAGEJSON-EOF
cat << METADATAJSON-EOF > metadata.json
{
    "type": "k8s",
    "label": "go-contract"
    "jit_artifact_url":  "localhost:5000/hello-artifact:latest"
}
METADATAJSON-EOF

chaincode build and publish

mkdir chaincode
echo "Chaincode on this artifact" > ./chaincode/source.code
echo "Chaincode build script on this artifact" > ./chaincode/build
echo "Chaincode release script on this artifact" > ./chaincode/release
echo "Chaincode run script on this artifact" > ./chaincode/run
echo "Chaincode content for this artifact" > ./chaincode/readme.md
echo "{\"doc\":\"readme.md\"}" > config.json

oras push localhost:5000/hello-artifact:latest \
  --config config.json:application/vnd.acme.rocket.config.v1+json \
  artifact.txt:text/plain \
  ./docs/:application/vnd.acme.rocket.docs.layer.v1+tar

JIT Job yaml example of getChaincodeJobSpec()

apiVersion: batch/v1
kind: Job
metadata:
  name: chaincode
spec:
  template:
    spec:
      initContainers:
      - name: just-in-time
        image: alpine
        command: ["/bin/sh", "-c"]
        args:
        - |
          oras manifest fetch localhost:5000/hello-artifact:latest
          oras pull localhost:5000/hello-artifact:latest
          ./build
          ./release
        volumeMounts:
        - name: artifact-volume
          mountPath: /artifact
      containers:
      - name: create-db
        image: postgres
        command: ["/bin/sh", "-c"]
        args:
        - |
          ./run
        volumeMounts:
        - name: artifact-volume
          mountPath: /artifact
      volumes:
      - name: artifact-volume
        emptyDir: {}

refs

jt-nti commented 2 months ago

Hi @y12studio, thanks for opening the issue. Adding some sort of development mode was something we considered previously (see #29). I'm even more convinced now than I was then that the chaincode as a server (ccaas) builder is the right option for chaincode development- it's now provided in core Fabric and, once it's set up, gives you a really tight develop/test/debug loop since there is no docker build/publish step at all, and no need to go round the chaincode lifecycle loop either. I definitely think the ccaas builder workflow could be improved in terms of getting it set up to begin with, but would that address your use case?

y12studio commented 2 months ago

Hi @jt-nti , thank you for sharing your thoughts on the chaincode-as-a-server (ccaas) builder. I completely agree that the ccaas builder provided in core Fabric significantly simplifies the develop/test/debug loop by eliminating the need for the Docker build/publish step and bypassing the chaincode lifecycle loop. This makes it a compelling option for chaincode development.

However, there are a few nuances to consider. First, the ccaas_builder external builder requires the chaincode to integrate with the gRPC ChaincodeServer, which is not a necessity for the k8s_builder external builder. As a result, developers may have to manage two versions of their chaincode: one for ccaas_builder and another for k8s_builder.

Furthermore, the configuration requirements vary between the two builders. For example, the connection.json file included in the chaincode package is not required for k8s_builder, which means two versions of the configuration also need to be maintained.

Although the ccaas builder workflow offers significant advantages, it might be worth considering enhancements to the build/release/run process within the Kubernetes job of k8s_builder to make it more developer-friendly. This is purely a suggestion and does not require adoption.

jt-nti commented 2 months ago

Hi @y12studio, there are definitely some differences between deploying with the k8s and ccaas builder, and making the k8s builder as developer friendly as possible would be good.

I think it's possible for chaincode to run unchanged in either client or server mode with the latest contract APIs though, which would help. If so, it would definitely be good to update the samples to make it obvious how to achieve that.

Building and deploying chaincode with the k8s builder in a development environment isn't too bad with the Fabric samples Kubernetes test network, e.g.

./network chaincode deploy sample-contract <path_to_contract_source>

Adding a new tutorial to the documentation to cover the chaincode developer experience might identify other enhancements that could be made without breaking the k8s builder's link to the Fabric chaincode lifecycle.

y12studio commented 2 months ago

Enhancing the documentation for chaincode developers using k8s_builder might be the best solution. From your explanation, I now understand that this model could potentially cause confusion or disruption to the existing process. The complexity of the multi-build-release-run process contributing to this confusion was an issue I hadn't considered before.