5.2.2.2. Certificates
Certificates are digital documents that verify the authenticity of components within a Kubernetes cluster. They provide secure communication, authentication, and encryption during interactions between nodes, control components, and users.
All certificates are created based on Public Key Infrastructure (PKI) and contain information about the owner, validity period, and the Certificate Authority (CA) that issued the certificate.
This section generates the certificates required for various Kubernetes components (API server, kubelet, controller-manager, etc.).
- Init
- Join
Creating application certificates
● Required
Creating application certificates
● Required
- Kubelet Server
- API -> Etcd
- API -> Kubelet
- API Server
- Proxy -> API
- Etcd Client
- Etcd Server
- Etcd Peer
- Controller server
- Scheduler server
Kubelet server
Kubelet server
Purpose: kubelet server certificate for TLS on port 10250. Presented when kube-apiserver and other clients connect to the kubelet API. Signed by kubernetes-ca.
- HardWay
- Kubeadm
Environment variables
export CLUSTER_NAME=my-first-cluster
export BASE_DOMAIN=example.com
export CLUSTER_DOMAIN=cluster.local
export FULL_HOST_NAME=${HOST_NAME}.${CLUSTER_NAME}.${BASE_DOMAIN}
export MACHINE_LOCAL_ADDRESS=$(ip -4 addr show scope global | awk '/inet/ {print $2; exit}' | cut -d/ -f1)
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
mkdir -p /var/lib/kubelet/pki
Configuration
cat <<EOF > /etc/kubernetes/openssl/kubelet-server.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = localhost
DNS.2 = ${HOST_NAME}
DNS.3 = ${FULL_HOST_NAME}
IP.1 = 127.0.0.1
IP.2 = 0:0:0:0:0:0:0:1
IP.3 = ${MACHINE_LOCAL_ADDRESS}
[ dn ]
CN = "system:node:${FULL_HOST_NAME}
O = "system:nodes"
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
EOF
Private key generation
openssl genrsa \
-out /var/lib/kubelet/pki/kubelet-server-key.pem 2048
CSR generation
openssl req \
-new \
-key /var/lib/kubelet/pki/kubelet-server-key.pem \
-out /etc/kubernetes/openssl/csr/kubelet-server.csr \
-config /etc/kubernetes/openssl/kubelet-server.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-outform PEM \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/kubelet-server.csr \
-out /var/lib/kubelet/pki/kubelet-server.pem \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/kubelet-server.conf
cat /var/lib/kubelet/pki/kubelet-server.pem /var/lib/kubelet/pki/kubelet-server-key.pem >> /var/lib/kubelet/pki/kubelet-server-$(date '+%Y-%m-%d-%H-%M-%S').pem
ln -s /var/lib/kubelet/pki/kubelet-server-$(date '+%Y-%m-%d-%H-%M-%S').pem /var/lib/kubelet/pki/kubelet-server-current.pem
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /var/lib/kubelet/pki/kubelet-server.pem
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
kubelet-server-current Oct 22, 2025 22:06 UTC 364d kubernetes no
kubeadm does not manage the server certificate used by the kubelet component.
When the kubelet systemd unit starts, it initiates a certificate signing request.
To complete the process, manual approval is required using the command:
kubectl certificate approve $CERT_NAME.
RotateKubeletServerCertificate
For automatickubelet certificate rotation, additional configuration is required:Kube-Apiserver configuration
spec:
containers:
- command:
- --feature-gates=RotateKubeletServerCertificate=true
apiServer:
extraArgs:
feature-gates: "RotateKubeletServerCertificate=true"
Kube-Controller-Manager configuration
spec:
containers:
- command:
- --feature-gates=RotateKubeletServerCertificate=true
controllerManager:
extraArgs:
feature-gates: "RotateKubeletServerCertificate=true"
Kubelet configuration
rotateCertificates: true
featureGates:
RotateKubeletServerCertificate: true
If you are using Cloud Controller Manager (CCM), the certificate will not be issued until
CCM assigns an address to the Node in the INTERNAL_IP field.
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
kubelet-server-current Oct 22, 2025 22:06 UTC 364d kubernetes no
K8S-API client > Etcd server
K8S-API client > Etcd server
Purpose: API Server client certificate for connecting to etcd. Used by kube-apiserver when accessing the cluster data store. Signed by etcd-ca.
- HardWay
- Kubeadm
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/apiserver-etcd-client.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[ dn ]
CN = kube-apiserver-etcd-client
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=clientAuth
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/apiserver-etcd-client.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/apiserver-etcd-client.key \
-out /etc/kubernetes/openssl/csr/apiserver-etcd-client.csr \
-config /etc/kubernetes/openssl/apiserver-etcd-client.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-CA /etc/kubernetes/pki/etcd/ca.crt \
-CAkey /etc/kubernetes/pki/etcd/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/apiserver-etcd-client.csr \
-out /etc/kubernetes/pki/apiserver-etcd-client.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/apiserver-etcd-client.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/apiserver-etcd-client.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
apiserver-etcd-client Oct 22, 2025 22:06 UTC 364d etcd-ca no
Certificate generation
kubeadm init phase certs apiserver-etcd-client \
--config=/var/run/kubeadm/kubeadm.yaml
After executing the commands, we get the following output.
#### Certificate generation
[certs] Generating "apiserver-etcd-client" certificate and key
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
apiserver-etcd-client Oct 22, 2025 22:06 UTC 364d etcd-ca no
K8S-API client > Kubelet server
K8S-API client > Kubelet server
Purpose: API Server client certificate for connecting to kubelet. Used by kube-apiserver when accessing the kubelet API (fetching logs, exec, port-forward). Signed by kubernetes-ca.
- HardWay
- Kubeadm
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/apiserver-kubelet-client.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[ dn ]
CN = kube-apiserver-kubelet-client
O = kubeadm:cluster-admins
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=clientAuth
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/apiserver-kubelet-client.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/apiserver-kubelet-client.key \
-out /etc/kubernetes/openssl/csr/apiserver-kubelet-client.csr \
-config /etc/kubernetes/openssl/apiserver-kubelet-client.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/apiserver-kubelet-client.csr \
-out /etc/kubernetes/pki/apiserver-kubelet-client.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/apiserver-kubelet-client.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/apiserver-kubelet-client.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
apiserver-kubelet-client Oct 22, 2025 22:06 UTC 364d ca no
Certificate generation
kubeadm init phase certs apiserver-kubelet-client \
--config=/var/run/kubeadm/kubeadm.yaml
After executing the commands, we get the following output.
#### Certificate generation
[certs] Generating "apiserver-kubelet-client" certificate and key
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
apiserver-kubelet-client Oct 22, 2025 22:06 UTC 364d ca no
K8S-API server
K8S-API server
Purpose: API Server server certificate, presented to clients during TLS connection. Contains SAN (Subject Alternative Names) for all API access addresses: node IP addresses, load balancer VIP, DNS names, and the
kubernetes.defaultservice ClusterIP address. Signed by kubernetes-ca.
- HardWay
- Kubeadm
Environment variables
export CLUSTER_NAME=my-first-cluster
export BASE_DOMAIN=example.com
export CLUSTER_DOMAIN=cluster.local
export FULL_HOST_NAME=${HOST_NAME}.${CLUSTER_NAME}.${BASE_DOMAIN}
export CLUSTER_API_ENDPOINT=api.my-first-cluster.example.com
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/apiserver.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.${CLUSTER_DOMAIN}
DNS.5 = ${FULL_HOST_NAME}
DNS.6 = ${CLUSTER_API_ENDPOINT}
IP.1 = $(ip -4 addr show scope global | awk '/inet/ {print $2; exit}' | cut -d/ -f1)
IP.2 = 127.0.0.1
[ dn ]
CN = kube-apiserver
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/apiserver.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/apiserver.key \
-out /etc/kubernetes/openssl/csr/apiserver.csr \
-config /etc/kubernetes/openssl/apiserver.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/apiserver.csr \
-out /etc/kubernetes/pki/apiserver.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/apiserver.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/apiserver.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
apiserver Oct 22, 2025 22:06 UTC 364d ca no
Certificate generation
kubeadm init phase certs apiserver \
--config=/var/run/kubeadm/kubeadm.yaml
After executing the commands, we get the following output.
#### Certificate generation
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [api.my-first-cluster.example.com kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local master-1.my-first-cluster.example.com] and IPs [29.64.0.1 10.0.0.16]
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
apiserver Oct 22, 2025 22:06 UTC 364d ca no
FrontProxy client > K8S-API
FrontProxy client > K8S-API
Purpose: Client certificate for the API aggregation mechanism (extension API servers). Used by kube-apiserver when proxying requests to extended API servers (e.g., metrics-server). Signed by front-proxy-ca.
- HardWay
- Kubeadm
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/front-proxy-client.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[ dn ]
CN = front-proxy-client
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=clientAuth
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/front-proxy-client.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/front-proxy-client.key \
-out /etc/kubernetes/openssl/csr/front-proxy-client.csr \
-config /etc/kubernetes/openssl/front-proxy-client.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-CA /etc/kubernetes/pki/front-proxy-ca.crt \
-CAkey /etc/kubernetes/pki/front-proxy-ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/front-proxy-client.csr \
-out /etc/kubernetes/pki/front-proxy-client.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/front-proxy-client.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/front-proxy-client.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
front-proxy-client Oct 22, 2025 22:06 UTC 364d front-proxy-ca no
Certificate generation
kubeadm init phase certs front-proxy-client \
--config=/var/run/kubeadm/kubeadm.yaml
After executing the commands, we get the following output.
#### Certificate generation
[certs] Generating "front-proxy-client" certificate and key
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
front-proxy-client Oct 22, 2025 22:06 UTC 364d front-proxy-ca no
Etcd client > Etcd
Etcd client > Etcd
Purpose: Client certificate for etcd healthcheck probes (liveness probe). Used for connecting to the etcd client API when checking cluster availability. Signed by etcd-ca.
- HardWay
- Kubeadm
Working directory
mkdir -p /etc/kubernetes/pki/etcd
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/healthcheck-client.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[ dn ]
CN = kube-etcd-healthcheck-client
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=clientAuth
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/etcd/healthcheck-client.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/etcd/healthcheck-client.key \
-out /etc/kubernetes/openssl/csr/etcd-client.csr \
-config /etc/kubernetes/openssl/healthcheck-client.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-CA /etc/kubernetes/pki/etcd/ca.crt \
-CAkey /etc/kubernetes/pki/etcd/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/etcd-client.csr \
-out /etc/kubernetes/pki/etcd/healthcheck-client.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/healthcheck-client.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/etcd/healthcheck-client.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
etcd-healthcheck-client Oct 22, 2025 22:06 UTC 364d etcd-ca no
Certificate generation
kubeadm init phase certs etcd-healthcheck-client \
--config=/var/run/kubeadm/kubeadm.yaml
After running the command, we get the following output.
#### Certificate generation
[certs] Generating "etcd/healthcheck-client" certificate and key
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
etcd-healthcheck-client Oct 22, 2025 22:06 UTC 364d etcd-ca no
Etcd server
Etcd server
Purpose: Server certificate for etcd serving client connections on port 2379. Presented during TLS connection from kube-apiserver and other etcd clients. Signed by etcd-ca.
- HardWay
- Kubeadm
Environment variables
export CLUSTER_NAME=my-first-cluster
export BASE_DOMAIN=example.com
export FULL_HOST_NAME=${HOST_NAME}.${CLUSTER_NAME}.${BASE_DOMAIN}
export MACHINE_LOCAL_ADDRESS=$(ip -4 addr show scope global | awk '/inet/ {print $2; exit}' | cut -d/ -f1)
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/etcd-server.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = localhost
DNS.2 = ${HOST_NAME}
DNS.3 = ${FULL_HOST_NAME}
IP.1 = 127.0.0.1
IP.2 = 0:0:0:0:0:0:0:1
IP.3 = ${MACHINE_LOCAL_ADDRESS}
[ dn ]
CN = ${FULL_HOST_NAME}
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth,clientAuth
subjectAltName=@alt_names
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/etcd/server.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/etcd/server.key \
-out /etc/kubernetes/openssl/csr/etcd-server.csr \
-config /etc/kubernetes/openssl/etcd-server.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-CA /etc/kubernetes/pki/etcd/ca.crt \
-CAkey /etc/kubernetes/pki/etcd/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/etcd-server.csr \
-out /etc/kubernetes/pki/etcd/server.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/etcd-server.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/etcd/server.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
etcd-server Oct 22, 2025 22:06 UTC 364d etcd-ca no
Certificate generation
kubeadm init phase certs etcd-server \
--config=/var/run/kubeadm/kubeadm.yaml
After running the command, we get the following output.
#### Certificate generation
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com] and IPs [192.168.10.27 127.0.0.1 ::1]
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
etcd-server Oct 22, 2025 22:06 UTC 364d etcd-ca no
Etcd peer > Etcd
Etcd peer > Etcd
Purpose: Certificate for mutual authentication (mutual TLS) between etcd cluster nodes on port 2380. Each cluster member uses the peer certificate for both the server and client side of the connection. Signed by etcd-ca.
- HardWay
- Kubeadm
Environment variables
export CLUSTER_NAME=my-first-cluster
export FULL_HOST_NAME=${HOST_NAME}.${CLUSTER_NAME}.${BASE_DOMAIN}
export MACHINE_LOCAL_ADDRESS=$(ip -4 addr show scope global | awk '/inet/ {print $2; exit}' | cut -d/ -f1)
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/etcd-peer.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = localhost
DNS.2 = ${HOST_NAME}
DNS.3 = ${FULL_HOST_NAME}
IP.1 = 127.0.0.1
IP.2 = 0:0:0:0:0:0:0:1
IP.3 = ${MACHINE_LOCAL_ADDRESS}
[ dn ]
CN = ${FULL_HOST_NAME}
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth,clientAuth
subjectAltName=@alt_names
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/etcd/peer.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/etcd/peer.key \
-out /etc/kubernetes/openssl/csr/etcd-peer.csr \
-config /etc/kubernetes/openssl/etcd-peer.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-CA /etc/kubernetes/pki/etcd/ca.crt \
-CAkey /etc/kubernetes/pki/etcd/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/etcd-peer.csr \
-out /etc/kubernetes/pki/etcd/peer.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/etcd-peer.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/etcd/peer.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
etcd-peer Oct 22, 2025 22:06 UTC 364d etcd-ca no
Certificate generation
kubeadm init phase certs etcd-peer \
--config=/var/run/kubeadm/kubeadm.yaml
After running the command, we get the following output.
#### Certificate generation
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com] and IPs [192.168.10.27 127.0.0.1 ::1]
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
etcd-peer Oct 22, 2025 22:06 UTC 364d etcd-ca no
Controller server
Controller server
Purpose: kube-controller-manager server certificate for TLS on the metrics port and healthz endpoints. Signed by kubernetes-ca. Note: kubeadm does not manage this certificate — it is only created in HardWay mode.
- HardWay
- Kubeadm
Environment variables
export MACHINE_LOCAL_ADDRESS=$(ip -4 addr show scope global | awk '/inet/ {print $2; exit}' | cut -d/ -f1)
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/controller-manager-server.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = kube-controller-manager
DNS.2 = kube-controller-manager.kube-system
DNS.3 = kube-controller-manager.kube-system.svc
IP.1 = 127.0.0.1
IP.2 = 0:0:0:0:0:0:0:1
IP.3 = ${MACHINE_LOCAL_ADDRESS}
[ dn ]
CN = "system:kube-controller-manager-server"
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/controller-manager-server.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/controller-manager-server.key \
-out /etc/kubernetes/openssl/csr/controller-manager-server.csr \
-config /etc/kubernetes/openssl/controller-manager-server.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-outform PEM \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/controller-manager-server.csr \
-out /etc/kubernetes/pki/controller-manager-server.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/controller-manager-server.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/controller-manager-server.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
controller-manager-server Oct 22, 2025 22:06 UTC 364d kubernetes no
Please note that kubeadm does not manage these certificates. Use HardWay mode
Scheduler server
Scheduler server
Purpose: kube-scheduler server certificate for TLS on the metrics port and healthz endpoints. Signed by kubernetes-ca. Note: kubeadm does not manage this certificate — it is only created in HardWay mode.
- HardWay
- Kubeadm
Environment variables
export MACHINE_LOCAL_ADDRESS=$(ip -4 addr show scope global | awk '/inet/ {print $2; exit}' | cut -d/ -f1)
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/scheduler-server.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = kube-scheduler
DNS.2 = kube-scheduler.kube-system
DNS.3 = kube-scheduler.kube-system.svc
IP.1 = 127.0.0.1
IP.2 = 0:0:0:0:0:0:0:1
IP.3 = ${MACHINE_LOCAL_ADDRESS}
[ dn ]
CN = "system:kube-scheduler-server"
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/scheduler-server.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/scheduler-server.key \
-out /etc/kubernetes/openssl/csr/scheduler-server.csr \
-config /etc/kubernetes/openssl/scheduler-server.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-outform PEM \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/scheduler-server.csr \
-out /etc/kubernetes/pki/scheduler-server.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/scheduler-server.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/scheduler-server.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
scheduler-server Oct 22, 2025 22:06 UTC 364d kubernetes no
Please note that kubeadm does not manage these certificates. Use HardWay mode
Creating application certificates
● Required
Creating application certificates
● Required
- Kubelet Server
- API -> Etcd
- API -> Kubelet
- API Server
- Proxy -> API
- Etcd Client
- Etcd Server
- Etcd Peer
- Controller server
- Scheduler server
Kubelet server
Kubelet server
- HardWay
- Kubeadm
Environment variables
export CLUSTER_NAME=my-first-cluster
export BASE_DOMAIN=example.com
export CLUSTER_DOMAIN=cluster.local
export FULL_HOST_NAME=${HOST_NAME}.${CLUSTER_NAME}.${BASE_DOMAIN}
export MACHINE_LOCAL_ADDRESS=$(ip -4 addr show scope global | awk '/inet/ {print $2; exit}' | cut -d/ -f1)
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
mkdir -p /var/lib/kubelet/pki
Configuration
cat <<EOF > /etc/kubernetes/openssl/kubelet-server.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = localhost
DNS.2 = ${HOST_NAME}
DNS.3 = ${FULL_HOST_NAME}
IP.1 = 127.0.0.1
IP.2 = 0:0:0:0:0:0:0:1
IP.3 = ${MACHINE_LOCAL_ADDRESS}
[ dn ]
CN = "system:node:${FULL_HOST_NAME}
O = "system:nodes"
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
EOF
Private key generation
openssl genrsa \
-out /var/lib/kubelet/pki/kubelet-server-key.pem 2048
CSR generation
openssl req \
-new \
-key /var/lib/kubelet/pki/kubelet-server-key.pem \
-out /etc/kubernetes/openssl/csr/kubelet-server.csr \
-config /etc/kubernetes/openssl/kubelet-server.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-outform PEM \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/kubelet-server.csr \
-out /var/lib/kubelet/pki/kubelet-server.pem \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/kubelet-server.conf
cat /var/lib/kubelet/pki/kubelet-server.pem /var/lib/kubelet/pki/kubelet-server-key.pem >> /var/lib/kubelet/pki/kubelet-server-$(date '+%Y-%m-%d-%H-%M-%S').pem
ln -s /var/lib/kubelet/pki/kubelet-server-$(date '+%Y-%m-%d-%H-%M-%S').pem /var/lib/kubelet/pki/kubelet-server-current.pem
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /var/lib/kubelet/pki/kubelet-server.pem
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
kubelet-server-current Oct 22, 2025 22:06 UTC 364d kubernetes no
Please note: during the Join phase, you cannot choose which certificates to generate — kubeadm creates them all at once, in full.
Certificate generation
kubeadm join phase control-plane-prepare certs \
--config=/var/run/kubeadm/kubeadm.yaml
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [api.my-first-cluster.example.com kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [29.64.0.1 217.114.0.145 31.129.111.153 127.0.0.1]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[certs] Using the existing "sa" key
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
kubelet-server-current Oct 22, 2025 22:06 UTC 364d kubernetes no
K8S-API client > Etcd server
K8S-API client > Etcd server
- HardWay
- Kubeadm
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/apiserver-etcd-client.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[ dn ]
CN = kube-apiserver-etcd-client
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=clientAuth
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/apiserver-etcd-client.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/apiserver-etcd-client.key \
-out /etc/kubernetes/openssl/csr/apiserver-etcd-client.csr \
-config /etc/kubernetes/openssl/apiserver-etcd-client.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-CA /etc/kubernetes/pki/etcd/ca.crt \
-CAkey /etc/kubernetes/pki/etcd/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/apiserver-etcd-client.csr \
-out /etc/kubernetes/pki/apiserver-etcd-client.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/apiserver-etcd-client.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/apiserver-etcd-client.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
apiserver-etcd-client Oct 22, 2025 22:06 UTC 364d etcd-ca no
Please note: during the Join phase, you cannot choose which certificates to generate — kubeadm creates them all at once, in full.
Certificate generation
kubeadm join phase control-plane-prepare certs \
--config=/var/run/kubeadm/kubeadm.yaml
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [api.my-first-cluster.example.com kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [29.64.0.1 217.114.0.145 31.129.111.153 127.0.0.1]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[certs] Using the existing "sa" key
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
apiserver-etcd-client Oct 22, 2025 22:06 UTC 364d etcd-ca no
K8S-API client > Kubelet server
K8S-API client > Kubelet server
- HardWay
- Kubeadm
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/apiserver-kubelet-client.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[ dn ]
CN = kube-apiserver-kubelet-client
O = kubeadm:cluster-admins
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=clientAuth
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/apiserver-kubelet-client.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/apiserver-kubelet-client.key \
-out /etc/kubernetes/openssl/csr/apiserver-kubelet-client.csr \
-config /etc/kubernetes/openssl/apiserver-kubelet-client.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/apiserver-kubelet-client.csr \
-out /etc/kubernetes/pki/apiserver-kubelet-client.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/apiserver-kubelet-client.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/apiserver-kubelet-client.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
apiserver-kubelet-client Oct 22, 2025 22:06 UTC 364d ca no
Please note: during the Join phase, you cannot choose which certificates to generate — kubeadm creates them all at once, in full.
Certificate generation
kubeadm join phase control-plane-prepare certs \
--config=/var/run/kubeadm/kubeadm.yaml
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [api.my-first-cluster.example.com kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [29.64.0.1 217.114.0.145 31.129.111.153 127.0.0.1]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[certs] Using the existing "sa" key
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
apiserver-kubelet-client Oct 22, 2025 22:06 UTC 364d ca no
K8S-API server
K8S-API server
- HardWay
- Kubeadm
Environment variables
export CLUSTER_NAME=my-first-cluster
export BASE_DOMAIN=example.com
export CLUSTER_DOMAIN=cluster.local
export FULL_HOST_NAME=${HOST_NAME}.${CLUSTER_NAME}.${BASE_DOMAIN}
export CLUSTER_API_ENDPOINT=api.my-first-cluster.example.com
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/apiserver.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.${CLUSTER_DOMAIN}
DNS.5 = ${FULL_HOST_NAME}
DNS.6 = ${CLUSTER_API_ENDPOINT}
IP.1 = $(ip -4 addr show scope global | awk '/inet/ {print $2; exit}' | cut -d/ -f1)
IP.2 = 127.0.0.1
[ dn ]
CN = kube-apiserver
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/apiserver.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/apiserver.key \
-out /etc/kubernetes/openssl/csr/apiserver.csr \
-config /etc/kubernetes/openssl/apiserver.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/apiserver.csr \
-out /etc/kubernetes/pki/apiserver.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/apiserver.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/apiserver.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
apiserver Oct 22, 2025 22:06 UTC 364d ca no
Please note: during the Join phase, you cannot choose which certificates to generate — kubeadm creates them all at once, in full.
Certificate generation
kubeadm join phase control-plane-prepare certs \
--config=/var/run/kubeadm/kubeadm.yaml
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [api.my-first-cluster.example.com kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [29.64.0.1 217.114.0.145 31.129.111.153 127.0.0.1]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[certs] Using the existing "sa" key
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
apiserver Oct 22, 2025 22:06 UTC 364d ca no
FrontProxy client > K8S-API
FrontProxy client > K8S-API
- HardWay
- Kubeadm
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/front-proxy-client.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[ dn ]
CN = front-proxy-client
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=clientAuth
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/front-proxy-client.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/front-proxy-client.key \
-out /etc/kubernetes/openssl/csr/front-proxy-client.csr \
-config /etc/kubernetes/openssl/front-proxy-client.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-CA /etc/kubernetes/pki/front-proxy-ca.crt \
-CAkey /etc/kubernetes/pki/front-proxy-ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/front-proxy-client.csr \
-out /etc/kubernetes/pki/front-proxy-client.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/front-proxy-client.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/front-proxy-client.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
front-proxy-client Oct 22, 2025 22:06 UTC 364d front-proxy-ca no
Please note: during the Join phase, you cannot choose which certificates to generate — kubeadm creates them all at once, in full.
Certificate generation
kubeadm join phase control-plane-prepare certs \
--config=/var/run/kubeadm/kubeadm.yaml
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [api.my-first-cluster.example.com kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [29.64.0.1 217.114.0.145 31.129.111.153 127.0.0.1]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[certs] Using the existing "sa" key
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
front-proxy-client Oct 22, 2025 22:06 UTC 364d front-proxy-ca no
Etcd client > Etcd
Etcd client > Etcd
- HardWay
- Kubeadm
Working directory
mkdir -p /etc/kubernetes/pki/etcd
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/healthcheck-client.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[ dn ]
CN = kube-etcd-healthcheck-client
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=clientAuth
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/etcd/healthcheck-client.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/etcd/healthcheck-client.key \
-out /etc/kubernetes/openssl/csr/etcd-client.csr \
-config /etc/kubernetes/openssl/healthcheck-client.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-CA /etc/kubernetes/pki/etcd/ca.crt \
-CAkey /etc/kubernetes/pki/etcd/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/etcd-client.csr \
-out /etc/kubernetes/pki/etcd/healthcheck-client.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/healthcheck-client.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/etcd/healthcheck-client.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
etcd-healthcheck-client Oct 22, 2025 22:06 UTC 364d etcd-ca no
Please note: during the Join phase, you cannot choose which certificates to generate — kubeadm creates them all at once, in full.
Certificate generation
kubeadm join phase control-plane-prepare certs \
--config=/var/run/kubeadm/kubeadm.yaml
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [api.my-first-cluster.example.com kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [29.64.0.1 217.114.0.145 31.129.111.153 127.0.0.1]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[certs] Using the existing "sa" key
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
etcd-healthcheck-client Oct 22, 2025 22:06 UTC 364d etcd-ca no
Etcd server
Etcd server
- HardWay
- Kubeadm
Environment variables
export CLUSTER_NAME=my-first-cluster
export BASE_DOMAIN=example.com
export FULL_HOST_NAME=${HOST_NAME}.${CLUSTER_NAME}.${BASE_DOMAIN}
export MACHINE_LOCAL_ADDRESS=$(ip -4 addr show scope global | awk '/inet/ {print $2; exit}' | cut -d/ -f1)
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/etcd-server.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = localhost
DNS.2 = ${HOST_NAME}
DNS.3 = ${FULL_HOST_NAME}
IP.1 = 127.0.0.1
IP.2 = 0:0:0:0:0:0:0:1
IP.3 = ${MACHINE_LOCAL_ADDRESS}
[ dn ]
CN = ${FULL_HOST_NAME}
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth,clientAuth
subjectAltName=@alt_names
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/etcd/server.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/etcd/server.key \
-out /etc/kubernetes/openssl/csr/etcd-server.csr \
-config /etc/kubernetes/openssl/etcd-server.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-CA /etc/kubernetes/pki/etcd/ca.crt \
-CAkey /etc/kubernetes/pki/etcd/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/etcd-server.csr \
-out /etc/kubernetes/pki/etcd/server.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/etcd-server.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/etcd/server.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
etcd-server Oct 22, 2025 22:06 UTC 364d etcd-ca no
Please note: during the Join phase, you cannot choose which certificates to generate — kubeadm creates them all at once, in full.
Certificate generation
kubeadm join phase control-plane-prepare certs \
--config=/var/run/kubeadm/kubeadm.yaml
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [api.my-first-cluster.example.com kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [29.64.0.1 217.114.0.145 31.129.111.153 127.0.0.1]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[certs] Using the existing "sa" key
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
etcd-server Oct 22, 2025 22:06 UTC 364d etcd-ca no
Etcd peer > Etcd
Etcd peer > Etcd
- HardWay
- Kubeadm
Environment variables
export CLUSTER_NAME=my-first-cluster
export FULL_HOST_NAME=${HOST_NAME}.${CLUSTER_NAME}.${BASE_DOMAIN}
export MACHINE_LOCAL_ADDRESS=$(ip -4 addr show scope global | awk '/inet/ {print $2; exit}' | cut -d/ -f1)
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/etcd-peer.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = localhost
DNS.2 = ${HOST_NAME}
DNS.3 = ${FULL_HOST_NAME}
IP.1 = 127.0.0.1
IP.2 = 0:0:0:0:0:0:0:1
IP.3 = ${MACHINE_LOCAL_ADDRESS}
[ dn ]
CN = ${FULL_HOST_NAME}
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth,clientAuth
subjectAltName=@alt_names
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/etcd/peer.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/etcd/peer.key \
-out /etc/kubernetes/openssl/csr/etcd-peer.csr \
-config /etc/kubernetes/openssl/etcd-peer.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-CA /etc/kubernetes/pki/etcd/ca.crt \
-CAkey /etc/kubernetes/pki/etcd/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/etcd-peer.csr \
-out /etc/kubernetes/pki/etcd/peer.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/etcd-peer.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/etcd/peer.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
etcd-peer Oct 22, 2025 22:06 UTC 364d etcd-ca no
Please note: during the Join phase, you cannot choose which certificates to generate — kubeadm creates them all at once, in full.
Certificate generation
kubeadm join phase control-plane-prepare certs \
--config=/var/run/kubeadm/kubeadm.yaml
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost master-1.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [217.114.0.145 127.0.0.1 ::1 31.129.111.153]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [api.my-first-cluster.example.com kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.my-first-cluster.example.com master-3.my-first-cluster.example.com] and IPs [29.64.0.1 217.114.0.145 31.129.111.153 127.0.0.1]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[certs] Using the existing "sa" key
Certificate readiness check
kubeadm certs check-expiration
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
etcd-peer Oct 22, 2025 22:06 UTC 364d etcd-ca no
Controller server
Controller server
- HardWay
- Kubeadm
Environment variables
export MACHINE_LOCAL_ADDRESS=$(ip -4 addr show scope global | awk '/inet/ {print $2; exit}' | cut -d/ -f1)
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/controller-manager-server.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = kube-controller-manager
DNS.2 = kube-controller-manager.kube-system
DNS.3 = kube-controller-manager.kube-system.svc
IP.1 = 127.0.0.1
IP.2 = 0:0:0:0:0:0:0:1
IP.3 = ${MACHINE_LOCAL_ADDRESS}
[ dn ]
CN = "system:kube-controller-manager-server"
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/controller-manager-server.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/controller-manager-server.key \
-out /etc/kubernetes/openssl/csr/controller-manager-server.csr \
-config /etc/kubernetes/openssl/controller-manager-server.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-outform PEM \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/controller-manager-server.csr \
-out /etc/kubernetes/pki/controller-manager-server.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/controller-manager-server.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/controller-manager-server.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
controller-manager-server Oct 22, 2025 22:06 UTC 364d kubernetes no
Please note that kubeadm does not manage these certificates. Use HardWay mode
Scheduler server
Scheduler server
- HardWay
- Kubeadm
Environment variables
export MACHINE_LOCAL_ADDRESS=$(ip -4 addr show scope global | awk '/inet/ {print $2; exit}' | cut -d/ -f1)
Working directory
mkdir -p /etc/kubernetes/pki
mkdir -p /etc/kubernetes/openssl/csr
Configuration
cat <<EOF > /etc/kubernetes/openssl/scheduler-server.conf
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_ext
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = kube-scheduler
DNS.2 = kube-scheduler.kube-system
DNS.3 = kube-scheduler.kube-system.svc
IP.1 = 127.0.0.1
IP.2 = 0:0:0:0:0:0:0:1
IP.3 = ${MACHINE_LOCAL_ADDRESS}
[ dn ]
CN = "system:kube-scheduler-server"
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
EOF
Private key generation
openssl genrsa \
-out /etc/kubernetes/pki/scheduler-server.key 2048
CSR generation
openssl req \
-new \
-key /etc/kubernetes/pki/scheduler-server.key \
-out /etc/kubernetes/openssl/csr/scheduler-server.csr \
-config /etc/kubernetes/openssl/scheduler-server.conf
CSR signing
openssl x509 \
-req \
-days 365 \
-sha256 \
-outform PEM \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-in /etc/kubernetes/openssl/csr/scheduler-server.csr \
-out /etc/kubernetes/pki/scheduler-server.crt \
-extensions v3_ext \
-extfile /etc/kubernetes/openssl/scheduler-server.conf
Certificate readiness check
/etc/kubernetes/openssl/cert-report.sh /etc/kubernetes/pki/scheduler-server.crt
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
scheduler-server Oct 22, 2025 22:06 UTC 364d kubernetes no
Please note that kubeadm does not manage these certificates. Use HardWay mode