Qué es Cert-Manager y cómo configurar Cert-Manager para los certificados SSL en el cluster de Kubernetes en AWS usando Helm
Cert-Manager es un controlador utilizado para la gestión de certificados. Un Cert-Manager puede ayudar a emitir certificados de diferentes emisores como Let’s Encrypt, HashiCorp Vault, Venafi, un par de claves de firma simple o autofirmados. Cert-Manager valida los certificados, se asegura de que estén actualizados y los renueva antes de que caduquen. Cert-Manager está formado por varios componentes, como se menciona a continuación.
- Emisor: Los emisores, y los ClusterIssuers, son objetos en Kubernetes que representan a las autoridades de certificación (CA) que pueden generar certificados firmados.
- Certificado: Un Certificado es un recurso con espacio de nombre que hace referencia a un Emisor o ClusterIssuer y que se renovará y mantendrá actualizado.
- CertificateRequest: El CertificateRequest es un recurso namespaced que se utiliza para solicitar un certificado a un emisor o cluster issuer.
- Pedidos ACME: Un pedido representa una solicitud de certificado que se creará una vez que se haya creado un nuevo recurso CertificateRequest que haga referencia a un emisor ACME
- Desafíos ACME: Cuando se crea un recurso de Pedido, el controlador de pedidos creará recursos de Desafío para cada nombre DNS que se esté autorizando con el servidor ACME.
- Webhook: Se despliega como otro pod junto con los pods principales de Cert-Manager y tiene 3 funciones: ValidatingAdmissionWebhook, MutatingAdmissionWebhook y CustomResourceConversionWebhook.
- Inyector de CA: Ayuda a configurar los certificados para Validating Webhooks, Mutating Webhooks y Conversion Webhooks.
En este artículo, configuraremos un Gestor de Certificados con el emisor Let’s Encrypt. Aseguraremos nuestra aplicación de ejemplo utilizando los certificados TLS y tendremos HTTPS en nuestro Hostname para acceder a la aplicación utilizando Ingress. Para ello, añadiremos anotaciones al Ingress para que el recurso del certificado se cree en nuestro nombre.
Para conocer en detalle el Cert-Manager, visita la documentación oficial aquí. Este artículo se centra en la configuración del Cert-Manager mediante Helm y se supone que estás familiarizado con los conceptos relacionados con el Cert-Manager.
Requisitos previos
- Cuenta de AWS(Créala si no tienes una).
- Cluster de Kubernetes (Haz clic aquí para aprender a crear un Cluster de Kubernetes usando Kops y saber más sobre él).
- Controlador de entrada Nginx en el clúster K8S (Busca «Qué es el controlador de entrada y cómo desplegar el controlador de entrada Nginx en el clúster Kubernetes en AWS usando Helm» para aprender a configurar el controlador de entrada Nginx)
- Helm v3.5.3 (Haz clic aquí para aprender a instalar Helm en un servidor Ubuntu)
- Cubo S3 (Haz clic aquí para aprender a crear un cubo S3 en AWS).
- Nombre de dominio (Haz clic aquí para aprender a registrar un dominio en AWS).
- Rol IAM con permisos de administrador (Haz clic aquí para aprender a crear un rol IAM en AWS).
¿Qué vamos a hacer?
- Comprobar el controlador de entrada en el clúster
- Configurar un Cert-Manager
- Crear archivos de definición de objetos para una aplicación de ejemplo
- Configurar el emisor de Let’s Encrypt de producción y de ensayo
- Despliega una aplicación de ejemplo
- Despliega un objeto de entrada con TLS
Comprueba el controlador de entrada en el clúster
Antes de continuar, comprueba si tienes el controlador de entrada de Nginx funcionando en el clúster.
kubectl get pods
kubectl get svc

Configurar el gestor de certificados
Note: I have used Helm binary present at my current location, hence you can see ./helm in screenshots.
Utiliza Helm v3.5.3 y ejecuta los siguientes comandos, esto instalará la carta Helm para Cert-Manager.
kubectl create namespace cert-manager
helm repo add jetstack https://charts.jetstack.io
helm repo update helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v1.2.0 --set installCRDs=true

En la captura de pantalla anterior, puedes ver que se ha instalado la Carta Helm para Cert-Manager.
Comprueba los pods que se han creado como parte del Cert-Manager.
kubectl get pods -A

Puedes ver 3 nuevos pods en el espacio de nombres «cert-manager».
Crea archivos de definición de objetos para una aplicación de ejemplo y emisores
Crea 1-nginx-main-app.yaml para la aplicación 1
Enlace Github: Haz clic aquí para copiar el archivo de mi repo de Github.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: nginx
name: nginx-deploy-main
spec:
replicas: 1
selector:
matchLabels:
run: nginx-main
template:
metadata:
labels:
run: nginx-main
spec:
containers:
- image: nginx
name: nginx
---
apiVersion: v1
kind: Service
metadata:
name: nginx-deploy-main
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
selector:
run: nginx-main
Crea 2-nginx-green-app.yaml para la aplicación 2.
Enlace Github: Haz clic aquí para copiar el archivo de mi repositorio de Github.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: nginx
name: nginx-deploy-green
spec:
replicas: 1
selector:
matchLabels:
run: nginx-green
template:
metadata:
labels:
run: nginx-green
spec:
volumes:
- name: webdata
emptyDir: {}
initContainers:
- name: web-content
image: busybox
volumeMounts:
- name: webdata
mountPath: "/webdata"
command: ["/bin/sh", "-c", 'echo "<h1>I am <font color=green>GREEN</font></h1>" > /webdata/index.html']
containers:
- image: nginx
name: nginx
volumeMounts:
- name: webdata
mountPath: "/usr/share/nginx/html"
---
---
apiVersion: v1
kind: Service
metadata:
name: nginx-deploy-green
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
selector:
run: nginx-green
Crea 3-nginx-blue-app.yaml para la aplicación 3
Enlace Github: Haz clic aquí para copiar el archivo de mi repo de Github.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: nginx
name: nginx-deploy-blue
spec:
replicas: 1
selector:
matchLabels:
run: nginx-blue
template:
metadata:
labels:
run: nginx-blue
spec:
volumes:
- name: webdata
emptyDir: {}
initContainers:
- name: web-content
image: busybox
volumeMounts:
- name: webdata
mountPath: "/webdata"
command: ["/bin/sh", "-c", 'echo "<h1>I am <font color=blue>BLUE</font></h1>" > /webdata/index.html']
containers:
- image: nginx
name: nginx
volumeMounts:
- name: webdata
mountPath: "/usr/share/nginx/html"
---
apiVersion: v1
kind: Service
metadata:
name: nginx-deploy-blue
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
selector:
run: nginx-blue
Crea 4-tls-ingress.yaml para crear reglas de Ingress basadas en la ruta con Staging Issuer.
Enlace Github: Haz clic aquí para copiar el archivo de mi repositorio de Github.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: letsencrypt-staging
name: ingress-resource-3
spec:
tls:
- hosts:
- kops.devopslee.com
secretName: sample-kubernetes-tls
rules:
- host: kops.devopslee.com
http:
paths:
- path: /
backend:
serviceName: nginx-deploy-main
servicePort: 80
- path: /blue
backend:
serviceName: nginx-deploy-blue
servicePort: 80
- path: /green
backend:
serviceName: nginx-deploy-green
servicePort: 80
Crea 5-tls-ingress-prod-issuer.yaml para crear reglas de entrada basadas en la ruta con el emisor de producción.
Enlace Github: Haz clic aquí para copiar el archivo de mi repositorio de Github.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: letsencrypt-production
name: ingress-resource-3
spec:
tls:
- hosts:
- kops.devopslee.com
secretName: sample-kubernetes-tls
rules:
- host: kops.devopslee.com
http:
paths:
- path: /
backend:
serviceName: nginx-deploy-main
servicePort: 80
- path: /blue
backend:
serviceName: nginx-deploy-blue
servicePort: 80
- path: /green
backend:
serviceName: nginx-deploy-green
servicePort: 80
Crear staging_issuer.yaml para Let’s Encrypt Staging Issuer
Enlace Github: Haz clic aquí para copiar el archivo de mi repositorio de Github.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
# Email address used for ACME registration
email: your-email-id-here
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Name of a secret used to store the ACME account private key
name: letsencrypt-staging-private-key
# Add a single challenge solver, HTTP01 using nginx
solvers:
- http01:
ingress:
class: nginx
Crea production_issuer.yaml para el emisor de producción de Let’s Encrypt
Enlace Github: Haz clic aquí para copiar el archivo de mi repositorio de Github.
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-production
spec:
acme:
# Email address used for ACME registration
email: your-email-id-here
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
# Name of a secret used to store the ACME account private key
name: letsencrypt-production-private-key
# Add a single challenge solver, HTTP01 using nginx
solvers:
- http01:
ingress:
class: nginx
Puedes encontrar todos estos archivos en mi repositorio de Github aquí.
Configurar el emisor de Let’s Encrypt de producción y de ensayo
Vamos a instalar el emisor de clústeres de ensayo y de producción.
Puesta enmarcha:
Staging tiene «servidor: https://acme-staging-v02.api.letsencrypt.org/directory»
kubectl logs cert-manager-56f5c44b5d-jn46m -n cert-manager -f
kubectl apply -f cluster-issuer/staging_issuer.yaml
Esto crea un secreto llamado «letsencrypt-staging-private-key».
kubectl get secret letsencrypt-staging-private-key -n cert-manager -o json

Producción:
Producción tiene «servidor: https://acme-v02.api.letsencrypt.org/directory»
kubectl logs cert-manager-56f5c44b5d-jn46m -n cert-manager -f
kubectl apply -f cluster-issuer/production_issuer.yaml

Esto crea un secreto llamado «letsencrypt-production-private-key».
kubectl get secret letsencrypt-production-private-key -n cert-manager -o json

Despliega una aplicación de ejemplo
Vamos a desplegar nuestras 3 aplicaciones de ejemplo.
kubectl apply -f sample-app/1-nginx-main-app.yaml
kubectl apply -f sample-app/2-nginx-green-app.yaml
kubectl apply -f sample-app/3-nginx-blue-app.yaml
Check the deployments, pods, and services created by the above commands.
kubectl get deployments
kubectl get pods kubectl
get service

Despliegue de Ingress
En primer lugar, vamos a desplegar un Ingress con Staging Issuer.
kubectl apply -f sample-app/4-tls-ingress.yaml
kubectl get ingress
kubectl describe ingress ingress-resource-3

Una vez creado el recurso Ingress, puedes ver todo lo que ha ocurrido en segundo plano para emitir el certificado para la sección TLS del Ingress.
kubectl get certificate -A
kubectl get certificaterequests.cert-manager.io -A
kubectl get orders.acme.cert-manager.io -A
kubectl get challenges.acme.cert-manager.io -A
kubectl get certificate -o json | grep secretName
kubectl get secret sample-kubernetes-tls -o yaml

Ahora se puede acceder a la aplicación a través de HTTPS, pero como hemos utilizado el Entorno de Escenificación del emisor Let’s Encrypt obtendremos una advertencia «Tu conexión a este sitio no es segura».

Despliega Ingress con el emisor de producción.
Ahora, vamos a eliminar el Ingress utilizando el Staging y a crear un nuevo Ingress apuntando al emisor de Producción.
kubectl delete -f sample-app/4-tls-ingress.yaml
kubectl apply -f sample-app/5-tls-ingress-prod-issuer.yaml
kubectl get ingress
kubectl describe ingress ingress-resource-3

Esta vez, si intentas acceder a la aplicación, no recibirás ninguna advertencia como «La conexión a este sitio no es segura».

Conclusión
En este artículo, hemos visto los pasos para configurar un Cert-Manager en el Cluster de Kubernetes. Desplegamos una aplicación de ejemplo y enrutamos el tráfico a través de la entrada basándonos en la ruta y aseguramos la conexión con HTTPS utilizando un certificado emitido por el emisor del clúster Let’s Encrypt. Primero emitimos un certificado utilizando el entorno de Let’s Encrypt Staging y luego utilizamos el entorno de Let’s Encrypt de producción
