kubernetes/security kubernetes/networking
01 - Cryptography and PKI Foundations
02 - Kubernetes PKI Architecture
Generate Certificates Manually | Kubernetes
Core Idea
A complete OpenSSL worked example for cluster TLS by hand: build a workspace, a root CA, then the admin client and kube-apiserver server certificates, and inspect the result.
- Steps: secure workspace, root CA, admin client certificate, kube-apiserver server certificate.
- Verification and inspection: certificate metadata, expiration dates, and the certificate chain.
- Prerequisites and external resources frame when you would do this manually at all.
This document provides a complete, worked example of how to manually generate TLS certificates for a Kubernetes cluster using OpenSSL.
We will generate:
- A Root Certificate Authority (CA)
- An Admin client certificate (with RBAC mapping)
- A Kube-APIServer server certificate (with Subject Alternative Names)
Prerequisites
Ensure OpenSSL is installed on your local host:
openssl versionStep-by-Step Worked Example
Step 1: Create a Secure Workspace
First, create a clean directory to store your keys and restrict permissions. Private keys must not be readable by unauthorized local users.
mkdir -p /tmp/k8s-pki-lab && cd /tmp/k8s-pki-lab
chmod 700 /tmp/k8s-pki-labStep 2: Generate the Root CA
The CA certificate (ca.crt) signs all other certificates in the cluster. It requires a private key (ca.key).
- Generate the private key:
openssl genrsa -out ca.key 2048 - Generate the Certificate Signing Request (CSR):
openssl req -new -key ca.key -subj "/CN=KUBERNETES-CA" -out ca.csr - Self-sign the certificate:
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt -days 3650
Output Files: ca.key (keep highly secure) and ca.crt (distribute to all nodes).
Step 3: Generate the Admin Client Certificate
We want to generate a client certificate that maps to the administrative group system:masters in Kubernetes.
- Generate the user’s private key:
openssl genrsa -out admin.key 2048 - Generate the CSR:
Notice the inclusion ofO=system:mastersin the Subject. This will bind the user to the administrator group.openssl req -new -key admin.key -subj "/CN=kube-admin/O=system:masters" -out admin.csr - Sign the certificate using the Root CA:
openssl x509 -req -in admin.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out admin.crt -days 365
Step 4: Generate the Kube-APIServer Server Certificate
The API server is accessed via different hostnames and IP addresses (e.g., node IP, service IP, cluster local DNS). These MUST be declared in the Subject Alternative Name (SAN) extensions, otherwise clients will reject the TLS connection with “Hostname mismatch”.
-
Create an OpenSSL Config File (
openssl.cnf):
Create a config file declaring the extensions and alt names:[ req ] distinguished_name = req_distinguished_name req_extensions = v3_req prompt = no [ req_distinguished_name ] CN = kube-apiserver [ v3_req ] basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = @alt_names [ alt_names ] # DNS Names DNS.1 = kubernetes DNS.2 = kubernetes.default DNS.3 = kubernetes.default.svc DNS.4 = kubernetes.default.svc.cluster.local DNS.5 = api.k8s.local # IP Addresses IP.1 = 10.96.0.1 # Kubernetes Internal Service Cluster IP (typically the first IP in service range) IP.2 = 192.168.1.100 # Master Node Internal IP Address IP.3 = 127.0.0.1 # Local Loopback -
Generate the API Server Private Key:
openssl genrsa -out apiserver.key 2048 -
Generate the CSR using the Config File:
openssl req -new -key apiserver.key -config openssl.cnf -out apiserver.csr -
Sign the API Server Certificate using the Root CA and Extensions:
openssl x509 -req -in apiserver.csr \ -CA ca.crt -CAkey ca.key -CAcreateserial \ -extfile openssl.cnf -extensions v3_req \ -out apiserver.crt -days 365
Step 5: Verification & Inspection
A. How to Inspect Certificate Metadata
To verify that the Common Name, Issuer, and SANs are correct, decode the certificate:
openssl x509 -in apiserver.crt -text -nooutExpected Output Excerpts:
- Issuer:
CN=KUBERNETES-CA - Subject:
CN=kube-apiserver - X509v3 Subject Alternative Name:
DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:api.k8s.local, IP Address:10.96.0.1, IP Address:192.168.1.100, IP Address:127.0.0.1
B. Verify the Expiration Dates
To view just the certificate start and end dates:
openssl x509 -in admin.crt -noout -datesOutput:
notBefore=Jun 20 07:00:00 2026 GMT
notAfter=Jun 20 07:00:00 2027 GMTC. Verify the Certificate Chain
To check if the generated client/server certificate was indeed signed by the Root CA:
openssl verify -CAfile ca.crt apiserver.crtExpected Output:
apiserver.crt: OKIf you get OK, your certificate chain is correct and client components trusting ca.crt will successfully establish connections with the API server.