Photo by Maximilian Weisbecker on Unsplash

by Alexander Kirillov

Hi! This is the second article from the series about installing Kubernetes from binaries. In this step we are going to configure certificates for master, workers and etcd nodes. Please, don’t forget to refer to our previous article to consult about cluster requirements and variables.

All steps described below can be performed on your host machine or on any other machine with the ssh access to all your nodes

To generate the certificates we’ll be using cfssl and cfssl json, so if they are not already installed on your machine, let’s do it now.

Installing cfssl and cfssljson

Download and install the binaries from the official repositories:



chmod +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 curl -OL https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -OL https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 chmod +x cfssl_linux-amd64 cfssljson_linux-amd64sudo mv cfssl_linux-amd64 /usr/local/bin/cfsslsudo mv cfssljson_linux-amd64 /usr/local/bin/cfssljson

Make sure that cfssl version is 1.2.0 or higher:

cfssl version

Note: cfssljson cannot print version to the command line.

Creating a CA

Create a configuration file and a private key for CA:

cat > ca-config.json <<EOF

{

"signing": {

"default": {

"expiry": "8760h"

},

"profiles": {

"kubernetes": {

"usages": ["signing", "key encipherment", "server auth", "client auth"],

"expiry": "8760h"

}

}

}

}

EOF cat > ca-csr.json <<EOF

{

"CN": "Kubernetes",

"key": {

"algo": "rsa",

"size": 2048

},

"names": [

{

"C": "LV",

"L": "Riga",

"O": "Kubernetes",

"OU": "CA"

}

]

}

EOF cfssl gencert -initca ca-csr.json | cfssljson -bare ca

Client and server certificates

Create certificates for each Kubernetes component and a client certificate for admin user:

cat > admin-csr.json <<EOF

{

"CN": "admin",

"key": {

"algo": "rsa",

"size": 2048

},

"names": [

{

"C": "LV",

"L": "Riga",

"O": "system:masters",

"OU": "Containerum"

}

]

}

EOF cfssl gencert \

-ca=ca.pem \

-ca-key=ca-key.pem \

-config=ca-config.json \

-profile=kubernetes \

admin-csr.json | cfssljson -bare admin

Generate a certificate for Kube Controller Manager

Generate a certificate:

cat > kube-controller-manager-csr.json <<EOF

{

"CN": "system:kube-controller-manager",

"key": {

"algo": "rsa",

"size": 2048

},

"names": [

{

"C": "LV",

"L": "Riga",

"O": "system:kube-controller-manager",

"OU": "Containerum"

}

]

}

EOF cfssl gencert \

-ca=ca.pem \

-ca-key=ca-key.pem \

-config=ca-config.json \

-profile=kubernetes \

kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager

Generate a certificate for Kube Scheduler

Generate a certificate:

cat > kube-scheduler-csr.json <<EOF

{

"CN": "system:kube-scheduler",

"key": {

"algo": "rsa",

"size": 2048

},

"names": [

{

"C": "LV",

"L": "Riga",

"O": "system:kube-scheduler",

"OU": "Containerum"

}

]

}

EOF cfssl gencert \

-ca=ca.pem \

-ca-key=ca-key.pem \

-config=ca-config.json \

-profile=kubernetes \

kube-scheduler-csr.json | cfssljson -bare kube-scheduler

Generate a certificate for Kube API Server

To generate a certificate provide a static IP address to the list of domain names for Kubernetes API Server certificates. This will ensure the certificate can be validated by remote clients.

10.96.0.1 is an IP address of Kubernetes API server instance in Cluster CIDR.

MASTER_IP=${PUBLIC_IP}

cat > kubernetes-csr.json <<EOF

{

"CN": "kubernetes",

"key": {

"algo": "rsa",

"size": 2048

},

"names": [

{

"C": "LV",

"L": "Riga",

"O": "Kubernetes",

"OU": "Containerum"

}

]

}

EOF cfssl gencert \

-ca=ca.pem \

-ca-key=ca-key.pem \

-config=ca-config.json \

-hostname=10.96.0.1,${MASTER_IP},127.0.0.1,kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster.local \

-profile=kubernetes \

kubernetes-csr.json | cfssljson -bare kubernetes

Generate a certificate for etcd

To generate a certificate provide a static IP address to the list of domain names for etcd certificates.

ETCD_NODE_1_IP , ETCD_NODE_2_IP , ETCD_NODE_3_IP are IP addresses of instances in the internal network, on which etcd has been installed. They will be used for communication with other cluster peers and to serve client requests.

Generate a certificate:

cat > etcd-csr.json <<EOF

{

"CN": "ETCD",

"key": {

"algo": "rsa",

"size": 2048

},

"names": [

{

"C": "LV",

"L": "Riga",

"O": "ETCD",

"OU": "Containerum"

}

]

}

EOF cfssl gencert \

-ca=ca.pem \

-ca-key=ca-key.pem \

-config=ca-config.json \

-hostname=${ETCD_NODE_1_IP},${ETCD_NODE_2_IP},${ETCD_NODE_3_IP},127.0.0.1 \

-profile=kubernetes \

etcd-csr.json | cfssljson -bare etcd

The service account key pair

Kubernetes Controller Manager uses a key pair to create and sign tokens for the service account.

Run the script:

cat > service-account-csr.json <<EOF

{

"CN": "service-accounts",

"key": {

"algo": "rsa",

"size": 2048

},

"names": [

{

"C": "LV",

"L": "Riga",

"O": "Kubernetes",

"OU": "Сontainerum"

}

]

}

EOF cfssl gencert \

-ca=ca.pem \

-ca-key=ca-key.pem \

-config=ca-config.json \

-profile=kubernetes \

service-account-csr.json | cfssljson -bare service-account

Generate certificates for Kubelet

Kubernetes uses a special mode of authorization, Node Authorizer, which also authorizes requests from Kubelet to API. To authorize with Node Authorizer, Kubelet uses the credentials from the system:nodes group and the system:node:${HOSTNAME} username. Create a certificate for each worker node to meet the Node Authorizer requirements.

Set the external and internal IP in EXTERNAL_IP and INTERNAL_IP correspondingly. If you don’t have a private network, you may use only EXTERNAL_IP . ${HOSTNAME} is the hostname of the worker node, for which a certificate is to be generated.

cat > ${HOSTNAME}-csr.json <<EOF

{

"CN": "system:node:${HOSTNAME}",

"key": {

"algo": "rsa",

"size": 2048

},

"names": [

{

"C": "LV",

"L": "Riga",

"O": "system:nodes",

"OU": "Containerum"

}

]

}

EOF cfssl gencert \

-ca=ca.pem \

-ca-key=ca-key.pem \

-config=ca-config.json \

-hostname=${HOSTNAME},${EXTERNAL_IP},${INTERNAL_IP} \

-profile=kubernetes \

${HOSTNAME}-csr.json | cfssljson -bare ${HOSTNAME}

Generate a certificate for Kube Proxy

Generate a certificate:

cat > kube-proxy-csr.json <<EOF

{

"CN": "system:kube-proxy",

"key": {

"algo": "rsa",

"size": 2048

},

"names": [

{

"C": "LV",

"L": "Riga",

"O": "system:node-proxier",

"OU": "Containerum"

}

]

}

EOF cfssl gencert \

-ca=ca.pem \

-ca-key=ca-key.pem \

-config=ca-config.json \

-profile=kubernetes \

kube-proxy-csr.json | cfssljson -bare kube-proxy

Distribution of certificates for clients and servers

If you used cfssl to generate the certificates, apply the naming scheme to the certificate files. This scheme will be used throughout the installation series.

for f in *-key.pem; do mv -vi "$f" "${f%-key.pem}.key"; done

for f in *.pem; do mv -vi "$f" "${f%.pem}.crt"; done

Copy the appropriate certificates and the private key to each controller:

for instance in master-1 master-2 master-3; do

scp ca.crt ca.key kubernetes.key kubernetes.crt \

service-account.key service-account.crt etcd.key etcd.cert ${instance}:~/

done

Copy the appropriate certificates and the private key to each worker node:

for instance in worker-1 worker-2 worker-3; do

scp ca.crt ${instance}.crt ${instance}.key ${instance}:~/

done

The kube-proxy, kube-controller-manager, kube-scheduler, and kubelet client certificates will be used to generate client authentication configuration files in the next article. Done! In the next article we will create kubeconfig files.

Thanks for reading! Leave your feedback and ask questions, we’ll be glad to help!

Also don’t forget to follow us on Twitter and join our Telegram chat to stay tuned! You might also want to check our Containerum project on GitHub. We need you feedback to make it stronger — you can submit an issue, or just support the project by giving it a ⭐. Your support really matters to us!