How to add custom templates to bitnami helm chart? - kubernetes-helm

I'm deploying a spring cloud data flow cluster on kubernetes with helm and the chart from bitnami. This works fine.
Now I need an additional template to add a route. Is there a way to somehow add this or inherit from the bitnami chart and extend it? Of course I'd like to reuse all of the variables which are already defined for the spring cloud data flow deployment.

That chart has a specific extension point for doing things like this. The list of "Common parameters" in the linked documentation includes a line
Name: extraDeploy; Description: Array of extra objects to deploy with the release; Value: []
The implementation calls through to a helper in the Bitnami Common Library Chart that calls the Helm tpl function on the value, serializing it to YAML first if it's not a string, so you can use Helm templating within that value.
So specifically for the Bitnami charts, you can include an extra object in your values.yaml file:
extraDeploy:
- apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: '{{ include "common.names.fullname" . }}'
...
As a specific syntactic note, the value of extraDeploy is a list of either strings or dictionaries, but any templating is rendered after the YAML is parsed; this is different from the normal Helm template flow. In the example above I've included a YAML object, but then quoted a string value that begins with a {{ ... }} template, lest it otherwise be parsed as a YAML mapping. You could also force the whole thing to be a string, though it might be harder to work with in an IDE.
extraDeploy:
- |-
metadata:
name: {{ include "common.names.fullname" . }}

You can just create the YAML template file in the templates folder and it will get deployed with the chart.
You can also edit the existing YAML template accordingly and extend it no need to inherit or much things.
For example, if you are looking forward to adding the ingress into your chart, add ingress template and respective values block in values.yaml file
You can add this whole YAML template in folder : https://github.com/helm/charts/blob/master/stable/ghost/templates/ingress.yaml
and specific values.yaml block for ingress.
Or for example your chart dont have any deployment and you want to add deployment you can write your own template or use form internet.
Deployment : https://github.com/helm/charts/tree/master/stable/ghost/templates
there is deployment.yaml file template and you can get specific variables that the template uses into values.yaml and you have extended the chart successfully.

Related

Helmfile with additional resource without chart

I know this is maybe a weird question, but I want to ask if it's possible to also manage single resources (like f.e. a configmap/secret) without a seperate chart?
F.e. I try to install a nginx-ingress and would like to additionally apply a secret map which includes http-basic-authentication data.
I can just reference the nginx-ingress-repo directly in my helmfile, but do I really need to create a seperate helm chart to also apply the http-basic-secret?
I have many releases which need a single, additional resource (like a json configmap, a single secret) and it would be cumbersome to always need a seperate chart file for each release?
Thank you!
Sorry, Helmfile only manages entire Helm releases.
There are a couple of escape hatches you might be able to use. Helmfile hooks can run arbitrary shell commands on the host (as distinct from Helm hooks, which usually run Jobs in the cluster) and so you could in principle kubectl apply a file in a hook. Helmfile also has some integration with Kustomize and it might be possible to add resources this way. As you've noted you can also write local charts and put whatever YAML you need in those.
The occasional chart does support including either arbitrary extra resources or specific configuration content; the Bitnami MariaDB chart, to pick one, supports putting anything you want under an extraDeploy value. You could use this in combination with Helmfile values: to inject more resources
releases:
- name: mariadb
chart: bitnami/mariadb
values:
- extraDeploy:
- |-
apiVersion: v1
kind: ConfigMap
...

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 do i pass a standalone mysql container as a dependency to a service in kubernetes-helm?

I have a service for which a helm chart has been generated. This helm chart spins off zookeeper and mysql containers with which the service communicates.
I now want to create a helm chart that spins off a platform of services of which the above service is one. When i attempt to do this, I use tags to disable the above service's dependencies that are listed in the helm chart, like so:
tags:
service-zookeeper: false
service-mysql: false
Now, i have a few init containers(liquibase) that populate the mysql instances created via dependencies whenever the service is deployed. I need to pass a separate, stand alone mysql container as the instance of mysql that this init container needs to populate. A similar chroots job for zookeeper exists.
The problem I need help tackling is that I can't seem to find a way to pass the separate mysql container as the container that needs to be populated by the first service's liquibase init-container. Is there any way to do so? Any help/insights are appreciated.
You just need the MySQL Service's hostname and credentials for this.
Remember that the Helm YAML templates can use everything in the Go text/template language. That includes conditionals {{ if ... }}...{{ else }}...{{ end }}, among other control structures, plus most of the support functions in the Sprig library. This can become verbose, but neatly solves this class of problem.
For the host name, one approach is to assert a single service name, whether installed by your chart itself or the wrapper chart. (If the top-level chart installs MySQL, and also installs your service, they will have the same Helm release name and the same generated hostname, independently of whether MySQL is a direct dependency of your chart.)
- name: MYSQL_HOST
value: {{ printf "%s-mysql.%s.svc.cluster.local" .Release.Name .Release.Namespace | quote }}
Another is to pass it in the values.yaml configuration, optionally. The Sprig default function is useful here.
- name: MYSQL_HOST
value: {{ .Values.mysqlHostname | default (printf "%s-mysql.%s.svc.cluster.local" .Release.Name .Release.Namespace) | quote }}
You can use a similar approach to either find the Secret the MySQL installation saves its passwords in or reconstruct it from configuration.

Helm `pre-install `hook calling to script during helm install

I want to use the pre-install hook of helm,
https://github.com/helm/helm/blob/master/docs/charts_hooks.md
in the docs its written that you need to use annotation which is clear but
what is not clear how to combine it ?
apiVersion: ...
kind: ....
metadata:
annotations:
"helm.sh/hook": "pre-install"
for my case I need to execute a bash script which create some env variable , where should I put this pre-hook script inside my chart that helm can use
before installation ?
I guess I need to create inside the templates folder a file which called: pre-install.yaml is it true? if yes where should I put the commands which create the env variables during the installation of the chart?
UPDATE
The command which I need to execute in the pre-install is like:
export DB=prod_sales
export DOMAIN=www.test.com
export THENANT=VBAS
A Helm hook launches some other Kubernetes object, most often a Job, which will launch a separate Pod. Environment variable settings will only effect the current process and children it launches later, in the same Docker container, in the same Pod. That is: you can't use mechanisms like Helm pre-install hooks or Kubernetes initContainers to set environment variables like this.
If you just want to set environment variables to fixed strings like you show in the question, you can directly set that in a Pod spec. If the variables are, well, variable, but you don't want to hard-code them in your Pod spec, you can also put them in a ConfigMap and then set environment variables from that ConfigMap. You can also use Helm templating to inject settings from install-time configuration.
env:
- name: A_FIXED_VARIABLE
value: A fixed value
- name: SET_FROM_A_CONFIG_MAP
valueFrom:
configMapKeyRef:
name: the-config-map-name
key: someKey
- name: SET_FROM_HELM
value: {{ .Values.environmentValue | quote }}
With the specific values you're showing, the Helm values path is probably easiest. You can run a command like
helm install --set db=prod_sales --set domain=www.test.com ...
and then have access to .Values.db, .Values.domain, etc. in your templates.
If the value is really truly dynamic and you can't set it any other way, you can use a Docker entrypoint script to set it at container startup time. In this answer I describe the generic-Docker equivalents to this, including the entrypoint script setup.
You can take as an example the built-in helm-chart from arc* project, here is the source code.
*Arc - kind of bootstraper for Laravel projects, that can Dockerize/Kubernetize existing apps written in this PHP framework.
You can place ENV in POD.yaml under the template folder. That will be the easiest option.

How to convert YAML to JSON when saving files into container using Kubernetes Configmap

We are going to write Helm chart and providing configuration file using configmap.
For some reasons our app is using JSON format configuration file. Currently we provide configuration file in Helm chart's values.yaml like this.
conffiles:
app_conf.json:
...(content in YAML)...
And to make it easy to modify, in values.yaml we use YAML format and in configmap's template we did conversion using "toJson",
data:
{{- range $key, $value := .Values.conffiles }}
{{ $key }}: |
{{ toJson $value | default "{}" | indent 4 }}
{{- end -}}
{{- end -}}
So in values.yaml it's YAML, and in configmap it will be JSON, then in container it will be stored into JSON file.
Our question is,
Is there a way to convert YAML to JSON when saving files into container? That is, we hope those configuration content could be 1) YAML in values.yaml 2) YAML in configmap 3) JSON file in container
Thank in advance.
I don't think there is anything out of the box but you do have options, depending upon your motivation.
Your app is looking for json and the configmap is mounted for your app to read that json. Your helm deployment isn't going to modify the container itself. But you could change your app to read yaml instead of json.
If you want to be able to easily see the yaml and json versions you could create two configmaps - one containing yaml and one with json.
Or if you're just looking to be able to see what the yaml was that was used to create the configmap then you could use helm get values <release_name> to look at the values that were used to create that release (which will include the content of the conffiles entry).