Kubernetes the hard way on bare metal/VMs — Install CloudFlare’s PKI Toolkit and generate TLS certs
Part of the Kubernetes the hard way on bare metal/VM
--
Introduction
This guide is part of the Kubernetes the hard way on bare metal/VMs series. On its own this may be useful to you however since it’s tailored for the series, it may not be completely suited to your needs.
You’re using CloudFlare’s PKI toolkit for the generation of the certificate authority and for generating the TLS certs that the cluster services and users will use to interact with the cluster. As always other options such as openSSL can be used.
Install cfssl
wget -q --show-progress --https-only --timestamping https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64chmod +x cfssl_linux-amd64 cfssljson_linux-amd64
sudo mv cfssl_linux-amd64 /usr/local/bin/cfssl
sudo mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
Provisioning CA
Create a few directories for the TLS certs to live in.
mkdir -p pki/{admin,api,ca,clients,controller,proxy,scheduler,service-account}
To generate the TLS certificates, you’ll need some configurations files; you’ll create each one as you generate the TLS cert.
Don’t just copy and paste the small section below as you will need to change the content of the environment variables below. They’ll be used in the configs to generate the TLS certs.
TLS_C="GB"
TLS_L="TOWN"
TLS_OU="DeeToTheVee Kubernetes"
TLS_ST="CITY"
Generate the CA (Certificate Authority) config files & certificates
cat > pki/ca/ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"kubernetes": {
"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "8760h"
}
}
}
}
EOFcat > pki/ca/ca-csr.json <<EOF
{
"CN": "Kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "${TLS_C}",
"L": "${TLS_L}",
"O": "Kubernetes",
"OU": "${TLS_OU}",
"ST": "${TLS_ST}"
}
]
}
EOFcfssl gencert -initca pki/ca/ca-csr.json | cfssljson -bare pki/ca/ca
Generating TLS Certificates
Generate the admin user config files and certificates
cat > pki/admin/admin-csr.json <<EOF
{
"CN": "admin",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "${TLS_C}",
"L": "${TLS_L}",
"O": "system:masters",
"OU": "${TLS_OU}",
"ST": "${TLS_ST}"
}
]
}
EOFcfssl gencert \
-ca=pki/ca/ca.pem \
-ca-key=pki/ca/ca-key.pem \
-config=pki/ca/ca-config.json \
-profile=kubernetes \
pki/admin/admin-csr.json | cfssljson -bare pki/admin/admin
Generate the worker(s) certs and keys
You can get your EXTERNAL_IP by running this from each worker node. This will force IPv4. If you want to use and have IPv6 then remove -4
curl -s -4 https://ifconfig.co/
For the INTERNAL_IP, you need to change the line with the result of running the following on each worker node (change ens3 if required):
ip addr show ens3 | grep -Po 'inet \K[\d.]+'
If you’re running on a single node or reduced worker nodes, adjust the for loop as appropriate.
NOTE: You will actually need to run the loop manually to ensure you fill out the correct EXTERNAL and INTERNAL IPs —copy and past the loop internals and adjust as required.
for instance in worker-0 worker-1 worker-2; do
cat > pki/clients/${instance}-csr.json <<EOF
{
"CN": "system:node:${instance}",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "${TLS_C}",
"L": "${TLS_L}",
"O": "system:nodes",
"OU": "${TLS_OU}",
"ST": "${TLS_ST}"
}
]
}
EOFEXTERNAL_IP=$(curl -s -4 https://ifconfig.co)
INTERNAL_IP=$(ip addr show ens3 | grep -Po 'inet \K[\d.]+')cfssl gencert \
-ca=pki/ca/ca.pem \
-ca-key=pki/ca/ca-key.pem \
-config=pki/ca/ca-config.json \
-hostname=${instance},${INTERNAL_IP},${EXTERNAL_IP} \
-profile=kubernetes \
pki/clients/${instance}-csr.json | cfssljson -bare pki/clients/${instance}done
Generate the kube-controller-manager cert and key
cat > pki/controller/kube-controller-manager-csr.json <<EOF
{
"CN": "system:kube-controller-manager",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "${TLS_C}",
"L": "${TLS_L}",
"O": "system:kube-controller-manager",
"OU": "${TLS_OU}",
"ST": "${TLS_ST}"
}
]
}
EOFcfssl gencert \
-ca=pki/ca/ca.pem \
-ca-key=pki/ca/ca-key.pem \
-config=pki/ca/ca-config.json \
-profile=kubernetes \
pki/controller/kube-controller-manager-csr.json | cfssljson -bare pki/controller/kube-controller-manager
Generate the kube-proxy cert and key
cat > pki/proxy/kube-proxy-csr.json <<EOF
{
"CN": "system:kube-proxy",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "${TLS_C}",
"L": "${TLS_L}",
"O": "system:node-proxier",
"OU": "${TLS_OU}",
"ST": "${TLS_ST}"
}
]
}
EOFcfssl gencert \
-ca=pki/ca/ca.pem \
-ca-key=pki/ca/ca-key.pem \
-config=pki/ca/ca-config.json \
-profile=kubernetes \
pki/proxy/kube-proxy-csr.json | cfssljson -bare pki/proxy/kube-proxy
Generate the scheduler cert and key
cat > pki/scheduler/kube-scheduler-csr.json <<EOF
{
"CN": "system:kube-scheduler",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "${TLS_C}",
"L": "${TLS_L}",
"O": "system:kube-scheduler",
"OU": "${TLS_OU}",
"ST": "${TLS_ST}"
}
]
}
EOFcfssl gencert \
-ca=pki/ca/ca.pem \
-ca-key=pki/ca/ca-key.pem \
-config=pki/ca/ca-config.json \
-profile=kubernetes \
pki/scheduler/kube-scheduler-csr.json | cfssljson -bare pki/scheduler/kube-scheduler
Generate the api-server cert and key
The KUBERNETES_PUBLIC_ADDRESS will be the IP/VIP/Pool IP of the load balancer that will direct all traffic to the controller nodes. In our case it’s 192.168.0.210.
NOTE: The — ‘hostname=’ line may need adjusting if you have different IPs for your controllers.
KUBERNETES_PUBLIC_ADDRESS=192.168.0.210cat > pki/api/kubernetes-csr.json <<EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "${TLS_C}",
"L": "${TLS_L}",
"O": "Kubernetes",
"OU": "${TLS_OU}",
"ST": "${TLS_ST}"
}
]
}
EOFcfssl gencert \
-ca=pki/ca/ca.pem \
-ca-key=pki/ca/ca-key.pem \
-config=pki/ca/ca-config.json \
-hostname=10.32.0.1,192.168.0.110,192.168.0.111,192.168.0.112,${KUBERNETES_PUBLIC_ADDRESS},127.0.0.1,kubernetes.default \
-profile=kubernetes \
pki/api/kubernetes-csr.json | cfssljson -bare pki/api/kubernetes
Generate the service-account cert and key
cat > pki/service-account/service-account-csr.json <<EOF
{
"CN": "service-accounts",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "${TLS_C}",
"L": "${TLS_L}",
"O": "Kubernetes",
"OU": "${TLS_OU}",
"ST": "${TLS_ST}"
}
]
}
EOFcfssl gencert \
-ca=pki/ca/ca.pem \
-ca-key=pki/ca/ca-key.pem \
-config=pki/ca/ca-config.json \
-profile=kubernetes \
pki/service-account/service-account-csr.json | cfssljson -bare pki/service-account/service-account
Finally, lets move the certs
Copy the files to the controllers and workers as shown below.
If you’re on a single node then simply copy all files listed below for both controllers & workers to the single node.
for instance in worker-0 worker-1 worker-2; do
scp pki/ca/ca.pem pki/clients/${instance}-key.pem pki/clients/${instance}.pem ${instance}:~/
done
for instance in controller-0 controller-1 controller-2; do
scp pki/ca/ca.pem pki/ca/ca-key.pem pki/api/kubernetes-key.pem pki/api/kubernetes.pem pki/service-account/service-account-key.pem pki/service-account/service-account.pem ${instance}:~/
done
Conclusion
You’ve generated all of the certificates required for the kubernetes cluster to work.