It’s been a year since I did the ‘Hello World’ with Jsonnet and Tanka, then I made a simple side-loader container to install Tanka as a plugin to ArgoCD and finally deployed an httpbin container with ArgoCD + Tanka + Jsonnet. However since Jsonnet wasn’t used in my work, those things were shelved afterwards.
Recently I got a new gig where Jsonnet was heavily used for infrastructure as code and configuration as code purposes. So I think it’s a no-brainer to practise Jsonnet again, with my blog as the playground.
The Jsonnet Migration
Here are some tips on how to translate existing YAML/Kustomize manifests to Jsonnet/Tanka combo. To prepare a project for Jsonnet, try tk init
in an empty directory like I did in my ‘Hello World’ experiment.
First of all, and the best of all, Jsonnet is a super set of JSON. This means if I put a raw JSON in a Jsonnet file, it should just work. So if I wasn’t sure how to handle a certain type of resource, I’ll just keep it as it is in JSON, eg.
{ namespace: { "apiVersion": "v1", "kind": "Namespace", ... } }
If it’s a large JSON block, it can even be imported via import
function. By this way I can hide some ugly raw JSON such as SealedSecrets away.
{ sealed_secret: import 'sealed-secrets.json' ... }
ConfigMap was managed by kustomize and it’s relatively straightforward to use importstr
function to import them.
(import 'k.libsonnet') + { local cm = $.core.v1.configMap, nginx_configmap: cm.new('nginx-config', { 'nginx.conf': importstr 'conf/nginx.conf'}), ... }
To use the super k8s-libsonnet library, The document is quite handy. For instance, according to the namespace object, I can immediately translate the above JSON for a namespace into Jsonnet.
(import 'k.libsonnet') + { local namespace = $.core.v1.namespace, namespace: namespace.new('wordpress') + namespace.mixin.metadata.withLabels({ "istio.io/rev": 'beta' }), ... }
Surprisingly almost all the time a service
has same labels, eg. app=wordpress for selectors as the deploy
which the service
linked to. This is easily done using references started with a $, which is the root element.
(import 'k.libsonnet') + { local deploy = $.apps.v1.deployment, local svc = $.core.v1.service, ... deploy: { ... }, service: svc.new($.deploy.metadata.name, $.deploy.spec.selector.matchLabels, [ { name: 'http-wp', port: 8080, targetPort: 8080 } ]),
So line by line here’s my Jsonnet powered manifest for my blog, you can compare it with the original kustomize version, too. The Jsonnet version is rather plain and without a lot abstractions for now.
🙂