Preface
A little note here; I wrote this years back and never actually thought it finished enough to post. I figure I'm just going to put it out into the world with a little massaging. Since this was initially written years ago, I've successfully lead an initiative to replace the bulk of the jsonnet deploys with cdk8s instead and the world is much greener. We still use jsonnet for certain things, Grafana Labs loves it (Prometheus, Mimir, etc) we will probably keep it around for much of that tooling.
Introduction
Over the last year or so I've been thrust into the world of Kubernetes, after taking a DevOps-centric role at a large organisation. Before that I was quite happy getting by in my CloudFormation / Elastic Beanstalk environment, with the devs running Docker locally. It worked, I understood it, and it mostly stayed out of my way.
Amongst getting to grips with the container orchestration engine of choice in the organisation, I've also had to get my head around the tooling choices that come with such a thing. There are many of these that we use, and I'll likely get to them over time — if and when they frustrate me enough to put fingers to keyboard.
First cab off the rank, and one of my top complaints about the tooling we use, is Jsonnet.
A note before the ranting starts
Well... I've written and re-written this article many times over the past six months. It was originally written from a place of frustration and anger, and it has mellowed out a little as I've been forced down the Jsonnet route and actually had to live with it. While I would still not select it as my first choice — with things like the AWS CDK becoming more powerful — it's not worth slamming it quite so hard as I did initially.
I'll also note before I go any further that we are using Jsonnet for templating the YAML documents for our Kubernetes deploys, including Helm. We do not — and in the world of me leading the team, will not — be using it for anything else at this stage. Everything below is written from inside that box.
So what is Jsonnet?
If you don't know what this is, I don't blame you. It calls itself "a data templating language for app and tool developers". While that's true, what it's really trying to achieve is the ability to template JSON.
Which, when you're working with Kubernetes, means you write Jsonnet, which becomes JSON, which you convert into YAML... which Kubernetes ingests and immediately converts back into JSON. Sigh.
The tool is basically non-existent outside of the world of some pretty custom Kubernetes deployments — the sort where even Helm is considered "too constraining".
The problem Jsonnet is trying to solve at its core is templating configuration. The issue, however, in my humble opinion, is that it's so poorly connected together — and leans so heavily on tooling that is sometimes woefully under-serving it — that it causes endless frustration.
Why not just use TypeScript?
This is where I depart from agreeing with its point. The fact is, for me as someone intimately familiar with Node.js, I really, really do not understand why the hell you'd use Jsonnet when you could just use Node.js, or even better, TypeScript.
The simple fact is that TypeScript has existed since 2012, where the first usable release of Jsonnet is from 2018. Granted, it was an internal Google config tool likely for years before this — but I don't work there.
TypeScript (which you use the AWS CDK with) is arguably far superior, far better supported, and works nicer with JSON, seeing as it is literally JavaScript Object Notation. You get far nicer tooling, including package managers that actually work. Yeah, I said it, jsonnet-bundler.
I'll also note that Amazon's CDK project goes even further into the realm of EKS/Kube by providing in-cluster config too. And it's not just TypeScript either — there are other languages, like Go, if you prefer arguing with JSON to writing it.
On that subject, let me hit a few topics to really drill into the issue with Jsonnet and its sometimes inadequate tooling.
Package management
Node.js has npm (or Yarn, if you like your bread buttered on the outside), and while it's far from perfect, it's come a long way.
Surely Jsonnet has a package manager... right? Umm. Not like Node.js has npm, that's for sure. You are lumped with jsonnet-bundler — which, to be fair to it, is not an official Jsonnet project, and has also been in alpha for three or four years at this point with very little work put into it.
Before I proceed to rip on this situation, I have to prefix it with the fact that I have all the respect in the world for the author(s) of this open-source project, trying to plug a major hole in Jsonnet and the other tooling surrounding it. Right, so...
Anything beyond installing or updating a package version, well, let's see:
- Want to list the currently installed packages? Nope, sorry.
- Want to remove or uninstall a package? Nope, sorry.
- Want to list any outdated packages? Nope, sorry.
- Want to update a subdirectory package? Nope, sorry.
There's heaps more, but I think I've made my point. It's basically an absolute bare-bones MVP/PoC project — which would be absolutely fine normally, except that the community has had no option but to adopt it as the de facto standard. That's the real problem: the gap between "someone's side project, honestly labelled alpha" and "load-bearing part of everyone's deploy pipeline" is exactly where the frustration lives, and it isn't the author's fault that it ended up there.
Tooling
Honestly, without the excellent work done by the team at Grafana Labs with Tanka, Jsonnet would never have caught on in the Kubernetes community, even in the limited capacity that it has. In my opinion, if Tanka ever dies, Jsonnet will too.
That is an enormous amount of weight for one project to be carrying on behalf of an entire language.
Documentation
While the tutorial has enough in it to get you started, anything more than basic concepts starts to tax the user significantly in making forward progress.
The documentation is sparse and lacks any usage examples. Some fundamental (and required) and more difficult concepts, like std.foldl and std.foldr, are not explained at all.
Functions that take anonymous functions do not provide the downstream parameters, leaving the end user to have to work this out before they're even able to use the functions. You end up reverse-engineering the standard library just to find out what your own callback is going to be handed.
Cognitive load
Jsonnet tasks the user with having to keep track of the inheritance, across multiple sources, in a compounding nature. At a certain point, even the original author can and will struggle to understand their own Jsonnet in the future — especially if anyone else has worked on it since they last touched it.
There's rarely a single file you can open and read to know what a deploy actually is. You have to hold the whole merge chain in your head, and that chain only ever grows.
Why are you using this, then?
Frankly, it wouldn't probably have been my first choice before I heard of it, or even now after using it and seeing some of the positives it can bring. It does solve a real problem, and in a large organisation you don't always get to choose the tooling you inherit.
Though I truly think that there should just be something better.
no comments yet