K8s Certificates and Keys #
Interactions between Kubernetes components are all conducted over HTTPS: the controller communicates with the API server, the kubelet connects to the API server, and even when we use the kubectl tool, it connects to the API server via HTTPS.
This is similar to using HTTPS when accessing websites in a browser, but Kubernetes employs mutual authentication: not only does the server require a certificate and key, but the client also needs its own certificate and key to verify its identity.
Let’s prepare these certificates and keys.
Certs | Components that uses this cert | files | Role |
---|---|---|---|
CA | Almost all K8s components |
| Root CA |
API Server Cert | kube-apiserver |
| API Server Cert |
Client Cert | All components that talks to API Server |
| API Server Client Cert |
Service Account Keypair | kube-apiserver |
| For issuing “Service Account” JWT tokens |
INFO
Service Account Keypair is a pub/private keypair, This is different from the mutual HTTPS authentication certificates mentioned earlier.
Download tools #
In this section, we’ll use Cloudflare’s SSL tool, cfssl
. Download here:https://github.com/cloudflare/cfssl/releases/
We’ll primarily use cfssl
and cfssljson
.
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssl_1.6.5_linux_amd64
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssljson_1.6.5_linux_amd64
mv cfssl_1.6.5_linux_amd64 /usr/local/bin/cfssl
mv cfssljson_1.6.5_linux_amd64 /usr/local/bin/cfssljson
chmod +x /usr/local/bin/cfssl
chmod +x /usr/local/bin/cfssljson
Let’s take this opportunity to add /usr/local/bin
to the PATH
, as other binaries will also be placed here later on.
echo "export PATH=$PATH:/usr/local/bin" >> ~/.bash_profile
source ~/.bash_profile
You may have heard that OpenSSL also has tools for generating certificates. It can be a bit cumbersome to use, so we’ll skip it for certificate creation (though we may use it briefly for generating keys.)
Generate the CA Certiticate #
Certificates are organized in a hierarchical, tree-like structure, with the CA certificate as the root. During the creation of other Kubernetes certificates, the CA certificate is always included, establishing a kind of parent-child relationship: all other certificates are the “children” of this root certificate, sharing a common “parent.”
Let’s start by generating this “parent” CA.
cd /etc/kubernetes/pki/
In the /etc/kubernetes/pki/
directory, create a file named ca-csr.json
and add the following content:
{
"CN": "IKFB",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "San Francisco",
"O": "Kubernetes",
"OU": "CA",
"ST": "California"
}
]
}
Next, use the cfssl
tool to generate the ca-key.pem
key and the ca.pem
certificate.
cfssl genkey -initca ca-csr.json | cfssljson -bare ca
Generating the API Server Certificate #
Next, we’ll generate the certificate for the API Server. This certificate, similar to a common HTTPS certificate, primarily serves to prove that the server is indeed the API Server.
It’s important to note that clients may access the API Server using different addresses: some may use the Service IP (10.96.0.1
), others might connect via https://master:6443
, or directly through an IP address (192.168.56.10
). Therefore, the certificate must cover these different access addresses. When issuing the certificate, we need to include all these addresses, effectively giving the API Server an “ID card” listing its multiple valid names.
In certificate terminology, specifying multiple addresses is done through Subject Alternative Names (SANs). We’ll add these SAN details to the certificate configuration file shortly.
Copy the following content into kube-apiserver-csr.json
.
{
"CN": "kube-apiserver",
"hosts": [
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster.local",
"master",
"10.96.0.1",
"192.168.56.10"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "San Francisco",
"O": "Kubernetes",
"OU": "CA",
"ST": "California"
}
]
}
Next, we’ll generate the certificate and key for the API Server.
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -profile=kube-apiserver kube-apiserver-csr.json | cfssljson -bare kube-apiserver
This will produce the kube-apiserver-key.pem
and kube-apiserver.pem
files.
Generating the client certificate #
Next, we’ll generate a client certificate for components accessing the API Server.
In this Kubernetes installation, authentication is certificate-based. The certificate we create will serve as a proof for a Kubernetes’ “super administrator.”
This certificate will be configured in the kubeconfig files for the controller, scheduler, and kubelet, allowing them to access the API Server.
WARNING
Each of these components should ideally have its own unique certificate and kubeconfig. However, to simplify the process, we’ll use a single certificate for all of them here.
Do not use this approach in a production environment.
Create client-csr.json
。
{
"CN": "admin",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"O": "system:masters"
}
]
}
Generate the client certificate and key.
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem client-csr.json | cfssljson -bare client
This will produce the client-key.pem
and client.pem
files.
After running the command, you might see a warning: [WARNING] This certificate lacks a "hosts" field...
, indicating that without specified hosts, this certificate isn’t suitable for identifying a server. However, since we don’t intend to use it as a server certificate, this warning can be ignored.
We specified CN=admin,O=system:masters
, which effectively declares that this user is named “admin” and belongs to the system:masters
group. This aligns with a preset Kubernetes rule: users in the system:masters
group are super administrators.
Generating the Service Account keypair #
Unlike the previous certificates and keys, the Service Account credential is a simple public-private key pair.
Sometimes, Pods need to interact with the Kubernetes API. To enable this, Kubernetes creates a JWT token as an interaction credential for each Pod upon creation, and this Service Account’s public-private key pair is used to generate and verify the JWT token.
This is straightforward, so we’ll use OpenSSL to generate the key pair directly.
Generate the private and public keys:
# Generate private key
openssl genrsa -out sa-key.pem 2048
# Generate public key from the private key
openssl rsa -in sa-key.pem -pubout -out sa-pub.pem
At this point, if the certificate directory contains the following files, it generally indicates that this step of the installation is complete.
[root@master pki]# ls -alh
total 60K
drwxr-xr-x. 2 root root 4.0K Oct 13 13:51 .
drwxr-xr-x. 3 root root 17 Oct 13 13:38 ..
-rw-r--r--. 1 root root 1009 Oct 13 13:48 ca.csr
-rw-r--r--. 1 root root 214 Oct 13 13:48 ca-csr.json
-rw-------. 1 root root 1.7K Oct 13 13:48 ca-key.pem
-rw-r--r--. 1 root root 1.3K Oct 13 13:48 ca.pem
-rw-r--r--. 1 root root 920 Oct 13 13:51 client.csr
-rw-r--r--. 1 root root 130 Oct 13 13:51 client-csr.json
-rw-------. 1 root root 1.7K Oct 13 13:51 client-key.pem
-rw-r--r--. 1 root root 1.3K Oct 13 13:51 client.pem
-rw-r--r--. 1 root root 1.2K Oct 13 13:50 kube-apiserver.csr
-rw-r--r--. 1 root root 411 Oct 13 13:49 kube-apiserver-csr.json
-rw-------. 1 root root 1.7K Oct 13 13:50 kube-apiserver-key.pem
-rw-r--r--. 1 root root 1.6K Oct 13 13:50 kube-apiserver.pem
-rw-------. 1 root root 1.7K Oct 13 13:51 sa-key.pem
-rw-r--r--. 1 root root 451 Oct 13 13:51 sa-pub.pem
Next up, let’s install control plane components.