K8s Certificates and Keys

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.

CertsComponents that uses this certfilesRole
CAAlmost all K8s components
  • ca-key.pem(Key)
  • ca.pem(Cert)
Root CA
API Server Certkube-apiserver
  • apiserver-key.pem(Key)
  • apiserver.pem(Cert)
API Server Cert
Client CertAll components that talks to API Server
  • client-key.pem(Key)
  • client.pem(Cert)
API Server Client Cert
Service Account Keypairkube-apiserver
  • sa-key.pem(Private Key)
  • sa-pub.pem(Pubkey)
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.

comments powered by Disqus