At Codethink, we regularly work with different tools and technologies across a range of clients. Terraform is a common tool we see used within these technology stacks for deploying cloud services from infrastructure as code. However, Terraform definitions are rarely defined in isolation without configurations for other tools such as Ansible, Puppet, Kubernetes. These definitions' close relationships often lead to changes in the configurations for multiple tools across various configuration languages.
What's wrong with HCL?
The problems with HCL (Hashicorp Configuration Language) for Terraform start with its domain-specific nature. As a Domain Specific Language (DSL), it requires additional learning for engineers who are previously unfamiliar with the tooling. Being specific to Hashicorp tooling, a dependency on HCL is likely to become a blocker towards any efforts to unify infrastructure and application configurations. In addition to these problems, HCL is not great for writing your configurations with any level of abstraction. For example, the lack of object orientation within HCL prevents teams from writing libraries for regularly used blocks of HCL. This leads to very verbose configuration files with endless duplication across services and projects.
Jsonnet as the solution
Jsonnet is a data templating language created by Google as an extension of json with support for functions, patching and imports. Jsonnet provides a means of defining infrastructure as code in a singular language that it can render into a variety of configuration languages (json, yaml, INI) for usage. Jsonnet has been heavily adopted by Grafana Labs, DataBricks and Bitnami for management of their service deployment configurations.
Jsonnet allows companies to define their configurations abstractly to facilitate sharing common components across many teams. These shared configurations can help save a team countless hours getting up and running without the need to copy and paste static configuration files. By effectively structuring configurations, service-specific definitions can be minimalized through well-defined libraries and well-constructed patches.
We can see an example of this in the Celduin project, where a range of environments for dev, staging and production can each be defined in less than 50 lines by patching the shared libraries. Each of the configuration layers can be abstracted away from terraform to kubernetes to application specific configs, these layers can be initialised with some parameters and evaluated to output the full configuration tree for deployment. Thanks to jsonnet patching, we can have these powerful abstractions available whilst still changing any fine detail within the configuration.
Since its creation in 2014, many tools have been built to support and extend jsonnet usage for different use cases. There are several implementations for the interpreter, jsonnet in C++, go-jsonnet (a faster version in Go) and sjsonnet by Databricks written in Scala. In large configurations, time taken to evaluate and render json can be substantial if consideration is not taken as to which interpreter to use. For general use, go-jsonnet is recommended. However, sjsonnet provides a significant reduction in evaluation time in exchange for the odd incompatibility with go-jsonnet.
Integrating jsonnet directly into deployment workflows usually requires some form of orchestration to render and pipe the manifests into relevant tools such as terraform or kubectl. To tackle these issues, a variety of specialized tools have been created. A few are listed below of notable mention:
- kubecfg: Created by Bitnami as an extension of kubectl accepting jsonnet configurations.
- rules_jsonnet: Allows evaluation of jsonnet configurations within bazel to orchestrate build/deploy pipelines.
- Tanka: Created by Grafana Labs for deploying jsonnet definitions to kubernetes.
On the whole, we believe jsonnet to be an ideal language to bridge the gap for configuring our infrastructure and applications for deployment. With well designed libraries, concise deployment configurations can be written to take advantage of previous efforts to provide meaningful abstractions in place of unnecessary duplication of configurations. The single language across these varying levels of confguration allows for teams to focus on the engineering challenges that really matter without worry of keeping infrastructure configurations in sync with other changes.
Related to the blog post:
- Tracking Players at the Edge: An Overview
- What is Remote Asset API?
- Running a devroom: FOSDEM 2021 Safety and Open Source
- Meet the codethings: Understanding BuildGrid and BuildBox with Beth White
- Bloodlight: Designing a Heart Rate Sensor with STM32, LEDs and Photodiode
- Making the tech industry more inclusive for women
- Bloodlight Case Design: Lessons Learned
- Safety is a system property, not a software property
- RISC-V: Codethink's first research about the open instruction set
- Meet the Codethings: Safety-critical systems and the benefits of STPA with Shaun Mooney
- Why Project Managers are essential in an effective software consultancy
- FOSDEM 2021: Devroom for Safety and Open Source
- Meet the Codethings: Ben Dooks talks about Linux kernel and RISC-V
- Here we go 2021: 4 open source events for software engineers and project leaders
- Xmas Greetings from Codethink
- Call for Papers: FOSDEM 2021 Dev Room Safety and Open Source Software
- Building the abseil-hello Bazel project for a different architecture using a dynamically generated toolchain
- Advent of Code: programming puzzle challenges
- Improving performance on Interrogizer with the stm32
- Introducing Interrogizer: providing affordable troubleshooting
- Improving software security through input validation
- More time on top: My latest work improving Topplot
- Cycling around the world
- Orchestrating applications by (ab)using Ansible's Network XML Parser
- My experience of the MIT STAMP workshop 2020
- Red Hat announces new Flatpak Runtime for RHEL
- How to keep your staff healthy in lockdown
- Bloodlight: A Medical PPG Testbed
- Bringing Lorry into the 2020s
- How to use Tracecompass to analyse kernel traces from LTTng
- Fixing Rust's test suite on RISC-V
- The challenges behind electric vehicle infrastructure
- Investigating kernel user-space access
- Consuming BuildStream projects in Bazel: the bazelize plugin
- Improving RISC-V Linux support in Rust
- Creating a Build toolkit using the Remote Execution API
- Trusting software in a pandemic
- The Case For Open Source Software In The Medical Industry
- My experiences moving to remote working
- Impact of COVID-19 on the Medical Devices Industry
- COVID-19 (Coronavirus) and Codethink
- Codethink develops Open Source drivers for Microsoft Azure Sphere MediaTek MT3620
- Codethink partners with Wirepas
- Testing Bazel's Remote Execution API
- Passing the age of retirement: our work with Fortran and its compilers
- Sharing technical knowledge at Codethink
- Using the REAPI for Distributed Builds
- An Introduction to Remote Execution and Distributed Builds
- Gluing hardware and software: Board Support Packages (BSPs)
- Engineering's jack of all trades: an intro to FPGAs
- Bust out your pendrives: Debian 10 is out!
- Why you should attend local open source meet-ups
- Acceptance, strife, and progress in the LGBTIQ+ and open source communities
- Codethink helps York Instruments to deliver world-beating medical brain-scanner
- Codethink open sources part of staff onboarding - 'How To Git Going In FOSS'
- Getting into open source
- How to put GitOps to work for your software delivery
- Open Source Safety Requirements Analysis for Autonomous Vehicles based on STPA
- Codethink engineers develop custom debug solution for customer project
- Codethink contributes to CIP Super Long Term Kernel maintenance
- Codethink creates custom USB 3 switch to support customer's CI/CD pipeline requirements
- Codethink unlocks data analysis potential for British Cycling
- MIT Doctor delivers Manchester masterclass on innovative safety methodology
- Balance for Better: Women in Technology Codethink Interviews
- Introducing BuildGrid
- Configuring Linux to stabilise latency
- GUADEC 2018 Talks
- Hypervisor Not Required
- Full archive