<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Ingress on Zwindler's Reflection</title><link>https://blog.zwindler.fr/tags/ingress/</link><description>Recent content in Ingress on Zwindler's Reflection</description><generator>Hugo -- gohugo.io</generator><language>fr-fr</language><copyright>Licensed under CC BY-SA 4.0</copyright><lastBuildDate>Mon, 14 Nov 2022 06:30:00 +0200</lastBuildDate><atom:link href="https://blog.zwindler.fr/tags/ingress/index.xml" rel="self" type="application/rss+xml"/><item><title>Je déconseille nginx en tant qu'ingressController en production</title><link>https://blog.zwindler.fr/2022/11/14/je-deconseille-nginx-ingresscontroller-en-production/</link><pubDate>Mon, 14 Nov 2022 06:30:00 +0200</pubDate><guid>https://blog.zwindler.fr/2022/11/14/je-deconseille-nginx-ingresscontroller-en-production/</guid><description>&lt;img src="https://blog.zwindler.fr/2017/06/kubernetes2.webp" alt="Featured image of post Je déconseille nginx en tant qu'ingressController en production" /&gt;&lt;h2 id="disclaimer"&gt;Disclaimer
&lt;/h2&gt;&lt;p&gt;Je n&amp;rsquo;utilise plus nginx comme &lt;strong&gt;IngressController&lt;/strong&gt; Kubernetes depuis 2020 (même si j&amp;rsquo;ai écris quelques articles dessus, notamment &lt;a class="link" href="https://blog.zwindler.fr/2018/03/06/exposer-des-applications-kubernetes-en-dehors-des-cloud-providers-nginx-ingress-controller/" &gt;Exposer des applications containerisées Kubernetes (nginx Ingress Controller)&lt;/a&gt;). Aussi, il se peut que les informations contenues ici soient périmées.&lt;/p&gt;
&lt;p&gt;Cependant, des issues récentes faisant état du même problème que le miens sont régulièrement ouvertes donc je pense que c&amp;rsquo;est toujours le cas.&lt;/p&gt;
&lt;p&gt;• &lt;a class="link" href="https://github.com/kubernetes/ingress-nginx/issues/2461" target="_blank" rel="noopener"
&gt;github.com/kubernetes/ingress-nginx/issues/2461&lt;/a&gt;
• &lt;a class="link" href="https://github.com/kubernetes/ingress-nginx/issues/7115" target="_blank" rel="noopener"
&gt;github.com/kubernetes/ingress-nginx/issues/7115&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="contexte"&gt;Contexte
&lt;/h2&gt;&lt;p&gt;Pour qu&amp;rsquo;on mette tout de suite d&amp;rsquo;accord sur ce dont on parle, je ne déconseille évidemment pas l&amp;rsquo;usage de nginx en production. nginx est un soft robuste qui a fait ses preuves pendant des années et que j&amp;rsquo;utilise encore dans certains contextes pros et perso.&lt;/p&gt;
&lt;p&gt;Cependant, quand j&amp;rsquo;ai commencé à travailler avec Kubernetes, j&amp;rsquo;ai (comme beaucoup) lu la documentation.&lt;/p&gt;
&lt;p&gt;Et à l&amp;rsquo;époque, pour ce qui est de l&amp;rsquo;utilisation des Ingress, la documentation officielle mettait en avant l&amp;rsquo;implémentation de l&amp;rsquo;IngressController nginx disponible sur le Github de Kubernetes &lt;a class="link" href="https://github.com/kubernetes/ingress-nginx" target="_blank" rel="noopener"
&gt;github.com/kubernetes/ingress-nginx&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Point intéressant, il existe un autre dépôt mis à disposition par la société nginx inc, que je n&amp;rsquo;ai jamais utilisé &lt;a class="link" href="https://github.com/nginxinc/kubernetes-ingress" target="_blank" rel="noopener"
&gt;github.com/nginxinc/kubernetes-ingress.&lt;/a&gt; qui n&amp;rsquo;est peut être pas affecté. Cependant quand on parle de &amp;ldquo;l&amp;rsquo;IngressController nginx&amp;rdquo; la plupart des gens parle du repo sur le Github de Kubernetes (source : moi, tkt)&lt;/p&gt;
&lt;h2 id="et-donc-quel-est-le-problème-"&gt;Et donc quel est le problème ?
&lt;/h2&gt;&lt;p&gt;Maintenant qu&amp;rsquo;on est bien d&amp;rsquo;accord que ce dont on parle, je peux vous raconter une petite histoire.&lt;/p&gt;
&lt;p&gt;A l&amp;rsquo;époque je travaillais pour une entreprise industrielle qui hébergeait &amp;ldquo;dans le cloud&amp;rdquo; un logiciel vendu en SaaS.&lt;/p&gt;
&lt;p&gt;Chaque client avait sa propre instance, hébergée sur un Kubernetes hébergé sur Azure.&lt;/p&gt;
&lt;p&gt;Au début nous avions peu de clients, tout allait bien. Mais au fur et à mesure que le nombre de clients grossissait, on commençait à avoir des retours de la part des équipes métiers et support comme quoi, de temps en temps, l&amp;rsquo;application perdait temporairement la connexion au serveur.&lt;/p&gt;
&lt;p&gt;En bon sysadmin et après avoir vérifié l&amp;rsquo;absence d&amp;rsquo;alertes de notre côté, on a d&amp;rsquo;abord blâmé l&amp;rsquo;utilisateur, le réseau et l&amp;rsquo;application elle même (dans cet ordre). &lt;strong&gt;#Trollface&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Blague à part, la réalité, c&amp;rsquo;est que nous ne savions pas trop par où prendre le problème car nous n&amp;rsquo;avions aucun log, aucun incident et le coupures étaient au début très rares et surtout aléatoires en apparence.&lt;/p&gt;
&lt;h2 id="jusquau-jour-où"&gt;Jusqu&amp;rsquo;au jour où&amp;hellip;
&lt;/h2&gt;&lt;p&gt;Jusqu&amp;rsquo;au jour où, pour des histoires de CVEs à patcher, nous avons redéployé un très grand nombre d&amp;rsquo;applications dans un créneau horaire assez court.&lt;/p&gt;
&lt;p&gt;A ce moment là, le nombre de plaintes a fortement augmenté et nous a permis de valider que le problème n&amp;rsquo;était pas aléatoire et était bien de notre côté.&lt;/p&gt;
&lt;p&gt;Nous avons deviné qu&amp;rsquo;il y avait une corrélation entre le déploiement d&amp;rsquo;applications dans Kubernetes et la coupure des connexions (websockets) côté client.&lt;/p&gt;
&lt;h2 id="on-est-pas-seul"&gt;On est pas seul
&lt;/h2&gt;&lt;p&gt;Une fois qu&amp;rsquo;on savait ça, on a trouvé le coupable assez vite. Une rapide recherche Google nous a permis de tomber sur plusieurs issues sur le repository de l&amp;rsquo;IngressController, décrivant les mêmes symptômes.&lt;/p&gt;
&lt;p&gt;En creusant un peu, on a également trouvé un article très complet qui détaille bien mieux que ce que j&amp;rsquo;aurais pu faire le problème.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://danielfm.me/post/painless-nginx-ingress/" target="_blank" rel="noopener"
&gt;DanielFM - pain(less) NGINX Ingress&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="cest-quoi-le-problème-"&gt;C&amp;rsquo;est quoi le problème ???
&lt;/h2&gt;&lt;p&gt;TL;DR tel que l&amp;rsquo;IngressController est implémenté par défaut, la configuration de nginx est rechargée à chaque fois qu&amp;rsquo;une modification a lieu sur les backends des Services Kubernetes.&lt;/p&gt;
&lt;p&gt;Pour ceux qui ne sont pas encore bien familier avec ces concepts, à chaque fois qu&amp;rsquo;un Pod (votre app containerisée) est créé ou détruit, nginx est rechargé.&lt;/p&gt;
&lt;p&gt;Théoriquement, ça se fait à chaud car nginx supporte les rechargements de configuration à chaud. Sauf que, tel que l&amp;rsquo;IngressController est implémenté, les Websockets ouvertes doivent être coupées&amp;hellip;&lt;/p&gt;
&lt;p&gt;Pour limiter la casse, à chaque rechargement de configuration, un processus nginx avec la nouvelle configuration est généré en parallèle de l&amp;rsquo;ancien qui est gardé au maximum 10 secondes pour donner une chance à toutes les connexions en cours de se fermer proprement.&lt;/p&gt;
&lt;h2 id="solutions-"&gt;Solutions ?
&lt;/h2&gt;&lt;p&gt;Dans son post, Daniel fait le tour des workarounds à votre disposition pour limiter la casse.&lt;/p&gt;
&lt;p&gt;La première chose qu&amp;rsquo;on peut faire et qui marche bien est d&amp;rsquo;ajouter l&amp;rsquo;option &lt;code&gt;--enable-dynamic-configuration&lt;/code&gt; qui fait que la configuration n&amp;rsquo;est plus rechargée à chaque changement de backends sur les services (événements hyper fréquent) mais uniquement lors des créations/suppression de services (le déploiement d&amp;rsquo;une nouvelle app).&lt;/p&gt;
&lt;p&gt;Ça limite drastiquement le nombre de reloads mais n&amp;rsquo;est évidemment pas une solution.&lt;/p&gt;
&lt;p&gt;Le deuxième levier mis en avant par Daniel est d&amp;rsquo;augmenter le timeout de 10s (&lt;code&gt;--worker-shutdown-timeout&lt;/code&gt;) et de mettre quelque chose de très grand. Cependant, il met en garde contre cette solution car on se retrouve vite avec un duplication des processus nginx avec X versions de la conf, ce qui peut faire saturer la RAM de votre ingressController ou votre node&amp;hellip;&lt;/p&gt;
&lt;p&gt;Dernière idée, pour limiter la disruption causée par un changement, nous avions envisagé de segmenter en ayant un ingressController par namespaces. Ainsi en cas de redéploiement, seul les applications du namespace en cours de déploiement seraient concernées par la coupure (des « workarounds » plutôt) :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Limiter les reloads (pénible)&lt;/li&gt;
&lt;li&gt;Augmenter sensiblement (24h ?) les timeout sur les connexions actives&lt;/li&gt;
&lt;li&gt;Segmenter les namespaces (1 Ingress Controller par namespace, on limite l&amp;rsquo;impact d&amp;rsquo;un redéploiement à un client)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mais-alors-on-fait-quoi-"&gt;Mais alors on fait quoi ?
&lt;/h2&gt;&lt;p&gt;Comme il n&amp;rsquo;y a pas vraiment de solution à date, le plus simple reste de ne tout simplement pas utiliser l&amp;rsquo;IngressController nginx de Kubernetes 😉 et de lui préférer une implémentation gérant ce genre de cas à chaud.&lt;/p&gt;
&lt;p&gt;Même si je n&amp;rsquo;ai pas retravaillé avec depuis un moment, nous avions eu à l&amp;rsquo;époque de bons résultats avec &lt;a class="link" href="https://traefik.io/solutions/kubernetes-ingress/" target="_blank" rel="noopener"
&gt;Traefik&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Et si vous en connaissez d&amp;rsquo;autres qui gèrent bien ce genre de cas, n&amp;rsquo;hésitez pas à me l&amp;rsquo;indiquer :).&lt;/p&gt;</description></item><item><title>Exposer des applications containerisées Kubernetes (nginx Ingress Controller)</title><link>https://blog.zwindler.fr/2018/03/06/exposer-des-applications-kubernetes-en-dehors-des-cloud-providers-nginx-ingress-controller/</link><pubDate>Tue, 06 Mar 2018 12:45:47 +0000</pubDate><guid>https://blog.zwindler.fr/2018/03/06/exposer-des-applications-kubernetes-en-dehors-des-cloud-providers-nginx-ingress-controller/</guid><description>&lt;img src="https://blog.zwindler.fr/2018/02/kubernetes_nginx.webp" alt="Featured image of post Exposer des applications containerisées Kubernetes (nginx Ingress Controller)" /&gt;&lt;h2 id="ingress-et-ingress-controller-versus-baremetal"&gt;Ingress et Ingress Controller versus Baremetal
&lt;/h2&gt;&lt;p&gt;Autant le dire tout de suite, cet article s’adresse surtout aux admins qui font du Kubernetes (K8s pour les intimes) et en plus qui font tout eux même. Mais comme je suis sympa j’explique tout et j’ai mis des schémas si vous êtes curieux ;-).&lt;/p&gt;
&lt;p&gt;Je vous plante le décors : &lt;a class="link" href="https://blog.zwindler.fr/recherche/?keyword=Kubernetes" &gt;vous avez suivi un de mes tutos sur Kubernetes&lt;/a&gt; et vous avez maintenant un cluster opérationnel en dehors des gros cloud providers (Amazon, Google, &amp;hellip;) et de leurs solutions clés en main (sur vos propres VMs et/ou serveurs physiques). Vous êtes super contents et il y a de quoi.&lt;/p&gt;
&lt;p&gt;Seulement voilà, maintenant que vous pouvez spawner des containers à tire larigot, vous voulez pouvoir y accéder depuis l’Internet.&lt;/p&gt;
&lt;h2 id="mais-là-comment-faire-"&gt;Mais là, comment faire ?
&lt;/h2&gt;&lt;p&gt;Le premier problème que vous risquez d’avoir est que les applications que vous déployez dans Kubernetes ne sont de base accessibles que DANS Kubernetes.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;On va être très très vite limité, niveau usecases.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Pour accéder à un container (ou faire discuter 2 containers comme un serveur web et une base de données), on passe par l’intermédiaire d’un objet appelé &lt;strong&gt;Service&lt;/strong&gt;. C’est cet objet qui permet le service discovery, le scaling aisé de nos applications et la résolution de nom au sein du cluster.&lt;/p&gt;
&lt;p&gt;Cependant, hors du cluster, pas de résolution de nom et/ou d’accès aux ressources par ce biais. Vous allez donc devoir passer par un DNS externe pour spécifier aux clients où sont vos applications et trouver un moyen de différencier quelle requête externe doit aboutir dans quelle container.&lt;/p&gt;
&lt;h2 id="accéder-aux-ressources"&gt;Accéder aux ressources
&lt;/h2&gt;&lt;p&gt;Le premier problème est donc de réussir à accéder à notre service. S’il est possible de créer des &lt;strong&gt;Services&lt;/strong&gt; (les points d’entrées de nos containers) de type &lt;strong&gt;LoadBalancer&lt;/strong&gt; sur AWS, Azure et GCP, qui ont l’avantage de permettre un accès direct au service depuis Internet (magie !), le mieux que l’on puisse faire par défaut sur un cluster Baremetal, c’est un &lt;strong&gt;Service&lt;/strong&gt; de type &lt;strong&gt;NodePort&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Si vous n’êtes pas chez un cloud provider comme nous l’avons dit au départ, vous allez vite vous rendre compte qu’il n’est pas trivial de présenter un container sur HTTP:80 ou HTTPS:443. Car par défaut, les &lt;strong&gt;Services NodePort&lt;/strong&gt; exposent nos container sur un port aléatoire compris entre 30000 et &lt;em&gt;3X000-je-sais-pas-combien&lt;/em&gt; (mate la précision) sur tous les nœuds du clusters.&lt;/p&gt;
&lt;p&gt;Il y a deux choses importantes dans cette dernière phrase :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;D’abord, on va se retrouver avec des URLs du type : &lt;code&gt;http://@IP_node:32251&lt;/code&gt; pour accéder à un serveur web depuis l’extérieur. Pas glop.&lt;/li&gt;
&lt;li&gt;Ensuite, pour un &lt;strong&gt;Service&lt;/strong&gt; de type &lt;strong&gt;NodePort&lt;/strong&gt; donné, le port alloué l’est sur TOUS les membres du cluster, que le container tourne dessus ou pas. Ça veut dire que &lt;em&gt;peu importe quel nœud Kubernetes on interroge&lt;/em&gt;, le 32251 répondra TOUJOURS sur le même container (les requêtes sont forwardé au bon nœud de manière transparente). Ça veut aussi dire qu’il n’y aura qu’un seul service qui aura le privilège d’utiliser le 32251 et aucun autre &lt;strong&gt;Service&lt;/strong&gt; ne pourra le réserver.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/02/Kubernetes1-1.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Clairement, c’est tout sauf idéal. On se retrouve donc à différencier les applications simplement avec les numéros des ports qu’on accède.&lt;/p&gt;
&lt;h2 id="le-dns"&gt;Le DNS
&lt;/h2&gt;&lt;p&gt;Et c’est pas fini&amp;hellip;&lt;/p&gt;
&lt;p&gt;Si on prend un cas simple : un site web à exposer sur Internet, on va souvent vouloir relier une URL humainement compréhensible au container qui gère ce site. Cependant cette notion n’a pas vraiment de sens avec Kubernetes.&lt;/p&gt;
&lt;p&gt;Vous ne savez pas &lt;em&gt;a priori&lt;/em&gt; &lt;strong&gt;où&lt;/strong&gt; va être instancié votre container dans le cluster (i.e. sur quelle machine et donc sur quelle IP). Ça sera un des nœuds du cluster, mais lequel ? D’autant que le &lt;strong&gt;Pod&lt;/strong&gt; bouge d’un nœud à l’autre au gré de la vie de l’application (&lt;em&gt;drain&lt;/em&gt; du node pour maintenance ou incident). Difficile donc de donner avec certitude un enregistrement DNS fiable dans le temps.&lt;/p&gt;
&lt;p&gt;Alors bien sûr, vous pouvez toujours fixer en dur l’adresse IP d’un des nœuds Kubernetes dans un enregistrement DNS mais cette méthode trouve très vite sa limite : le moindre arrêt du serveur cause la perte de l’accès à l’application, qui pourtant a probablement été redémarrée sur un nœud du cluster.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/02/Kubernetes2.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Vous me pardonnerez ce « comic » en mode Draw.io. On s’amuse comme on peut ;-)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A quoi ça sert d’avoir un cluster dans ce cas là ?&lt;/p&gt;
&lt;p&gt;Vous aurez peut être alors l’idée d’utiliser un moyen automatique (&lt;a class="link" href="https://blog.zwindler.fr/2014/09/22/mise-a-jour-de-votre-dns-chez-ovh-avec-dynhost/" &gt;genre ce script qui utilise Dynhost, au hasard&lt;/a&gt;) pour mettre à jour le DNS dès que l’application change de nœud. Mais c’est clairement de la bidouille et on se retrouvera avec pleins d’utilisateurs dont les caches DNS ne sont pas à jour.&lt;/p&gt;
&lt;h2 id="la-méthode-simple"&gt;La méthode simple
&lt;/h2&gt;&lt;p&gt;On peut quand même bosser avec ce qu’on a et présenter à nos gentils utilisateurs des URLs user-friendly sans trop de difficultés, dans la majorité des cas.&lt;/p&gt;
&lt;p&gt;La première chose qu’on peut faire c’est simplement mettre en face de notre cluster Kubernetes un bête reverse proxy et/ou répartiteur de charge. Après tout, c’est ni plus ni moins ce que font AWS et autre avec leur implémentation du &lt;strong&gt;Service&lt;/strong&gt; de type &lt;strong&gt;Loadbalancer&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;L’ensemble des requêtes HTTP(S) sont donc dirigées vers le reverse proxy, qui se charge de masquer la complexité de l’URL (l’aiguillage via des ports chelous et le maintiens à jour de l’ensemble des nœud du cluster qu’on arrive à contacter) à l’utilisateur final.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://blog.zwindler.fr/2018/02/Kubernetes3.avif"
loading="lazy"
&gt;&lt;/p&gt;
&lt;p&gt;Personnellement, &lt;strong&gt;pour mes projets perso&lt;/strong&gt;, ça m’ennuie d’avoir un composant externe au cluster K8s pour faire ça. J’ai déjà investi dans un cluster pour rendre mes applications hautement disponibles (ce qui est déjà overkill), je ne vais pas en plus :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;soit ajouter un SPOF en ajoutant une seule machine pour faire mon reverse proxy&lt;/li&gt;
&lt;li&gt;soit ajouter un cluster de machines rien que pour le reverse proxy&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="et-les-ingress-dans-tout-ça-"&gt;Et les Ingress dans tout ça ?
&lt;/h2&gt;&lt;p&gt;Donc on l’a vu, tout ça c’est pas super propre et on ajoute potentiellement un SPOF, mais ça « marche ». Mais on peut faire mieux :)&lt;/p&gt;
&lt;p&gt;Si vous manipulez un peu Kubernetes, vous avez donc peut être vu qu’il existe un autre type d’objet qui s’appelle les &lt;strong&gt;Ingress&lt;/strong&gt; et les &lt;strong&gt;Ingress Controllers&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Pour ceux qui n’ont pas eu le temps de potasser, un &lt;strong&gt;Ingress&lt;/strong&gt; est une règle qui permet de relier une URL à un &lt;strong&gt;Service&lt;/strong&gt; et un &lt;strong&gt;Ingress Controller&lt;/strong&gt; est un composant qui permet de piloter un reverse-proxy pour implémenter cette règle. C’est &lt;em&gt;LA&lt;/em&gt; méthode propre pour traduire une URL provenant d’un client en requête interne dans le cluster K8s pour atteindre le bon service.&lt;/p&gt;
&lt;p&gt;L’&lt;strong&gt;Ingress Controller&lt;/strong&gt; le plus utilisé est probablement celui pour nginx, mais il existe des &lt;strong&gt;Ingress Controllers&lt;/strong&gt; pour &lt;a class="link" href="https://doc.traefik.io/traefik/reference/install-configuration/providers/kubernetes/kubernetes-ingress/" target="_blank" rel="noopener"
&gt;traefik&lt;/a&gt; ou ha-proxy (ou autre) qui ont été développés et qui sont plus ou moins aboutis.&lt;/p&gt;
&lt;h2 id="helm"&gt;Helm
&lt;/h2&gt;&lt;p&gt;Helm c’est super. &lt;a class="link" href="https://blog.zwindler.fr/2018/02/06/se-simplifier-kubernetes-helm-charts/" &gt;J’en ai parlé dans un autre article il n’y a pas longtemps&lt;/a&gt;, c’est un genre de gestionnaire d’application pour Kubernetes et ça simplifie grandement son utilisation. Mais il faut être honnête, ce n’est pas toujours une super idée&amp;hellip;&lt;/p&gt;
&lt;p&gt;Déjà, la documentation sur &lt;a class="link" href="https://github.com/kubernetes/ingress-nginx" target="_blank" rel="noopener"
&gt;la page d’accueil du Chart est super light&lt;/a&gt;. Si vous ne trouvez pas d’infos sur comment le déployer, c’est normal, c’est parce qu’il faut aller dans le dossier « deploy » du dépôt pour &lt;a class="link" href="https://github.com/kubernetes/ingress-nginx/tree/master/deploy" target="_blank" rel="noopener"
&gt;trouver la doc d’installation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Du coup, confiant, j’y suis allé avant d’avoir trouvé cette page, et je me suis pris ma première claque ;-)&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;helm install stable/nginx-ingress --name nginx-ingress
NAME: nginx-ingress
LAST DEPLOYED: Sun Feb 25 16:24:11 2018
NAMESPACE: default
STATUS: DEPLOYED
[...]
NOTES:
The nginx-ingress controller has been installed.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Oh cool, ça marché déjà ?&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-7c6f79d45c-jwqkp 0/1 CrashLoopBackOff 14 47m
nginx-ingress-default-backend-6664bc64c9-2zpg4 1/1 Running 0 47m
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ah ben non en fait parce que je suis en RBAC (K8s &amp;gt; 1.7.0) ! Il faut créer des autorisations et un compte de service pour l’&lt;strong&gt;Ingress Controller&lt;/strong&gt;.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl logs nginx-ingress-controller-7c6f79d45c-jwqkp
-------------------------------------------------------------------------------
NGINX Ingress controller
Release: 0.10.2
Build: git-fd7253a
Repository: https://github.com/kubernetes/ingress-nginx
-------------------------------------------------------------------------------
I0225 16:11:13.374547 7 flags.go:159] Watching for ingress class: nginx
I0225 16:11:13.376659 7 main.go:181] Creating API client for https://10.233.0.1:443
I0225 16:11:13.438774 7 main.go:193] Running in Kubernetes Cluster version v. (v1.9.0+coreos.0) - git (clean) commit 1b69a2a6c01194421b0aa17747a8c1a81738a8dd - platform linux/amd64
F0225 16:11:13.442654 7 main.go:80] &amp;amp;#x2716; It seems the cluster it is running with Authorization enabled (like RBAC) and there is no permissions for the ingress controller. Please check the configuration
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ok, pas grave&amp;hellip; On supprime et on recommence !&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;helm list
NAME REVISION UPDATED STATUS CHART NAMESPACE
nginx-ingress 1 Sun Feb 25 16:24:11 2018 DEPLOYED nginx-ingress-0.9.1 default
helm delete nginx-ingress
release &amp;#34;nginx-ingress&amp;#34; deleted
helm install stable/nginx-ingress --name nginx-ingress --set rbac.create=true
[...]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Bon, ne vous fatiguez pas. Ça aura l’air de marcher mais en fait, le &lt;em&gt;nginx-ingress-controller&lt;/em&gt; se base sur un &lt;strong&gt;Service&lt;/strong&gt; de type&amp;hellip; &lt;strong&gt;Loadbalancer&lt;/strong&gt; ! Si vous n’êtes pas sur AWS, GCE ou Azure, votre &lt;strong&gt;Service&lt;/strong&gt; restera indéfiniment à l’état &lt;em&gt;Pending&lt;/em&gt; en attente d’une IP publique ;-)&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-ingress-controller LoadBalancer 10.233.52.122 80:30215/TCP,443:31438/TCP 41m
nginx-ingress-default-backend ClusterIP 10.233.29.8 80/TCP 41m
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="donc-on-laisse-tomber-helm-pour-cette-fois"&gt;Donc on laisse tomber Helm pour cette fois
&lt;/h2&gt;&lt;p&gt;En réalité, le mieux c’est de repartir sur le projet nginx Ingress Controller, qui donne (pour qui trouve la documentation) la bonne marche à suivre pour instancier rapidement son &lt;strong&gt;Ingress Controller&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/ingress-nginx" target="_blank" rel="noopener"
&gt;github.com/kubernetes/ingress-nginx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md#bare-metal" target="_blank" rel="noopener"
&gt;github.com/kubernetes/ingress-nginx/blob/master/docs/deploy/index.md#bare-metal&lt;/a&gt; (lien mis à jour le 08/10/2018)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Partie à exécuter dans tous les cas&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/cb876766897806ed60b1f2f36564d5f3af8a18c8/deploy/namespace.yaml \
| kubectl apply -f -
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/cb876766897806ed60b1f2f36564d5f3af8a18c8/deploy/default-backend.yaml \
| kubectl apply -f -
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/cb876766897806ed60b1f2f36564d5f3af8a18c8/deploy/configmap.yaml \
| kubectl apply -f -
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/cb876766897806ed60b1f2f36564d5f3af8a18c8/deploy/tcp-services-configmap.yaml \
| kubectl apply -f -
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/cb876766897806ed60b1f2f36564d5f3af8a18c8/deploy/udp-services-configmap.yaml \
| kubectl apply -f -
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Partie spécifique à ajouter pour déployer l’&lt;strong&gt;Ingress Controller&lt;/strong&gt; dans un environnement de type RBAC (K8s &amp;gt;= 1.7)&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/cb876766897806ed60b1f2f36564d5f3af8a18c8/deploy/rbac.yaml \
| kubectl apply -f -
curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/cb876766897806ed60b1f2f36564d5f3af8a18c8/deploy/with-rbac.yaml \
| kubectl apply -f -
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Partie spécifique à ajouter en dernier, dans le cas où on est sur un cluster baremetal (i.e. en dehors des cloud providers).&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/cb876766897806ed60b1f2f36564d5f3af8a18c8/deploy/provider/baremetal/service-nodeport.yaml \
| kubectl apply -f -
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="ok-on-a-quoi-maintenant-"&gt;OK, on a quoi maintenant ?
&lt;/h2&gt;&lt;p&gt;Et bien, c’est pas encore fini malheureusement&amp;hellip; En fait, tel quel, le dernier fichier YAML qu’on a créé nous créé un service de type NodePort&amp;hellip;&lt;/p&gt;
&lt;p&gt;Oui vous l’avez compris : retour à la case départ ! Nous avons un composant reverse proxy intégré à K8s, mais qui est en écoute sur un port 3XXXX au lieu du 80, et 3YYYY au lieu du 443. Là encore, on aurait pas du tout ce problème si on était chez AWS, car un service de type Loadbalancer (avec une IP publique) aurait été créé pour nous.&lt;/p&gt;
&lt;p&gt;Rassurez vous, il y a des solutions, moyennant un peu de bidouille. J’en ai trouvé 2 dans notre cas.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://medium.com/@olegsmetanin/how-to-setup-baremetal-kubernetes-cluster-with-kubespray-and-deploy-ingress-controller-with-170cdb5ac50d" target="_blank" rel="noopener"
&gt;blog.will3942.com/nginx-kubernetes-bare-metal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&amp;lt;a href=&amp;ldquo;&lt;a class="link" href="https://medium.com/@olegsmetanin/how-to-setup-baremetal-kubernetes-cluster-with-kubespray-and-deploy-ingress-controller-with-170cdb5ac50d%3e" target="_blank" rel="noopener"
&gt;https://medium.com/@olegsmetanin/how-to-setup-baremetal-kubernetes-cluster-with-kubespray-and-deploy-ingress-controller-with-170cdb5ac50d&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour faire simple, la première nécessite juste de modifier unfichier de configuration de Kubernetes pour autoriser le composant &lt;strong&gt;NodePort&lt;/strong&gt; à utiliser des ports en dessous de la limite arbitraire des 30000. Je ne suis pas fan du tout de cette solution mais elle « fonctionne » donc je vous laisse juger.&lt;/p&gt;
&lt;p&gt;En revanche, je trouve la seconde bien plus élégante quoique peut être un peu moins flexible. On peut modifier le &lt;strong&gt;Service&lt;/strong&gt; de l’&lt;strong&gt;Ingress Controller&lt;/strong&gt; en y listant toutes les adresses IPs de tous vos serveurs K8s. Ce n’est pas super confortable dans le cas où ils changent souvent, mais ça à l’effet qu’on recherche, à savoir ouvrir les ports 80 et 443 et rediriger l’ensemble des requêtes HTTP vers les &lt;strong&gt;Ingress&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;La modification à réaliser se situe au niveau du champ &lt;strong&gt;externalIPs&lt;/strong&gt; :&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;curl https://raw.githubusercontent.com/kubernetes/ingress-nginx/cb876766897806ed60b1f2f36564d5f3af8a18c8/deploy/provider/baremetal/service-nodeport.yaml -o ingress-nginx-service-nodeport.yaml
vi ingress-nginx-service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
- name: https
port: 443
targetPort: 443
protocol: TCP
externalIPs:
- 10.0.0.1
- 10.0.0.2
- 10.0.0.3
selector:
app: ingress-nginx
kubectl apply -f ingress-nginx-service-nodeport.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Normalement après application de la modification vous devriez avoir la joie (oui oui, carrément) de voir apparaitre sur tous les serveurs (que vous aurez listés) les ports 80 et 443 en écoute !!&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;ss -lnt
LISTEN 0 128 8.8.8.8:80 *:*
LISTEN 0 128 8.8.8.8:443 *:*
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="super-et-maintenant-cest-bon-mon-container-nginx-est-accessible-"&gt;Super, et maintenant c’est bon, mon container nginx est accessible ?
&lt;/h2&gt;&lt;p&gt;Ah ben non, toujours pas. On a configuré l’&lt;strong&gt;Ingress Controller&lt;/strong&gt;, mais ça fait un moment qu’on parle plus des &lt;strong&gt;Ingress&lt;/strong&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;Comme je l’ai dis plus haut, les &lt;strong&gt;Ingress&lt;/strong&gt; sont donc les règles de notre reverse proxy, permettant de mapper les URLs entrant dans le cluster sur les ports 80 et 443 (ou autre si on en définit d’autres) vers les &lt;strong&gt;Services&lt;/strong&gt; définis dans le K8s.&lt;/p&gt;
&lt;p&gt;Heureusement c’est partie est assez simple à configurer. Voici l’exemple minimaliste d’une application dont le &lt;strong&gt;Service&lt;/strong&gt; &lt;em&gt;toto-app-svc&lt;/em&gt; écoute sur le port 8080 à l’intérieur du cluster Kubernetes. Ce service est maintenant accessible pour toute requête HTTP aboutissant sur un des noeuds du cluster et accédé avec l’URL toto.zwindler.fr.&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;cat nginx-ingress.yaml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
name: nginx-ingress
spec:
rules:
- host: toto.zwindler.fr
http:
paths:
- path: /
backend:
serviceName: toto-app-svc
servicePort: 8080
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Point intéressant à noter, il n’est plus nécessaire de faire du &lt;strong&gt;NodePort&lt;/strong&gt; maintenant, on peut se contenter des &lt;strong&gt;ClusterIP&lt;/strong&gt; par défaut. En effet, l’&lt;strong&gt;Ingress Controller&lt;/strong&gt; étant interne au cluster K8s, il sait résoudre les Services sans passer par un port crado en 30000. Autant ne plus les exposer donc et bannir les &lt;strong&gt;NodePorts&lt;/strong&gt; à présent !&lt;/p&gt;
&lt;p&gt;Bon vous avez vu ? Cette dernière étape n’est pas la plus dure qu’on ait fait !&lt;/p&gt;
&lt;p&gt;Et maintenant, à vos &lt;strong&gt;Ingress&lt;/strong&gt; !&lt;/p&gt;</description></item></channel></rss>