TL;DR: Homebrew for Kubernetes, with packages called "Charts"
This document outlines the architecture for a Kubernetes package management tool.
Our work suggests that great benefits could accrue if the community shares (and iterates on) a set of "best practices" Kubernetes packages. Examples of this might be:
- A Postgres database
- A cluster of Memcached servers
- A Varnish caching proxy
By providing common service definitions, lifecycle handling, health checking, and configuration, a Kubernetes package can serve the purposes of many Kubernetes users, and serve as a foundation for many other users.
For our purposes, a "workload" is any pre-packaged set of manifest files that can be deployed into Kubernetes, and that implement a particular functional unit of service (e.g. a web application, a database, or a message queue).
When it comes to deploying a workload into Kubernetes there are always one or more Kubernetes manifest files. Often, these files (particularly pod and replication controller manifests) will reference one or more container images. These are typically pulled from external registries like GCR, Quay.io, and Docker Hub.
A Kubernetes package is thus:
- A collection of one or more Kubernetes manifest files...
- That can be installed together...
- Together with descriptive metadata...
In this document, we refer to a Kubernetes package as a Chart. The package format is discussed later in the document.
Right now, the Kubernetes community largely hand-crafts their manifest files. There is no accepted distribution schema, and the only commonly referenced set of files are the ones in the core Kubernetes GitHub repository, which are examples.
The Helm Classic project will provide a GitHub repository to store and collaborate on Charts. Users will fetch information about available packages from this archive. Charts in the archive will be usable as-is, but will also serve as a basis for customization.
This section describes a few different workflows for Helm Classic users.
Use case: User is looking for a redis cluster. User wants it immediately installed on Kubernetes.
$ helmc update
---> Cloning into '$HOME/.helmc/cache/charts'...
---> Updating cache from https://github.com/helm/charts
---> Done
$ helmc search redis
---> redis-cluster (redis-cluster 0.0.5) - Highly available Redis cluster with multiple sentinels and standbys.
---> redis-standalone (redis-standalone 0.0.1) - Standalone Redis Master
$ helmc info redis-cluster
Name: redis-cluster
Home: http://github.com/deis/redis-cluster
Version: 0.0.5
Description: Highly available Redis cluster with multiple sentinels and standbys.
Details: This package provides a highly available Redis cluster with multiple sentinels and standbys. Note the `redis-master` pod is used for bootstrapping only and can be deleted once the cluster is up and running.
$ helmc install redis-cluster
---> No chart named "redis-cluster" in your workspace. Fetching now.
---> Fetched chart into workspace $HOME/.helmc/workspace/charts/redis-cluster
---> Running `kubectl create -f` ...
services/redis-sentinel
pods/redis-master
replicationcontrollers/redis
replicationcontrollers/redis-sentinel
---> Done
Use Case: User wants to get an NGINX chart, modify it, and then install the modified version into a running Kubernetes cluster.
$ helmc update
---> Updating cache from https://github.com/helm/charts
---> Done
$ helmc fetch redis-standalone redis
---> Fetched chart into workspace $HOME/.helmc/workspace/charts/redis
---> Done
$ helmc edit redis
$ helmc install redis
---> Running `kubectl create -f` ...
replicationcontrollers/redis-standalone
---> Done
This section describes the design of the Helm Classic package repository.
The goals for designing an archive backend are as follows:
- Supports authentication and authorization
- Provides simple methods for storing, retrieving, searching, and browsing
- Intuitive to a software developer
- Highly available
- Understandable API
- Provides workflow for submitting, reviewing, and filing bugs
In this model, the only backend is a single GitHub repository. This repository contains all supported charts inside individual directories.
(root)
|
|- charts/
|
|- mychart/
|
|- postgres/
|
|- ...
The API to this service is essentially the git protocol.
Contributing packages to the archive is done by submitting GitHub Pull Requests.
The helmc
command line client is the primary way that users interact with the Helm repository. The client is used for getting and installing packages.
The command line will support (at least) the following commands:
list
: List currently installed Chartssearch PATTERN
: Search the available Charts, list those that match thePATTERN
fetch CHART [NAME]
: Retrieve the Chart and put it in a local working directory, optionally with a different chart nameinstall CHART
: Fetch the Chart (if necessary) and then install it into Kubernetes, attaching to the k8s server configured for the current user viakubectl
.test CHART
: Verifies that the chart can successfully enter the "Running" state (e.g. passes initial health checks)uninstall CHART
: Uninstall the chart via the k8s server configured for the current user viakubectl
.create CHART
: Create a new chart for local editing.edit CHART
: Edit a local chart with your interactive editor.publish CHART
: Publish a chart from your workspace to your repo checkoutinfo CHART
: Print information about a Chartupdate
: Refresh local metadata about available Charts. This will re-pull the repo.help
: Print help.
The client will locally track the following three things:
- The client's own configuration
- The packages available from the remote service (a local cache)
- The packages that the client has "downloaded" into the working directory
The tree looks something like this:
- $HELMC_HOME
|
|- cache/ # Where `helmc update` data goes
|
|- workspace/ # Working directory, where `helmc fetch` copies to
|
|- config.yaml # configuration info
The default location for $HELMC_HOME
will be $HOME/.helmc
. This reflects the fact that package management by this method is scoped to the developer, not to the system. However, we will make this flexible because we have the following target use cases in mind:
- Individual Helm Classic developer/user
- CI/CD system
- Workspace shared by
git
repo among several developers - Dockerized Helm Classic that runs in a container
Clients will track minimal configuration about remote hosts, local state, and possibly security.
The initial web interface will focus exclusively on education:
- Introduction to Helm Classic
- Instructions for installing
- Instructions for package submission
In the future, we will support the following additional features:
- Package search: Search for packages and show the details
- Test results: View the test results for any package
To maintain a high bar for the submitted charts, a CI/CD service is run on each submitted project. The initial CI/CD implementation does the following:
- Runs the install script on an isolated container, and ensures that it exits with no errors
- Validates the manifest files
- Runs the package on its own in a Kubernetes cluster
- Verifies that the package can successfully enter the "Running" state (e.g. passes initial health checks)
A package will be composed of the following parts:
- A metadata file
- One or more Kubernetes manifest files, stored in a
manifests/
directory
A Chart Metadata file is a YAML-formatted file describing a package's purpose, version, and authority information. It is called Chart.yaml
.
The Chart.yaml
file contains the following information:
- name: The name of the package
- version: A SemVer 2 version number, no leading
v
- home: The URL to a relevant project page, git repo, or contact person
- description: A single line description
- details: A multi-line description
- maintainers: A list of name and URL/email address combinations for the maintainer(s)
- dependencies: A list of other services on which this depends. Dependencies contain names and version ranges. See Dependecies below.
Example:
name: ponycorn
home: http://github.com/technosophos/ponycorn
version: 1.0.3
description: The ponycorn server
maintainers:
- Matt Butcher <mbutcher@deis.com>
dependencies:
- name: nginx
version: 1.9 < x <= 1.10
details:
This package provides the ponycorn server, which requires an existing nginx
server to function correctly.
If dependencies are declared, helmc
will...
- Check to see if the named dependency is locally present
- If it is, check to see if the version is within the supplied parameters
If either check fails, helmc
will emit a warning, but will not prevent the installation. Under normal operation, it will prompt to continue. If the --force
flag is set, it will simply continue.
Example:
$ helmc install ponycorn
!!-> WARNING: Dependency nginx (1.9 < x <= 1.10) does not seem to be satisfied.
!!-> This package may not function correctly.
Continue? yes
---> Running `kubectl create -f ...
All Kubernetes manifests are stored in a manifests/
directory under each chart directory. They must be valid YAML ending with the .yaml
suffix, and they must conform to the Kubernetes definitions.
The following items have already been considered and will not be part of Version 1:
- Homebrew tap/keg system
- pre-install scripts to (for example) perform secrets generation
- post-install exec scripts (run
kubectl exec -it
on a pod)