Ingress

Ingress est un type de service Kubernetes qui centralise l’accès HTTP à des services du cluster. Les instances Ingress sont gérée par un Ingress Controller, dont il existe plusieurs implémentations.

Ingress

Ingress Controller

L’implémentation la plus classique de contrôleur Ingress se base du nginx. Le projet Kubernetes fournit aussi des implémentations avec AWS ou Google Cloud. Beaucoup d’autres implémentations existent, dans des projets indépendants, comme HAProxy, Traefik, Azure,…​

Le contrôleur peut être activé en utilisant le fichier de configuration proposé dans la documentation.

~$ kubectl apply -f ingress-nginx-deploy.yaml

Dans Minikube, le contrôleur est fourni sous forme d’un module complémentaire.

~$ minikube addons enable ingress

Routage HTTP

Le routage HTTP est la mission principale d’Ingress.

Contrairement à un nginx nu, Ingress ne relaie pas les requêtes vers n’importe quel host et port. Il le fait uniquement dans le cadre d’un cluster Kubernetes, vers des services de type NodePort ou LoadBalancer.

L’essentiel de la configuration d’un service Ingress est fait de règles de renvoi vers les services.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
spec:
  rules:
  - ...
  - ...

Ces règles peuvent se baser sur le chemin de la requête, sous forme de préfixe (Prefix) ou en chemin exact (Exact).

Ingress routes by path
  - http:
      paths:
        - path: /app1
          pathType: Prefix
          backend:
            service:
              name: app1
              port:
                number: 8080

Elles peuvent aussi se baser sur le nom d’hôte de la requête, soit avec un nom exact (app1.example.com) soit avec un jocker (*.example.com).

Ingress routes by hostname
  - host: app1.example.com
    http:
      paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: app1
              port:
                number: 9999

TLS

Pour activer le support des requêtes TLS, sur le port 443, il faut créer un secret de type tls, avec les clés.

apiVersion: v1
kind: Secret
metadata:
  name: tls-keys
  namespace: default
data:
  tls.crt: MIIEKTCCApGgAwIBAgIQHsvvNTJVqVoJBk+C0pPZ3jANBgkqhkiG9w0BA...
  tls.key: MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDWkHM3g...
type: kubernetes.io/tls

Ça peut aussi se faire en ligne de commande, à partir de fichiers.

~$ kubectl create secret tls tls-keys --key example.key --cert example.crt
Les clés peuvent être créées avec OpenSSL ou tout autre outil dérivé. mkcert est pratique dans un environnement local.

Les clés ajoutées peuvent être utilisées explicitement dans une configuration Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
spec:
  tls:
  - secretName: tls-key
    hosts:
    - app1.example.com
  rules:
  - ...

Elles peuvent être déclarées comme clés par défaut avec Minikube.

~$ minikube addons configure ingress
-- Enter custom cert (format is "namespace/secret"): default/tls-keys
✅  ingress was successfully configured

~$ minikube addons disable ingress
🌑  "The 'ingress' addon is disabled

~$ minikube addons enable ingress
🌟  The 'ingress' addon is enabled

Annotations

L’ajout d’annotations dans la configuration Ingress permet d’utiliser des fonctionnalités propres au contrôleur, comme avec nginx:

  • le support d’expressions régulières,

  • la réécriture d’URL,

  • l’authentification,

  • le canary deployment,

  • …​

La réécriture d’URL s’utilise conjointement avec le support d’expressions régulières. Avec l’exemple ci-dessous, Ingress remplace le préfixe des chemins qui commenncent par /app par /service avant de transférer les requêtes vers la cible.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /service$2
spec:
  rules:
  - http:
      paths:
      - path: /app(/|$)(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: app
            port:
              number: 8080

On active la fonctionnalité d’expression régulière avec l’annotation nginx.ingress.kubernetes.io/use-regex et en utilisant un type de chemin ImplementationSpecific.

Routage TCP / UDP

Ingress ne supporte officiellement que le protocole HTTP. Certains contrôleurs peuvent quand même router d’autres protocoles TCP et/ou UDP.

C’est le cas du contrôleur nginx qui peut être configuré via des ressources ConfigMap.

Dans Minikube, dès qu’on active l’extension Ingress, une ConfigMap est créée pour TCP et une autre pour UDP. Toutes deux sont dans l’espace de nommage ingress-nginx sans donnée et peuvent être patchées.

Par exemple, pour exposer une base de données PostgreSQL déployée dans un service postgres de l’espace de nommage par défaut.

~$ kubectl patch configmap tcp-services --nanespace ingress-nginx                \
                           --patch '{"data":{"5432":"default/postgres:5432"}}'

Il faut aussi modifier la configuration du contrôleur pour qu’il écoute sur le port 5432.

~$ kubectl patch deployment ingress-nginx-controller --nanespace ingress-nginx   \
                            --patch-file ingress-nginx-controller-patch.yaml

Avec le contenu suivant pour le fichier ingress-nginx-controller-patch.yaml, on configure le contrôleur pour qu’il écoute les ports PostgreSQL, Redis et AMQP.

spec:
  template:
    spec:
      containers:
      - name: controller
        ports:
         - containerPort: 5432
           hostPort: 5432
         - containerPort: 6379
           hostPort: 6379
         - containerPort: 5672
           hostPort: 5672