En esta página, se muestra cómo configurar varios certificados SSL para recursos de Ingress en clústeres de Google Kubernetes Engine (GKE).
Descripción general
Si deseas aceptar solicitudes HTTPS de los clientes, el balanceador de cargas de aplicaciones debe contar con un certificado para que pueda demostrar su identidad a los clientes. También debe tener una clave privada para completar el protocolo de enlace HTTPS.
Cuando el balanceador de cargas acepta una solicitud HTTP(S) de un cliente, el tráfico entre el cliente y el balanceador de cargas se encripta mediante TLS. Sin embargo, el balanceador de cargas finaliza el cifrado TLS y reenvía la solicitud sin encriptación a la aplicación. Cuando configuras un balanceador de cargas de aplicaciones a través de Ingress, puedes configurarlo para que presente hasta diez certificados TLS al cliente.
El balanceador de cargas usa la indicación de nombre del servidor (SNI) para determinar qué certificado presentar al cliente, según el nombre de dominio en el protocolo de enlace TLS. Si el cliente no usa SNI o usa un nombre de dominio que no coincide con el nombre común (CN) en uno de los certificados, el balanceador de cargas usa el primer certificado que se encuentra en el Ingress.
En el siguiente diagrama, se muestra un balanceador de cargas que envía tráfico a backends diferentes, según el nombre de dominio que se usa en la solicitud:
Puedes proporcionar un balanceador de cargas de aplicaciones con certificados SSL con los siguientes métodos:
Certificado SSL de Google Cloud que administras. El certificado SSL usa un certificado ya compartido que subes al proyecto de Google Cloud.
Secretos de Kubernetes. El secreto contiene un certificado y una clave que tú mismo creas. Debes agregar el nombre del Secret al campo
tls
del manifiesto de Ingress.
Puedes usar más de un método en el mismo Ingress. Esto permite migraciones entre métodos sin tiempo de inactividad.
Panorama general
Esta es una descripción general de los pasos en este documento:
Crea una implementación.
Crea un servicio.
Crea dos archivos de certificado y dos archivos de claves o dos objetos
ManagedCertificate
. Debes configurar estos certificados en el mismo proyecto y en el mismo espacio de nombres en el que se implementa el balanceador de cargas.Crea un Ingress que use Secretos o certificados ya compartidos. Cuando creas el Ingress, GKE crea y configura un balanceador de cargas de aplicaciones.
Prueba el balanceador de cargas de aplicaciones.
Antes de comenzar
Antes de comenzar, asegúrate de haber realizado las siguientes tareas:
- Habilita la API de Google Kubernetes Engine. Habilitar la API de Google Kubernetes Engine
- Si deseas usar Google Cloud CLI para esta tarea, instala y, luego, inicializa gcloud CLI. Si ya instalaste gcloud CLI, ejecuta
gcloud components update
para obtener la versión más reciente.
- Debes tener dos nombres de dominio. Los nombres de dominio no deben tener más de 63 caracteres.
Limitaciones
- Para los balanceadores de cargas de aplicaciones internos, debes inhabilitar HTTP en el manifiesto de Ingress. Esto no es necesario con el balanceador de cargas externo.
- No debes cambiar ni actualizar manualmente la configuración del balanceador de cargas de la aplicación. Esto significa que no debes editar ninguno de los componentes del balanceador de cargas, incluidos los proxies de destino, los mapas de URL y los servicios de backend. GKE reemplazará todos los cambios que realices.
Crear una implementación
Guarda el siguiente manifiesto como
my-mc-deployment.yaml
:apiVersion: apps/v1 kind: Deployment metadata: name: my-mc-deployment spec: selector: matchLabels: app: products department: sales replicas: 3 template: metadata: labels: app: products department: sales spec: containers: - name: hello image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0" env: - name: "PORT" value: "50001" - name: hello-again image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0" env: - name: "PORT" value: "50002"
En este manifiesto, se describe un Deployment con tres Pods. Cada Pod tiene dos contenedores. Un contenedor ejecuta
hello-app:1.0
y escucha en el puerto TCP 50001. El otro contenedor ejecutahello-app:2.0
y escucha en el puerto TCP 50002.Aplica el manifiesto al clúster:
kubectl apply -f my-mc-deployment.yaml
Crea un Service
Guarda el siguiente manifiesto como
my-mc-service.yaml
:apiVersion: v1 kind: Service metadata: name: my-mc-service spec: type: NodePort selector: app: products department: sales ports: - name: my-first-port protocol: TCP port: 60001 targetPort: 50001 - name: my-second-port protocol: TCP port: 60002 targetPort: 50002
En este manifiesto, se describe un Service con las siguientes propiedades:
selector
: Especifica que cualquier Pod que tenga las etiquetasapp: products
ydepartment: sales
es miembro de este servicio.ports
: Especifica que, cuando un cliente envía una solicitud al servicio enmy-first-port
, GKE reenvía la solicitud a uno de los Pods miembro en el puerto 50001. Cuando un cliente envía una solicitud al servicio enmy-second-port
, GKE reenvía la solicitud a uno de los pods miembro en el puerto 50002.
Aplica el manifiesto al clúster:
kubectl apply -f my-mc-service.yaml
Crea certificados y claves
Para hacer los ejercicios en esta página, necesitas dos certificados, cada uno con una clave correspondiente. Cada certificado debe tener un nombre común (CN, por sus siglas en inglés) que sea igual a un nombre de dominio de tu propiedad.
Si ya tienes dos archivos de certificado con los valores adecuados para el nombre común, puedes pasar a la siguiente sección.
Certificados administrados por el usuario
Crea tu primera clave:
openssl genrsa -out test-ingress-1.key 2048
Crea tu primera solicitud de firma de certificado:
openssl req -new -key test-ingress-1.key -out test-ingress-1.csr \ -subj "/CN=FIRST_DOMAIN"
Reemplaza
FIRST_DOMAIN
por un nombre de dominio de tu propiedad, comoexample.com
.Crea el primer certificado:
openssl x509 -req -days 365 -in test-ingress-1.csr -signkey test-ingress-1.key \ -out test-ingress-1.crt
Crea tu segunda clave:
openssl genrsa -out test-ingress-2.key 2048
Crea tu segunda solicitud de firma de certificado:
openssl req -new -key test-ingress-2.key -out test-ingress-2.csr \ -subj "/CN=SECOND_DOMAIN"
Reemplaza
SECOND_DOMAIN
por otro nombre de dominio de tu propiedad, comoexamplepetstore.com
.Crea el segundo certificado:
openssl x509 -req -days 365 -in test-ingress-2.csr -signkey test-ingress-2.key \ -out test-ingress-2.crt
Para obtener más información sobre los certificados y las claves, consulta la Descripción general de certificados SSL.
Ahora tienes dos archivos de certificado y dos archivos de claves.
En las tareas restantes, se usan los siguientes marcadores de posición para hacer referencia a tus dominios, certificados y claves:
FIRST_CERT_FILE
es la ruta de acceso a tu primer archivo de certificado.FIRST_KEY_FILE
es la ruta al archivo de claves que acompaña a tu primer certificado.FIRST_DOMAIN
es un nombre de dominio de tu propiedad.FIRST_SECRET_NAME
: El nombre del Secret que contiene tu primer certificado y clave.SECOND_CERT_FILE
es la ruta a tu segundo archivo de certificado.SECOND_KEY_FILE
es la ruta al archivo de claves que acompaña a tu segundo certificado.SECOND_DOMAIN
es un segundo nombre de dominio de tu propiedad.SECOND_SECRET_NAME
: El nombre del Secret que contiene tu segundo certificado y clave.
Especifica certificados para el Ingress
El paso siguiente es crear un objeto Ingress. En el manifiesto de Ingress, puedes usar uno de los siguientes métodos a fin de proporcionar certificados para el balanceador de cargas:
- Secrets
- Certificados ya compartidos
Secrets
Crea un Secreto que contenga tu primer certificado y tu primera clave:
kubectl create secret tls FIRST_SECRET_NAME \ --cert=FIRST_CERT_FILE \ --key=FIRST_KEY_FILE
Crea un secreto que contenga el segundo certificado y la segunda clave:
kubectl create secret tls SECOND_SECRET_NAME \ --cert=SECOND_CERT_FILE \ --key=SECOND_KEY_FILE
Crea un Ingress
Guarda el siguiente manifiesto como
my-mc-ingress.yaml
:apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-mc-ingress spec: tls: - secretName: FIRST_SECRET_NAME - secretName: SECOND_SECRET_NAME rules: - host: FIRST_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60001 - host: SECOND_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60002
Reemplaza
FIRST_DOMAIN
ySECOND_DOMAIN
por nombres de dominio de tu propiedad, comoexample.com
yexamplepetstore.com
.Aplica el manifiesto al clúster:
kubectl apply -f my-mc-ingress.yaml
Describe tu Ingress:
kubectl describe ingress my-mc-ingress
El resultado es similar al siguiente:
Name: my-mc-ingress Address: 203.0.113.1 ... TLS: FIRST_SECRET_NAME terminates SECOND_SECRET_NAME terminates Rules: Host Path Backends ---- ---- -------- FIRST_DOMAIN my-mc-service:my-first-port (<none>) SECOND_DOMAIN my-mc-service:my-second-port (<none>) Annotations: ... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 3m loadbalancer-controller default/my-mc-ingress Normal CREATE 2m loadbalancer-controller ip: 203.0.113.1
El resultado muestra que dos Secretos están asociados con el Ingress. El resultado también muestra la dirección IP externa del balanceador de cargas. Si no se configuró la dirección IP externa, espera unos minutos y vuelve a ejecutar el comando.
Certificados ya compartidos
Crea un certificado:
gcloud compute ssl-certificates create FIRST_CERT_NAME \ --certificate=FIRST_CERT_FILE \ --private-key=FIRST_KEY_FILE
Reemplaza lo siguiente:
FIRST_CERT_NAME
es el nombre de tu primer certificado.FIRST_CERT_FILE
: Es el primer archivo de certificado.FIRST_KEY_FILE
: Es el primer archivo de claves.
Crea un segundo certificado:
gcloud compute ssl-certificates create SECOND_CERT_NAME \ --certificate=SECOND_CERT_FILE \ --private-key=SECOND_KEY_FILE
Reemplaza lo siguiente:
SECOND_CERT_NAME
es el nombre de tu segundo certificado.SECOND_CERT_FILE
: El segundo archivo de certificado.SECOND_KEY_FILE
: Es el segundo archivo de claves.
Observa tus recursos de certificado:
gcloud compute ssl-certificates list
El resultado es similar al siguiente:
NAME CREATION_TIMESTAMP FIRST_CERT_NAME 2018-11-03T12:08:47.751-07:00 SECOND_CERT_NAME 2018-11-03T12:09:25.359-07:00
Crea un Ingress
Guarda el siguiente manifiesto como
my-psc-ingress.yaml
:apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-psc-ingress annotations: ingress.gcp.kubernetes.io/pre-shared-cert: "FIRST_CERT_NAME,SECOND_CERT_NAME" spec: rules: - host: FIRST_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60001 - host: SECOND_DOMAIN http: paths: - pathType: ImplementationSpecific backend: service: name: my-mc-service port: number: 60002
Reemplaza
FIRST_DOMAIN
ySECOND_DOMAIN
por tus nombres de dominio.En este manifiesto, se describe un Ingress que enumera recursos de certificados ya compartidos en una anotación.
Aplica el manifiesto al clúster:
kubectl apply -f my-psc-ingress.yaml
Describe tu Ingress:
kubectl describe ingress my-psc-ingress
El resultado es similar al siguiente:
Name: my-psc-ingress Address: 203.0.113.2 ... Rules: Host Path Backends ---- ---- -------- FIRST_DOMAIN my-mc-service:my-first-port (<none>) SECOND_DOMAIN my-mc-service:my-second-port (<none>) Annotations: ... ingress.gcp.kubernetes.io/pre-shared-cert: FIRST_CERT_NAME,SECOND_CERT_NAME ... ingress.kubernetes.io/ssl-cert: FIRST_CERT_NAME,SECOND_CERT_NAME Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 2m loadbalancer-controller default/my-psc-ingress Normal CREATE 1m loadbalancer-controller ip: 203.0.113.2
En el resultado se muestra que el Ingress está asociado con certificados ya compartidos llamados
FIRST_CERT_NAME
ySECOND_CERT_NAME
. El resultado también muestra la dirección IP externa del balanceador de cargas. Si no se configuró la dirección IP externa, espera unos minutos y vuelve a intentar el comando.
Prueba el balanceador de cargas
Espera unos cinco minutos para que GKE termine de configurar el balanceador de cargas.
Para probar el balanceador de cargas, debes tener dos nombres de dominio y ambos nombres deben resolver la dirección IP externa del balanceador de cargas de la aplicación externo.
Envía una solicitud al balanceador de cargas mediante tu primer nombre de dominio:
curl -v https://FIRST_DOMAIN
Es posible que debas usar la opción
curl -k
para realizar una transferencia SSL no segura, de modo quecurl
aceptará certificados autofirmados.El resultado es similar al siguiente:
... * Trying 203.0.113.1... ... * Connected to FIRST_DOMAIN (203.0.113.1) port 443 (#0) ... * TLSv1.2 (IN), TLS handshake, Certificate (11): ... * Server certificate: * subject: CN=FIRST_DOMAIN ... > Host: FIRST_DOMAIN.com ... Hello, world! Version: 1.0.0 ...
El resultado muestra que el primer certificado se usó en el protocolo de enlace TLS.
Envía una solicitud al balanceador de cargas mediante el segundo nombre de dominio:
curl -v https://SECOND_DOMAIN
El resultado es similar al siguiente:
... * Trying 203.0.113.1... ... * Connected to SECOND_DOMAIN (203.0.113.1) port 443 (#0) ... * Server certificate: * subject: CN=SECOND_DOMAIN ... > Host: SECOND_DOMAIN ... Hello, world! Version: 2.0.0
Esta salida muestra que el segundo certificado se usó en el protocolo de enlace TLS.
El campo hosts de un objeto Ingress
Un IngressSpec tiene un campo tls
que es un arreglo de objetos IngressTLS. Cada objeto IngressTLS
tiene un campo hosts
y un campo SecretName
.
En GKE, el campo hosts
no se usa. GKE lee el nombre común (CN) del certificado en el secreto. Si el nombre común coincide con el nombre de dominio en una solicitud del cliente, entonces el balanceador de cargas presenta al cliente el certificado coincidente.
¿Qué certificado se presenta?
El balanceador de cargas elige un certificado de acuerdo con las siguientes reglas:
Si los Secretos y los certificados ya compartidos aparecen en el Ingress, los certificados ya compartidos tienen prioridad sobre los Secretos. En otras palabras, los Secretos siguen incluidos, pero los certificados ya compartidos se presentan primero.
Si ningún certificado tiene un nombre común (CN) que coincida con el nombre de dominio en la solicitud del cliente, el balanceador de cargas presenta el certificado principal.
Para los secretos enumerados en el bloque
tls
, el certificado principal se encuentra en el primer secreto de la lista.Para los certificados ya compartidos que se enumeran en la anotación, el certificado principal es el primer certificado en la lista.
Prácticas recomendadas para la rotación de certificados
Si deseas rotar el contenido de tu Secret o un certificado ya compartido, sigue estas prácticas recomendadas:
- Crea un nuevo Secreto o certificado ya compartido con un nombre diferente que contenga los datos del certificado nuevo. Conecta este recurso (junto con el existente) a tu Ingress siguiente las instrucciones anteriores. Una vez que los cambios sean de tu agrado, puedes quitar el certificado anterior del Ingress.
- Si no te molesta interrumpir el tráfico, puedes quitar el recurso anterior del Ingress, aprovisionar un recurso nuevo con el mismo nombre, pero de contenido diferente y, luego, volver a conectarlo al Ingress.
Soluciona problemas
Especificar los Secretos no válidos o que no existen genera un error de evento de Kubernetes. Puedes verificar los eventos de Kubernetes para un Ingress de la siguiente manera:
kubectl describe ingress
El resultado es similar al siguiente:
Name: my-ingress
Namespace: default
Address: 203.0.113.3
Default backend: hello-server:8080 (10.8.0.3:8080)
TLS:
my-faulty-Secret terminates
Rules:
Host Path Backends
---- ---- --------
* * my-service:443 (10.8.0.3:443)
Events:
Error during sync: cannot get certs for Ingress default/my-ingress:
Secret "my-faulty-ingress" has no 'tls.crt'