K8S The Hard Way 2/10 - Gerando Certificados

Sat, Feb 13, 2021 5-minute read

Provisionando uma CA e gerando certificados TLS

Neste laboratório, você irá provisionar uma infraestrutura PKI usando o kit de ferramentas PKI da CloudFlare, cfssl, depois usá-la para inicializar uma autoridade de certificadora e gerar certificados TLS para os seguintes componentes: etcd, kube-apiserver, kube-controller-manager, kube-scheduler, kubelet e kube-proxy.

Autoridade Certificadora

Você fornecerá uma Autoridade de Certificação que pode ser usada para gerar certificados TLS adicionais.

Gere o arquivo de configuração de CA, o certificado e a chave privada:

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": "BR",
      "L": "Sao Paulo",
      "O": "Kubernetes",
      "OU": "CA",
      "ST": "Sao Paulo"
    }
  ]
}
EOF

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

Resultado

ca-key.pem
ca.pem

Certificados do cliente e servidor:

Você gerará certificados do cliente e servidor para cada componente do Kubernetes e um certificado de cliente para o usuário administrador do Kubernetes.

O Certificado de Cliente Admin

Gere o certificado do cliente administrador e a chave privada:

cat > admin-csr.json <<EOF
{
  "CN": "admin",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "BR",
      "L": "Sao Paulo",
      "O": "system:masters",
      "OU": "Kubernetes The Hard Way",
      "ST": "Sao Paulo"
    }
  ]
}
EOF

cfssl gencert \
  -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -profile=kubernetes \
  admin-csr.json | cfssljson -bare admin

Resultado

admin-key.pem
admin.pem

Os certificados de cliente Kubelet

O Kubernetes usa um modo de autorização de propósito especial denominado Node Authorizer, que autoriza especificamente solicitações da API feitas por Kubelets. Para ser autorizado pelo Node Authorizer, o Kubelets deve usar uma credencial que os identifique como estando no grupo system: nodes, com um nome de usuário system: node: . Nesta seção, você criará um certificado para cada worker do Kubernetes que atenda aos requisitos do Autorizador de Nó.

Gere um certificado e uma chave privada para cada nó de trabalho do Kubernetes:

for instance in worker-0 worker-1 worker-2; do
    cat > ${instance}-csr.json <<EOF
{
  "CN": "system:node:${instance}",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "BR",
      "L": "Sao Paulo",
      "O": "system:nodes",
      "OU": "Kubernetes The Hard Way",
      "ST": "Sao Paulo"
    }
  ]
}
EOF

EXTERNAL_IP=`sudo vagrant ssh-config $instance | grep HostName | xargs  | sed 's/HostName//g' | xargs`

cfssl gencert \
      -ca=ca.pem \
      -ca-key=ca-key.pem \
      -config=ca-config.json \
      -hostname=${instance},${EXTERNAL_IP} \
      -profile=kubernetes \
      ${instance}-csr.json | cfssljson -bare ${instance}
done

Resultado

worker-0-key.pem
worker-0.pem
worker-1-key.pem
worker-1.pem
worker-2-key.pem
worker-2.pem

O Certificado de Cliente do Controller Manager

Gere o certificado de cliente kube-controller-manager e a chave privada:

cat > kube-controller-manager-csr.json <<EOF
{
  "CN": "system:kube-controller-manager",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "BR",
      "L": "Sao Paulo",
      "O": "system:kube-controller-manager",
      "OU": "Kubernetes The Hard Way",
      "ST": "Sao Paulo"
    }
  ]
}
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

Resultado

kube-controller-manager-key.pem
kube-controller-manager.pem

O certificado de cliente proxy Kube

Gere o certificado de cliente kube-proxy e a chave privada:

cat > kube-proxy-csr.json <<EOF
{
  "CN": "system:kube-proxy",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "BR",
      "L": "Sao Paulo",
      "O": "system:node-proxier",
      "OU": "Kubernetes The Hard Way",
      "ST": "Sao Paulo"
    }
  ]
}
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

Resultado

kube-proxy-key.pem
kube-proxy.pem

O certificado do cliente do Scheduler

Gere o certificado do cliente kube-scheduler e a chave privada:

cat > kube-scheduler-csr.json <<EOF
{
  "CN": "system:kube-scheduler",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "BR",
      "L": "Sao Paulo",
      "O": "system:kube-scheduler",
      "OU": "Kubernetes The Hard Way",
      "ST": "Sao Paulo"
    }
  ]
}
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

Resultado

kube-scheduler-key.pem
kube-scheduler.pem

O certificado do servidor da API Kubernetes

O endereço IP estático do kubernetes-the-hard-way será incluído na lista de nomes alternativos de assunto para o certificado do servidor da API Kubernetes. Isso garantirá que o certificado possa ser validado por clientes remotos.

O servidor da API Kubernetes é atribuído automaticamente ao nome dns interno do kubernetes, que será vinculado ao primeiro endereço IP (10.32.0.1) do intervalo de endereços (10.32.0.0/24) reservado para serviços de cluster internos durante o laboratório de bootstrap do plano de controle.

Gere o certificado e a chave privada do servidor da API Kubernetes:


KUBERNETES_PUBLIC_ADDRESS=`sudo vagrant ssh-config | grep -a1 "Host controller*\|Host loadbalance" | grep -v "Host controller*\|--\|Host loadbalance" | grep HostName | xargs  | sed 's/HostName//g' | xargs | tr " " ","`
KUBERNETES_HOSTNAMES=kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster,kubernetes.svc.cluster.local

cat > kubernetes-csr.json <<EOF
{
  "CN": "kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "BR",
      "L": "Sao Paulo",
      "O": "Kubernetes",
      "OU": "Kubernetes The Hard Way",
      "ST": "Sao Paulo"
    }
  ]
}
EOF

cfssl gencert \
      -ca=ca.pem \
      -ca-key=ca-key.pem \
      -config=ca-config.json \
      -hostname=127.0.0.1,10.32.0.1,${KUBERNETES_PUBLIC_ADDRESS},${KUBERNETES_HOSTNAMES} \
      -profile=kubernetes \
      kubernetes-csr.json | cfssljson -bare kubernetes

Resultado

kubernetes-key.pem
kubernetes.pem

Par de chaves da conta de serviço

O Kubernetes Controller Manager aproveita um par de chaves para gerar e assinar tokens de conta de serviço, conforme descrito na documentação de gerenciamento de contas de serviço.

Gere o certificado da conta de serviço e a chave privada:

cat > service-account-csr.json <<EOF
{
  "CN": "service-accounts",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "BR",
      "L": "Sao Paulo",
      "O": "Kubernetes",
      "OU": "Kubernetes The Hard Way",
      "ST": "Sao Paulo"
    }
  ]
}
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

Resultado

service-account-key.pem
service-account.pem

Distribuir os certificados de cliente e servidor

Copie os certificados apropriados e as chaves privadas para cada instância do trabalhador:

for instance in worker-0 worker-1 worker-2; do
      IP=`sudo vagrant ssh-config $instance | grep HostName | xargs  | sed 's/HostName//g' | xargs`
      sudo scp -i /home/$USER/vagrant-vm/kubernetes-the-hard-way/.vagrant/machines/$instance/libvirt/private_key \
      ca.pem ${instance}-key.pem ${instance}.pem \
      vagrant@${IP}:~/
done

Copie os certificados apropriados e as chaves privadas para cada instância do controlador:

for instance in controller-0 controller-1 controller-2; do
      IP=`sudo vagrant ssh-config $instance | grep HostName | xargs  | sed 's/HostName//g' | xargs`
      sudo scp -i /home/$USER/vagrant-vm/kubernetes-the-hard-way/.vagrant/machines/$instance/libvirt/private_key \
      ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem service-account-key.pem service-account.pem \
      vagrant@${IP}:~/
done

Proximo: K8S The Hard Way 3/10 - Arquivos de Configuração