May 15, 2024
Get featured on Geeklore.io
Geeklore is in very early stages of development. If you want to help us grow, consider letting us sponsor you by featuring your tool / platform / company here instead of this text. 😊
Welcome back to Jsonnet series! After covering the basics in my previous post, it is time to delve into Jsonnet's more advanced features: functions, conditionals, advanced templating, and leveraging external libraries.
I'll showcase these through an update to our Kubernetes deployment setup, gearing it towards a production-ready (well... almost) application.
Before diving into the specifics, let's take a look at the updated files in our project:
We have added applications.libsonnet to allow us to easily manage our code, and create different types of applications. Here's how it looks like:
local deployment = import './deployment.libsonnet';
local service = import './service.libsonnet';
local ingress = import './ingress.libsonnet';
{
basicApplication(p):: {
[p.appName + '-deployment']: deployment.basicDeployment(p),
[p.appName + '-service']: service.LoadBalancer(p),
},
productionApplication(p):: {
[p.appName + '-deployment']: deployment.productionDeployment(p),
[p.appName + '-service']: service.ClusterIP(p),
[p.appName + '-ingress']: ingress.basicIngress(p),
}
}
We define the application type we want, and set up the resources we want to deploy. This is a great way to organize our code and make it more maintainable. We also moved the imports to the top of this file rather than having them in each application-specific apps.jsonnet file.
Jsonnet contains powerful pre-defined functions and libraries that we can leverage to enhance our code. In our updated libs/deployment.libsonnet, the productionDeployment function utilizes the std.map() function to generate environment variables for our production deployment:
productionDeployment(p):: {
// ... Other deployment details ...
spec: {
template: {
spec: {
containers: [
{
// ... Other container configurations ...
env: if std.objectHas(p, 'env') then
std.map(
function(key) { name: key, value: std.toString(p.env[key]) },
std.objectFields(p.env)
)
else [],
}
],
}
}
}
}
This addition dynamically generates the necessary environment variables for the container from the parameters file, and uses a conditional "if" to check if the parameters file contains an "env" object. If it does, it will generate the environment variables, otherwise it will generate an empty array.
std.objectHas and std.map are only two of the many functions available in Jsonnet. You can find the full list here.
I've also brought in kube.libsonnet from the Bitnami kube-libsonnet library to further empower our Jsonnet scripts.
In this tutorial, we are only using its List() function, which helps us bundle the resources we want to deploy into our (future) ArgoCD cluster.
More about the kube.libsonnet library later in future posts.
In /simple-node-app/prd/apps.jsonnet, we now have a simplified deployment file:
local applications = import '../../libs/applications.libsonnet';
local params = import 'parameters.libsonnet';
local kube = import '../../libs/kube.libsonnet';
kube.List() {
items_: applications.productionApplication(params)
}
Notice how we now import only the applications rather than all the individual libraries. This way the deployment process becomes more readable and manageable using the kube.List() function. This will generate an ArgoCD-ready application manifest which we can deploy to our cluster.
Finally, the parameters.libsonnet has been updated to include environmental variables:
{
appName: 'simple-node-app',
environment: 'prd',
replicas: 3,
port: 8080,
imageTag: 'latest',
env: {
NODE_ENV: 'production',
PORT: 8080,
},
}
It doesn't matter if we want one, two, or 15 environment variables. Because of the std.map() function, our productionDeployment function will generate the necessary environment variables for our container.
This is just how powerful Jsonnet really is.
In this post, we updated our codebase using Jsonnet's more advanced feature and hopefully started feeling more creative! We also added an external library, and are getting ready to soon start deploying our applications to our Kubernetes cluster.
In the next post, we will take a look at how ArgoCD handles Jsonnet, and how a simple ArgoCD application built with Jsonnet looks like.
I hope you learned something and if you feel like chatting, connect with me on X or hit me up with a comment below!
Closing GIF time!
Latest Comments