Best practices for values in global section of helm values.yaml - kubernetes

Is it best practice to include installation of sub-charts in global part of values.yaml. Example..
Root level values.yaml
global:
foo: bar
subchartA:
enable: true
Or the best practice is to have subcharts out of the global part as shown.
global:
foo: bar
subchartA:
enable: true
Please provide a brief explanation why. Thank you

Subchart configuration settings need to be at the top level, outside a global: block.
At a style level, each chart should be independently installable, whether or not it's used as a subchart. Something like the stable/mysql chart is a reasonable example: you can manually helm install mysql stable/mysql --set mysqlPassword=... without mentioning global. That means when you include it as a dependency its settings need to be under the subchart's key in the values.yaml file.
At a mechanical level, when the subchart is run, the subchartA settings are promoted up to be .Values and then the original global: is merged with that (see Subcharts and Globals). So the subchart itself needs to be aware of the difference
{{/* Option 1 */}}
{{ .Values.global.subchartA.enabled }}
{{/* Option 2 (within subchartA) */}}
{{ .Values.enabled }}
and at the top level you need to use the form that's compatible with the included chart.
(If you browse through the "stable" Helm chart repository you'll see global used fairly sparingly; rabbitmq allows you to declare global.imagePullSecrets but that's close to it.)

Related

How can I do this in a Helm chart's values.yaml file?

We deploy our microservices in multiple AWS regions. I therefore want to be able to do this in a Helm chart values.yaml file.
# Default region
aws_region: us-east-1
aws_ecrs:
us-east-1: 01234567890.dkr.ecr.us-east-1.amazonaws.com
eu-north-1: 01234567890.dkr.ecr.eu-nort-1.amazonaws.com
image:
name: microservice0
repository: {{ .Values.aws_ecrs.{{ .Values.aws_region }} }} # I know this is incorrect
So now when I install the chart, I just want to do
$ helm install microservice0 myChart/ --set aws_region=eu-north-1
and the appropriate repository will be assigned to .Values.image.repository. Can I do this? If so what is the correct syntax?
NOTE: The image repository is just one value that depends on the AWS region, we have many more other values that also depend on the AWS region.
Pass the repository name as an ordinary Helm value.
# templates/deployment.yaml
image: {{ .Values.repository }}/my-image:{{ .Values.tag }}
Create a separate file per region. This does not necessarily need to be in the same place as the Helm chart. Provide the regional values as ordinary top-level values. You'll have multiple files that provide the same values and that's fine.
# eu-north-1.yaml
repository: 01234567890.dkr.ecr.eu-nort-1.amazonaws.com
Then when you deploy the chart, use the helm install -f option to use the correct per-region values. These values will override anything in the chart's values.yaml file, but anything you don't specifically set here will use those default values from the chart.
helm install microservice0 myChart/ \
--set-string tag=20220201 \
-f eu-north-1.yaml
You can in principle use the Go template index function to do the lookup as you describe; the top-level structure in Variable value as yaml key in helm chart is similar to what you show in the question. This is more complex to implement in the templating code, though, and it means you have different setups for the values that must vary per region and those that can't.

How to add automountServiceAccountToken: false using Helm

I have been trying to add automountServiceAccountToken: false into deployment using helm but my changes are reflecting inside deployment in kubernetes.
I tried below in helpers.tpl
{{- "<chart-name>.automountserviceaccounttoken" }}
{{- default "false" .Values.automountserviceaccounttoken.name }}
{{- end }}
in app-deployment.yaml
automountServiceAccountToken: {{- include "<chart-name>.automountserviceaccounttoken" . }}
in values.yaml
automountServiceAccountToken: false
But I can't see the changes. Please guide
You can give a try with following troubleshooting steps
In the helpers.tpl file you are taking the
automountserviceaccounttoken value from the values.yaml. In
values.yaml you metnioned automountserviceaccounttoken:false but
in the tpl file you are accesing the value like
automountserviceaccounttoken.name there is no attribute called
name under automountserviceaccounttoken in values file. Although you
are using default value in function sometimes it may not include it.
So correct he value in values.yaml.
Debug the deployed heml chart by using a command $helm template template-name. It will download the generated helm template along
with values. Check whether your desired values are reflecting or
not.
In case you are redeploying the chart try upgrading it by $helm upgrade [RELEASE] [CHART] and make sure your values are reflecting.
Before installing the helm chart running with dry-run will give us
the templates with compiled values. So using dry run will helps to
confirm the templates. Command for dry-run $helm install chart-name . --dry-run
Fore more information refer to official document

How to maintain a separate values file for a dependency Helm subchart that is shared with the parent chart?

I'm building a Helm chart that depends on another chart (let's say, "kafka" from bitnami repo). I declared this other chart as a dependency in my Chart.yaml:
dependencies:
- name: kafka
version: 14.0.5
repository: https://charts.bitnami.com/bitnami
Now I can set the values for this dependency chart in the top-level kafka section of my values.yaml. So far, so good.
What if I also need to run "kafka" chart independently with the same values? Let's say I extract them into a separate kafka-values.yaml. In this case, will I be able to reuse this separate file when I'm deploying the parent chart?
I understand that if I simply do --values kafka-values.yaml when deploying the parent chart, the values will be attached to the root scope instead of the kafka scope and "kafka" subchart won't see them.
You are absolutely right that it is a possibility for you to create an extra values file to pass into your chart. So let's say you create your kafka-values.yaml file with some values. If you now install your parent chart with the option --values kafka-values.yaml, this file will now be overlayed onto the values.yaml that is inside your helm chart. You can now also use this kafka-values.yaml to do the same thing if you would like to just install the kafka chart.
In general, the order of overlaying values in helm follows the order of this list. This means that any values passed into a chart, either by external file or individual values will overlay onto the values.yaml file in the chart. If the same values are specified, the values.yaml value will be overridden. If it has not been defined in a "lower priority", the values will be overlayed into the values for the chart.
EDIT
The main difference between what you are trying to do is the fact that your kafka-values.yaml for your parent chart need to be indented under the kafka: scope.
If you have something listed as a dependency of your chart, Helm will always try to install it connected to the parent chart. It won't look for another installation elsewhere in the cluster or try to import or export values from another Helm release.
You might reasonably want to use Kafka as a messaging or eventing bus across several services. In this case you don't necessarily want Kafka tied to a single service; you could install it at the cluster level, or on dedicated hardware, or use a cloud-hosted version of it. This means you need two things: a setting to say whether or not to install Kafka as a dependency, and a setting to point to the Kafka bootstrap server(s).
# values.yaml
# kafka has settings for the Kafka broker.
kafka:
# enabled indicates whether to install Kafka as part of this release.
enabled: true
# bootstrapServers is a comma-separated list of HOST:PORT indicating
# the location of at least one known Kafka broker. Only used if
# enabled is false.
bootstrapServers: ''
In your chart requirements, you can specify a condition to cause the dependency to only be installed if the value is set:
dependencies:
- name: kafka
version: ^14
repository: https://charts.bitnami.com/bitnami
condition: kafka.enabled # <--- add this line
Finally, you need to use template logic to pass the correct Kafka address to the application.
env:
- name: KAFKA_BOOTSTRAP_SERVERS
{{- if .Values.kafka.enabled }}
value: {{ .Release.Name }}-kafka:9092
{{- else }}
value: {{ .Values.kafka.bootstrapServers }}
{{- end }}
And then when you install the chart, you can specify to use either a local or remote Kafka.
helm install chart-with-local-kafka .
# --set kafka.enabled=true # on by default
helm install chart-with-remote-kafka . \
--set kafka.enabled=false \
--set kafka.bootstrapServers=kafka.infra.example.com:9092

Include system username in helm charts in helm version 2.14.1

I am using helm version 2.14.1. I have created helm charts for an application that will be deployed by users to test their code on kubernetes cluster. I want to add labels for username values, so I can retrieve deployments by users (deployments by user labels). Is there a way to include system username in helm charts just like we do in Java with System.getProperty("user.name"). My helm template is like this:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "common.fullname" . }}--{{ Release.name }}
labels:
application: {{ include "common.name" . }}
branch: "{{ Release.name }}"
username: "{{ System.user.name }}" # need to fetch the logged in user from system here
spec:
...
Is there a standard way to achieve this or is there anyway I can allow users to input there usernames from command line while using helm install or helm template commands?
EDIT:
Although, the --set works for me in setting the values for my chart, I also need to set the same value in the dependencies. Something like this:
values.yaml
username: ""
dependency1:
username: {{ .Values.username }}
dependency2:
username: {{ .Values.username }}
...
Of course the above implementation doesn't work. I need to reference the set value in the dependencies as well
This is a community wiki answer based on the comments and posted for better visibility. Feel free to expand it.
You can use the helm template command with a --set option:
--set stringArray set values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)
--set-file stringArray set values from respective files specified via the command line (can specify multiple or separate values with commas: key1=path1,key2=path2)
--set-string stringArray set STRING values on the command line (can specify multiple or separate values with commas: key1=val1,key2=val2)
The --set parameters have the highest precedence among other methods of passing values into the charts. It means that by default values come from the values.yaml which can be overridden by a parent chart's values.yaml, which can in turn be overridden by a user-supplied values file, which can in turn be overridden by --set parameters.
You can check more details and examples in the official docs.
I have resolved this. Thanks for help #MichaelAlbers and #WytrzymaƂyWiktor. So the solution is as below.
helm template path/to/chart --set global.username=username
And then in all the templates refer to this value as {{ .Values.global.username }}. This works for any dependency chart as well.

How to get the name of a child chart with Helm?

I have a helm chart that requires stable/redis as a child chart. The parent chart needs to expose the redis service as an environment variable.
The redis chart includes a template called redis.fullname. How can I refer to this in my parent chart? I.e. I want something like this in my parent deployment but it doesn't work:
kind: Deployment
spec:
template:
containers:
env:
- name: REDIS_CLUSTER_SERVICE_HOST
value: {{ template "redis.fullname" . }}
You can use '{{ .Release.Name }}-redis' in your parent chart. I had same requirement. This is my example in case you want to take a look ->https://github.com/kubernetes/charts/tree/master/incubator/distribution
Templates are now sharable across parent and child charts.
Refer this - https://github.com/kubernetes/helm/blob/master/docs/chart_template_guide/subcharts_and_globals.md#sharing-templates-with-subcharts
Problem that I see will be:
If your redis.fullname template uses a variable (eg: .Values.commonVariable) that has the same name in both the charts but with different value, then, while referencing it in the parent chart, the value that will be used will be of the parent chart and not the child's.
Consider this:
{{- define "zookeeper.fullname" -}}
{{- printf "%s-%s" (.Values.component) (.Values.subcomponent) -}}
{{- end -}}
Although I want my zookeeper.fullname to be referenced in a kafka (parent) chart. But the .Values.component and .Values.subcomponent will be used of kafka and not that for zookeeper (the subchart) in the case, which totally destroys the idea.
The way out in this specific case will be to use Jainish Shah's answer. But if this is not the case, please don't follow that answer. That destroys the idea of templating. If in any way you ought to change the template function in the subchart, you will also need to modify the value {{ .Release.Name }}-redis in your parent chart. This is not templating.
Link for the aforementioned issue - https://github.com/kubernetes/helm/issues/4314
Improving on Akash's answer, you could try to emulate the correct scope. This also only works if you know what variables the sub-template uses, but might be a bit more stable:
{{ template "redis.fullname" (dict "Values" $.Values.redis "Chart" (dict "Name" "redis") "Release" $.Release) }}