---
title: Exporting as YAML
sidebar:
  order: 5
---

Tanka provides you with a day-to-day workflow for working with Kubernetes clusters:

- `tk show` for quickly checking the YAML representation looks good
- `tk diff` to ensure your changes will behave like they should
- `tk apply` makes it happen

However sometimes it can be required to integrate with other tooling that does
only support `.yaml` files.

For that case, `tk export` can be used:

```bash
#         <outputDir> <environment>
tk export promtail/   environments/promtail
```

:::note
The arguments flipped in v0.14.0, the `<outputDir>` comes first now.
:::

This will create a separate `.yaml` file for each Kubernetes resource included in your Jsonnet.

## Filenames

Tanka by default uses the following pattern:

```bash
${apiVersion}.${kind}-${metadata.name}.yaml

# examples:
apps-v1.Deployment-distributor.yaml
v1.ConfigMap-loki.yaml
v1.Service-ingester.yaml
```

If that does not fit your need, you can provide your own pattern using the `--format` flag:

```bash
tk export promtail environments/promtail --format='{{.metadata.labels.app}}-{{.metadata.name}}-{{.kind}}'
```

> The syntax is Go `text/template`. See <https://pkg.go.dev/text/template>
> for reference.

This would include the label named `app`, the `name` and `kind` of the resource:

```
loki-distributor-Deployment
loki-loki-ConfigMap
loki-ingester-Service
```

You can optionally use the template function `lower` for lower-casing fields, e.g. in the above example

```bash
... --format='{{.metadata.labels.app}}-{{.metadata.name}}-{{.kind | lower}}'
```

would yield

```
loki-distributor-deployment
```

etc.

You can also use a different file extension by providing `--extension='yml'`, for example.

## Multiple environments

Tanka can also export multiple inline environments, as showcased in [Use case: consistent inline
environments](./inline-environments/#use-case-consistent-inline-environments). This follows the same
principles as describe before with the addition that you can also refer to Environment specific data through the `env`
keyword.

For example an export might refer to data from the Environment spec:

```bash
# Format based on environment {{env.<...>}}
tk export exportDir environments/dev/ \
  --format '{{env.metadata.labels.cluster}}/{{env.spec.namespace}}//{{.kind}}-{{.metadata.name}}'
```

Even more advanced use cases allow you to export multiple environments in a single execution:

```bash
# Export multiple environments
tk export exportDir environments/dev/ environments/qa/
# Recursive export
tk export exportDir environments/ --recursive
# Recursive export with labelSelector
tk export exportDir environments/ -r -l team=infra
```

## Performance features

When exporting a large amount of environments, jsonnet evaluation can become a bottleneck. To speed up the process, Tanka provides a few optional features.

### Partial export (in a GitOps context)

Given multiple environments, one may want to only export the environments that were modified since the last export. This is enabled by passing both the `--merge-strategy=replace-envs` flags.

When these flags are passed, Tanka will:

1. Delete the manifests that were previously exported by the environments that are being exported. This is done by looking at the `manifest.json` file that is generated by Tanka when exporting. The related entries are also removed from the `manifest.json` file.
2. Generate the manifests for the targeted environments into the output directory.
3. Add in the new manifests entries into the `manifest.json` file and re-export it.

#### Finding out which environments to export

Tanka provides the `tk tool importers` command to figure out which `main.jsonnet` need to be re-exported based on what files were modified in a workspace.

If, for example, the `lib/my-lib/main.libsonnet` file was modified, you could run the command like this to find which files to export:

```bash
# Find out which envs to re-export
tk tool importers lib/my-lib/main.libsonnet
> my-repo-path/jsonnet/environments/my-env/main.jsonnet

# Re-export the envs
tk export myoutputdir my-repo-path/jsonnet/environments/my-env/main.jsonnet --merge-strategy=replace-envs
```

Note that deleted environments need special consideration when doing this.
The `tk tool importers` utility only works with existing files so deleting an environment will result in stale `manifest.json` entries and moving an environment will result in manifest conflicts.
In order to correctly handle deleted environments, they need to be passed to the export command:

```bash
tk export myoutputdir my-repo-path/jsonnet/environments/my-new-env-path/main.jsonnet --merge-strategy=replace-envs \
  --merge-deleted-envs my-repo-path/jsonnet/environments/my-old-env-path/main.jsonnet \
  --merge-deleted-envs my-repo-path/jsonnet/environments/other-deleted-env-path/main.jsonnet
```

### Using a memory ballast

_Read [this blog post](https://blog.twitch.tv/en/2019/04/10/go-memory-ballast-how-i-learnt-to-stop-worrying-and-love-the-heap/) for more information about memory ballasts._

For large environments that load lots of data into memory on evaluation, a memory ballast can dramatically improve performance. This feature is exposed through the `--mem-ballast-size-bytes` flag on the export command.

Anecdotally (Grafana Labs), environments that took around a minute to load were able to load in around 45 secs with a ballast of 5GB (`--mem-ballast-size-bytes=5368709120`). Decreasing the ballast size resulted in negative impact on performance, and increasing it more did not result in any noticeable impact.

### Caching

Tanka can also cache the results of the export. This is useful if you often export the same files and want to avoid recomputing them. The cache key is calculated from the main file and all of its transitive imports, so any change to any file possibly used in an environment will invalidate the cache.

This is configured by two flags:

- `--cache-path`: The local filesystem path where the cache will be stored. The cache is a flat directory of json files (one per environment).
- `--cache-envs`: If exporting multiple environments, this flag can be used to specify, with regexes, which environments to cache. If not specified, all environments are cached.

Notes:

- Using the cache might be slower than evaluating jsonnet directy. It is only recommended for environments that are very CPU intensive to evaluate.
- To use object storage, you can point the `--cache-path` to a FUSE mount, such as [`s3fs`](https://github.com/s3fs-fuse/s3fs-fuse)
