Configurar el servidor de métricas de Kubernetes en modo seguro

Después de varias horas investigando por qué el componente metrics-server que se ejecuta en mi clúster de kubernetes obtenía errores relacionados con un certificado no válido al recuperar métricas de los nodos, he podido solucionar el problema y obtener métricas correctamente de todos los nodos kubernetes mediante HTTPS.

En las líneas siguientes se describe cuál es el problema y cómo solucionarlo.

Problema

Después de desplegar el componente metrics-server, el pod metrics-server no es capaz de arrancar. Veo muchos mensajes como el de las líneas siguientes:

E1229 07:09:05.013998 1 summary.go:97] error while getting metrics summary from Kubelet node2(192.168.x.x:10250): Get https://192.168.x.x:10250/metrics/resource/: x509: cannot validate certificate for 192.168.x.x because it doesn't contain any IP SANs

El mensaje de error es muy claro. El problema es que el certificado configurado en los nodos del clúster de kubernetes no permite IPs como nombres de host en la URL de consulta de métricas.

Solución

Gracias a Github, he encontrado una solución que funcionaba en el momento en que se planteó el problema, pero que hoy en día no funciona.

De todas formas, tras unos pequeños retoques, consigo que funcione en Kubernetes 1.23

En mi caso, estoy utilizando un portatil corriendo Ubuntu por lo que los siguientes pasos son los que he ejecutado en Ubuntu.

  • Instalar los siguientes paquetes necesarios para los siguientes pasos
sudo apt install -y golang-cfssl jq
  • Generar una Solicitud de Firma de Certificado (CSR) . Tras ejecutar el siguiente comando, se crearán dos nuevos archivos kubelet-server-key .pem y kubelet-server.csr
{
    "hosts": [
        "master1",
        "node2",
        "node3",
        "node4",
        "192.168.30.12",
        "192.168.30.11",
        "192.168.30.15",
        "192.168.30.16"
    ],
    "CN": "system:node:kubelet-server",
    "name": [
        {
            "C": "ES",
            "ST": "Spain",
            "L": "Malaga",
            "O": "system:nodes",
            "OU": "system:nodes"
        }
    ]
}
  • Es hora de crear el CSR en el cluster de kubernetes para que kubernetes pueda crear el certificado correcto
cat <<EOF | kubectl create -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest 
metadata:
  name: kubelet-server
spec:
  request: $(cat kubelet-server.csr | base64 | tr -d '\n')
  signerName: kubernetes.io/kubelet-serving
  groups:
  - system:nodes
  - system:authenticated
  usages:
  - digital signature
  - key encipherment
  - server auth
EOF
  • Después de crear el CSR en kubernetes, necesitamos aprobarlo
kubectl certificate approve kubelet-server
  • Descargar el nuevo certificado
kubectl get csr kubelet-server -o jsonpath='{.status.certificate}' | base64 --decode > kubelet-server.pem
  • Llegados a este punto, deberíamos tener dos archivos diferentes que contienen la clave privada(kubelet-server-key.pem) y la clave pública(kubelet-server.pem) del certificado. Necesitamos copiar estos dos archivos en todos los nodos de kubernetes (masters y workers). He decidido colocar estos archivos en /var/lib/kubernetes/pki, por lo que los archivos deben ubicarse en /var/lib/kubernetes/pki/kubelet-server-key.pem y /var/lib/kubernetes/pki/kubelet-server.pem
  • Debemos configurar kubelet para que lea los archivos que acabamos de copiar en todos los nodos de kubernetes. Necesitamos saber qué archivo utiliza el componente kubelet para cargar la configuración
sudo ps aux | grep kubelet
  • La salida del comando anterior debería tener un aspecto similar al de las siguientes líneas
root 2020195 5.6 0.3 2160136 121488 ? Ssl Sep18 73:58 /opt/bin/kubelet --logtostderr=true --v=2 --node-ip=192.168.30.16 --hostname-override=node4
--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --config=/etc/kubernetes/kubelet-config.yaml --kubeconfig=/etc/kubernetes/kubelet.conf
--container-runtime=remote --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --runtime-cgroups=/systemd/system.slice --network-plugin=cni --cni-conf-dir=/etc/cni/net.d
--cni-bin-dir=/opt/cni/bin --volume-plugin-dir=/var/lib/kubelet/volumeplugins
  • Podemos comprobar que el archivo de configuración que lee kubelet es /etc/kubernetes/kubelet-config.yaml
    Tenemos que editar este archivo para configurar dónde se encuentran las partes privada y pública de los certificados. Ten en cuenta que los siguientes comandos deben ejecutarse como usuario root.
echo "tlsPrivateKeyFile: /var/lib/kubelet/pki/kubelet-server-key.pem" >> /etc/kubernetes/kubelet-config.yaml
echo "tlsCertFile: /var/lib/kubelet/pki/kubelet-server.pem" >> /etc/kubernetes/kubelet-config.yaml
  • El último paso es reiniciar kubelet en todos los nodos
sudo systemctl daemon-reload
sudo systemctl restart kubelet

En este punto, kubelet debería estar utilizando un certificado que contenga las IPs de todos los nodos de kubernetes y que haya sido firmado por la CA del clúster para que el servidor de métricas pueda obtener todas las métricas utilizando HTTPS.

Espero que este post te resulte útil y que puedas solucionar este problema fácilmente si lo encuentras.

¡Nos vemos en el próximo post!

Comentarios

Aún no hay comentarios. ¿Por qué no comienzas el debate?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *