Un objet API qui gère l'accès externe aux services d'un cluster, typiquement HTTP.
L'Ingress peut fournir un équilibrage de charge, une terminaison SSL ainsi qu'un hébergement virtuel basé sur un nom.
Le projet Kubernetes recommande d'utiliser Gateway plutôt qu'Ingress. L'API Ingress est figée.
Cela signifie que :
Par souci de clarté, ce guide définit les termes suivants :
Un Ingress expose des routes HTTP et HTTPS depuis l'extérieur du cluster vers des services du cluster. Le routage du trafic est contrôlé par des règles définies sur la ressource Ingress.
Voici un exemple simple dans lequel un Ingress envoie tout son trafic vers un seul Service :
Figure. Ingress
Un Ingress peut être configuré pour donner aux Services des URL accessibles de l'extérieur, équilibrer la charge du trafic, assurer la terminaison SSL / TLS et proposer un hébergement virtuel basé sur le nom. Un contrôleur d'Ingress est chargé de mettre en œuvre l'Ingress, généralement avec un équilibreur de charge (load balancer), mais il peut aussi configurer votre routeur de bordure ou des frontaux supplémentaires pour aider à gérer le trafic.
Un Ingress n'expose pas de ports ni de protocoles arbitraires. Pour exposer à Internet des services autres que HTTP et HTTPS, on utilise généralement un Service de type Service.Type=NodePort ou Service.Type=LoadBalancer.
Vous devez disposer d'un contrôleur d'Ingress pour qu'un Ingress soit pris en compte. La simple création d'une ressource Ingress n'a aucun effet.
Vous avez le choix entre de nombreux contrôleurs d'Ingress.
Idéalement, tous les contrôleurs d'Ingress devraient respecter la spécification de référence. En pratique, les différents contrôleurs d'Ingress fonctionnent de manière légèrement différente.
Exemple de ressource Ingress minimale :
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 a besoin des champs apiVersion, kind, metadata et spec.
Le nom d'un objet Ingress doit être un
nom de sous-domaine DNS valide.
Pour des informations générales sur l'utilisation des fichiers de configuration, consultez
déployer des applications,
configurer des conteneurs et
gérer des ressources.
Les contrôleurs d'Ingress utilisent souvent des annotations pour configurer leur comportement.
Consultez la documentation du contrôleur d'Ingress que vous avez choisi pour savoir quelles annotations sont attendues ou prises en charge.
La spec de l'Ingress contient toutes les informations nécessaires pour configurer un équilibreur de charge ou un serveur proxy. Elle contient surtout une liste de règles comparées à toutes les requêtes entrantes. La ressource Ingress ne prend en charge que des règles pour diriger du trafic HTTP(S).
Si ingressClassName est omis, une classe d'Ingress par défaut
devrait être définie.
Certains contrôleurs d'Ingress fonctionnent même sans définition d'une IngressClass par défaut. Même si vous utilisez un contrôleur d'Ingress capable de fonctionner sans IngressClass, le projet Kubernetes recommande tout de même de définir une IngressClass par défaut.
Chaque règle HTTP contient les informations suivantes :
/testpath), chacun associé à un
backend défini par un service.name et un service.port.name ou un
service.port.number. L'hôte et le chemin doivent tous deux correspondre au contenu
d'une requête entrante pour que l'équilibreur de charge dirige le trafic vers le
Service référencé.Un defaultBackend est souvent configuré dans un contrôleur d'Ingress pour traiter toutes les requêtes
qui ne correspondent à aucun chemin de la spec.
Un Ingress sans règles envoie tout le trafic vers un unique backend par défaut, et .spec.defaultBackend
est le backend qui doit traiter les requêtes dans ce cas.
Le defaultBackend est habituellement une option de configuration du
contrôleur d'Ingress et
n'est pas indiqué dans vos ressources Ingress.
Si .spec.rules n'est pas défini, .spec.defaultBackend doit l'être.
Si defaultBackend n'est pas défini, c'est le contrôleur d'Ingress qui décide du traitement des requêtes
qui ne correspondent à aucune règle (consultez la documentation de votre contrôleur d'Ingress pour savoir comment il gère ce cas).
Si aucun des hôtes ou chemins des objets Ingress ne correspond à la requête HTTP, le trafic est acheminé vers votre backend par défaut.
Un backend Resource est une référence (ObjectRef) vers une autre ressource Kubernetes du
même namespace que l'objet Ingress. Resource et Service s'excluent mutuellement :
la validation échoue si les deux sont indiqués. Un backend Resource sert
couramment à faire entrer des données dans un backend de stockage objet
contenant des ressources statiques.
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
Après avoir créé l'Ingress ci-dessus, vous pouvez l'afficher avec la commande suivante :
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>
Chaque chemin d'un Ingress doit avoir un type de chemin correspondant. Les chemins
sans pathType explicite échouent à la validation. Trois types de chemins
sont pris en charge :
ImplementationSpecific : avec ce type de chemin, la correspondance dépend de
l'IngressClass. Les implémentations peuvent le traiter comme un pathType distinct ou
de la même manière que les types de chemins Prefix ou Exact.
Exact : correspond exactement au chemin de l'URL, en tenant compte de la casse.
Prefix : correspond selon un préfixe du chemin de l'URL découpé par /. La correspondance
tient compte de la casse et se fait élément par élément. Un élément de chemin désigne
la liste des libellés du chemin découpé par le séparateur /. Une requête correspond
au chemin p si chaque p est un préfixe, élément par élément, de p dans le
chemin de la requête.
/foo/bar
correspond à /foo/bar/baz, mais pas à /foo/barbaz).| Type | Chemin(s) | Chemin(s) de la requête | Correspondance ? |
|---|---|---|---|
| Prefix | / | (tous les chemins) | Oui |
| Exact | /foo | /foo | Oui |
| Exact | /foo | /bar | Non |
| Exact | /foo | /foo/ | Non |
| Exact | /foo/ | /foo | Non |
| Prefix | /foo | /foo, /foo/ | Oui |
| Prefix | /foo/ | /foo, /foo/ | Oui |
| Prefix | /aaa/bb | /aaa/bbb | Non |
| Prefix | /aaa/bbb | /aaa/bbb | Oui |
| Prefix | /aaa/bbb/ | /aaa/bbb | Oui, ignore la barre oblique finale |
| Prefix | /aaa/bbb | /aaa/bbb/ | Oui, correspond avec la barre oblique finale |
| Prefix | /aaa/bbb | /aaa/bbb/ccc | Oui, correspond au sous-chemin |
| Prefix | /aaa/bbb | /aaa/bbbxyz | Non, ne correspond pas au préfixe de chaîne |
| Prefix | /, /aaa | /aaa/ccc | Oui, correspond au préfixe /aaa |
| Prefix | /, /aaa, /aaa/bbb | /aaa/bbb | Oui, correspond au préfixe /aaa/bbb |
| Prefix | /, /aaa, /aaa/bbb | /ccc | Oui, correspond au préfixe / |
| Prefix | /aaa | /ccc | Non, utilise le backend par défaut |
| Mixte | /foo (Prefix), /foo (Exact) | /foo | Oui, préfère Exact |
Dans certains cas, plusieurs chemins d'un Ingress correspondent à une requête. La priorité est alors donnée au chemin correspondant le plus long. Si deux chemins correspondent toujours à égalité, la priorité est donnée aux chemins de type exact plutôt qu'aux chemins de type préfixe.
Les hôtes peuvent être des correspondances précises (par exemple « foo.bar.com ») ou un joker (par
exemple « *.foo.com »). Une correspondance précise exige que l'en-tête HTTP host
corresponde au champ host. Une correspondance avec joker exige que l'en-tête HTTP host
soit égal au suffixe de la règle avec joker.
| Hôte | En-tête Host | Correspondance ? |
|---|---|---|
*.foo.com | bar.foo.com | Correspond grâce au suffixe commun |
*.foo.com | baz.bar.foo.com | Pas de correspondance, le joker ne couvre qu'un seul libellé DNS |
*.foo.com | foo.com | Pas de correspondance, le joker ne couvre qu'un seul libellé 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
Les Ingress peuvent être mis en œuvre par différents contrôleurs, souvent avec des configurations différentes. Chaque Ingress devrait indiquer une classe, c'est-à-dire une référence à une ressource IngressClass qui contient une configuration supplémentaire, dont le nom du contrôleur chargé de mettre en œuvre la classe.
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
Le champ .spec.parameters d'une IngressClass vous permet de référencer une autre
ressource qui fournit la configuration associée à cette IngressClass.
Le type précis de paramètres à utiliser dépend du contrôleur d'Ingress
que vous indiquez dans le champ .spec.controller de l'IngressClass.
Selon votre contrôleur d'Ingress, vous pourrez peut-être utiliser des paramètres définis pour tout le cluster, ou pour un seul namespace.
Par défaut, les paramètres d'une IngressClass ont une portée à l'échelle du cluster.
Si vous définissez le champ .spec.parameters sans définir
.spec.parameters.scope, ou si vous définissez .spec.parameters.scope sur
Cluster, l'IngressClass fait référence à une ressource à portée cluster.
Le kind (combiné à l'apiGroup) des paramètres
fait référence à une API à portée cluster (éventuellement une ressource personnalisée), et
le name des paramètres identifie une ressource précise à portée cluster
de cette API.
Par exemple :
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb-1
spec:
controller: example.com/ingress-controller
parameters:
# The parameters for this IngressClass are specified in a
# ClusterIngressParameter (API group k8s.example.net) named
# "external-config-1". This definition tells Kubernetes to
# look for a cluster-scoped parameter resource.
scope: Cluster
apiGroup: k8s.example.net
kind: ClusterIngressParameter
name: external-config-1
Si vous définissez le champ .spec.parameters et définissez
.spec.parameters.scope sur Namespace, l'IngressClass fait référence
à une ressource à portée namespace. Vous devez aussi définir le champ namespace
de .spec.parameters avec le namespace qui contient
les paramètres que vous voulez utiliser.
Le kind (combiné à l'apiGroup) des paramètres
fait référence à une API à portée namespace (par exemple : ConfigMap), et
le name des paramètres identifie une ressource précise
dans le namespace indiqué dans namespace.
Les paramètres à portée namespace aident l'opérateur du cluster à déléguer le contrôle de la configuration (par exemple : réglages de l'équilibreur de charge, définition de la passerelle d'API) utilisée pour une charge de travail. Avec un paramètre à portée cluster, soit :
L'API IngressClass elle-même a toujours une portée cluster.
Voici un exemple d'IngressClass qui fait référence à des paramètres à portée namespace :
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb-2
spec:
controller: example.com/ingress-controller
parameters:
# The parameters for this IngressClass are specified in an
# IngressParameter (API group k8s.example.com) named "external-config",
# that's in the "external-configuration" namespace.
scope: Namespace
apiGroup: k8s.example.com
kind: IngressParameter
namespace: external-configuration
name: external-config
Avant l'ajout de la ressource IngressClass et du champ ingressClassName dans
Kubernetes 1.18, les classes d'Ingress étaient indiquées par une annotation
kubernetes.io/ingress.class sur l'Ingress. Cette annotation n'a jamais été
définie formellement, mais elle était largement prise en charge par les contrôleurs d'Ingress.
Le champ ingressClassName, plus récent, remplace cette
annotation, sans en être un équivalent direct. Alors que l'annotation servait
généralement à référencer le nom du contrôleur d'Ingress chargé de mettre en œuvre
l'Ingress, le champ est une référence à une ressource IngressClass qui contient
une configuration d'Ingress supplémentaire, dont le nom du contrôleur d'Ingress.
Vous pouvez marquer une IngressClass donnée comme classe par défaut de votre cluster. Définir
l'annotation ingressclass.kubernetes.io/is-default-class sur true sur une
ressource IngressClass garantit que cette IngressClass par défaut sera attribuée
aux nouveaux Ingress qui n'indiquent pas de champ ingressClassName.
ingressClassName. Pour résoudre ce problème, assurez-vous qu'au plus une
IngressClass est marquée comme classe par défaut dans votre cluster.Commencez par définir une IngressClass par défaut. Il est toutefois recommandé d'indiquer l'IngressClass par défaut :
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
Il existe déjà des concepts Kubernetes qui permettent d'exposer un seul Service (voir les alternatives). Vous pouvez aussi le faire avec un Ingress en indiquant un backend par défaut sans règles.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
spec:
defaultBackend:
service:
name: test
port:
number: 80
Si vous le créez avec kubectl apply -f, vous devriez pouvoir afficher l'état
de l'Ingress que vous avez ajouté :
kubectl get ingress test-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
test-ingress external-lb * 203.0.113.123 80 59s
203.0.113.123 est l'adresse IP allouée par le contrôleur d'Ingress pour satisfaire
cet Ingress.
<pending>.Une configuration en fanout achemine le trafic d'une seule adresse IP vers plusieurs Services, en fonction de l'URI HTTP demandée. Un Ingress vous permet de réduire au minimum le nombre d'équilibreurs de charge. Prenons par exemple la configuration suivante :
Figure. Fanout d'Ingress
Elle nécessiterait un Ingress comme celui-ci :
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
Une fois l'Ingress créé avec 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
Le contrôleur d'Ingress provisionne un équilibreur de charge propre à son implémentation
qui satisfait l'Ingress, à condition que les Services (service1, service2) existent.
Une fois que c'est fait, vous pouvez voir l'adresse de l'équilibreur de charge dans le
champ Address.
Les hôtes virtuels basés sur le nom permettent d'acheminer le trafic HTTP vers plusieurs noms d'hôte partageant la même adresse IP.
Figure. Hébergement virtuel basé sur le nom
L'Ingress suivant indique à l'équilibreur de charge sous-jacent d'acheminer les requêtes en fonction de l'en-tête 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 vous créez une ressource Ingress sans définir d'hôte dans les règles, tout trafic web adressé à l'adresse IP de votre contrôleur d'Ingress peut correspondre sans qu'un hôte virtuel basé sur le nom soit nécessaire.
Par exemple, l'Ingress suivant achemine le trafic
demandé pour first.bar.com vers service1, celui pour second.bar.com vers service2,
et tout trafic dont l'en-tête Host de la requête ne correspond ni à first.bar.com
ni à second.bar.com vers 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
Vous pouvez sécuriser un Ingress en indiquant un Secret
qui contient une clé privée et un certificat TLS. La ressource Ingress ne prend en charge
qu'un seul port TLS, le 443, et suppose que la terminaison TLS se fait au point d'entrée
(le trafic vers le Service et ses Pods circule en clair).
Si la section de configuration TLS d'un Ingress indique plusieurs hôtes, ils sont
multiplexés sur le même port selon le nom d'hôte indiqué via
l'extension TLS SNI (à condition que le contrôleur d'Ingress prenne en charge SNI). Le Secret TLS
doit contenir des clés nommées tls.crt et tls.key, qui contiennent le certificat
et la clé privée à utiliser pour TLS. Par exemple :
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
Référencer ce Secret dans un Ingress indique au contrôleur d'Ingress de
sécuriser avec TLS le canal entre le client et l'équilibreur de charge. Vous devez vous
assurer que le Secret TLS que vous avez créé provient d'un certificat contenant un Common
Name (CN), aussi appelé nom de domaine complet (FQDN), pour https-example.foo.com.
hosts de la section tls doivent correspondre explicitement au host de la section
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 contrôleur d'Ingress démarre avec des réglages de politique d'équilibrage de charge qu'il applique à tous les Ingress, comme l'algorithme d'équilibrage de charge, le schéma de pondération des backends, etc. Les concepts d'équilibrage de charge plus avancés (par exemple les sessions persistantes ou les pondérations dynamiques) ne sont pas encore exposés via l'Ingress. Vous pouvez en revanche obtenir ces fonctionnalités grâce à l'équilibreur de charge utilisé pour un Service.
Notez aussi que, même si les contrôles de santé (health checks) ne sont pas exposés directement via l'Ingress, il existe dans Kubernetes des concepts parallèles, comme les sondes de disponibilité (readiness probes), qui permettent d'obtenir le même résultat. Consultez la documentation propre à votre contrôleur pour savoir comment il gère les contrôles de santé.
Pour mettre à jour un Ingress existant afin d'ajouter un nouvel hôte, vous pouvez modifier la ressource :
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)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 35s loadbalancer-controller default/test
kubectl edit ingress test
Un éditeur s'ouvre avec la configuration existante au format YAML. Modifiez-la pour ajouter le nouvel hôte :
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
..
Une fois vos modifications enregistrées, kubectl met à jour la ressource dans le serveur d'API, ce qui indique au contrôleur d'Ingress de reconfigurer l'équilibreur de charge.
Vérifiez-le :
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)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 45s loadbalancer-controller default/test
Vous pouvez obtenir le même résultat en exécutant kubectl replace -f sur un fichier YAML d'Ingress modifié.
Les techniques de répartition du trafic entre domaines de défaillance diffèrent d'un fournisseur de cloud à l'autre. Consultez la documentation du contrôleur d'Ingress concerné pour plus de détails.
Vous pouvez exposer un Service de plusieurs manières qui n'impliquent pas directement la ressource Ingress :