|

Certificados Kubernetes the Hard Way: la PKI paso a paso

En pocas palabras: El Step 04 de Kubernetes the Hard Way genera con openssl una CA autofirmada (4096 bits, 3653 días de validez) y firma ocho pares de certificados —admin, node-0, node-1, kube-proxy, kube-scheduler, kube-controller-manager, kube-api-server y service-accounts— que después se distribuyen por scp a los workers y al controlador.

El Step 04 de Kubernetes the Hard Way arma la PKI completa del clúster con openssl: una CA autofirmada más ocho pares de certificados (admin, node-0, node-1, kube-proxy, kube-scheduler, kube-controller-manager, kube-api-server y service-accounts), distribuidos después a los workers y al controlador vía scp. Así lo documentó un usuario de dev.to el 13 de septiembre de 2026 replicando paso a paso la guía original.

Los certificados kubernetes the hard way son el mecanismo de autenticación TLS que usa cada componente del clúster para confiar en los demás. La guía oficial de Kelsey Hightower los define así: una Certificate Authority propia, generada con openssl, firma las claves de cada pieza (API server, kubelet, scheduler, etc.) para que se identifiquen entre sí sin depender de un proveedor externo.

En 30 segundos

  • La CA se genera con openssl genrsa (4096 bits) y openssl req -x509 con vigencia de 3653 días (10 años).
  • Se firman 8 certificados: admin, node-0, node-1, kube-proxy, kube-scheduler, kube-controller-manager, kube-api-server y service-accounts.
  • Los certificados de los workers van a /var/lib/kubelet/ vía scp; los del controlador (ca, api-server, service-accounts) se copian a la home del server.
  • El usuario de dev.to reportó un warning de “directory already exists” en ambos nodos, sin impacto real en la copia de archivos.
  • No hubo desvíos respecto a la guía original: los comandos se ejecutaron tal cual están documentados.

¿Por qué Kubernetes necesita una Certificate Authority propia?

Porque cada componente del clúster (API server, kubelet, scheduler, controller-manager) actúa como un servicio de red independiente y necesita autenticarse contra los demás igual que dos servidores cualquiera configurando TLS mutuo. El propio autor de la nota lo resume bien: generar e instalar estos certificados “se sintió exactamente como configurar TLS entre un montón de servidores para que confíen entre sí”.

Esa comparación tiene sentido si se piensa en capas: primero se abstrajo el cómputo (servidor físico → contenedor), y ahora Kubernetes abstrae la confianza misma entre servicios. Cada pieza del control plane termina siendo un microservicio más en la red, con su propia identidad criptográfica en vez de depender de contraseñas o tokens estáticos. La pregunta que vale hacerse acá no es “por qué tanto certificado” sino “qué pasaría si no los hubiera”: sin CA propia, cualquier proceso que hable con la API tendría que confiar a ciegas en quien dice ser el API server, y eso es exactamente el tipo de superficie de ataque que TLS mutuo busca cerrar.

Ojo con esto: la guía oficial aclara que una CA autofirmada sirve para el laboratorio, pero “no debería considerarse algo que harías en un entorno de producción real”. Tomalo con pinzas si pensás llevar este setup más allá de un homelab.

¿Cómo se genera un certificado autofirmado con openssl para kubernetes?

certificados kubernetes the hard way diagrama explicativo

Se genera con dos comandos openssl encadenados: primero la clave privada de la CA, después el certificado autofirmado que la respalda. Estos son los comandos exactos que documenta la guía y que el autor de dev.to ejecutó sin desvíos:

  • Clave privada de la CA: openssl genrsa -out ca.key 4096, una clave RSA de 4096 bits.
  • Certificado autofirmado: openssl req -x509 -new -sha512 -noenc -key ca.key -days 3653 -config ca.conf -out ca.crt, válido por 3653 días (10 años).

El archivo ca.conf es el que define todos los detalles de cada certificado por sección, así que ahorra tener que escribir a mano la configuración de openssl para cada componente. El resultado son dos archivos: ca.key (la clave privada, permisos 600) y ca.crt (el certificado público). En el log del autor, ambos quedaron con fecha del 11 de septiembre.

Criterio práctico: antes de correr estos dos comandos conviene decidir de antemano si ca.conf va a vivir en un repo versionado o solo en el disco del jumpbox. Es el único archivo del que depende toda la PKI del clúster: si se pierde o se edita mal a mitad de camino, cada certificado que se firme después queda con datos inconsistentes (Subject, SAN) respecto a los que ya se distribuyeron.

Qué componentes de Kubernetes necesitan su propio certificado

Ocho componentes necesitan certificado propio, cada uno firmado por la misma CA: admin, node-0, node-1, kube-proxy, kube-scheduler, kube-controller-manager, kube-api-server y service-accounts. La guía los genera todos con un solo loop de bash que repite tres pasos por cada nombre en el array certs.

El ciclo es siempre el mismo: openssl genrsa crea la clave privada del componente, openssl req -new arma el CSR (Certificate Signing Request) usando la sección correspondiente de ca.conf, y openssl x509 -req firma ese CSR con la CA (-CA ca.crt -CAkey ca.key) generando el certificado final con 10 años de vigencia. Subís el nombre del componente al array, corrés el for, esperás unos segundos y listo: tenés clave, CSR y certificado firmado para cada pieza del clúster sin tocar nada a mano.

El resultado, según confirmó el autor con ls -1 *.crt *.key *.csr, son 26 archivos: tres por cada uno de los ocho componentes (clave, CSR y certificado), más ca.crt y ca.key. Nada raro: “también sin desvíos, directo de la guía”, anotó.

Ejemplo hipotético (no ocurrió en la fuente, es solo para ilustrar el razonamiento): supongamos que en vez de node-0 y node-1 se quisiera sumar un tercer worker, node-2. El cambio no requiere tocar ca.conf ni el loop de generación completo: alcanza con agregar “node-2” al array certs, correr el mismo for (que va a generar solo los tres archivos faltantes si los demás ya existen) y después repetir el bloque de distribución con node-2 en la lista de hosts. El punto de decisión real está en ca.conf: si esa sección no define correctamente el SAN para node-2, el certificado se genera sin errores pero el kubelet de ese nodo va a fallar al autenticarse recién cuando intente hablar con la API, no antes.

Cómo distribuir los certificados a nodos worker y al controlador

Los certificados se distribuyen con scp: a cada worker le toca su propio par (renombrado como kubelet.crt/kubelet.key) más la CA, y al controlador le tocan los certificados de API server y service-accounts junto con la clave privada de la CA. La lógica separa claramente qué necesita cada rol dentro del clúster.

Para node-0 y node-1, el script primero crea el directorio /var/lib/kubelet/ por SSH y después copia tres archivos: ca.crt, el certificado del nodo renombrado a kubelet.crt, y la clave renombrada a kubelet.key. Para el controlador (llamado server en la guía), el scp manda seis archivos de una: ca.key, ca.crt, kube-api-server.key, kube-api-server.crt, service-accounts.key y service-accounts.crt.

Vale aclarar algo que no siempre queda obvio en la guía: los certificados de kube-proxy, kube-controller-manager, kube-scheduler y kubelet no se distribuyen todavía. Se usan recién en el próximo paso, cuando se generan los archivos kubeconfig de autenticación. El criterio detrás de esta separación es simple: solo se copia lo que un componente necesita para arrancar, y kube-proxy/scheduler/controller-manager no arrancan hasta el siguiente step, así que sus certificados esperan.

Errores y advertencias durante el proceso (según la fuente)

El único inconveniente reportado fue un warning inofensivo, no un error real. Al correr ssh root@${host} mkdir /var/lib/kubelet/ en ambos nodos, el sistema devolvió mkdir: cannot create directory '/var/lib/kubelet/': File exists, algo esperable si el directorio ya existía de un paso anterior (probablemente de la instalación de containerd en steps previos).

El autor lo aclaró sin vueltas: “el warning apareció en los dos nodos, pero las copias de archivos funcionaron todas bien, así que no hay problema”. Las tres líneas de scp que siguieron (ca.crt, node-X.crt, node-X.key) se completaron sin errores en ambos casos.

Errores comunes al armar la PKI de Kubernetes the Hard Way

  • Confundir el certificado de admin con el de service-accounts: son entidades distintas. El de admin autentica a un usuario humano contra la API; el de service-accounts firma los tokens que usan los pods para hablar con la API. Mezclarlos rompe la autenticación de pods.
  • Copiar la clave privada de la CA a los workers: la guía solo manda ca.key al controlador, nunca a node-0 ni node-1. Si un worker tiene la clave privada de la CA, cualquiera con acceso a ese nodo puede firmar certificados falsos para todo el clúster.
  • No renombrar el certificado del worker a kubelet.crt/kubelet.key: kubelet busca esos nombres exactos en /var/lib/kubelet/. Si dejás el archivo como node-0.crt, el servicio simplemente no lo encuentra.
  • Ignorar la vigencia de 3653 días pensando que es “para siempre”: son 10 años, no una eternidad. En un clúster real conviene documentar la fecha de expiración desde el día uno.

Un criterio simple para decidir si vale la pena tocar la vigencia por defecto: en un homelab que se va a recrear seguido, 3653 días es irrelevante porque el clúster probablemente no dura tanto. En un entorno que se piensa mantener corriendo por años sin reinstalar, tiene más sentido acortar esa ventana (por ejemplo a 365 días) y automatizar la renovación desde el principio, en vez de heredar el valor de la guía sin pensarlo.

Preguntas Frecuentes

¿Para qué sirve la Certificate Authority en Kubernetes the Hard Way?

La CA firma todos los certificados de los componentes del clúster para que se autentiquen entre sí por TLS. Sin una CA propia, el API server, los kubelets y el resto de los servicios no tendrían forma de verificar que están hablando con quien dicen ser.

¿Cómo se genera un certificado autofirmado con openssl para kubernetes?

Se generan con dos comandos: openssl genrsa -out ca.key 4096 para la clave privada, y openssl req -x509 -new -sha512 -noenc -key ca.key -days 3653 -config ca.conf -out ca.crt para el certificado autofirmado. El resultado es un par ca.key/ca.crt válido por 3653 días.

¿Qué componentes de kubernetes necesitan certificado propio?

Ocho componentes: admin, node-0, node-1, kube-proxy, kube-scheduler, kube-controller-manager, kube-api-server y service-accounts. Cada uno tiene su propio par clave/certificado firmado por la misma CA.

¿Cómo distribuir los certificados a los nodos worker y al controlador?

A los workers (node-0, node-1) se les copia ca.crt y su propio certificado/clave (renombrados a kubelet.crt/kubelet.key) dentro de /var/lib/kubelet/ vía scp. Al controlador se le copian ca.key, ca.crt, y los pares de kube-api-server y service-accounts a su directorio home.

¿Qué diferencia hay entre el certificado de admin y el de service-accounts?

El certificado de admin autentica a un usuario humano con permisos administrativos contra la API de Kubernetes. El de service-accounts firma los tokens que usan los pods para autenticarse ante la API, sin intervención humana.

Conclusión

El Step 04 de Kubernetes the Hard Way deja algo claro: la PKI de un clúster no es magia, son openssl y scp bien encadenados, con una regla de distribución simple (cada componente recibe solo lo que necesita para arrancar). Si estás siguiendo la guía en tu propio homelab, el criterio práctico más útil es verificar cada certificado con openssl x509 -in archivo.crt -text -noout antes de distribuirlo, así confirmás que el Subject y los SAN (Subject Alternative Names) corresponden al componente correcto. Un certificado mal firmado no falla en el momento de crearlo, falla recién cuando el API server intenta usarlo, y ahí perdés tiempo debuggeando algo que se podía chequear en 10 segundos.

Lo que el reporte de dev.to no permite concluir es si este mismo flujo escala sin fricción a un clúster con más de dos workers, ni cómo se maneja la renovación de certificados cuando se acerquen esos 3653 días. Son preguntas para el próximo step, no para este.

Fuentes

Te puede interesar...