A TLS Certificate is used to guarantee trust between two parties in a transaction by encryption the data during transfer using encryption keys. There are two ways to encrypt the data:
To secure the Kubernetes cluster, we need to encrypt the following:
There are actually three sets of certificates that we need:
For self-managed Kubernetes clusters which could be setup using kubeadm, the following keypairs needs to be generated:
For the client’s side, there’s actually four clients that talks to the kube-apiserver.
In a Kubernetes setup, the CA is simply a pair of key and certificate files. The server where these files are securely stored are called the CA server. These certificates can also be placed in the master node, which makes the master node a CA server.
We can use the following tools to generate the certificates
Start with the CA Certificates by generating a private key:
openssl genrsa -out ca.key 2048 # ca.key
Using the private key, generate a CSR. This is similar to a certificate but is not signed yet.
openssl req -new -key ca.key -subj \ # ca.csr
"/CN=KUBERNETES-CA" -out ca.csr
Finally, sign the certificate.
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
Going forward, we can use this CA key pair to sign all other certificates.
Generate a private key:
openssl genrsa -out admin.key 2048 # admin.key
Using the private key, generate a CSR. Note that for admin users, we need to add the “O=system:master”. For any other users, we ignore it.
openssl req -new -key admin.key \
-subj "/CN=kube-admin/O=system:master" \
-out admin.csr
Finally, sign the certificate.
openssl x509 -req -in admin.csr -CA ca.crt -CAkey ca.key -out admin.crt
The same steps is followed for generating the other client certificates:
The other server certificates need to be generated (for self-managed Kubernetes cluster):
The same steps is followed for generating the other client certificates:
The following set of certs need to be generated:
For the etcd server, it can be deployed in an HA setup thus we will need additional peer certificates. The certificates are then specified in the etcd.yaml file alogn with the CA root certificate.
For the kube-apiserver, we can specify an openssl.cnf file and specify the alternate names for the kube-apiserver.
[ req ]
req_extensions = v3_req
[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation ,
sibjectAltName = @alt_names
[alt_names]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster.local
IP.1 = 10.23.45.61
IP.2 = 172.16.1.88
Generate the private key the same way:
openssl genrsa -out apiserver.key 2048 # apiserver.key
Create the CSR. Make sure to specify the config file.
openssl req -new -key admin.key -subj \
"/CN=kube-apiserver" -out apiserver.csr \
-config openssl.cnf
Then sign the certificate:
openssl x509 -req -in apiserver.csr \
-CA ca.crt -CAkey ca.key -out apiserver.crt
The location of these certificates are also passed to the kube-apiserver service.
The certificate paths can also be specified when running the kube-apiserver in the command line.
kube apiserver
--authorization mode= Node,RBAC
--advertise address=172.17.0.18
--allow privileged=true
--client ca file=/ etc kubernetes pki /ca.crt
--disable admission plugins= PersistentVolumeLabel
--enable admission plugins= NodeRestriction
--enable bootstrap token auth=true
--etcd cafile etc kubernetes pki etcd /ca.crt
--etcd certfile etc kubernetes pki /apiserver etcd client.crt
--etcd keyfile etc kubernetes pki apiserver etcd client.key
--etcd servers=https://127.0.0.1:2379
--insecure port=0
--kubelet client certificate=/ etc kubernetes pki /apiserver kubelet client.crt
--kubelet client key=/ etc kubernetes pki apiserver kubelet client.key
--kubelet preferred address types= InternalIP,ExternalIP,Hostname
--proxy client cert file=/ etc kubernetes pki /front proxy client.crt
--proxy client key file=/ etc kubernetes pki /front proxy client.key
--requestheader allowed names=front proxy client
--requestheader client ca file=/ etc kubernetes pki /front proxy ca.crt
--requestheader extra headers prefix=X Remote Extra
--requestheader group headers=X Remote Group
--requestheader username headers=X Remote User
--secure port=6443
--service account key file=/ etc kubernetes pki /sa.pub
--service cluster ip range=10.96.0.0/12
--tls cert file=/ etc kubernetes pki /apiserver.crt
--tls private key file=/ etc kubernetes pki apiserver.key
The certificates can be used as options in a REST API call;
curl https://kube-apiserver:6443/api/v1/pods/
--key admin.key \
--cert admin.crt \
--cacert ca.crt
They can also be specified in a kube-config.yaml file.
apiVersion: v1
kind: Config
clusters:
- name: kubernetes
cluster:
certificate-authority: ca.crt
server: https://kube-apiserver:6443
users:
- name: kubernetes-admin
user:
client-certificate: admin.crt
client-key: admin.key
For a Kubernetes Cluster that is setup via kubeadm, look for the YAMl file for kube-apiserver.
cat /etc/kubernetes/manifests/kube-apiserver.yaml
Next, we can drill down on the individual certificates that are defined in the YAML file. We can use OpenSSL to view the certificates:
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout
Check the following:
Perform the same checks on the other certificates.
Kubernetes has a built-in certificates API which we can use to manage certificates, signing requests, and certificate rotation.
User send signing request directly to Kubernetes through an API call.
# Create the private key first
openssl genrsa -out jane.key 2048
# Create CSR
openssl req -new -key jane.key -subj "/CN=jane" -out jane.csr
Admin creates a CSR Object through a YAML file, which can be seen by all cluster administrators.
# encode th e CSR first
cat jane.csr | base64
# Create the YAML file for the CSR Object.
# Copy base64 encoded CSR ot the "request" field.
vi jane-csr.yml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: jane
spec:
groups:
- system:authenticated
usages:
- digital signature
- key encipherment
- server auth
request:
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZqQ0NBVDRDQVFBd0VURV
BNQTBHQTFVRUF3d0dZVzVuWld4aE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRgpBQU9DQVE4QU1J
SUJDZ0tDQVFFQTByczhJTHRHdTYxakx2dHhWTTJSVlRWMDNHWlJTWWw0dWluVWo4RElaWjBOCn
R2MUZtRVFSd3VoaUZsOFEzcWl0Qm0wMUFSMkNJVXBGd2ZzSjZ4MXF3ckJzVkhZbGlBNVhwRVpZ
Requests can be reviewed and approved using kubectl. Kubernetes signs the certificates using the keypairs and generate a certificate for the user.
# To retrieve all CSR
kubectl get csr
# To approve the CSR
kubectl certificate approve jane
The certificate can then extracted and shared back to the users.
# View certificate in a yaml format.
# The generated certificate is part of the output.
kubectl get csr jane -o yaml
# COpy the certificate to a file and decode it
cat jane-approved.csr | base64 --decode
The Controller Manager takes care of all certificate-related operations.
To sign the certificates, recall that we need the CA root server and private key. These files are also defined in the Controller Manager’s definitions file.
As additional troubleshooting steps, we can check the logs for any certificate-related issues.
For kubeadm-managed cluster:
If kubectl doesn’t work due to the core components being down, we can also use the docker CLI to check logs.