Helm pass values to the templates for multiple environment - kubernetes

I am very newbie on Helm and struggling to configure deployment.yaml.Mychart tree structure looks like below. But how should I pass the values for dev and prod to the deployment.yaml?
For example if I would like to use different replicas for prod should I add another values such as below or deployment.yaml always keep as it is and use mutlipe values.yaml like as below.
replicas: {{ .Values.replicaCount .values.dev.replicacount }}
Or use only below tag is enough. Let's say if git branch equals to master then use below command
helm install . -f values.production.yaml
If git branch equal to development then use following command
helm install . -f values.dev.yaml
+-- charts
| \-- my-chart
| +-- Chart.yaml # Helm chart metadata
| +-- templates
| | \-- ...
| +-- values.yaml # default values
| +-- values.dev.yaml # development override values
| +-- values.prod.yaml # production override values

You should have a values.yaml file per environment.
That means that in your templates/deployment.yaml you'll have
replicas: {{ .Values.replicaCount }}
And then, for each environment you'll have a specific values.yaml. Like:
+-- values.yaml # default values
+-- values.dev.yaml # development override values
+-- values.prod.yaml # production override values

It really depends on the differences between your environments.
As being described in helm docs:
There are three potential sources of values:
A chart's values.yaml file
A values file supplied by helm install -f or helm upgrade -f on helm install or helm upgrade
The values passed to a --set or --set-string flag
At a high level, you might want consider the two approaches below:
If your environments have major differences between them then passing a different values.yaml file is a option and worth the extra maintenance.
On the other hand, if the differences are only with a few fields - consider using just one base values.yaml file with default values and override just the specific fields with the --set flag.
(*) In your specific case, you divided the DEV/PROD configuration into different files which is a good practice but there are cases where the difference can be only with one or two urls (and maybe some secrets that you'll want to pass as inline values anyway). So you can save yourself the extra maintenance.

Related

How to structure Helm chart with different environments?

I plan to use Helm for deploying purposes. I have three applications/pods p1,p2,p3 and each of these has 2 enivronments dev, prod and in each environment there is a configmap.yml and deployment.yml.
I plan on using helm, however how can I structure these. Do I need three helm charts?, one per application or is it possible to pack everything in one helm, considering the constraints.
I thought of the following structure.
+-- charts
| \-- my-chart
| +-- Chart.yaml # Helm chart metadata
| +-- templates
| \-- p1
+-- configmap1.yml
+-- dep1.yaml
............................ similiary for p2,p3
| +-- values.yaml # default values
| +-- values.dev.p1.yaml # development override values
| +-- values.dev.p2.yaml
| +-- values.dev.p3.yaml
| +-- values.prod.p1.yaml # production override values
| +-- values.prod.p2.yaml
| +-- values.prod.p3.yaml
Now if I want to deploy p1 in prod , then I simply
helm install -f values.prod.p1.yaml helm-app
Would this work is this the general convention?
You can use the single helm chart to manage all the deployment and config map.
Create the tpl for deployment and service so this single tpl (template) will use to generate the multiple deployment YAML configs.
So you will get the 3 YAML deployment file as output while you will be managing a single template file.
For configmap also you can follow same and keep in single helm chart is it's working fine for you.
For different environment you can mange the different values into values.yaml file like dev-values.yaml & prod-values.yaml
helm install -f values.prod.p1.yaml helm-app

How to override values from value.yaml file into value.dev.yaml file

I have some Helm value files.
There are value.yaml, value.dev.yaml, value.test.yaml, ... file.
In value.dev.yaml:
env:
"Environment" "development"
For some parameters in value.yaml file, I expected they override or insert them into pod parameters while deployment.
If I set up them into each value.dev.yaml, value.test.yaml,... it works with helm upgrade --install --set env.parameter=$variable
Now I want to define all variables in value.yaml file and expect them insert (override) them in to pods while deployment.
In value.yaml file :
env:
"Appconfig": "dev"
I'd like to combine them while deployment:
env:
"Environment": "development"
"Appconfig": "dev"
Apreciate your help !
You can specify the --values/-f flag multiple times. The priority will be given to the last (right-most) file specified. For example, if both myvalues.yaml and override.yaml contained a key called 'Test', the value set in override.yaml would take precedence:
$ helm install -f myvalues.yaml -f override.yaml myredis ./redis
Ref Helm Install Doc

get name of all resources from helm release

I want get name of resources from helm release. But I don't understand how.
I don't find anything
helm get all RELEASE_NAME --template '{{range .items}}{{.metadata.name}}{{end}}'
helm get all has a somewhat constrained set of options for its --template option; it gets passed in a single .Release object, and the set of created Kubernetes options is stored in text in a .Release.Manifest field.
helm get all RELEASE_NAME --template '{{ .Release.Manifest }}'
# returns the manifest as a string
There's a dedicated helm get manifest subcommand that returns the manifest as YAML.
Once you have the YAML, you need to extract the resource names from it. One approach is to use a tool like yq that can do generic queries over YAML:
helm get manifest RELEASE_NAME | yq eval '.metadata.name' -

helm chart - value file variables

I am using a helm chart (with sub-charts) to deploy my application.
I am using a value file for setting values.
I am looking a way to set variables in my value file (or any other place) that will be valid for my value file.
I have some sections (services) in my value files that I need to use the same value in it
so I am looking for a variable in my value file.
Is there any way that I can use variables for my value file?
Thx
Helm on its own can't do this.
If you control all of the charts and subcharts, you can allow specific values to have embedded Go templating. Helm includes a tpl extension function that will let you render an arbitrary string as a template. So if you have values
global:
commonKey: some value
otherKey: '{{ .Values.global.commonKey }}'
then you can render
- name: OTHER_KEY
value: '{{ tpl .Values.otherKey . }}'
But, you have to use tpl every place you access the key value(s); if you don't control the subcharts you may not be able to do this.
Higher-level tools may also let you do this. I'm familiar in particular with Helmfile which lets you declare multiple Helm charts and their settings, but also lets you use almost-Helm templating in many places. So your helmfile.yaml could specify:
environments:
default:
# These values are available when rendering templates in this file
values:
- commonKey: some value
releases:
- name: my-service
namespace: my-service
chart: ./charts/my-service
values:
# List items can be file names or YAML dictionaries.
# If it's a dictionary, arbitrary nested values.yaml content.
# If it's a *.yaml.gotmpl file name, templating is applied to the file.
- otherKey: '{{ .Values.commonKey }}'
yetAnotherKey: '{{ .Values.commonKey }}'
- ./my-service.yaml.gotmpl
Helmsman is simpler, but can only set chart values from environment variables; but I believe you can reference the same environment variable in different setString: options. You could also do something similar with the Terraform Helm provider, using Terraform's native expression syntax, particularly if you're already familiar with Terraform.

helm template output showing values not being resolved

I'm new to helm charts and K8s, so forgive me. I'm working on a project that deploys an application project with several apps as part of it. The previous dev that put the charts together was using a "find-and-replace" technique to fill in values for things like the image repository, tags, etc. This is making our CICD pipeline development tricky and not scalable. I'm trying to update the charts to use variables and values.yml files. Most of it seems to be working, values are getting passed down to the templates except for one part and I can't figure out why. Its a large project so I won't copy all the chart files. I'll try to lay out the important parts:
Folder structure:
helm
project1
dev
charts
app1
templates
*template files
Chart.yaml
values.yaml
app2
*same subfolders
app3
*same subfolders
Chart.yml
values.yml
Base Values.yml
artifactory_base_url: company.repo.io/repo_folder
imageversions:
app1_tag: 6.1.2-alpine-edge
app2_tag: 8.1.0.0-edge
app3_tag: 8.1.0.0-alpine-edge
app4_tag: 10.1.1-alpine-edge
initcontainer: latest
App Values.yml file
app:
image:
repository: "{{ .Values.artifactory_base_url }}/pingaccess"
tag: "{{ .Values.pa_tag }}"
deployment.yml template file
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.app.image }}"
I'm running the following helm template command to confirm that I'm getting the proper output for at least the app1 part before actually trying to deploy to the k8s cluster.
helm template app1 --set date="$EPOCHSECONDS" --set namespace='porject_namespace' --values helm/project1/dev/values.yaml helm/project1/dev/charts/app1
Most of the resulting yaml looks great, and it looks like the values I have defined in the base values.yml file are getting passed through in other areas like this example:
initContainers:
- name: appinitcontainer
image: "company.repo.io/repo_folder/initcontainer:latest"
But there is one portion that is populated from the deployment.yml template file that is still showing the curly braces for variables
containers:
- name: app1
image: "map[repository:{{ .Values.image_repo_base_url }}/app1 tag:{{ .Values.app1_tag }}]"
imagePullPolicy: Always
I've tried making variations in all the files mentioned above to remove quotes, use single quotes, etc. In those attempts I usually get a variation of the following errors:
"error converting yaml to json. did not find expected key"
"error mapping values"
I haven't been able to find a solution. I'm assuming that the "helm template" command should not contain any braces like that, all variables and values should be resolved. I'm hoping somebody can provide some tips of things I might be missing.
You're hitting two issues here. First, .Values.app.image is a map containing the two keys repository and tag; that's why you get the weird map[repository:... tag:...] syntax in the output. Second, string values in values.yaml aren't reinterpreted for Helm template syntax; that's why the {{ ... }} markup gets passed through to the output.
This in turn means you need to do two things. To resolve the map, construct the string from the contents of the dictionary; and to resolve the templating markup inside the string values, use Helm's tpl function.
{{- $repository := tpl .Values.app.image.repository . }}
{{- $tag := tpl .Values.app.image.tag . }}
image: "{{ $repository }}:{{ $tag }}"
(You may find it useful to separate "repository", "registry" or "image", and "tag" into three separate parts, since probably all of your images are coming from the same repository; that would let you configure the repository in one place and customize the image name per component. The bitnami/postgresql chart is one example of this setup.)