BLOG | NGINX

Équilibrage de charge des services Kubernetes avec NGINX Plus

NGINX-Partie-de-F5-horiz-black-type-RGB
Michael Pleshakov Miniature
Michel Pleshakov
Publié le 17 novembre 2015

Kubernetes est un système open source développé par Google pour exécuter et gérer des applications basées sur des microservices conteneurisés dans un cluster. Les personnes qui utilisent Kubernetes ont souvent besoin de rendre les services qu’elles créent dans Kubernetes accessibles depuis l’extérieur de leur cluster Kubernetes.

Bien que Kubernetes fournisse des solutions intégrées pour exposer des services, décrites dans Exposition des services Kubernetes avec des solutions intégrées ci-dessous, ces solutions vous limitent à l'équilibrage de charge de couche 4 ou à l'équilibrage de charge HTTP round-robin.

Cet article montre comment utiliser NGINX Plus comme solution avancée d’équilibrage de charge de couche 7 pour exposer les services Kubernetes à Internet, que vous exécutiez Kubernetes dans le cloud ou sur votre propre infrastructure.

Nous supposerons que vous avez une compréhension de base de Kubernetes (pods, services, contrôleurs de réplication et étiquettes) et d'un cluster Kubernetes en cours d'exécution. Pour en savoir plus sur Kubernetes, consultez le guide d'utilisation officiel de Kubernetes .

Exposer les services Kubernetes avec des solutions intégrées

Kubernetes propose plusieurs options pour exposer les services . Deux d’entre eux – NodePort et LoadBalancer – correspondent à un type de service spécifique. Une troisième option, Ingress API, est devenue disponible en version bêta dans la version 1.1 de Kubernetes.

NodePort

La spécification du type de service comme NodePort rend le service disponible sur le même port sur chaque nœud Kubernetes. Pour exposer le service à Internet, vous exposez un ou plusieurs nœuds sur ce port. Pour une haute disponibilité, vous pouvez exposer plusieurs nœuds et utiliser l’équilibrage de charge basé sur DNS pour répartir le trafic entre eux, ou vous pouvez placer les nœuds derrière un équilibreur de charge de votre choix.

Lorsque le trafic entrant atteint un nœud du port, sa charge est équilibrée entre les pods du service. L'équilibrage de charge effectué par le proxy réseau Kubernetes ( kube-proxy ) exécuté sur chaque nœud est limité à l'équilibrage de charge TCP/UDP.

Équilibreur de charge

La spécification du type de service comme LoadBalancer alloue un équilibreur de charge cloud qui répartit le trafic entrant entre les pods du service.

La solution LoadBalancer est prise en charge uniquement par certains fournisseurs de cloud et Google Container Engine et n'est pas disponible si vous exécutez Kubernetes sur votre propre infrastructure. De plus, Kubernetes vous permet uniquement de configurer l’équilibrage de charge TCP round-robin, même si l’équilibreur de charge cloud dispose de fonctionnalités avancées telles que la persistance de session ou le mappage de requêtes.

API d'entrée

La création d'une ressource Ingress vous permet d'exposer des services à Internet à des URL personnalisées (par exemple, le service A à l'URL /foo et le service B à l'URL /bar ) et plusieurs noms d'hôtes virtuels (par exemple, foo.example.com pour un groupe de services et bar.example.com pour un autre groupe). Un contrôleur Ingress consomme une ressource Ingress et configure un équilibreur de charge externe.

Un contrôleur Ingress ne fait pas partie d'un déploiement Kubernetes standard : vous devez choisir le contrôleur qui correspond le mieux à vos besoins ou en implémenter un vous-même et l'ajouter à votre cluster Kubernetes. De nombreuses implémentations de contrôleur devraient bientôt apparaître, mais pour l'instant, la seule implémentation disponible est le contrôleur pour Google Compute Engine HTTP Load Balancer , qui ne fonctionne que si vous exécutez Kubernetes sur Google Compute Engine ou Google Container Engine . L’API Ingress prend uniquement en charge l’équilibrage de charge HTTP round-robin, même si l’équilibreur de charge réel prend en charge les fonctionnalités avancées.

Au moment de la rédaction de cet article, l’API Ingress et le contrôleur de l’équilibreur de charge HTTP Google Compute Engine sont en version bêta.

Mise à jour – NGINX Ingress Controller pour NGINX et NGINX Plus est désormais disponible dans notre référentiel GitHub . Pour plus de détails sur le produit, voir NGINX Ingress Controller .

Bien que les solutions mentionnées ci-dessus soient simples à configurer et fonctionnent immédiatement, elles ne fournissent aucune fonctionnalité avancée, en particulier les fonctionnalités liées à l'équilibrage de charge de couche 7.

Exposer les services Kubernetes avec NGINX Plus

[Éditeur – Cette section a été mise à jour pour faire référence à l’ API NGINX Plus , qui remplace et déprécie le module de configuration dynamique distinct initialement décrit ici.]

Pour intégrer NGINX Plus à Kubernetes, nous devons nous assurer que la configuration NGINX Plus reste synchronisée avec Kubernetes, reflétant les modifications apportées aux services Kubernetes, telles que l'ajout ou la suppression de pods. Avec NGINX Open Source, vous modifiez manuellement le fichier de configuration NGINX et effectuez un rechargement de configuration. Avec NGINX Plus, il existe deux manières de mettre à jour la configuration de manière dynamique :

  • Avec des API – Cette méthode utilise l’ API NGINX Plus pour ajouter et supprimer des entrées pour les pods Kubernetes dans la configuration NGINX Plus, et l’API Kubernetes pour récupérer les adresses IP des pods. Cette méthode nécessite que nous écrivions du code, et nous n'en parlerons pas en profondeur ici. Pour plus de détails, regardez le webinaire de Kelsey Hightower, Bringing Kubernetes to the Edge with NGINX Plus , dans lequel il explore les API et crée une application qui les utilise.
  • En résolvant à nouveau les noms DNS – Cette méthode ne nécessite qu’une configuration unique appropriée de NGINX Plus, comme décrit dans la section suivante.

Utilisation de la reconfiguration basée sur DNS

Nous supposons que vous disposez déjà d'un cluster Kubernetes en cours d'exécution et d'un hôte avec l'utilitaire kubectl disponible pour gérer le cluster ; pour obtenir des instructions, consultez le guide de démarrage de Kubernetes pour votre type de cluster. Vous devez également avoir créé une image Docker NGINX Plus, et des instructions sont disponibles dans Déploiement de NGINX et NGINX Plus avec Docker sur notre blog.

Voici un aperçu de ce que nous allons faire :

  1. Configurez un pod NGINX Plus pour exposer et équilibrer la charge du service que nous créons à l’étape 2.
  2. Créez une application Web simple en tant que notre service.
  3. Augmentez ou réduisez la taille du service et observez comment NGINX Plus est automatiquement reconfiguré.

Remarques : Nous avons testé la solution décrite dans ce blog avec Kubernetes 1.0.6 exécuté sur Google Compute Engine et une configuration Vagrant locale, que nous utilisons ci-dessous.

Dans les commandes, les valeurs qui peuvent être différentes pour votre configuration Kubernetes apparaissent en italique.

Configuration du pod NGINX Plus

Nous plaçons NGINX Plus dans un pod Kubernetes sur un nœud que nous exposons à Internet. Notre pod est créé par un contrôleur de réplication, que nous sommes également en train de configurer. Notre fichier de configuration NGINX Plus spécifique à Kubernetes réside dans un dossier partagé entre le pod NGINX Plus et le nœud, ce qui le rend plus simple à maintenir.

Choisir un nœud pour héberger le pod NGINX Plus

Pour désigner le nœud sur lequel s’exécute le pod NGINX Plus, nous ajoutons une étiquette à ce nœud. Nous obtenons la liste de tous les nœuds en exécutant :

$ kubectl get nodes NOM ÉTIQUETTES STATUT 10.245.1.3 Kubernetes.io/hostname=10.245.1.3 Prêt 10.245.1.4 Kubernetes.io/hostname=10.245.1.4 Prêt 10.245.1.5 Kubernetes.io/hostname=10.245.1.5 Prêt

Nous choisissons le premier nœud et lui ajoutons une étiquette en exécutant :

$ kubectl nœud d'étiquette10.245.1.3 rôle=nginxplus

Configuration du contrôleur de réplication pour le pod NGINX Plus

Nous ne créons pas directement un pod NGINX Plus, mais plutôt via un contrôleur de réplication. Nous configurons le contrôleur de réplication pour le pod NGINX Plus dans un fichier de déclaration Kubernetes appelé nginxplus-rc.yaml .

  • Nous définissons le nombre de répliques sur un, ce qui signifie que Kubernetes s'assure qu'un pod NGINX Plus est toujours en cours d'exécution : si le pod tombe en panne, il est remplacé par un nouveau pod.
  • Dans le champ nodeSelector, nous spécifions que le pod NGINX Plus est créé sur un nœud étiqueté avec le rôle : nginxplus .
  • Notre conteneur NGINX Plus expose deux ports, 80 et 8080, et nous configurons un mappage entre eux et les ports 80 et 8080 sur le nœud.
  • Notre conteneur NGINX Plus partage également le dossier /etc/nginx/conf.d qui réside sur le nœud. Comme expliqué plus en détail dans Configuration de NGINX Plus ci-dessous, le partage du dossier nous permet de reconfigurer NGINX Plus sans reconstruire l'image du conteneur.
apiVersion : v1
type : ReplicationController
métadonnées :
nom : nginxplus-rc
spécification :
répliques : 1
sélecteur :
application : nginxplus
modèle :
métadonnées :
étiquettes :
application : nginxplus
spécification :
nodeSelector :
rôle : nginxplus
conteneurs :
- nom : nginxplus
imagePullPolicy : IfNotPresent
image : nginxplus
ports :
- nom : http
containerPort : 80
Port de l'hôte : 80
- nom : http-alt
containerPort : 8080
Port hôte : 8080
volumeMounts :
- mountPath : "/etc/nginx/conf.d"
nom : etc-nginx-confd
volumes :
- hostPath :
chemin : "/etc/nginx/conf.d"
nom : etc-nginx-confd

Rendre l'image Docker NGINX Plus disponible sur le nœud

Comme nous l’avons dit ci-dessus, nous avons déjà créé une image Docker NGINX Plus. Nous le rendons maintenant disponible sur le nœud. Pour plus de simplicité, nous n'utilisons pas de référentiel Docker privé et nous chargeons simplement manuellement l'image sur le nœud.

Sur l’hôte où nous avons créé l’image Docker, nous exécutons la commande suivante pour enregistrer l’image dans un fichier :

$ docker save -o nginxplus.tar nginxplus

Nous transférons nginxplus.tar sur le nœud et exécutons la commande suivante sur le nœud pour charger l'image à partir du fichier :

$ docker load -i nginxplus.tar

Configuration de NGINX Plus

Dans le dossier /etc/nginx du conteneur NGINX Plus, nous conservons le fichier de configuration principal nginx.conf par défaut fourni avec les packages NGINX Plus. La directive include dans le fichier par défaut lit d'autres fichiers de configuration à partir du dossier /etc/nginx/conf.d . Comme spécifié dans le fichier de déclaration du contrôleur de réplication NGINX Plus ( nginxplus-rc.yaml ), nous partageons le dossier /etc/nginx/conf.d sur le nœud NGINX Plus avec le conteneur. Le partage signifie que nous pouvons apporter des modifications aux fichiers de configuration stockés dans le dossier (sur le nœud) sans avoir à reconstruire l'image Docker NGINX Plus, ce que nous devrions faire si nous créions le dossier directement dans le conteneur. Nous avons placé notre fichier de configuration spécifique à Kubernetes ( backend.conf ) dans le dossier partagé.

Tout d’abord, créons le dossier /etc/nginx/conf.d sur le nœud.

$ sudo mkdir -p /etc/nginx/conf.d

Ensuite, nous créons le fichier backend.conf et incluons ces directives :

  • resolver – Définit le serveur DNS que NGINX Plus utilise pour résoudre périodiquement le nom de domaine que nous utilisons pour identifier nos serveurs en amont (dans la directive server à l'intérieur du bloc en amont , abordée dans la puce suivante). Nous identifions ce serveur DNS par son nom de domaine, kube-dns.kube-system.svc.cluster.local . Le paramètre valide indique à NGINX Plus d’envoyer la demande de nouvelle résolution toutes les cinq secondes.

    (Notez que le processus de résolution de cette directive diffère de celui des serveurs en amont : ce nom de domaine est résolu uniquement lorsque NGINX démarre ou se recharge, et NGINX Plus utilise le ou les serveurs DNS système définis dans le fichier /etc/resolv.conf pour le résoudre.)

  • en amont – Crée un groupe en amont appelé backend pour contenir les serveurs qui fournissent le service Kubernetes que nous exposons. Plutôt que de répertorier les serveurs individuellement, nous les identifions avec un nom d'hôte complet dans une seule directive de serveur . Le paramètre resolve indique à NGINX Plus de résoudre à nouveau le nom d’hôte au moment de l’exécution, conformément aux paramètres spécifiés avec la directive resolver .

    Étant donné que Kubernetes DNS et NGINX Plus (R10 et versions ultérieures) prennent en charge les enregistrements du service DNS ( SRV ), NGINX Plus peut obtenir les numéros de port des serveurs en amont via DNS. Nous incluons le paramètre de service pour que NGINX Plus demande des enregistrements SRV , en spécifiant le nom ( _http ) et le protocole ( _tcp ) pour les ports exposés par notre service. Nous déclarons ces valeurs dans le fichier webapp-svc.yaml décrit dans Création du contrôleur de réplication pour le service ci-dessous.

    Pour plus d'informations sur la découverte de services avec DNS, consultez Utilisation de DNS pour la découverte de services avec NGINX et NGINX Plus sur notre blog.

  • serveur (deux fois) – Définir deux serveurs virtuels :

    • Le premier serveur écoute sur le port 80 et équilibre la charge des requêtes entrantes pour /webapp (notre service) entre les pods exécutant les instances de service. Nous mettons également en place des contrôles de santé actifs .

    • Le deuxième serveur écoute sur le port 8080. Ici, nous configurons la surveillance de l'activité en direct de NGINX Plus. Plus tard, nous l'utiliserons pour vérifier que NGINX Plus a été correctement reconfiguré.

      [Éditeur – La configuration de ce deuxième serveur a été mise à jour pour utiliser l’ API NGINX Plus , qui remplace et déprécie le module d’état distinct utilisé à l’origine.]

résolveur kube-dns.kube-system.svc.cluster.local valide=5s;

backend en amont {
zone backend en amont 64k;
serveur webapp-svc.default.svc.cluster.local service=_http._tcp resolve;
}

serveur {
écoute 80;
zone_état backend-serveurs;

emplacement /webapp {
proxy_pass http://backend;
contrôle_état;
}
}

serveur {
écoute 8080;
racine /usr/share/nginx/html;

emplacement = /dashboard.html { }

emplacement = / {
retour 302 /dashboard.html;
}

emplacement /api {
api write=on;
}
}

Création du contrôleur de réplication

Nous sommes maintenant prêts à créer le contrôleur de réplication en exécutant cette commande :

$ kubectl create -f nginxplus-rc.yaml

Pour vérifier que le pod NGINX Plus a été créé, nous exécutons :

$ kubectl get pods NOM PRÊT STATUT RESTARTS AGE nginxplus-rc-0ts5t 1/1 En cours d'exécution 0 17s

Nous exécutons Kubernetes sur une configuration Vagrant locale, nous savons donc que l’adresse IP externe de notre nœud est 10.245.1.3 et nous utiliserons cette adresse pour le reste de cet exemple. Si vous exécutez Kubernetes sur un fournisseur de cloud, vous pouvez obtenir l'adresse IP externe de votre nœud en exécutant :

$ kubectl get nodes nom-noeud -o json | grep -i externalIP -A 1 "type": « ExternalIP », « adresse » : XXX.XXX.XXX.XXX

Si vous utilisez un cloud, n'oubliez pas de configurer une règle de pare-feu pour permettre au nœud NGINX Plus d'accepter le trafic entrant. Reportez-vous à la documentation de votre fournisseur de cloud.

Nous pouvons vérifier que notre pod NGINX Plus est opérationnel en consultant le tableau de bord de surveillance des activités en direct de NGINX Plus, qui est disponible sur le port 8080 à l'adresse IP externe du nœud (donc http://10.245.1.3:8080/dashboard.html dans notre cas). Cependant, si nous regardons ce point, nous ne voyons aucun serveur pour notre service, car nous n'avons pas encore créé le service.

Le tableau de bord de surveillance des activités en direct de NGINX Plus avant de créer les services Kubernetes

Créer un service Kubernetes simple

Il est maintenant temps de créer un service Kubernetes. Notre service se compose de deux serveurs Web qui fournissent chacun une page Web contenant des informations sur le conteneur dans lequel ils s'exécutent.

Création du contrôleur de réplication pour le service

Nous créons d’abord un contrôleur de réplication afin que Kubernetes s’assure que le nombre spécifié de répliques de serveur Web (pods) sont toujours en cours d’exécution dans le cluster. Voici le fichier de déclaration ( webapp-rc.yaml ) :

apiVersion: v1kind: ReplicationController
métadonnées :
nom : webapp-rc
spécification :
répliques : 2
sélecteur :
application : webapp
modèle :
métadonnées :
étiquettes :
application : webapp
spécification :
conteneurs :
- nom : hello
image : nginxdemos/hello 
ports :
- containerPort : 80

Notre contrôleur se compose de deux serveurs Web. Nous déclarons un contrôleur composé de pods avec un seul conteneur, exposant le port 80. L'image nginxdemos/hello sera extraite de Docker Hub.

Pour créer le contrôleur de réplication, nous exécutons la commande suivante :

$ kubectl create -f webapp-rc.yaml

Pour vérifier que nos pods ont été créés, nous pouvons exécuter la commande suivante. Nous utilisons le sélecteur d'étiquettes app=webapp pour obtenir uniquement les pods créés par le contrôleur de réplication à l'étape précédente :

$ kubectl get pods -l app=webapp NOM PRÊT ÉTAT RESTARTS AGE webapp-rc-544f1 1/1 En cours d'exécution 0 2m webapp-rc-uk6pm 1/1 En cours d'exécution 0 2m

Création du service

Ensuite, nous créons un service pour les pods créés par notre contrôleur de réplication. Nous déclarons le service avec le fichier suivant ( webapp-service.yaml ) :

apiVersion: v1kind: Service
métadonnées :
nom : webapp-svc
spécification :
clusterIP : Aucun
ports :
- port : 80
targetPort : 80
protocole : TCP
nom : http
sélecteur :
application : webapp

Ici, nous déclarons un service spécial sans tête en définissant le champ ClusterIP sur None . Avec ce type de service, aucune adresse IP de cluster n'est attribuée et le service n'est pas disponible via le proxy Kube. Une requête DNS vers le DNS Kubernetes renvoie plusieurs enregistrements A (les adresses IP de nos pods).

Nous déclarons également le port que NGINX Plus utilisera pour connecter les pods. En plus de spécifier le port et les numéros de port cible, nous spécifions le nom ( http ) et le protocole ( TCP ). Nous utilisons ces valeurs dans le fichier de configuration NGINX Plus, dans lequel nous demandons à NGINX Plus d'obtenir les numéros de port des pods via DNS à l'aide d'enregistrements SRV .

En définissant le champ sélecteur sur app: webapp , nous déclarons quels pods appartiennent au service, à savoir les pods créés par notre contrôleur de réplication NGINX (défini dans webapp-rc.yaml ).

Nous exécutons la commande suivante, qui crée le service :

$ kubectl create -f service d'application web.yaml

Maintenant, si nous actualisons la page du tableau de bord et cliquons sur l’onglet Upstreams dans le coin supérieur droit, nous voyons les deux serveurs que nous avons ajoutés.

Le tableau de bord de surveillance des activités en direct de NGINX Plus après la création des services Kubernetes

Nous pouvons également vérifier que NGINX Plus équilibre la charge du trafic entre les pods du service. Si c'est le cas, lorsque nous accédons à http://10.245.1.3/webapp/ dans un navigateur, la page nous montre les informations sur le conteneur dans lequel le serveur Web s'exécute, telles que le nom d'hôte et l'adresse IP.

Si nous actualisons cette page plusieurs fois et regardons le tableau de bord d’état, nous voyons comment les requêtes sont réparties sur les deux serveurs en amont.

Mise à l'échelle du service Kubernetes

[Éditeur – Cette section a été mise à jour pour utiliser l’ API NGINX Plus , qui remplace et supprime le module d’état distinct utilisé à l’origine.]

Ajoutons maintenant deux autres pods à notre service et assurons-nous que la configuration NGINX Plus est à nouveau mise à jour automatiquement. Nous exécutons cette commande pour modifier le nombre de pods à quatre en mettant à l'échelle le contrôleur de réplication :

$ kubectl scale rc webapp-rc --replicas=4 mis à l'échelle

Pour vérifier que NGINX Plus a été reconfiguré, nous pouvons à nouveau consulter le tableau de bord, mais cette fois, nous utilisons l' API NGINX Plus à la place. Nous exécutons la commande suivante, avec10.245.1.3 étant l'adresse IP externe de notre nœud NGINX Plus et3 la version de l' API NGINX Plus . Pour formater proprement la sortie JSON, nous la canalisons vers jq .

$ curl -s10.245.1.3 :8080/api/3 /http/upstreams/backend/servers | jq { "pairs": [ { "id": 1, « serveur » : "10.0.0.1:80", "sauvegarde" : faux, "poids" : 1, « état » : « malsain », « actif » : 0, « requêtes » : 1, "réponses": { "1xx": 0, « 2xx » : 0, "3xx": 0, « 4xx » : 0, « 5xx » : 0, "totale" : 0 }, "envoyé": 0, "reçu" : 0, « échoue » : 0, "non disponible" : 0, "contrôles_de_santé": { "contrôles": 1, « échoue » : 1, « malsain » : 1, "last_passed": faux }, "temps d'arrêt": 33965, « démarrage » : 1445378182275, « sélectionné » : 1445378131000 }, { "id": 2, « serveur » : "10.246.1.6:80", ... }, { "id": 3, « serveur » : "10.246.3.2:80", ... { "id": 4, « serveur » : "10.0.0.2:80", ... } ], "keepalive": 0 }

Le tableau des pairs dans la sortie JSON contient exactement quatre éléments, un pour chaque serveur Web.

Réduisons maintenant le nombre de pods de quatre à un et vérifions à nouveau l’état de NGINX Plus :

$ kubectl scale rc webapp-rc --replicas=1 mis à l'échelle $ curl -s10.245.1.3 :8080/api/3 /http/upstreams/backend/serveurs | jq

Désormais, le tableau des pairs dans la sortie JSON ne contient qu’un seul élément (la sortie est la même que pour le pair avec l’ID 1 dans l’exemple de commande précédent).

Maintenant que NGINX Plus est opérationnel, nous pouvons commencer à exploiter ses fonctionnalités avancées telles que la persistance de session , la terminaison SSL/TLS , le routage des requêtes , la surveillance avancée , etc.

Résumé

Les options de reconfiguration à la volée disponibles dans NGINX Plus vous permettent de l'intégrer facilement à Kubernetes : soit par programmation via une API, soit entièrement au moyen de DNS. L’utilisation de NGINX Plus pour exposer les services Kubernetes à Internet offre de nombreuses fonctionnalités qui manquent aux solutions d’équilibrage de charge Kubernetes intégrées actuelles.

Pour découvrir comment NGINX Plus fonctionne avec Kubernetes, démarrez votre essai gratuit de 30 jours dès aujourd'hui ou contactez-nous pour discuter de votre cas d'utilisation.


« Cet article de blog peut faire référence à des produits qui ne sont plus disponibles et/ou qui ne sont plus pris en charge. Pour obtenir les informations les plus récentes sur les produits et solutions F5 NGINX disponibles, explorez notre famille de produits NGINX . NGINX fait désormais partie de F5. Tous les liens NGINX.com précédents redirigeront vers un contenu NGINX similaire sur F5.com."