Skip to content

Commit be79635

Browse files
committed
Update docs/admin/kubeadm.md for 1.8
- Made a couple of minor wording changes (not strictly 1.8 related). - Updated references to the default token TTL (was infinite, now 24 hours). - Added an anchor for `#kubeadm-join` since we reference that in the URL for one of the new warning messages in 1.8. - Documented the new `--discovery-token-ca-cert-hash` and `--discovery-token-unsafe-skip-ca-verification` flags for `kubeadm join`. - Added references to the new `--discovery-token-ca-cert-hash` flag in all the default examples. - Added a new _Security Model_ section that describes the security tradeoffs of the various discovery modes. - Documented the new `--groups` flag for `kubeadm token create` - Added a note of caution under _Automating kubeadm_ that references the _Security Models_ section. - Updated the component version table to drop 1.6 and add 1.8.
1 parent 6dcb9d4 commit be79635

File tree

1 file changed

+100
-22
lines changed

1 file changed

+100
-22
lines changed

docs/admin/kubeadm.md

Lines changed: 100 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ following steps:
2727
dropping it in the cert directory (configured via `--cert-dir`, by default
2828
`/etc/kubernetes/pki`), this step is skipped.
2929

30-
1. Outputting a kubeconfig file for the kubelet to use to connect to the API
30+
1. kubeadm outputs a kubeconfig file for the kubelet to use to connect to the API
3131
server, as well as an additional kubeconfig file for administration.
3232

3333
1. kubeadm generates Kubernetes static Pod manifests for the API server,
@@ -46,8 +46,9 @@ following steps:
4646
Running `kubeadm join` on each node in the cluster consists of the following
4747
steps:
4848

49-
1. kubeadm downloads root CA information from the API server. It uses the token
50-
to verify the authenticity of that data.
49+
1. kubeadm downloads root CA information from the API server. By default, it
50+
uses the bootstrap token and the CA key hash to verify the authenticity of
51+
that data. The root CA can also be discovered directly via a file or URL.
5152

5253
1. kubeadm creates a local key pair. It prepares a certificate signing request
5354
(CSR) and sends that off to the API server for signing. The bootstrap token
@@ -185,24 +186,30 @@ managing tokens](#manage-tokens) below.
185186

186187
This sets an expiration time for the token. This is specified as a duration
187188
from the current time. After this time the token will no longer be valid and
188-
will be removed. A value of 0 specifies that the token never expires. 0 is the
189-
default. See the [section on managing tokens](#manage-tokens) below.
189+
will be removed. A value of 0 specifies that the token never expires. The
190+
default is 24 hours. See the [section on managing tokens](#manage-tokens) below.
190191

191-
### `kubeadm join`
192+
### `kubeadm join` {#kubeadm-join}
192193

193194
When joining a kubeadm initialized cluster, we need to establish bidirectional
194195
trust. This is split into discovery (having the Node trust the Kubernetes
195196
master) and TLS bootstrap (having the Kubernetes master trust the Node).
196197

197198
There are 2 main schemes for discovery. The first is to use a shared token along
198-
with the IP address of the API server. The second is to provide a file (a subset
199-
of the standard kubeconfig file). This file can be a local file or downloaded
200-
via an HTTPS URL. The forms are `kubeadm join --discovery-token
201-
abcdef.1234567890abcdef 1.2.3.4:6443`, `kubeadm join --discovery-file
202-
path/to/file.conf` or `kubeadm join --discovery-file https://url/file.conf`.
199+
with the IP address of the API server and a hash of the root CA key. The second
200+
is to provide a file (a subset of the standard kubeconfig file). This file can
201+
be a local file or downloaded via an HTTPS URL. The forms are:
202+
203+
- `kubeadm join --discovery-token abcdef.1234567890abcdef --discovery-token-ca-cert-hash sha256:1234..cdef 1.2.3.4:6443`
204+
205+
- `kubeadm join --discovery-file path/to/file.conf`
206+
207+
- `kubeadm join --discovery-file https://url/file.conf`
208+
203209
Only one form can be used. If the discovery information is loaded from a URL,
204210
HTTPS must be used and the host installed CA bundle is used to verify the
205-
connection.
211+
connection. For details on the security tradeoffs of these mechanisms, see the
212+
[security-model](#security-model) section below.
206213

207214
The TLS bootstrap mechanism is also driven via a shared token. This is used to
208215
temporarily authenticate with the Kubernetes master to submit a certificate
@@ -216,7 +223,7 @@ can be used instead of specifying the each token individually.
216223

217224
Here's an example on how to use it:
218225

219-
`kubeadm join --token=abcdef.1234567890abcdef 192.168.1.1:6443`
226+
`kubeadm join --token=abcdef.1234567890abcdef --discovery-token-ca-cert-hash sha256:1234..cdef 192.168.1.1:6443`
220227

221228
Specific options:
222229

@@ -260,6 +267,28 @@ unnamed argument) to download and verify information about the cluster. The
260267
most critical part of the cluster information is the root CA bundle used to
261268
verify the identity of the server during subsequent TLS connections.
262269

270+
- `--discovery-token-ca-cert-hash`
271+
272+
The CA key hash is used to verify the full root CA certificate discovered during
273+
token-based bootstrapping. It has the format `sha256:<hex_encoded_hash>`. By
274+
default, the hash value is returned in the `kubeadm join` command printed at the
275+
end of `kubeadm init`. It is in a standard format (see
276+
[RFC7469](https://tools.ietf.org/html/rfc7469#section-2.4)) and can also be
277+
calculated out of band by 3rd party tools or orchestration systems. For example, in OpenSSL:
278+
`openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>&/dev/null | openssl dgst -sha256 -hex`
279+
280+
Skipping this flag is allowed in Kubernetes 1.8, but makes certain spoofing
281+
attacks possible. See the [security model](#security-model) for details.
282+
Pass `--discovery-token-unsafe-skip-ca-verification` to silence warnings (which
283+
will become errors in Kubernetes 1.9).
284+
285+
- `--discovery-token-unsafe-skip-ca-verification`
286+
287+
Disable the warning/error when `--discovery-token-ca-cert-hash` is not provided.
288+
Passing this flag is an acknowledgement of the
289+
[security tradeoffs](#security-model) involved in skipping this verification
290+
(which may or may not be appropriate in your environment).
291+
263292
- `--tls-bootstrap-token`
264293

265294
The token used to authenticate to the API server for the purposes of TLS
@@ -419,9 +448,15 @@ commands.
419448
* `kubeadm token create` Creates a new token.
420449
* `--description` Set the description on the new token.
421450
* `--ttl duration` Set expiration time of the token as a delta from "now".
422-
Default is 0 for no expiration. The unit of the duration is seconds.
451+
Default is 24 hours. A value of 0 means "never expire". The default unit
452+
of the duration is seconds but other units can be specified (e.g., `15m`, `1h`).
423453
* `--usages` Set the ways that the token can be used. The default is
424454
`signing,authentication`. These are the usages as described above.
455+
* `--groups` add extra bootstrap groups as which this token will
456+
authenticate. Can be specified multiple times. Each extra group must start
457+
with `system:bootstrappers:`. This is an advanced feature meant for custom
458+
bootstrap scenarios where you want to change how CSR approval works for
459+
different groups of nodes.
425460
* `kubeadm token delete <token id>|<token id>.<token secret>` Delete a token.
426461
The token can either be identified with just an ID or with the entire token
427462
value. Only the ID is used; the token is still deleted if the secret does not
@@ -460,6 +495,49 @@ started.
460495
Once the cluster is up, you can grab the admin credentials from the master node
461496
at `/etc/kubernetes/admin.conf` and use that to talk to the cluster.
462497

498+
Note that this style of bootstrap has some relaxed security guarantees because
499+
it does not allow the root CA hash to be validated with
500+
`--discovery-token-ca-cert-hash` (since it's not generated when the nodes are
501+
provisioned). For details, see the [security model](#security-model)
502+
503+
## Security model {#security-model}
504+
The kubeadm discovery system has several options, each with security tradeoffs.
505+
The right method for your environment depends on how you provision nodes and the
506+
security expectations you have about your network and node lifecycles.
507+
508+
### Token-based discovery with CA pinning
509+
This is the default mode in Kubernetes 1.8. It allows bootstrapping nodes to
510+
securely discover a root of trust for the master even if other worker nodes or
511+
the network are compromised. It's also convenient to execute manually since all
512+
of the information required fits into a single `kubeadm join` command that is
513+
easy to copy and paste. The downside of this method is that the CA hash is not
514+
normally known until the master has been provisioned, which can make it more
515+
difficult to build automated provisioning tools that use kubeadm.
516+
517+
### Token-based discovery without CA pinning
518+
This was the default in Kubernetes 1.7 and earlier, but comes with some
519+
important weaknesses to consider. It's still possible in Kubernetes 1.8 and above
520+
using the `--discovery-token-unsafe-skip-ca-verification` flag. The main
521+
advantage of this mode is that the token can be generated ahead of time and
522+
shared with the master and worker nodes, which can then bootstrap in parallel
523+
without coordination. This allows it to be used in many provisioning scenarios.
524+
525+
This mode still prevents many network-level attacks. However, if an attacker is
526+
able to steal a bootstrap token via some vulnerability, they can use that token
527+
(along with network-level access) to impersonate the master to other
528+
bootstrapping nodes. This may or may not be an appropriate tradeoff in your
529+
environment. Consider using one of the other modes if possible.
530+
531+
### File or HTTPS-based discovery
532+
This provides an out-of-band way to establish a root of trust between the master
533+
and bootstrapping nodes. It requires that you have some way to carry the
534+
discovery information from the master to the bootstrapping nodes. This might be
535+
possible, for example, via your cloud provider or provisioning tool. The
536+
information in this file is not secret, but HTTPS is required to ensure its
537+
integrity. Consider using this mode if you are building automated provisioning
538+
using kubeadm. This mode is less convenient to use manually since the file is
539+
difficult to copy and paste between nodes.
540+
463541
## Use Kubeadm with other CRI runtimes
464542

465543
Since [Kubernetes 1.6 release](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md#node-components-1), Kubernetes container runtimes have been transferred to using CRI by default. Currently, the build-in container runtime is Docker which is enabled by build-in `dockershim` in `kubelet`.
@@ -492,17 +570,17 @@ the following images are required for the cluster works will be automatically
492570
pulled by the kubelet if they don't exist locally while `kubeadm init` is initializing
493571
your master:
494572

495-
| Image Name | v1.6 release branch version | v1.7 release branch version
573+
| Image Name | v1.7 release branch version | v1.8 release branch version
496574
|---|---|---|
497-
| gcr.io/google_containers/kube-apiserver-${ARCH} | v1.6.x | v1.7.x
498-
| gcr.io/google_containers/kube-controller-manager-${ARCH} | v1.6.x | v1.7.x
499-
| gcr.io/google_containers/kube-scheduler-${ARCH} | v1.6.x | v1.7.x
500-
| gcr.io/google_containers/kube-proxy-${ARCH} | v1.6.x | v1.7.x
575+
| gcr.io/google_containers/kube-apiserver-${ARCH} | v1.7.x | v1.8.x
576+
| gcr.io/google_containers/kube-controller-manager-${ARCH} | v1.7.x | v1.8.x
577+
| gcr.io/google_containers/kube-scheduler-${ARCH} | v1.7.x | v1.8.x
578+
| gcr.io/google_containers/kube-proxy-${ARCH} | v1.7.x | v1.8.x
501579
| gcr.io/google_containers/etcd-${ARCH} | 3.0.17 | 3.0.17
502580
| gcr.io/google_containers/pause-${ARCH} | 3.0 | 3.0
503-
| gcr.io/google_containers/k8s-dns-sidecar-${ARCH} | 1.14.1 | 1.14.4
504-
| gcr.io/google_containers/k8s-dns-kube-dns-${ARCH} | 1.14.1 | 1.14.4
505-
| gcr.io/google_containers/k8s-dns-dnsmasq-nanny-${ARCH} | 1.14.1 | 1.14.4
581+
| gcr.io/google_containers/k8s-dns-sidecar-${ARCH} | 1.14.4 | 1.14.4
582+
| gcr.io/google_containers/k8s-dns-kube-dns-${ARCH} | 1.14.4 | 1.14.4
583+
| gcr.io/google_containers/k8s-dns-dnsmasq-nanny-${ARCH} | 1.14.4 | 1.14.4
506584

507585
Here `v1.7.x` means the "latest patch release of the v1.7 branch".
508586

0 commit comments

Comments
 (0)