How to refer to a helm chart in the same repository - kubernetes-helm

I want to maintain a few Helm charts in the same repository that refer to each other in their respective requirements.yaml files. How should these charts refer to each other's relative paths?
For local development I can use the file:// protocol as in
name: chart-name
repository: file://../chart-name
However when I move to a hosted repository I will need to change this. I would prefer that this directory of charts does not need to have its final location baked into its repository.yaml files. Is this possible?

When you move to a hosted repository, won't you have had to publish each chart?
If so, as long as you don't have cyclic dependencies, publish each chart in dependent order to your hosted repo and then update requirements.yaml.
i.e. if you have 3 charts A,B and C.
A has no dependency on B nor C
B depends on A
C depends on B
Publish A to the hosted repo, update B's requirements to point to the hosted repo name of A, then publish B and repeat the update process for C.
I'm doing something similar but I don't use a hosted repo. I already have a large Ansible setup so I wrote a role which installs charts directly from directories. There's a single git repo with all (currently 7) my charts and this minus running a helm server is a similar process. The obvious downside being the manual update of requirements, but I'm not sure there's any other choice on that.
EDIT
A bit hacky but could work:
To avoid editing dependencies one way is to also run your chart repo locally.
If your repo is available at charts.domain.com, add a dependency to this as per usual
dependencies:
- name: my-chart
repository: http://charts.domain.com
version: 0.0.1
then, when you develop locally, add an entry to your hosts file which points charts.domain.com to your localhost charts.
Sample workflow might be something like:
mkdir my-charts
mv my-char-a-0.0.1.tgz my-charts/
helm repo index my-charts/ --url http://charts.domain.com
Now serve the index/repo generated from localhost. This way your dependency is always to charts.domain.com
Depending on which remote host you're using you could just rsync this local index to your remote when you're happy to release and that way you reduce the chance of your local and remotes diverging.
Again, caveat being you need to enable disable this host entry depending on if your developing or wanting to use the live repo.
You can always script the editing of host file entry.

Related

How to add helm repo from an existing github project?

I have an existing github project. I want to create/add a helm folder to the project to store the helm yaml files. I want to reference this github project/folder to act like a helm repo in my local/dev environment. I know I can add the charts to my local/default helm repo. The use case is if another developer checks out the code in github and he needs to work on the charts then he can run helm install directly from the working folder. The helm.sh website has instructions of adding a gh-pages branch but I am wondering if I can avoid it.
Can I use an existing github project and it via the helm repo add command?
Unfortunately, I wasn't able to find a way to publish helm charts via GitHub using private repositories. On a theoretical level, it might work using GitHub token and 2nd (raw URLs method), but I haven't tried it. Since you're using docker registry anyway, it might be worth trying using OCI (docker) registry to store the charts.
If that doesn't work, or you have public repos, it is possible to either use GitHub Pages, or use GitHub raw URLs. Both of the solutions require public repository.
To use GitHub pages:
Setup github pages to publish docs folder as github pages (you can use a different name, just substitue later)
Package the helm repo as .tgz (using helm package): helm package charts/mychart -d docs/. Substitute charts/mychart with a path to a chart root folder
Include an index.yaml -- an index file for the repository helm repo index ./docs --url https://<YOUR_ORG_OR_USERNAME>.github.io/<REPO_NAME>
Now you can add the repo: helm repo add <INTERNAL_NAME> https://<YOUR_ORG_OR_USERNAME>.github.io/<REPO_NAME>
To use Raw URLs:
Place index.yaml and chart TGZs into a folder called docs, just like above
Now you can add a repo: helm repo add <INTERNAL_NAME> https://raw.githubusercontent.com/<YOUR_ORG_OR_USERNAME>/<REPO_NAME>/<BRANCH_USUALLY_MASTER>/docs
Firstly make sure that you have have fully functional helm repository. The tricky part is to access it as if it was simple HTTP server hosting raw files. Fortunately Github provides such feature using raw.githubusercontent.com. In order for helm to be able to pull files from such repository you need to provide it with Github username and token (Personal Access Token):
> helm repo add - username <your_github_username> - password <your_github_token> my-github-helm-repo 'https://raw.githubusercontent.com/my_organization/my-github-helm-repo/master/'
> helm repo update
> helm repo list
NAME URL
stable https://kubernetes-charts.storage.googleapis.com
local http://127.0.0.1:8879/charts
my-github-helmrepo https://raw.githubusercontent.com/my_organization/my-github-helm-repo/master/
> helm search my-app
NAME CHART VERSION APP VERSION DESCRIPTION
my-github-helmrepo/my-app-chart 0.1.0 1.0 A Helm chart for Kubernetes
These are steps for adding new packages to existing repository
If you want to add new package to existing repository simply:
1. Place new package in your local repository root
2. Execute: helm repo index .. This will detect new file/folder and make updates.
3. Commit and push your new package
4. Finally execute command: helm repo update
Security ascpect
It is important to realize where does helm actually store your Github token. It is stored as plain text in ~/.helm/repository/repositories.yaml. In this case it will be good to generate token with as few permissions as possible.
Take a look here: hosting helm private repository.

Helm chart versions for CI/CD

I have a helm repository set up for my CI/CD pipeline, but the one thing I am having trouble with is helm's versioning system which is focused on a semantic versioning system as in x.x.x.
I want to be able to specify tags like "staging", "latest", and "production", and although I am able to successfully upload charts with string versions
NAME CHART VERSION APP VERSION
chartmuseum/myrchart latest 1.0
Any attempt to actually access the chart fails, such as
helm inspect chartmuseum/mychart --version=latest
Generates the error:
Error: failed to download "chartmuseum/mychart" (hint: running 'helm repo update' may help)
I don't really want to get into controlled semantic versioning at this point in development, or the mess that is appending hashes to a version. Is there any way to get helm to pull non-semantically tagged chart versions?
My approach to this, where I do not want to version my chart (and subcharts) semanticaly as well is not to use helm repository at all and just pull whole chart in CI/CD from git instead. If you are publishing them to wider audience this may not suit you, but for own CI/CD which is authorized to access our repositories anyway it works like charm.
I found something that worked for me. Since the semvar allows you to append values after the last number like 0.1.0-aebcaber, I've taken to simply using 0.1.0-latest and overwriting that in chartmuseum on uploads.

Secure access to a private helm repository

Is this even possible with helm?
What options for security are possible (BasicAuth? Client Certs? OAuth2?)
Is there any example / documentation about this (both server and client side)?
Helm Private Repository using private GitHub repositories.
Steps:
Create a private GitHub repository named private-helm-registry or any.
Place your Raw Helm Charts.
Create a charts folder and place index.yaml and packaged charts in .tgz format inside this folder.
Create a GitHub Personal Access Token with read-only access.
Add your Repository to helm using the following command:
$ helm repo add helm-registry 'https://<git_hub_personal_access_token>#raw.githubusercontent.com/myGitHubAccountName/private-helm-registry/master/charts/'
"helm-registry" has been added to your repositories
Note:
1. Enclose the Url with single quotes ' '.
2. The trailing / is mandatory.
To add development or other branches as helm repository, use branch name:
$ helm repo add helm-registry-dev 'https://<git_hub_personal_access_token>#raw.githubusercontent.com/myGitHubAccountName/private-helm-registry/<branch>/charts/'
"helm-registry-dev" has been added to your repositories
Explore more at: Using a private github repo as helm chart repo.
If you want a private helm repository, there are not many options today, at least to my knowledge.
Use internal network where you deploy your repository, so it will be not accessible from the outer world.
Use helm plugins or write your own.
So basically there are no built-in helm private repositories, but you can achieve required functionality with helm plugins.
Plugin examples:
GitHub - it is for using GitHub Pages as a chart repository. Not a private repo, but it shows an idea of a plugin, it is very small and simple.
Keybase - similar to GitHub plugin, but stores charts in Keybase instead. Still not private, but can be modified to use keybase /private directories.
App Registry - uses app registry (quay.io) to store charts.
AWS S3 - provides a way to use Amazon S3 as a private repo for helm charts. I am the author of this plugin, I wrote it because all options above were not suitable for my purposes.
Azure Blob Stoage - This blog post contains a way to use Azure Blob storage as a private repo for helm charts
I assume you mean a Helm Repo rather than securing the docker images.
My understanding is that it's just a basic webserver
You could just use GCS or S3 and set up the IAM rules to secure them?

How do I version control a kubernetes application?

I've checked out helm.sh of course, but at first glance the entire setup seems a little complicated (helm-client & tiller-server). It seems to me like I can get away by just having a helm-client in most cases.
This is what I currently do
Let's say I have a project composed of 3 services viz. postgres, express, nginx.
I create a directory called product-release that is as follows:
product-release/
.git/
k8s/
postgres/
Deployment.yaml
Service.yaml
Secret.mustache.yaml # Needs to be rendered by the dev before use
express/
Deployment.yaml
Service.yaml
nginx/
Deployment.yaml
Service.yaml
updates/
0.1__0.2/
Job.yaml # postgres schema migration
update.sh # k8s API server scritps to patch/replace existing k8s objects, and runs the state change job
The usual git stuff can apply now. Everytime I make a change, I make changes to the spec files, test them, write the update scripts to help move from the last version to this current version and then commit it and tag it.
Questions:
This works for me so far, but is this "the right way"?
Why does helm have the tiller server? Isn't it simpler to do the templating on the client-side? Of course, if you want to separate the activity of the deployment from the knowledge of the application (like secrets) the templating would have to happen on the server, but otherwise why?
Seems that https://redspread.com/ (open source) addresses this particular issue, but needs more development before it'll be production ready - at least from my team quick glance at it.
We'll stick with keeping yaml files in git together with the deployed application for now I guess.
We are using kubernetes/helm (the latest/incubated version) and a central repository for Helm charts (with references container images built for our component releases).
In other words, the Helm package definitions and its dependencies are separate from the source code and image definitions that make up the several components of our web applications.
Notice: Tiller has been removed in Helm v3. Checkout this answer to see details on why it needs tiller in Helm v2 and why it's removed in Helm v3: https://v3.helm.sh/docs/faq/#removal-of-tiller
According to the idea of GitOps, what you did is a right way (to perform release from a git repo). However, if you want to push it further to make it more common, you can plan more goals including:
Choose a configuration management system beyond k8s app declarative definition only. E.g., Helm (like above answer https://stackoverflow.com/a/42053983/914967), Kustomize. They're pure client-side only.
avoid custom release process by altering update.sh with popular tools like kubectl apply or helm install.
drive change delivery from git tags/branches by using a CI/CD engine like argocd, Travis CI or GitHub Actions.
Uses branching strategy so that you can try changes on test/staging/production/ environment before delivering it directly.

Is it possible to have ansible use a "remote" playbook for git-based continuous deployment?

I need to manage a few servers that run code that is currently being deployed there as a couple of git repositories. I would like to be able to store in the project's repository the parts (if not all) of the playbook that is relevant for the repository. For example, the list of package dependencies, virtualenv requirements, configuration templates. This will also allow those to change in a per branch/commit way. Meaning I can make sure that if I need to deploy a specific branch/commit, playbook that is correct for that commit is being used, if, say, the configuration template being used changed.
It seems like the only solution is to checkout the git repository locally. Is it possible in ansible to tell it to run a remote play book (from the git repository that is being checked out on the server)? I was thinking of having ansible run a ansible using a local connection on the remote host, I haven't tried it to see if this will actually work out.
How do people manage to use ansible for continuous deployment based on git without some mechanisms for running a remote playbook?
Take a look at ansible-pull.
It pulls the repo and executes playbook.