3

Is there a way to set the values of some keys in a Knative service.yaml file using environment variables?


More detail

I am trying to deploy a Knative service to a Kubernetes cluster using GitLab CI. Some of the variables in my service.yaml file depend on the project and environment of the GitLab CI pipeline. Is there a way I can seamlessly plug those values into my service.yaml file without resorting to hacks like sed -i ...?

For example, given the following script, I want the $(KUBE_NAMESPACE), $(CI_ENVIRONMENT_SLUG), and $(CI_PROJECT_PATH_SLUG) values to be replaced by accordingly-named environment variables.

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: design
  namespace: "$(KUBE_NAMESPACE)"
spec:
  template:
    metadata:
      name: design-v1
      annotations:
        app.gitlab.com/env: "$(CI_ENVIRONMENT_SLUG)"
        app.gitlab.com/app: "$(CI_PROJECT_PATH_SLUG)"
    spec:
      containers:
        - name: user-container
          image: ...
      timeoutSeconds: 600
      containerConcurrency: 8
ostrokach
  • 17,993
  • 11
  • 78
  • 90

2 Answers2

2

I don't think there is a great way to expand environment variables inside of an existing yaml, but if you don't want to use sed, you might be able to use envsubst:

envsubst < original.yaml > modified.yaml

You would just run this command before you use the yaml to expand the environment variables contained within it.

Also I think you'll need your variables to use curly braces, instead of parentheses, like this: ${KUBE_NAMESPACE}.

EDIT: You might also be able to use this inline like this: kubectl apply -f <(envsubst < service.yaml)

Brian Pursley
  • 1,098
  • 7
  • 18
2

More than a Knative issue this is more of Kubernetes limitation. Kubernetes allows some expansion but not in annotations or namespace definitions. For example, you can do it in container env definitions:

containers:
- env:
  - name: PODID
    valueFrom: ...
  - name: LOG_PATH
    value: /var/log/$(PODID)

If this is a CI/CD system like Gitlab the environment variables should be in a shell environment, so a simple shell expansion will do. For example.

#!/bin/bash

echo -e "
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: design
  namespace: "${KUBE_NAMESPACE}"
spec:
  template:
    metadata:
      name: design-v1
      annotations:
        app.gitlab.com/env: "${CI_ENVIRONMENT_SLUG}"
        app.gitlab.com/app: "${CI_PROJECT_PATH_SLUG}"
    spec:
      containers:
        - name: user-container
          image: ...
      timeoutSeconds: 600
      containerConcurrency: 8
" | kubectl apply -f -

You can also use envsubst as a helper like mentioned in the other answer.

Rico
  • 58,485
  • 12
  • 111
  • 141
  • Thank you for explaining the containers env section! I saw the `env` section in the docs and this is what made me think it may be possible to extract environment variables from the calling process. – ostrokach Jul 08 '20 at 14:59