O que fazer se os certificados estiverem podres e o cluster se transformar em abóbora?

Se, em resposta ao comando kubectl get pod você obtiver:

 Unable to connect to the server: x509: certificate has expired or is not yet valid 

então, provavelmente, um ano se passou, seus certificados kubernetes expiraram, os componentes do cluster pararam de usá-los, a interação entre eles parou e o cluster se transformou em uma abóbora.

imagem

O que fazer e como restaurar um cluster?

Primeiro, precisamos entender onde estão localizados os certificados que precisam ser atualizados.

Dependendo da maneira como o cluster foi instalado, o local e o nome dos arquivos de certificado podem variar. Por exemplo, ao criar um cluster, o Kubeadm decompõe os arquivos de certificado de acordo com as práticas recomendadas . Portanto, todos os certificados estão localizados no /etc/kuberenetes/pki , em arquivos com a extensão .crt , chaves privadas, respectivamente, nos arquivos .key . Além disso, em /etc/kubernetes/ estão .conf arquivos .conf com configuração de acesso para administrador de contas de usuário, controlador de gerente, sheduler e kubelet no nó principal. Os certificados nos arquivos .conf estão no campo user.client-certificate-data no formato codificado em base64.

Você pode verificar a data de validade para quem foi emitido e por quem o certificado foi assinado usando este pequeno script shcert

shcert
 #!/bin/bash [ -f "$1" ] || exit if [[ $1 =~ \.(crt|pem)$ ]]; then openssl x509 -in "$1" -text -noout fi if [[ $1 =~ \.conf$ ]]; then certfile=$(mktemp) grep 'client-certificate-data:' "$1"| awk '{ print $2}' | base64 -d > "$certfile" openssl x509 -in "$certfile" -text -noout rm -f "$certfile" fi 


Ainda existem certificados que usam o kubelet em nós de trabalho para autenticação na API. Se você usou o kubeadm join para adicionar nós ao cluster, provavelmente o nó foi conectado usando o procedimento de inicialização TLS ; nesse caso, o kubelet poderá renovar seu certificado automaticamente se receber a opção --rotate-certificates . Nas versões recentes do kubernetes, essa opção já está ativada por padrão.
Verificar se o nó está conectado usando o procedimento de inicialização TLS é bastante simples - nesse caso, o arquivo /etc/kubernetes/kubelet.conf geralmente é especificado no campo de certificado do cliente no arquivo /var/lib/kubelet/pki/kubelet-client-current.pem que é um link simbólico para o certificado atual.

Você também pode ver as datas de validade deste certificado usando o script shcert

Voltamos ao problema de renovação de certificados.

Se você instalou o cluster usando o kubeadm, tenho boas notícias para você. A partir da versão 1.15, o kubeadm pode atualizar quase todos os certificados do plano de controle com um comando

 kubeadm alpha certs renew all 

Este comando renova todos os certificados no diretório / etc / kubernetes, mesmo se eles já tiverem expirado e tudo estiver quebrado.

Somente o certificado kubelet não será atualizado - esse é o que está no arquivo /etc/kubernetes/kubelet.conf !
Atualização: o kubeadm, a partir da versão 1.17, inclui em todos os nós (mesmo no primeiro assistente em que o kubeadm init foi executado) a renovação automática do certificado culet. A verificação é muito simples - em /etc/kubernetes/kubelet.conf caminho para o arquivo /var/lib/kubelet/pki/kubelet-client-current.pem será indicado no campo de certificado do cliente

Para renovar este certificado, use o comando create user account

 kubeadm alpha kubeconfig user --client-name system:node:kube.slurm.io --org system:nodes > /etc/kubernetes/kubelet.conf 

Se o sistema tiver uma conta de usuário, este comando atualizará o certificado para esta conta. Não se esqueça de especificar o nome do host correto na opção --client-name , você pode --client-name nome --client-name host no campo Assunto de um certificado existente:

 shcert /etc/kubernetes/kubelet.conf 

E, é claro, após atualizar os certificados, é necessário reiniciar todos os componentes do plano de controle, reiniciar o nó inteiro ou parar os contêineres com etcd, api, controller-manager e scheduler com o docker stop e, em seguida, reiniciar o kubelet systemctl restart kubelet .

Se o cluster tiver uma versão antiga: 1.13 ou menos, ele simplesmente não funcionará para atualizar o kubeadm para a 1.15, pois ele puxa as dependências kubelet e kubernetes-cni, o que pode causar problemas, pois o desempenho dos componentes do cluster difere nas versões em mais de um. estágio, não garantido. A maneira mais fácil de sair dessa situação é instalar o kubeadm em outra máquina, pegar o arquivo binário /usr/bin/kubeadm , copiá-lo para os nós principais do cluster falecido e usá-lo apenas para renovar certificados. E depois que o cluster tiver sido revitalizado, atualize-o passo a passo usando métodos regulares, instalando o kubeadm uma versão mais nova a cada vez.

E, finalmente, a partir da versão 1.15, o kubeadm aprendeu a renovar todos os certificados ao atualizar um cluster com o comando kubeadm upgrade . Portanto, se você atualizar regularmente seu cluster pelo menos uma vez por ano, seus certificados sempre serão válidos.

Mas se o cluster não estiver instalado usando o kubeadm, você terá que abrir o openssl e renovar todos os certificados individualmente.

O problema é que os certificados contêm campos estendidos e diferentes ferramentas de instalação de cluster podem adicionar seu próprio conjunto de campos. Além disso, os nomes desses campos na configuração openssl e na saída do conteúdo do certificado estão correlacionados, mas fracamente. É necessário pesquisar e selecionar no Google.

Vou dar um exemplo de configuração para o openssl, em seções separadas, cujos atributos estendidos são descritos, específicos para cada tipo de certificado. Iremos nos referir à seção correspondente ao criar e assinar o csr. Essa configuração foi usada para revitalizar o cluster estabelecido há um ano pelo fazendeiro.

openssl.cnf
 [req] distinguished_name = req_distinguished_name req_extensions = v3_req [v3_req] keyUsage = nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth [client] keyUsage = critical,digitalSignature, keyEncipherment extendedKeyUsage = clientAuth [apiproxyclient] keyUsage = critical,digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, serverAuth [etcd] keyUsage = critical,digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, serverAuth subjectAltName = @alt_names [api] keyUsage = critical,digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, serverAuth subjectAltName = @alt_names [alt_names] DNS.1 = ec2-us-east-1-1a-c1-master-2 DNS.2 = ec2-us-east-1-1a-c1-master-3 DNS.3 = ec2-us-east-1-1a-c1-master-1 DNS.4 = localhost DNS.5 = kubernetes DNS.6 = kubernetes.default DNS.7 = kubernetes.default.svc DNS.8 = kubernetes.default.svc.cluster.local IP.1 = 10.0.0.109 IP.2 = 10.0.0.159 IP.3 = 10.0.0.236 IP.4 = 127.0.0.1 IP.5 = 10.43.0.1 


Atributos reais e nomes adicionais no certificado podem ser visualizados usando o comando

 openssl x509 -in cert.crt -text 

Ao renovar o certificado para a API do servidor, tive um problema: o certificado atualizado não funcionou. A solução foi emitir um certificado válido por 1 ano no passado.

No openssl, você não pode emitir um certificado válido no passado com um comando simples, o código afirma estritamente que o certificado é válido apenas a partir do momento atual. Mas você pode voltar no tempo localmente usando a biblioteca libfaketime

 yum install libfaketime LD_PRELOAD=/usr/lib64/faketime/libfaketime.so.1 FAKETIME="-365d" openssl x509 -req ... 

Emitimos certificados estendidos de acordo com o seguinte algoritmo:

Criamos um CSR usando um certificado existente, especificamos a seção desejada com uma lista de atributos avançados no arquivo de configuração:

 openssl x509 -x509toreq -in "node.cert" -out "node.csr" -signkey "node.key" -extfile "openssl.cnf" -extensions client 

Assinamos com o certificado raiz correspondente, alterando o tempo há 1 ano e especificando a seção desejada com uma lista de atributos avançados no arquivo de configuração

 LD_PRELOAD=/usr/lib64/faketime/libfaketime.so.1 FAKETIME="-365d" openssl x509 -req -days 36500 -in "node.csr" -CA "kube-ca.pem" -CAkey "kube-ca-key.pem" -CAcreateserial -out "node.new.cert" -extfile "openssl.cnf" -extensions client 

Verificamos os atributos e reiniciamos os componentes do plano de controle.

Sergey Bondarev,
Professor Slurm
slurm.io

Source: https://habr.com/ru/post/pt465733/


All Articles