The Easy Way To Deploy Multilanguage Apps to Kubernetes
Kubernetes can be intricate to manage, and companies want to leverage its power while avoiding its complexity. A recent survey found that 84% of companies don’t see value in owning Kubernetes themselves. To address this complexity, Cloud Foundry introduced open-source Korifi, which preserves the classic Cloud Foundry experience of being able to deploy apps written in any language or framework with a single cf push
command. But the big difference is that this time, apps are pushed to Kubernetes.
In this tutorial, we’ll explore how to use Korifi to deploy web applications written in different languages: Ruby, Node.js, ASP.NET, and PHP. I will also provide insights into Korifi’s functioning and basic configuration knowledge, helping you kick-start your multi-cloud, multitenant, and polyglot journey.
Ruby
For all the examples in this tutorial, I will use sample web applications that you can download from this GitHub repository, but feel free to use your own. You can also find instructions on installing Korifi in this article, which guides you through the easiest way to achieve that by running two Bash scripts that will set everything up for you.
Once you have Korifi installed and have cloned a Ruby sample application, go into the root folder and type the following command:
cf push my-ruby-app
That’s it! That is all you need to deploy a Ruby application to Kubernetes. Keep in mind that while the first iteration of cf push
will take some time as Korifi needs to download a number of elements (I will explain this in the next paragraph); all subsequent runs will be much faster.
At any point, if you want to check the status of a Korifi app, you can use the cf app
command, which, in the case of our Ruby app, would be:
cf app my-ruby-app
Node.js
Before deploying a Node.js application to Kubernetes using Korifi, let me explain how it works under the hood.
One of the key components at play here is Cloud Native Buildpacks. The concept was initially introduced in 2011 and adopted by PaaS providers like Google App Engine, GitLab, Deis, and Dokku. This project became a part of the CNCF in 2018.
Buildpacks are primarily designed to convert an application’s source code into an OCI image, such as a Docker image. This process unfolds in two steps: first, it scans the application to identify its dependencies and configures them for seamless operation across diverse clouds. Then, it assembles an image using a Builder, a structured amalgamation of Buildpacks, a foundational build image, a lifecycle, and a reference to a runtime image.
Although you have the option to construct your own build images and Buildpacks, you can also leverage those provided by established entities such as Google, Heroku, and Paketo Buildpacks. In this tutorial, I will exclusively use ones provided by Paketo — an open-source project that delivers production-ready Buildpacks for popular programming languages.
Let’s briefly demonstrate what Korifi does by manually creating a Buildpack from a Node.js application. You can follow the installation instructions here to install the pack CLI. Then, get into the root folder of your application and run the following command:
pack build my-nodejs-app --builder paketobuildpacks/builder:base
Your Node.js OCI image is available; you can check this by running the command:
docker images
Once the Docker image is ready, Korifi utilizes Kubernetes RBAC and CRDs to mimic the robust Cloud Foundry paradigm of orgs and spaces. But the beauty of Korifi is that you don’t have to manage any of that. You only need one command to push a Node.js application to Kubernetes:
cf push my-nodejs-app
That’s it!
ASP.NET
Now, let’s push an ASP.NET application. If you run cf push my-aspnet-app
, the build will fail, and you will get the following error message:
BuildFail: Check build log output
FAILED
2023-08-11T19:12:58.11+0000 [STG/] OUT ERROR: No buildpack groups passed detection.
2023-08-11T19:12:58.11+0000 [STG/] OUT ERROR: failed to detect: buildpack(s) failed with err
These logs tell us that Korifi may not know a valid Buildpack to package an ASP.NET application. We can verify that by running the following command:
cf buildpacks
You should get the following output, and we can see that there are no .NET-related buildpacks.
position name stack enabled locked filename
1 paketo-buildpacks/java io.buildpacks.stacks.jammy true false paketo-buildpacks/java@9.18.0
2 paketo-buildpacks/go io.buildpacks.stacks.jammy true false paketo-buildpacks/go@4.4.5
3 paketo-buildpacks/nodejs io.buildpacks.stacks.jammy true false paketo-buildpacks/nodejs@1.8.0
4 paketo-buildpacks/ruby io.buildpacks.stacks.jammy true false paketo-buildpacks/ruby@0.39.0
5 paketo-buildpacks/procfile io.buildpacks.stacks.jammy true false paketo-buildpacks/procfile@5.6.4
To fix that, first, we need to tell Korifi which Buildpack to use for an ASP.NET application by editing the ClusterStore:
kubectl edit clusterstore cf-default-buildpacks -n tutorial-space
Make sure to replace tutorial-space
with the value you used during your Korifi cluster configuration. Add the line – image: gcr.io/paketo-buildpacks/python
; your file should look like this:
spec:
sources:
- image: gcr.io/paketo-buildpacks/java
- image: gcr.io/paketo-buildpacks/nodejs
- image: gcr.io/paketo-buildpacks/ruby
- image: gcr.io/paketo-buildpacks/procfile
- image: gcr.io/paketo-buildpacks/go
- image: gcr.io/paketo-buildpacks/python
Then we need to tell Korifi in which order to use Buildbacks by editing our ClusterBuilder:
kubectl edit clusterbuilder cf-kpack-cluster-builder -n tutorial-space
Add the line – id: paketo-buildpacks/dotnet-core
at the top of the spec order list. your file should look like this:
spec:
sources:
- image: gcr.io/paketo-buildpacks/java
- image: gcr.io/paketo-buildpacks/nodejs
- image: gcr.io/paketo-buildpacks/ruby
- image: gcr.io/paketo-buildpacks/procfile
- image: gcr.io/paketo-buildpacks/go
- image: gcr.io/paketo-buildpacks/python
If everything was done right, you should see the .NET Core Paketo Buildpack in the list output by the cf buildpacks command. Finally, you can simply run cf push my-aspnet-app
to push your ASP.NET application to Kubernetes.
PHP
We need to follow the same process for PHP with the Buildpack paketo-buildpacks/php
that needs to be added to the ClusterStore and ClusterBuilder.
For anyone using Korifi version 0.9.0 released a few days ago, the issue that I am about to discuss has been fixed. But in case you are using an older version, running cf push my-php-app
will fail and return the following error message:
[APP/] OUT php: error while loading shared libraries: libxml2.so.2: cannot open shared object file: No such file or directory
The OCI image is missing the libxml library, which is required by PHP, this is probably due to the builder not supporting PHP. To check that, let’s look what builder Korifi is using by running this command:
kubectl describe clusterbuilder cf-kpack-cluster-builder | grep 'Run Image'
Which will output the following:
Run Image: index.docker.io/paketobuildpacks/run-jammy-base@sha256:4cf369b562808105d3297296efea68449a2ae17d8bb15508f573cc78aa3b3772a
As you can see, Korifi currently uses Paketo Jammy Base, which, according to its Github repo description, does not support PHP. You also can check that by looking at the builder’s builder.toml file or by running the command pack builder suggest, which will return the output:
Suggested builders:
[...]
Paketo Buildpacks: paketobuildpacks/builder-jammy-base Ubuntu 22.04 Jammy Jellyfish base image with buildpacks for Java, Go, .NET Core, Node.js, Python, Apache HTTPD, NGINX and Procfile
Paketo Buildpacks: paketobuildpacks/builder-jammy-buildpackless-static Static base image (Ubuntu Jammy Jellyfish build image, distroless-like run image) with no buildpacks included. To use, specify buildpack at build time.
Paketo Buildpacks: paketobuildpacks/builder-jammy-full Ubuntu 22.04 Jammy Jellyfish full image with buildpacks for Apache HTTPD, Go, Java, Java Native Image, .NET, NGINX, Node.js, PHP, Procfile, Python, and Ruby
[...]
While Jammy Base does not support PHP, the Jammy Full builder does. There are multiple ways to get Korifi to use another builder, I will just cover one way in this tutorial. This way assumes that we used the easy way to install Korifi with the deploy-on-kind.sh
script.
You need to go to Korifi source code and edit the file scripts/assets/values.yaml so that the fields clusterStackBuildImage and clusterStackRunImage are set to paketobuildpacks/build-jammy-full
by running this command:
sed -i 's/base/full/g' scripts/assets/values.yaml`
Then, run the scripts/deploy-on-kind.sh
script.
That’s it! Korifi will use the Jammy full builder, and Korifi will be able to deploy your PHP application with a cf push my-php-app
command.
Summary
Hopefully, now you’ve experienced just how easy it is to use Korifi to deploy applications to Kubernetes written in Ruby, Node.js, ASP.NET, and PHP. You can stay tuned with the Korifi project by following Cloud Foundry X account and joining the Slack workspace.