20

I currently use a Kubernetes spec Deployment.yaml for deploying a service. The spec includes a verbatim reference to a specific IP address (marked as <static-ip-address> below):

spec:
  type: LoadBalancer
  loadBalancerIP: <static-ip-address>

I am concerned about pushing information such as passwords or IP addresses into remote Git repositories. Can I avoid this e.g. by making use of environment variables, e.g. with a deployment spec and actual deployment roughly as follows:

spec:
   type: LoadBalancer
   loadBalancerIP: ${SERVICE_ADDRESS}

and

export SERVICE_ADDRESS=<static-ip-address>
kubectl create -f Deployment.yaml

Obviously this specific syntax does not work yet. But is something like this possible and if so how?

I'd prefer not relying on a separate provisioning tool. Secrets and ConfigMaps seem promising, but apparently they cannot be consumed in a way that suits this purpose. If I could directly reference a static IP address that was defined with gcloud compute addresses create service-address that would be best.

4 Answers 4

32

A much easier/cleaner solution: envsubst

In deploy.yml:

LoadbalancerIP: $LBIP

Then just create your env var and run kubectl like this:

export LBIP="1.2.3.4"
envsubst < deploy.yml | kubectl apply -f -

You just put regular Bash variables into whatever file you want to use, in this case the YAML manifest, and have ensubst read that file. It will output the file with the env vars replaced by their values. You can also use it to create new files like this:

envsubst < input.yml > output.yml

envsubst is available in e.g. Ubuntu/Debian gettext package.

5
  • 3
    +1 for envsubst. didnt know about this until now Mar 8, 2018 at 14:53
  • 1
    It's not easier/cleaner, as it requires a separate tool, which is not by default installed on all systems (e.g. Mac)
    – Ivan
    Feb 10, 2019 at 14:05
  • @Ivan His question was "But is something like this possible and if so how?", and that is the answer to his question. The question was not "How can i do this with tools available on every OS by default?". And yes, it is 1) easier AND 2) cleaner than using sed. By your definition, the proposed solution with sed would also not be easier/cleaner, as there is no sed installed on Windows machines by default.
    – Jan Grewe
    Feb 11, 2019 at 15:13
  • It's not clear at all that you were comparing to "sed" option.
    – Ivan
    Feb 11, 2019 at 20:17
  • having gone the sed route a year ago - sed does not scale well. envsubst is the way to go.
    – ztron
    Apr 11, 2020 at 23:50
2

There was another pleasantly simple solution: I have a Google Compute Address my-address defined, and I can apparently use it in the service spec like so: loadBalancerIP: my-address.

With this as "external" source for IP addresses and secrets for passwords there is no more need for a provisioning tool (or templates) for my simple use case (within a GKE environment).

OBSOLETE NOW: I have decided on using a provisioning tool of sorts, namely "built-in" sed, after all.

My Deployment.yaml now contains a "template variable" e.g. in

loadBalancerIP: $$EXTERNAL_IP

and I deploy the service with, say, 1.2.3.4 as external IP address with

cat Deployment.yaml | sed s/\$\$EXTERNAL_IP/1.2.3.4/ | kubectl create -f -
1
  • 1
    Jan Grewe s approach is more generic an can be applied to any number of variables. I would suggest do accept his answer instead of accepting your own that is less generic and needs to be adjusted for every additional variable.
    – TekTimmy
    Jun 3, 2019 at 7:46
0

You can write a simple pre-processor to do variable substitution on your yaml files (or you can use jsonnet to accomplish the same thing on json configuration files).

There is some discussion around adding templates directly into Kubernetes configuration but it isn't yet implemented or available.

2
  • Yes, but jsonnet is a provision tool as mentioned in the question.
    – Drux
    Jul 26, 2016 at 16:07
  • 1
    If you're looking for something built-in, then following the issue I linked to is your best bet at this point. Jul 30, 2016 at 4:57
0

Until templates are available, the easiest way to do it is to run a job which uses the Kubernetes API to update the service. A short shell script in an alpine-based image, coupled with a secret (containing the IP address) and a configmap (containing the template), should be simple enough. The difficult bit is correctly using the authentication and authorization features of the apiserver.

https://stackoverflow.com/questions/30690186/how-do-i-access-the-kubernetes-api-from-within-a-pod-container gives an example of accessing the API. Obviously, you'll want to POST to /api/v1/namespaces/default/services instead of the GET in that example.

1
  • Sounds interesting, but can you please elaborate a bit more. Could you give or point to an example of a suitable shell script.
    – Drux
    Jul 30, 2016 at 18:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .