With Kubernetes 1.4 sig-cluster-lifecycle released an alpha of kubeadm, a new utility we’ve been working on to make cluster bootstrapping as simple as possible for new users, but also provide tooling and infrastructure that can be used for production clusters.

The initial goal was simple, install the bits (now delivered via new OS packages), one command to create a cluster:

$ kubeadm init

And one very short command to copy and paste to join nodes to the cluster:

$ kubeadm join --token f0c861.753c505740ecde4c

This has been quite popular with users, and while we’re still very much an alpha feature there are a couple security trade-offs involved that are probably worth understanding before kubeadm hits beta/GA.

Discovery Service

In the above example you will notice at no point did we create a CA or copy any files around, an explicit goal of the sig for our alpha. This is great for anyone looking to just get Kubernetes up and running as quickly as possible. It is debatable whether or not this is a good idea for production clusters.

Discovery today is provided by the kube-discovery pod you will see running after initializing your masters. The IP specified when joining nodes identifies the location of this discovery service, and the token is used to provide some level of trust that the node is getting valid information from the server. The bootstrap token consists of two parts, an ID to help identify what token we are using, and a shared secret used for JWS signature verification. This secret is not sent over the wire during bootstrapping, the server uses the token ID to load the correct secret and then signs a JWS payload sent back to the client. This payload contains the list of API servers, and the CA certificate to communicate with them.

This token based discovery is the first trade-off, arguably this is less secure than distributing your CA out of band or baked into your OS/images. Use of the JWS bootstrap token provides some level of trust, but critically anyone in posession of the shared secret could technically impersonate the server and distribute bad API endpoints and CA. (we will however be implementing expiration on bootstrap tokens for beta, which will narrow the window for abuse)

For beta we also plan to offer a flat file and https alternative to grabbing the cluster information (soon to be transmitted as a kubeconfig). These would provide better options for production grade clusters who want control of trust distribution, but still would like to use kubeadm. It hasn’t been discussed in the sig yet, but we may also want ways to explicitly remove the CA from this payload server side and have kubeadm gracefully skip this step, for environments which already distribute their own CA out of band.

NOTE: For beta and GA, it looks as though the discovery service as a separate pod will be going away, replaced by re-use of internal Kubernetes config maps and secrets, with related controllers to maintain them. However the core functionality of requesting cluster info and verifying it’s authenticity with JWS and a shared secret will remain.

TLS Bootstrapping

TLS Bootstrapping is an experimental API also introduced in 1.4 which allows nodes to request certificates from the cluster CA. In kubeadm we leverage this to get the node it’s final identity and allow it to actually join the cluster.

In the kubeadm alpha there are are a couple trade-offs in play with this. The TLS bootstrap API is intended to be protected via an initial authentication token (NOTE: not the same as the bootstrap token above, which is not yet used for any kind of authentication), which only provides the caller with sufficient rights to submit a CSR request to the API. As far as I know this is not currently in use in our configuration.

More importantly, CSR requests are configured to automatically be accepted today, rather than requiring manual approval.

Correcting both of these would be recommended for production grade clusters. At present we plan to re-use the above bootstrap token to authenticate to the TLS bootstrap API. I don’t believe we’ve discussed when/how to enable the manual signing of CSRs, but based on past discussions this will most likely become the default behaviour, with an additional option when initializing your master to disable it and clearly demonstrate intent to accept this security trade-off.


Kubeadm has been quite well received due to just how quick and easy it is to get a functional cluster up and running, however there definitely are trade-offs involved that are important to understand. We need to keep these in mind when working towards GA so they are either improved, or made optional, and users are clearly informed when they’re opting into a less than secure configuration.

Kubeadm development happens 100% in the open, if you’d like to join in come find us in the sig-cluster-lifecycle slack, mailing list, or join in on the weekly Zoom meeting.