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:
├── environments
│ └── default # default environment
│ ├── main.jsonnet # main file
│ └── spec.json # environment's config
├── jsonnetfile.json
├── lib # libraries
└── vendor # external libraries
The original files look like this:
// main.jsonnet
{
some_deployment: {/* ... */ },
some_service: {/* ... */ },
}
// spec.json
{
"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.
// main.jsonnet
{
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:
// 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: { /* ... */ },
}
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:
// environments/monitoring-stack/main.jsonnet
{
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' },
],
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.jsonnet
$ tk 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.jsonnet
$ tk 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.