Inline environments
Inline environments is the practice of defining the environment’s config inline
for evaluation at runtime as opposed to configuring it statically in
spec.json
.
The general take away is:
spec.json
will no longer be usedmain.jsonnet
is expected to render atanka.dev/Environment
object- this object is expected to hold Kubernetes objects at
.data
Converting to an inline environment
Converting a traditional spec.json
environment into an inline environment is quite
straight forward. Based on the example from Using Jsonnet:
The directory structure:
Directoryenvironments
Directorydefault # default environment
- main.jsonnet # main file
- spec.json # environment’s config
- jsonnetfile.json
Directorylib/ # libraries
- …
Directoryvendor/ # external libraries
- …
The original files look like this:
{ some_deployment: {/* ... */ }, some_service: {/* ... */ },}
{ "apiVersion": "tanka.dev/v1alpha1", "kind": "Environment", "metadata": { "name": "default" }, "spec": { "apiServer": "https://127.0.0.1:6443", "namespace": "monitoring" }}
Converting is as simple as bringing in the spec.json
into main.jsonnet
and
moving the original main.jsonnet
scope into the data:
element.
{ apiVersion: 'tanka.dev/v1alpha1', kind: 'Environment', metadata: { name: 'default', }, spec: { apiServer: 'https://127.0.0.1:6443', namespace: 'monitoring', }, data: { // original main.jsonnet data some_deployment: {/* ... */ }, some_service: {/* ... */ }, },}
Use case: variable apiServer
Even though the apiServer
directive is originally meant to prevent that the
manifests don’t get accidentally applied to the wrong Kubernetes cluster, there
is a valid use case for making the apiServer
variable: Local test clusters.
Instead of modifying spec.json
each time, with inline environments it is
possible to leverage powerful jsonnet concepts, for example with top level
arguments:
function(apiServer) { apiVersion: 'tanka.dev/v1alpha1', kind: 'Environment', metadata: { name: 'minikube-test-setup', }, spec: { apiServer: apiServer, namespace: 'monitoring', }, data: { /* ... */ },}
Applying this to a local Kubernetes cluster can be done like this:
tk apply --tla-str apiServer=https://127.0.0.1:4758 environments/minikube-test-setup
Similarly this can be used to configure any part of the Environment object, like
namespace:
, metadata.labels
, …
Use case: consistent inline environments
It is possible to define multiple inline environments in a single jsonnet. This enables an operator to generate consistent Tanka environments for multiple Kubernetes clusters.
We can define a Tanka environment once and then repeat that for a set of clusters as shown in this example:
{ environment(cluster):: { apiVersion: 'tanka.dev/v1alpha1', kind: 'Environment', metadata: { name: 'environment/%s' % cluster.name, }, spec: { apiServer: cluster.apiServer, namespace: 'monitoring', }, data: { /* ... */ }, },
clusters:: [ { name: 'us-central1', apiServer: 'https://127.0.0.1:6433' }, { name: 'europe-west2', apiServer: 'https://127.0.0.2:6433' }, ],
envs: { [cluster.name]: $.environment(cluster) for cluster in $.clusters },}
In the workflow you now have to use --name
to select the environment you want
to deploy:
tk apply --name environment/us-central1 environments/monitoring-stack/main.jsonnettk diff --name environment/europe-west2 environments/monitoring-stack/main.jsonnet
# Partial matches also work (if they match a single environment)tk apply --name us-central1 environments/monitoring-stack/main.jsonnettk diff --name west2 environments/monitoring-stack/main.jsonnet
For export, it is possible to use the same --name
selector or you can do a
recursive export while using the --format
option:
tk export outputDir/ environments/monitoring-stack/main.jsonnet --recursive \ --format '{{env.metadata.name}}/{{.metadata.namespace}}/{{.kind}}-{{.metadata.name}}'
Caveats
import "tk"
Inline environments cannot use import "tk"
anymore as
this information was populated before jsonnet evaluation by the existence of
spec.json
.
tk env
The different tk env
subcommands are heavily based on the spec.json
approach. tk env list
will continue to work as expected, tk env (add|remove|set)
will only work for spec.json
based environments.