Grafana Tanka
repository·main·Indexed 25 days ago
https://github.com/grafana/tankaA Jsonnet-based tool for Kubernetes cluster management designed to replace YAML. Grafana Tanka provides a programmable way to define Kubernetes resources and Helm charts, offering features such as reusable libraries, boilerplate reduction, and the ability to preview changes via `tk diff` before applying them to production environments.
What's inside Grafana Tanka
- Grafana Tanka is an open-source tool designed to manage Kubernetes applications using the Jsonnet language. It provides a more expressive, reusable, and concise alternative to YAML for defining Kubernetes resources. Tanka is used to deploy production environments like Grafana Cloud and leverages powerful diffing capabilities to ensure reliable deployments by showing exact changes before they are applied.
Jsonnet Syntax Overview
mainJsonnet is a data templating language used by Tanka to express Kubernetes deployments. It is a superset of JSON and supports comments, local variables, and exported objects.
- Comments: Use
//for line comments and/* ... */for block comments. - Local Variables: Defined using
local name = value;. These are not exported. - Exported Objects: The top-level object (or the only non-local entity) is what is returned.
- Unexported Fields: Use
::instead of:to define a field that is hidden from the final output.
// Line comment /* Block comment */ // a local variable (not exported) local greeting = "hello world!"; // the exported/returned object { foo: "bar", // string bar: 5, // int baz: false, // bool list: [1,2,3], // array // object dict: { nested: greeting, // using the local }, hidden:: "incognito!" // an unexported field }- Comments: Use
Understand the Tanka directory structure
mainTanka projects are organized around environments and dependency management files. The core structure typically includes:
environments/: Contains environment-specific configurations.lib/: Local libraries specific to the project.vendor/: External libraries installed viajb(jsonnet-bundler).jsonnetfile.json: Defines direct dependencies.jsonnetfile.lock.json: Contains exact versions and SHA256 hashes of all dependencies.
Note: The
vendor/directory can be added to.gitignoreas long asjsonnetfile.lock.jsonis committed to source control.Understand the difference between Tanka and ksonnet
mainTanka is designed as a fully compatible, drop-in replacement for the core
ksonnetworkflow, specifically theshow,diff, andapplycommands.Unlike
ksonnet, Tanka does not include:- A rich code generator for CLI-based editing of Kubernetes objects.
- Built-in dependency management.
- Complex abstraction layers.
Tanka prioritizes being a minimal tool, so these features are intentionally omitted and are not planned for future addition.
Understand the difference between Tanka and kubecfg
mainWhile both tools are similar,kubecfgis primarily a thin Kubernetes-specific wrapper around Jsonnet evaluation. Tanka is designed specifically to provide continuity for users migrating from theksonnetecosystem.Understand the difference between Tanka and Helm
mainTanka uses Jsonnet instead of Helm's string-based YAML templating.
Key differences include:
- Structure Awareness: Helm uses string templating which is unaware of YAML syntax, making debugging difficult. Tanka uses Jsonnet, which is a superset of JSON and understands data structures.
- Extensibility: Helm charts often require modification to support new parameters. Tanka/Jsonnet allows you to use mixing (patching and deep-merging) to apply changes on top of library outputs without modifying the original source.
Create Kubernetes helper utilities
mainYou can reduce boilerplate in your service definitions by creating a
kubernetes.libsonnetfile containing constructor functions for standard Kubernetes resources likeDeploymentandService. This allows you to focus on the specific configuration (like container images and ports) rather than the structural requirements of the Kubernetes API.// /environments/default/kubernetes.libsonnet { deployment: { new(name, containers):: { apiVersion: "apps/v1", kind: "Deployment", metadata: { name: name, }, spec: { selector: { matchLabels: { name: name, }}, template: { metadata: { labels: { name: name, }}, spec: { containers: containers } } } } } }Structure Jsonnet output for Tanka
mainTanka invokes the Jsonnet compiler on a file named
main.jsonnet. The compiler evaluates the code into a single JSON object. Becausekubectlexpects a YAML stream of individual manifests rather than a single nested tree, Tanka traverses the resulting JSON object to find valid Kubernetes manifests.An object is identified as a valid Kubernetes manifest if it contains both
apiVersionandkindkeys.Run Tanka acceptance tests
mainAcceptance tests for Tanka cover end-to-end use cases, such as creating a new Tanka environment and pushing it to an ephemeral Kubernetes cluster.
To run these tests, you must have the Dagger CLI >= 0.11 installed. The command must be executed from the root directory of the project.
make acceptance-testsManage dependencies with jsonnetfile.json and jsonnetfile.lock.json
mainTanka uses
jb(jsonnet-bundler) to manage external libraries in thevendor/directory.jsonnetfile.json: The source of truth for direct dependencies. It should only include packages that are directly required by your project; recursive dependencies are handled automatically.jsonnetfile.lock.json: Automatically generated on every run of jsonnet-bundler. It contains the exact versions andsha256hashes of all packages invendor/to ensure reproducible builds.
Best Practice: Both
jsonnetfile.jsonandjsonnetfile.lock.jsonmust be checked into source control to ensurejb installproduces identical environments across different machines.Install Tanka (tk)
mainTanka is distributed as a single binary called
tk. It includes the Jsonnet compiler but requireskubectlanddiffto be available on your$PATH. It is also recommended to installjb(Jsonnet Bundler) andhelmfor full functionality.macOS
Install via Homebrew:
brew install tankaArchLinux
Install via an AUR helper (e.g.,
yay):- From source:
yay tanka - Pre-compiled binary:
yay tanka-bin
Binary Installation (Linux/macOS)
Download the appropriate binary from GitHub Releases, place it in your
$PATH(e.g.,/usr/local/bin/tk), and make it executable.Build from Source (Go)
If you have a Go toolchain, use
go installor manual compilation viamake.# macOS brew install tanka # ArchLinux (Source) yay tanka # ArchLinux (Binary) yay tanka-bin # Linux amd64 sudo curl -Lo /usr/local/bin/tk https://github.com/grafana/tanka/releases/latest/download/tk-linux-amd64 sudo chmod a+x /usr/local/bin/tk # Linux arm / arm64 sudo curl -Lo /usr/local/bin/tk https://github.com/grafana/tanka/releases/latest/download/tk-linux-arm sudo curl -Lo /usr/local/bin/tk https://github.com/grafana/tanka/releases/latest/download/tk-linux-arm64 sudo chmod a+x /usr/local/bin/tk # macOS Binary sudo curl -Lo /usr/local/bin/tk https://github.com/grafana/tanka/releases/latest/download/tk-darwin-amd64 sudo chmod a+x /usr/local/bin/tk # Go install go install github.com/grafana/tanka/cmd/tk@latest # Manual build git clone https://github.com/grafana/tanka cd tanka make install- From source:
Use top-level arguments for variable apiServer
mainYou can use Jsonnet top-level arguments to make environment configuration (like
apiServerornamespace) dynamic. This is useful for local test clusters where the API server address changes.Define your
main.jsonnetas a function that accepts these arguments, then pass the values using the--tla-strflag with thetkCLI.// environments/minikube-test-setup/main.jsonnet function(apiServer) { apiVersion: 'tanka.dev/v1alpha1', kind: 'Environment', metadata: { name: 'minikube-test-setup', }, spec: { apiServer: apiServer, namespace: 'monitoring', }, data: { /* ... */ }, }tk apply --tla-str apiServer=https://127.0.0.1:4758 environments/minikube-test-setup