2017-08-28 14:19:25 -07:00
# Provisioning a CA and Generating TLS Certificates
2018-05-12 16:54:18 +00:00
In this lab you will provision a [PKI Infrastructure ](https://en.wikipedia.org/wiki/Public_key_infrastructure ) using CloudFlare's PKI toolkit, [cfssl ](https://github.com/cloudflare/cfssl ), then use it to bootstrap a Certificate Authority, and generate TLS certificates for the following components: etcd, kube-apiserver, kube-controller-manager, kube-scheduler, kubelet, and kube-proxy.
2017-08-28 14:19:25 -07:00
## Certificate Authority
In this section you will provision a Certificate Authority that can be used to generate additional TLS certificates.
2018-05-12 16:54:18 +00:00
Generate the CA configuration file, certificate, and private key:
2017-08-28 14:19:25 -07:00
2019-08-03 12:03:53 +08:00
```sh
2018-05-12 16:54:18 +00:00
{
2017-08-28 14:19:25 -07:00
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": "US",
"L": "Portland",
"O": "Kubernetes",
"OU": "CA",
"ST": "Oregon"
}
]
}
EOF
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
2018-05-12 16:54:18 +00:00
}
2017-08-28 14:19:25 -07:00
```
Results:
```
2019-08-03 12:03:53 +08:00
$ ls -p | grep -v /
ca-config.json
ca-csr.json
2017-08-28 14:19:25 -07:00
ca-key.pem
2019-08-03 12:03:53 +08:00
ca.csr
2017-08-28 14:19:25 -07:00
ca.pem
```
## Client and Server Certificates
In this section you will generate client and server certificates for each Kubernetes component and a client certificate for the Kubernetes `admin` user.
### The Admin Client Certificate
2018-05-12 16:54:18 +00:00
Generate the `admin` client certificate and private key:
2017-08-28 14:19:25 -07:00
2019-08-03 12:03:53 +08:00
```sh
2018-05-12 16:54:18 +00:00
{
2017-08-28 14:19:25 -07:00
cat > admin-csr.json < < EOF
{
"CN": "admin",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:masters",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
admin-csr.json | cfssljson -bare admin
2018-05-12 16:54:18 +00:00
}
2017-08-28 14:19:25 -07:00
```
Results:
```
2019-08-03 12:03:53 +08:00
admin-csr.json
2017-08-28 14:19:25 -07:00
admin-key.pem
2019-08-03 12:03:53 +08:00
admin.csr
2017-08-28 14:19:25 -07:00
admin.pem
```
### The Kubelet Client Certificates
2019-08-03 12:03:53 +08:00
Kubernetes uses a **special-purpose authorization mode** called [Node Authorizer ](https://kubernetes.io/docs/admin/authorization/node/ ), that specifically authorizes API requests made by [Kubelets ](https://kubernetes.io/docs/concepts/overview/components/#kubelet ). In order to be authorized by the Node Authorizer, Kubelets must use a credential that identifies them as being in the `system:nodes` group, with a username of `system:node:<nodeName>` . In this section you will create a certificate for each Kubernetes worker node that meets the Node Authorizer requirements.
2017-08-28 14:19:25 -07:00
Generate a certificate and private key for each Kubernetes worker node:
2019-08-03 12:03:53 +08:00
```sh
2017-08-28 14:19:25 -07:00
for instance in worker-0 worker-1 worker-2; do
2019-08-03 12:03:53 +08:00
cat > ${instance}-csr.json < < EOF
2017-08-28 14:19:25 -07:00
{
"CN": "system:node:${instance}",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:nodes",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
2019-08-03 12:03:53 +08:00
EXTERNAL_IP=$(gcloud compute instances describe ${instance} \
--format 'value(networkInterfaces[0].accessConfigs[0].natIP)')
2017-08-28 14:19:25 -07:00
2019-08-03 12:03:53 +08:00
INTERNAL_IP=$(gcloud compute instances describe ${instance} \
--format 'value(networkInterfaces[0].networkIP)')
2017-08-28 14:19:25 -07:00
2019-08-03 12:03:53 +08:00
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-hostname=${instance},${EXTERNAL_IP},${INTERNAL_IP} \
-profile=kubernetes \
${instance}-csr.json | cfssljson -bare ${instance}
2017-08-28 14:19:25 -07:00
done
```
Results:
```
2019-08-03 12:03:53 +08:00
worker-0-csr.json
2017-08-28 14:19:25 -07:00
worker-0-key.pem
2019-08-03 12:03:53 +08:00
worker-0.csr
2017-08-28 14:19:25 -07:00
worker-0.pem
2019-08-03 12:03:53 +08:00
worker-1-csr.json
2017-08-28 14:19:25 -07:00
worker-1-key.pem
2019-08-03 12:03:53 +08:00
worker-1.csr
2017-08-28 14:19:25 -07:00
worker-1.pem
2019-08-03 12:03:53 +08:00
worker-2-csr.json
2017-08-28 14:19:25 -07:00
worker-2-key.pem
2019-08-03 12:03:53 +08:00
worker-2.csr
2017-08-28 14:19:25 -07:00
worker-2.pem
```
2018-05-12 16:54:18 +00:00
### The Controller Manager Client Certificate
2017-08-28 14:19:25 -07:00
2018-05-12 16:54:18 +00:00
Generate the `kube-controller-manager` client certificate and private key:
2017-08-28 14:19:25 -07:00
2019-08-03 12:03:53 +08:00
```sh
2017-08-28 14:19:25 -07:00
{
2018-05-12 16:54:18 +00:00
2019-08-03 12:03:53 +08:00
cat > kube-controller-manager-csr.json < < EOF
2018-05-12 16:54:18 +00:00
{
"CN": "system:kube-controller-manager",
2017-08-28 14:19:25 -07:00
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
2018-05-12 16:54:18 +00:00
"O": "system:kube-controller-manager",
2017-08-28 14:19:25 -07:00
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
2018-05-12 16:54:18 +00:00
2019-08-03 12:03:53 +08:00
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
2018-05-12 16:54:18 +00:00
}
```
Results:
```
2019-08-03 12:03:53 +08:00
kube-controller-manager-csr.json
2018-05-12 16:54:18 +00:00
kube-controller-manager-key.pem
2019-08-03 12:03:53 +08:00
kube-controller-manager.csr
2018-05-12 16:54:18 +00:00
kube-controller-manager.pem
2017-08-28 14:19:25 -07:00
```
2018-05-12 16:54:18 +00:00
### The Kube Proxy Client Certificate
2017-08-28 14:19:25 -07:00
Generate the `kube-proxy` client certificate and private key:
2019-08-03 12:03:53 +08:00
```sh
2018-05-12 16:54:18 +00:00
{
2019-08-03 12:03:53 +08:00
cat > kube-proxy-csr.json < < EOF
2018-05-12 16:54:18 +00:00
{
"CN": "system:kube-proxy",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:node-proxier",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
2019-08-03 12:03:53 +08:00
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
kube-proxy-csr.json | cfssljson -bare kube-proxy
2018-05-12 16:54:18 +00:00
}
2017-08-28 14:19:25 -07:00
```
Results:
```
2019-08-03 12:03:53 +08:00
kube-proxy-csr.json
2017-08-28 14:19:25 -07:00
kube-proxy-key.pem
2019-08-03 12:03:53 +08:00
kube-proxy.csr
2017-08-28 14:19:25 -07:00
kube-proxy.pem
```
2018-05-12 16:54:18 +00:00
### The Scheduler Client Certificate
Generate the `kube-scheduler` client certificate and private key:
2019-08-03 12:03:53 +08:00
```sh
2018-05-12 16:54:18 +00:00
{
2019-08-03 12:03:53 +08:00
cat > kube-scheduler-csr.json < < EOF
2018-05-12 16:54:18 +00:00
{
"CN": "system:kube-scheduler",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "system:kube-scheduler",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
2019-08-03 12:03:53 +08:00
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
kube-scheduler-csr.json | cfssljson -bare kube-scheduler
2018-05-12 16:54:18 +00:00
}
```
Results:
```
2019-08-03 12:03:53 +08:00
kube-scheduler-csr.json
2018-05-12 16:54:18 +00:00
kube-scheduler-key.pem
2019-08-03 12:03:53 +08:00
kube-scheduler.csr
2018-05-12 16:54:18 +00:00
kube-scheduler.pem
```
2017-08-28 14:19:25 -07:00
### The Kubernetes API Server Certificate
The `kubernetes-the-hard-way` static IP address will be included in the list of subject alternative names for the Kubernetes API Server certificate. This will ensure the certificate can be validated by remote clients.
2018-05-12 16:54:18 +00:00
Generate the Kubernetes API Server certificate and private key:
2017-08-28 14:19:25 -07:00
2019-08-03 12:03:53 +08:00
```sh
2018-05-12 16:54:18 +00:00
{
2019-08-03 12:03:53 +08:00
KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
--region $(gcloud config get-value compute/region) \
--format 'value(address)')
2017-08-28 14:19:25 -07:00
2019-08-03 12:03:53 +08:00
cat > kubernetes-csr.json < < EOF
2017-08-28 14:19:25 -07:00
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "Kubernetes",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
2019-08-03 12:03:53 +08:00
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-hostname=10.32.0.1,10.240.0.10,10.240.0.11,10.240.0.12,${KUBERNETES_PUBLIC_ADDRESS},127.0.0.1,kubernetes.default \
-profile=kubernetes \
kubernetes-csr.json | cfssljson -bare kubernetes
2018-05-12 16:54:18 +00:00
}
2017-08-28 14:19:25 -07:00
```
Results:
```
2019-08-03 12:03:53 +08:00
kubernetes-csr.json
2017-08-28 14:19:25 -07:00
kubernetes-key.pem
2019-08-03 12:03:53 +08:00
kubernetes.csr
2017-08-28 14:19:25 -07:00
kubernetes.pem
```
2018-05-12 16:54:18 +00:00
## The Service Account Key Pair
The Kubernetes Controller Manager leverages a key pair to generate and sign service account tokens as describe in the [managing service accounts ](https://kubernetes.io/docs/admin/service-accounts-admin/ ) documentation.
Generate the `service-account` certificate and private key:
2019-08-03 12:03:53 +08:00
```sh
2018-05-12 16:54:18 +00:00
{
2019-08-03 12:03:53 +08:00
cat > service-account-csr.json < < EOF
2018-05-12 16:54:18 +00:00
{
"CN": "service-accounts",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "Portland",
"O": "Kubernetes",
"OU": "Kubernetes The Hard Way",
"ST": "Oregon"
}
]
}
EOF
2019-08-03 12:03:53 +08:00
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
service-account-csr.json | cfssljson -bare service-account
2018-05-12 16:54:18 +00:00
}
```
Results:
```
2019-08-03 12:03:53 +08:00
service-account-csr.json
2018-05-12 16:54:18 +00:00
service-account-key.pem
2019-08-03 12:03:53 +08:00
service-account.csr
2018-05-12 16:54:18 +00:00
service-account.pem
```
2017-08-28 14:19:25 -07:00
## Distribute the Client and Server Certificates
Copy the appropriate certificates and private keys to each worker instance:
2019-08-03 12:03:53 +08:00
- ca.pem
- worker-X.pem & worker-X-key.pem
2017-08-28 14:19:25 -07:00
2019-08-03 12:03:53 +08:00
```sh
2017-08-28 14:19:25 -07:00
for instance in worker-0 worker-1 worker-2; do
gcloud compute scp ca.pem ${instance}-key.pem ${instance}.pem ${instance}:~/
done
```
Copy the appropriate certificates and private keys to each controller instance:
2019-08-03 12:03:53 +08:00
- ca.pem & ca-key.pem
- kubernetes-key.pem & kubernetes.pem
- service-account-key.pem & service-account.pem
2017-08-28 14:19:25 -07:00
2019-08-03 12:03:53 +08:00
```sh
2017-08-28 14:19:25 -07:00
for instance in controller-0 controller-1 controller-2; do
2018-05-12 16:54:18 +00:00
gcloud compute scp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \
service-account-key.pem service-account.pem ${instance}:~/
2017-08-28 14:19:25 -07:00
done
```
2018-05-12 16:54:18 +00:00
> The `kube-proxy`, `kube-controller-manager`, `kube-scheduler`, and `kubelet` client certificates will be used to generate client authentication configuration files in the next lab.
2017-08-28 14:19:25 -07:00
Next: [Generating Kubernetes Configuration Files for Authentication ](05-kubernetes-configuration-files.md )