Mastering Platform Engineering with Kratix
Tags: devops, sitereliabilityengineering, opensource, platformengineering
Published: 2023-11-25 11:22:20



The [evolution of DevOps to Platform Engineering](/blogs/devops-to-platform-engineering-how-we-got-here/) is an interesting transformation occurring in the current technology landscape. [Platform engineering](/blogs/platform-engineering-101/) includes the creation of innovative engineering solutions that help developers reduce the time spent on non-development activities such as infrastructure deployment so they can focus on application development and delivery.   

The adoption of platform engineering is supported by various engineering solutions such as the IDP (Internal Development Platform) - for example Backstage. Some of these tools focus on creating a central dashboard for developers while some help platform engineers to build platform-as-a-service which could be as simple as helping to set up an environment for development by running a single command.   

In this blog post, we will explore Kratix, a tool that enables you to build and deliver platform-as-a-service.

## What is Kratix?

[Kratix](https://kratix.io/) is an open source framework, offering platform engineers the capability to deliver platform as a product. Kratix empowers platform engineers to elevate their platform-building capabilities by harnessing the power of Kubernetes and GitOps at the same time providing means to include business logic as well in the service being offered.

Unlike other frameworks and tooling which focus exclusively on application-developer experience, Kratix focuses on empowering platform engineers to build better platforms. With teams adopting platform engineering technologies, Kratix could be an asset to your platform team if they are looking to deliver day-to-day platform engineering tasks as a self-service option for developers. Kratix could be an advantage if your platform team is looking to save up their time servicing individual requests from developers. While that said, Kratix is a flexible tool and can work alongside other tools as well and supports a wide range of use cases.  

For visualizing how you may use Kratix, consider a situation where your QA team wants to test an application in a particular environment. This environment may include resources like a virtual network with a database and a Kubernetes cluster. The database and Kubernetes cluster may be required to be deployed with a particular version.

### Without Kratix

In a typical business environment, it would involve raising a ticket and assigning it to the platform team who would then pick up the task and deliver it. This would entail platform engineers scrambling to put together the environment by firing up scripts and performing other activities while chasing the deadline given to deliver the task. 

### With Kratix

With Kratix, one would create a Promise which contains configuration to service a request such as environment creation. This Promise would entertain any request from the developer for an environment creation, with a couple of inputs from the developer, the Promise would run in the Kubernetes cluster and create the environment. In the background, the Promise would use Terraform CRD (Custom Resource Definition), and pipeline among others to deliver the task. We will discuss more about its working further down the blog post.  

While this is just a simple use case, one could leverage this tool to deliver a comprehensive platform as a product with compliance, and business logic among others. 

## Features of Kratix

### Promise

Promise is a transparent agreement between application and platform teams by shaping and implementing well-defined abstractions which are defined in a YAML document and created by the platform team. The Promise is installed on the Kubernetes cluster to fulfill the requirements asked by the developer or any stakeholder.   

What’s in a Promise?


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j6c1y3bke2k0sh7bipag.png)

1. **API**    
The API (in Kubernetes terms, the CRD) that application developers would use to request a Resource from the Kratix Promise. It defines the options that users can configure when they request the Promise.  

2. **Dependencies**    
A collection of prerequisites that enable the creation of a Resource that must be pre-installed on any destination. It could be Jenkins CRD (Custom Resource Definition) and the operator required to deploy Jenkins.  

3. **Workflows**    
Workflows allow you to define a pipeline that would run on on creation, maintenance, or update of a resource. The pipeline can constitute steps to convert user input to the operator’s expected document and much more. The pipeline can also help you to perform any tasks outside the Kubernetes cluster such as sending a Slack alert if the deployment has failed.     
  
You can check out the [Promise to deploy a PostgreSQL resource](https://github.com/infracloudio/promise-postgresql/blob/main/promise.yaml) defined in YAML configuration to understand how the API, dependencies, and workflow come together to form a Promise.  

### Compound Promise

[Compound Promises](https://kratix.io/docs/main/guides/compound-promises) are Promises inside a Promise as a dependency which could be a way to deploy your entire stack starting from application to database packaged as one. Considering a business environment, a compound Promise could be your way of doing much more than deploying a single resource.   

It could mean integrating a host of tasks starting from installing the Promise in a main cluster to installing dependencies such as CRDs in the worker cluster and also use cases like creating a golden path. It could involve creating a Promise that would include taking care of security, networking, storage, compliance, and deployment tasks while setting up an environment.

### Kratix marketplace

[Kratix marketplace](https://kratix.io/marketplace) is a place where you can find Promises that are created by the community and the Kratix team. This means you might not have to create a Promise from scratch, you could reuse existing Promises. If the need is not exactly in line with your requirement, you can go ahead and use it as a base Promise and build upon it to customize it as per your need. You can find multiple pre-created Promises for use cases such as deploying your monitoring stack - Prometheus and Grafana to setting up RabbitMQ or Kafka.

## Integration of Kratix with other tools

Kratix complements many tools such as [Backstage](/blogs/starting-platform-engineering-journey-backstage/), [Kubernetes operators](/kubernetes-school/writing-k8s-operator-kluster/), and Terraform among others. For instance, using Kratix you could create a Promise that could deploy Backstage views. This would be encoding the view as a configuration in Kratix. You could deploy these views as and when required any number of times.   

Kratix could be used in tandem with the Terraform operator. Deploying cloud resources could be achieved through a Promise. A developer could simply request a virtual machine creation by requesting the resource and the Promise would service it by leveraging Terraform CRD to create the resource on the cloud.

## How does Kratix work?

Kratix is built on top of Kubernetes. As mentioned earlier the working of Kratix revolves around a Promise. The Promise which contains the nuts and bolts to service the request would service any requests on a Kubernetes cluster. Kratix allows implementation in a single or multi-cluster architecture. In a single cluster, the Promise that fulfills requests for resource creation would be deployed in the same cluster where any incoming resource creation request would also happen. While in multi-cluster, you can have a platform cluster where Promise would be deployed and any incoming resource creation requests would be created in a separate worker cluster by the Promise. A simple visualization of Kratix in action is pictured below.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8t4n0n62deso0e9tskj9.png)

## Implementing Kratix 

To understand how Kratix can be implemented, we will install a Promise that fulfills a request for PostgreSQL resource creation. The Promise will be deployed on a single kind cluster called the platform cluster. In this example, you can think of the worker and platform cluster as one. This Promise consists of a base Promise from Kratix. This Promise accepts certain inputs from the user and creates the PostgreSQL resource based on the inputs. The base Promise has been updated to accept a new field ‘deployedBy’ which the user can also input during request. This field will be added as a label to the PostgreSQL resource which will be created.  

The basic input parameters that the requester can pass include the name of the database, the name of the superuser who is deploying the resource, the namespace where it is getting deployed, and the label ‘deployedBy’.  

The Promise for PostgreSQL is preconfigured with values such as CPU and memory limits for the PostgreSQL pod. A platform engineer could go a step beyond and also configure granular level access (reader, writer, and owner), node affinity, and many more which are specific to their business requirements. This helps the platform engineer to do away with intervention in every PostgreSQL deployment executed. At the same time, the developer has to just run a command with basic inputs to get the PostgreSQL up and running without having to worry about other database-related configurations which the developer does not have to decide upon. All of those could be pre-configured by a platform engineer in the Promise.

Below are the steps to perform the said use case:  

### Prerequisites

1. [Docker](https://docs.docker.com/engine/install/) should be installed 
2. Kind should be installed ([find how to install kind](https://kind.sigs.k8s.io/#installation-and-usage))

### Steps

1. Kratix Installation  

    You can follow the [official documentation to install Kratix](https://kratix.io/docs/main/guides/installing-kratix/single-cluster) as a single cluster setup.

2. Get the PostgreSQL Promise.

    Clone the PostgreSQL Promise which is a base Promise from Kratix updated to have a new input parameter- ‘deployed by:’. Check out the [promise.yaml](https://github.com/infracloudio/promise-postgresql/blob/main/promise.yaml) and [resource-request.yaml](https://github.com/infracloudio/promise-postgresql/blob/main/resource-request.yaml). The promise.yaml contains Promise configuration which is usually set by the platform team. The resource-request.yaml is the file that is used by the user to request PostgreSQL resource creation by adding the required input in the file.

    ```sh
    $  git clone https://github.com/infracloudio/promise-postgresql.git  
    ```  

3. Create pipeline image.  
  
   The pipeline in Kratix Promise for our use case creates manifest file based on user input any time user requests the resource. The manifest is required by Postgres Operator to create Postgres instance. This pipeline which consists of bash script that takes input and outputs [minimal-postgres-manifest.yaml](https://github.com/infracloudio/promise-postgresql/blob/main/internal/configure-pipeline/resources/minimal-postgres-manifest.yaml) will be converted into a Docker image using a [Dockerfile](https://github.com/infracloudio/promise-postgresql/blob/main/internal/configure-pipeline/Dockerfile) which we will use in subsequent steps. The rationale for this approach is the reusability of the pipeline once it's transformed into an image. The pipeline, once encapsulated in the form of a Docker image, can be easily reused across different Promise.

    $ cd promise-postgresql/internal/configure-pipeline  

    $ docker build . --tag kratix-workshop/postgres-configure-pipeline:dev  
    [+] Building 0.2s (10/10) FINISHED  
    docker:default  
    => [internal] load build definition from Dockerfile                    
    => => transferring dockerfile: 399B                                           
    => [internal] load .dockerignore                                             
    => => transferring context: 2B                                               
    => [internal] load metadata for docker.io/library/alpine:latest               
    => [1/5] FROM docker.io/library/alpine  
    => [internal] load build context                                              
    => => transferring context: 127B                                             
    => CACHED [2/5] RUN [ "mkdir", "/tmp/transfer" ]                              
    => CACHED [3/5] RUN apk update && apk add --no-cache yq                       
    => CACHED [4/5] ADD resources/* /tmp/transfer/                                
    => CACHED [5/5] ADD execute-pipeline execute-pipeline                         
    => exporting to image                                                        
    => => exporting layers                                                         
    => => writing image sha256:XX  
    => => naming to docker.io/kratix-workshop/postgres-configure-pipeline:dev  

4. Give the kind cluster - ‘platform’ access to your pipeline image.

    ```sh  
    $ kind load docker-image kratix-workshop/postgres-configure-pipeline:dev --name platform   
    Image: "kratix-workshop/postgres-configure-pipeline:dev" with ID "sha256:XXXXX"    
    ```    

5. Install Postgres Promise on the platform cluster and verify.    

    Make sure you are in the promise-postgresql folder while running the below command.

    ```sh
    nitin@NITIN-NAIDU:~/kratix/Promise-postgresql$ kubectl apply   
    --filename Promise.yaml  
    Promise.platform.kratix.io/postgresql created  
    nitin@NITIN-NAIDU:~/kratix/Promise-postgresql$ kubectl get crds  
    NAME                                   CREATED AT
    bucketstatestores.platform.kratix.io   2023-10-17T12:48:08Z  
    certificaterequests.cert-manager.io    2023-10-17T12:47:14Z  
    certificates.cert-manager.io           2023-10-17T12:47:14Z  
    challenges.acme.cert-manager.io        2023-10-17T12:47:14Z  
    clusterissuers.cert-manager.io         2023-10-17T12:47:14Z  
    destinations.platform.kratix.io        2023-10-17T12:48:08Z  
    gitstatestores.platform.kratix.io      2023-10-17T12:48:08Z  
    issuers.cert-manager.io                2023-10-17T12:47:14Z  
    orders.acme.cert-manager.io            2023-10-17T12:47:14Z  
    postgresqls.marketplace.kratix.io      2023-10-17T12:50:31Z  
    Promises.platform.kratix.io            2023-10-17T12:48:08Z  
    workplacements.platform.kratix.io      2023-10-17T12:48:08Z  
    works.platform.kratix.io               2023-10-17T12:48:08Z  
    
    nitin@NITIN-NAIDU:~/kratix/Promise-postgresql$ kubectl --namespace default get pods  
    NAME                                 READY   STATUS      RESTARTS   AGE        minio-create-bucket-pzjsr            0/1     Completed   0          22m      
    postgres-operator-64cbcd6fdf-2dpkk   1/1     Running     0          14m    
    ```  

6. Verifying your Kratix Promise can be fulfilled.

    ```sh  
    nitin@NITIN-NAIDU:~/kratix/Promise-postgresql$ kubectl apply   
    --filename resource-request.yaml  
    postgresql.marketplace.kratix.io/example created  
    
    nitin@NITIN-NAIDU:~/kratix/Promise-postgresql$ kubectl get pods  
    NAME                                        READY   STATUS      RESTARTS   AGE  
    acid-example-postgresql-0                   1/1     Running     0          29m  
    configure-pipeline-postgresql-8b724-nx2ct   0/1     Completed   0          30m  
    minio-create-bucket-pzjsr                   0/1     Completed   0          53m  
    postgres-operator-64cbcd6fdf-2dpkk          1/1     Running     0          45m  
    
    nitin@NITIN-NAIDU:~/kratix/Promise-postgresql$ kubectl get pods --selector deployedBy=InfraCloud  
    NAME                        READY   STATUS    RESTARTS   AGE  
    acid-example-postgresql-0   1/1     Running   0          30  
    ```  
  
There we go! We just deployed a customized Kratix Promise which helped to fulfill a request to install PostgreSQL in the Kubernetes cluster with the label - deployedBy and other inputs that the user provided during creation. We ran a command as a developer/user to request a resource which was successfully serviced.    

Next, you can follow the [official documentation to create a Kratix Promise](https://kratix.io/docs/main/guides/writing-a-promise) of your own with business-specific requirements.  

## Conclusion

With platform engineering evolving, leveraging a tool such as Kratix would be beneficial to present your platform as a service, thereby alleviating the load on platform engineers and developers.  

[Kratix marketplace](https://kratix.io/marketplace) is a great place for you to use Promise developed by the community out-of-the-box. While some Promises may fit your requirements right away others may require customization to better cater to your specific needs. 

In a nutshell, Kratix is a Kubernetes native flexible tool that could be used to create an abstraction for non-development activities for developers and serve as a handy tool for a platform engineer to create this abstraction for vivid platform engineering tasks. 

Feel free to connect with our [platform engineering consulting](/platform-engineering-consulting/) team to adopt tools such as Kratix and enable a shift to adopting platform engineering in your organization. You can reach out to me on [LinkedIn](https://www.linkedin.com/in/nitin-naidu-4b86a7129/) to start a conversation regarding this blog post.

## References

- [Kratix official documentation](https://kratix.io/docs/main/intro)