Installing Shipper

Step 0: procure a cluster

The rest of this document assumes that you have access to a Kubernetes cluster and admin privileges on it. If you don’t have this, check out docker desktop, kind, microk8s or minikube. Cloud clusters like GKE are also fine. Shipper requires Kubernetes 1.17 or later, and you’ll need to be an admin on the cluster you’re working with. [1]

Make sure that kubectl works and can connect to your cluster before continuing.

Setting up kind clusters

How to set-up an application kind cluster and a management kind cluster:
We would like to setup two clusters, mgmt and app.

Lets write a kind.yaml manifest to configure our clusters:

:caption: kind.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane

Now we’ll use this to create the clusters:

$ kind create cluster --name app --config kind.yaml --image kindest/node:v1.15.7
$ kind create cluster --name mgmt --config kind.yaml --image kindest/node:v1.15.7

Congratulations, you have created your clusters!

Step 1: get shipperctl

shipperctl automates setting up clusters for Shipper. Grab the tarball for your operating system, extract it, and stick it in your PATH somewhere.

You can find the binaries on the GitHub Releases page for Shipper.

Step 2: write a cluster manifest

shipperctl expects a manifest of clusters to configure. It uses your ~/.kube/config to translate context names into cluster API server URLs. Find out the name of your context like so:

$ kubectl config get-contexts
CURRENT   NAME              CLUSTER         AUTHINFO            NAMESPACE
          kind-app          kind-app        kind-app
*         kind-mgmt         kind-mgmt       kind-mgmt

In my setup, the context name of the application cluster is kind-app.

This configuration will allow management cluster to communicate with application cluster. The cluster API server URL stored in the kubeconfig is a local address (127.0.0.1), we need an actual ip address for our kind-app cluster. This is how you can get it:

$ kind get kubeconfig --name app --internal | grep server

Note that app is the name we gave to kind when creating the application cluster. Copy the URL of the server.

Now let’s write a clusters.yaml manifest to configure Shipper here:

:caption: clusters.yaml

applicationClusters:
- name: kind-app
  region: local
  apiMaster: "SERVER_URL"

Paste your server URL as a string.

Step 3: Setup the Management Cluster

Before you run shipperctl, make sure that your kubectl context is set to the management cluster:

$ kubectl config get-contexts
CURRENT   NAME          CLUSTER                  AUTHINFO            NAMESPACE
          kind-app      kind-app                 kind-app
*         kind-mgmt     kind-mgmt                kind-mgmt

First we’ll setup all the needed resources in the management cluster:

    $ shipperctl clusters setup management -n shipper-system
    Setting up management cluster:
    Registering or updating custom resource definitions... done
Creating a namespace called shipper-system... already exists. Skipping
Creating a namespace called rollout-blocks-global... already exists. Skipping
Creating a service account called shipper-management-cluster... already exists. Skipping
Creating a ClusterRole called shipper:management-cluster... already exists. Skipping
Creating a ClusterRoleBinding called shipper:management-cluster... already exists. Skipping
Checking if a secret already exists for the validating webhook in the shipper-system namespace... yes. Skipping
Creating the ValidatingWebhookConfiguration in shipper-system namespace... done
Creating a Service object for the validating webhook... done
Finished setting up management cluster

Step 4: deploy shipper

Now that we have the namespace, custom resource definitions, role bindings, service accounts, and so on, let’s create the Shipper Deployment:

$ kubectl --context kind-mgmt create -f https://github.com/bookingcom/shipper/releases/latest/download/shipper.deployment.yaml
deployment.apps/shipper created

This will create an instance of Shipper in the shipper-system namespace.

Step 5: Join the Application cluster to the Management cluster

Now we’ll give clusters.yaml to shipperctl to configure the cluster for Shipper:

$ shipperctl clusters join -f clusters.yaml -n shipper-system
Creating application cluster accounts in cluster kind-app:
Creating a namespace called shipper-system... already exists. Skipping
Creating a service account called shipper-application-cluster... already exists. Skipping
Creating a ClusterRoleBinding called shipper:application-cluster... already exists. Skipping
Finished creating application cluster accounts in cluster kind-app

Joining management cluster to application cluster kind-app:
Creating or updating the cluster object for cluster kind-app on the management cluster... done
Checking whether a secret for the kind-app cluster exists in the shipper-system namespace... yes. Skipping
Finished joining management cluster to application cluster kind-app

Step 6: do a rollout!

Now you should have a working Shipper installation. Let’s roll something out!

Namespace manager

By design, Shipper does not create namespaces in the application cluster. Shipper requires the existence of a namespace in the application cluster with the same name as the namespace in management cluster where the Application objects is installed. In case the namespace does not exist in the application cluster, and this application cluster is selected for a Release, Shipper will continue to try and install the charts, and fail. This loop will end only when the namespace is created in the application cluster, or this application cluster is not selected anymore (by deleting the Release or Application objects).

To help with this, we recommend having some sort of a namespace manager tool. This can be a simple controller that installs a namespace in all the application clusters for each namespace existing in the management cluster, or a more complex tool, depending on your needs.

Footnotes

[1]For example, on GKE you need to bind yourself to cluster-admin before shipperctl will work.