Comment fournir un accès externe à plusieurs services Kubernetes dans mon cluster Amazon EKS ?

Date de la dernière mise à jour : 30/03/2021

Je souhaite fournir un accès externe à plusieurs services Kubernetes dans mon cluster Amazon Elastic Kubernetes Service (Amazon EKS).

Brève description

Vous pouvez utiliser le contrôleur d'entrée NGINX pour Kubernetes pour fournir un accès externe à plusieurs services Kubernetes dans votre cluster Amazon EKS.

Remarque : le contrôleur d'entrée NGINX peut être plus efficace et plus économique qu'un équilibreur de charge. En outre, vous devrez peut-être réserver votre équilibreur de charge pour envoyer le trafic vers différents microservices. Le contrôleur d'entrée NGINX est géré principalement par NGINX. Pour vérifier les problèmes avec le contrôleur d'entrée NGINX, consultez la liste des problèmes sur GitHub.

Important : le contrôleur d'entrée (depuis le site de Kubernetes) n'est pas le même que l'entrée (depuis le site de Kubernetes). Le contrôleur d'entrée est une ressource Kubernetes qui expose les routes HTTP et HTTPS depuis l'extérieur du cluster vers les services au sein du cluster. Le contrôleur d'entrée assure l'entrée (généralement avec un équilibreur de charge). Vous ne pouvez pas utiliser l'entrée sans un contrôleur d'entrée.

Résolution

La résolution suivante utilise le contrôleur d'entrée nginxinc/kubernetes-ingress contrôleur d'entrée à partir du site Web NGINX GitHub. L'autre contrôleur d'entrée disponible pour un usage public est kubernetes/ingress-nginx du site Web Kubernetes GitHub. Pour plus d'informations, voir Différences entre les contrôleurs d'entrée nginxinc/kubernetes-ingress et kubernetes/ingress-nginx sur le site Web de NGINX.

Déployer le contrôleur d'entrée NGINX pour Kubernetes

1.    Téléchargez le contrôleur d'entrée NGINX pour Kubernetes :

git clone https://github.com/nginxinc/kubernetes-ingress.git

2.    Choisissez le répertoire de déploiement du contrôleur d'entrée :

cd kubernetes-ingress/deployments/

Remarque : toutes les commandes des étapes suivantes sont exécutées à partir du répertoire deployments (déploiements).

3.    Vérifiez que vous utilisez la version stable du contrôleur d'entrée NGINX et non la version Edge (expérimental en date de mars 2021) :

git checkout v1.10.1

Remarque : pour plus d'informations sur les versions de contrôleur d'entrée NGINX, consultez NGINX Ingress Controller Releases sur GitHub.

4.    Créez un espace de noms dédié, un compte de service et des certificats TLS (avec une clé) pour le serveur par défaut :

kubectl apply -f common/ns-and-sa.yaml
kubectl apply -f common/default-server-secret.yaml

Remarque : le serveur par défaut renvoie une page « Not Found » (Introuvable) avec un code de statut 404 pour toutes les demandes de domaines pour lesquelles aucune règle d'entrée n'est définie. Vous pouvez utiliser le certificat autosigné et la clé qui sont générés à des fins de test. Une bonne pratique consiste à utiliser votre propre certificat et votre propre clé pour les environnements de production.

5.    Créez un ConfigMap pour personnaliser votre configuration NGINX :

kubectl apply -f common/nginx-config.yaml

Remarque : pour des exemples de configurations, reportez-vous à ConfigMap et Annotations sur le site web NGINX GitHub.

6.    Configurez le contrôle d'accès basé sur les rôles (RBAC), créez un ClusterRole, puis liez le ClusterRole au compte de service créé à l'étape 3. Par exemple :

kubectl apply -f rbac/rbac.yaml

Remarque : le rôle ClusterRole donne au contrôleur d'entrée l'autorisation d'interagir avec votre cluster Amazon EKS.

7.    Si votre version de cluster Kubernetes est supérieure ou égale à 1.18, créez une classe d'entrée NGINX :

kubectl apply -f common/ingress-class.yaml

8.    Déployez le contrôleur d'entrée :

kubectl apply -f deployment/nginx-ingress.yaml
kubectl get pods --namespace=nginx-ingress

Remarque : vous pouvez déployer un contrôleur d'entrée avec l'option Deployment ou DaemonSet. L'option Deployment vous permet de modifier dynamiquement le nombre de réplicas du contrôleur d'Ingress. L'option DaemonSet vous permet de déployer le contrôleur d'entrée sur chaque nœud ou sous-ensemble de nœuds. L'étape 7 précédente utilise l'option Deployment.

Exemple de sortie :

NAME                            READY   STATUS    RESTARTS   AGE
nginx-ingress-fb4f4b44c-xmq6z   1/1     Running   0          12s

Votre contrôleur d'entrée peut désormais accepter les demandes provenant d'objets d'entrée.

Accédez au contrôleur d'Ingress et exécutez votre application.

Pour un ingress-controller de déploiement, vous pouvez utiliser un objet de service avec le type NodePort ou LoadBalancer. Les étapes suivantes utilisent le type LoadBalancer.

1.    Appliquez votre configuration :

kubectl apply -f service/loadbalancer-aws-elb.yaml

kubectl get svc --namespace=nginx-ingress

Exemple de sortie :

NAME          TYPE         EXTERNAL-IP                                      PORT(S)
nginx-ingress LoadBalancer aaa71bxxxxx-11xxxxx10.us-east-1.elb.amazonaws.com 80:32462/TCP,443:32226/TCP

Remarque : Amazon EKS alloue un Classic Load Balancer en mode TCP avec le protocole PROXY activé pour transmettre les informations du client (adresse IP et port). Vous devez transmettre ces informations de proxy au contrôleur d'entrée.

2.    Configurez NGINX afin d'utiliser le protocole PROXY pour pouvoir transmettre les informations de proxy au contrôleur d'entrée et ajoutez les clés suivantes au fichier nginx-config.yaml de l'étape 1. Par exemple :

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-config
  namespace: nginx-ingress
data:
  proxy-protocol: "True"
  real-ip-header: "proxy_protocol"
  set-real-ip-from: "0.0.0.0/0"

Remarque : les informations de proxy sont transmises au contrôleur d'Ingress via la ressource ConfigMap que vous avez créée précédemment.

3.    Mettez à jour la ConfigMap :

kubectl apply -f common/nginx-config.yaml

4.    Configurez vos déploiements ou vos microservices (par exemple, hostname-app et apache-app). Reportez-vous aux exemples suivants.

Remarque : cette étape suppose que vous exécutez deux microservices (à des fins de démonstration). Les microservices sont exposés en interne avec Kubernetes comme type par défaut.

Exemple d'un fichier hostname-app-svc.yaml pour hostname-app :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hostname-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hostname-app
  template:
    metadata:
      labels:
        app: hostname-app
    spec:
      containers:
      - name: hostname-app
        image: k8s.gcr.io/serve_hostname:1.1

---
apiVersion: v1
kind: Service
metadata:
  name: hostname-svc
spec:
  ports:
  - port: 80
    targetPort: 9376
    protocol: TCP
  selector:
    app: hostname-app

Exemple d'un fichier apache-app-svc.yaml pour apache-app:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apache-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: apache-app
  template:
    metadata:
      labels:
        app: apache-app
    spec:
      containers:
      - name: apache-app
        image: httpd:latest
        ports:
        - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: apache-svc
  labels:
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: apache-app

Appliquez vos configurations :

kubectl apply -f hostname-app-svc.yaml
kubectl apply -f apache-app-svc.yaml

5.    Implémentez l'Ingress afin qu'il interagisse avec vos services à l'aide de l'unique équilibreur de charge fourni par le contrôleur d'Ingress. Consultez l'exemple micro-ingress.yaml suivant :

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: micro-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: hostname.mydomain.com
      http:
        paths:
          - backend:
              serviceName: hostname-svc
              servicePort: 80
    - host: apache.mydomain.com
      http:
        paths:
          - backend:
              serviceName: apache-svc
              servicePort: 80

Remarque : Pour plus d'informations, voir Hébergement virtuel basé sur un nom sur le site Web Kubernetes.

6.    Appliquez votre configuration :

kubectl apply -f micro-ingress.yaml

Remarque : cette ressource d'entrée définit les règles qui redirigent tout ce qui concerne hostname.mydomain.com vers hostname-svc, et tout ce qui concerne apache.mydomain.com vers apache-svc. Toute demande qui ne correspond pas à la règle renvoie un message d'erreur 404 « Introuvable » ( Non trouvé).

Si vous décrivez l'Ingress, vous recevrez un message similaire à ce qui suit :

kubectl describe ingress micro-ingress                       

Name:             micro-ingress
Namespace:        default
Address:
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host                   Path  Backends
  ----                   ----  --------
  hostname.mydomain.com
                            hostname-svc:80 (192.168.47.163:9376,192.168.70.76:9376)
  apache.mydomain.com
                            apache-svc:80 (192.168.37.44:80,192.168.84.218:80)
Annotations:             kubernetes.io/ingress.class: nginx
Events:
  Type    Reason          Age   From                      Message
  ----    ------          ----  ----                      -------
  Normal  AddedOrUpdated  23s   nginx-ingress-controller  Configuration for default/micro-ingress was added or updated

Test du contrôleur d'Ingress NGINX

1.    Accédez à l'URL DNS de l'équilibreur de charge que vous avez récupéré précédemment à partir de la ligne de commande :

curl -I http://aaa71bxxxxx-11xxxxx10.us-east-1.elb.amazonaws.com/

Remarque : le point de terminaison de l'équilibreur de charge provient de la section Accès au contrôleur d'entrée et exécution de l'application précédente.

Exemple de sortie :

HTTP/1.1 404 Not Found
Server: nginx/1.17.5
Date: Mon, 25 Nov 2019 20:50:58 GMT
Content-Type: text/html
Content-Length: 153
Connection: keep-alive

Remarque : le serveur par défaut renvoie une page « Not Found » (Introuvable) avec un code de statut 404 pour toutes les demandes de domaines pour lesquelles aucune règle d'entrée n'est définie. D'après les règles définies, le contrôleur d'Ingress ne détourne pas le trafic vers le service backend spécifié, sauf si la demande correspond à la configuration. Étant donné que le champ host (hôte) est configuré pour l'objet d'Ingress, vous devez fournir l'en-tête Host (hôte) de la demande avec le même nom d'hôte.

2.    Ajoutez l'en-tête Host à la demande.

Il s'agit d'une demande basée sur le premier domaine configuré :

curl -I -H "Host: hostname.mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-1.elb.amazonaws.com/

Exemple de sortie :

HTTP/1.1 200 OK
Server: nginx/1.19.8
Date: Fri, 26 Mar 2021 15:49:43 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 29
Connection: keep-alive

Il s'agit d'une demande basée sur le deuxième domaine configuré :

curl -I -H "Host: apache.mydomain.com" http://aaa71bxxxxx-11xxxxx10.us-east-1.elb.amazonaws.com/

Exemple de sortie :

HTTP/1.1 200 OK
Server: nginx/1.19.8
Date: Fri, 26 Mar 2021 15:50:27 GMT
Content-Type: text/html
Content-Length: 45
Connection: keep-alive
Last-Modified: Mon, 11 Jun 2007 18:53:14 GMT
ETag: "2d-432a5e4a73a80"
Accept-Ranges: bytes

Après avoir ajouté l'en-tête Host, le contrôleur d'entrée peut rediriger le trafic vers le service backend configuré car il correspond à la configuration définie dans le contrôleur d'entrée.

Si vous souhaitez conserver le même nom de domaine, mais détourner le trafic en fonction du chemin d'accès, vous devez ajouter un routage basé sur le chemin d'accès avec le contrôleur d'entrée. Par exemple :

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: path-ingress
annotations:
  nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: hostname.mydomain.com
  http:
        paths:
        - path: /login
          backend:
                serviceName: service1
                servicePort: 4200
        - path: /cart
          backend:
                serviceName: service2
                servicePort: 8080

L'exemple précédent renvoie uniquement la réponse 200 lorsque les demandes ont pour en-tête d'hôte hostname.mydomain.com. Les demandes sont accessibles sur les chemins d'accès /login ou /cart. Pour toutes les autres demandes, les réponses 404 sont renvoyées.


Cet article vous a-t-il été utile ?


Besoin d'aide pour une question technique ou de facturation ?