Skaffold: Environment variables and profile

Created on 16 Apr 2019  Β·  5Comments  Β·  Source: GoogleContainerTools/skaffold

Hi,
How do I specify environment variables in skaffold?

My Flask app loads environment specific settings based on a ENVIRONMENT environment variable. e.g.

import os
import my_config
environment = os.environ['ENVIRONMENT']
my_settings = my_config.get_settings(environment)
// rest of my code

Is there a way of using skaffold profiles and specify something like below in my skaffold.yaml:

build:
  artifacts:
  - image: gcr.io/k8s-skaffold/skaffold-example
deploy:
  kubectl:
    manifests:
    - k8s-pod
profiles:
  - name: staging
    env:
      ENVIRONMENT: staging
   - name: production
     env:
      ENVIRONMENT: production

If you know of something simpler, please let me know

aredeploy areprofiles kindocumentation

Most helpful comment

Skaffold does not support specifying env vars, and it would be tricky as well - what if the k8s manifests have multiple pods specified - should we pass those in everywhere?

As I understand you want to set these env vars at runtime, right? You can set those env vars in the pod spec. Now, how to have different pod specs per environment:

  1. I would recommend experimenting with the kustomize deployer and add a profile specific kustomization that would setup the right env vars in your pod
  2. if you want to stick with kubectl only, you can create separate manifests

All 5 comments

Skaffold does not support specifying env vars, and it would be tricky as well - what if the k8s manifests have multiple pods specified - should we pass those in everywhere?

As I understand you want to set these env vars at runtime, right? You can set those env vars in the pod spec. Now, how to have different pod specs per environment:

  1. I would recommend experimenting with the kustomize deployer and add a profile specific kustomization that would setup the right env vars in your pod
  2. if you want to stick with kubectl only, you can create separate manifests

I think this would be useful to document though - it seems like a common enough problem that people might run into.

Thank you very much for that insight. I'll look into kustomize. I can close this but I see you have labelled this for documentation so I'll keep it open but feel free to close this if you have another ticket.

@balopat We currently pass in environment variables in to the corresponding pods by defining a list of them for each environment. These usually live in a dir in the project repo and are passed into the helm command during the corresponding CI pipeline stage. This currently works great, but we would ideally like to eliminate the need for the separate values files for each environment, and bring everything into a single skaffold.yml file in the root of the project.

.
β”œβ”€β”€ Chart.yaml
β”œβ”€β”€ prod.yml
β”œβ”€β”€ staging.yml
β”œβ”€β”€ templates
β”‚   β”œβ”€β”€ _helpers.tpl
β”‚   β”œβ”€β”€ deployment.yaml
β”‚   β”œβ”€β”€ ingress.yaml
β”‚   └── service.yaml

deployment.yml ranges over a list of env vars defined in each environments values file.

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
  labels:
    app: {{ template "chart-name.name" . }}
    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  replicas: {{ .Values.replicaCount }}
  template:
    metadata:
      labels:
        app: {{ template "chart-name.name" . }}
        release: {{ .Release.Name }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: {{ .Values.image }}
          imagePullPolicy: {{ .Values.pullPolicy }}
          {{- if .Values.vars }}
          env:
          {{- range $key, $value := .Values.vars }}
            - name: "{{ $key }}"
              value: "{{ $value }}"
          {{- end }}
          {{- end }}
          ports:
            - containerPort: {{ .Values.service.internalPort }}
          resources:
{{ toYaml .Values.resources | indent 12 }}
    {{- if .Values.nodeSelector }}
      nodeSelector:
{{ toYaml .Values.nodeSelector | indent 8 }}
    {{- end }}

So, staging.yml contains the list of env's that need to be passed in alongside all its other customisations.

vars:
  TestVar: "TestValue"
  TestVar2: "TestValue2"

As per the documentation the values:{} field in skaffold.yml passes in key-value pairs supplementing the HelmΒ valuesΒ file, however if fails to handle a map:

FATA[0000] creating runner: parsing skaffold config: unable to parse config: yaml: unmarshal errors:
  line 23: cannot unmarshal !!map into string

If the values parameter were able to handle maps this could be achieved with the following skaffold.yml

apiVersion: skaffold/v1beta17
kind: Config
build:
  tagPolicy:
    gitCommit:
      variant: AbbrevCommitSha
  artifacts:
    - image: projectname
      docker:
        dockerfile: Dockerfile
profiles:
  - name: staging
    deploy:
      helm:
        releases:
          - name: staging-projectname
            namespace: example
            chartPath: chart-name
            values:
              image: projectname
              vars:
                StagingVar: StagingValue
                StagingVar2: StagingValue2
 - name: prod
    deploy:
      helm:
        releases:
          - name: prod-projectname
            namespace: example
            chartPath: chart-name
            values:
              image: projectname
              vars:
                ProdVar: ProdValue
                ProdVar2: ProdValue2

Thoughts?

I'm closing this issue as it hasn't seen activity in awhile, and it's unclear if this issue still exists. If this issue does continue to exist in the most recent release of Skaffold, please feel free to add a comment and we'll re-open it.

If someone sees a similar issue, please create a new issue, but do include a link to this issue if possible.

Thank you for opening the issue!

Was this page helpful?
0 / 5 - 0 ratings