Browse files

RFC: Introduce shipperctl command line utility (#29)

* rfcs: add shipperctl admin rfc

* Changed the RFC to follow our latest discussions.

* Made tiny fixes.

* shipperctl admin rfc: add k8s envelope to cluster manifest
  • Loading branch information...
isutton authored and kanatohodets committed Nov 1, 2018
1 parent 1db584e commit a62dd9a9dad8d55a6227605f3e58b3d2c872d0e0
Showing with 100 additions and 0 deletions.
  1. +100 −0 rfcs/999-shipperctl-admin.adoc
@@ -0,0 +1,100 @@
= 999 Introduce _shipperctl_ command line utility
Parham Doustdar <>
:RFC-Status: Draft

== Abstract

Now that we're working to simplify setup, administration, and scripting, I think it makes sense to re-open the discussion around a _shipperctl_ CLI for Shipper. The most valuable functionality we can get out of such a tool now is *simplifying Shipper's setup*, so this RFC will focus only on the `+shipperctl admin clusters apply`+ command.

== Motivation

The current process of configuring a Shipper installation for production is quite complicated and error prone: Shipper CRDs, service accounts, role bindings, and cluster secrets must be created, only to name a few of the actions required to properly set it up.

Having a complicated process also complicates other parts of our project, specifically Shipper documentation and quick-start guides. In addition to documentation and guides, it also makes it very difficult for third parties interested in Shipper to properly evaluate it. The team strongly believes that having a simple administration tool that performs the majority of those error prone and complicated procedures will increase the chances of such third parties to consider and use Shipper in their environments.

== Reference level explanation

`+shipperctl admin clusters apply`+ performs a bulk operation setting up all clusters contained in a Shipper cluster configuration file. This file contains all clusters to be configured for Shipper operation, for both Management and Application clusters. It is structed like a Kubernetes object because that's a handy set of primitives (for dealing with compatibility, for example), but it is not an object which lives in a cluster. Potentially in the future this might be consumed by an operator.

.Cluster configuration file example
kind: ClusterManifest
name: production
- name: eu-management # <1>
- name: us-management
context: gke-us-management # <2>
- name: eu-application # <1>
region: eu-west1
zone: a
- gdpr
- ipv4
- kubernetes1.12
- name: us-application
context: gke-us-application # <2>
region: us-west1
zone: a
- ipv4
- ssd-local-disk
<1> Without the `context` field present, `name` is considered a valid and existing _kubectl_ context, and will be used both to gather connection details to perform relevant operations on the cluster to set up Shipper and to name cluster specific manifests in the Management Cluster.
<2> With the `context` field present, the `name` value is used only to name cluster specific manifests in the Management Cluster. Connection details are gathered using the specified `context` value.

.*shipperctl admin clusters apply* arguments

|`-f, --file`
| Shipper cluster configuration file to be applied

| Print out what actions it would do, according to the given cluster configuration file

|`-n, --namespace`
| Shipper system namespace to be created in all clusters

| Same as _kubectl_


There are two use cases for this command:

* One use case is to set up a collection of management and application clusters for the first time. In this case, all of the operations required to set up a management/application cluster are done.
* The second use case is to update the Cluster objects, or to re-do any of the steps that are necessary to add this cluster. For example, if a service account is already set up for Shipper, this command will skip that step. This makes this command idempotent, and allows it to be used for git-ops or any sort of pipeline.

This command should do the following steps for each cluster:

=== Set Up the Management Cluster

* Create the Namespace based on the `namespace` argument on the management cluster
* Register CRDs on the management cluster
* Create a service account called `shipper` in the Shipper namespace on the management cluster
* Create a ClusterRole called `shipper-admin` to manage Shipper resources on the management cluster
* Create a ClusterRoleBinding to bind the shipper service account to the shipper-admin role on the management cluster
* Create a Role called `secret-reader` in the Shipper namespace that gives permission to read secrets on the management cluster
* Create a RoleBinding to bind the Shipper service account to the `secret-reader` role

=== Set Up the Application Cluster

* Create the Namespace based on the `namespace` argument on the application cluster
* Create a service account called `shipper` in the namespace on the application cluster
* Create a ClusterRoleBinding to bind the Shipper service account to the `cluster-admin` ClusterRole on the application cluster

=== Connect the Clusters Together

* Create the cluster Secret on the management cluster
** The name of the Secret is the `name` of the cluster in the configuration
** The `namespace` is the Shipper namespace passed as the `shipperctl clusters apply` argument
** The Secret type is `opaque`
** Create a checksum and store it in an annotation on the Secret called ``
** The rest of the fields should be copied from the service account secret in the application cluster, typically called `shipper-token-<hash>`.
* Create a Cluster named the `name` in the configuration on the management cluster, and copy the rest of the cluster fields verbatim into it

0 comments on commit a62dd9a

Please sign in to comment.