Kubernetes v1.19 [stable]Un objeto de la API que administra el acceso externo a los servicios en un clúster, típicamente HTTP.
Un Ingress podría proveer balanceo de cargas, terminación SSL y hosting virtual basado en nombres.
Para mayor claridad, esta guía define los siguientes términos:
Un Ingress expone rutas HTTP y HTTPS desde el exterior del clúster a los servicios dentro del clúster. El control del tráfico es controlado por las reglas definidas en el recurso Ingress.
Aquí tienes un ejemplo simple de un Ingress que envía todo su tráfico a un Service:
Figure. Ingress
Un Ingress se puede configurar para otorgar URLs a los Services que son accesibles desde el exterior, para hacer balance de cargas del tráfico, finalizar SSL/TLS y ofrecer alojamiento virtual basado en nombres.
Un controlador de Ingress es responsable de complementar el Ingress, comúnmente con un balanceador de cargas, aunque también puedes configurar tu enrutador edge con frontends adicionales para ayudar a manejar el tráfico.
Un Ingress no expone puertos o protocolos arbitrariamente. Exponer servicios distintos de HTTP o HTTPS al internet usa un servicio de tipo Service.Type=NodePort o Service.Type=LoadBalancer.
Debes tener un controlador de Ingress para satisfacer a un Ingress. Crear únicamente un recurso Ingress no tiene ningún efecto.
Puede que necesites desplegar un controlador Ingress controller. Puedes elegir de un número de controladores de Ingress.
Idealmente, todos los controladores de Ingress deberían encajar con la especificación de referencia. En realidad, los distintos controladores de Ingress operan ligeramente diferente.
Un ejemplo mínimo de un recurso Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
spec:
ingressClassName: nginx-example
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80
Un Ingress necesita los campos apiVersion, kind, metadata y spec.
El nombre del objeto Ingress debe ser un
nombre de subdominio DNS
válido.
Para información general sobre cómo trabajar con archivos de configuración,
mira desplegando aplicaciones,
configurando contenedores,
administrando recursos.
Los Ingress usan anotaciones frecuentemente para configurar algunas opciones dependiendo del controlador de Ingress. Distintos controladores de Ingress soportan anotaciones diferentes. Revisa la documentación para tu elección del controlador de Ingress para saber qué anotaciones son soportadas.
La especificación Ingress tiene toda la información que necesitas para configurar un balanceador de cargas o un servidor proxy. Mucho más importante, contiene un listado de reglas que emparejan contra todas las peticiones entrantes. El recurso Ingress solo soporta reglas para dirigir el tráfico HTTP(S).
Si se omite la ingressClassName, se define
una clase Ingress por defecto.
Existen algunos controladores de Ingress,
que trabajan sin la definición de una IngressClass por defecto.
Se recomienda especificar el IngressClass por defecto como se
muestra abajo.
Cada regla HTTP contiene la siguiente información:
/testpath), cada una de las cuales tiene
un backend asociado con un service.name y un service.port.name o
un service.port.number. Tanto el host como la ruta deben coincidir con el
contenido de una petición de entrada antes que el balanceador de cargas dirija
el tráfico al Service referenciado.Un defaultBackend se configura frecuentemente en un controlador de Ingress
para dar servicio a cualquier petición que no coincide con una ruta en la
especificación.
Un Ingress sin reglas envía todo el tráfico a un único backend
y .spec.defaultBackend está en el backend que debería manejar las peticiones
en ese caso.
El defaultBackend es una opción de configuración convencional
del controlador Ingress y no se especifica en tus recursos del Ingress.
Si no se especifican reglas .spec.rules, se debe
especificar .spec.defaultBackend.
Si no se establece un defaultBackend, las peticiones que no coincidan con
ninguna de las reglas las decidirá el controlador ingress (consulta la
documentación de tu controlador de ingress para saber cómo maneja este caso).
Si ninguno de los hosts o rutas coincide con la petición HTTP en los objetos Ingress, el tráfico será enrutado a tu backend predeterminado.
Un Resource backend es una referencia de objeto
(ObjectRef en inglés)
a otro recurso de Kubernetes dentro del mismo espacio de nombres que el objeto
Ingress.
Este Resource es mutuamente exclusivo con el Service,
y la validación fallará si ambos se especifican.
Un uso común para un Resource backend es para ingresar datos a un backend de almacenamiento de datos con activos estáticos.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-resource-backend
spec:
defaultBackend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: static-assets
rules:
- http:
paths:
- path: /icons
pathType: ImplementationSpecific
backend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: icon-assets
Luego de crear el Ingress mencionado arriba, puedes verlo con el siguiente comando:
kubectl describe ingress ingress-resource-backend
Name: ingress-resource-backend
Namespace: default
Address:
Default backend: APIGroup: k8s.example.com, Kind: StorageBucket, Name: static-assets
Rules:
Host Path Backends
---- ---- --------
*
/icons APIGroup: k8s.example.com, Kind: StorageBucket, Name: icon-assets
Annotations: <none>
Events: <none>
Se requiere que cada ruta de un Ingress tenga un tipo de ruta correspondiente.
Las Rutas que no incluyen un pathType explícito fallarán la validación.
Hay 3 tipos de rutas soportadas:
ImplementationSpecific: Con este tipo de ruta, la coincidencia depende de la
IngressClass.
Las implementaciones pueden tratar esto como un pathType separado o
tratarlas de forma idéntica a los tipos de ruta Prefix o Exact.
Exact: Coincide la ruta de la URL exactamente con sensibilidad a mayúsculas
y minúsculas.
Prefix: Coincide basado en el prefijo de una ruta URL dividida por /.
La coincidencia es sensible a mayúsculas y minúsculas, y hecha en un elemento
de la ruta por elemento.
Un elemento de la ruta refiere a la lista de etiquetas en la ruta dividida por
el separador /.
Una petición es una coincidencia para la ruta p si cada p es un elemento
prefijo de p de la ruta requerida.
/foo/bar
coincide con /foo/bar/baz, pero no coincide con /foo/barbaz).| Tipo | Ruta(s) | Ruta de la(s) peticion(es) | ¿Coincide? |
|---|---|---|---|
| Prefijo | / | (todas las rutas) | Sí |
| Exacto | /foo | /foo | Si |
| Exacto | /foo | /bar | No |
| Exacto | /foo | /foo/ | No |
| Exacto | /foo/ | /foo | No |
| Prefijo | /foo | /foo, /foo/ | Si |
| Prefijo | /foo/ | /foo, /foo/ | Si |
| Prefijo | /aaa/bb | /aaa/bbb | No |
| Prefijo | /aaa/bbb | /aaa/bbb | Si |
| Prefijo | /aaa/bbb/ | /aaa/bbb | Si, ignora la barra diagonal |
| Prefijo | /aaa/bbb | /aaa/bbb/ | Si, coincide con barra diagonal |
| Prefijo | /aaa/bbb | /aaa/bbb/ccc | Si, coincide con la subruta |
| Prefijo | /aaa/bbb | /aaa/bbbxyz | No, no coincide con el prefijo de cadena |
| Prefijo | /, /aaa | /aaa/ccc | Si, coincide con el prefijo /aaa |
| Prefijo | /, /aaa, /aaa/bbb | /aaa/bbb | Si, coincide con el prefijo /aaa/bbb |
| Prefijo | /, /aaa, /aaa/bbb | /ccc | Si, coincide con el prefijo/ |
| Prefijo | /aaa | /ccc | No, usa el backend predeterminado |
| Mezclado | /foo (Prefijo), /foo (Exacto) | /foo | Si, prefiere la coincidencia exacta |
En algunos casos, muchas rutas dentro de un Ingress coincidirán con una petición. En esos casos, la precedencia se le dará al primero con la ruta más larga que coincide. Si dos rutas todavía coinciden por igual, se le dará precedencia a las rutas con una coincidencia de ruta exacta sobre las rutas que contienen prefijos.
Los hosts pueden ser coincidencias exactas
(por ejemplo “foo.bar.com”) o un comodín (por ejemplo “*.foo.com”).
Las coincidencias precisas requieren que el encabezado host coincida con el
campo host.
Las coincidencias de comodín requieren que el encabezado host sea igual al
sufijo de la regla del comodín.
| Host | Encabezado Host | ¿Coincidencia? |
|---|---|---|
*.foo.com | bar.foo.com | Coincide basado en el sufijo común |
*.foo.com | baz.bar.foo.com | No coincide, el comodín solo cubre una etiqueta DNS |
*.foo.com | foo.com | No coincide, el comodín solo cubre una etiqueta DNS |
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-wildcard-host
spec:
rules:
- host: "foo.bar.com"
http:
paths:
- pathType: Prefix
path: "/bar"
backend:
service:
name: service1
port:
number: 80
- host: "*.foo.com"
http:
paths:
- pathType: Prefix
path: "/foo"
backend:
service:
name: service2
port:
number: 80
Los Ingress pueden ser implementados por distintos controladores, comúnmente con una configuración distinta. Cada Ingress debería especificar una clase, una referencia a un recurso IngressClass que contiene información adicional incluyendo el nombre del controlador que debería implementar la clase.
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb
spec:
controller: example.com/ingress-controller
parameters:
apiGroup: k8s.example.com
kind: IngressParameters
name: external-lb
El campo .spec.parameters de un IngressClass te permite hacer referencia a
otro recurso que proporciona la configuración relacionada con esa IngressClass.
El tipo específico de parámetros a usar depende del controlador de Ingress que
especificas en el campo spec.controller de la IngressClass.
Dependiendo de tu controlador de ingress, podrías ser capaz de usar parámetros que se establecen en todo el clúster, o solamente para un namespace.
El alcance por defecto de los parámetros IngressClass es para todo el clúster.
Si estableces el campo spec.parameters y no estableces el
campo spec.parameters.scope,
entonces el IngressClass se refiere al recurso cuyo alcance es todo el clúster.
El atributo kind (en combinación con el apiGroup)
de los parámetros se refiere a la API con alcance a todo el clúster
(posiblemente un recurso personalizado), y el name de los parámetros
identifica al recurso del clúster específico para esa API.
Por ejemplo:
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb-1
spec:
controller: example.com/ingress-controller
parameters:
# Los parámetros para este IngressClass se especifican en un
# ClusterIngressParameter (API group k8s.example.net) llamado
# "external-config-1". Esta definición le indica a Kubernetes
# de buscar por un parámetro de recurso con alcance a todo el clúster.
scope: Cluster
apiGroup: k8s.example.net
kind: ClusterIngressParameter
name: external-config-1
Kubernetes v1.23 [stable]Si estableces el campo spec.parameters y el spec.parameters.scope
al Namespace,
entonces el IngressClass se refiere al recurso cuyo alcance es el namespace.
También debes establecer el campo namespace dentro de spec.parameters con el
Namespace que contiene los parámetros que quieres usar.
El atributo kind (en combinación con apiGroup)
de los parámetros se refiere a la API restringida por un Namespace (por ejemplo:
ConfigMap), y el name de los parámetros identifica al recurso específico en el
namespace que has especificado en namespace.
Los parámetros con alcance al Namespace ayudan al operador del clúster a delegar el control sobre la configuración (por ejemplo, ajustes del balanceador de cargas, definición de una API gateway) que se usa para una carga de trabajo. Si utilizas un parámetro con alcance al Namespace entonces:
La API de la IngressClass por sí misma siempre tiene alcance al clúster.
Aquí hay un ejemplo de una IngressClass que hace referencia a parámetros que están restringidos por un Namespace:
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb-2
spec:
controller: example.com/ingress-controller
parameters:
# Los parámetros para esta IngressClass se especifican en un
# IngressParameter (API group k8s.example.com) llamado "external-config",
# que está en el namespace "external-configuration".
scope: Namespace
apiGroup: k8s.example.com
kind: IngressParameter
namespace: external-configuration
name: external-config
Antes que el recurso IngressClass y el campo ingressClassName se añadieran a
Kubernetes
1.18,
las clases Ingress se especificaban con una
anotación kubernetes.io/ingress.class en el Ingress.
Esta anotación nunca se definió formalmente,
pero era ampliamente soportada por los controladores de Ingress.
El nuevo campo ingressClassName en los recursos Ingress es un reemplazo para
esa anotación, pero no es un equivalente directo.
Mientras que la anotación se utilizaba generalmente para hacer referencia al
nombre del controlador de Ingress que debería implementar el Ingress, el campo
es una referencia a un recurso IngressClass que contiene configuración adicional
del Ingress, incluyendo el nombre del controlador Ingress.
Puedes marcar un ingressClass en particular por defecto para tu clúster.
Establecer la anotación ingressclass.kubernetes.io/is-default-class a true
en un recurso IngressClass
asegurará que los nuevos Ingress sin un campo ingressClassName especificado
sean asignados a esta IngressClass por defecto.
ingressClassName especificado.
Puedes resolver esto asegurándote que como máximo 1 IngressClass está marcado
como el predeterminado en tu clúster.Existen algunos controladores de ingress,
que funcionan sin una definición de una ingressClass.
Se recomienda especificar el IngressClass predeterminado:
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
labels:
app.kubernetes.io/component: controller
name: example-class
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: k8s.io/example-class
Hay conceptos existentes de Kubernetes que te permiten exponer un Service único (mirar alternativas). También puedes hacerlo con un Ingress especificando un backend predeterminado sin reglas.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
spec:
defaultBackend:
service:
name: test
port:
number: 80
Si lo creas usando kubectl apply -f podrías mirar el estado del Ingress que
has creado:
kubectl get ingress test-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
test-ingress external-lb * 203.0.113.123 80 59s
Donde 203.0.113.123 es la IP asignada por el controlador Ingress para
satisfacer este Ingress.
<pending>.Una configuración de abanico enruta el tráfico de una única dirección IP a más de un Service, basado en la URI HTTP solicitada. Un Ingress te permite tener el número de balanceadores de carga al mínimo. Por ejemplo, una configuración como:
Figure. Ingress Fan Out
Requeriría un Ingress como este:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: simple-fanout-example
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: service1
port:
number: 4200
- path: /bar
pathType: Prefix
backend:
service:
name: service2
port:
number: 8080
Cuando creas el Ingress con kubectl apply -f:
kubectl describe ingress simple-fanout-example
Name: simple-fanout-example
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:4200 (10.8.0.90:4200)
/bar service2:8080 (10.8.0.91:8080)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 22s loadbalancer-controller default/test
El controlador de Ingress aprovisiona un balanceador de cargas específico para
la implementación que satisface al Ingress,
mientras los Services (service1, service2) existan.
Cuando sea así, podrás ver la dirección del balanceador de cargas en el campo de dirección.
Los hostings virtuales basados en el nombre soportan enrutado de tráfico HTTP a nombres hosts múltiples con la misma dirección IP.
Figure. Ingress Name Based Virtual hosting
El siguiente Ingress le dice al balanceador de cargas de respaldo de enrutar las peticiones basadas en el encabezado del Host .
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: bar.foo.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
Si creas un recurso Ingress sin ningún host definido en las reglas, luego cualquier tráfico web a la dirección IP de tu controlador Ingress puede coincidir sin requerir un host virtual basado en el nombre.
Por ejemplo, el siguiente Ingress enruta el tráfico solicitado
para first.bar.com a service1, second.bar.com a service2,
y cualquier tráfico cuyo encabezado de petición del host no coincida
con first.bar.com y second.bar.com a service3.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress-no-third-host
spec:
rules:
- host: first.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: second.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
- http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service3
port:
number: 80
Puedes segurizar un Ingress especificando un Secret que contiene una clave privada TLS y un certificado.
El recurso Ingress solo soporta un puerto TLS,
el 443,
y asume la terminación TLS en el punto del ingress
(El tráfico al Service y sus Pods es en texto plano).
Si la sección de configuración TLS especifica hosts diferentes,
se multiplexan en el mismo puerto de acuerdo con el hostname especificado a
través de la extensión TLS SNI (teniendo el cuenta que el controlador de Ingress
soporte SNI).
El secreto TLS debe contener claves llamadas tls.crt y tls.key que contiene
el certificado y llave privad para usar TLS.
Por ejemplo:
apiVersion: v1
kind: Secret
metadata:
name: testsecret-tls
namespace: default
data:
tls.crt: base64 encoded cert
tls.key: base64 encoded key
type: kubernetes.io/tls
Al hacer referencia a este secreto en un Ingress le indica al controlador
Ingress de segurizar el canal desde el cliente al balanceador de cargas usando
TLS.
Necesitas asegurarte que el secreto TLS que has creado viene de un certificado que
contiene un nombre común (CN), también conocido como Nombre de dominio
calificado (FQDN en inglés)
para https-example.foo.com.
hosts en la sección tls tienen que coincidir
explícitamente con el host en la sección rules.apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-example-ingress
spec:
tls:
- hosts:
- https-example.foo.com
secretName: testsecret-tls
rules:
- host: https-example.foo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
Un controlador de Ingress está configurado por defecto con algunos ajustes de política de balanceo de cargas que aplica a todos los Ingress, como los algoritmos de balanceo de cargas, esquema de pesos del backend y otros. Otros conceptos más avanzados de balanceo de cargas (ej., sesiones persistentes, pesos dinámicos) no están expuestos todavía a través del Ingress. En su lugar, obtienes estas características a través del balanceador de cargas usado por un Service.
Vale la pena apuntar que aunque las revisiones de salud no se exponen directamente a través del Ingress, existen conceptos paralelos en Kubernetes tales como readiness probes que permiten lograr el mismo resultado final. Revisa la documentación específica del controlador para conocer cómo manejar estas revisiones de salud (por ejemplo: GCE).
Para actualizar un Ingress existente a un nuevo Host, puedes actualizarlo editando el recurso:
kubectl describe ingress test
Name: test
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:80 (10.8.0.90:80)
Annotations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 35s loadbalancer-controller default/test
kubectl edit ingress test
Esto muestra un editor con la configuración existente en formato YAML. Modifícalo para incluir el nuevo Host:
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
service:
name: service1
port:
number: 80
path: /foo
pathType: Prefix
- host: bar.baz.com
http:
paths:
- backend:
service:
name: service2
port:
number: 80
path: /foo
pathType: Prefix
#..
Luego de guardar tus cambios, kubectl actualiza el recurso en el servidor API, que le indica al controlador Ingress de reconfigurar el balanceador de cargas.
Verifica esto:
kubectl describe ingress test
Name: test
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:80 (10.8.0.90:80)
bar.baz.com
/foo service2:80 (10.8.0.91:80)
Annotations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 45s loadbalancer-controller default/test
Puedes lograr el mismo resultado invocando kubectl replace -f en un fichero
YAML de Ingress.
Las técnicas para distribuir el tráfico entre dominios de falla difieren entre los proveedores de la nube. Revisa la documentación del Ingress controller relevante para detalles.
Puedes exponer un Service de muchas maneras que no involucran directamente el recurso Ingress: