How to create a Helm chart repository using Amazon S3

Published 05-05-2018 00:00:00

Helm is a package manager for Kubernetes. You can bundle Kubernetes resources together as charts that define all the necessary resources and dependencies of an application. You can then use the Helm CLI to install all the pods, services, and ingresses for an application in one simple command.

Just like Docker or NuGet, there’s a common public repository for Helm charts that the helm CLI uses by default. And just like Docker and NuGet, you can host your own Helm repository for your charts.

In this post, I’ll show how you can use an AWS S3 bucket to host a Helm chart repository, how to push custom charts to it, and how to install charts from the chart repository. I won’t be going into Helm or Kubernetes in depth, I suggest you check the Helm quick start guide if they’re new to you.

If you’re not using AWS, and you’d like to store your charts on Azure, Michal Cwienczek has a post on how to create a Helm chart repository using Blob Storage instead.

Installing the prerequisites

Before you start working with Helm properly, youu need to do some setup. The Helm S3 plugin you’ll be using later requires that you have the AWS CLI installed and configured on your machine. You’ll also need an S3 bucket to use as your repository.

Installing the AWS CLI

I’m using an Ubuntu 16.04 virtual machine for this post, so all the instructions assume you have the same setup.

The suggested approach to install the AWS CLI is to use pip, the Python package index. This obviously requires Python, which you can confirm is installed using:

$ python -V
Python 2.7.12  

According to the pip website: pip is already installed if you are using Python 2 >=2.7.9 or Python 3 >=3.4

However, running which pip returned nothing for me, so I installed it anyway using

$ sudo apt-get install python-pip

Finally, we can install the AWS CLI using:

$ pip install awscli

The last thing to do is to configure your environment to access your AWS account. Add the ~./aws/config and ~./aws/credentials files to your home directory with the appropriate access keys, as described in the docs

Creating the repository S3 bucket

You’re going to need an S3 bucket to store your charts. You can create the bucket anyway you like, either using the AWS CLI, or using the AWS Management Console. I used the Management Console to create a bucket called my-helm-charts:

Creating a bucket

Whenever you create a new bucket, it’s a good idea to think about who is able to access it, and what they’re able to do. You can control this using IAM policies or S3 policies, whatever works for you. Just make sure you’ve looked into it!

The policy below, for example, grants read and write access to the IAM user andrew.

Once your repository is working correctly, you might want to update this so that only your CI/CD pipeline can push charts to your repository, but that any of your users can list and fetch charts. It may also be wise to remove the delete action completely.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowListObjects",
      "Effect": "Allow",
      "Principal": {
        "AWS": ["arn:aws:iam::111122223333:user/infra-helm-user"]
      },
      "Action": [
        "s3:ListBucket"
      ],
      "Resource": "arn:aws:s3:::my-helm-charts"
    },
    {
      "Sid": "AllowObjectsFetchAndCreate",
      "Effect": "Allow",
      "Principal": {
        "AWS": ["arn:aws:iam::111122223333:user/inrfa-helm-user"]
      },
      "Action": [
        "s3:DeleteObject",
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::my-helm-charts/*"
    }
  ]
}
Installing the Helm S3 plugin

You’re almost set now. If you’ve haven’t already, install Helm using the instructions in the quick start guide.

The final prerequisite is the Helm S3 plugin. This acts as an intermediary between Helm and your S3 bucket. It’s not the only way to create a custom repository, but it simplifies a lot of things.

You can install the plugin from the GitHub repo by running:

$ helm plugin install https://github.com/hypnoglow/helm-s3.git
Downloading and installing helm-s3 v0.5.2 ...  
Installed plugin: s3  

This downloads the latest version of the plugin from GitHub, and registers it with Helm.

Creating your Helm chart repository

You’re finally ready to start playing with charts properly!

The first thing to do is to turn the my-helm-charts bucket into a valid chart repository. This requires adding an index.yaml to it. The Helm S3 plugin has a helper method to do that for you, which generates a valid index.yaml and uploads it to your S3 bucket:

$ helm S3 init s3://my-helm-charts/charts
Initialized empty repository at s3://my-helm-charts/charts  

If you fetch the contents of the bucket now, you’ll find an index.yaml file under the /charts key

Initialised project in the repo

Note, the /charts prefix is entirely optional. If you omit the prefix, the Helm chart repository will be in the root of the bucket. I just included it for demonstration purposes here.

The contents of the index.yaml file is very basic at the moment:

apiVersion: v1  
entries: {}  
generated: 2018-02-10T15:27:15.948188154-08:00  

To work with the chart repository by name instead of needing the whole URL, you can add an alias. For example, to create a my-charts alias:

$ helm repo add my-charts s3://my-helm-charts/charts
"my-charts" has been added to your repositories

If you run helm repo list now, you’ll see your repo listed (along with the standard stable and local repos:

$ helm repo list
NAME            URL  
stable          https://kubernetes-charts.storage.googleapis.com  
local           http://127.0.0.1:8879/charts  
my-charts       s3://my-helm-charts/charts  

You now have a functioning chart repository, but it doesn’t have any charts yet! In the next section I’ll show how to push charts to, and install charts from, your S3 repository.

Uploading a chart to the repository

Before you can push a chart to the repository, you need to create one. If you already have one, you could use that, or you could copy one of the standard charts from the stable repository. For the sake of completion, I’ll create a basic chart, and use that for the rest of the post.

Creating a simple test Helm chart

I used the example from the Helm docs for this test, which creates one of the simplest templates, a ConfigMap, and adds it at the path test-chart/templates/configmap.yaml:

$ helm create test-chart
Creating test-chart  
# Remove the initial cruft
$ rm -rf test-chart/templates/*.*
# Create a ConfigMap template at test-chart/templates/configmap.yaml
$ cat >test-chart/templates/configmap.yaml <<EOL
apiVersion: v1  
kind: ConfigMap  
metadata:  
  name: test-chart-configmap
data:  
  myvalue: "Hello World"
EOL

You can install this chart into your kubernetes cluster using:

$ helm install ./test-chart
NAME:   zeroed-armadillo  
LAST DEPLOYED: Fri Feb  9 17:10:38 2018  
NAMESPACE: default  
STATUS: DEPLOYED

RESOURCES:  
==> v1/ConfigMap
NAME               DATA  AGE  
test-chart-configmap  1     0s  

and remove it again completely using the release name presented when you installed it (zeroed-armadillo) :

# --purge removes the release from the "store" completely
$ helm delete --purge zeroed-armadillo
release "zeroed-armadillo" deleted  

Now you have a chart to work with it’s time to push it to your repository.

Uploading the test chart to the chart repository

To push the test chart to your repository you must first package it. This takes all the files in your ./test-chart repository and bundles them into a single .tgz file:

$ helm package ./test-chart
Successfully packaged chart and saved it to: ~/test-chart-0.1.0.tgz  

Once the file is packaged, you can push it to your repository using the S3 plugin, by specifying the packaged file name, and the my-charts alias you specified earlier.

$ helm s3 push ./test-chart-0.1.0.tgz my-charts

Note that without the plugin you would normally have to “manually” sync your local and remote repos, merging the remote repository with your locally added charts. The S3 plugin handles all that for you.

If you check your S3 bucket after pushing the chart, you’ll see that the tgz file has been uploaded:

Chart in repository

That’s it, you’ve pushed a chart to an S3 repository!

Searching and installing from the repository If you do a search for a test chart using helm search you can see your chart listed:

$ helm search test-chart
NAME                    CHART VERSION   APP VERSION     DESCRIPTION  
my-charts/test-chart    0.1.0           1.0             A Helm chart for Kubernetes  

You can fetch and/or unpack the chart locally using helm fetch my-charts/test-chart or you can jump straight to installing it using:

$ helm install my-charts/test-chart
NAME:   rafting-crab  
LAST DEPLOYED: Sat Feb 10 15:53:34 2018  
NAMESPACE: default  
STATUS: DEPLOYED

RESOURCES:  
==> v1/ConfigMap
NAME               DATA  AGE  
mychart-configmap  1     0s  

To remove the test chart from the repository, you provide the chart name and version you wish to delete:

$ helm s3 delete test-chart --version 0.1.0 my-charts