7

Let's say we have a number of Kubernetes configuration files in a folder kubernetes and we want to apply them all:

kubectl apply -f kubernetes -n MyNamespace

Some of these files contain environment variables which need to be substituted first (no templating in Kubernetes). For instance, several of the deployment yamls contain something like:

image: myregistry.com/myrepo:$TAG

For a single yaml file, this can be done e.g. by using envsubst like this:

envsubst < deploy.yml | kubectl apply -f -

What's the best way to do these substitutions for all the yaml files?

(Looping over the files in the folder and calling envsubst as above is one option, but I suspect that it would be preferrable to pass the entire folder to kubectl and not individual files)

Max
  • 9,220
  • 10
  • 51
  • 83
  • 2
    Would either Kustomize or Helm fit your needs here? Kustomize can directly set the image tag; Helm has a more general templating engine but setting image tags is a very common use for it. – David Maze Jan 13 '21 at 17:44
  • Yes, both would solve the problem as well. In my particular case, there's only a single variable substitution, so I'm leaning towards a lightweight solution vs adding another tool. – Max Jan 13 '21 at 17:49

2 Answers2

9

This works:

for f in *.yaml; do envsubst < $f | kubectl apply -f -; done
Max
  • 9,220
  • 10
  • 51
  • 83
7

You can let envsubst read the content of multiple files from standard input as if it were reading one file < deploy.yaml either using process substitution <(..) feature of bash or using plain ol' cat

envsubst < <(cat *.yaml) | kubectl apply -f -

or

cat *.yaml | envsubst - | kubectl apply -f -
Inian
  • 80,270
  • 14
  • 142
  • 161
  • Thanks! This will make it look like one large configuration file to kubectl instead of several ones, right? Is there any downside to that? – Max Jan 13 '21 at 16:30
  • 1
    @Max: It doesn't matter to `kubectl`, all it needs is a valid YAML to render. If you are worried about all the files being processed, name your files to suit the glob expressions, e.g. for deploy charts alone i.e. `deploy*.yaml` – Inian Jan 13 '21 at 16:31
  • ok great! No, I was just wondering if kubectl behaves differently if it gets separate files, e.g. processes them in parallel or does some other kind of optimization. – Max Jan 13 '21 at 16:33
  • 2
    What really happens is, by the time, `kubectl` sees the input, it does not even know which files it came from, except its a content over its standard input i.e. `-`l, it doesn't really care – Inian Jan 13 '21 at 16:35
  • 4
    I spoke too soon- this actually doesn't quite work. Since kubectl considers the input a single file with multiple resources, there has to be a `---` separator between them. See https://stackoverflow.com/a/52255987. – Max Jan 14 '21 at 00:42
  • 2
    Thanks to this thread, I've found a way to pass system env to Kustomize with envsubst: Just run `envsubst < <(kubectl kustomize overlays/staging) | kubectl apply -f -` – RedGiant Apr 29 '21 at 07:47