Skip to content

Commit d174742

Browse files
committed
kubeadm: add section on how to use the "generate-csr" command
The "generate-csr" command is useful in cases users don't wish to use the default certificate duration that kubeadm has hardcoded to 1 year. The command can also be used when the certificate rotation process is done manually, out of bounds with an external CA.
1 parent 726ad9f commit d174742

File tree

2 files changed

+250
-22
lines changed

2 files changed

+250
-22
lines changed

content/en/docs/reference/setup-tools/kubeadm/kubeadm-certs.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ For more details see
6060
## kubeadm certs generate-csr {#cmd-certs-generate-csr}
6161

6262
This command can be used to generate keys and CSRs for all control-plane certificates and kubeconfig files.
63-
The user can then sign the CSRs with a CA of their choice.
63+
The user can then sign the CSRs with a CA of their choice. To read more information
64+
on how to use the command see
65+
[Signing certificate signing requests (CSR) generated by kubeadm](/docs/tasks/administer-cluster/kubeadm/kubeadm-certs#signing-csr).
6466

6567
{{< tabs name="tab-certs-generate-csr" >}}
6668
{{< tab name="generate-csr" include="generated/kubeadm_certs_generate-csr.md" />}}

content/en/docs/tasks/administer-cluster/kubeadm/kubeadm-certs.md

Lines changed: 247 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -225,28 +225,11 @@ A CSR represents a request to a CA for a signed certificate for a client.
225225
In kubeadm terms, any certificate that would normally be signed by an on-disk CA can be produced
226226
as a CSR instead. A CA, however, cannot be produced as a CSR.
227227

228-
### Create certificate signing requests (CSR)
229-
230-
You can create certificate signing requests with `kubeadm certs renew --csr-only`.
231-
232-
Both the CSR and the accompanying private key are given in the output.
233-
You can pass in a directory with `--csr-dir` to output the CSRs to the specified location.
234-
If `--csr-dir` is not specified, the default certificate directory (`/etc/kubernetes/pki`) is used.
235-
236-
Certificates can be renewed with `kubeadm certs renew --csr-only`.
237-
As with `kubeadm init`, an output directory can be specified with the `--csr-dir` flag.
238-
239-
A CSR contains a certificate's name, domains, and IPs, but it does not specify usages.
240-
It is the responsibility of the CA to specify [the correct cert usages](/docs/setup/best-practices/certificates/#all-certificates)
241-
when issuing a certificate.
228+
### Renewal by using certificate signing requests (CSR)
242229

243-
* In `openssl` this is done with the
244-
[`openssl ca` command](https://superuser.com/questions/738612/openssl-ca-keyusage-extension).
245-
* In `cfssl` you specify
246-
[usages in the config file](https://github.com/cloudflare/cfssl/blob/master/doc/cmd/cfssl.txt#L170).
247-
248-
After a certificate is signed using your preferred method, the certificate and the private key
249-
must be copied to the PKI directory (by default `/etc/kubernetes/pki`).
230+
Renewal of ceritficates is possible by generating new CSRs and signing them with the external CA.
231+
For more details about working with CSRs generated by kubeadm see the section
232+
[Signing certificate signing requests (CSR) generated by kubeadm](#signing-csr).
250233

251234
## Certificate authority (CA) rotation {#certificate-authority-rotation}
252235

@@ -373,3 +356,246 @@ The following example will generate a kubeconfig file with administrator credent
373356
```shell
374357
kubeadm kubeconfig user --config example.yaml --client-name admin --validity-period 168h
375358
```
359+
360+
## Signing certificate signing requests (CSR) generated by kubeadm {#signing-csr}
361+
362+
You can create certificate signing requests with `kubeadm certs generate-csr`.
363+
Calling this command will generate `.csr` / `.key` file pairs for regular
364+
certificates. For certificates embedded in kubeconfig files, the command will
365+
generate a `.csr` / `.conf` pair where the key is already embedded in the `.conf` file.
366+
367+
A CSR file contains all relevant information for a CA to sign a certificate.
368+
kubeadm uses a
369+
[well defined specification](/docs/setup/best-practices/certificates/#all-certificates)
370+
for all its certificates and CSRs.
371+
372+
The default certificate directory is `/etc/kubernetes/pki`, while the default
373+
directory for kubeconfig files is `/etc/kubernetes`. These defaults can be
374+
overridden with the flags `--cert-dir` and `--kubeconfig-dir`, respectively.
375+
376+
To pass custom options to `kubeadm certs generate-csr` use the `--config` flag,
377+
which accepts a [kubeadm configuration](/docs/reference/config-api/kubeadm-config.v1beta3/)
378+
file, similarly to commands such as `kubeadm init`. Any specification such
379+
as extra SANs and custom IP addresses must be stored in the same configuration
380+
file and used for all relevant kubeadm commands by passing it as `--config`.
381+
382+
{{< note >}}
383+
This guide will cover the usage of the `openssl` command for singing the CSRs,
384+
but you can use your preferred tools.
385+
{{< /note >}}
386+
387+
{{< note >}}
388+
This guide will use the default Kubernetes directory `/etc/kubernetes`, which requires
389+
a super user. If you are following this guide with permissive directories
390+
(by passing `--cert-dir` and `--kubeconfig-dir`) you can omit the `sudo` command).
391+
But note that the resulted files must be copied to the `/etc/kubernetes` tree,
392+
so that `kubeadm init` or `kubeadm join` will find them.
393+
{{< /note >}}
394+
395+
### Preparing CA and service account files
396+
397+
On the primary control plane node, where `kubeadm init` will be executed, call the following
398+
commands:
399+
400+
```shell
401+
sudo kubeadm init phase certs ca
402+
sudo kubeadm init phase certs etcd-ca
403+
sudo kubeadm init phase certs front-proxy-ca
404+
sudo kubeadm init phase certs sa
405+
```
406+
407+
This will populate the folders `/etc/kubernetes/pki` and `/etc/kubernetes/pki/etcd`
408+
with all self-signed CA files (certificates and keys) and service account (public and
409+
private keys) that kubeadm needs for a control plane node.
410+
411+
{{< note >}}
412+
If you are using an external CA, you must generate the same files out of band and manually
413+
copy them to the primary control plane node in `/etc/kubernetes`. Once all CSRs
414+
are signed, you can delete the root CA key (`ca.key`) as noted in the
415+
[External CA mode](#external-ca-mode) section.
416+
{{< /note >}}
417+
418+
For secondary control plane nodes (`kubeadm join --control-plane`) there is no need to call
419+
the above commands. Depending on how you setup the
420+
[High Availability](/docs/setup/production-environment/tools/kubeadm/high-availability)
421+
cluster, you either have to manually copy the same files from the primary
422+
control plane node, or use the automated `--upload-certs` functionality of `kubeadm init`.
423+
424+
### Generate CSRs
425+
426+
The `kubeadm certs generate-csr` command generates CSRs for all known certificates
427+
managed by kubeadm. Once the command is done you must manually delete `.csr`, `.conf`
428+
or `.key` files that you don't need.
429+
430+
#### Considerations for kubelet.conf {#considerations-kubelet-conf}
431+
432+
This section applies to both control plane and worker nodes.
433+
434+
If you have deleted the `ca.key` file from control plane nodes
435+
([External CA mode](#external-ca-mode)), the active kube-controller-manager in
436+
this cluster will not be able to sign kubelet client certificates. If no external
437+
method for signing these certificates exists in your setup (such as an
438+
[external signer](#set-up-a-signer), you could manually sign the `kubelet.conf.csr`
439+
as explained in this guide.
440+
441+
Note that this also means that the automatic
442+
[kubelet client certificate rotation](/docs/tasks/tls/certificate-rotation/#enabling-client-certificate-rotation)
443+
will be disabled. If so, close to certificate expiration, you must generate
444+
a new `kubelet.conf.csr`, sign the certificate, embed it in `kubelet.conf`
445+
and restart the kubelet.
446+
447+
If this does not apply to your setup, you can skip processing the `kubelet.conf.csr`
448+
on secondary control plane and on workers nodes (all nodes tha call `kubeadm join ...`).
449+
That is because the active kube-controller-manager will be responsible
450+
for signing new kubelet client certificates.
451+
452+
{{< note >}}
453+
Processing the `kubelet.conf.csr` on the primary control plane node
454+
(`kubeadm init`) is required, because that is considered the node that
455+
bootstraps the cluster and a pre-populated `kubelet.conf` is needed.
456+
{{< /note >}}
457+
458+
#### Control plane nodes
459+
460+
Execute the following command on primary (`kubeadm init`) and secondary
461+
(`kubeadm join --control-plane`) control plane nodes to generate all CSR files:
462+
463+
```shell
464+
sudo kubeadm certs generate-csr
465+
```
466+
467+
If external etcd is to be used, follow the
468+
[External etcd with kubeadm](docs/setup/production-environment/tools/kubeadm/high-availability/#external-etcd-nodes)
469+
guide to understand what CSR files are needed on the kubeadm and etcd nodes. Other
470+
`.csr` and `.key` files under `/etc/kubernetes/pki/etcd` can be removed.
471+
472+
Based on the explanation in
473+
[Considerations for kubelet.conf](#considerations-kubelet-conf) keep or delete
474+
the `kubelet.conf` and `kubelet.conf.csr` files.
475+
476+
#### Worker nodes
477+
478+
Based on the explanation in
479+
[Considerations for kubelet.conf](#considerations-kubelet-conf), optionally call:
480+
481+
```shell
482+
sudo kubeadm certs generate-csr
483+
```
484+
485+
and keep only the `kubelet.conf` and `kubelet.conf.csr` files. Alternatively skip
486+
the steps for worker nodes entirely.
487+
488+
### Signing CSRs for all certificates
489+
490+
{{< note >}}
491+
If you are using external CA and already have CA serial number files (`.srl`) for
492+
`openssl` you can copy such files to a kubeadm node where CSRs will be processed.
493+
`.srl` files to copy are `/etc/kubernetes/pki/ca.srl`,
494+
`/etc/kubernetes/pki/front-proxy-ca.srl` and `/etc/kubernetes/pki/etcd/ca.srl`.
495+
The files can be then moved to a new node where CSR files will be processed.
496+
497+
If a `.srl` file is missing for a CA on a node, the script below will generate a new SRL file
498+
with a random starting serial number.
499+
500+
To read more about `.srl` files see the
501+
[`openssl`](https://www.openssl.org/docs/man3.0/man1/openssl-x509.html)
502+
documentation for the `--CAserial` flag.
503+
{{< /note >}}
504+
505+
Repeat this step for all nodes that have CSR files.
506+
507+
Write the following script in the `/etc/kubernetes` directory, navigate to the directory
508+
and execute the script. The script will generate certificates for all CSR files that are
509+
present in the `/etc/kubernetes` tree.
510+
511+
```bash
512+
#!/bin/bash
513+
514+
# Set certificate expiration time in days
515+
DAYS=365
516+
517+
# Process all CSR files except those for front-proxy and etcd
518+
find ./ -name "*.csr" | grep -v "pki/etcd" | grep -v "front-proxy" | while read -r FILE;
519+
do
520+
echo "* Processing ${FILE} ..."
521+
FILE=${FILE%.*} # Trim the extension
522+
if [ -f "./pki/ca.srl" ]; then
523+
SERIAL_FLAG="-CAserial ./pki/ca.srl"
524+
else
525+
SERIAL_FLAG="-CAcreateserial"
526+
fi
527+
openssl x509 -req -days "${DAYS}" -CA ./pki/ca.crt -CAkey ./pki/ca.key ${SERIAL_FLAG} \
528+
-in "${FILE}.csr" -out "${FILE}.crt"
529+
sleep 2
530+
done
531+
532+
# Process all etcd CSRs
533+
find ./pki/etcd -name "*.csr" | while read -r FILE;
534+
do
535+
echo "* Processing ${FILE} ..."
536+
FILE=${FILE%.*} # Trim the extension
537+
if [ -f "./pki/etcd/ca.srl" ]; then
538+
SERIAL_FLAG=-CAserial ./pki/etcd/ca.srl
539+
else
540+
SERIAL_FLAG=-CAcreateserial
541+
fi
542+
openssl x509 -req -days "${DAYS}" -CA ./pki/etcd/ca.crt -CAkey ./pki/etcd/ca.key ${SERIAL_FLAG} \
543+
-in "${FILE}.csr" -out "${FILE}.crt"
544+
done
545+
546+
# Process front-proxy CSRs
547+
echo "* Processing ./pki/front-proxy-client.csr ..."
548+
openssl x509 -req -days "${DAYS}" -CA ./pki/front-proxy-ca.crt -CAkey ./pki/front-proxy-ca.key -CAcreateserial \
549+
-in ./pki/front-proxy-client.csr -out ./pki/front-proxy-client.crt
550+
```
551+
552+
### Embedding certificates in kubeconfig files
553+
554+
Repeat this step for all nodes that have CSR files.
555+
556+
Write the following script in the `/etc/kubernetes` directory, navigate to the directory
557+
and execute the script. The script will take the `.crt` files that were signed for
558+
kubeconfig files from CSRs in the previous step and will embed them in the kubeconfig files.
559+
560+
```bash
561+
#!/bin/bash
562+
563+
CLUSTER=kubernetes
564+
find ./ -name "*.conf" | while read -r FILE;
565+
do
566+
echo "* Processing ${FILE} ..."
567+
KUBECONFIG="${FILE}" kubectl config set-cluster "${CLUSTER}" --certificate-authority ./pki/ca.crt --embed-certs
568+
USER=$(KUBECONFIG="${FILE}" kubectl config view -o jsonpath='{.users[0].name}')
569+
KUBECONFIG="${FILE}" kubectl config set-credentials "${USER}" --client-certificate "${FILE}.crt" --embed-certs
570+
done
571+
```
572+
573+
### Performing cleanup {#post-csr-cleanup}
574+
575+
Perform this step on all nodes that have CSR files.
576+
577+
Write the following script in the `/etc/kubernetes` directory, navigate to the directory
578+
and execute the script.
579+
580+
```bash
581+
#!/bin/bash
582+
583+
# Cleanup CSR files
584+
rm -f ./*.csr ./pki/*.csr ./pki/etcd/*.csr # Clean all CSR files
585+
586+
# Cleanup CRT files that were already embedded in kubeconfig files
587+
rm -f ./*.crt
588+
```
589+
590+
Optionally, move `.srl` files to the next node to be processed.
591+
592+
Optionally, if using external CA remove the `/etc/kubernetes/pki/ca.key` file,
593+
as explained in the [External CA node](#external-ca-mode) section.
594+
595+
### kubeadm node initialization
596+
597+
Once CSR files have been signed and required certificates are in place on the hosts
598+
you want to use as nodes, you can use the commands `kubeadm init` and `kubeadm join`
599+
to create a Kubernetes cluster from these nodes. During `init` and `join`, kubeadm
600+
uses existing certificates, encryption keys and kubeconfig files that it finds in the
601+
`/etc/kubernetes` tree on the host's local filesystem.

0 commit comments

Comments
 (0)