Right now, I have to install multiple helm charts in different namespaces for my product to work. I am trying to create a super helm chart in which I am planning to add the helm charts (of my tools, as mentioned above) and install them in one shot. My problem is, as these tools are in different namespaces I am not sure where to specify the namespace key where I want that particular dependency (chart) to be installed. For e.g. if below is the Charts.yaml of my super helm chart
dependencies:
- name: first_chart
version: 1.2.3
repository: https://firstchart.repo
- name: second_chart
version: 1.5.6
repository: https://secondchart.repo
I want my first chart to be installed in namespace foo and the second chart to be installed in namespace bar.
I was looking at using conditions but I believe conditions will only take a boolean as a value.
I stumbled upon this link (https://github.com/helm/helm/issues/2060) which says the we can do it in Helm 3 but mostly on how to keep releases between different namespaces. It does not specifically answer my question.
There is no builtin way to do this with pure Helm, but there is with helmfile.
Your example as helmfile.yaml:
releases:
- name: chart1 # name of the release (helm install <...> first_chart)
chart: repo1/first_chart
version: 1.2.3
namespace: foo
- name: chart2
chart: repo2/second_chart
version: 1.5.6
namespace: bar
# in case you want helmfile to automatically update repos
repositories:
- name: repo1
url: https://firstchart.repo
- name: repo2
url: https://secondchart.repo
Then, run:
helmfile sync => run helm install/upgrade on all releases, or
helmfile apply => same as sync, but do a diff first to only upgrade/install releases that changed
There is way more to helmfile, but this is the gist.
PS: if you struggle with values or want to have something similar to how umbrella Chart values are handled, have a look at helmfile: a simple trick to handle values intuitively
The way I solved this for my clusters with with ArgoCD's App of Apps cluster bootstrapping model. Of course, it requires that ArgoCD is install the cluster. However, for many reasons not relevant to this answer I would highly encourage installing ArgoCD regardless of the easy of bootstrapping capabilities.
Assuming ArgoCD is in place the structure is a single Helm chart containing templates for each of the child charts it will deploy and managed via Argo's Application CRD. You will notice there is a definition as part of the CRD, spec.destination.namespace, which governs where the chart will be deployed.
An example Application template which governs my cert-manager chart deployment to the cert-manager namespace looks like:
{{- if .Values.certManager.enabled }}
# ref: https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#applications
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: cert-manager
# You'll usually want to add your resources to the argocd namespace.
namespace: argocd
# Add a this finalizer ONLY if you want these to cascade delete.
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
# The project the application belongs to.
project: cluster-configs
# Source of the application manifests
source:
repoURL: https://github.com/yourOrg/Helm
targetRevision: {{ .Values.targetRevision }}
path: charts/cert-manager-chart
# helm specific config
helm:
# Helm values files for overriding values in the helm chart
# The path is relative to the spec.source.path directory defined above
valueFiles:
{{- range .Values.certManager.valueFiles }}
- {{ . }}
{{- end }}
# Optional Helm version to template with. If omitted it will fall back to look at the 'apiVersion' in Chart.yaml
# and decide which Helm binary to use automatically. This field can be either 'v2' or 'v3'.
version: v3
# Destination cluster and namespace to deploy the application
destination:
server: https://kubernetes.default.svc
namespace: cert-manager
{{- end }}
With a corresponding values.yaml file for this parent chart which may look something like the following with the path to desired value file(s) in that child chart's directory specified.
targetRevision: v1.11.0
certManager:
enabled: true
valueFiles:
- "values.yaml"
clusterAutoScaler:
valueFiles:
- "envs/dev-account/saas/values.yaml"
clusterResourceLimits:
valueFiles:
- "values.yaml"
externalDns:
valueFiles:
- "envs/dev-account/saas/values.yaml"
ingressNginx:
enabled: true
valueFiles:
- "values.yaml"
Below is a screenshot of one of my app of apps directory to complete the example.
Related
I have an yaml which gets deployed by the ArgoCd controller, that deploys a helm chart from artifactory.
For my local development I use a sperate values.yml in the helm chart.
My controller looks like below refer git link
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: <name-to-the-app>
namespace: argocd
spec:
project: default
source:
repoURL: https://harbor.1000kit.org/chartrepo/1000kit/
targetRevision: <version-hardcode-in-repo>
chart: <chart-name-that-is-getting-deployed>
helm:
releaseName: <release-name-hardcoded>
# custom values to override the helm chart one
values: |
<pass-the-custom-values>>
destination:
server: https://kubernetes.default.svc
namespace: <namespace-where-to-be-deployed>
syncPolicy:
automated:
prune: true
selfHeal: true
The helm chart that is getting deployed is containing the values.yaml
I am trying to override the values.yml present in the helm chart in artifcatory, so passing all the values in part of the source -> helm -> values like above.
Question:
In the custom values, I skipped some value but the ArgoCd is fetching those values from the helm chart value.yml and using it. Is this the behavior?
Another observation is that, The helm chart repo values.yaml is being loaded as parmater in the ArgoCD, and the argocd.io application yaml the values are displayed in the UI.
From the documents i see there are parameters, which can be overridden but the values can't be overridden.
spec:
source:
helm:
parameters:
- name: app
value: $ARGOCD_APP_NAME
Is there any option to explicitly tell ArgoCD to ignore the values.yml from the helm chart in artifactory.
I am new to ArgoCd
Looks like,
The helm chart in the artifactory has a key : value combination say
# value present in the helm chart values.yaml
app-details:
name: "demoapp"
version: "1.0"
description: "simple demo app"
In argoCd application manifest
# .....
helm:
releaseName: <release-name-hardcoded>
# custom values to override the helm chart one
values: |
app-details :
name: "demoapp"
version: "1.0"
# if I didn't specify the description here <--------------- *
# ....
* - ArgoCd is setting the default value (from values.yaml) for description key in this case. This description value can be seen in the deployed manifest.
Also the values.yml data are displayed as parameter in the UI.
I had to use a different approach, where I need to make changes in the template charts that uses this description value.
I’m using Argocd with helm charts. I have two environments: uat, prod.
As far as I understand, proper approach for helm is to have base folder with commons + per env folder.
So I have single branch with 3 folders:
base # for commons: Chart.yaml, templates, etc.
uat # for uat values.yaml
prod # for prod values.yaml
In my helm chart I have following Chart.yaml (stored in base folder):
apiVersion: v1
appVersion: 1.0.11
name: my-nice-app
version: 1.0.11
With every release I increase appVersion and version (version is used as image tag version in charts).
I use declarative approach to deploy helm chart (this is uat application resource, similar is for prod):
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-nice-app
namespace: argocd
spec:
project: default
source:
repoURL: some-url
targetRevision: HEAD
path: base
helm:
version: v3
valueFiles:
- uat/values.yaml
destination:
server: https://kubernetes.default.svc
namespace: uat
syncPolicy:
syncOptions:
- CreateNamespace=false
automated:
selfHeal: true
prune: true
Question:
I do update uat values file.
I do update Chart.yaml with new version.
I would like to deploy uat only (but when I update base prod would also triggers).
Where or how should I store Chart.yaml? Should I change Argocd Application resource? Or only option is to duplicate charts per env?
I prefer also not to store any version related info in Argocd Application resource (so not to change it every time).
It would be nice not to apply kustomized.io.
You should split it into 2 charts (base chart and value chart)
base chart is chart dependency of value chart, like that if you update base chart, value chart won't be affected if you don't update chart dependency.
File Chart.yaml of value-chart will look like this.
apiVersion: v2
name: my-nice-app-prod
description: Chart for production
type: application
version: 0.0.1
appVersion: "1.0.0"
dependencies:
- name: my-nice-app-chart
version: 0.1.9
Link references:
https://helm.sh/docs/helm/helm_dependency/
You should use the variants folder,
The base directory holds configuration which is common to all environments. It is not expected to change often. If you want to do changes to multiple environments at the same time, it is best to use the “variants” folder.
Please go through this doc
https://codefresh.io/blog/how-to-model-your-gitops-environments-and-promote-releases-between-them/
I am currently using Kustomize. We are have multiple deployments and services. These have the same spec but different names. Is it possible to store the spec in individual files & refer them across all the deployments files?
Helm is a good fit for the solution.
However, since we were already using Kustomize & migration to Helm would have needed time, we solved the problem using namePrefix & label modifiers in Kustomize.
Use Helm, in ArgoCD create a pipeline with helm:3 container and create a helm-chart directory or repository. Pull the chart repository, deploy with helm. Use values.yaml for the dynamic values you want to use. Also, you will need to add kubeconfig file to your pipeline but that is another issue.
This is the best offer I can give. For further information I need to inspect ArgoCD.
I was faced with this problem and I resolved it using Helm3 charts:
I have a chart. Yaml file where I indicated my release name and version
values. Yam where I define all variable to use for a specific environment.
Values-test. Yaml a file to use, for example, in a test environment where you should only put the variable that must be changed from an environment to another.
I hope that can help you to resolve your issue.
I would also suggest using Helm. However a restriction of Helm is that you cannot create dynamic values.yaml files (https://github.com/helm/helm/issues/6699) - this can be very annoying, especially for multi-environment setups. However, ArgoCD provides a very nice way to do this with its Application type.
The solution is to create a custom Helm chart for generating your ArgoCD applications (which can be called with different config for each environment). The templates in this helm chart will generate ArgoCD Application types. This type supports a source.helm.values field where you can dynamically set the values.yaml.
For example, the values.yaml for HashiCorp Vault can be highly complex and this is a scenario where a dynamic values.yaml per environment is highly desirable (as this prevents having multiple values.yaml files for each environment which are large but very similar).
If your custom ArgoCD helm chart is my-argocd-application-helm, then the following are example values.yaml and the template which generates your Vault application i.e.
values.yaml
server: 1.2.3.4 # Target kubernetes server for all applications
vault:
name: vault-dev
repoURL: https://git.acme.com/myapp/vault-helm.git
targetRevision: master
path: helm/vault-chart
namespace: vault
hostname: 5.6.7.8 # target server for Vault
...
templates/vault-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: {{ .Values.vault.name }}
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
destination:
namespace: 'vault'
server: {{ .Values.server }}
project: 'default'
source:
path: '{{ .Values.vault.path }}'
repoURL: {{ .Values.vault.repoURL }}
targetRevision: {{ .Values.vault.targetRevision }}
helm:
# Dynamically generate `values.yaml`
values: |
vault:
server:
ingress:
activeService: true
hosts:
- host: {{ required "Please set 'vault.hostname'" .Values.vault.hostname | quote }}
paths:
- /
ha:
enabled: true
config: |
ui = true
...
These values will then override any base configuration residing in the values.yaml specified by {{ .Values.vault.repoURL }} which can contain config which doesn't change for each environment.
The syntax for adding a dependency to a helm 3 chart looks like this (inside of chart.yaml).
How can you specify a release name if you need multiple instances of a dependency?
apiVersion: v2
name: shared
description: Ingress Controller and Certificate Manager
type: application
version: 0.1.1
appVersion: 0.1.0
dependencies:
- name: cert-manager
version: ~0.13
repository: https://charts.jetstack.io
In the CLI it's just helm upgrade -i RELEASE_NAME CHART_NAME -n NAMESPACE
But inside of Chart.yaml the option to specify a release seems to be missing.
The next question I have is if there's a weird way to do it, how would you write the values for each instance in the values.yaml file?
After 5 more minutes of searching I found that there's an alias field that can be added, like so:
dependencies:
- name: cert-manager
alias: first-one
version: ~0.13
repository: https://charts.jetstack.io
- name: cert-manager
alias: second-one
version: ~0.13
repository: https://charts.jetstack.io
And in the values.yaml file
first-one:
# values go here
second-one:
# values go here
Reference https://helm.sh/docs/topics/charts/#the-chartyaml-file
Using cert-manager is just an example, I can't think of a use-case that would need two instances of that particular chart. I'm hoping to use it for brigade projects
I'm doing a very simple chart with helm.
It consists on deploying a chart with just one object ("/templates/pod.yaml"), that have to be deployed just if a parameter of file Values.yaml is true.
To provide an example of my case, this is what I have:
/templates/pod.yaml
{{- if eq .Values.shoudBeDeployed true }}
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
name: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
{{- end}}
Values.yaml
shoudBeDeployed: true
So when I use shoudBeDeployed with true value, helm installs it correctly.
My problem is that when shoudBeDeployed is false, helm doesn't deploy anything (as I expected), but helm shows the following message:
Error: release CHART_NAME failed: no objects visited
And if I execute helm ls I get that CHART_NAME is deployed with STATUS FAILED.
My question is if there is a way to not have it as a failed helm deploy. So I would like to not see it when using the command helm ls
I know that I could move the logic of shoudBeDeployed variable outside the chart, and then deploy the chart or not depending on its value, but I would like to know if there is a solution just using helm.
#pcampana I think there is no way to stop helm deployment if there is nothing to deploy. But here is a trick that you can use to delete a helm chart if it is
FAILED.
helm install --name temp demo --atomic
where demo is the helm chart directory and temp is release name .
release name is mandatory for this to work.
One scenario is when you see error
Error: release temp failed: no objects visited
you can use above command to deploy helm chart.
I think this might be useful for you.