I have a little bit strange question, but maybe you can advise right way for this implementation.
I read about Helm Dependencies - when you can set the list of necessary charts and install them during your "main" chart install.
Is it possible to have this list of dependencies (with versions) without "main/root" chart?
For example - I want to install to my k8s cluster rabbit, redis, postgres and few my custom charts.
I don't want to run few times "helm chart install..." - I want to have one file with the list of helms/versions and install them in one command.
Also I want to easy upgrade helm charts using my the same one file - I want to change version, run again one command and update only necessary helm charts (with different versions).
Is it possible, or, maybe I should use something another for this?
There's no actual requirement that a Helm chart contain any templates of its own. It's possible to have a Helm chart that only contains dependencies; then running helm install on that "parent" chart would install all of the dependencies.
It would be valid to run helm create to build a new chart, then delete the values.yaml file and template directory from the generator, and fill in the requirements in Chart.yaml.
In your setup you're just installing infrastructure services. Occasionally you will see a dependency-only chart like this used to install several application components as well; this is sometimes called an umbrella chart. There are potential problems around umbrella charts where Helm likes to combine together dependencies: if different application components depend on different major versions of some chart there can be a conflict, and if you have multiple components that each depend on, say, Redis, an umbrella-chart installation will typically install just one shared Redis rather than an isolated Redis per component.
There are a number of ways to group multiple helm install commands into a single execution. Just writing a simple shell script will often work, depending on your needs. General-purpose automation tools (Ansible, Salt Stack, Chef) may have ways to run Helm, or if not, then to run arbitrary commands. There are also a couple of Helm-specific tools here: Helmsman is simpler and Helmfile more complex, but both let you "install" a collection of related charts without necessarily building an umbrella chart.
What you describe at the beginning of your question is called "Umbrella Charts". These are Charts that are used to bundle other Charts and manage these as one unit.
If this is not what you want to do (that's how I understand your question), then you are required to use other tools. One such tool is Helmfile, which allows you to define a list of Helm Charts, their versions and Helm Values. You can then install/upgrade/uninstall all referenced Helm Charts in one go.
Another option is to use kluctl (disclaimer: I'm the main developer of it). It basically allows you to do the same as offered by Helmfile, but in a different way/style. Kluctl focuses on Kustomize deployments while allowing you to easily pull-in third-party Helm Charts.
Having the mentioned Helm Charts in a Kluctl deployment would require you to have a kluctl deployment project that looks like this:
my_project
├── third-party
│ ├── rabbit
│ │ ├── kustomization.yaml
│ │ ├── helm-chart.yaml
│ │ └── helm-values.yaml
│ ├── redis
│ │ ├── kustomization.yaml
│ │ ├── helm-chart.yaml
│ │ └── helm-values.yaml
│ └── deployment.yaml
├── deployment.yaml
└── .kluctl.yaml
my_project/deployment.yaml
vars:
- values:
# this is arbitrary yaml
my:
ns: my-namespace
# this is also possible, loading vars from a file...
# many other sources are supported as well
# - file: my-config.yaml
deployments:
- include: third-party
commonLabels:
my.example.com/deployment: my-example-deployment
my.example.com/target: {{ target.name }}
my_project/third-party/deployment.yaml
deployments:
- path: rabbit
- path: redis
my_project/third-party/rabbit/kustomization.yaml
resources:
# this file is auto-generated by the helm-integration
- deploy.yaml
my_project/third-party/rabbit/helm-chart.yaml
helmChart:
repo: https://charts.bitnami.com/bitnami
chartName: rabbitmq
chartVersion: 10.3.2
releaseName: my-rabbit
# my.ns comes from the 'vars' defined in the root deployment.yaml
namespace: "{{ my.ns }}"
output: deploy.yaml
my_project/third-party/rabbit/helm-values.yaml
auth:
username: my-user
password: you-would-of-course-never-do-this
my_project/third-party/redis/helm-chart.yaml and helm-values.yaml
Basically the same as for rabbitmq, but with redis specific settings.
my_project/.kluctl.yaml
targets:
- name: dev
context: my-dev-cluster-context
Using kluctl
Based on the above example, you would then run kluctl helm-pull from the root project directory, which will then pre-pull all involved Helm Charts and write the contents besides the helm-chart.yaml files. These pre-pulled Charts are meant to be added to you version control (this might change in the future).
After that, you can run commands like kluctl diff -t dev, kluctl deploy -t dev and kluctl prune -t dev to work with the deployment.
kluctl helm-upgrade will help you while upgrading the pre-pulled Helm Charts.
Fully working example
A fully working example can be found here. The shown yamls from above are only meant to give an idea about the Helm related stuff.
Related
I have a ton of helm files, with the structure aligned to comply with Helm2, i.e. a separate requirements.yaml file and no type:application in Chart.yaml
Is there an option in helm-2to3 plugin that automagically places the requirements.yaml under Chart.yaml or do I have to write myself a script to do this?
My charts are checked-in to GH btw (not using a helm repo but operating them via GitOps)
edit: After confirmation in answers below that helm-2to3 does not provide that functionality, I ended up using the draft script below (warning: do not use it in production :) ); you can then proceed by a simple find/xargs oneliner to remove all requirements.yaml (or give them an extension of .bak to keep around for some time).
the chart should of course be run from the root directory of the project where your helm files are kept.
import os
import time
for root, dirs, files in os.walk(os.path.abspath(".")):
for file in files:
if file == "requirements.yaml":
path = os.path.dirname(os.path.join(root, file))
print(path)
os.chdir(path)
files = [f for f in os.listdir('.') if os.path.isfile(f)]
# print(files)
if "requirements.yaml" in files and "Chart.yaml" in files:
requirements_path = os.path.join(root, file)
print("Doing job in..: ", requirements_path)
chart_path = path + "/Chart.yaml"
print(chart_path)
with open(requirements_path) as req:
r = req.read()
with open(chart_path, 'a') as chr:
chr.write(r)
time.sleep(2)
I have a ton of helm template files, with the structure aligned to comply with Helm2, i.e. a separate requirements.yaml file and no type:application in Chart.yaml
The template files, within the helm chart, should work the same way under Helm 3. It's the Chart.yaml file, in each chart that will need to be edited. Unfortunately the helm-2to3 plugin won't do that for you. It's primarily designed to fix the Kubernetes cluster where you might have previously installed helm charts.
Helm3 is capable of installing older helm charts, so I suggest updating each helm chart one at a time.
To conclude, we're using GitOps too. Happily ArgoCD supports both Helm 2 + Helm 3 charts and only uses Helm to generate YAML. This means there is no Helm configuration on the cluster that requires updating. (Miles has a link in his answer, if you're alternatively using FluxCD)
There is a very good plugin that does what you're looking for: https://github.com/helm/helm-2to3
There is also information on migrating a GitOps setup on the Flux CD page (assuming you're using Flux and Helm Operator for your GitOps) https://docs.fluxcd.io/projects/helm-operator/en/stable/helmrelease-guide/release-configuration/#migrating-from-helm-v2-to-v3
Even more information here: https://helm.sh/docs/topics/v2_v3_migration/
I am starting to get my arms around using Kubernetes and Helm. Most of it makes perfect sense to me. I am missing one thing though and maybe someone can answer me. Why is there a separate Chart.yaml and values.yaml file? it seems to me that it would make better sense on a helm install command to have one file with a standard name. Asking for some DevOps wisdom.
Chart.yaml contains metadata about the chart itself: its name, the chart version, a description, and similar details. In Helm 3 it can contain dependencies as well.
values.yaml contains configuration settings for the chart. This typically includes things like the image repository to pull from, where you want data to be stored, and how to make the service accessible.
When you install the chart, you can use helm install -f to supply an additional YAML file of configuration options that override things in value.yaml, or helm install --set to set a single specific value. You can't override things in the Chart.yaml.
In the template code, items in Chart.yaml and values.yaml are available in the top-level data items .Chart and .Values, respectively.
I have a project that contains the deployment descriptor files for Kubernetes. This project has a folder structure that looks like this:
> project-deployment
> - base
> - dev
> - production
Inside the base folder, I have the kubernetes deployment files (deployment, service, namespaces etc.,). In the dev and production folder, I have kustomization.yaml that composes everything from the base folder. So far so good. I now want to introduce helm into this so that I can manage my releases much better. My question now is how do I go about structuring my folder structure?
Should I move everything (base, dev and production) folder into templates and just have one Charts.yaml and values.yaml? Any thoughts?
The configuration values that you push into your charts should be separate between environments. Build simple extendable charts that can have overrides per environment.
For example, a good workflow would have different value files per environment with specific differences in configuration:
~/myapp
└── config
├── production.yml
└── staging.yml
There are tools that can help you manage that particular use case. For example, consider using orca:
What Orca does best is manage environments. An Environment is a
Kubernetes namespace with a set of Helm charts installed on it. There
are a few use cases you will probably find useful right off the bat.
There are also some examples provided with it.
I also recommend going through the official The Chart Best Practices Guide.
If I have a chart that depends on another chart, what's the best practices around when it should be included as a package in the charts/ directory vs requirements.yaml vs the dependencies property in Chart.yaml?
For example, if I have a shared dependency that multiple Helm charts will use, should I always put that in a Helm repo and then just refer to it in each chart's requirements.yaml? Or is there a benefit to including it in the charts/ directory?
Example
requirements.yaml
dependencies:
- name: mariadb
version: 7.x.x
repository: https://charts.bitnami.com/bitnami
condition: mariadb.enabled
tags:
- wordpress-database
Chart.yaml
dependencies:
- name: mariadb
version: 7.x.x
repository: https://charts.bitnami.com/bitnami
condition: mariadb.enabled
tags:
- wordpress-database
charts/ directory
my-package.tgz
/charts
mariadb-7.0.0.tgz
...elided...
(and there's technically a 4th where I put the actual exploded chart into the charts directory)
If you need both Helm 2 and Helm 3 compatibility, include it in a separate requirements.yaml file. Most charts will work fine with either version of Helm (if the CLIs are somewhat different) so if your environment still needs Helm 2 compatibility, this is your best choice.
If you don't need Helm 2 compatibility, listing it in the Chart.yaml file is one file fewer.
I'd only manually download the chart (or unpack it) if I had a specific requirement to, probably because my product is uncomfortable downloading software from the public Internet without specifically verifying or approving it. Even then, it's common to have an internal repository of approved artifacts, and it'd be better to point the requirements.yaml/Chart.yaml at that repository than to keep an extra copy. (How do you handle open-source library dependencies in general?)
Even if you have a local dependency chart or support chart library, it's better to properly version it and publish it to a chart repository than to replicate its tarball in charts/ directories. The only benefit to putting a dependency in charts/ is not needing to have it in a repository, but you'll usually want a repository for ease of management.
I have a few microservices and one of them needs to use postreSQL. I configure this microservice using Helm 3.I have two different values.yaml per environments such as values.stage.yaml and values.prod.yaml.So my confusion is,
Should I independentyl install the PostreSQL? What I mean, in my scr code I have helm chart call helm/app. Should I create one more chart for PostreSQL? How can I configure the PostreSQL per environments.
2.In future, if one more microservice would like to use the same PostreSQL, what should I do to provide this feature.
Your chart should declare postgresql as a dependency, in Helm 3 in its Chart.yaml file. (In Helm 2 there was a separate requirements.yaml file.) You will need to run helm dep up (helm dependency update) before deploying your chart, but then when you run helm install it will install both your application and its database dependency.
So your Chart.yaml can look roughly like
apiVersion: v2
name: app
...
dependencies:
- name: postgresql
version: '^8'
repository: #stable
(In Helm 3 you also need to helm repo add the stable Helm charts repository.)
You can configure the database per environment in the same way you configure the rest of your application. Database settings would be nested under the subchart's name; at the command line you might --set postgresql.postgresqlPassword=..., and in a YAML file you'd put database settings under a postgresql: key.
If you have a second service that needs PostgreSQL, it should declare a dependency in the same way and install its own independent copy of the database. With database installation isolated inside containers this isn't considered particularly heavy-weight. If your two services need to communicate, they should do it via a network (often HTTP) connection and not by sharing a database.
By default, Helm picks values.yaml of root directory of the chart.
To install same Helm Chart with different values, you can do something like,
helm install . -f values.stage.yaml