How to pass dynamic data to helm subchart - kubernetes

I'm using the mongodb helm chart and the mongo-express one. mongodb generates the name depending on my release name, so it is dynamic. The mongodb service name will be something like my-release-mongodb.
mongo-express requires to pass mongodbServer - the location at which the mongodb can be reached. How can I provide this value to mongo-express if it is generated and can change depending on the release name?

Helm doesn't directly have this ability. (See also helm - programmatically override subchart values.yaml.) It has a couple of ways to propagate configured values from a subchart to a parent but not to use computed values, or to send these values to a sibling chart.
In the particular case of Services created by a subchart, I've generally considered the Service name as part of the chart's "API": you know the Service will be named {{ .Release.Name }}-mongodb and you just have to hard-code that in the consuming chart.
If you're launching this under a single "umbrella" chart, this is a little more straightforward. Both parts have the same release name, so you can construct the service name the same way. (Umbrella charts have other limitations – if you have multiple services that each should have an independent MongoDB installation, Helm will only deploy the database once for the whole umbrella chart – but you can still hit this same problem making HTTP calls between microservices.)
If they're totally separate installations, you may need to pick the release name yourself and pass it in as a value.
helm install thedb ./mongodb
helm install theapp ./mongo-express --set serviceName=thedb-mongodb
This also a place where a still higher-level tool like Helmfile or Helmsman can come in handy, since that would let you specify these parameters in a fixed file.

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
...

Helm - how to add secrets for subchart from repo?

I installed mongodb chart from bitnami as follows
helm install mongodb bitnami/mongodb
which created this file ./charts/mongodb-10.15.2.tgz
What I do not understand and what I cant find is how to link Secrets to these kind of subcharts. I am aware that values.yaml can override child subcharts. What really confuses me is that this downloaded subchart is just encoded file and I have absolutely no idea how to bend it in terms of deployment/service...
Therefore my question is, how to supply this subchart (of which I dont know anything) with Secrets like dbpassword, dbroot... ? (I hope that the secrets are not supplied via values.yaml override)
When you have sub chart, you map them probably as a dependency (look at the condition carefully, that will match with your values.yaml of the same parent chart.), and here is how you pass the sub-charts values.
Now, I believe you are using this mongodb chart, and in case you want to pass the passwords, you might want to create a k8s secret object and pass the name here.
Now let's say,
There is a chart A and MongoDB is a sub chart of the chart A,
if you add MongoDB as a dependency like this, you can put the configuration/values of chart MongoDB, in A values, just like this.
Now, for the secrets, there is mentioned in the values.yaml of MongoDB, you can create a custom secret and pass the name of the same there, if still not satisfied, you might want to pass the env vars directly to the MongoDB charts values.
and most importantly, when you defining any chart as dependency or sub chart, you would know which chart it is and what are the values it takes,
you can nest the same values in the parent chart.
When you have more time you can spend some here :)

Update helm chart values for different environments

I have helm charts created for a microservice that I have built and everything is working as expected. Now, I have created a new k8s namespace and I want to try to deploy the same helm charts as my old namespace. Although, I have just one value that I need it different while everything else remain the same.
Do I have to create another values.yaml for the new namespace and copy everything over and update the one field I want updated ? Or is there any other way ? I do not want to use the --set method of passing updates to the command line.
David suggested the right way. You can use different values.yaml where you can specify the namespace you want to deploy the chart:
$ helm install -f another-namespace-values.yaml <my-release> .
It's also entirely possible to launch helm chart with multiple values.
For more reading please check values section of helm docs.

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.

Whats the best way for stage-specific K8s config?

Let's say we have to manage a database connection string for stages test, int and prod.
What are the patterns here for Kubernetes?
I would handle general configuration via ConfigMaps. Create configuration for each environment and have your pods/deployment consume the values via environment variables.
This approach allows you to decouple your configuration from your k8 object definition and gives the ability to inject the required config per environment.
For sensitive data, which might include a username and password in a connection string for example, consider using Secrets instead.
The best way in my experience is to use a higher level construct like Helm Chart. This way you manage all your manifests in platform agnostic way and make them configurable during chart install/update.
That way you can use both ConfigMaps, Secrets or env vars, and populate them from values set during install/upgrade. With helm, you would do it somewhat like this :
helm install -f values.yaml : where values yaml contains all your non-default values (ie. db password)
helm upgrade <release> --reuse-values --set image.tag=1.0.1 to say release a new version keeping all other values defined during initial install.
For non-default components like ie. development database, you can use value like devdb.enabled with a default value to false and set it to true only on dev env where you want to launch devdb pod and point your database service there (all the logic for it within manifest templates in helm chart)