Skip to main content

Compound Promises

Compound Promises are Promises that, in its Dependencies, contain other Promises. That ability allows Platform teams deliver entire stacks on demand, instead of simple databases or services.

In this tutorial, you will

  1. encapsulate multiple Promises into a Compound Promise

  2. request a complete development environment Resource through a Compound Promise

    Pre-requisites

    You need an installation of Kratix for this section. Click here for instructions

    The simplest way to do so is by running the quick-start script from within the Kratix directory. The script will create two KinD clusters, install, and configure Kratix.

    ./scripts/quick-start.sh --recreate

    You can run Kratix either with a multi-cluster or a single-cluster setup. The commands on the remainder of this document assume that two environment variables are set:

    1. PLATFORM representing the platform cluster Kubernetes context
    2. WORKER representing the worker cluster Kubernetes context

    If you ran the quick-start script above, do:

    export PLATFORM="kind-platform"
    export WORKER="kind-worker"

    For single cluster setups, the two variables should be set to the same value. You can find your cluster context by running:

    kubectl config get-contexts

    Refer back to Installing Kratix for more details.

Register the Platform as a Worker

To install a Compound Promises, the first step is to register the platform cluster itself as an available Destination. That's because the Dependencies for the Compound Promises are Promises themselves, therefore they need to be scheduled to the platform cluster.

Create a new Destination document platform-cluster.yaml with the following contents:

platform-cluster.yaml
apiVersion: platform.kratix.io/v1alpha1
kind: Destination
metadata:
name: platform-cluster
labels:
environment: platform
spec:
strictMatchLabels: true
stateStoreRef:
name: default
kind: BucketStateStore

Register the Destination:

kubectl --context $PLATFORM apply --filename platform-cluster.yaml

Install and configure GitOps

For the platform cluster to sync as a worker, you will need to install the GitOps toolkit in it. The quickest way to do that is to run the ./scripts/install-gitops script from the Kratix root directory:

cd /path/to/kratix
./scripts/install-gitops --context $PLATFORM --path platform-cluster

Install a Compound Promise

You can now install a "Paved Path" Promise:

kubectl --context $PLATFORM apply --filename https://raw.githubusercontent.com/syntasso/kratix/main/samples/paved-path-demo/paved-path-demo-promise.yaml

This Promise is composed of a Knative and Postgres. Installing the Promise on the Platform will have the following side-effects:

  • Three Promises will be scheduled to the platform Destination: Paved Path, Knative and Postgres.
  • The Knative and Postgres's Dependencies will be scheduled to the worker Destination

To verify the installation was successful, run:

$ kubectl --context $PLATFORM get promises
NAME STATUS KIND API VERSION VERSION
knative Available knative marketplace.kratix.io/v1alpha1
paved-path-demo-promise Available paved-path-demo example.promise.syntasso.io/v1
postgresql Available postgresql marketplace.kratix.io/v1alpha1

$ kubectl --context $WORKER get pods
NAME READY STATUS RESTARTS AGE
postgres-operator-6c6dbd4459-kv5lw 1/1 Running 0 1h

$ kubectl --context $WORKER get crds | grep knative
certificates.networking.internal.knative.dev 2022-11-25T12:24:20Z
clusterdomainclaims.networking.internal.knative.dev 2022-11-25T12:24:20Z
...

Send a request for a Resource

Platform users can now send requests for a new "Paved Path" Resource. That will create a new Knative Serving and a new Postgres database in the worker cluster:

kubectl --context $PLATFORM apply --filename https://raw.githubusercontent.com/syntasso/kratix/main/samples/paved-path-demo/paved-path-demo-resource-request.yaml

You can see the Workflow for the Paved Path Promise running, which will in turn trigger the Knative and Postgres Workflows:

$ kubectl --context $PLATFORM get pods
NAMESPACE NAME READY STATUS RESTARTS AGE
default configure-pipeline-knative-66cf1-g4kx7 0/1 Completed 0 28s
default configure-pipeline-paved-path-demo-promise-d8e6e-58grl 0/1 Completed 0 36s
default configure-pipeline-postgresql-4e937-bnnpb 0/1 Completed 0 28s

Eventually, the resources will be ready to be used:

$ kubectl --context $WORKER get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
default acid-minimal-cluster-0 1/1 Running 0 1h
default acid-minimal-cluster-1 1/1 Running 0 1h
...
knative-serving activator-7d967fb5f4-4k4m5 1/1 Running 0 1h
knative-serving autoscaler-684b55df5f-7gw86 1/1 Running 0 1h
knative-serving controller-65866d54fc-zfh8d 1/1 Running 0 1h
knative-serving default-domain-dl972 0/1 Completed 0 1h
...

🎉 Congratulations: you have installed a Compound Promise and requested a Paved Path Resource!

A closer look in the Promise

Start by noticing the dependencies for the Paved Path Promise:

apiVersion: platform.kratix.io/v1alpha1
kind: Promise
metadata:
name: paved-path-demo-promise
spec:
destinationSelectors:
- matchLabels:
environment: platform
dependencies:
- apiVersion: platform.kratix.io/v1alpha1
kind: Promise
metadata:
name: knative
spec:
destinationSelectors:
- matchLabels:
environment: dev
dependencies:
... # remainder of the knative Promise
- apiVersion: platform.kratix.io/v1alpha1
kind: Promise
metadata:
name: postgres
spec:
destinationSelectors:
- matchLabels:
environment: dev
dependencies:
... # remainder of the postgres Promise
... # remainder of the paved path Promise...

Since Paved Path Promise Dependencies are Promises, and considering that Kratix and its CRDs (Custom Resource Definitions) are only installed in the platform cluster, you need to ensure the Dependencies are applied exclusively to the platform cluster.

That is controlled by the destinationSelectors key:

apiVersion: platform.kratix.io/v1alpha1
kind: Promise
metadata:
name: paved-path-demo-promise
spec:
destinationSelectors:
- matchLabels:
environment: platform
dependencies:
- # knative Promise
- # postgres Promise
... # remainder of the paved path Promise

The Paved Path Promise destinationSelectors is set to target clusters with matchLabel equal to environment: platform. In other words, that is telling Kratix to install the sub-Promises into Destinations with an environment: platform label.

You may have noticed that, when registering the Platform Destination, the Destination definition included exactly that label. You can verify the applied labels with:

$ kubectl --context $PLATFORM get destinations.platform.kratix.io --show-labels
NAME AGE LABELS
platform-cluster 1hr environment=platform
worker-1 1hr environment=dev

However, the sub-Promises' Dependencies (i.e. the Knative and Postgres Dependencies) should not be installed in the platform cluster, but in the worker cluster. When you executed the quick start script, it registered the worker cluster as a Destination with a label environment: dev (as per output above). The destinationSelectors field in the sub-Promises are set to target those clusters:

apiVersion: platform.kratix.io/v1alpha1
kind: Promise
metadata:
name: paved-path-demo-promise
spec:
destinationSelectors:
- matchLabels:
environment: platform
dependencies:
- apiVersion: platform.kratix.io/v1alpha1
kind: Promise
metadata:
name: knative
spec:
destinationSelectors:
- matchLabels:
environment: dev
dependencies:
... # remainder of the knative Promise
- apiVersion: platform.kratix.io/v1alpha1
kind: Promise
metadata:
name: postgres
spec:
destinationSelectors:
- matchLabels:
environment: dev
dependencies:
... # remainder of the postgres Promise ...
... # remainder of the paved path Promise...

This configuration ensures the Knative CRDs and the Postgres Operator are installed exclusively in the worker. This is how, when installing the Paved Path Promise, Kratix knew it should install the sub-Promises in the platform cluster and the sub-Promises' Dependencies in the worker.

A closer look in the Workflow

When a request for a Resource is created, the Paved Path Workflow is triggered. Usually, the output of the Workflow is a set of Kubernetes Resources that need to be created. For Compound Promises, that's usually a set of requests for other promised Resources to be applied in the Platform itself.

The Paved Path Promise is a very basic example, but you can see that's exactly what the Workflow Pipeline is doing in its Dockerfile.

🎉 Congratulations

✅   You have just installed and used your first Compound Promise.
👉   Let's see where to go from here.