Provisioning a CA and Generating TLS Certificates

In this lab you will provision a PKI Infrastructure using CloudFlare’s PKI toolkit, 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.

Certificate Authority

In this section you will provision a Certificate Authority that can be used to generate additional TLS certificates.

Generate the CA configuration file, certificate, and private key:

  1. {
  2. cat > ca-config.json <<EOF
  3. {
  4. "signing": {
  5. "default": {
  6. "expiry": "8760h"
  7. },
  8. "profiles": {
  9. "kubernetes": {
  10. "usages": ["signing", "key encipherment", "server auth", "client auth"],
  11. "expiry": "8760h"
  12. }
  13. }
  14. }
  15. }
  16. EOF
  17. cat > ca-csr.json <<EOF
  18. {
  19. "CN": "Kubernetes",
  20. "key": {
  21. "algo": "rsa",
  22. "size": 2048
  23. },
  24. "names": [
  25. {
  26. "C": "US",
  27. "L": "Portland",
  28. "O": "Kubernetes",
  29. "OU": "CA",
  30. "ST": "Oregon"
  31. }
  32. ]
  33. }
  34. EOF
  35. cfssl gencert -initca ca-csr.json | cfssljson -bare ca
  36. }

Results:

  1. ca-key.pem
  2. 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

Generate the admin client certificate and private key:

  1. {
  2. cat > admin-csr.json <<EOF
  3. {
  4. "CN": "admin",
  5. "key": {
  6. "algo": "rsa",
  7. "size": 2048
  8. },
  9. "names": [
  10. {
  11. "C": "US",
  12. "L": "Portland",
  13. "O": "system:masters",
  14. "OU": "Kubernetes The Hard Way",
  15. "ST": "Oregon"
  16. }
  17. ]
  18. }
  19. EOF
  20. cfssl gencert \
  21. -ca=ca.pem \
  22. -ca-key=ca-key.pem \
  23. -config=ca-config.json \
  24. -profile=kubernetes \
  25. admin-csr.json | cfssljson -bare admin
  26. }

Results:

  1. admin-key.pem
  2. admin.pem

The Kubelet Client Certificates

Kubernetes uses a special-purpose authorization mode called Node Authorizer, that specifically authorizes API requests made by Kubelets. 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.

Generate a certificate and private key for each Kubernetes worker node:

  1. for instance in worker-0 worker-1 worker-2; do
  2. cat > ${instance}-csr.json <<EOF
  3. {
  4. "CN": "system:node:${instance}",
  5. "key": {
  6. "algo": "rsa",
  7. "size": 2048
  8. },
  9. "names": [
  10. {
  11. "C": "US",
  12. "L": "Portland",
  13. "O": "system:nodes",
  14. "OU": "Kubernetes The Hard Way",
  15. "ST": "Oregon"
  16. }
  17. ]
  18. }
  19. EOF
  20. EXTERNAL_IP=$(gcloud compute instances describe ${instance} \
  21. --format 'value(networkInterfaces[0].accessConfigs[0].natIP)')
  22. INTERNAL_IP=$(gcloud compute instances describe ${instance} \
  23. --format 'value(networkInterfaces[0].networkIP)')
  24. cfssl gencert \
  25. -ca=ca.pem \
  26. -ca-key=ca-key.pem \
  27. -config=ca-config.json \
  28. -hostname=${instance},${EXTERNAL_IP},${INTERNAL_IP} \
  29. -profile=kubernetes \
  30. ${instance}-csr.json | cfssljson -bare ${instance}
  31. done

Results:

  1. worker-0-key.pem
  2. worker-0.pem
  3. worker-1-key.pem
  4. worker-1.pem
  5. worker-2-key.pem
  6. worker-2.pem

The Controller Manager Client Certificate

Generate the kube-controller-manager client certificate and private key:

  1. {
  2. cat > kube-controller-manager-csr.json <<EOF
  3. {
  4. "CN": "system:kube-controller-manager",
  5. "key": {
  6. "algo": "rsa",
  7. "size": 2048
  8. },
  9. "names": [
  10. {
  11. "C": "US",
  12. "L": "Portland",
  13. "O": "system:kube-controller-manager",
  14. "OU": "Kubernetes The Hard Way",
  15. "ST": "Oregon"
  16. }
  17. ]
  18. }
  19. EOF
  20. cfssl gencert \
  21. -ca=ca.pem \
  22. -ca-key=ca-key.pem \
  23. -config=ca-config.json \
  24. -profile=kubernetes \
  25. kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager
  26. }

Results:

  1. kube-controller-manager-key.pem
  2. kube-controller-manager.pem

The Kube Proxy Client Certificate

Generate the kube-proxy client certificate and private key:

  1. {
  2. cat > kube-proxy-csr.json <<EOF
  3. {
  4. "CN": "system:kube-proxy",
  5. "key": {
  6. "algo": "rsa",
  7. "size": 2048
  8. },
  9. "names": [
  10. {
  11. "C": "US",
  12. "L": "Portland",
  13. "O": "system:node-proxier",
  14. "OU": "Kubernetes The Hard Way",
  15. "ST": "Oregon"
  16. }
  17. ]
  18. }
  19. EOF
  20. cfssl gencert \
  21. -ca=ca.pem \
  22. -ca-key=ca-key.pem \
  23. -config=ca-config.json \
  24. -profile=kubernetes \
  25. kube-proxy-csr.json | cfssljson -bare kube-proxy
  26. }

Results:

  1. kube-proxy-key.pem
  2. kube-proxy.pem

The Scheduler Client Certificate

Generate the kube-scheduler client certificate and private key:

  1. {
  2. cat > kube-scheduler-csr.json <<EOF
  3. {
  4. "CN": "system:kube-scheduler",
  5. "key": {
  6. "algo": "rsa",
  7. "size": 2048
  8. },
  9. "names": [
  10. {
  11. "C": "US",
  12. "L": "Portland",
  13. "O": "system:kube-scheduler",
  14. "OU": "Kubernetes The Hard Way",
  15. "ST": "Oregon"
  16. }
  17. ]
  18. }
  19. EOF
  20. cfssl gencert \
  21. -ca=ca.pem \
  22. -ca-key=ca-key.pem \
  23. -config=ca-config.json \
  24. -profile=kubernetes \
  25. kube-scheduler-csr.json | cfssljson -bare kube-scheduler
  26. }

Results:

  1. kube-scheduler-key.pem
  2. kube-scheduler.pem

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.

Generate the Kubernetes API Server certificate and private key:

  1. {
  2. KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \
  3. --region $(gcloud config get-value compute/region) \
  4. --format 'value(address)')
  5. cat > kubernetes-csr.json <<EOF
  6. {
  7. "CN": "kubernetes",
  8. "key": {
  9. "algo": "rsa",
  10. "size": 2048
  11. },
  12. "names": [
  13. {
  14. "C": "US",
  15. "L": "Portland",
  16. "O": "Kubernetes",
  17. "OU": "Kubernetes The Hard Way",
  18. "ST": "Oregon"
  19. }
  20. ]
  21. }
  22. EOF
  23. cfssl gencert \
  24. -ca=ca.pem \
  25. -ca-key=ca-key.pem \
  26. -config=ca-config.json \
  27. -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 \
  28. -profile=kubernetes \
  29. kubernetes-csr.json | cfssljson -bare kubernetes
  30. }

Results:

  1. kubernetes-key.pem
  2. kubernetes.pem

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 documentation.

Generate the service-account certificate and private key:

  1. {
  2. cat > service-account-csr.json <<EOF
  3. {
  4. "CN": "service-accounts",
  5. "key": {
  6. "algo": "rsa",
  7. "size": 2048
  8. },
  9. "names": [
  10. {
  11. "C": "US",
  12. "L": "Portland",
  13. "O": "Kubernetes",
  14. "OU": "Kubernetes The Hard Way",
  15. "ST": "Oregon"
  16. }
  17. ]
  18. }
  19. EOF
  20. cfssl gencert \
  21. -ca=ca.pem \
  22. -ca-key=ca-key.pem \
  23. -config=ca-config.json \
  24. -profile=kubernetes \
  25. service-account-csr.json | cfssljson -bare service-account
  26. }

Results:

  1. service-account-key.pem
  2. service-account.pem

Distribute the Client and Server Certificates

Copy the appropriate certificates and private keys to each worker instance:

  1. for instance in worker-0 worker-1 worker-2; do
  2. gcloud compute scp ca.pem ${instance}-key.pem ${instance}.pem ${instance}:~/
  3. done

Copy the appropriate certificates and private keys to each controller instance:

  1. for instance in controller-0 controller-1 controller-2; do
  2. gcloud compute scp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \
  3. service-account-key.pem service-account.pem ${instance}:~/
  4. 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 lab.

Next: Generating Kubernetes Configuration Files for Authentication