Moby: Impossible de récupérer l'adresse IP de l'utilisateur en mode Docker Swarm

Créé le 9 août 2016  ·  324Commentaires  ·  Source: moby/moby

Sortie de docker version :

Client:
 Version:      1.12.0
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   8eab29e
 Built:        Thu Jul 28 22:00:36 2016
 OS/Arch:      linux/amd64

Server:
 Version:      1.12.0
 API version:  1.24
 Go version:   go1.6.3
 Git commit:   8eab29e
 Built:        Thu Jul 28 22:00:36 2016
 OS/Arch:      linux/amd64

Sortie de docker info :

Containers: 155
 Running: 65
 Paused: 0
 Stopped: 90
Images: 57
Server Version: 1.12.0
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 868
 Dirperm1 Supported: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: host overlay null bridge
Swarm: active
 NodeID: 0ddz27v59pwh2g5rr1k32d9bv
 Is Manager: true
 ClusterID: 32c5sn0lgxoq9gsl1er0aucsr
 Managers: 1
 Nodes: 1
 Orchestration:
  Task History Retention Limit: 5
 Raft:
  Snapshot interval: 10000
  Heartbeat tick: 1
  Election tick: 3
 Dispatcher:
  Heartbeat period: 5 seconds
 CA configuration:
  Expiry duration: 3 months
 Node Address: 172.31.24.209
Runtimes: runc
Default Runtime: runc
Security Options: apparmor
Kernel Version: 3.13.0-92-generic
Operating System: Ubuntu 14.04.4 LTS
OSType: linux
Architecture: x86_64
CPUs: 8
Total Memory: 31.42 GiB
Name: ip-172-31-24-209
ID: 4LDN:RTAI:5KG5:KHR2:RD4D:MV5P:DEXQ:G5RE:AZBQ:OPQJ:N4DK:WCQQ
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Username: panj
Registry: https://index.docker.io/v1/
WARNING: No swap limit support
Insecure Registries:
 127.0.0.0/8

Détails supplémentaires sur l'environnement (AWS, VirtualBox, physique, etc.) :

Étapes pour reproduire le problème :

  1. exécuter le service suivant qui publie le port 80
docker service create \
--name debugging-simple-server \
--publish 80:3000 \
panj/debugging-simple-server
  1. Essayez de vous connecter avec http://<public-ip>/ .

Décrivez les résultats que vous avez reçus :
Ni ip ni header.x-forwarded-for n'est l'adresse IP correcte de l'utilisateur.

Décrivez les résultats que vous attendiez :
ip ou header.x-forwarded-for doit être l'adresse IP de l'utilisateur. Le résultat attendu peut être archivé à l'aide du conteneur docker autonome docker run -d -p 80:3000 panj/debugging-simple-server . Vous pouvez voir les deux résultats via les liens suivants,
http://swarm.issue-25526.docker.takemetour.com :81/
http://container.issue-25526.docker.takemetour.com :82/

Informations supplémentaires que vous jugez importantes (par exemple, le problème n'arrive qu'occasionnellement) :
Cela se produit à la fois en mode global et en mode replicated .

Je ne sais pas si j'ai raté quelque chose qui devrait résoudre ce problème facilement.

En attendant, je pense que je dois faire une solution de contournement qui exécute un conteneur proxy en dehors du mode swarm et le laisse passer au port publié en mode swarm (la terminaison SSL doit également être effectuée sur ce conteneur), ce qui brise le but de swarm mode d'auto-guérison et d'orchestration.

arenetworking areswarm kinenhancement statuneeds-attention versio1.12

Commentaire le plus utile

J'ai également rencontré le problème en essayant d'exécuter logstash en mode essaim (pour collecter les messages syslog de divers hôtes). Le champ "hôte" de logstash apparaît toujours sous la forme 10.255.0.x, au lieu de l'adresse IP réelle de l'hôte qui se connecte. Cela le rend totalement inutilisable, car vous ne pouvez pas dire de quel hôte proviennent les messages de journal. Existe-t-il un moyen d'éviter de traduire l'IP source ?

Tous les 324 commentaires

/ cc @aluzzardi @mrjana a demandé

@PanJ pouvez-vous s'il vous plaît partager quelques détails sur la façon dont debugging-simple-server détermine le ip ? De plus, quelle est l'attente si un service est mis à l'échelle sur plus d'un réplica sur plusieurs hôtes (ou en mode global) ?

@mavenugo c'est l'objet de requête de koa qui utilise le module remoteAddress du nœud net . Le résultat doit être le même pour toutes les autres bibliothèques pouvant récupérer l'adresse distante.

On s'attend à ce que le champ ip soit toujours une adresse distante, quelle que soit la configuration.

@PanJ, utilisez- vous toujours votre solution de contournement ou avez-vous trouvé une meilleure solution ?

@PanJ Lorsque

docker run -it --rm -p 80:3000 --name test panj/debugging-simple-server

et accéder au port publié à partir d'un autre hôte, j'obtiens ceci

vagrant@net-1:~$ curl 192.168.33.12
{"method":"GET","url":"/","header":{"user-agent":"curl/7.38.0","host":"192.168.33.12","accept":"*/*"},"ip":"::ffff:192.168.33.11","ips":[]}
vagrant@net-1:~$

192.168.33.11 est l'adresse IP de l'hôte sur lequel j'exécute curl. Est-ce le comportement attendu ?

@sanimej Oui, c'est le comportement attendu qui devrait également être en mode essaim.

@marech J'utilise toujours le conteneur autonome comme solution de contournement, ce qui fonctionne bien.

Dans mon cas, il existe 2 instances nginx, des instances autonomes et en essaim. La terminaison SSL et le proxy inverse sont effectués sur nginx autonome. L'instance Swarm est utilisée pour acheminer vers d'autres services en fonction de l'hôte de demande.

@PanJ La façon dont le port publié d'un conteneur est accessible est différente en mode essaim. En mode essaim, un service peut être atteint à partir de n'importe quel nœud du cluster. Pour faciliter cela, nous acheminons via un réseau ingress . 10.255.0.x est l'adresse de l'interface réseau ingress sur l'hôte du cluster à partir duquel vous essayez d'atteindre le port publié.

@sanimej J'ai un peu vu comment cela fonctionnait lorsque j'ai creusé le problème. Mais le cas d'utilisation (possibilité de récupérer l'IP de l'utilisateur) est assez courant.

J'ai des connaissances limitées sur la façon dont le correctif doit être mis en œuvre. Peut-être un type de réseau spécial qui ne modifie pas l'adresse IP source ?

Rancher est similaire au mode essaim de Docker et il semble avoir le comportement attendu. C'est peut-être un bon endroit pour commencer.

@sanimej une bonne idée pourrait être d'ajouter toutes les adresses IP à l'en-tête X-Forwarded-For si c'est possible, alors nous pouvons voir toute la chaîne.

@PanJ hmm, et comment votre conteneur autonome nignx communique-t-il avec l'instance swarm, via le nom du service ou l'adresse IP ? Peut-être pouvez-vous partager la partie de configuration nginx où vous la transmettez à l'instance swarm.

Le conteneur autonome 80 , puis le proxy pour localhost:8181

server {
  listen 80 default_server;
  location / {
    proxy_set_header        Host $host;
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_pass          http://localhost:8181;
    proxy_read_timeout  90;
  }
}

Si vous devez effectuer une terminaison SSL, ajoutez un autre bloc de serveur qui écoute le port 443 , puis effectuez également la terminaison SSL et les proxys vers localhost:8181

Le nginx du mode Swarm publie 8181:80 et achemine vers un autre service en fonction de l'hôte de la demande.

server {
  listen 80;
  server_name your.domain.com;
  location / {
    proxy_pass          http://your-service:80;
    proxy_set_header Host $host;
    proxy_read_timeout  90;
  }
}

server {
  listen 80;
  server_name another.domain.com;
  location / {
    proxy_pass          http://another-service:80;
    proxy_set_header Host $host;
    proxy_read_timeout  90;
  }
}

Dans notre cas, notre API RateLimit et d'autres fonctions dépendent de l'adresse IP de l'utilisateur. Existe-t-il un moyen d'ignorer le problème en mode essaim?

J'ai également rencontré le problème en essayant d'exécuter logstash en mode essaim (pour collecter les messages syslog de divers hôtes). Le champ "hôte" de logstash apparaît toujours sous la forme 10.255.0.x, au lieu de l'adresse IP réelle de l'hôte qui se connecte. Cela le rend totalement inutilisable, car vous ne pouvez pas dire de quel hôte proviennent les messages de journal. Existe-t-il un moyen d'éviter de traduire l'IP source ?

+1 pour une solution à ce problème.

Sans la possibilité de récupérer l'adresse IP de l'utilisateur, nous ne pouvons pas utiliser des solutions de surveillance comme Prometheus.

Peut-être que les capacités IPVS du noyau Linux seraient utiles ici. Je suppose que le changement d'IP a lieu car les connexions sont proxy dans l'espace utilisateur. IPVS, d'autre part, peut rediriger et équilibrer la charge des demandes dans l'espace noyau sans changer l'adresse IP source. IPVS pourrait également être utile pour intégrer des fonctionnalités plus avancées, telles que différents algorithmes d'équilibrage de charge, des adresses IP flottantes et un routage direct.

Pour moi, il suffirait que je puisse découvrir d'une manière ou d'une autre la relation entre l'adresse IP virtuelle et l'adresse IP du serveur auquel appartient le point de terminaison. De cette façon, lorsque Prometheus envoie une alerte liée à une adresse IP virtuelle, je pourrais découvrir quel est le serveur concerné. Ce ne serait pas une bonne solution mais ce serait mieux que rien.

@vfarcic Je ne pense pas que cela soit possible avec la façon dont cela fonctionne maintenant. Toutes les connexions clientes proviennent de la même adresse IP, vous ne pouvez donc pas la reconduire. La seule façon dont cela fonctionnerait est que tout ce qui fait le proxy/nat des connexions enregistre un journal de connexion avec l'horodatage, l'adresse IP source et le port source. Même dans ce cas, cela ne serait pas très utile dans la plupart des cas d'utilisation où l'adresse IP source est nécessaire.

Je n'ai probablement pas bien expliqué le cas d'utilisation.

J'utilise Prometheus qui est configuré pour supprimer les exportateurs qui s'exécutent en tant que services globaux Swarm. Il utilise des tâches.pour obtenir les IP de toutes les répliques. Ainsi, il n'utilise pas le service mais les points de terminaison de réplica (pas d'équilibrage de charge). Ce dont j'aurais besoin, c'est de déterminer d'une manière ou d'une autre l'adresse IP du nœud d'où proviennent chacune de ces adresses IP de réplique.

Je viens de réaliser le "docker network inspecter" fournit des informations sur les conteneurs et les adresses IPv4 d'un seul nœud. Cela peut-il être étendu pour qu'il y ait des informations à l'échelle du cluster d'un réseau avec les nœuds ?

Quelque chose comme:

       "Containers": {
            "57bc4f3d826d4955deb32c3b71550473e55139a86bef7d5e584786a3a5fa6f37": {
                "Name": "cadvisor.0.8d1s6qb63xdir22xyhrcjhgsa",
                "EndpointID": "084a032fcd404ae1b51f33f07ffb2df9c1f9ec18276d2f414c2b453fc8e85576",
                "MacAddress": "02:42:0a:00:00:1e",
                "IPv4Address": "10.0.0.30/24",
                "IPv6Address": "",
                "Node": "swarm-4"
            },
...

Notez l'ajout du "Node".

Si de telles informations étaient disponibles pour l'ensemble du cluster, pas seulement un seul nœud avec l'ajout d'un argument --filter , j'aurais tout ce dont j'aurais besoin pour comprendre la relation entre une adresse IPv4 de conteneur et le nœud. Ce ne serait pas une bonne solution mais c'est quand même mieux que rien. À l'heure actuelle, lorsque Prometheus détecte un problème, je dois exécuter "docker network inspect" sur chaque nœud jusqu'à ce que je trouve l'emplacement de l'adresse.

Je suis d'accord avec @dack , étant donné que le réseau d'entrée utilise IPVS, nous devrions résoudre ce problème à l'aide d'IPVS afin que l'adresse IP source soit préservée et présentée au service correctement et de manière transparente.

La solution doit fonctionner au niveau IP afin que tout service qui n'est pas basé sur HTTP puisse toujours fonctionner correctement (ne peut pas compter sur les en-têtes http...).

Et je ne peux pas souligner à quel point c'est important, sans cela, il existe de nombreux services qui ne peuvent tout simplement pas fonctionner du tout en mode essaim.

@kobolog pourrait peut-être faire la lumière sur cette question étant donné son discours sur IPVS à DockerCon.

Je m'ajoute juste à la liste. J'utilise logstash pour accepter les messages syslog, et ils sont tous poussés dans Elasticsearch avec l'adresse IP de l'hôte définie sur 10.255.0.4, ce qui le rend inutilisable, et je vais devoir revenir à mon déploiement de logstash non conteneurisé s'il n'y a pas de solution à cela.

@mrjana pouvez-vous ajouter la suggestion que vous avez eue pour contourner ce problème ?

IPVS n'est pas un proxy inverse de l'espace utilisateur qui peut réparer les choses dans la couche HTTP. C'est la différence entre un proxy d'espace utilisateur comme HAProxy et celui-ci. Si vous souhaitez utiliser HAProxy, vous pouvez le faire en plaçant un HAProxy dans le cluster et en faisant en sorte que toutes vos instances de service et HAProxy participent au même réseau. De cette façon, HAProxy peut réparer HTTP header.x-forwarded-for . Ou si l'équilibreur de charge L7 est externe au cluster, vous pouvez utiliser la fonctionnalité à venir (en 1.13) pour un nouveau PublishMode appelé Host PublishMode qui exposera chacune des instances individuelles du service dans son propre port individuel et vous pouvez y faire pointer votre équilibreur de charge externe.

@mrjana L'idée d'utiliser IPVS (au lieu de ce que docker fait actuellement en mode essaim) serait d'éviter de traduire l'adresse IP source pour commencer. L'ajout d'un X-Forwarded-For peut aider pour certaines applications HTTP, mais cela ne sert à rien pour toutes les autres applications qui sont cassées par le comportement actuel.

@dack, je crois comprendre que le réseau d'entrée Docker utilise déjà IPVS.

Si vous souhaitez utiliser HAProxy, vous pouvez le faire en plaçant un HAProxy dans le cluster et en faisant en sorte que toutes vos instances de service et HAProxy participent au même réseau. De cette façon, HAProxy peut corriger l'en-tête HTTP.x-forwarded-for

Cela ne fonctionnerait pas non plus @mrjana , le seul moyen pour HAProxy d'obtenir l'adresse IP du client est de s'exécuter en dehors du réseau d'entrée à l'aide de docker run ou directement sur l'hôte, mais vous ne pouvez utiliser aucun de vos services car ils sont sur un réseau différent et vous ne pouvez pas y accéder.

En termes simples, à ma connaissance, il n'y a absolument aucun moyen de gérer cela dès que vous utilisez les services docker et le mode essaim.

Il serait intéressant que les auteurs du réseau d'entrée docker puissent se joindre à la discussion, car ils auraient probablement un aperçu de la façon dont IPVS est configuré / exploité sous le capot (il existe de nombreux modes pour IPVS) et comment nous pouvons y remédier le problème.

@tlvenn Savez-vous où cela se trouve dans le code source ? Je peux me tromper, mais je ne pense pas qu'il utilise IPVS sur la base de certaines choses que j'ai observées :

  • Le port source est traduit (toute la raison de ce problème). IPVS ne fait pas cela. Même en mode NAT, il ne traduit que l'adresse de destination. Vous devez utiliser la route par défaut ou le routage de stratégie pour renvoyer les paquets de retour à l'hôte IPVS.
  • Lorsqu'un port est publié en mode swarm, toutes les instances dockerd du swarm écoutent sur le port publié. Si IPVS était utilisé, cela se produirait dans l'espace du noyau et dockerd n'écouterait pas sur le port.

Salut @dack ,

De leur blog :

En interne, nous réalisons ce travail en utilisant Linux IPVS, un équilibreur de charge multi-protocole de couche 4 intégré au noyau Linux depuis plus de 15 ans. Avec les paquets de routage IPVS à l'intérieur du noyau, le maillage de routage de swarm offre un équilibrage de charge hautes performances tenant compte des conteneurs.

Le code source devrait résider dans le projet swarmkit si je ne me trompe pas.

Je me demande si @stevvooe peut nous aider à comprendre quel est le problème sous-jacent ici.

OK, j'ai parcouru brièvement le code et je pense que je le comprends un peu mieux maintenant. Il semble en effet utiliser IPVS comme indiqué dans le blog. SNAT se fait via une règle iptables configurée dans service_linux.go. Si je comprends bien, la logique derrière cela ressemblerait à ceci (en supposant que le nœud A reçoive un paquet client pour le service exécuté sur le nœud B):

  • Le nœud Swarm A reçoit le paquet client. IPVS/iptables traduit (src ip)->(node ​​a ip) et (dst ip)->(node ​​B ip)
  • Le paquet est transmis au nœud B
  • Le nœud B envoie sa réponse au nœud A (car c'est ce qu'il considère comme l'ip src)
  • Le nœud A traduit le src et le dst en valeurs d'origine et transmet la réponse au client

Je pense que le raisonnement derrière le SNAT est que la réponse doit passer par le même nœud que la demande d'origine (car c'est là que l'état NAT/IPVS est stocké). Comme les demandes peuvent passer par n'importe quel nœud, le SNAT est utilisé pour que le nœud de service sache par quel nœud renvoyer la demande. Dans une configuration IPVS avec un seul nœud d'équilibrage de charge, ce ne serait pas un problème.

Ainsi, la question est alors de savoir comment éviter le SNAT tout en permettant à tous les nœuds de gérer les demandes des clients entrants. Je ne sais pas exactement quelle est la meilleure approche. Il existe peut-être un moyen d'avoir une table d'état sur le nœud de service afin qu'il puisse utiliser le routage de stratégie pour diriger les réponses au lieu de s'appuyer sur SNAT. Ou peut-être qu'une sorte d'encapsulation pourrait aider (VXLAN ?). Ou, la méthode de routage direct d'IPVS pourrait être utilisée. Cela permettrait au nœud de service de répondre directement au client (plutôt que via le nœud qui a reçu la demande d'origine) et permettrait d'ajouter de nouvelles adresses IP flottantes pour les services. Cependant, cela signifierait également que le service ne peut être contacté que via l'adresse IP flottante et non les adresses IP des nœuds individuels (je ne sais pas si cela pose un problème pour tous les cas d'utilisation).

Découverte assez intéressante @dack !

Espérons qu'une solution sera trouvée pour ignorer ce SNAT tous ensemble.

En attendant, il existe peut-être une solution de contournement qui a été validée il n'y a pas longtemps, qui introduit une publication de port au niveau de l'hôte avec PublishMode , contournant efficacement le réseau d'entrée.

https://github.com/docker/swarmkit/pull/1645

Hé, merci pour la grande quantité de commentaires - nous examinerons ce problème en profondeur après le week-end.

Quelques infos en attendant :

@tlvenn : @mrjana est l'auteur principal de la fonctionnalité de réseau d'entrée. La source réside principalement dans docker/libnetwork, certains dans SwarmKit

@dack : il est en effet soutenu par IPVS

@tlvenn pour autant que je sache, Docker Swarm utilise le masquage, car c'est le moyen le plus simple et garanti de fonctionner dans la plupart des configurations. De plus, c'est le seul mode qui permet réellement de masquer les ports aussi [re: @dack], ce qui est pratique. En théorie, ce problème pourrait être résolu en utilisant le mode d'encapsulation IPIP - le flux de paquets sera alors comme ceci :

  • Un paquet arrive au serveur de passerelle - dans notre cas n'importe quel nœud de l'essaim - et IPVS sur ce nœud détermine qu'il s'agit en fait d'un paquet pour un service virtuel, en fonction de son adresse IP et de son port de destination.
  • Le paquet est encapsulé dans un autre paquet IP et envoyé au serveur réel qui a été choisi en fonction de l'algorithme d'équilibrage de charge.
  • Le serveur réel reçoit le paquet englobant, le désencapsule et voit l'IP du client réel comme source et l' IP du service virtuel comme destination. Tous les serveurs réels sont censés avoir un alias d'interface non ARPable avec l'IP du service virtuel, de sorte qu'ils supposeraient que ce paquet leur est réellement destiné.
  • Le serveur réel traite le paquet et renvoie la réponse directement au client. L'IP source dans ce cas sera l' IP du service virtuel , donc aucune réponse martienne n'est impliquée, ce qui est bien.

Il y a bien sûr de nombreuses mises en garde et des choses qui peuvent mal tourner, mais généralement c'est possible et le mode IPIP est largement utilisé en production.

En espérant qu'une solution puisse être trouvée rapidement pour cela, car la fixation IP et d'autres contrôles de sécurité doivent pouvoir recevoir l'adresse IP externe correcte.

En train de regarder. Notre produit exploite les informations IP source pour la sécurité et l'analyse.

@aluzzardi une mise à jour pour nous ?

bump, nous en avons besoin pour travailler pour un très grand projet que nous commençons au début de l'année prochaine.

En examinant le flux, il semble fonctionner actuellement comme ceci (dans cet exemple, le nœud A reçoit le trafic entrant et le nœud B exécute le conteneur de service) :

  • le nœud A exécute DNAT pour diriger le paquet dans l'espace de noms réseau ingress_sbox (/var/run/docker/netns/ingress_sbox)
  • ingress_sbox sur le nœud A exécute IPVS en mode NAT, qui exécute DNAT pour diriger le paquet vers le conteneur sur le nœud B (via le réseau superposé d'entrée) et également SNAT pour changer l'adresse IP source vers l'adresse IP du réseau superposé d'entrée du nœud A
  • le paquet est acheminé via la superposition vers le serveur réel
  • les paquets de retour suivent le même chemin en sens inverse, réécrivant les adresses source/dest aux valeurs d'origine

Je pense que le SNAT pourrait être évité avec quelque chose comme ceci :

  • le nœud A passe le paquet dans ingress_sbox sans aucun NAT (iptables/policy routing ?)
  • le nœud A ingress_sbox exécute IPVS en mode de routage direct, qui envoie le paquet au nœud B via le réseau superposé d'entrée
  • le conteneur sur le nœud B reçoit le paquet non modifié (le conteneur doit accepter les paquets pour toutes les adresses IP publiques, mais ne pas envoyer d'ARP pour elles. Il existe plusieurs façons de le faire, voir la documentation IPVS).
  • les paquets de retour sont envoyés directement du nœud B au client (n'a pas besoin de repasser par le réseau superposé ou le nœud A)

En prime, aucun état NAT n'a besoin d'être stocké et le trafic réseau de superposition est réduit.

@aluzzardi @mrjana Une mise à jour à ce sujet s'il vous plaît ? Un petit retour de Docker serait très apprécié.

En train de regarder. sans information IP source, la plupart de nos services ne peuvent pas fonctionner comme prévu

Comment est-ce arrivé ?
unassign_bug

@tlvenn semble être un bug dans Github ?

@PanJ @tlvenn @vfarcic @dack et autres, PTAL #27917. Nous avons introduit la possibilité d'activer le mode de publication de service = host qui fournira un moyen pour le service de contourner IPVS et de ramener docker run -p comportement similaire à

Veuillez essayer 1.13.0-rc2 et fournir des commentaires.

tu es assez bizarre

En ce qui concerne le mode de publication, j'avais déjà lié cela à partir du kit swarm ci-dessus, cela pourrait être une solution de contournement, mais j'espère vraiment qu'une solution appropriée sera fournie avec Docker 1.13 pour résoudre ce problème pour de bon.

Ce problème pourrait très bien être classé comme un bogue car la préservation de l'adresse IP source est le comportement auquel nous nous attendons en tant qu'utilisateurs et c'est une limitation très sérieuse des services Docker en ce moment.

Je crois que @kobolog et @dack ont trouvé des pistes potentielles sur la façon de résoudre ce problème et cela fait presque 2 semaines sans suivi de ceux de Docker.

Pourrions-nous avoir une certaine visibilité sur qui étudie ce problème chez Docker et une mise à jour du statut ? Merci d'avance.

À part #27917, il n'y a pas d'autre solution pour la 1.13. La fonctionnalité de retour direct doit être analysée pour divers cas d'utilisation et ne doit pas être prise à la légère pour être considérée comme une correction de bogue. Nous pouvons examiner cela pour 1.14. Mais, cela relève également de la catégorie du comportement LB configurable, qui inclut l'algorithme (rr contre 10 autres méthodes), le chemin de données (LVS-DR, LVS-NAT & LVS-TUN). Si quelqu'un est prêt à contribuer à cela, veuillez pousser un PR et nous pouvons le faire bouger.

Assez juste, je suppose que @mavenugo étant donné que nous avons maintenant une alternative.

À tout le moins, pouvons-nous modifier le document pour 1.13 afin qu'il indique clairement que lors de l'utilisation des services Docker avec le mode de publication d'entrée par défaut, l'adresse IP source n'est pas conservée et suggère d'utiliser le mode hôte si cela est une exigence pour l'exécution du service ?

Je pense que cela aidera les personnes qui migrent vers les services à ne pas être brûlées par ce comportement inattendu.

Bien sûr, une mise à jour de la documentation pour indiquer ce comportement et la solution de contournement consistant à utiliser la publication mode=host sera utile pour de tels cas d'utilisation qui échouent en mode LVS-NAT.

Juste vérifier s'il n'y a pas eu de nouveaux développements pour comprendre cette vraie chose ? C'est certainement une énorme limitation pour nous aussi

Une solution est-elle sur la feuille de route pour docker 1.14 ? Nous avons pris du retard dans le déploiement de nos solutions à l'aide de docker en partie à cause de ce problème.

J'adorerais voir un en-tête personnalisé ajouté à la requête http/https qui préserve l'adresse IP du client. Cela devrait être possible, non ? Cela ne me dérange pas lorsque X_Forwarded_for est écrasé, je veux juste avoir un champ personnalisé qui n'est défini que la toute première fois que la demande entre dans l'essaim.

J'adorerais voir un en-tête personnalisé ajouté à la requête http/https qui préserve l'adresse IP du client. Cela devrait être possible, non ? Cela ne me dérange pas lorsque X_Forwarded_for est écrasé, je veux juste avoir un champ personnalisé qui n'est défini que la toute première fois que la demande entre dans l'essaim.

L'équilibrage de charge est effectué à L3/4. L'ajout d'un en-tête http n'est pas possible.

Un correctif impliquera la suppression de la réécriture de l'adresse source.

@mavenugo J'ai mis à jour le docker 1.13 aujourd'hui et j'ai utilisé mode=host sur mon service proxy. Actuellement, cela fonctionne, l'IP du client est conservée, mais j'espère une meilleure solution :) Merci pour votre travail !

Désolé pour le double post...
Comment puis-je utiliser un fichier de pile (yml v3) pour obtenir le même comportement que lorsque j'utiliserais --publish mode=host,target=80,published=80 via le service docker create ?

J'ai essayé

...
services:
  proxy:
    image: vfarcic/docker-flow-proxy:1.166
    ports:
      - "80:80/host"
      - "443:443/host" 
...

mais cela ne fonctionne pas (utilisé le même modèle que dans https://docs.docker.com/docker-cloud/apps/stack-yaml-reference/#/ports)

Comment puis-je utiliser un fichier de pile (yml v3) pour obtenir le même comportement que lorsque j'utiliserais --publish mode=host,target=80,published=80 via docker service create ?

@hamburml - gardez un œil sur https://github.com/docker/docker/issues/30447 c'est un problème/fonction ouvert.

Malheureusement, je ne peux pas utiliser mode=host comme solution de contournement car j'ai besoin de mon service pour communiquer avec le réseau swarm et être également à l'écoute sur tous les nœuds, pas seulement sur l'interface hôte...

@ tkeeler33 Je pense que vous devriez pouvoir déployer le service en tant que service global (qui déploie une instance sur chaque nœud de l'essaim) et le connecter à un réseau d'essaim pour communiquer avec d'autres services de l'essaim

@thaJeztah - Oui, mais je ne peux pas connecter un conteneur à la fois à un réseau de superposition/essaim et à l'hôte mode=host en même temps. C'est ma plus grande limitation en ce moment.

@ tkeeler33 semble fonctionner pour moi;

$ docker network create -d overlay swarm-net

$ docker service create \
  --name web \
  --publish mode=host,published=80,target=80 \
  --network swarm-net \
  --mode=global \
  nginx:alpine

$ docker service create --name something --network swarm-net nginx:alpine

Testez si le service web est capable de se connecter avec le service something sur le même réseau ;

docker exec -it web.xczrerg6yca1f8ruext0br2ow.kv8iqp0wdzj3bw7325j9lw8qe sh -c 'ping -c3 -w1 something'
PING something (10.0.0.4): 56 data bytes
64 bytes from 10.0.0.4: seq=0 ttl=64 time=0.251 ms

--- something ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.251/0.251/0.251 ms

@thaJeztah - Merci ! Après avoir creusé plus profondément, j'ai réalisé que mon problème était que j'avais créé mon réseau Docker à l'aide de l'option --opt encrypted , ce qui faisait échouer les connexions du conteneur à partir de l'hôte. Une fois que j'ai essayé vos étapes, j'ai pu affiner rapidement la cause première. Cette option peut être une bonne solution de contournement provisoire, j'ai juste besoin de comprendre toutes les implications en matière de sécurité.

Appréciez grandement l'information!

@tkeeler33 --opt encrypted ne devrait pas affecter le mappage hôte-port. Le seul objectif de l'option cryptée est de crypter le trafic du tunnel vxlan entre les nœuds. De la documentation : "Si vous envisagez de créer un réseau superposé avec cryptage (--opt crypté), vous devrez également vous assurer que le trafic du protocole 50 (ESP) est autorisé." Pouvez-vous vérifier vos configurations pour vous assurer que l'ESP est autorisé ?
De plus, l'option --opt encrypted est purement un cryptage de plan de données. Tout le trafic du plan de contrôle (échanges de routage, distribution Service Discovery, etc...) est crypté par défaut même sans l'option.

@mavenugo Vous avez raison. Lorsque j'ai créé un nouveau réseau avec --opt encrypted cela a bien fonctionné. Lorsque j'ai comparé le réseau nouvellement créé avec mon réseau existant, j'ai remarqué que "Internal": true était défini. C'était probablement le problème et c'était une erreur lors de la création initiale du réseau... Merci pour votre aide et vos éclaircissements, ça a été une longue journée...

@dack @kobolog Dans les déploiements typiques des

@thaJeztah Je pense que nous devrions clarifier cela dans la documentation, suggérer d'utiliser le mod hôte si l'adresse IP du client doit être préservée et fermer ce problème.

@sanimej Je ne vois toujours pas pourquoi il est impossible de le faire sans NAT. Ne pourrions-nous pas simplement avoir la possibilité d'utiliser, par exemple, le flux LVS-DR normal ? Docker ajoute le vip non-arp aux nœuds appropriés, LVS dirige les paquets entrants vers les nœuds et les paquets sortants retournent directement. Pourquoi est-il important que le paquet entrant puisse toucher n'importe quel hôte ? Ce n'est pas différent du LVS standard avec plusieurs serveurs frontaux et plusieurs serveurs principaux.

@thaJeztah merci pour la solution de contournement :)
Si vous déployez votre proxy avec compose version 3, la nouvelle syntaxe de publication n'est pas prise en charge, nous pouvons donc corriger le service déployé à l'aide de cette commande (remplacez nginx_proxy par le nom du service)

docker service update nginx_proxy \
    --publish-rm 80 \
    --publish-add "mode=host,published=80,target=80" \
    --publish-rm 443 \
    --publish-add "mode=host,published=443,target=443"

@dack Dans le flux LVS-DR normal, l'adresse IP de destination sera le service VIP. Ainsi, le LB peut envoyer le paquet au backend sans aucun changement d'IP de destination. Ce n'est pas le cas avec le maillage de routage car l'IP de destination du paquet entrant sera l'une des IP de l'hôte.

@sanimej des retours sur la proposition ci-dessus d'utiliser le mode d'encapsulation IPIP pour résoudre ce problème ?

@tlvenn Le tunnel LVS-IP fonctionne de manière très similaire à LVS-DR, sauf que le backend obtient le paquet via un tunnel IP dans IP plutôt qu'une réécriture mac. Il a donc le même problème pour le cas d'utilisation du maillage de routage.

De la proposition à laquelle vous avez fait référence..
The real server receives the enclosing packet, decapsulates it and sees real client IP as source and virtual service IP as destination.

L'IP de destination du paquet serait l'IP de l'hôte auquel le client a envoyé le paquet et non le VIP. S'il n'est pas réécrit, le serveur réel le supprimera après avoir supprimé l'en-tête IP externe. Si l'adresse IP de destination est réécrite, la réponse du serveur réel au client aura une adresse IP source incorrecte, ce qui entraînera un échec de la connexion.

Merci pour la précision @sanimej. Pourriez-vous peut-être implémenter le protocole PROXY ? Cela ne fournirait pas une solution transparente, mais au moins cela offrirait au service une solution pour résoudre l'IP de l'utilisateur.

Il existe un moyen simple d'obtenir la préservation de l'adresse IP source en divisant la plage de ports source en blocs et en affectant un bloc à chaque hôte du cluster. Ensuite, il est possible de faire une approche hybride NAT + DR, où l'hôte d'entrée fait le SNAT habituel et envoie le paquet à un vrai serveur. Sur l'hôte sur lequel le serveur réel s'exécute, en fonction de l'adresse IP source, effectuez un SNAT pour remplacer le port source par un port dans la plage attribuée à l'hôte d'entrée. Ensuite, sur le paquet de retour du conteneur, faites correspondre la plage de ports source (et le port cible) et remplacez l'adresse IP source par celle de l'hôte d'entrée.

Techniquement, cela fonctionnerait, mais peu pratique et fragile dans les déploiements réels où les membres du cluster sont ajoutés et supprimés rapidement. Cela réduit également considérablement l'espace du port.

L'approche NAT + DR que j'ai mentionnée ne fonctionnerait pas car l'adresse IP source ne peut pas être modifiée dans l'hôte d'entrée. En changeant uniquement le port source en un dans la plage pour cet hôte particulier et en utilisant la politique de routage de l'hôte principal pour renvoyer le paquet vers l'hôte d'entrée peut être une option. Cela a encore d'autres problèmes que j'ai mentionnés plus tôt.

@thaJeztah
Existe-t-il actuellement une solution de contournement pour transférer une adresse IP réelle du conteneur Nginx au conteneur Web ?
J'ai un conteneur Nginx exécuté en mode global et publié sur host , donc le conteneur Nginx obtient une adresse IP correcte. Les deux conteneurs se voient bien, cependant, le conteneur Web obtient l'adresse IP du conteneur Nginx, pas celle du client.
Nginx est un proxy inverse pour le Web, et le Web exécute uwsgi sur le port 8000 :

server {
    resolver 127.0.0.11;
    set $web_upstream http://web:8000;

    listen 80;
    server_name domain.com;
    location / {
        proxy_pass $web_upstream;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        proxy_redirect off;
        proxy_buffering off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

@lpakula Veuillez vérifier ma réponse ci-dessus + cette configuration nginx fonctionnelle

@pi0 Merci pour la réponse

J'utilise la configuration nginx à partir du lien, mais l'adresse IP est toujours fausse, je dois avoir quelque chose qui manque dans ma configuration

J'ai un cluster swarm docker (

    docker service create --name nginx --network overlay_network --mode=global \
        --publish mode=host,published=80,target=80 \
        --publish mode=host,published=443,target=443 \
        nginx:1.11.10

    docker service create --name web --network overlay_network \
        --replicas 1 \
        web:newest

Le conteneur Nginx utilise le dernier conteneur officiel https://hub.docker.com/_/nginx/
Le conteneur Web exécute le serveur uwsgi sur le port 8000

J'utilise le nginx.conf global conf.d/default.conf ressemble à ceci :

   server {
       resolver 127.0.0.11;
       set $web_upstream http://web:8000;

       listen 80;
       server_name domain.com;
       location / {
        proxy_pass $web_upstream;
      }
  }

Et puis les journaux du conteneur nginx :

  194.168.X.X - - [17/Mar/2017:12:25:08 +0000] "GET / HTTP/1.1" 200

Journaux de conteneur Web :

  10.0.0.47 - - [17/Mar/2017 12:25:08] "GET / HTTP/1.1" 200 -

Qu'est-ce qui manque là-bas ?

L'adresse IP sera toujours fausse. Mais il ajoutera des en-têtes HTTP qui
contiennent une adresse IP réelle. Vous devez configurer votre serveur web de votre choix
faire confiance au proxy (utiliser l'en-tête au lieu de l'IP source)
Le ven 17 mars 2560 à 19h36 Lukasz Pakula [email protected]
a écrit:

@pi0 https://github.com/pi0 Merci pour la réponse

J'utilise la configuration nginx à partir du lien, mais l'adresse IP est toujours
faux, je dois avoir quelque chose qui manque dans ma configuration

J'ai un cluster d'essaim docker ( 17.03.0-ce ) avec un réseau superposé et deux
prestations de service

docker service create --name nginx --network overlay_network --mode=global \
    --publish mode=host,published=80,target=80 \
    --publish mode=host,published=443,target=443 \
    nginx:1.11.10

docker service create --name web --network overlay_network \
    --replicas 1 \
    web:newest

Le conteneur Nginx utilise le dernier conteneur officiel
https://hub.docker.com/_/nginx/ http://url
Le conteneur Web exécute le serveur uwsgi sur le port 8000

J'utilise global nginx.conf à partir du lien et conf.d/default.conf ressemble
comme suit:

serveur {
résolveur 127.0.0.11 ;
définir $web_upstream http://web :8000 ;

   listen 80;
   server_name domain.com;
   location / {
    proxy_pass $web_upstream;
  }

}

Et puis les journaux du conteneur nginx :

194.168.XX - - [17/Mar/2017:12:25:08 +0000] "GET / HTTP/1.1" 200

Journaux de conteneur Web :

10.0.0.47 - - [17/Mar/2017 12:25:08] "GET / HTTP/1.1" 200 -

Qu'est-ce qui manque là-bas ?

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/docker/docker/issues/25526#issuecomment-287342795 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/ABtu97EFaCmLwAZiOrYT4nXi4oXPCbLQks5rmn43gaJpZM4Jf2WK
.

>

PanJ,
Panjamapong Sermsawatsri
Tél. (+66)869761168

@lpakula Ah, il y a une autre chose que votre image web:newest devrait également honorer l'en-tête X-Real-IP . nginx ne changera pas automatiquement l'adresse IP des expéditeurs, il envoie simplement un en-tête d'indice.

@pi0 @PanJ
C'est logique, merci les gars !

Liez le port en utilisant le mode hôte.

nginx prend en charge la transparence IP à l'aide du module de noyau TPROXY .

@stevvooe Docker peut-il aussi faire quelque chose comme ça ?

nginx prend en charge la transparence IP à l'aide du module de noyau TPROXY.
@stevvooe Docker peut-il aussi faire quelque chose comme ça ?

Peu probable, car l'entrée doit être suivie à travers les nœuds. Je laisse @sanimej ou @mavenugo.

Swarm peut-il fournir l'API REST pour obtenir l'adresse IP du client ?

@tonysongtl qui n'est pas lié à ce problème

Un autre élément à prendre en compte est la manière dont votre trafic est acheminé vers vos nœuds dans une configuration hautement disponible. Un nœud doit pouvoir s'arrêter sans créer d'erreurs pour les clients. La recommandation actuelle est d'utiliser un équilibreur de charge externe (ELB, F5, etc.) et d'équilibrer la charge au niveau de la couche 4 vers chaque nœud Swarm, avec une simple vérification de l'état de la couche 4. Je crois que F5 utilise SNAT, donc le meilleur des cas dans cette configuration est de capturer l'adresse IP unique de votre F5, et non la véritable IP du client.

Les références:
https://docs.docker.com/engine/swarm/ingress/#configure -an-external-load-balancer
https://success.docker.com/Architecture/Docker_Reference_Architecture%3A_Docker_EE_Best_Practices_and_Design_Considerations
https://success.docker.com/Architecture/Docker_Reference_Architecture%3A_Universal_Control_Plane_2.0_Service_Discovery_and_Load_Balancing

reflétant le commentaire ci -

Calico a également le mode ipip - https://docs.projectcalico.org/v2.2/usage/configuration/ip-in-ip - qui est l'une des raisons pour lesquelles github l'utilise. https://githubengineering.com/kubernetes-at-github/

Salut.

Dans un souci de compréhension et d'exhaustivité, permettez-moi de résumer et veuillez me corriger si je me trompe :

Le problème principal est que les conteneurs ne reçoivent pas l'adresse IP src d'origine mais swarm VIP. J'ai répliqué ce problème avec le scénario suivant :

create docker swarm
docker service create --name web --publish 80:80 nginx
access.log source IP is 10.255.0.7 instead of client's browser IP

Il semble:

Lorsque les services au sein de swarm utilisent le maillage (par défaut), swarm effectue-t-il un NAT pour s'assurer que le trafic de la même origine est toujours envoyé au même service d'exécution d'hôte ?
Par conséquent, il perd l'adresse IP src d'origine et la remplace par le service VIP de swarm.

Semble @kobolog https://github.com/moby/moby/issues/25526#issuecomment -258660348 et @dack https://github.com/moby/moby/issues/25526#issuecomment -260813865 propositions ont été réfutées par @sanimej https://github.com/moby/moby/issues/25526#issuecomment -280722179 https://github.com/moby/moby/issues/25526#issuecomment -281289906 mais, TBH, ses arguments ne sont pas tout à fait clairs pour moi encore, je ne comprends pas non plus pourquoi le fil n'a pas été fermé si cela est définitivement impossible.

@sanimej cela ne fonctionnerait-il pas ? :

  1. Swarm reçoit un message avec src-IP=A et destination="my-service-virtual-address"
  2. Le package est envoyé à un nœud d'essaim exécutant ce service, encapsulant le message d'origine.
  3. Le nœud passe à la tâche en changeant la destination en conteneur-exécutant-ce-service-IP
    Swarm et les nœuds pourraient maintenir des tables pour s'assurer que le trafic provenant de la même origine est acheminé vers le même nœud dans la mesure du possible.

Une option permettant d'activer le "reverse proxy au lieu de NAT" pour des services spécifiques ne résoudrait-elle pas tous ces problèmes en satisfaisant tout le monde ?

D'autre part, IIUC, la seule option qui reste est d'utiliser https://docs.docker.com/engine/swarm/services/#publish -a-services-ports-directly-on-the-swarm-node, qui -encore une fois IIUC- semble être comme ne pas utiliser de maillage du tout, donc je ne vois pas les avantages d'utiliser le mode essaim (vs composer). En fait, cela ressemble à un essaim pré-1.12, nécessitant _Consul_ et ainsi de suite.

Merci pour votre aide et votre patience.
Salutations

@sanimej
Encore plus... pourquoi Docker ne fait pas seulement un NAT de redirection de port (en changeant uniquement l'IP/le port de destination) ?

  1. Swarm reçoit le message "de A à myservice"
  2. Swarm transmet le message à l'hôte exécutant ce service, en définissant dest=node1
  3. Node1 reçoit le message "de A à node1" et transmet le paramètre dest=container1
  4. Container1 reçoit le message "de A à container1"
  5. Pour répondre, le conteneur utilise la route de passerelle par défaut

J'aimerais juste intervenir ; bien que je comprenne qu'il n'y a pas de moyen facile de le faire, le fait de ne pas conserver l'adresse IP d'origine d'une manière ou d'une autre entrave gravement un certain nombre de cas d'utilisation d'applications. En voici quelques-uns auxquels je peux penser par cœur :

  • Pouvoir disposer de métriques détaillant l'origine de vos utilisateurs est vital pour l'ingénierie de réseau/service.

  • Dans de nombreuses applications de sécurité, vous devez avoir accès à l'adresse IP d'origine afin de permettre une liste noire dynamique basée sur un abus de service.

  • Les services de localisation doivent souvent pouvoir accéder à l'adresse IP afin de localiser l'emplacement général de l'utilisateur lorsque d'autres méthodes échouent.

D'après ma lecture de ce fil de discussion, il ne semble pas que les solutions de contournement données fonctionnent très bien lorsque vous souhaitez disposer de services évolutifs au sein d'un Docker Swarm. Se limiter à une instance par nœud de travail réduit considérablement la flexibilité de l'offre. De plus, maintenir une approche hybride consistant à avoir un LB/Proxy à la périphérie fonctionnant en tant que conteneur non orchestré par Swarm avant de l'alimenter dans des conteneurs orchestrés par Swarm semble comme remonter dans le temps. Pourquoi l'utilisateur doit-il maintenir 2 paradigmes différents pour l'orchestration des services ? Qu'en est-il de la possibilité de mettre à l'échelle dynamiquement le LB/Proxy à la périphérie ? Cela devrait être fait manuellement, non?

L'équipe Docker pourrait-elle peut-être tenir compte de ces commentaires et voir s'il existe un moyen d'introduire cette fonctionnalité, tout en maintenant la qualité et la flexibilité présentes dans l'écosystème Docker ?

Autre aparté, je suis actuellement touché par cela maintenant. J'ai une application Web qui transmet les demandes autorisées/authentifiées à un serveur Web en aval. Nos techniciens de service doivent être en mesure de vérifier si les gens ont atteint le serveur en aval, pour lequel ils aiment utiliser les journaux d'accès Web. Dans le scénario actuel, il n'y a aucun moyen pour moi de fournir cette fonctionnalité car mon serveur proxy ne voit jamais l'adresse IP d'origine. Je veux que mon application soit facilement évolutive, et il ne semble pas que je puisse le faire avec les solutions de contournement présentées, du moins pas sans lancer de nouvelles machines virtuelles pour chaque instance mise à l'échelle.

@Jitsusama Kubernetes pourrait-il résoudre votre problème ?

@thaJeztah existe-t-il un moyen de contourner l'utilisation de docker-compose?

J'ai essayé

`services:
  math:
    build: ./math
    restart: always
    ports:
    - target: 12555
      published: 12555
      mode: host

Mais il semble prendre 172.xx1 comme IP source

@trajano , je n'en ai aucune idée. Kubernetes parvient-il d'une manière ou d'une autre à contourner ce problème ?

@Jitsusama
Oui, ils ont une documentation faisant référence à la façon dont ils préservent l'IP source . C'est fonctionnel, mais pas si joli si vous n'utilisez pas d'équilibreur de charge car le paquet est abandonné sur les nœuds sans ces points de terminaison. Si vous envisagez d'utiliser Rancher comme équilibreur de charge auto-hébergé, il ne le prend malheureusement

@trajano

Mais il semble prendre 172.xx1 comme IP source

Si vous accédez à votre application localement, cette IP doit être correcte (si vous utilisez swarm) car le docker_gwbridge est l'interface qui interagit avec votre conteneur proxy. Vous pouvez essayer d'accéder à l'application depuis une autre machine de votre réseau IP pour voir si elle capte la bonne adresse.

Quant à la solution de contournement de composition, elle est possible. Ici, j'utilise l'image jwilder/nginx-proxy comme proxy inverse frontend (pour simplifier les concepts) avec une image de construction officielle de nginx comme service backend. Je déploie la pile en Docker Swarm Mode :

version: '3.3'

services:

  nginx-proxy:
    image: 'jwilder/nginx-proxy:alpine'
    deploy:
      mode: global
    ports:
      - target: 80
        published: 80
        protocol: tcp
        mode: host
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro

  nginx:
    image: 'nginx:1.13.5-alpine'
    deploy:
      replicas: 3
    ports:
      - 80
      - 443
    environment:
      - VIRTUAL_HOST=website.local
$ echo '127.0.0.1 website.local' | sudo tee -a /etc/hosts
$ docker stack deploy --compose-file docker-compose.yml website

Cela créera un réseau website_default pour la pile. Mon point de terminaison est défini dans la variable d'environnement VIRTUAL_HOST et accéder à http://website.local me donne :

website_nginx-proxy.0.ny152x5l9sh7<strong i="30">@Sherry</strong>    | nginx.1    | website.local 172.18.0.1 - - [08/Sep/2017:21:33:36 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"
website_nginx.1.vskh5941kgkb<strong i="33">@Sherry</strong>    | 10.0.1.3 - - [08/Sep/2017:21:33:36 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36" "172.18.0.1"

Notez que la fin de l'en-tête pour website_nginx.1.vskh5941kgkb a un indice de l'IP d'origine ( 172.18.0.1 ). X-Forwarded-For et X-Real-IP sont définis dans le nginx.tmpl de jwilder/nginx-proxy par défaut.

Pour le port 443 , je n'ai pas pu ajouter les deux ports dans le fichier docker-compose, j'utilise donc simplement :

docker service update website_nginx-proxy \
    --publish-rm 80 \
    --publish-add "mode=host,published=80,target=80" \
    --publish-rm 443 \
    --publish-add "mode=host,published=443,target=443" \
    --network-add "<network>"

tout en ajoutant également des réseaux que je souhaite inverser avec des applications contenant la variable d'environnement VIRTUAL_HOST . Des options plus granulaires sont possibles dans la documentation de jwilder/nginx-proxy , ou vous pouvez créer votre propre configuration.

Les contrôleurs d'entrée sur Kubernetes font essentiellement la même chose, car les graphiques d'entrée (généralement) prennent en charge X-Forwarded-For et X-Real-IP avec un peu plus de flexibilité avec le choix et le type d'entrées ainsi que leurs réplicas de déploiement.

La documentation de kubernetes n'est donc pas complète. Une autre façon qui est d'être
assez couramment est en fait le protocole d'entrée + proxy.

https://www.haproxy.com/blog/haproxy/proxy-protocol/

Le protocole proxy est un protocole largement accepté qui préserve la source
informations. Haproxy est livré avec une prise en charge intégrée du protocole proxy. Nginx
peut lire mais pas injecter le protocole proxy.

Une fois le protocole proxy configuré, vous pouvez accéder à ces informations à partir de n'importe quel
services en aval comme
https://github.com/nginxinc/kubernetes-ingress/blob/master/examples/proxy-protocol/README.md

Même openshift exploite cela pour les informations IP source
https://docs.openshift.org/latest/install_config/router/proxy_protocol.html

Il s'agit de la dernière entrée haproxy pour k8s qui injecte le protocole proxy.

À mon humble avis, la façon de le faire dans swarm est de rendre l'entrée capable de lire le proxy
protocole (au cas où il reçoit du trafic d'un LB en amont qui a
protocole proxy déjà injecté) ainsi que le protocole proxy d'injection
informations (au cas où tout le trafic atteint l'entrée en premier).

Je ne suis pas en faveur de procéder autrement, surtout lorsqu'il y a un
norme généralement acceptée pour ce faire.

Traefik a ajouté le support proxy_protocol il y a quelques semaines et est disponible à partir de la v1.4.0-rc1.

Cela doit être fait au niveau de l'entrée de l'essaim de docker. Si l'entrée
n'injecte pas de données de protocole proxy, aucun des services en aval
(y compris traefix, nginx, etc.) pourra le lire.

Le 10-Sep-2017 21:42, "monotykamary" [email protected] a écrit :

Traefik a ajouté le support proxy_protocol
https://github.com/containous/traefik/pull/2004 il y a quelques semaines et est
disponible à partir de la v1.4.0-rc1.

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-328352805 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsU3jj5dJcpMDysjIyGQK7SGx8GwWbks5shApqgaJpZM4Jf2WK
.

Je suis également confus sur la relation de ce bogue avec infrakit. par exemple https://github.com/docker/infrakit/pull/601 quelqu'un peut-il commenter la direction que va prendre l'essaim de docker ?

L'essaim sera-t-il intégré à infrakit ? Je suis particulièrement intéressé par le côté entrée.

Nous sommes également confrontés à ce problème. Nous voulons connaître l'adresse IP du client et l'adresse IP demandée pour les connexions entrantes. Par exemple, si l'utilisateur effectue une connexion TCP brute à notre serveur, nous voulons savoir quelle est son adresse IP et à quelle adresse IP sur notre machine il s'est connecté.

@blazedd Comme commenté précédemment et dans d'autres fils de discussion, cela est en fait possible en utilisant publishMode. c'est-à-dire que les services ne sont pas gérés par le réseau maillé.

IIUC, des progrès sont en cours pour améliorer la façon dont l'entrée gère cela, mais c'est en fait la seule solution.

Nous avons déployé notre service nginx en utilisant publishmode et mode:global , pour éviter la configuration LB externe

@mostolog Merci pour votre réponse. Juste quelques remarques :

  1. publishMode ne résout pas le problème du tout. La connexion socket entrante se résout toujours au réseau local configuré par swarm. Au moins lorsque vous utilisez la liste des ports mode: host
  2. nginx n'est pas vraiment une bonne solution. Notre application est basée sur TCP, mais n'est pas un serveur Web. Il n'y a pas d'en-têtes que nous pourrons utiliser sans les coder manuellement.
  3. Si j'utilise docker run --net=host ... , tout fonctionne bien.
  4. La seule solution que j'ai vue qui fonctionne jusqu'à présent est d'utiliser : https://github.com/moby/moby/issues/25873#issuecomment -319109840

@blazedd Dans notre pile, nous avons :

    ports:
      - target: 80
        published: 80
        protocol: tcp
        mode: host

et donc, je parierais que nous obtenons de vraies adresses IP sur nos journaux.

@mostolog Cela ne fonctionne pas sur Windows au moins. Je reçois toujours l'adresse 172.0.0.x comme source.

@mostolog mode: host n'expose pas votre conteneur au réseau hôte. Il supprime le conteneur du réseau d'entrée, c'est ainsi que Docker fonctionne normalement lors de l'exécution d'un conteneur. Cela répliquerait le --publish 8080:8080 utilisé dans une commande d'exécution de docker. Si nginx obtient de vraies ips, ce n'est pas le résultat de la connexion directe du socket à ces ips. Pour tester cela, vous devriez sérieusement envisager d'utiliser une implémentation TCP brute ou un serveur HTTP, sans framework, et vérifier l'adresse signalée.

Pourquoi ne pas utiliser le réseau de routage IPVS vers le conteneur directement ? liez toutes les ips de l'interface de superposition du nœud swarm en tant qu'ips virtuelles, utilisez ip rule from xxx table xxx pour créer plusieurs passerelles, puis les nœuds swarm peuvent acheminer le client directement vers le conteneur (DNAT), sans aucun démon proxy réseau en espace utilisateur (dockerd)

@blazedd L' avez-vous essayé? J'obtiens des adresses IP externes en suivant l'exemple de

Je me heurte à nouveau à ce problème.

Ma configuration est la suivante :

  • équilibreur de charge ipvs en mode DR (externe à l'essaim docker)
  • 3 nœuds docker, avec l'adresse IP de destination ajoutée à tous les nœuds et arp configuré de manière appropriée pour le routage IPVS DR

Je voudrais déployer une pile sur l'essaim et le faire écouter sur le port 80 sur l'adresse IP virtuelle sans modifier les adresses.

Je peux presque y arriver en faisant ceci:
ports :
- cible : 80
publié : 80
protocole : tcp
mode : hôte

Le problème ici est qu'il ne vous permet pas de spécifier à quelle adresse IP se lier - il se lie simplement à tous. Cela crée des problèmes si vous souhaitez exécuter plusieurs services à l'aide de ce port. Il doit se lier uniquement à une seule adresse IP. L'utilisation de ports différents n'est pas une option avec l'équilibrage de charge DR. Il semble que les développeurs aient supposé que la même adresse IP n'existerait jamais sur plusieurs nœuds, ce qui n'est pas le cas lors de l'utilisation d'un équilibreur de charge DR.

De plus, si vous utilisez la syntaxe courte, elle ignorera l'adresse IP de liaison et se liera toujours à toutes les adresses. La seule façon que j'ai trouvée de se lier à une seule adresse IP est d'exécuter un conteneur non clusterisé (pas un service ou une pile).

Alors maintenant, je suis de nouveau obligé d'utiliser des conteneurs autonomes et de devoir les gérer moi-même au lieu de compter sur les fonctionnalités de service/pile pour le faire.

Nous avons le même problème.
Je voterais pour une solution transparente au sein de Docker Ingress qui permettrait à toutes les applications (certaines utilisant UDP/TCP brut, pas spécialement HTTP) de fonctionner comme prévu.

Je pourrais utiliser la solution de contournement "mode=host port publishing" car mon service est déployé à l'échelle mondiale.
Cependant, il semble que cela soit incompatible avec l'utilisation du pilote réseau macvlan, dont j'ai besoin pour d'autres raisons.
Nous obtenons des journaux comme "le pilote macvlan ne prend pas en charge les mappages de ports".
J'ai essayé d'utiliser plusieurs réseaux, mais cela n'aide pas.

J'ai créé un ticket spécifique ici : https://github.com/docker/libnetwork/issues/2050
Cela ne me laisse aucune solution pour l'instant :'(

salut les gars
Existe-t-il une solution de contournement pour le moment ? Sans l'avoir publié en tant que port hôte
Port ?

Le 11 janvier 2018 00:03, "Olivier Voortman" [email protected] a écrit :

Nous avons le même problème.
Je voterais pour une solution transparente au sein de Docker Ingress qui permettrait à tous
applications (certaines utilisant UDP/TCP brut, pas spécialement HTTP) pour fonctionner comme
attendu.

Je pourrais utiliser la solution de contournement "mode = publication de port hôte" car mon service est
déployé à l'échelle mondiale.
Cependant, il semble que cela soit incompatible avec l'utilisation du macvlan
pilote réseau, dont j'ai besoin pour d'autres raisons.
Nous obtenons des journaux comme "le pilote macvlan ne prend pas en charge les mappages de ports".
J'ai essayé d'utiliser plusieurs réseaux, mais cela n'aide pas.

J'ai créé un ticket spécifique ici : docker/libnetwork#2050
https://github.com/docker/libnetwork/issues/2050
Cela ne me laisse aucune solution pour l'instant :'(

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-356693751 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsUzlM-BMbEsDYAiYH6hKLha-aRqerks5tJQJngaJpZM4Jf2WK
.

C'est vraiment dommage qu'il ne soit pas possible d'obtenir l'IP du client. cela rend inutilisables la plupart des fonctionnalités intéressantes de Docker Swarm.

Sur ma configuration, le seul moyen d'obtenir l'adresse IP du client est d'utiliser network_mode:host et de ne pas utiliser du tout swarm.

l'utilisation de mode=host port publishing ou d'un docker run -p "80:80" ... traditionnel n'a pas fonctionné

Certaines solutions ont été suggérées dans https://github.com/moby/moby/issues/15086 mais la seule solution qui a fonctionné pour moi était la mise en réseau "hôte"...

Un autre problème lié au fait de ne pas avoir la bonne adresse IP est que la limitation du débit nginx ne fonctionne pas correctement et ne peut donc pas être utilisée avec l'équilibreur de charge docker swarm, car les demandes sont limitées en débit et refusées car nginx les compte toutes car elles proviennent d'un seul utilisateur/IP. Donc, la seule solution de contournement consiste à utiliser mode=host, mais de cette façon, je perds les capacités d'équilibrage de charge et je dois pointer DNS vers des instances spécifiques.

Peut-être que docker n'est pas l'outil idéal pour ce travail, je cherchais vagrant à configurer les serveurs HTTP frontaux et à mettre l'adresse IP du client dans les en-têtes de requête HTTP.

Jusqu'à ce que Docker soit capable de transmettre les informations client sur des réseaux superposés, on peut utiliser un proxy comme Docker Flow Proxy ou Traefik, publier les ports souhaités en mode hôte dans ce service et y connecter les services d'application. Pas une solution complète mais fonctionne plutôt bien et permet l'équilibrage de charge des services applicatifs / la récupération de l'adresse IP du client.

@deeky666 Traefik et travaux similaires uniquement s'ils ne sont pas dockerisés

Je ne vois pas de support udo sur traefik

Envoyé de mon iPhone

Finalement, nous avons abandonné le conteneur docker. Ce n'est pas prêt pour la production !

Le mercredi 24 janvier 2018 à 5h43, Efrain [email protected] a écrit :

Je ne vois pas de support udo sur traefik

Envoyé de mon iPhone

>

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-360091189 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AHf7rvMcH2iFBxcExfO_Ol0UttCspuTnks5tNwlkgaJpZM4Jf2WK
.

Le problème semble partiellement résolu dans 17.12.0-ce en utilisant mode=host .

docker service create --publish mode=host,target=80,published=80 --name=nginx nginx

Il a quelques limitations (pas de maillage de routage) mais fonctionne !

@goetas mode=host fonctionné pendant un certain temps comme solution de contournement, donc je ne dirais pas que le problème est résolu d'une manière ou d'une autre. L'utilisation de mode=host a beaucoup de limitations, le port est exposé, ne peut pas utiliser l'équilibrage de charge en essaim, etc.

@darklow Je connais les limites, mais pour mon cas d'utilisation, ça va (sinon encore mieux !). Dans 17.09.1-ce ne fonctionnait pas du tout, donc pour moi c'est déjà une amélioration !

Le gros inconvénient de cette solution de contournement est qu'il est impossible d'éviter le temps d'arrêt pendant la mise à jour.
Actuellement, nous devons choisir de renoncer à la stabilité ou à l'adresse IP source.

Je suis d'accord. Swarm a besoin d'un moyen de haute disponibilité pour préserver l'IP source.

Probablement en utilisant le protocole proxy. Je ne pense pas que ce soit un effort énorme à ajouter
prise en charge du protocole proxy pour docker swarm.

Est-ce que quelqu'un regarde ça ?

Le 28 janvier 2018 à 22h39, "Genki Takiuchi" [email protected] a écrit :

Le gros inconvénient de cette solution de contournement est qu'il est impossible d'éviter le duvet
temps pendant la mise à jour.
Actuellement, nous devons choisir de renoncer à la stabilité ou à l'IP source
adresse.

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-361078416 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsU-or7fnhKTg7fhjtZYjGYHBFRE7Dks5tPKnYgaJpZM4Jf2WK
.

@sandys je suis d'accord. Le protocole proxy serait une excellente idée.
@thaJeztah @aluzzardi @mrjana ce problème pourrait-il attirer l'attention s'il vous plaît ? Il n'y a pas eu de réponse de l'équipe depuis un moment. Merci.

Le protocole Proxy me semble être la meilleure solution. Espérons que l'équipe y réfléchira.

@goetas cela a fonctionné à un moment donné au moins je l'ai vu fonctionner mais il semble être revenu au comportement 172.xxx à nouveau dans docker 1.12.6

C'est TRÈS mauvais, cela atténue toute limitation de débit, prévention de la fraude, journalisation, connexions sécurisées, surveillance de session, etc. !
L'écoute avec mode:host fonctionne, mais n'est pas une vraie solution car vous perdez l'équilibrage de charge du maillage et seul le loadbalanacer logiciel sur l'hôte qui a l'adresse IP publique doit gérer tout le trafic seul.

c'est un bug très critique et important pour nous et cela bloque notre go-live avec Swarm. Nous pensons également que le protocole proxy est la bonne solution pour cela. L'entrée Docker doit transmettre l'adresse IP source sur le protocole proxy.

Sur twitter une des solutions qui a été proposée est d'utiliser Traefik comme ingress géré en dehors de Swarm . C'est très sous-optimal pour nous - et ce n'est pas une surcharge que nous aimerions gérer.

Si les développeurs de Swarm veulent savoir comment implémenter le protocole proxy dans Swarm-ingress, ils doivent vérifier tous les bogues discutés dans Traefik (par exemple https://github.com/containous/traefik/issues/2619)

J'ai réussi à ce que cela fonctionne de manière cohérente en utilisant "composer" plutôt que le mode essaim. Peut-être quelque chose à penser.

Quelques problèmes avec le protocole proxy :

Est-il décodé par docker lui-même, ou par l'application ? Si nous comptons sur l'application pour implémenter le protocole proxy, alors ce n'est pas une solution générale pour toutes les applications et ne fonctionne que pour les serveurs Web ou d'autres applications qui implémentent le protocole proxy. Si docker déballe le protocole proxy et traduit l'adresse, il devra également suivre l'état de la connexion et effectuer la traduction inverse sur les paquets sortants. Je ne suis pas en faveur d'une solution spécifique au Web (s'appuyant sur le protocole proxy dans l'application), car docker est également utile pour de nombreuses applications non Web. Ce problème doit être résolu pour le cas général de toute application TCP/UDP - rien d'autre dans docker n'est spécifique au Web.

Comme pour toute autre méthode d'encapsulation, il y a aussi le problème de la taille des paquets/MTU. Cependant, je pense que cela va probablement être une préoccupation avec à peu près n'importe quelle solution à ce problème. La réponse à cela sera probablement de s'assurer que votre réseau en essaim prend en charge une MTU suffisamment grande pour permettre la surcharge. Je pense que la plupart des essaims sont exécutés sur des réseaux locaux, ce n'est donc probablement pas un problème majeur.

@trajano - Nous savons que cela fonctionne avec la mise en réseau hôte (ce qui est probablement ce que fait votre solution de composition). Cependant, cela annule tous les avantages de mise en réseau de cluster de swarm (tels que l'équilibrage de charge).

Les backends @dack doivent connaître le protocole proxy.
Je pense que cela résout la plupart des cas et au moins vous pouvez installer un proxy mince de type passthrough qui traite l'en-tête du protocole devant vos backends à l'intérieur des conteneurs.
En raison du manque d'informations qui est un problème mortel, je pense qu'il est nécessaire de le résoudre le plus rapidement possible avant une autre solution soignée.

le protocole proxy est largement accepté. consultez le nombre d'outils pris en charge - https://www.haproxy.com/blog/haproxy/proxy-protocol/
il ne couvre même pas les équilibreurs de charge cloud (ELB, Google LB) et les outils plus récents comme Traefik.

Aussi - c'est à peu près la norme dans kubernetes : https://github.com/kubernetes/ingress-nginx#proxy -protocol

À ce stade, le protocole proxy est la norme la plus largement acceptée pour résoudre ce problème. Je ne vois pas l'intérêt de réinventer cela et de rompre la compatibilité avec les nginx du monde.

Ce sont des protocoles L7. L'entrée de l'essaim est L4. Il n'y a rien à réinventer ici, tout est IPVS utilisant DNAT.

@ cpuguy83 ne

Le protocole proxy est la couche 4.
http://www.haproxy.org/download/1.8/doc/proxy-protocol.txt

Le but du protocole PROXY est de remplir les structures internes du serveur avec les
informations collectées par le proxy que le serveur aurait pu obtenir
par lui-même si le client se connectait directement au serveur au lieu de via un
Procuration. Les informations portées par le protocole sont celles que le serveur
get en utilisant getsockname() et getpeername() :

  • famille d'adresses (AF_INET pour IPv4, AF_INET6 pour IPv6, AF_UNIX)
  • protocole socket (SOCK_STREAM pour TCP, SOCK_DGRAM pour UDP)
  • adresses source et destination de la couche 3
  • les ports source et de destination de la couche 4, le cas échéant

http://cbonte.github.io/haproxy-dconv/1.9/configuration.html#5.1 -accept-proxy

accepter-proxy

Impose l'utilisation du protocole PROXY sur toute connexion acceptée par l'un des
les sockets déclarées sur la même ligne. Versions 1 et 2 du protocole PROXY
sont pris en charge et correctement détectés. Le protocole PROXY dicte la couche
3/4 adresses de la connexion entrante à utiliser partout où une adresse est
utilisé, à la seule exception des règles "tcp-request connection" qui
ne voir que l'adresse de connexion réelle. Les journaux refléteront les adresses
indiqué dans le protocole, à moins qu'il ne soit violé, auquel cas le véritable
l'adresse sera toujours utilisée. Ce mot-clé combiné avec le soutien de l'extérieur
Les composants peuvent être utilisés comme une alternative efficace et fiable à la
Mécanisme X-Forwarded-For qui n'est pas toujours fiable et même pas toujours
utilisable. Voir aussi "tcp-request connection expect-proxy" pour une granularité plus fine
paramètre de quel client est autorisé à utiliser le protocole.

Vouliez-vous dire qu'il existait un meilleur moyen que le protocole proxy ? c'est tout à fait possible et j'aimerais en savoir plus sur la préservation de l'adresse IP source dans docker swarm. Cependant, Proxy Protocol est plus largement pris en charge par d'autres outils (comme nginx, etc.) qui seront en aval de swarm-ingress... ainsi que des outils comme AWS ELB qui seront en amont de swarm-ingress. C'était mon seul 0,02 $

@sandys Le protocole proxy ressemble à une encapsulation (au moins à l'initiation de la connexion), ce qui nécessite une connaissance de l'encapsulation du récepteur tout au long de la pile. Il y a beaucoup de compromis à cette approche.

Je ne voudrais pas prendre en charge cela dans le noyau, mais peut-être que rendre l'entrée enfichable serait une approche intéressante.

@sandys https://github.com/sandys Le protocole proxy ressemble à
encapsulation (au moins à l'initiation de la connexion), qui nécessite des connaissances
de l'encapsulation du récepteur tout en bas de la pile. Là
Il y a beaucoup de compromis à cette approche.

C'est vrai. C'est à peu près pourquoi c'est une norme avec un RFC. Il y a
élan derrière cela cependant - à peu près chaque importance des composants
le supporte. À mon humble avis, ce n'est pas une mauvaise décision de le soutenir.

Je ne voudrais pas prendre en charge cela dans le noyau, mais peut-être en faisant une entrée
enfichable serait une approche intéressante.

Il s'agit d'une discussion plus large - mais je pourrais ajouter que le plus gros
l'avantage de Docker Swarm par rapport aux autres est qu'il a toutes les batteries
intégré.

Je vous demanderais toujours de considérer le protocole proxy comme une excellente solution pour
ce problème qui a le soutien de l'industrie.

N'est-il pas possible de simuler un routeur L3 sur Linux et LxC (pas spécifiquement docker)

@trajano La simulation n'est pas nécessaire mais l'encapsulation pour résoudre ce problème.
Par exemple, une option (ex : --use-proxy-protocol ) peut être fournie pour les services qui nécessitent une adresse IP client et savent comment traiter les paquets encapsulés tels que nginx.

Tel qu'il fonctionne actuellement, le nœud docker qui reçoit le paquet effectue SNAT et transmet le paquet au nœud avec le conteneur d'application. Si une forme de tunnellisation/encapsulation était utilisée à la place de SNAT, alors il devrait être possible de transmettre le paquet original non modifié à l'application.

C'est un problème résolu dans d'autres projets. Par exemple, avec OpenStack, vous pouvez utiliser des tunnels comme GRE et VXLAN.

Est-ce que quelqu'un dans la partie récente de ce fil est ici pour représenter l'équipe Docker et au moins dire que « nous vous entendons » ? Il semble qu'une fonctionnalité que vous attendez d'être « prête à l'emploi » et d'un tel intérêt pour la communauté n'est toujours pas résolue après avoir été signalée pour la première fois le 9 août 2016, il y a environ 18 mois.

Est-ce que quelqu'un dans la partie récente de ce fil est ici pour représenter l'équipe Docker et au moins dire que « nous vous entendons » ?

/cc @GordonTheTurtle @thaJeztah @riyazdf @aluzzardi

@bluejaguar @ruudboon Je fais partie de Docker. C'est un problème bien connu. À l'heure actuelle, l'équipe réseau se concentre sur les bogues de longue date avec une stabilité de réseau superposée. C'est pourquoi il n'y a pas vraiment eu de nouvelles fonctionnalités de mise en réseau dans les dernières versions.

Ma suggestion serait de faire une proposition concrète sur laquelle vous êtes prêt à travailler pour résoudre le problème ou au moins une proposition suffisamment bonne pour que n'importe qui puisse l'accepter et l'utiliser.

@ cpuguy83 J'ai suivi certaines des fonctionnalités du protocole proxy entrant dans k8s. Par exemple https://github.com/kubernetes/kubernetes/issues/42616 (PS, il est intéressant de noter que le protocole proxy ici provient de Google Kubernetes Engine, qui prend en charge le protocole proxy de manière native en mode HTTPS).

De plus, ELB a ajouté la prise en charge de Proxy Protocol v2 en novembre 2017 (https://docs.aws.amazon.com/elasticloadbalancing/latest/network/doc-history.html)

Openstack Octavia LB-as-a-service (similaire à notre entrée) a fusionné le protocole proxy en avril dernier - http://git.openstack.org/cgit/openstack/octavia/commit/?id=bf7693dfd884329f7d1169eec33eb03d2ae81ace

Voici une partie de la documentation sur le protocole proxy dans openstack - https://docs.openshift.com/container-platform/3.5/install_config/router/proxy_protocol.html
Certaines nuances concernent le protocole proxy pour https (à la fois dans les cas où vous mettez fin aux certificats à l'entrée ou non).

Des mises à jour/solutions de contournement concernant ce problème ? nous avons vraiment besoin de connaître l'adresse IP du client en mode essaim docker.
Toute aide serait très appréciée.

Ma version :

Client:
Version : 18.02.0-ce
Version API : 1.36
Version Go : go1.9.3
Validation Git : fc4de44
Construit: Mer 7 février 21:16:33 2018
OS/Arch : linux/amd64
Expérimental : faux
Orchestrateur : essaim

Serveur:
Moteur:
Version : 18.02.0-ce
Version API : 1.36 (version minimale 1.12)
Version Go : go1.9.3
Validation Git : fc4de44
Construit: mer 7 fév 21:15:05 2018
OS/Arch : linux/amd64
Expérimental : faux

@adijes et d'autres utilisateurs confrontés à ce problème. Vous pouvez lier les conteneurs au réseau bridge (comme mentionné par quelqu'un dans ce fil).

version: "3.4"

services:
  frontend:
    image: nginx
    deploy:
      placement:
        constraints:
          - node.hostname == "prod1"
    networks:
      - default
      - bridge
  # backed services...
  # ...

networks:
  bridge:
    external:
      name: bridge

Notre frontend est lié à bridge et reste toujours dans un hôte exact, dont l'IP est lié à notre domaine public. Cela lui permet de recevoir une véritable IP d'utilisateur. Et comme il est également lié au réseau default , il pourra se connecter aux services sauvegardés.

Vous pouvez également mettre à l'échelle le frontend , tant que vous le conservez en direct dans ce seul hôte. Cela fait que l'hôte est un point de défaillance unique, mais (je pense) c'est OK pour les petits sites.

Modifié pour ajouter plus d'informations :

Mes conteneurs nginx sont derrière https://github.com/jwilder/nginx-proxy , j'utilise également https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion pour activer SSL. Le nginx-proxy est exécuté via la commande docker run , pas un service docker swarm. C'est peut-être pour cette raison que j'ai obtenu une véritable IP des clients. Le réseau bridge est requis pour permettre à mes conteneurs nginx de communiquer avec nginx-proxy.

FWIW, j'utilise :

Client:
 Version:      17.09.1-ce
 API version:  1.32
 Go version:   go1.8.3
 Git commit:   19e2cf6
 Built:        Thu Dec  7 22:23:40 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.09.1-ce
 API version:  1.32 (minimum version 1.12)
 Go version:   go1.8.3
 Git commit:   19e2cf6
 Built:        Thu Dec  7 22:25:03 2017
 OS/Arch:      linux/amd64
 Experimental: false

La configuration ci-dessus fonctionne également sur une autre configuration en cours d'exécution :

Client:
 Version:      17.09.1-ce
 API version:  1.32
 Go version:   go1.8.3
 Git commit:   19e2cf6
 Built:        Thu Dec  7 22:23:40 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.09.1-ce
 API version:  1.32 (minimum version 1.12)
 Go version:   go1.8.3
 Git commit:   19e2cf6
 Built:        Thu Dec  7 22:25:03 2017
 OS/Arch:      linux/amd64
 Experimental: false

@letientai299 qui ne fonctionne pas pour moi je reçois

le réseau "bridge" est déclaré comme externe, mais il n'est pas dans la bonne portée : "local" au lieu de "swarm"

j'ai un maître et trois nœuds de travail

@trajano , voir ma mise à jour.

@letientai299 en fait, je me demandais comment vous pouviez faire fonctionner bridge en mode essaim . c'est-à-dire que vous n'avez pas obtenu l'erreur que j'ai.

@dack quand vous dites réseau hôte, je suppose que vous voulez dire avoir

ports:
- target: 12555
  published: 12555
  protocol: tcp
  mode: host

Malheureusement, lorsqu'il est exécuté en mode docker stack deploy , il ne fonctionne pas et perd toujours l'adresse IP source alors que docker-compose up fonctionne correctement.

J'avais également essayé ce qui suit basé sur @goetas

docker service create --constraint node.hostname==exposedhost \
  --publish published=12555,target=12555,mode=host \
  trajano.net/myimage

Toujours pas de chance d'obtenir l'IP source c'est sur Server Version: 17.12.0-ce

Cela semble être quelque chose que tout le monde voudrait à un moment donné, et comme l'utilisation de réseaux superposés avec un réseau pont/hôte n'est pas vraiment possible, c'est un bloqueur dans les cas où vous avez vraiment besoin de l'adresse IP du client pour diverses raisons.

Client:
Version : 17.12.0-ce
Version API : 1.35
Version Go : go1.9.2
Validation Git : c97c6d6
Construit: mer. 27 déc. 20:03:51 2017
OS/Arch : darwin/amd64

Serveur:
Moteur:
Version : 17.12.1-ce
Version API : 1.35 (version minimale 1.12)
Version Go : go1.9.4
Validation Git : 7390fc6
Construit: mar 27 fév 22:17:54 2018
OS/Arch : linux/amd64
Expérimental : vrai

Nous sommes en 2018. Quoi de plus récent sur ce problème ?
En mode essaim, je ne peux pas utiliser la limite de req nginx. $remote_addr a toujours attrapé 10.255.0.2.
Il s'agit d'un problème très sérieux à propos de l'essaim de dockers.
Peut-être que je devrais essayer kubernetes depuis aujourd'hui.

@Maslow j'ai posté où nous sommes juste quelques commentaires ci-dessus.

Pouvons-nous assouplir le chèque pour

networks:
  bridge:
    external:
      name: bridge

ou l'étendre comme

networks:
  bridge:
    external:
      name: bridge
      scope: local

et les réseaux scope: local ne sont autorisés que si le mode réseau est host

le réseau "bridge" est déclaré comme externe, mais il n'est pas dans la bonne portée : "local" au lieu de "swarm"

ou autoriser

networks:
  bridge:
    driver: bridge

Pour ne pas échouer avec

échec de la création du service trajano_serv : réponse d'erreur du démon : le réseau trajano_bridge ne peut pas être utilisé avec les services. Seuls les réseaux étendus à l'essaim peuvent être utilisés, tels que ceux créés avec le pilote de superposition.

en ayant mode: host sur les ports publiés.

ports:
- target: 32555
  published: 32555
  protocol: tcp
  mode: host

@trajano Vous pouvez déjà utiliser des réseaux sans

version: '3.4'

services:
  test:
    image: alpine
    command: top
    ports:
      - target: 32555
        published: 32555
        protocol: tcp
        mode: host
    networks:
      - bridge

networks:
  bridge:
    external:
      name: bridge

Avez-vous testé cela sur un essaim avec plus d'un travailleur avec le déploiement de la pile docker. Je sais que cela fonctionne avec composer.

Le 18 mars 2018, à 20h55, Brian Goff [email protected] a écrit :

@trajano Vous pouvez déjà utiliser des réseaux sans

version : '3.4'

prestations de service:
test:
image : alpin
commande : haut
ports :
- cible : 32555
publié : 32555
protocole : tcp
mode : hôte
réseaux :
- pont

réseaux :
pont:
externe:
nom : pont
-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, affichez-le sur GitHub ou coupez le fil de discussion.

Oui, je le fais par essaim...

Le lun. 19 mars 2018 à 09:12, Archimedes Trajano <
[email protected]> a écrit :

Avez-vous testé cela sur un essaim avec plus d'un travailleur avec une pile de docker
déployer. Je sais que cela fonctionne avec composer.

Le 18 mars 2018, à 20h55, Brian Goff [email protected]
a écrit:

@trajano Vous pouvez déjà utiliser des réseaux sans
par exemple cela fonctionne :

version : '3.4'

prestations de service:
test:
image : alpin
commande : haut
ports :

  • cible : 32555
    publié : 32555
    protocole : tcp
    mode : hôte
    réseaux :
  • pont

réseaux :
pont:
externe:
nom : pont
-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, affichez-le sur GitHub ou coupez le fil de discussion.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-374206587 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAwxZsm3OohKL0sqUWhlgUNjCrqR0OaVks5tf67YgaJpZM4Jf2WK
.

--

  • Brian Goff

+1

J'ai ce problème avec l'équilibrage de charge Docker Swarm suivant avec 3 nœuds :

réseau de superposition <-> nginx proxy jwilder docker <-> nginx web head docker

J'ai suivi les suggestions et les journaux continuent de renvoyer l'adresse IP du réseau docker 10.255.0.3 au lieu de l'adresse IP du client réel.

+1

@ cpuguy83 cela a commencé à devenir un bloqueur pour nos plus grandes configurations d'essaim. alors que nous commençons à tirer davantage parti du cloud (où le protocole proxy est utilisé de facto par les équilibreurs de charge), nous perdons ces informations qui sont très importantes pour nous.

Avez-vous une idée d'ETA ? cela nous aiderait beaucoup.

@sandys Un ETA pour quoi exactement ?

@ cpuguy83 salut, merci pour ta réponse. Je suis conscient qu'il n'y a pas d'accord général sur la façon dont vous voulez le résoudre. Je commente en quelque sorte la façon dont l'équipe s'est occupée des problèmes de stabilité et n'est pas libérée pour ce problème.
Quand pensez-vous que cette question serait abordée (le cas échéant) ?

Notez que vous pouvez résoudre ce problème en exécutant un service global et en publiant des ports à l'aide de PublishMode=host. Si vous savez sur quel nœud les gens se connecteront, vous n'en avez même pas besoin, utilisez simplement une contrainte pour le fixer à ce nœud.

@kleptog Vous ne pouvez pas en partie. Il ne peut pas éviter les temps d'arrêt lors de la mise à jour du service.

Scénario de test - examinez de plus près lvs/ipvs.

  • nsenter dans le conteneur d'entrée caché et supprimez la règle snat
  • nsenter au service avec les ports publiés, supprimez le gw par défaut et ajoutez la route par défaut aux conteneurs d'entrée ip.

Maintenant, l'ip source sera conservée.

J'essaie toujours de comprendre les implications des frais généraux, en maintenant le routage basé sur des politiques dans chaque conteneur de service au lieu d'avoir uniquement la règle snat dans le conteneur d'entrée.
Ce serait vraiment soulageant que cela fonctionne.

Désolé pour mon bidouillage naïf, mais quelqu'un pourrait-il ( @dack ? ) m'indiquer le code docker, où cela se fait ?

Ah, maintenant j'ai compris. Dans un essaim multinœud, l'adresse IP doit être celle des directeurs lvs, pour retrouver son chemin vers le bon nœud, la demande est arrivée...

Il serait intéressant de voir le code de toute façon, cependant. Cela pourrait me faire gagner du temps si quelqu'un le savait déjà. Merci

Toutes les mises à jour à ce sujet, ayant trois clusters dans différents pays, et même Azure Traffic Manager ont besoin de véritables adresses IP d'utilisateur, sinon, il ne redirigera pas l'utilisateur vers un bon cluster, etc. Quelqu'un, bientôt ou jamais, vérifiera cela? Merci

J'ai également besoin d'une mise à jour à ce sujet - c'est un énorme piège - le seul moyen que j'ai trouvé est d'ajouter un autre proxy devant et d'envoyer x-forwarded-for à la pile, ce qui signifie en quelque sorte que Swarm n'est pas une option pour le public face au trafic pour de nombreux scénarios.

@cpuguy83 @trajano
Je peux confirmer que ce qui suit ne fonctionne pas

version: '3.4'
services:
  nginx:
    ports:
      - mode: host
        protocol: tcp
        published: 80
        target: 80
      - mode: host
        protocol: tcp
        published: 443
        target: 81
networks:
  bridge:
    external:
      name: bridge

Il échoue avec network "bridge" is declared as external, but it is not in the right scope: "local" instead of "swarm" .

version docker

Client:
 Version:       18.03.0-ce-rc4
 API version:   1.37
 Go version:    go1.9.4
 Git commit:    fbedb97
 Built: Thu Mar 15 07:33:59 2018
 OS/Arch:       windows/amd64
 Experimental:  false
 Orchestrator:  swarm

Server:
 Engine:
  Version:      18.03.0-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.4
  Git commit:   0520e24
  Built:        Wed Mar 21 23:08:31 2018
  OS/Arch:      linux/amd64
  Experimental: false

@Mobe91
Essayez de recréer l'essaim. J'ai aussi eu une erreur. Après l'essaim de ré-init, tout a fonctionné pour moi.
Mon fichier docker-compose.yml :

version: "3.6"

services:
    nginx:
        image: nginx:latest
        depends_on:
            - my-app
            - my-admin
        ports: 
            - target: 80
              published: 80
              protocol: tcp
              mode: host
            - target: 443
              published: 443
              protocol: tcp
              mode: host
            - target: 9080
              published: 9080
              protocol: tcp
              mode: host
        volumes:
            - /etc/letsencrypt:/etc/letsencrypt:ro
            - /home/project/data/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
            - /home/project/data/nginx/conf.d:/etc/nginx/conf.d
            - /home/project/public:/var/public
        networks:
            - my-network
            - bridge
        deploy:
            placement:
                constraints: [node.role == manager]

    my-app:
        image: my-app
        ports:
            - 8080:8080
        volumes:
            - /usr/src/app/node_modules
            - /home/project/public:/usr/src/app/public
        networks:
            - my-network

    my-admin:
        image: my-admin
        ports:
            - 9000:9000
        networks:
            - my-network

networks:
    my-network:
    bridge:
        external: true
        name: bridge

mes docker version :

Client:
 Version:   18.03.0-ce
 API version:   1.37
 Go version:    go1.9.4
 Git commit:    0520e24
 Built: Wed Mar 21 23:10:01 2018
 OS/Arch:   linux/amd64
 Experimental:  false
 Orchestrator:  swarm

Server:
 Engine:
  Version:  18.03.0-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.4
  Git commit:   0520e24
  Built:    Wed Mar 21 23:08:31 2018
  OS/Arch:  linux/amd64
  Experimental: false

Désolé pour mon anglais.

@ Mobe91 c'est ce que j'ai utilisé mais je déploie depuis "portainer" ou sur la machine Linux. Je n'arrive pas à le déployer correctement depuis Windows.

version: '3.4'
services:
  hath:
    image: trajano.net/hath
    deploy:
      placement:
        constraints:
        - node.hostname==docker-engine
    networks:
    - host
    ports:
    - target: 12555
      published: 12555
      protocol: tcp
      mode: host
    secrets:
    - hath_client_login
    volumes:
    - hath:/var/lib/hath
volumes:
  hath:
    name: 'noriko/s/hath'
    driver: cifs
networks:
  host:
    external:
      name: host
secrets:
  hath_client_login:
    external:
      name: hath_client_login

La principale différence est que j'utilise host plutôt que bridge Dans mon cas, j'exécute également mes hôtes en tant que machines virtuelles VirtualBox et j'utilise le routeur qui effectue le routage NAT et qui préserve l'adresse IP entrante jusqu'à le conteneur.

Bien sûr, il n'y a pas de capacité d'équilibrage de charge, je pense que si vous voulez un équilibrage de charge, vous devez avoir quelque chose à l'avant comme un routeur L3 qui ferait l'équilibrage de charge

@trajano a raison, le client Windows était le problème, le déploiement avec le client Linux a fonctionné.

Mais je ne comprends pas pourquoi vous avez même besoin du réseau host ou bridge ?
Ce qui suit fonctionne très bien pour moi, c'est-à-dire que j'obtiens de vraies adresses IP client dans nginx :

version: '3.4'
services:
  nginx:
    ports:
      - mode: host
        protocol: tcp
        published: 80
        target: 80

@ Mobe91 merci, je voulais ouvrir un problème pour cela. Essentiellement à lier avec https://github.com/moby/moby/issues/32957 car cela se produisait toujours avec le client 18.03-ce pour Windows.

Est-ce que quelqu'un a utilisé Cilium ? http://cilium.readthedocs.io/en/latest/gettingstarted/docker/ .

Il semble qu'il puisse résoudre ce problème sans lier les services à l'hôte.

@sandys good find - Je suis sur le point de commencer à le tester, cela a-t-il fonctionné pour vous? Je suis sur le point de retirer nginx de mon essaim si je ne peux pas résoudre ce problème .....

Nous avons atteint cet objectif en repensant notre déploiement pour éviter d'épingler des proxys à des hôtes individuels (qui, en production, se lient à une interface pour d'autres raisons et « récupèrent » donc l'adresse IP du client en tant que sous-produit).

Dans notre environnement de test, nous ne pouvons nous améliorer qu'en déployant sur les gestionnaires par contrainte et en définissant mode = global pour garantir que chaque gestionnaire obtient une instance en cours d'exécution. C'est toujours une surcharge supplémentaire à prendre en compte, en particulier si nous perdons un nœud de gestionnaire et que quelque chose y dirige notre trafic. Cependant, c'est mieux que d'être épinglé à un seul hôte.

@sandys avez-vous essayé Cilium? Ressemble à Weave, qui semble souffrir du même problème au moins avec k8s : https://github.com/kubernetes/kubernetes/issues/51014

Je n'ai pas pu utiliser Cilium, mais j'ai contacté le Cilium
devs pour aider dans la configuration de l'essaim. Mais je suis assez excité à propos de Cilium
parce que l'entrée est un problème déclaré qu'il veut résoudre (contrairement au tissage)

Le jeu 10 mai 2018, 17:24 James Green, [email protected] a écrit :

Nous avons atteint cet objectif en repensant notre déploiement pour éviter d'épingler des proxys à
hôtes individuels (qui, en production, se lient à une interface pour d'autres
raisons et donc « récupérer » l'adresse IP du client en tant que sous-produit).

Dans notre environnement de test, nous ne pouvons nous améliorer qu'en déployant aux managers en
contrainte et mode de paramétrage = global pour s'assurer que chaque manager obtient un
instance en cours d'exécution. C'est toujours un surcoût supplémentaire dont il faut être conscient,
en particulier si nous perdons un nœud de gestionnaire et que quelque chose dirige notre
trafic vers celui-ci. Cependant, c'est mieux que d'être épinglé à un seul hôte.

@sandys https://github.com/sandys avez-vous essayé Cilium ? Ressemble à
Weave, qui semble souffrir du même problème au moins avec les k8 :
kubernetes/kubernetes#51014
https://github.com/kubernetes/kubernetes/issues/51014

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-388032011 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsUzQCgIeTenQIHIERxOfHKCzn1O6Aks5txCpogaJpZM4Jf2WK
.

Le 10 mai 2018 à 17h24, "James Green" [email protected] a écrit :

Nous avons atteint cet objectif en repensant notre déploiement pour éviter d'épingler des proxys à
hôtes individuels (qui, en production, se lient à une interface pour d'autres
raisons et donc « récupérer » l'adresse IP du client en tant que sous-produit).

Dans notre environnement de test, nous ne pouvons nous améliorer qu'en déployant aux managers en
contrainte et mode de réglage = global pour s'assurer que chaque gestionnaire obtient un fonctionnement
exemple. C'est toujours un surcoût supplémentaire dont il faut être conscient, en particulier si
nous perdons un nœud de gestionnaire et quelque chose y dirige notre trafic.
Cependant, c'est mieux que d'être épinglé à un seul hôte.

@sandys https://github.com/sandys avez-vous essayé Cilium ? Ressemble à
Weave, qui semble souffrir du même problème au moins avec les k8 :
kubernetes/kubernetes#51014
https://github.com/kubernetes/kubernetes/issues/51014

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-388032011 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsUzQCgIeTenQIHIERxOfHKCzn1O6Aks5txCpogaJpZM4Jf2WK
.

  • 1

salut les gars,
si vous souhaitez la prise en charge de Docker Swarm dans Cilium (en particulier pour l'entrée et
autour de ce problème particulier), veuillez commenter/aimer ce bug -
https://github.com/cilium/cilium/issues/4159

Le vendredi 11 mai 2018 à 00h59, McBacker [email protected] a écrit :

>

  • 1

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-388159466 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsU_18F_cNttRUaAwaRF3gVpMZ-3qSks5txJUfgaJpZM4Jf2WK
.

pour moi avec la version actuelle, cela fonctionne comme ceci:
je peux alors accéder aux autres nœuds de l'essaim comme c'est également le cas dans le réseau "par défaut"

  web-server:
    image: blabla:7000/something/nginx:latest
    #ports:
    #  - "80:80"
    #  - "443:443"
    ports:
      - target: 80
        published: 80
        protocol: tcp
        mode: host
      - target: 443
        published: 443
        protocol: tcp
        mode: host        
    deploy:
      mode: global
      restart_policy:
        condition: any
      update_config:
        parallelism: 1
        delay: 30s

Je peux confirmer que la clé est d'utiliser ports.mode: host . À partir de la documentation (https://docs.docker.com/compose/compose-file/#long-syntax-1) :

mode : hôte pour publier un port hôte sur chaque nœud, ou entrée pour un port en mode essaim à charge équilibrée.

Ensuite, en utilisant mode: host arrêtez d'être équilibré en charge par l'entrée et la véritable IP apparaît. À titre d'exemple, voici mes journaux nginx :

  • avec mode: host
    metrics-agents_nginx.1.pip12ztq3y1h<strong i="14">@xxxxxxxx</strong> | 62.4.X.X - - [12/Jun/2018:08:46:04 +0000] "GET /metrics HTTP/1.1" 200 173979 "-" "Prometheus/2.2.1" "-" [CUSTOM] "request_time: 0.227" remote_addr: 62.4.X.X proxy_add_x_forwarded_for: 62.4.X.X
  • sans mode: host
    metrics-agents_nginx.1.q1eosiklkgac<strong i="20">@xxxxxxxx</strong> | 10.255.0.2 - - [12/Jun/2018:08:50:04 +0000] "GET /metrics HTTP/1.1" 403 162 "-" "Prometheus/2.2.1" "-" [CUSTOM] "request_time: 0.000" remote_addr: 10.255.0.2 proxy_add_x_forwarded_for: 10.255.0.2

Et si vous vous demandez pourquoi le dernier journal est une réponse 403 Forbidden, c'est à cause de l'utilisation d'une liste blanche sur nginx ( allow 62.4.X.X et deny all ).

Le contexte:
Description: Debian GNU/Linux 9.4 (stretch)
Docker version 18.03.0-ce, build 0520e24

Je confirme ce que @nperron a dit.
L'utilisation du mode hôte permet d'obtenir l'adresse IP du client.

Docker version 18.03.1-ce, build 9ee9f40
Ubuntu 16.04.4 LTS

Je peux confirmer que cela fonctionne.

Docker version 18.03.1-ce, build 9ee9f40
Ubuntu 16.04.4 LTS

ATTENTION : CELA NE FONCTIONNERA PAS SI VOUS AVEZ DÉFINI IPTABLES=FALSE !
Vous l'avez peut-être fait (ou du moins je l'ai fait) si vous utilisez UFW pour sécuriser les ports et que l'essaim de docker remplace ces paramètres UFW.

Il existe des tutoriels qui suggèrent de définir iptables = false via la commande ou dans /etc/docker/daemon.json

J'espère que cela sauvera quelqu'un de la frustration que je viens de vivre !

les gens devraient vraiment arrêter de dire "Mode: host" = working, car cela n'utilise pas Ingress. Cela rend impossible d'avoir un seul conteneur avec un service s'exécutant sur l'essaim mais de pouvoir y accéder via n'importe quel hôte. Vous devez soit rendre le service "Global", soit y accéder uniquement sur l'hôte qu'il exécute, ce qui va à l'encontre de l'objectif de Swarm.

TLDR : "Mode : Host" est une solution de contournement, pas une solution

@r3pek Bien que je sois d'accord avec vous pour dire que vous perdez Ingress si vous utilisez le mode Host pour résoudre cette situation, je dirais que cela ne va guère à l'encontre de l'objectif de Swarm, qui fait bien plus qu'un réseau d'entrée public. Dans notre scénario d'utilisation, nous avons dans le même essaim de superposition :
conteneurs répliqués de gestion qui ne doivent être accessibles que via l'intranet -> ils n'ont pas besoin de l'adresse IP de l'appelant, ils sont donc configurés "normalement" et tirent parti de l'entrée.
conteneurs non exposés -> rien à dire à ce sujet (je pense que vous sous-estimez le pouvoir de pouvoir y accéder via leur nom de service).
service public -> il s'agit d'un proxy nginx qui effectue un routage basé sur https et URL. Il a été défini globalement avant même la nécessité de x-forward-pour la vraie IP du client, donc pas de réel problème là-bas.

Avoir nginx global et ne pas avoir d'entrée signifie que vous pouvez l'atteindre via n'importe quelle adresse IP du cluster, mais ce n'est pas équilibré en charge ou tolérant aux pannes, nous avons donc ajouté un équilibreur de charge Azure L4 très très bon marché et facile à configurer devant le nginx service.

Comme vous le dites, Host est une solution de contournement, mais dire que son activation va à l'encontre de l'objectif de Docker Swarm est un peu exagéré imo.

Salut Roberto
Je ne pense pas que ce soit exagéré - car le mode hôte expose des points uniques
d'échec. De plus, il attend des couches supplémentaires de gestion pour la charge
équilibre en dehors de l'écosystème de l'essaim.

En disant que vous avez utilisé azure lb vous-même, vous avez en quelque sorte validé que
argument.

Cela revient à dire que "pour exécuter swarm avec la propagation de l'adresse IP du client,
assurez-vous que vous utilisez un équilibreur de charge externe que vous avez configuré... Ou utilisez
l'un des services cloud".

Nous ne disons pas qu'il ne s'agit pas d'une solution de contournement temporaire... Mais ce serait
ignorant la promesse de Swarm si nous ne reconnaissons pas tous catégoriquement le
défaut.

Le jeu. 5 juil. 2018, 14:16 Roberto Fabrizi, [email protected]
a écrit:

@r3pek https://github.com/r3pek Bien que je sois d'accord avec vous que vous perdez
Ingress si vous utilisez le mode hôte pour résoudre ce problème, je dirais qu'il
va à peine à l'encontre de tout l'objectif de Swarm, qui fait bien plus qu'un
réseau d'entrée public. Dans notre scénario d'utilisation, nous avons dans le même
essaim de superposition :
gestion des conteneurs répliqués qui ne doivent être accessibles que sur le
intranet -> ils n'ont pas besoin de l'adresse IP de l'appelant, ils sont donc configurés
"normalement" et profiter de l'entrée.
conteneurs non exposés -> rien à dire sur ceux-ci (je crois que vous êtes
sous-estimer le pouvoir de pouvoir y accéder via leur service
nom cependant).
conteneur public -> il s'agit d'un proxy nginx qui fait https et url
routage basé. Il a été défini global avant même la nécessité de x-forward-for
la vraie IP du client, donc pas de vrai problème là-bas.

Avoir nginx global et ne pas avoir d'entrée signifie que vous pouvez l'atteindre via
n'importe quelle adresse IP du cluster, mais ce n'est pas équilibré en charge, nous avons donc ajouté un très très
pas cher et facile à configurer L4 Azure Load Balancer devant le nginx
service.

Comme vous le dites, Host est une solution de contournement, mais dire que l'activer complètement
bat le but de Docker Swarm est un peu exagéré imo.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-402650066 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsU_ogRzwM6X0PMknXxsxmZLLTtfraks5uDdJlgaJpZM4Jf2WK
.

Il est clair qu'un mauvais équilibreur de charge (IPVS) a été choisi pour l'entrée de Docker Swarm. S'il prenait en charge au moins le protocole proxy L4, ce ne serait pas un problème. Sauf que ce serait toujours un équilibreur de charge L4 (TCP) sans toutes les fonctionnalités supplémentaires que L7 lb peut offrir.

Dans Kubernetes, il existe des équilibreurs de charge L4(TCP)-L7(HTTP) comme nginx ingress , haproxy ingress qui permettent tous deux l'utilisation du protocole proxy L4 ou des en-têtes HTTP L7 pour garantir que X-Forwarded-For est exploité pour transmettre le réel de l'utilisateur IP au backend.

Je me demande ce que diraient les développeurs de l'entrée Docker Swarm. Quelqu'un doit probablement déplacer ce cas vers https://github.com/docker/swarmkit/issues ?

Dans Kubernetes, il existe des équilibreurs de charge L4 (TCP)-L7 (HTTP) tels que nginx ingress, haproxy ingress qui permettent tous deux l'utilisation du protocole proxy L4 ou des en-têtes HTTP L7 pour garantir que X-Forwarded-For est utilisé pour transmettre l'adresse IP réelle de l'utilisateur. au backend.

AFAICS, ces services LB ne sont pas intégrés dans K8 mais des services qui doivent être explicitement déployés. Vous pouvez également faire la même chose avec Docker swarm. Je ne vois pas de différence ici. (En dehors de cela, le contrôleur d'entrée nginx semble être "officiel".)

Pour autant que je sache, la différence est que même si vous déployez un tel service d'équilibrage de charge, il sera "appelé" à partir de l'équilibreur de charge swarmkit et vous perdez ainsi l'adresse IP des utilisateurs. Vous ne pouvez donc pas désactiver l'équilibreur de charge swarmkit si vous n'utilisez pas hostmode.

pour être juste - dans k8s, il est possible d'avoir une entrée personnalisée. en essaim
n'est pas.

swarm soutient que tout est "intégré". Il en est de même avec
réseaux - dans k8s, vous devez configurer le tissage, etc. dans swarm, il est intégré.

donc le point que fait valoir Andrey (et je suis en quelque sorte d'accord avec) est que -
swarm devrait intégrer cette fonctionnalité à l'entrée, car l'utilisateur a
aucun contrôle dessus.

Le samedi 28 juillet 2018 à 17h07, Seti [email protected] a écrit :

Pour autant que je sache, la différence est que e en si vous déployez un tel
service d'équilibrage de charge, il sera "appelé" à partir de l'équilibreur de charge swarmkit
et ainsi vous perdez l'ip des utilisateurs. Donc vous ne pouvez pas désactiver le swarmkit
loadbalancer si vous n'utilisez pas hostmode.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-408601274 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsU1-Ism_S1Awml8lO8N0Aq6rtrLH4ks5uLEzugaJpZM4Jf2WK
.

Je pensais que nous avions fini d'aplanir nos rides d'essaim, mais ensuite nous sommes arrivés sur scène et avons remarqué que tous les accès externes au conteneur du serveur Web apparaissent comme l'adresse IP du réseau d'entrée.

J'exécute ma pile sur un essaim à nœud unique et je le ferai pendant au moins les prochains mois. Pouvez-vous recommander la solution de contournement la moins mauvaise pour notre cas d'utilisation actuel (essaim à nœud unique) ? Je ne peux pas me passer de l'adresse IP du client - trop de choses en dépendent.

Notre approche temporaire a consisté à exécuter un simple conteneur proxy en mode "global" (dont IIRC peut obtenir l'adresse IP réelle de la carte réseau), puis à lui faire transmettre toutes les connexions au service interne exécuté sur le réseau de superposition d'essaims avec des en-têtes de proxy ajoutés.

Si obtenir un en-tête x-forwarded-for vous suffit, cette configuration devrait fonctionner AFAICT.

Merci @maximelb. Avec quoi avez-vous fini par choisir (par exemple, nginx, haproxy) ?

@jamiejackson c'est

Je ne suis pas très familier avec les proxys HTTP, mais je soupçonne que la plupart d'entre eux feraient l'affaire pour vous. :-/

salut Maxime,
c'est très intéressant pour nous. Pouvez-vous partager votre docker-compose par n'importe quel
chance ?

J'essaie de comprendre comment cela fonctionne. Aujourd'hui, nous avons nginx à l'envers
proxy (en tant que service) et plusieurs services docker derrière lui.

Dans votre cas, nginx devient-il le proxy "mode global" ? ou est-ce un
transitaire TCP spécial. Ainsi, à mesure que vous augmentez le nombre de nœuds, le redirecteur proxy
va sur chaque nœud. J'ai en quelque sorte pensé que dans cette situation le x-transmis pour
l'en-tête se perd .. parce que le réseau d'entrée tue l'adresse IP externe
(puisqu'il n'y a pas de proxy-protocol).

Nous serions très reconnaissants si vous pouviez nous aider avec plus de détails.

Cordialement
sandeep

Le mer. 8 août 2018 à 7:18 Maxime Lamothe-Brassard <
[email protected]> a écrit :

Notre approche temporaire a consisté à exécuter un simple conteneur proxy dans
mode "global" (que IIRC peut obtenir l'adresse IP réelle de la carte réseau), puis l'avoir
transférer toutes les connexions au service interne exécuté sur l'essaim
réseau de superposition avec des en-têtes de proxy ajoutés.

Si obtenir un en-tête x-forwarded-for vous suffit, cette configuration devrait
travail AFAICT.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-411257087 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsUx3DOjXb79FNjsuZ-RZVqkkhHAbYks5uOkOHgaJpZM4Jf2WK
.

@sandys bien sûr, voici un extrait de notre docker-compose avec les conteneurs concernés.

Ceci est l'entrée docker-compose du proxy inverse :

reverseproxy:
    image: yourorg/repo-proxy:latest
    networks:
      - network_with_backend_service
    deploy:
      mode: global
    ports:
      - target: 443
        published: 443
        protocol: tcp
        mode: host

Voici l'entrée du service backend :

backendservice:
    image: yourorg/repo-backend:latest
    networks:
      - network_with_backend_service
    deploy:
      replicas: 2

La cible du reverseproxy (le côté backend) serait tasks.backendservice (qui a des enregistrements A pour chaque réplica). Vous pouvez ignorer la partie networks si le service backend se trouve sur le réseau de superposition d'essaims par défaut.

Le bit global dit "déployez ce conteneur une seule fois sur chaque nœud Docker swarm. Les ports mode: host sont ceux qui disent "se lier à la carte réseau native du nœud".

J'espère que ça aide.

Vous utilisez le mode hôte. Donc à peu près vous avez un équilibreur de charge externe
devant le tout.
Vous ne pouvez plus compter sur Swarm car vous êtes en mode hôte.

C'est en fait le problème dont nous parlons depuis un moment :(

Le mer. 8 août 2018, 20:47 Maxime Lamothe-Brassard, <
[email protected]> a écrit :

@sandys https://github.com/sandys bien sûr, voici un extrait de notre
docker-compose avec les conteneurs correspondants.

Ceci est l'entrée docker-compose du proxy inverse :

proxy inverse :
image : yourorg/repo- proxy:latest
réseaux :
- network_with_backend_service
déployer:
mode : global
ports :
- cible : 443
publié : 443
protocole : tcp
mode : hôte

Voici l'entrée du service backend :

service backend :
image: yourorg/repo- backend:latest
réseaux :
- network_with_backend_service
déployer:
répliques : 2

La cible du reverseproxy (le côté backend) serait
task.backendservice (qui a des enregistrements A pour chaque réplica). Vous pouvez
ignorer la partie réseaux si le service backend est sur l'essaim par défaut
réseau de superposition.

Le bit global dit "déployez ce conteneur exactement une fois sur chaque Docker
nœud d'essaim. Le mode ports : l'hôte est celui qui dit "se lier au natif
NIC du nœud".

J'espère que ça aide.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-411442155 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsU8N7KAFtOp_cPO8wpbBQqzDfpBWOks5uOwEkgaJpZM4Jf2WK
.

Pas sûr à 100% de ce que vous voulez dire, mais en externe, nous utilisons un DNS avec un enregistrement A par nœud de cluster. Cela permet un "équilibrage" bon marché sans avoir de pièce mobile externe. Lorsqu'un client fait une demande, il choisit un enregistrement A aléatoire et se connecte à 443 sur l'un des nœuds du cluster.

Là, le proxy inverse qui s'exécute sur ce nœud spécifique et écoute sur 443 obtient une connexion native, y compris l'adresse IP du client réel. Ce conteneur de proxy inverse ajoute ensuite un en-tête et transfère la connexion à un autre conteneur interne à l'aide du réseau de superposition en essaim (tasks.backend). Comme il utilise la cible task.backend, il obtiendra également un enregistrement A aléatoire pour un service interne.

Donc au sens strict, c'est la magie du contournement du réseau superposé qui redirige la connexion. Au lieu de cela, il réplique en quelque sorte ce comportement avec le proxy inverse et ajoute un en-tête. L'effet final est le même (au sens large) que la magie du réseau de superposition. Il le fait également en parallèle de l'exécution de l'essaim, ce qui signifie que je peux exécuter tous mes autres services qui ne nécessitent pas l'adresse IP du client sur le même cluster sans rien faire d'autre pour ceux-ci.

En aucun cas une solution parfaite, mais jusqu'à ce qu'un correctif soit apporté (le cas échéant), il vous permet de vous en sortir sans composants externes ni configuration de docker majeure.

@jamiejackson la solution de contournement "la moins mauvaise" que nous ayons trouvée consiste à utiliser Traefik en tant que service global en mode hôte. Ils ont un bon exemple générique dans leurs docs . Nous avons vu quelques bugs qui peuvent ou non être liés à cette configuration, mais Traefik est un excellent projet et il semble assez stable sur Swarm. Il y a tout un fil sur leur page de problèmes (qui revient ici :) ), avec des solutions de contournement similaires :
https://github.com/containous/traefik/issues/1880

J'espère que cela t'aides. Nous ne pouvons pas non plus utiliser une solution qui ne nous permet pas de vérifier les adresses IP réelles des demandeurs, nous sommes donc bloqués avec ce correctif de kludge jusqu'à ce que quelque chose change. Cela semble être un besoin assez courant, au moins pour des raisons de sécurité.

Compris (et une version lâche de ceci est ce que nous utilisons).

Cependant, l'ordre du jour de ce bogue particulier consistait à demander aux développeurs
pour intégrer cela dans le réseau de superposition magique (peut-être en utilisant un proxy
protocole ou d'autres mécanismes)

Le mer. 8 août 2018, 21:22 Maxime Lamothe-Brassard, <
[email protected]> a écrit :

Pas sûr à 100% de ce que vous voulez dire, mais en externe, nous utilisons un DNS avec un A
enregistrement par nœud de cluster. Cela permet un "équilibrage" bon marché sans avoir un
partie mobile externe. Lorsqu'un client fait une demande, il choisit un A aléatoire
et connectez-vous à 443 sur l'un des nœuds du cluster.

Là, le proxy inverse qui s'exécute sur ce nœud spécifique et
l'écoute sur 443 obtient une connexion native, y compris l'adresse IP réelle du client.
Ce conteneur de proxy inverse ajoute ensuite un en-tête et transfère la connexion
vers un autre conteneur interne à l'aide du réseau de superposition swarm
(tâches.backend). Comme il utilise la cible task.backend, il obtiendra également un
aléatoire Un enregistrement pour un service interne.

Donc au sens strict, c'est contourner la magie du réseau superposé qui
redirige la connexion. Au lieu de cela, il reproduit en quelque sorte ce comportement avec
le proxy inverse et ajoute un en-tête. L'effet final est le même (dans un
sens lâche) comme la magie du réseau superposé. Il le fait aussi en
parallèlement à l'exécution de l'essaim, ce qui signifie que je peux exécuter tous mes autres services qui
n'exigez pas l'IP du client sur le même cluster sans rien faire
d'autre pour ceux-là.

En aucun cas une solution parfaite, mais jusqu'à ce qu'un correctif soit apporté (si jamais), il obtient
vous sans composants externes ni configuration de docker majeure.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-411455384 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsU5RKjGc3hEk6bk-doicDa1MbYGAyks5uOwlIgaJpZM4Jf2WK
.

TBH Je ne sais pas pourquoi le réseau d'entrée n'est pas corrigé pour ajouter une adresse IP
données dans le protocole proxy.

C'est incrémental, ça ne cassera pas les piles existantes, c'est un bien défini
standard, il est largement pris en charge même par les grands fournisseurs de cloud, il est largement
pris en charge par les cadres d'application.

Est-ce un effort de développement important ?

Le mercredi 8 août 2018, à 21h30, Matt Glaser, [email protected] a écrit :

@jamiejackson https://github.com/jamiejackson le "moins mauvais"
La solution de contournement que nous avons trouvée consiste à utiliser Traefik en tant que service global en mode hôte.
Ils ont un bon exemple générique dans leurs docs
https://docs.traefik.io/user-guide/cluster-docker-consul/#full-docker-compose-file_1 .
Nous avons vu quelques bugs qui peuvent ou non être liés à cette configuration, mais
Traefik est un excellent projet et il semble assez stable sur Swarm. Il y a un
fil entier sur leur page de problèmes (qui revient ici :) ), avec
solutions de contournement similaires :
contenant/traefik#1880
https://github.com/containous/traefik/issues/1880

J'espère que cela t'aides. Nous ne pouvons pas non plus utiliser une solution qui ne nous permet pas de
vérifier les adresses IP réelles du demandeur afin que nous soyons coincés avec ce correctif kludge jusqu'à ce que
quelque chose change. Cela semble être un besoin assez courant, pour des raisons de sécurité
au moins.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-411458326 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsU7NNbsW44L95VYCvlyL_Bje-h6L9ks5uOwsUgaJpZM4Jf2WK
.

Eh bien, Docker ne touche actuellement pas le trafic entrant, donc certainement au moins pas négligeable à ajouter.
Gardez également à l'esprit qu'il s'agit d'un projet open source, si vous voulez vraiment quelque chose, ce sera généralement à vous de le mettre en œuvre.

+1, c'est vraiment un écueil.
Je crois que la majorité des applications a besoin de l'adresse IP des vrais clients. Pensez simplement à une pile de serveurs de messagerie - vous ne pouvez pas vous permettre d'accepter des courriers provenant d'hôtes arbitraires.

Nous sommes passés au mode hôte d'instance de flux global proxy_protocol nginx, qui est transféré à l'application répliquée proxy_nginx. Cela fonctionne assez bien pour le moment.

service global nginx_stream

stream {
    resolver_timeout 5s;
    # 127.0.0.11 is docker swarms dns server
    resolver 127.0.0.11 valid=30s;
    # set does not work in stream module, using map here
    map '' $upstream_endpoint {
        default proxy_nginx:443;
    }

    server {
        listen 443;
        proxy_pass $upstream_endpoint;
        proxy_protocol on;
    }
}

service répliqué nginx_proxy

server {
    listen 443 ssl http2 proxy_protocol;
    include /ssl.conf.include;

    ssl_certificate /etc/nginx/certs/main.crt;
    ssl_certificate_key /etc/nginx/certs/main.key;

    server_name example.org;

    auth_basic           "closed site";
    auth_basic_user_file /run/secrets/default.htpasswd;

    # resolver info in nginx.conf
    set $upstream_endpoint app;
    location / {
        # relevant proxy_set_header in nginx.conf
        proxy_pass http://$upstream_endpoint;
    }
}

Serait-il possible de passer toute la configuration nginx pour nginx_stream et
nginx_proxy avec leurs configurations Swarm ?

C'est génial si ça marche !

Le mardi 11 septembre 2018, 17:14 rubot, [email protected] a écrit :

Nous sommes passés à l'instance de flux global proxy_protocol nginx, qui est
transfert vers l'application répliquée proxy_nginx. Cela fonctionne assez bien
pour le moment.

service global nginx_stream

flux {
resolver_timeout 5s ;
# 127.0.0.11 est le serveur DNS Docker Swarms
résolveur 127.0.0.11 valide=30s ;
# set ne fonctionne pas dans le module de flux, en utilisant la carte ici
map '' $ upstream_endpoint {
proxy_nginx par défaut : 443 ;
}

server {
    listen 443;
    proxy_pass $upstream_endpoint;
    proxy_protocol on;
}

}

service répliqué nginx_proxy

serveur {
écouter 443 ssl http2 proxy_protocol;
inclure /ssl.conf.include ;

ssl_certificate /etc/nginx/certs/main.crt;
ssl_certificate_key /etc/nginx/certs/main.key;

server_name example.org;

auth_basic           "closed site";
auth_basic_user_file /run/secrets/default.htpasswd;

# resolver info in nginx.conf
set $upstream_endpoint app;
location / {
    # relevant proxy_set_header in nginx.conf
    proxy_pass http://$upstream_endpoint;
}

}

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-420244262 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsU5K-gK09XdI9NxLlT36IrJP7U7_cks5uZ6IrgaJpZM4Jf2WK
.

@sandys J'ai une solution basée sur haproxy pour la partie du protocole proxy qui est configurée via des variables d'environnement.

Serait-il possible de coller toute la configuration nginx pour nginx_stream et nginx_proxy avec leurs configurations Swarm ? C'est génial si ça marche !

@sandys Quelque chose comme ça :
https://gist.github.com/rubot/10c79ee0086a8a246eb43ab631f3581f

rencontrer le même problème, est-ce que cela va être résolu? semble être une fonctionnalité de base qui devrait être prévue pour une version.

déployer:
mode : global
ports :

  • cible : 443 publié : 443 protocole : mode tcp : hôte

Suivre ce conseil résout le problème car l'équilibreur d'essaim de docker est désormais hors de l'équation.
Pour moi, c'est une solution valable car c'est toujours HA et j'avais déjà haproxy (à l'intérieur du conteneur de proxy de flux docker).
Le seul problème est que les statistiques haproxy sont réparties entre toutes les répliques, j'ai donc besoin d'agréger ces informations lors de la surveillance du trafic pour l'ensemble du cluster. Dans le passé, je n'avais qu'une seule instance haproxy qui était derrière l'équilibreur d'essaim de docker.
À votre santé,
Jacques

Lors de la lecture de la demande du PO ( @PanJ ), il semble que les fonctionnalités actuelles résolvent désormais ce problème, comme cela a été suggéré pendant des mois. L'OP n'a pas demandé de routage d'entrée + IP client AFAIK, ils ont demandé un moyen d'avoir un service d'essaim dans la réplique/globale pour obtenir l'adresse IP du client, ce qui est maintenant faisable. Deux axes principaux d'amélioration permettent d'y parvenir :

  1. Nous pouvons maintenant créer un service Swarm qui "publie" un port sur l'adresse IP de l'hôte, en sautant la couche de routage d'entrée
  2. Ce même service peut se connecter à d'autres réseaux comme la superposition en même temps, afin qu'il puisse accéder à d'autres services avec des avantages de superposition

Pour moi, avec le moteur 18.09, j'obtiens le meilleur des deux mondes lors des tests. Un seul service peut se connecter à des réseaux de superposition backend et également publier des ports sur la carte réseau hôte et voir l'adresse IP client réelle entrante sur l'adresse IP hôte. Je l'utilise avec le proxy inverse traefik pour enregistrer le trafic IP client dans traefik qui est destiné aux services backend . J'ai l'impression que cela pourrait résoudre la plupart des demandes que j'ai vues pour "enregistrer la vraie IP".

@PanJ est-ce que cela le résout pour vous ?

La clé est de publier les ports en mode: host plutôt qu'en mode: ingress (par défaut).

L'avantage de ce mode est que vous obtenez de vraies performances IP client et NIC hôte native (puisqu'il est en dehors de l'encapsulation IPVS AFAIK). L'inconvénient est qu'il n'écoutera que sur le ou les nœuds exécutant les répliques.

Pour moi, la demande "Je souhaite utiliser le routage IPVS d'entrée et voir également l'adresse IP du client" est une demande de fonctionnalité différente de libnetwork.

Qu'est-ce qui a changé ici ? Parce que nous utilisons le mode hôte pour le faire depuis
longtemps maintenant. En fait, c'est la solution de contournement suggérée dans ce fil comme
bien.

Le problème est que bien sûr vous devez verrouiller ce service à un
hôte afin que Swarm ne puisse pas le programmer ailleurs. Quel était le problème
entièrement - que le protocole proxy/IPVS, etc. résolvent ce problème.

Le vendredi 4 janvier 2019, 09:34 Bret Fisher < [email protected] a écrit :

Lors de la lecture de la demande de l'OP ( @PanJ https://github.com/PanJ ), il
semble que les fonctionnalités actuelles résolvent maintenant ce problème, comme cela a été suggéré pour
mois. L'OP n'a pas demandé de routage d'entrée + IP client AFAIK, ils ont demandé
pour un moyen d'avoir un service d'essaim dans la réplique/globale obtenir les adresses IP du client,
ce qui est désormais faisable. Deux axes principaux d'amélioration permettent d'y parvenir :

  1. Nous pouvons maintenant créer un service Swarm qui "publie" un port vers le
    IP hôte, en sautant la couche de routage d'entrée
  2. Ce même service peut se connecter à d'autres réseaux comme la superposition au
    en même temps, afin qu'il puisse accéder à d'autres services avec des avantages de superposition

Pour moi, avec le moteur 18.09, j'obtiens le meilleur des deux mondes lors des tests. UNE
un seul service peut se connecter à des réseaux de superposition backend et également publier
ports sur la carte réseau hôte et voir l'adresse IP client réelle entrante sur l'adresse IP hôte. je suis
l'utiliser avec traefik reverse proxy pour enregistrer le trafic IP client dans traefik
qui est destiné aux services backend
https://github.com/BretFisher/dogvscat/blob/7e9fe5b998f2cf86951df3f443714beb413d63fb/stack-proxy-global.yml#L75-L83 .
J'ai l'impression que cela pourrait résoudre la plupart des demandes que j'ai vues pour "enregistrer le vrai
IP".

@PanJ https://github.com/PanJ est-ce que cela résout le problème pour vous ?

La clé est de publier les ports en mode : hôte plutôt qu'en mode : entrée (le
défaut).

L'avantage de ce mode est que vous obtenez de vraies adresses IP client et une carte réseau hôte native
performance (puisqu'il est en dehors de l'encapsulation IPVS AFAIK). L'inconvénient c'est ça
écoutera uniquement sur le(s) nœud(s) exécutant les réplicas.

Pour moi, la demande de "Je souhaite utiliser le routage IPVS d'entrée et voir également
IP client" est une demande de fonctionnalité différente de libnetwork.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451348906 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsUzs15UVWOVl54FLwBJSZJKX-9D0jks5u_tLPgaJpZM4Jf2WK
.

@BretFisher le mode: host n'est qu'une solution de contournement mais pas la solution. Comme @sandys a déclaré que la solution de contournement comporte quelques mises en garde, nous ne devrions pas considérer ce problème comme résolu.

Je ne sais pas s'il y a eu une amélioration depuis que la solution de contournement a été découverte. J'ai migré vers Kubernetes depuis assez longtemps et je suis toujours surpris que le problème soit toujours ouvert depuis plus de deux ans.

Je suis toujours un peu surpris de savoir pourquoi les gens pensent que c'est un bug. De mon
perspective, même la déclaration de passage à kubernetes n'est pas une
réponse. Comme je vois, kubernetes a exactement le même problème/comportement. Toi non plus
avoir un LB externe, ou utiliser quelque chose comme le proxy d'entrée nginx qui doit
exécuter en tant que daemonset. Veuillez me corriger si je me trompe, mais nous avons le même
situation exacte ici, mais pas de solution automatique préparée ici. Quelqu'un pourrait
vérifier et emballer ma solution de flux tcp proposée décrite ci-dessus pour obtenir
quelque chose comme le comportement du proxy nginx. Accepte juste, cet essaim doit être
personnalisé par vous-même

PanJ [email protected] schrieb am Ve, 4. Jan. 2019, 09:28:

@BretFisher https://github.com/BretFisher le mode : l'hôte n'est qu'un
solution de contournement mais pas la solution. Comme @sandys https://github.com/sandys
dit que la solution de contournement comporte quelques mises en garde, nous ne devrions pas considérer ce problème
comme fixe.

Je ne sais pas s'il y a eu une amélioration depuis que la solution de contournement a été
découvert. J'ai déménagé chez Kubernetes depuis assez longtemps et je suis toujours
surpris que la question soit toujours ouverte depuis plus de deux ans.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451382365 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAPgu40OJ-uNKORD-LAD12m1lafxzMiSks5u_xCcgaJpZM4Jf2WK
.

Vous pouvez même étendre le projet dockerflow et ajouter une variante nginx pour commencer
kubernetes-ingressproxy pour swarn. Certainement tout cela emballé avec un essaim
soulèverait un conteneur système supplémentaire car vous savez qu'il y a un tas de
eux avec kubernetes. N'est-ce pas la force de l'essaim pour la ressource mince
projets d'être lean?

Ruben Nicolaides [email protected] schrieb am Fr., 4. Jan. 2019, 09:48:

Je suis toujours un peu surpris de savoir pourquoi les gens pensent que c'est un bug. De mon
perspective, même la déclaration de passage à kubernetes n'est pas une
réponse. Comme je vois, kubernetes a exactement le même problème/comportement. Toi non plus
avoir un LB externe, ou utiliser quelque chose comme le proxy d'entrée nginx qui doit
exécuter en tant que daemonset. Veuillez me corriger si je me trompe, mais nous avons le même
situation exacte ici, mais pas de solution automatique préparée ici. Quelqu'un pourrait
vérifier et emballer ma solution de flux tcp proposée décrite ci-dessus pour obtenir
quelque chose comme le comportement du proxy nginx. Accepte juste, cet essaim doit être
personnalisé par vous-même

PanJ [email protected] schrieb am Ve, 4. Jan. 2019, 09:28:

@BretFisher https://github.com/BretFisher le mode : l'hôte n'est qu'un
solution de contournement mais pas la solution. Comme @sandys https://github.com/sandys
dit que la solution de contournement comporte quelques mises en garde, nous ne devrions pas considérer ce problème
comme fixe.

Je ne sais pas s'il y a eu une amélioration depuis que la solution de contournement a été
découvert. J'ai déménagé chez Kubernetes depuis assez longtemps et je suis toujours
surpris que la question soit toujours ouverte depuis plus de deux ans.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451382365 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAPgu40OJ-uNKORD-LAD12m1lafxzMiSks5u_xCcgaJpZM4Jf2WK
.

Ce sont des solutions complexes - le protocole proxy ajoute simplement un en-tête supplémentaire
informations et est une norme très connue - haproxy, nginx, AWS elb,
etc. tous le suivent. https://www.haproxy.com/blog/haproxy/proxy-protocol/

La superficie du changement serait limitée au Swarm construit en
ingress (où ce support serait ajouté). Et tous les services l'auront
disponible.

Le vendredi 4 janvier 2019, 14:36 ​​rubot < [email protected] a écrit :

Vous pouvez même étendre le projet dockerflow et ajouter une variante nginx pour commencer
kubernetes-ingressproxy pour swarn. Certainement tout cela emballé avec un essaim
soulèverait un conteneur système supplémentaire car vous savez qu'il y a un tas de
eux avec kubernetes. N'est-ce pas la force de l'essaim pour la ressource mince
projets d'être lean?

Ruben Nicolaides [email protected] schrieb am Fr., 4. Jan. 2019, 09:48:

Je suis toujours un peu surpris de savoir pourquoi les gens pensent que c'est un bug. De mon
perspective, même la déclaration de passage à kubernetes n'est pas une
réponse. Comme je vois, kubernetes a exactement le même problème/comportement. Tu
Soit
avoir un LB externe, ou utiliser quelque chose comme le proxy d'entrée nginx qui doit
exécuter en tant que daemonset. Veuillez me corriger si je me trompe, mais nous avons le même
situation exacte ici, mais pas de solution automatique préparée ici. Quelqu'un pourrait
vérifier et emballer ma solution de flux tcp proposée décrite ci-dessus pour obtenir
quelque chose comme le comportement du proxy nginx. Accepte juste, cet essaim doit être
personnalisé par vous-même

PanJ [email protected] schrieb am Ve, 4. Jan. 2019, 09:28:

@BretFisher https://github.com/BretFisher le mode : l'hôte n'est qu'un
solution de contournement mais pas la solution. Comme @sandys https://github.com/sandys
dit que la solution de contournement comporte quelques mises en garde, nous ne devrions pas considérer cela
problème
comme fixe.

Je ne sais pas s'il y a eu une amélioration depuis que la solution de contournement a été
découvert. J'ai déménagé chez Kubernetes depuis assez longtemps et toujours
être
surpris que la question soit toujours ouverte depuis plus de deux ans.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451382365 , ou
muet
le fil
<
https://github.com/notifications/unsubscribe-auth/AAPgu40OJ-uNKORD-LAD12m1lafxzMiSks5u_xCcgaJpZM4Jf2WK

.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451389574 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsU2FCEGFs5v6IOEy6AqjcBMl7IqEiks5u_xmTgaJpZM4Jf2WK
.

Comme je l'ai dit, vérifiez la solution de flux tcp ci-dessus, qui utilise déjà le proxy
protocole.
L'ajout du protocole proxy nécessiterait également une configuration à l'intérieur du conteneur si
ajouté à l'essaim en amont. Je ne vois aucune valeur, à part un produit plus propre et peut-être meilleur
objectif documenté dans votre demande

Sandeep Srinivasa [email protected] schrieb am Fr., 4. Jan. 2019,
11h37 :

Ce sont des solutions complexes - le protocole proxy ajoute simplement un en-tête supplémentaire
informations et est une norme très connue - haproxy, nginx, AWS elb,
etc. tous le suivent. https://www.haproxy.com/blog/haproxy/proxy-protocol/

La superficie du changement serait limitée au Swarm construit en
ingress (où ce support serait ajouté). Et tous les services l'auront
disponible.

Le vendredi 4 janvier 2019, 14:36 ​​rubot < [email protected] a écrit :

Vous pouvez même étendre le projet dockerflow et ajouter une variante nginx à
début
kubernetes-ingressproxy pour swarn. Certainement tout cela emballé avec un essaim
soulèverait un conteneur système supplémentaire car vous savez qu'il y a un tas de
eux avec kubernetes. N'est-ce pas la force de l'essaim pour la ressource mince
projets d'être lean?

Ruben Nicolaides [email protected] schrieb am Fr., 4. Jan. 2019, 09:48:

Je suis toujours un peu surpris de savoir pourquoi les gens pensent que c'est un bug. De mon
perspective, même la déclaration de passage à kubernetes n'est pas une
réponse. Comme je vois, kubernetes a exactement le même problème/comportement. Tu
Soit
avoir un LB externe, ou utiliser quelque chose comme le proxy d'entrée nginx qui
doit
exécuter en tant que daemonset. Veuillez me corriger si je me trompe, mais nous avons le même
situation exacte ici, mais pas de solution automatique préparée ici. Quelqu'un pourrait
vérifier et emballer ma solution de flux tcp proposée décrite ci-dessus pour obtenir
quelque chose comme le comportement du proxy nginx. Accepte juste, cet essaim doit
être
personnalisé par vous-même

PanJ [email protected] schrieb am Ve, 4. Jan. 2019, 09:28:

@BretFisher https://github.com/BretFisher le mode : l'hôte n'est qu'un
solution de contournement mais pas la solution. Comme @sandys <
https://github.com/sandys>
dit que la solution de contournement comporte quelques mises en garde, nous ne devrions pas considérer cela
problème
comme fixe.

Je ne sais pas s'il y a eu une amélioration depuis que la solution de contournement a été
découvert. J'ai déménagé chez Kubernetes depuis assez longtemps et toujours
être
surpris que la question soit toujours ouverte depuis plus de deux ans.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451382365 ,
ou
muet
le fil
<

https://github.com/notifications/unsubscribe-auth/AAPgu40OJ-uNKORD-LAD12m1lafxzMiSks5u_xCcgaJpZM4Jf2WK
>

.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451389574 , ou
muet
le fil
<
https://github.com/notifications/unsubscribe-auth/AAEsU2FCEGFs5v6IOEy6AqjcBMl7IqEiks5u_xmTgaJpZM4Jf2WK

.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451409453 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAPgu83fSrSzfopOlDXsDooN1tMboGZaks5u_y8EgaJpZM4Jf2WK
.

La solution ci-dessus nécessite une liaison en mode hôte. C'est le gros problème. Ce
élimine la possibilité d'utiliser le planificateur de docker pour allouer des conteneurs
à différents hôtes - je ne fais plus partie du réseau maillé.

Le vendredi 4 janvier 2019, 17:28 rubot < [email protected] a écrit :

Comme je l'ai dit, vérifiez la solution de flux tcp ci-dessus, qui utilise déjà le proxy
protocole.
L'ajout du protocole proxy nécessiterait également une configuration à l'intérieur du conteneur si
ajouté à l'essaim en amont. Je ne vois aucune valeur, à part un produit plus propre et peut-être meilleur
objectif documenté dans votre demande

Sandeep Srinivasa [email protected] schrieb am Fr., 4. Jan. 2019,
11h37 :

Ce sont des solutions complexes - le protocole proxy ajoute simplement un en-tête supplémentaire
informations et est une norme très connue - haproxy, nginx, AWS elb,
etc. tous le suivent. https://www.haproxy.com/blog/haproxy/proxy-protocol/

La superficie du changement serait limitée au Swarm construit en
ingress (où ce support serait ajouté). Et tous les services auront
ce
disponible.

Le vendredi 4 janvier 2019, 14:36 ​​rubot < [email protected] a écrit :

Vous pouvez même étendre le projet dockerflow et ajouter une variante nginx à
début
kubernetes-ingressproxy pour swarn. Certainement tout cela emballé avec
essaim
soulèverait un conteneur système supplémentaire car vous savez qu'il y a un tas
de
eux avec kubernetes. N'est-ce pas la force de l'essaim pour la ressource mince
projets d'être lean?

Ruben Nicolaides [email protected] schrieb am Fr., 4. Jan. 2019, 09:48:

Je suis toujours un peu surpris de savoir pourquoi les gens pensent que c'est un bug. De mon
perspective, même la déclaration de passage à kubernetes n'est pas un
adéquat
réponse. Comme je vois, kubernetes a exactement le même problème/comportement. Tu
Soit
avoir un LB externe, ou utiliser quelque chose comme le proxy d'entrée nginx qui
doit
exécuter en tant que daemonset. Veuillez me corriger si je me trompe, mais nous avons le
même
situation exacte ici, mais pas de solution automatique préparée ici. Quelqu'un
pourrait
vérifier et emballer ma solution de flux tcp proposée décrite ci-dessus pour obtenir
quelque chose comme le comportement du proxy nginx. Accepte juste, cet essaim doit
être
personnalisé par vous-même

PanJ [email protected] schrieb am Ve, 4. Jan. 2019, 09:28:

@BretFisher https://github.com/BretFisher le mode : l'hôte est uniquement
une
solution de contournement mais pas la solution. Comme @sandys <
https://github.com/sandys>
dit que la solution de contournement comporte quelques mises en garde, nous ne devrions pas considérer
cette
problème
comme fixe.

Je ne sais pas s'il y a une amélioration puisque la solution de contournement a
été
découvert. J'ai déménagé chez Kubernetes depuis assez longtemps et
toujours
être
surpris que la question soit toujours ouverte depuis plus de deux ans.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451382365 ,
ou
muet
le fil
<

https://github.com/notifications/unsubscribe-auth/AAPgu40OJ-uNKORD-LAD12m1lafxzMiSks5u_xCcgaJpZM4Jf2WK

>

.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451389574 , ou
muet
le fil
<

https://github.com/notifications/unsubscribe-auth/AAEsU2FCEGFs5v6IOEy6AqjcBMl7IqEiks5u_xmTgaJpZM4Jf2WK
>

.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451409453 , ou
muet
le fil
<
https://github.com/notifications/unsubscribe-auth/AAPgu83fSrSzfopOlDXsDooN1tMboGZaks5u_y8EgaJpZM4Jf2WK

.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451424992 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsU-q-I3fXVAP9JcGgTdJJOzI7b575ks5u_0HIgaJpZM4Jf2WK
.

Comme je l'ai dit, l'entrée kubernetes nginx a également besoin d'une liaison en mode hôte, appelée
ensemble de démons. LB externe se connecte aux nodeports, qui nécessitent également le mode hôte
en service, ou configurer manuellement le protocole proxy en service. Kubernetes
traite toujours les mêmes problèmes.
Une demande de fonctionnalité possible de mon point de vue pour swarm serait de
rendre le fournisseur de réseau enfichable. Cela permettrait d'utiliser
autres techniques que lvs/iptables

Sandeep Srinivasa [email protected] schrieb am Fr., 4. Jan. 2019,
13h05 :

La solution ci-dessus nécessite une liaison en mode hôte. C'est le gros problème. Ce
élimine la possibilité d'utiliser le planificateur de docker pour allouer des conteneurs
à différents hôtes - je ne fais plus partie du réseau maillé.

Le vendredi 4 janvier 2019, 17:28 rubot < [email protected] a écrit :

Comme je l'ai dit, vérifiez la solution de flux tcp ci-dessus, qui utilise déjà le proxy
protocole.
L'ajout d'un protocole proxy nécessiterait également une configuration à l'intérieur du conteneur
si
ajouté à l'essaim en amont. Je ne vois aucune valeur, à part un nettoyant et peut-être
meilleur
objectif documenté dans votre demande

Sandeep Srinivasa [email protected] schrieb am Fr., 4. Jan.
2019,
11h37 :

Ce sont des solutions complexes - le protocole proxy ne fait qu'ajouter
entête
informations et est une norme très connue - haproxy, nginx, AWS
elbe,
etc. tous le suivent.
https://www.haproxy.com/blog/haproxy/proxy-protocol/

La superficie du changement serait limitée au Swarm construit en
ingress (où ce support serait ajouté). Et tous les services auront
ce
disponible.

Le vendredi 4 janvier 2019, 14:36 ​​rubot < [email protected] a écrit :

Vous pouvez même étendre le projet dockerflow et ajouter une variante nginx à
début
kubernetes-ingressproxy pour swarn. Certainement tout cela emballé avec
essaim
soulèverait un conteneur système supplémentaire car vous savez qu'il y a un tas
de
eux avec kubernetes. N'est-ce pas la force de l'essaim pour slim
Ressource
projets d'être lean?

Ruben Nicolaides [email protected] schrieb am Fr., 4. Jan. 2019,
09h48 :

Je suis toujours un peu surpris de savoir pourquoi les gens pensent que c'est un bug. De
ma
perspective, même la déclaration de passage à kubernetes n'est pas un
adéquat
réponse. Comme je vois, kubernetes a exactement le même problème/comportement.
Tu
Soit
avoir un LB externe, ou utiliser quelque chose comme le proxy d'entrée nginx
lequel
doit
exécuter en tant que daemonset. Veuillez me corriger si je me trompe, mais nous avons le
même
situation exacte ici, mais pas de solution automatique préparée ici. Quelqu'un
pourrait
vérifier et emballer ma solution de flux tcp proposée décrite ci-dessus pour
avoir
quelque chose comme le comportement du proxy nginx. Accepte juste, cet essaim a besoin
à
être
personnalisé par vous-même

PanJ [email protected] schrieb am Fr., 4. Jan. 2019,
09h28 :

@BretFisher https://github.com/BretFisher le mode : l'hôte est
seul
une
solution de contournement mais pas la solution. Comme @sandys <
https://github.com/sandys>
dit que la solution de contournement comporte quelques mises en garde, nous ne devrions pas considérer
cette
problème
comme fixe.

Je ne sais pas s'il y a une amélioration puisque la solution de contournement a
été
découvert. J'ai déménagé chez Kubernetes depuis assez longtemps et
toujours
être
surpris que la question soit toujours ouverte depuis plus de deux ans.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
< https://github.com/moby/moby/issues/25526#issuecomment -451382365
,
ou
muet
le fil
<

https://github.com/notifications/unsubscribe-auth/AAPgu40OJ-uNKORD-LAD12m1lafxzMiSks5u_xCcgaJpZM4Jf2WK

>

.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451389574 ,
ou
muet
le fil
<

https://github.com/notifications/unsubscribe-auth/AAEsU2FCEGFs5v6IOEy6AqjcBMl7IqEiks5u_xmTgaJpZM4Jf2WK

>

.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451409453 , ou
muet
le fil
<

https://github.com/notifications/unsubscribe-auth/AAPgu83fSrSzfopOlDXsDooN1tMboGZaks5u_y8EgaJpZM4Jf2WK
>

.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451424992 , ou
muet
le fil
<
https://github.com/notifications/unsubscribe-auth/AAEsU-q-I3fXVAP9JcGgTdJJOzI7b575ks5u_0HIgaJpZM4Jf2WK

.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451426276 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAPguw88UN68sw_TNTunZpuAGqgvexxMks5u_0NxgaJpZM4Jf2WK
.

Et juste pour clarifier, la solution ci-dessus a tcp stream devant service
Procuration. Ainsi, votre demande n'est certainement pas un bug, mais une demande de fonctionnalité. Et
cette fonctionnalité ne pourrait être implémentée que dans swarm, si le mode réseau
changer, car le problème principal reste la perte d'ip au niveau Nat/host

Ruben Nicolaides [email protected] schrieb am Fr., 4. Jan. 2019, 13:11:

Comme je l'ai dit, l'entrée kubernetes nginx a également besoin d'une liaison en mode hôte, appelée
ensemble de démons. LB externe se connecte aux nodeports, qui nécessitent également le mode hôte
en service, ou configurer manuellement le protocole proxy en service. Kubernetes
traite toujours les mêmes problèmes.
Une demande de fonctionnalité possible de mon point de vue pour swarm serait de
rendre le fournisseur de réseau enfichable. Cela permettrait d'utiliser
autres techniques que lvs/iptables

Sandeep Srinivasa [email protected] schrieb am Fr., 4. Jan.
2019, 13:05 :

La solution ci-dessus nécessite une liaison en mode hôte. C'est le gros problème. Ce
élimine la possibilité d'utiliser le planificateur docker pour allouer
conteneurs
à différents hôtes - je ne fais plus partie du réseau maillé.

Le vendredi 4 janvier 2019, 17:28 rubot < [email protected] a écrit :

Comme je l'ai dit, vérifiez la solution de flux tcp ci-dessus, qui utilise déjà le proxy
protocole.
L'ajout d'un protocole proxy nécessiterait également une configuration à l'intérieur du conteneur
si
ajouté à l'essaim en amont. Je ne vois aucune valeur, à part un nettoyant et peut-être
meilleur
objectif documenté dans votre demande

Sandeep Srinivasa [email protected] schrieb am Fr., 4. Jan.
2019,
11h37 :

Ce sont des solutions complexes - le protocole proxy ne fait qu'ajouter
entête
informations et est une norme très connue - haproxy, nginx, AWS
elbe,
etc. tous le suivent.
https://www.haproxy.com/blog/haproxy/proxy-protocol/

La superficie du changement serait limitée au Swarm construit en
ingress (où ce support serait ajouté). Et tous les services seront
ont
ce
disponible.

Le vendredi 4 janvier 2019, 14:36 ​​rubot < [email protected] a écrit :

Vous pouvez même étendre le projet dockerflow et ajouter une variante nginx à
début
kubernetes-ingressproxy pour swarn. Certainement tout cela emballé avec
essaim
soulèverait un conteneur système supplémentaire car vous savez qu'il existe un
groupe
de
eux avec kubernetes. N'est-ce pas la force de l'essaim pour slim
Ressource
projets d'être lean?

Ruben Nicolaides [email protected] schrieb am Fr., 4. Jan. 2019,
09h48 :

Je suis toujours un peu surpris de savoir pourquoi les gens pensent que c'est un bug. De
ma
perspective, même la déclaration de passage à kubernetes n'est pas un
adéquat
réponse. Comme je vois, kubernetes a exactement le même problème/comportement.
Tu
Soit
avoir un LB externe, ou utiliser quelque chose comme le proxy d'entrée nginx
lequel
doit
exécuter en tant que daemonset. Veuillez me corriger si je me trompe, mais nous avons le
même
situation exacte ici, mais pas de solution automatique préparée ici. Quelqu'un
pourrait
vérifier et emballer ma solution de flux tcp proposée décrite ci-dessus pour
avoir
quelque chose comme le comportement du proxy nginx. Accepte juste, cet essaim
a besoin de
être
personnalisé par vous-même

PanJ [email protected] schrieb am Fr., 4. Jan. 2019,
09h28 :

@BretFisher https://github.com/BretFisher le mode : l'hôte est
seul
une
solution de contournement mais pas la solution. Comme @sandys <
https://github.com/sandys>
dit que la solution de contournement comporte quelques mises en garde, nous ne devrions pas considérer
cette
problème
comme fixe.

Je ne sais pas s'il y a une amélioration puisque la solution de contournement a
été
découvert. J'ai déménagé chez Kubernetes depuis assez longtemps et
toujours
être
surpris que la question soit toujours ouverte depuis plus de deux ans.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
<
https://github.com/moby/moby/issues/25526#issuecomment-451382365>,
ou
muet
le fil
<

https://github.com/notifications/unsubscribe-auth/AAPgu40OJ-uNKORD-LAD12m1lafxzMiSks5u_xCcgaJpZM4Jf2WK

>

.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451389574 ,
ou
muet
le fil
<

https://github.com/notifications/unsubscribe-auth/AAEsU2FCEGFs5v6IOEy6AqjcBMl7IqEiks5u_xmTgaJpZM4Jf2WK

>

.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451409453 ,
ou
muet
le fil
<

https://github.com/notifications/unsubscribe-auth/AAPgu83fSrSzfopOlDXsDooN1tMboGZaks5u_y8EgaJpZM4Jf2WK
>

.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451424992 , ou
muet
le fil
<
https://github.com/notifications/unsubscribe-auth/AAEsU-q-I3fXVAP9JcGgTdJJOzI7b575ks5u_0HIgaJpZM4Jf2WK

.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-451426276 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAPguw88UN68sw_TNTunZpuAGqgvexxMks5u_0NxgaJpZM4Jf2WK
.

  1. après un si long fil, j'essayais de documenter l'ensemble de fonctionnalités actuel avec un exemple complet.
  2. Je ne vois pas votre besoin spécifique dans la demande du PO. @PanJ a demandé à voir les adresses IP des clients emploi , ce que vous pouvez faire à partir de la mi-2018. Je ne les vois pas exiger qu'il utilise également un maillage de routage d'entrée.

Que vous l'appeliez un bug ou une demande de fonctionnalité, le maillage d'entrée sans source nat est (à mon avis) essentiel. Il existe de nombreuses applications qui se cassent lorsqu'elles ne peuvent pas voir la véritable adresse IP source. Bien sûr, dans le cas des serveurs Web, vous pouvez inverser le proxy à l'aide d'un nœud hôte et ajouter des en-têtes IP client. Cependant, cela ajoute une surcharge et n'est probablement pas une option pour les applications non basées sur le Web. Avec une application qui a réellement besoin que l'adresse IP source réelle sur le paquet soit correcte, la seule option est de ne pas utiliser de maillage d'entrée. Cela jette une grande partie des avantages de l'utilisation de swarm en premier lieu.

S'il vous plaît laissez-nous savoir quand ce problème a été résolu ou non ?!
devrions-nous utiliser kuberneties à la place ?

J'ai rencontré le même problème... je n'ai pas trouvé de solution pour le moment.

Lorsque quelqu'un trouve une solution à ce comportement, veuillez le signaler ici.

Merci!

J'ai le même problème. J'ai un serveur httpd apache et je souhaite enregistrer tous les accès afin d'extraire des statistiques plus tard sur les pays de quels pays nous recevons des demandes.

Je suis moi-même tombé sur ce problème en essayant de comprendre pourquoi php:apache n'enregistrait pas correctement le champ d'en-tête de l'hôte. Je suis choqué et déçu que cela ne fonctionne pas encore après toutes ces années. Comment sommes-nous censés utiliser le mode Swarm pour l'hébergement Web lorsque le champ hôte continue d'enregistrer l'adresse IP du proxy de l'espace utilisateur ? Je n'ai pas réussi à trouver un moyen de contourner cela avec le mode Swarm. Je suppose que je pourrais utiliser Classic Swarm (basé sur des conteneurs) et quelque chose comme Consul, mais j'ai l'impression que cela va à l'envers.

J'ai trouvé une solution acceptable pour mon scénario :

services:
  server:
    image: httpd:2
    deploy:
      mode: global
    ports:
      - target: 80
        published: 80
        protocol: tcp
        mode: host
      - target: 443
        published: 443
        protocol: tcp
        mode: host
    networks:
      - my_second_service
      - another_great_software

Cela amènera Apache à écouter sur l'ordinateur hôte au lieu de derrière le réseau de superposition (en lisant l'adresse IP distante appropriée), tout en continuant de transmettre les requêtes à d'autres services via les options networks et d'obtenir une "haute disponibilité" en l'ayant courir partout

@rafaelsierra - voici le problème que j'ai avec cela (et corrigez-moi si je me trompe), mais cette configuration ne permet qu'un seul conteneur Apache/PHP de s'exécuter et de se lier au port 80 sur le nœud hôte. Je dois exécuter de nombreux conteneurs Apache avec un conteneur Nginx lié au port 80/443, puis les héberger.

@SysEngDan oui, il est vrai que vous ne pouvez avoir qu'un seul conteneur lié aux ports 80/443, mais dans mon cas, ce n'est pas un problème car le conteneur qui se lie à ce port n'est responsable que de la transmission par proxy de toutes les demandes vers d'autres conteneurs qui s'exécutent derrière le réseau superposé.

Vous pouvez probablement utiliser la même solution en ayant un seul conteneur nginx/apache recevant toutes les requêtes et se rendant au conteneur approprié en fonction du vhost, et ces conteneurs n'ont pas à se lier à l'hôte

@rafaelsierra - Respectueusement, je ne sais pas si vous comprenez le problème documenté dans ce ticket. Si je configure des services comme vous l'avez mentionné dans votre dernier paragraphe, le problème est que l'adresse IP du client n'est pas transmise aux conteneurs qui n'écoutent que dans le réseau superposé. Si je me lie directement à l'hôte, ce n'est pas un problème. Si nous comptons sur le proxy du réseau Docker de l'externe (hôte) à l'interne (superposition), le conteneur Apache de destination ne recevra pas l'adresse IP du client d'origine mais à la place l'IP du proxy (du réseau Docker).

@SysEngDan Je comprends le problème, et comme il n'y a pas de solution au cours des 2 dernières années (et je ne sais honnêtement pas si cela est "réparable"), j'ai dû trouver une solution alternative qui corresponde à mes besoins (restreindre l'accès basé sur l'adresse IP distante).

Avoir un seul conteneur à l'écoute sur le port 80/443 sur l'hôte, puis se connecter à d'autres conteneurs (avec des en-têtes HTTP appropriés que je n'ai pas mentionnés car hors de la portée de ce problème) a résolu mon problème, et je voulais partager cette solution pour les personnes confrontées à un problème similaire en raison de l'impossibilité de transmettre l'adresse IP distante aux réseaux superposés

Oh je vois ce que tu as fait là... désolé, j'ai raté ça. Vous découpez le réseau de superposition et attachez à la place votre conteneur externe directement au réseau de service (celui qui est créé automatiquement lorsque vous démarrez un nouveau service sans spécifier de réseau). Ok, je pense que ça marche. La surcharge ajoutée est la tâche d'ajouter le réseau de service au fichier docker-compose. Je me demande ce qui se passe lorsque l'hôte-conteneur démarre et qu'un de ces services n'est pas disponible ?

Dans ce cas, vous obtiendrez un 502.

Je n'ai pas un seul docker-compose.yml, j'ai plusieurs piles avec plusieurs services qui se parlent via un réseau superposé, puis j'ai le service public qui est lié au serveur hôte mais qui a toujours accès au tous les autres réseaux superposés afin qu'il puisse proxy toutes les demandes.

La solution de contournement en mode hôte a déjà été discutée plusieurs fois sur ce problème. Bien que cela puisse convenir pour certains scénarios limités (tels que certaines configurations de trafic Web de proxy inverse), ce n'est pas une solution générale à ce problème. Veuillez lire les messages précédents plutôt que de ressasser les mêmes "solutions".

@darrellenns il y a plus de 200 commentaires ici, je pense qu'il serait préférable de verrouiller et de nettoyer ce problème en fournissant la solution de base "utilisez simplement la liaison de l'hôte si cela vous concerne" alors qu'aucune solution officielle n'est fournie, sinon plus de gens comme moi manqueront ça et continue de commenter les mêmes choses encore et encore

Donc, je pense que ce bogue affecte la capacité de traefiks à ajouter des ips à la liste blanche. Est-ce exact?

Quoi qu'il en soit, pour quiconque cherche à exécuter le mode essaim, voici un exemple d'utilisation du mode hôte pour publier des ports.

docker service create \
--name traefik \
--constraint=node.role==manager \
--publish mode=host,target=80,published=80 \
--publish mode=host,target=443,published=443 \
--mount type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock \
--mount type=bind,source=/home/$USER/dev-ops/logs,target=/dev-ops/logs \
--mount type=bind,source=/opt/data/traefik/traefik.toml,target=/traefik.toml \
--mount type=bind,source=/opt/data/traefik/acme.json,target=/acme.json \
--network traefik \
--label traefik.frontend.rule=Host:traefik.example.com \
--label traefik.port=8080 \
traefik \
--docker \
--docker.swarmMode \
--docker.watch \
--docker.exposedByDefault

@coltenkrauter Je ne sais pas exactement ce que cela affecte, mais en mode hôte, je ne peux exécuter qu'une seule réplique du service traefik, et je ne pense pas que ce soit juste moi. De cette façon, je dois faire entièrement confiance à la stabilité de traefik sans relayer la fonction de mode essaim pour les services.

De plus, comme indiqué pour la première fois, cela n'a pas tant à voir avec les besoins spéciaux de traefik, il a été testé avec un service http générique qui ne reçoit pas l'adresse IP d'origine, ce qui signifie que le mode docker swarm est cassé (cette fonctionnalité importante est manquante), et il semble que personne ne s'en soucie.

Et je veux continuer à commenter ce truc, car j'espère que le bruit dérange quelqu'un qui préférerait le réparer :) (désolé, cela s'applique à moi de la part de mes utilisateurs)

en mode hôte, je ne peux exécuter qu'une seule réplique du service traefik, et je ne pense pas que ce soit juste moi. De cette façon, je dois faire entièrement confiance à la stabilité de traefik sans relayer la fonction de mode essaim pour les services.

Vous pouvez exécuter une instance par hôte

en mode hôte, je ne peux exécuter qu'une seule réplique du service traefik, et je ne pense pas que ce soit juste moi. De cette façon, je dois faire entièrement confiance à la stabilité de traefik sans relayer la fonction de mode essaim pour les services.

Vous pouvez exécuter une instance par hôte

oui, mais traefik est obligé de travailler sur le nœud du gestionnaire, car il en a besoin pour fonctionner correctement. Donc, un nœud de gestionnaire, un hôte, une instance

traefik peut fonctionner à partir des nœuds de gestionnaire de plusieurs manières, y compris en utilisant un
proxy socket docker, socket distant ou entreprise traefik. voici un
exemple de fichier de pile pour savoir comment procéder :
https://github.com/BretFisher/dogvscat/blob/master/stack-proxy-global.yml

Le sam. 16 mars 2019 à 17h25 Daniele Cruciani [email protected]
a écrit:

en mode hôte, je ne peux exécuter qu'une seule réplique du service traefik, et je ne
pense que c'est juste moi. De cette façon, je dois faire entièrement confiance à la stabilité de traefik
sans relais sur la fonction de mode essaim pour les services.

Vous pouvez exécuter une instance par hôte

oui, mais traefik est obligé de travailler sur le nœud du gestionnaire, car il en a besoin
pour fonctionner correctement. Donc, un nœud de gestionnaire, un hôte, une instance

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-473593956 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAwW31DHIwEJE1EqN3-8qj44WopocuQTks5vXWE_gaJpZM4Jf2WK
.

Il est intéressant de le savoir, mais voyez, cette fonctionnalité est disponible sur kubernetes mais pas en mode docker swarm, et vous insistez sur le fait qu'il existe des options pour exécuter plusieurs instances de traefik, mais dans plusieurs nœuds, si je veux exécuter plusieurs instances dans un seul nœud, ce n'est pas possible, car ce n'est pas pris en charge.
De plus, tout autre service, qui ne se limite pas aux requêtes proxy, n'est autorisé à mapper aucun port, car il nécessite un type de configuration spécial qui doit y mapper chaque hôte, et de toute façon, il a besoin de plusieurs nœuds, au moins un par instance. .

Ainsi de suite. Vous pouvez faire défiler cette discussion vers le haut et en trouver d'autres à ce sujet. Je ne pense pas que cela puisse être réduit à une démonstration de la qualité de votre solution de contournement, car celle-ci reste une solution de contournement difficile à maintenir et à suivre. Et tout le temps passé à maintenir une solution de contournement de cas spécial est mieux utilisé pour résoudre le problème.

Par contre, si ce genre de fonctionnalité est un problème de sécurité pour le modèle de docker swarm, il suffit de le marquer comme wontfix et j'envisage de passer à kubernetes, si c'est le cas, je ne pense pas qu'il y ait de conflit entre projets, c'est juste dire explicitement que cela n'arriverait jamais, et donc tout le monde peut agir, si possible avant le choix du mode docker swarm pour tout type d'essaim de nœuds

Il y a beaucoup de fonctionnalités dans kubernetes qui ne sont pas dans swarm, et vice versa. Nous prenons tous des décisions sur l'orchestrateur à utiliser pour une solution spécifique en fonction de nombreux facteurs, y compris les fonctionnalités. Aucun outil ne résout tous les problèmes/besoins.

Je suis juste un membre de la communauté qui essaie d'aider. Si vous n'aimez pas les solutions actuelles à ce problème, il semble que vous devriez chercher d'autres moyens de le résoudre, éventuellement avec quelque chose comme kubernetes. C'est une raison raisonnable de choisir un orchestrateur plutôt qu'un autre si vous pensez que la façon dont kubernetes le résout vous convient davantage.

Historiquement, les mainteneurs de moby et swarm ne résolvent pas les problèmes comme celui-ci car demain quelqu'un de la communauté pourrait laisser tomber un PR avec une solution à ce problème. De plus, je pense que discuter des moyens de contourner cela jusque-là est une utilisation valable de ce fil de discussion. :)

Bien que n'étant pas un mainteneur d'essaim, je peux dire qu'historiquement, l'équipe ne divulgue pas les futurs plans de fonctionnalités au-delà des PR que vous pouvez actuellement voir obtenir des commits dans les dépôts.

J'ai oublié de dire que bien sûr votre commentaire est le bienvenu (ou je l'ai dit de manière obscure, désolé). Mais j'aime renforcer le rapport original de @PanJ :

En attendant, je pense que je dois faire une solution de contournement qui exécute un conteneur proxy en dehors du mode swarm et le laisse passer au port publié en mode swarm (la terminaison SSL doit également être effectuée sur ce conteneur), ce qui brise le but de swarm mode d'auto-guérison et d'orchestration.

Je veux dire que cela "casse le but du mode essaim", bien sûr uniquement sur ce sujet spécifique, est suffisant pour mériter plus d'attention.

J'essaie de faire en sorte que mon équipe crée un PR qui ajoute le protocole proxy à
le réseau d'entrée. On n'est pas des programmeurs de Golang, donc on trouve ça un peu
rusé.

Mais j'espère ardemment que l'équipe Docker conviendra que le meilleur et le plus
la solution compatible (à travers l'écosystème) consiste à superposer le protocole proxy
prise en charge du réseau d'entrée.

La complexité vient du fait que le réseau d'entrée doit non seulement
injecter ses propres en-têtes, mais il doit prendre en charge le fait qu'il pourrait y avoir
en-têtes de protocole proxy en amont déjà insérés (par exemple Google LB ou
AWS ELB).

Le dimanche 17 mars 2019, 12:17 Daniele Cruciani, [email protected]
a écrit:

J'ai oublié de dire que bien sûr votre commentaire est le bienvenu (ou je l'ai dit dans un
manière obscure, désolé). Mais j'aime renforcer l'original @PanJ
https://github.com/PanJ rapport :

En attendant, je pense que je dois faire une solution de contournement qui exécute un
conteneur proxy en dehors du mode essaim et laissez-le transférer vers le port publié
en mode essaim (la terminaison SSL doit également être effectuée sur ce conteneur), ce qui
brise le but du mode essaim pour l'auto-guérison et l'orchestration.

Je veux dire que cela "casse le but du mode essaim", bien sûr uniquement sur ce
sujet spécifique, est suffisant pour mériter plus d'attention.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-473621667 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsUwNWJsGKlLejcNzS2pR0awBB4OVlks5vXeTugaJpZM4Jf2WK
.

https://stackoverflow.com/questions/50585616/kubernetes-metallb-traefik-how-to-get-real-client-ip
Comme demandé pour les k8 où il est superposé, complètement et configurable

Pour toute personne exécutant nginx sur digitalocean avec docker swarm et essayant d'obtenir le vrai $remote_addr au lieu de seulement 10.255.0.2 dans vos journaux nginx ; vous pouvez utiliser la solution de @coltenkrauter. Le hic, c'est que vous ne pouvez exécuter qu'un seul conteneur nginx sur l'hôte avec cette solution, ce qui devrait convenir à la plupart des gens.

Modifiez simplement votre fichier docker-compose.yml :

INCORRECT

services:
  nginx:
    ports:
      - "80:80"
      - "443:443"

CORRECT

services:
  nginx:
    ports:
      - target: 80
        published: 80
        mode: host
      - target: 443
        published: 443
        mode: host

_edit : maintenant nous sommes tous assurés d'avoir la bonne réponse_

Ne pas utiliser d'entrée ( mode: host ) n'est pas une solution de contournement, lorsque le problème indique que le problème se produit avec le réseau d'entrée.
Personne n'utiliserait un seul hôte comme proxy inverse. Vous voulez plusieurs hôtes avec une adresse IP flottante, et le swarm-mesh est obligatoire pour réaliser cette configuration.

Ce n'est peut-être pas possible, mais j'ai pensé que modifier les règles iptables pour faire MASQUERADE à un moment donné dans les chaînes INGRESS serait une solution de contournement afin de préserver la véritable adresse IP source. N'y a-t-il pas des experts en iptables/netfilter ?

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy DROP)
target     prot opt source               destination         
DOCKER-USER  all  --  anywhere             anywhere            
DOCKER-INGRESS  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-1  all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
DOCKER     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
ACCEPT     all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere            

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain DOCKER (2 references)
target     prot opt source               destination         

Chain DOCKER-INGRESS (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target     prot opt source               destination         
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
DOCKER-ISOLATION-STAGE-2  all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-ISOLATION-STAGE-2 (2 references)
target     prot opt source               destination         
DROP       all  --  anywhere             anywhere            
DROP       all  --  anywhere             anywhere            
RETURN     all  --  anywhere             anywhere            

Chain DOCKER-USER (1 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            

Comme alternative, swarm ne peut-il pas simplement prendre l'adresse IP source d'origine et créer un en-tête X-Forwarded-For ?

Personne n'utiliserait un seul hôte comme proxy inverse. Vous voulez plusieurs hôtes avec une adresse IP flottante, et le swarm-mesh est obligatoire pour réaliser cette configuration.

Chaque nœud de l'essaim peut exécuter une instance du proxy inverse et acheminer le trafic vers les services sous-jacents via un réseau superposé (mais seul le proxy connaîtrait l'adresse IP d'origine).

Assurez-vous de lire tout le fil (je vois que GitHub cache quelques commentaires utiles, vous devrez donc les développer :disappointed:);

Comme alternative, swarm ne peut-il pas simplement prendre l'adresse IP source d'origine et créer un en-tête X-Forwarded-For ?

Voir https://github.com/moby/moby/issues/25526#issuecomment -367642600 ; X-Forwarded-For est le protocole L7 ; L'entrée de l'essaim est L4, en utilisant IPVS avec DNAT

@ port22 en général, nous convenons qu'une solution de contournement n'est pas une solution, une solution consiste à la rendre superposable, voir @sandys proposer sur le commentaire #25526

Comme alternative, vous ne pouvez pas swarm simplement prendre l'adresse IP source d'origine et créer

un en-tête X-Forwarded-For ?
Voir #25526 (commentaire)
https://github.com/moby/moby/issues/25526#issuecomment-367642600 ;
X-Forwarded-For est le protocole L7 ; L'entrée de l'essaim est L4, en utilisant IPVS avec DNAT

la bonne solution ici est le protocole proxy injecté à L4. il y a quelques
discussions pour et contre pertinentes dans Envoy pour le même cas d'utilisation
https://github.com/envoyproxy/envoy/issues/4128 et
https://github.com/envoyproxy/envoy/issues/1031

Le mer. 10 avril 2019 à 01h40 Sebastiaan van Stijn <
[email protected]> a écrit :

Personne n'utiliserait un seul hôte comme proxy inverse. Vous voulez plusieurs
hôtes avec une ip flottante, et le swarm-mesh est obligatoire pour y parvenir
mettre en place.

Chaque nœud de l'essaim peut exécuter une instance du proxy inverse et acheminer
trafic vers les services sous-jacents sur un réseau superposé (mais seul le
proxy connaîtrait l'adresse IP d'origine).

Assurez-vous de lire l'intégralité du fil (je vois que GitHub cache pas mal de choses utiles
commentaires, vous devrez donc les développer 😞);

Comme alternative, vous ne pouvez pas swarm simplement prendre l'adresse IP source d'origine et créer
un en-tête X-Forwarded-For ?

Voir #25526 (commentaire)
https://github.com/moby/moby/issues/25526#issuecomment-367642600 ;
X-Forwarded-For est le protocole L7 ; L'entrée de l'essaim est L4, en utilisant IPVS avec DNAT

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-481415217 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsU5KdnWQ21hJx_xzc-QROJiWbAlulks5vfPOigaJpZM4Jf2WK
.

Chaque nœud de l'essaim peut exécuter une instance du proxy inverse

Cela élimine la fonctionnalité de l'équilibreur de charge en essaim, qui est en fait le problème.
Et mon problème, pour être précis, est que traefik n'est pas agile en cluster. Il doit être exécuté de manière autonome, sauf si vous utilisez consul comme backend de configuration, ce qui limite alors le nombre maximal de certificats à ~ 100, ce qui ne m'est pas applicable. Bien sûr, vous pouvez affirmer qu'il ne s'agit pas d'un problème d'essaim mais du problème de traefik. Fait amusant : traefik déclare qu'il s'agit d'un problème de consul. le consul déclare: traefik le fait mal.

@ port22 en général, nous convenons qu'une solution de contournement n'est pas une solution

Ce que je veux dire, c'est que NE PAS utiliser d'entrée n'est pas une solution de contournement lorsque vous avez BESOIN d'une entrée. Une solution de contournement serait quelque chose qui permettrait de continuer à utiliser l'équilibreur de charge swarm tout en conservant l'adresse IP source, même si cela nécessite un piratage.

utiliser IPVS avec DNAT

donc je pensais que cela pouvait être fait avec MASQUERADE dans la règle/chaîne DNAT. ?

@ port22 J'ai compris, mais docker gère ses réseaux tout seul, j'ai essayé de le faire fonctionner avec shorewall, mais le seul moyen est de créer des exceptions pour les règles/chaînes docker, et je n'ai eu aucun succès avec le mode essaim docker (mais il est ok pour docker en mode essaim, dans la mesure où je désactive tous les services sauf ceux qui s'exécutent dans l'essaim)
Peut-être qu'il devrait y avoir des options comme il y en a pour le réseau de pont https://docs.docker.com/network/overlay/#customize -the-docker_gwbridge-interface
donc pour simplifier la configuration, mais le principal problème reste le support manquant dans le réseau de superposition. Les options ne sont donc pas là, car elles seraient ignorées et dockerd réécrira les règles si elles étaient modifiées de l'extérieur.

J'ai déposé une demande de fonctionnalité pour la prise en charge du protocole proxy pour résoudre le
problème dans ce bogue.

Juste au cas où quelqu'un voudrait ajouter ses commentaires.

https://github.com/moby/moby/issues/39465

Le mer. 10 avril 2019, 21:37 Daniele Cruciani, [email protected]
a écrit:

@ port22 https://github.com/port22 J'ai compris, mais docker manage
ses réseaux par lui-même, j'ai essayé de le faire fonctionner avec shorewall, mais le
le seul moyen est de créer des exceptions pour les règles/chaînes docker, et je n'avais pas
succès avec le mode essaim de docker (mais c'est ok pour docker en mode essaim, car
jusqu'à présent, je désactive tous les services sauf ceux qui s'exécutent dans l'essaim)
Peut-être qu'il devrait y avoir des options comme il y en a pour le réseau de pont
https://docs.docker.com/network/overlay/#customize -the-docker_gwbridge-interface
donc pour simplifier la configuration, mais le problème principal reste le
support manquant dans le réseau superposé. Il n'y a donc pas d'options, car
ceux-ci seraient ignorés et dockerd réécrira les règles si elles étaient modifiées à partir de
à l'extérieur.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526#issuecomment-481754635 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAEsUxsVQ7m9uiYbHhNKMMtkhTZV6iTNks5vfgwygaJpZM4Jf2WK
.

Après 3 ans, pas de solution ?

J'ai aussi le même problème mais avec haproxy. Bien qu'il soit acceptable d'avoir des serveurs proxy en mode hôte et HA utilisant keepalived, la seule partie manquante serait l'équilibrage de charge qui, à mon avis, n'est pas vraiment un problème pour un simple proxy Web. À moins que des scripts compliqués ne soient inclus ou que le proxy et le backend ne soient pas sur la même machine physique et que le trafic réseau soit trop élevé pour une seule carte réseau et...

Alors, n'est-il vraiment pas possible de voir l'adresse IP source d'une requête provenant de l'extérieur d'un Docker Swarm plutôt que l'adresse privée du réseau de superposition interne ? Toujours?

@thaJeztah Un membre de l'équipe Docker Inc peut-il nous

@thaJeztah https://github.com/thaJeztah Quelqu'un peut-il sur le Docker Inc
l'équipe nous tient au courant de l'état de ce problème. Est-il encore envisagé
et/ou travaillé dessus ? Un ETA ? Ou est-ce complètement ignoré depuis Docker
intégration avec Kubernetes ? Cela a été signalé il y a presque 3 ans :/

Ce serait vraiment bien d'obtenir cette déclaration ("ne corrigera pas") afin que je puisse pleinement
justifier une migration vers kubernetes. Quel dommage.

Merci.

>

Peut-être qu'ils répondront sur twitter ?

https://twitter.com/suretec/status/1160496779386904576?s=19

il y a une demande d'amélioration proposée qui devrait résoudre ce problème - https://github.com/moby/moby/issues/39465

s'il vous plaît ajoutez vos pensées et commentaires là-bas

J'ai déjà commenté ce problème :-)

Celui-ci a été un bloqueur pour moi pendant un certain temps. J'ai besoin de passer par les adresses IP et après de nombreuses recherches (wow presque 3 ans de recherche avec les autres dans ce fil ...) je n'ai pas encore trouvé de solution réalisable avec swarm.

Je n'ai pas pu utiliser swarm en production à cause de ce problème et j'attends une réponse officielle si cela peut être ajouté ou non. Si cela n'est pas ajouté, les solutions alternatives proposées sont les bienvenues.

Nous rencontrons le même problème en utilisant traefik derrière haproxy. J'ai été surpris de voir qu'il y a 254 commentaires depuis 2016.

@Betriebsrat Pourquoi ne pas autoriser traefik à traiter les demandes tout de suite ? L'happroxy est-il vraiment nécessaire, ou juste une habitude ? Si vous exposez traefik en mode hôte, vous verrez les adresses IP des clients, puis tout va bien :)

Je crois que cette "solution" a été mentionnée à plusieurs reprises, mais les gens continuent de la manquer.

Je sais aussi que ce n'est parfois pas une option, mais je pense que la plupart du temps, cela devrait être possible.

@ajardan cette solution que j'ai essayée et n'est pas viable pour moi car j'ai plus d'un hôte pour répondre sur le frontend. Idéalement, je veux que l'ensemble de l'essaim puisse acheminer les requêtes. Je conviens que pour les opérations à petite échelle, le simple fait de basculer un service en mode host et de l'utiliser comme serveur d'acquisition peut fonctionner correctement.

Placer quelque chose comme traefik en mode hôte annule les avantages dont nous essayons de tirer parti de l'utilisation de swarm, bien que dans la plupart des cas :(

Le mode hôte @pattonwebz peut être activé pour un service exécutant plusieurs conteneurs sur plusieurs hôtes, vous pouvez même le faire avec mode=global. Ensuite, traefik s'exécutera sur tous vos nœuds d'essaim et acceptera les connexions aux ports spécifiés, puis acheminera les demandes en interne vers les services qui ont besoin de voir ces connexions.

J'ai utilisé cette configuration avec un service en mode global mais limité aux nœuds de gestionnaire, et cela fonctionnait parfaitement bien pour des dizaines de milliers de requêtes/s

Je serais heureux d'élaborer si plus de détails sont nécessaires.

@pattonwebz @ajardan J'utilise un service haproxy configurable pour tous ces cas. haproxy utilise seulement 2 Mo de RAM dans mon cas. Je pense que c'est négligeable.

@pattonwebz En plus de la solution de https://hub.docker.com/r/decentralize/swarm-tcp-proxy en mode global avec la mise en réseau de l'hôte pour ajouter la prise en charge du protocole PROXY au trafic entrant, puis transférez-le à Traefik configuré pour décoder les en-têtes du protocole proxy.

Cela devrait juste être un drapeau dans le cadre de Docker Swarm proprement dit, pas tous ces
solutions alambiquées IMHO.

Nous utilisons simplement haproxy pour gérer les certificats et décharger SSL.
Les gens n'arrivent pas à comprendre que la solution "l'exécution est en mode hôte" n'est pas une solution.
Ils veulent qu'il fonctionne avec le réseau d'entrée pour tirer parti de l'équilibrage de charge Docker.
L'ensemble du fil est essentiellement un cercle 'utiliser hostmode' -> 'pas possible car "raisons"' qui dure depuis 3 ans maintenant.

Je considérerai à nouveau swarm-tcp-proxy comme une alternative viable, mais en regardant des choses similaires dans le passé, quelque chose s'est toujours avéré être un problème pour moi avec de telles idées.

Dans un monde parfait, mon essaim existant (et fonctionnant bien à l'exception de l'impossibilité de récupérer l'adresse IP réelle du client) fonctionnerait et passerait simplement les données IP sans avoir besoin de couches de service supplémentaires ou de plus de proxys sur des proxys.

Les gens n'arrivent pas à comprendre que la solution "l'exécution est en mode hôte" n'est pas une solution.

Ce n'est pas une solution en soi , mais peut être utilisé (et est utilisé) avec beaucoup de succès comme solution de contournement. Vous pouvez toujours utiliser l'équilibreur de charge natif de Docker - tout ce que vous faites est d'ajouter une couche à la pile réseau hôte avant d'atteindre le maillage de service de Docker.

@Betriebsrat traefik peut très bien faire des certificats et SSL, donc je ne sais toujours pas pourquoi c'est nécessaire.

Comme mentionné par @matthanley auparavant, l'équilibrage de charge docker ne disparaît pas. Si vous n'aimez pas la façon dont traefik équilibre vos demandes dans le backend, vous pouvez lui demander d'utiliser le LB de swarm, et il enverra simplement des demandes au service VIP, où swarm s'en occupera plus tard.

Ceci est configurable par service même, vous êtes donc assez flexible.

Vous pouvez essayer de définir un autre serveur Nginx en dehors du cluster docker swarm et transmettre la demande au service swarm. dans cette conf Niginx, ajoutez simplement les en-têtes avant. par exemple.
emplacement / {
proxy_pass http://phpestate;

    #Proxy Settings
    proxy_redirect     off;
    proxy_set_header   Host             $host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;

Il semble qu'il n'y ait pas de solution pour obtenir une véritable adresse IP client en mode essaim docker.

Nous avons vu le même problème et nous l'avons contourné en implémentant :
https://github.com/moby/moby/issues/25526#issuecomment-475083415

Ce n'est pas une solution idéale car nous ne pouvons pas exécuter plusieurs conteneurs d'entrée sur un seul nœud (je suppose qu'ils sont mondiaux maintenant)

La difficulté est que Docker traite en TCP/UDP, alors qu'il s'agit d'un problème de protocole HTTP. Au minimum, j'aimerais que docker "simule" l'adresse IP source en tant qu'hôte distant plutôt que de donner sa propre adresse IP interne à partir du Swarm Mesh... mais cela casserait probablement les choses car le trafic de retour irait au mauvais endroit.

Le moyen le plus simple serait d'ajouter l'en-tête de l'adresse IP d'origine pour chaque requête http.

Correct. Juste pour être précis - en tant qu'en-tête de protocole proxy qui fonctionne sur l4
et l7 et est accepté par la plupart des logiciels d'application connus (ainsi que le
grands fournisseurs de cloud).

J'ai déposé un bug séparé pour cela, qui est lié à quelques commentaires
dessus. Ajoutez à ce bug si vous êtes intéressé

Le jeu. 5 septembre 2019, 18:56 Vladimir, [email protected] a écrit :

Le moyen le plus simple serait d'ajouter l'en-tête de l'adresse IP d'origine pour chaque
requête http.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/25526?email_source=notifications&email_token=AAASYU7APUNJPLZ6AJ6XXMDQIECIJA5CNFSM4CL7MWFKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJZKTDN5WWOLA# ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AAASYU4VZGKUFLL5STZ44GDQIECIJANCNFSM4CL7MWFA
.

C'est 2019 et c'est toujours un problème ?? Cela rend la liste blanche des adresses IP sur traefik pénible. Je ne devrais pas avoir besoin de ports hôtes sur chaque nœud.

@kaysond notre position a été d'abandonner Swarm. Nous sommes passés à AWS et à ECS. Je suis juste désolé de ne pas pouvoir poster quelque chose de plus constructif mais finalement nous avons besoin de quelque chose qui fonctionne ; ce n'est pas le seul bug majeur de Swarm (ou le manque de fonctionnalité) qui nous affecte et d'autres n'ont reçu aucun correctif / retour apparent au cours des dernières années. Le plus décevant, mais là.

@jmkgreen, nous sommes dans la même position et avons passé les 6 derniers mois à passer de l'essaim de dockers à d'autres choses à cause de ce problème toujours en cours. J'ai déjà passé des dizaines d'heures moi-même et des centaines d'heures de temps de membre de l'équipe à cela sans jamais trouver une solution de contournement acceptable. La liaison à tous les ports hôtes va à l'encontre du but de nos LB flottants :(

Quel est votre problème avec la solution de contournement ? Vous déclarez votre service en mode hôte + global et configurez votre LB pour frapper tous les nœuds, cela fonctionne. Parce que le proxy est léger (j'utilise nginx parce que je fais du déchargement https et d'autres choses), le fait qu'il soit déployé sur chaque serveur n'est pas un problème, il utilise moins de 1% d'une ressource de serveur. Je peux vous aider si vous rencontrez une erreur durant le processus ([email protected]).

Quel est votre problème avec la solution de contournement ? Vous déclarez votre service en mode hôte + global et configurez votre LB pour frapper tous les nœuds, cela fonctionne.

@RemiBou Lorsque le proxy lui-même doit être mis à jour/redémarré, l'équilibreur de charge externe ne détecte pas immédiatement la panne et continue d'envoyer des demandes au(x) nœud(s) où le proxy redémarre toujours. Il y a donc une panne d'environ 30 secondes en fonction de la configuration LB externe.

Il n'y a également aucun moyen dans Swarm de mettre un crochet dans le processus de mise à jour du service pour appeler l'équilibreur de charge externe et mettre un nœud hors service pendant la mise à jour. Vous ne pouvez pas non plus déclencher l'exécution d'un script à l'intérieur du conteneur avant sa mise à jour (par exemple, pour supprimer un indicateur " i_am_healthy " et laisser le LB externe découvrir qu'il est hors service via une interrogation).

Quel est votre problème avec la solution de contournement ?

Mon problème est qu'avec cette solution de contournement, il m'est impossible d'exécuter plusieurs du même service (ou plusieurs services qui veulent les mêmes ports) sur l'hôte. C'est un besoin pour les projets sur lesquels je travaille.

En effet, mais ne pouvez-vous pas déployer un service proxy qui ne ferait que cela, puis lorsque l'IP est à l'intérieur de l'essaim. Vous pouvez le transmettre en tant qu'en-tête http à vos autres services ?

En effet, mais ne pouvez-vous pas déployer un service proxy qui ne ferait que cela, puis lorsque l'IP est à l'intérieur de l'essaim. Vous pouvez le transmettre en tant qu'en-tête http à vos autres services ?

Oui... et tant que ce service de proxy léger n'a jamais besoin d'être reconfiguré ou mis à jour, il est possible de mettre à jour les composants sous-jacents à l'aide de Swarm LB pour éviter les temps d'arrêt.

Quelqu'un a pointé vers https://hub.docker.com/r/decentralize/swarm-tcp-proxy qui utilise haproxy pour le faire.

Une sorte de douleur cependant. Et si vous devez mettre à jour le proxy, vous avez toujours des temps d'arrêt.

@ ms1111 Démarrage de l'image docker Nginx en quelques secondes, et si ce service ne gère que cette partie, vous n'aurez pas besoin de la mettre à jour souvent. À mon humble avis, l'inconvénient n'est pas si important, mais cela peut être différent dans votre cas

Quel est votre problème avec la solution de contournement ?

Dans notre cas, c'est la combinaison de cette solution de contournement avec l'impossibilité de lier un port exposé à l'hôte à une adresse IP spécifique. Au lieu de cela, tous les services internes qui ont besoin de l'adresse IP du vrai visiteur et prennent en charge le protocole PROXY ont leur port exposé sur 0.0.0.0 sur l'hôte, ce qui est moins qu'optimal.

Un autre est l'impact non négligeable des performances lorsque vous avez des centaines de nouvelles connexions par seconde - tous les ports exposés sont en fait des règles DNAT dans iptables qui nécessitent conntrack et ont d'autres problèmes (touche k8s aussi, mais Swarm a ceci niveau supplémentaire de NAT qui l'aggrave).

À Docker,

Se réveiller! Il y a un problème évident étant donné le nombre de personnes impliquées dans ce problème (il y en a d'autres avec la même cause). Tout ce que nous obtenons, ce sont des gens qui répètent encore et encore qu'il existe une solution de contournement, même s'il a été expliqué à plusieurs reprises pourquoi cette solution de contournement n'est pas une solution. Le mot même "solution de contournement" indique qu'il s'agit d'une chose temporaire qui sera résolue plus tard. Cela fait plus de 3 ans que le problème a été créé et pendant tout ce temps, la réponse est "il existe une solution de contournement".

À tous les utilisateurs de Swarm,

Soyons réalistes. La triste vérité est que personne, y compris Docker, ne se soucie vraiment de Swarm. Tout le monde est passé à k8s et il n'y a pas de "réel" investissement dans Swarm. Le projet est sous assistance respiratoire en attente de mort, alors ne vous attendez pas à ce que ce problème soit résolu. Soyez intelligent et passez aux k8.

Cette question semble être ignorée depuis trop longtemps. Cela ne semble jamais être mis en œuvre. Il suffit d'aller droit au but et d'utiliser des k8.

@leojonathanoh pouvez-vous s'il vous plaît expliquer comment les k8 résolvent-ils exactement ce problème particulier :) ?

Simple : protocole proxy

@ajatkj Comme dit. Ou, si cela n'est pas possible, alors un équilibreur de charge externe et externalTrafficPolicy: Local sur la ressource Service . C'est tout ce que je dirai ici. Et je me désabonne du fil.

Pourquoi les gens s'attendent-ils à ce que d'autres personnes fassent le travail à leur place ?

J'adorerais être le héros et m'occuper de ça, mais la réalité est que je travaille sur beaucoup d'autres choses et cela n'a aucun effet sur mon quotidien. Cela affecte-t-il votre quotidien ? Nous aimerions avoir de l'aide pour résoudre ce problème !

J'ai également examiné cela plusieurs fois et il ne semble vraiment pas qu'il existe un moyen de faire fonctionner cela avec IPVS NAT, ce que le routage magique en essaim utilise.

Je suis d'accord que k8s est beaucoup plus flexible ici. Si cela correspond mieux à vos besoins, utilisez-le.
Se plaindre que ce n'est pas corrigé, puis menacer de passer à k8s n'a vraiment pas sa place dans notre outil de suivi des problèmes et est généralement inutile.

Les gens aident avec les connaissances qu'ils ont. Tous n'ont pas les compétences nécessaires pour modifier le code eux-mêmes, ils créent donc des problèmes comme celui-ci pour aider à parvenir à un consensus sur le changement nécessaire.

Personne ici ne prétend que vous devez spécifiquement apporter les modifications, mais même sur les problèmes ouverts par @sandys à propos du protocole proxy, l'équipe de base s'est mise d'accord sur les modifications. Alors, comment quelqu'un peut-il travailler là-dessus s'il ne sait pas si le changement sera accepté ?

La meilleure façon est de faire une proposition, c'est-à-dire. à quoi pensez-vous que l'architecture ressemblera une fois le travail terminé. Qu'apporte-t-il ? Que perdons-nous ?

La meilleure façon est de faire une proposition, c'est-à-dire. à quoi pensez-vous que l'architecture ressemblera une fois le travail terminé. Qu'apporte-t-il ? Que perdons-nous ?

Déjà fait ici : #39465

essayez le réseau en mode hôte

Merci de lire tout le fil avant de commenter

"Utiliser le protocole proxy", bien qu'intéressant, ne précise pas ce que
des modifications doivent être apportées à la base de code.

C'est peut-être une question naïve, mais pourquoi est-il nécessaire de réécrire l'IP source pour commencer ? Le trafic ne serait-il pas renvoyé via la passerelle par défaut de l'interface de toute façon ? Même s'il est venu via l'équilibreur de charge swarm, la passerelle pourrait simplement le renvoyer via l'équilibreur de charge qui sait déjà d'où vient le trafic...

C'est peut-être une question naïve, mais pourquoi est-il nécessaire de réécrire l'IP source pour commencer ? Le trafic ne serait-il pas renvoyé via la passerelle par défaut de l'interface de toute façon ? Même s'il est venu via l'équilibreur de charge swarm, la passerelle pourrait simplement le renvoyer via l'équilibreur de charge qui sait déjà d'où vient le trafic...

Il est nécessaire de savoir de quelle IP provient la requête. Peut-être qu'un utilisateur spécifique veut limiter l'adresse IP, et vous ne pouvez pas le faire en dehors du service en cours d'exécution, c'est-à-dire que traefik ne connaît pas le contenu de la demande qui peut spécifier quel utilisateur la fait, il ne peut donc pas exclure un utilisateur et accepte autre basé uniquement sur ip (car la politique dans cet exemple est ip + request-content => allow/disallow).

Ou, plus souvent, juste pour la connexion de journalisation. Je dois facturer au client mon utilisation du service et je dois fournir sous forme de tableau : l'heure de la demande, la quantité de ressources, l'adresse IP source de la demande. Presque tous les services facturés fournissent ce type de rapport.

Je pense que vous avez mal compris ma question. Je comprends pourquoi les services voudraient voir la véritable adresse IP source. Je veux savoir pourquoi Docker le modifie avant qu'il n'atteigne un conteneur

Le 1er novembre 2019, à 01h47, à 01h47, Daniele Cruciani [email protected] a écrit :

C'est peut-être une question naïve, mais pourquoi est-il nécessaire de réécrire
l'ip source pour commencer ? Le trafic ne serait-il pas renvoyé via le
la passerelle par défaut de l'interface de toute façon? Même si c'est venu via la charge d'essaim
équilibreur, la passerelle pourrait simplement le renvoyer via l'équilibreur de charge qui
sait déjà d'où vient le trafic...

Il est nécessaire de savoir de quelle IP provient la requête. Peut-être un
utilisateur spécifique veut limiter l'adresse IP, et vous ne pouvez pas le faire en dehors de la
service en cours d'exécution, c'est-à-dire que traefik ne connaît pas le contenu de la demande
qui peut spécifier quel utilisateur le fait, il ne peut donc pas exclure certains
utilisateur et accepte d'autres basés uniquement sur l'adresse IP (parce que la politique de ce
l'exemple est ip + request-content => allow/disallow).

Ou, plus souvent, juste pour la connexion de journalisation. Je dois facturer le client
pour mon utilisation du service, et je dois fournir sous forme de tableau :
demande, quantité de ressource, IP source de la demande. Presque tous les services
facturés fournir ce type de rapport.

--
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail ou consultez-le sur GitHub :
https://github.com/moby/moby/issues/25526#issuecomment-548711563

@kaysond Pas un bon endroit pour demander.

Vous posez essentiellement deux questions,

  1. Comment IPVS fonctionne techniquement, et
  2. Pourquoi libnetwork a choisi IPVS pour commencer

Il est difficile de répondre aux deux de différentes manières.

Je me demande où est le meilleur endroit pour poser ces questions parce que je suis maintenant très intrigué de lire l'histoire de ces choix et comment tout cela fonctionne afin que je puisse avoir un peu plus de contexte ici.

@kaysond Pas un bon endroit pour demander.

Vous posez essentiellement deux questions,

  1. Comment IPVS fonctionne techniquement, et
  2. Pourquoi libnetwork a choisi IPVS pour commencer

Il est difficile de répondre aux deux de différentes manières.

toute mise à jour?

Je suis ce fil depuis un moment maintenant parce que je suis tombé sur le même problème, mais après avoir fait tourner quelques conteneurs whoami dans un essaim derrière traefik, j'ai vu que cela fonctionnait. Le problème, c'est que nous étions derrière Cloudflare et que nous devions faire suivre les en-têtes des FC. (oui nous utilisons ipvs et nos services sont répliqués en swarm).

Je viens de réessayer avec avec :

Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea838
 Built:             Wed Nov 13 07:29:52 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea838
  Built:            Wed Nov 13 07:28:22 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

et le docker suivant composent :

version: "3.3"

services:

  traefik:
    image: "traefik:v2.0.0-rc3"
    container_name: "traefik"
    command:
      #- "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.swarmMode=true"
      - "--providers.docker.endpoint=unix:///var/run/docker.sock"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  whoami:
    image: "containous/whoami"
    container_name: "simple-service"
    deploy:
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.whoami.rule=HostRegexp(`{any:.*}`)"
        - "traefik.http.routers.whoami.entrypoints=web"
        - "traefik.http.services.whoami.loadbalancer.server.port=80"

la sortie whoami était:

Hostname: 085c373eb06d
IP: 127.0.0.1
IP: 10.0.1.10
IP: 172.19.0.4
RemoteAddr: 10.0.1.11:51888
GET / HTTP/1.1
Host: testserver.nub.local
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5
Dnt: 1
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 10.0.0.2
X-Forwarded-Host: testserver.nub.local
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: ad14e372f6e9
X-Real-Ip: 10.0.0.2

Donc non. ça ne marche toujours pas

Par curiosité... un développeur peut-il m'indiquer le code qui gère le réseau en essaim ?

Je viens de réessayer avec avec :

Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea838
 Built:             Wed Nov 13 07:29:52 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea838
  Built:            Wed Nov 13 07:28:22 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

et le docker suivant composent :

version: "3.3"

services:

  traefik:
    image: "traefik:v2.0.0-rc3"
    container_name: "traefik"
    command:
      #- "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.swarmMode=true"
      - "--providers.docker.endpoint=unix:///var/run/docker.sock"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"

  whoami:
    image: "containous/whoami"
    container_name: "simple-service"
    deploy:
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.whoami.rule=HostRegexp(`{any:.*}`)"
        - "traefik.http.routers.whoami.entrypoints=web"
        - "traefik.http.services.whoami.loadbalancer.server.port=80"

la sortie whoami était:

Hostname: 085c373eb06d
IP: 127.0.0.1
IP: 10.0.1.10
IP: 172.19.0.4
RemoteAddr: 10.0.1.11:51888
GET / HTTP/1.1
Host: testserver.nub.local
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5
Dnt: 1
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 10.0.0.2
X-Forwarded-Host: testserver.nub.local
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: ad14e372f6e9
X-Real-Ip: 10.0.0.2

Donc non. ça ne marche toujours pas

vous pouvez utiliser traefik par mode hôte pour obtenir une véritable IP

ports:
      - target: 80
        published: 80
        mode: host
      - target: 443
        published: 443
        mode: host

toujours ouvert ?
2020-05-08

toujours ouvert ?
2020-05-08

Oui, toujours ouvert. Il y a des problèmes architecturaux notés dans le fil qui soulignent pourquoi cela ne peut pas être résolu aussi facilement qu'il semble qu'il devrait l'être en surface. À ce stade, il est probable que ces problèmes ne puissent probablement pas être surmontés.

Si vous avez besoin d'obtenir une véritable adresse IP d'utilisateur, certaines alternatives sont publiées dans le fil de discussion ici, ce qui peut convenir. Le mode HOST pour les services semble l'approche la plus simple, mais cela ne convient pas à certains qui ont besoin d'évolutivité sur des nœuds individuels.

Nous avons eu du succès en utilisant le protocole PROXY avec DigitalOcean LB -> Traefik -> Apache container. Le conteneur Apache a pu enregistrer les adresses IP réelles des utilisateurs accédant au service. Théoriquement, cela devrait fonctionner tant que toutes les couches proxy prennent en charge le protocole PROXY.

https://docs.traefik.io/v1.7/configuration/entrypoints/#proxyprotocol

Le service Traefik se trouve sur un réseau Docker nommé 'ingress', le service Apache a son propre réseau de pile mais fait également partie du réseau 'ingress' en tant qu'externe.

https://autoize.com/logging-client-ip-addresses-behind-a-proxy-with-docker/

2020 et toujours pas réparé, quelle traînée. semble être une caractéristique très importante

C'est très nécessaire. Mettre un peu d'hôte en mode n'est qu'un patch, parfois il faut faire tourner NGINX derrière le réseau (en fonction de l'utilisation et de la configuration). Veuillez corriger cela.

Je pense qu'une solution de contournement pour cela et pour qu'un essaim de docker s'exécute sans définir l'hôte consiste à obtenir l'adresse IP du côté client. ex. en utilisant js pour les clients Web et mobiles et n'acceptez que des sources fiables. ex. js -> get ip, le backend accepte uniquement les ips qui incluent un jeton utilisateur ou etc. L'ip peut être définie dans l'en-tête et chiffrée via https. par contre je ne connais pas les performances

@ Damidara16 c'est exactement ce que nous ne voulons pas faire. C'est vraiment peu sûr de faire ça. Vous pouvez le contourner comme vous le souhaitez.

Dommage que ce soit toujours un problème ouvert, malheureusement... il ne semble pas qu'il soit bientôt résolu

Dommage que ce soit toujours un problème ouvert, malheureusement... il ne semble pas qu'il soit bientôt résolu

Je pense qu'il sera bientôt fermé par le bot. Depuis que github a lancé cette fonctionnalité, de nombreux bugs peuvent être ignorés.

Dommage que ce soit toujours un problème ouvert, malheureusement... il ne semble pas qu'il soit bientôt résolu

Je pense qu'il sera bientôt fermé par le bot. Depuis que github a lancé cette fonctionnalité, de nombreux bugs peuvent être ignorés.

C'est la meilleure fonctionnalité pour les équipes pléthoriques des entreprises pour prendre le contrôle de la communauté.

Il y a très peu de chances que cela soit corrigé un jour. AFAIK, tout le monde considère que les k8 ont remporté la "course" et que l'essaim n'est pas nécessaire, mais je dirais que les deux peuvent coexister et être correctement utilisés en fonction des besoins et des compétences de l'équipe qui les utilise. essaim RIP :)

J'utilise un HAIP géré, mais vous pouvez utiliser autre chose devant l'essaim, un équilibreur de charge nginx autonome qui pointe vers les adresses IP de votre essaim.
https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/

Dans votre essaim, le proxy inverse a besoin de ceci :

server {
        listen 443 ssl proxy_protocol;
        location / {
        proxy_set_header   X-Real-IP $proxy_protocol_addr;  # this is the real IP address 

Si vous exécutez un essaim, vous aurez besoin d'un équilibreur de charge pour effectuer un round-robin des requêtes adressées à votre essaim (ou sticky, etc.).

Jusqu'à présent, cette décision architecturale peut sembler être une "pièce manquante", cependant, cela ajoute de la flexibilité en fournissant des options et en supprimant le besoin de désactiver la fonctionnalité intégrée pour la remplacer par quelque chose de plus adapté aux besoins de l'application.

Je pense avoir trouvé une solution de contournement à ce problème, avec la limitation _current_ selon laquelle les réplicas de conteneurs de services doivent tous être déployés sur un seul nœud, par exemple avec --constraint-add='node.hostname==mynode', ou avec un ensemble d'essaims constitués chacun d'un seul nœud.

Le problème

Le problème sous-jacent est causé par la règle SNAT dans la table iptables nat dans l'espace de noms ingress_sbox, qui fait que toutes les requêtes entrantes sont vues par les conteneurs pour avoir l'adresse IP du nœud dans le réseau d'entrée (par exemple 10.0.0.2, 10.0.0.3, . .., dans la configuration du réseau d'entrée par défaut), par exemple :

iptables -t nat -A POSTROUTING -d 10.0.0.0/24 -m ipvs --ipvs -j SNAT --to-source 10.0.0.2

Cependant, la suppression de cette règle SNAT signifie que même si les conteneurs reçoivent toujours des paquets entrants - provenant désormais de l'adresse IP source d'origine - les paquets sortants renvoyés à l'adresse IP source d'origine sont envoyés via la passerelle par défaut du conteneur, qui n'est pas sur le même réseau d'entrée mais sur le réseau docker_gwbridge (par exemple 172.31.0.1), et ces paquets sont alors perdus.

La solution de contournement

La solution de contournement comprend donc : 1. la suppression (en fait, l'inhibition) de cette règle SNAT dans l'espace de noms ingress_sbox ; et 2. créer une règle de routage de politique pour les conteneurs de service en essaim, qui force ces paquets sortants à retourner à l'adresse IP du réseau d'entrée du nœud à laquelle ils seraient retournés (par exemple 10.0.0.2) ; 3. automatiser l'ajout des règles de routage des politiques, de sorte que chaque nouveau conteneur de services les ait rapidement installés lors de la création.

  1. Pour inhiber la règle SNAT, nous créons une règle plus tôt dans le tableau qui empêche d'atteindre le SNAT habituel :
nsenter --net=/var/run/docker/netns/ingress_sbox iptables -t nat -I POSTROUTING -d $INGRESS_SUBNET -m ipvs --ipvs -j ACCEPT

(Nous procédons de cette façon, plutôt que de simplement supprimer la règle SNAT existante, car docker semble recréer la règle SNAT plusieurs fois au cours de la création d'un service. Cette approche remplace simplement cette règle, ce qui la rend plus résiliente).

  1. Pour créer la règle de routage de la stratégie de conteneur :
docker inspect -f '{{.State.Pid}}' <container-id>
nsenter -n -t $NID bash -c "ip route add table 1 default via 10.0.0.2 && ip rule add from 10.0.0.0/24 lookup 1 priority 32761"
  1. Enfin, en associant ce qui précède à docker event nous automatisons le processus de modification des règles SNAT, de surveillance des conteneurs nouvellement démarrés et d'ajout des règles de routage de politique, via ce script ingress-routing-daemon :
#!/bin/bash

# Ingress Routing Daemon
# Copyright © 2020 Struan Bartlett
# --------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person 
# obtaining a copy of this software and associated documentation files 
# (the "Software"), to deal in the Software without restriction, 
# including without limitation the rights to use, copy, modify, merge, 
# publish, distribute, sublicense, and/or sell copies of the Software, 
# and to permit persons to whom the Software is furnished to do so, 
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be 
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
# SOFTWARE.
# --------------------------------------------------------------------
# Workaround for https://github.com/moby/moby/issues/25526

echo "Ingress Routing Daemon starting ..."

read INGRESS_SUBNET INGRESS_DEFAULT_GATEWAY \
  < <(docker inspect ingress --format '{{(index .IPAM.Config 0).Subnet}} {{index (split (index .Containers "ingress-sbox").IPv4Address "/") 0}}')

echo INGRESS_SUBNET=$INGRESS_SUBNET
echo INGRESS_DEFAULT_GATEWAY=$INGRESS_DEFAULT_GATEWAY

# Add a rule ahead of the ingress network SNAT rule, that will cause the SNAT rule to be skipped.
echo "Adding ingress_sbox iptables nat rule: iptables -t nat -I POSTROUTING -d $INGRESS_SUBNET -m ipvs --ipvs -j ACCEPT"
while nsenter --net=/var/run/docker/netns/ingress_sbox iptables -t nat -D POSTROUTING -d 10.0.0.0/24 -m ipvs --ipvs -j ACCEPT; do true; done 2>/dev/null
nsenter --net=/var/run/docker/netns/ingress_sbox iptables -t nat -I POSTROUTING -d $INGRESS_SUBNET -m ipvs --ipvs -j ACCEPT

# Watch for container start events, and configure policy routing rules on each container
# to ensure return path traffic from incoming connections is routed back via the correct interface.
docker events \
  --format '{{.ID}} {{index .Actor.Attributes "com.docker.swarm.service.name"}}' \
  --filter 'event=start' \
  --filter 'type=container' | \
  while read ID SERVICE
  do
    if [ -n "$SERVICE" ]; then

      NID=$(docker inspect -f '{{.State.Pid}}' $ID)
      echo "Container ID=$ID, NID=$NID, SERVICE=$SERVICE started: applying policy route."
      nsenter -n -t $NID bash -c "ip route add table 1 default via $INGRESS_DEFAULT_GATEWAY && ip rule add from $INGRESS_SUBNET lookup 1 priority 32761"
    fi
  done

Désormais, lorsque les demandes arrivent aux ports publiés pour le nœud unique, ses conteneurs verront l'adresse IP d'origine de la machine effectuant la demande.

Usage

Exécutez le ingress-routing-daemon ci-dessus en tant que root sur _chacun_ de vos nœuds d'essaim _avant_ de créer votre service. (Si votre service est déjà créé, assurez-vous de le mettre à l'échelle à 0 avant de le réduire à un nombre positif de réplicas.) Le démon initialisera iptables, détectera quand docker crée de nouveaux conteneurs et appliquera de nouvelles règles de routage à chaque nouveau conteneur.

Tests, cas d'utilisation et limites

Ce qui précède a été testé à l'aide de plusieurs réplicas contraints à un seul nœud sur un service s'exécutant sur un essaim multi-nœuds.

Il a également été testé à l'aide de plusieurs nœuds, chacun avec un service par nœud distinct limité à ce nœud, mais cela s'accompagne de la limitation selon laquelle différents ports publiés doivent être utilisés pour chaque service par nœud. Cela pourrait quand même fonctionner pour certains cas d'utilisation.

La méthode devrait également fonctionner en utilisant plusieurs nœuds, si chacun était configuré comme un seul nœud dans son propre essaim. Cela comporte la limitation que les essaims docker ne peuvent plus être utilisés pour distribuer des conteneurs sur les nœuds, mais il pourrait toujours y avoir d'autres avantages d'administration à utiliser des services docker, tels que la réplique de conteneur et la gestion du cycle de vie.

Améliorer la solution de contournement pour traiter d'autres cas d'utilisation

Avec le développement ultérieur, cette méthode devrait être capable de s'adapter à plusieurs nœuds sans avoir besoin de services séparés par nœud ou de diviser l'essaim. Je peux penser à deux approches possibles : 1. Faire en sorte que Docker, ou un démon sur mesure, supprime toutes les adresses IP non locales de la table ipvsadm de chaque nœud. 2. Étendre les règles de routage de la politique pour permettre le routage des packages de sortie vers le nœud approprié.

Pour 1, nous pourrions interroger ipvsadm -S -n pour rechercher de nouvelles adresses IP ajoutées à n'importe quel service, vérifier si chacune est locale et supprimer celles qui ne le sont pas. Cela permettrait à chaque nœud de fonctionner comme un équilibreur de charge pour ses propres conteneurs au sein du service global, mais sans que les demandes atteignant un nœud puissent être transmises à un autre. Cela satisferait certainement mon propre cas d'utilisation, où nous avons notre propre équilibreur de charge IPVS assis devant un ensemble de serveurs, chacun exécutant une application Web, que nous aimerions remplacer par plusieurs instances conteneurisées à charge équilibrée de la même application , pour nous permettre de déployer des mises à jour sans perdre un serveur entier.

Pour 2, nous pourrions utiliser iptables pour attribuer un TOS par nœud dans l'iptable ingress_sbox de chaque nœud (par exemple à l'octet final de l'IP du réseau d'entrée du nœud) ; puis dans le conteneur, organisez pour mapper la valeur TOS à une marque de connexion, puis d'une marque de connexion à une marque de pare-feu pour les paquets sortants, et pour chaque marque de pare-feu, sélectionnez une table de routage différente qui achemine les paquets vers le nœud d'origine. Les règles pour cela seront un peu maladroites, mais j'imagine qu'elles devraient s'adapter parfaitement à 2-16 nœuds.

J'espère que ce qui précède vous sera utile. Je vais également essayer (2), et si je progresse, je publierai une autre mise à jour.

Vous trouverez ci-dessous une version améliorée du démon de routage d'entrée, ingress-routing-daemon-v2 , qui étend le modèle de règle de routage de politique pour permettre à chaque conteneur de rediriger ses paquets de sortie vers le bon nœud, sans avoir besoin de SNAT.

Le modèle amélioré

En plus d'inhiber la règle SNAT comme dans le modèle précédent, le nouveau modèle nécessite une règle iptables dans l'espace de noms ingress_sbox sur chaque nœud que vous avez l'intention d'utiliser comme point de terminaison d'équilibreur de charge IPVS (donc normalement vos nœuds de gestionnaire, ou un sous-ensemble de ceux-ci nœuds de gestionnaire), qui attribue une valeur TOS par nœud à tous les paquets destinés à n'importe quel nœud du réseau d'entrée. (Nous utilisons le dernier octet de l'adresse IP du réseau d'entrée du nœud.)

Comme la valeur TOS est stockée dans le paquet, elle peut être lue par le nœud de destination vers lequel la demande entrante a été dirigée, et le paquet a été envoyé.

Ensuite, dans le conteneur du nœud de destination, nous nous chargeons de mapper la valeur TOS sur tous les paquets entrants à une marque de connexion, en utilisant la même valeur.

Maintenant, étant donné que les paquets sortants sur la même connexion auront la même marque de connexion, nous mappons la marque de connexion sur tous les paquets sortants à une marque de pare-feu, en utilisant à nouveau la même valeur.

Enfin, un ensemble de règles de routage de politique sélectionne une table de routage différente, conçue pour acheminer les paquets sortants vers le nœud de point de terminaison d'équilibrage de charge requis, en fonction de la valeur de la marque de pare-feu.

Désormais, lorsque les demandes du client arrivent aux ports publiés pour n'importe quel nœud de l'essaim, le conteneur (que ce soit sur le même et/ou sur d'autres nœuds) vers lequel la demande est dirigée verra l'adresse IP d'origine du client faisant la demande, et pouvoir acheminer la réponse vers le nœud d'équilibrage de charge d'origine ; qui, à son tour, pourra acheminer la réponse vers le client.

Usage

Mise en place

Générez une valeur pour INGRESS_NODE_GATEWAY_IPS spécifique à votre essaim, en exécutant ingress-routing-daemon-v2 tant que root sur chacun des nœuds de votre essaim _que vous souhaitez utiliser comme point de terminaison d'équilibrage de charge_ (normalement, seul votre gestionnaire nœuds ou un sous-ensemble de vos nœuds de gestionnaire), en notant les valeurs affichées pour INGRESS_DEFAULT_GATEWAY . Vous ne devez le faire qu'une seule fois, ou chaque fois que vous ajoutez ou supprimez des nœuds. Votre INGRESS_NODE_GATEWAY_IPS devrait ressembler à 10.0.0.2 10.0.0.3 10.0.0.4 10.0.0.5 (selon le sous-réseau défini pour le réseau d'entrée et le nombre de nœuds).

Exécuter le démon

Exécutez INGRESS_NODE_GATEWAY_IPS="<Node Ingress IP List>" ingress-routing-daemon-v2 --install tant que root sur _chacun_ des nœuds de votre essaim (gestionnaires et travailleurs) _avant_ de créer votre service. (Si votre service est déjà créé, assurez-vous de le mettre à l'échelle à 0 avant de le réduire à un nombre positif de réplicas.) Le démon initialisera iptables, détectera quand docker crée de nouveaux conteneurs et appliquera de nouvelles règles de routage à chaque nouveau conteneur.

Si vous devez restreindre les activités du démon à un service particulier, modifiez alors [ -n "$SERVICE" ] en [ "$SERVICE" = "myservice" ] .

Désinstallation des règles iptables

Exécutez ingress-routing-daemon-v2 --uninstall sur chaque nœud.

Essai

Le script ingress-routing-daemon-v2 a été testé avec 8 répliques d'un service Web déployé sur un essaim à quatre nœuds.

Les demandes Curl pour le service, dirigées vers l'une des adresses IP de nœud de point de terminaison à équilibrage de charge spécifiées, ont renvoyé des réponses positives, et l'examen des journaux du conteneur a montré que l'application considérait les demandes entrantes comme provenant de l'adresse IP du client Curl.

Limites

Comme la valeur TOS peut stocker un nombre de 8 bits, ce modèle peut en principe prendre en charge jusqu'à 256 nœuds de point de terminaison d'équilibrage de charge.

Cependant, comme le modèle exige que chaque conteneur soit installé avec une règle mangle iptables + une règle de routage de politique + une table de routage de politique par nœud de point de terminaison de gestionnaire, il peut y avoir une dégradation des performances à mesure que le nombre de ces nœuds de point de terminaison augmente (bien que l'expérience suggère que cela soit peu susceptible d'être perceptible avec <= 16 nœuds de point de terminaison d'équilibrage de charge sur du matériel moderne).

Si vous ajoutez des nœuds de points de terminaison d'équilibreur de charge à votre essaim - ou si vous souhaitez commencer à utiliser des nœuds de gestionnaire existants comme points de terminaison d'équilibreur de charge - vous devrez faire preuve de prudence car les conteneurs existants ne pourront pas acheminer le trafic vers les nouveaux nœuds de point de terminaison. Essayez de redémarrer INGRESS_NODE_GATEWAY_IPS="<Node Ingress IP List>" ingress-routing-daemon-v2 avec la valeur mise à jour pour INGRESS_NODE_GATEWAY_IPS , puis effectuez une mise à jour progressive de tous les conteneurs, avant d'utiliser le nouveau point de terminaison d'équilibrage de charge.

Portée de l'intégration native de Docker

Je ne connais pas la base de code Docker, mais je ne vois rien de ce que ingress-routing-daemon-v2 fait qui ne puisse, en principe, être implémenté par Docker nativement, mais je laisserai cela à l'équipe Docker considérer, ou comme un exercice pour quelqu'un qui connaît le code Docker.

Le script du démon de routage d'entrée v2

Voici le nouveau script ingress-routing-daemon-v2 .

#!/bin/bash

# Ingress Routing Daemon v2
# Copyright © 2020 Struan Bartlett
# ----------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person 
# obtaining a copy of this software and associated documentation files 
# (the "Software"), to deal in the Software without restriction, 
# including without limitation the rights to use, copy, modify, merge, 
# publish, distribute, sublicense, and/or sell copies of the Software, 
# and to permit persons to whom the Software is furnished to do so, 
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be 
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
# SOFTWARE.
# ----------------------------------------------------------------------
# Workaround for https://github.com/moby/moby/issues/25526

if [ "$1" = "--install" ]; then
  INSTALL=1
elif [ "$1" = "--uninstall" ]; then
  INSTALL=0
else
  echo "Usage: $0 [--install|--uninstall]"
fi

echo
echo "  Dumping key variables..."

if [ "$INSTALL" = "1" ] && [ -z "$INGRESS_NODE_GATEWAY_IPS" ]; then
  echo "!!! ----------------------------------------------------------------------"
  echo "!!! WARNING: Using default INGRESS_NODE_GATEWAY_IPS"
  echo "!!! Please generate a list by noting the values shown"
  echo "!!! for INGRESS_DEFAULT_GATEWAY on each of your swarm nodes."
  echo "!!!"
  echo "!!! You only have to do this once, or whenever you add or remove nodes."
  echo "!!!"
  echo "!!! Then relaunch using:"
  echo "!!! INGRESS_NODE_GATEWAY_IPS=\"<Node Ingress IP List>\" $0 -x"
  echo "!!! ----------------------------------------------------------------------"
fi

read INGRESS_SUBNET INGRESS_DEFAULT_GATEWAY \
  < <(docker inspect ingress --format '{{(index .IPAM.Config 0).Subnet}} {{index (split (index .Containers "ingress-sbox").IPv4Address "/") 0}}')

echo "  - INGRESS_SUBNET=$INGRESS_SUBNET"
echo "  - INGRESS_DEFAULT_GATEWAY=$INGRESS_DEFAULT_GATEWAY"

# We need the final bytes of the IP addresses on the ingress network of every node
# i.e. We need the final byte of $INGRESS_DEFAULT_GATEWAY for every node in the swarm
# This shouldn't change except when nodes are added or removed from the swarm, so should be reasonably stable.
# You should configure this yourself, but for now let's assume we have 8 nodes with IPs in the INGRESS_SUBNET numbered x.x.x.2 ... x.x.x.9
if [ -z "$INGRESS_NODE_GATEWAY_IPS" ]; then
  INGRESS_NET=$(echo $INGRESS_DEFAULT_GATEWAY | cut -d'.' -f1,2,3)
  INGRESS_NODE_GATEWAY_IPS="$INGRESS_NET.2 $INGRESS_NET.3 $INGRESS_NET.4 $INGRESS_NET.5 $INGRESS_NET.6 $INGRESS_NET.7 $INGRESS_NET.8 $INGRESS_NET.9"
fi

echo "  - INGRESS_NODE_GATEWAY_IPS=\"$INGRESS_NODE_GATEWAY_IPS\""

# Create node ID from INGRESS_DEFAULT_GATEWAY final byte
NODE_ID=$(echo $INGRESS_DEFAULT_GATEWAY | cut -d'.' -f4)
echo "  - NODE_ID=$NODE_ID"

if [ -z "$INSTALL" ]; then
  echo
  echo "Ingress Routing Daemon v2 exiting."
  exit 0
fi

# Add a rule ahead of the ingress network SNAT rule, that will cause the SNAT rule to be skipped.
[ "$INSTALL" = "1" ] && echo "Adding ingress_sbox iptables nat rule: iptables -t nat -I POSTROUTING -d $INGRESS_SUBNET -m ipvs --ipvs -j ACCEPT"
while nsenter --net=/var/run/docker/netns/ingress_sbox iptables -t nat -D POSTROUTING -d 10.0.0.0/24 -m ipvs --ipvs -j ACCEPT; do true; done 2>/dev/null
[ "$INSTALL" = "1" ] && nsenter --net=/var/run/docker/netns/ingress_sbox iptables -t nat -I POSTROUTING -d $INGRESS_SUBNET -m ipvs --ipvs -j ACCEPT

# 1. Set TOS to NODE_ID in all outgoing packets to INGRESS_SUBNET
[ "$INSTALL" = "1" ] && echo "Adding ingress_sbox iptables mangle rule: iptables -t mangle -A POSTROUTING -d $INGRESS_SUBNET -j TOS --set-tos $NODE_ID/0xff"
while nsenter --net=/var/run/docker/netns/ingress_sbox iptables -t mangle -D POSTROUTING -d $INGRESS_SUBNET -j TOS --set-tos $NODE_ID/0xff; do true; done 2>/dev/null
[ "$INSTALL" = "1" ] && nsenter --net=/var/run/docker/netns/ingress_sbox iptables -t mangle -A POSTROUTING -d $INGRESS_SUBNET -j TOS --set-tos $NODE_ID/0xff

if [ "$INSTALL" = "0" ]; then
  echo
  echo "Ingress Routing Daemon v2 iptables rules uninstalled, exiting."
  exit 0
fi

echo "Ingress Routing Daemon v2 starting ..."

# Watch for container start events, and configure policy routing rules on each container
# to ensure return path traffic for incoming connections is routed back via the correct interface
# and to the correct node from which the incoming connection was received.
docker events \
  --format '{{.ID}} {{index .Actor.Attributes "com.docker.swarm.service.name"}}' \
  --filter 'event=start' \
  --filter 'type=container' | \
  while read ID SERVICE
  do
    if [ -n "$SERVICE" ]; then

      NID=$(docker inspect -f '{{.State.Pid}}' $ID)
      echo "Container ID=$ID, NID=$NID, SERVICE=$SERVICE started: applying policy routes."

      # 3. Map any connection mark on outgoing traffic to a firewall mark on the individual packets.
      nsenter -n -t $NID iptables -t mangle -A OUTPUT -p tcp -j CONNMARK --restore-mark

      for NODE_IP in $INGRESS_NODE_GATEWAY_IPS
      do
        NODE_ID=$(echo $NODE_IP | cut -d'.' -f4)

    # 2. Map the TOS value on any incoming packets to a connection mark, using the same value.
        nsenter -n -t $NID iptables -t mangle -A PREROUTING -m tos --tos $NODE_ID/0xff -j CONNMARK --set-xmark $NODE_ID/0xffffffff

    # 4. Select the correct routing table to use, according to the firewall mark on the outgoing packet.
        nsenter -n -t $NID ip rule add from $INGRESS_SUBNET fwmark $NODE_ID lookup $NODE_ID prio 32700

    # 5. Route outgoing traffic to the correct node's ingress network IP, according to its firewall mark
    #    (which in turn came from its connection mark, its TOS value, and ultimately its IP).
        nsenter -n -t $NID ip route add table $NODE_ID default via $NODE_IP dev eth0

      done

    fi
  done

Bonjour @struanb , je ne comprends pas comment fonctionne la section de désinstallation dans votre script v2, y a-t-il quelque chose qui manque ?

Bonjour @jrbecart. J'espère que non. Avant que les règles iptables ne soient installées, vous verrez qu'il y a deux boucles while qui suppriment toutes les règles préexistantes, en utilisant iptables -D . C'est une mesure de sécurité, au cas où le script est exécuté avec --install plusieurs fois de suite, sans aucun appel intermédiaire avec --uninstall .

En tant que tel, lorsque le script est appelé avec --uninstall, au moment où le script se termine, ces règles auront été supprimées et de nouvelles règles n'auront pas encore été ajoutées.

J'espère que ça répond à ta question.

Salut à tous, je tiens à vous dire que j'ai découvert un correctif à ce problème, sans rien installer et configurer rien d'autre que de bien définir la configuration NGINX. Je sais que nous avons tous essayé des approches différentes. Celui-ci a été découvert par erreur. Pour être honnête, j'ai abandonné ça il y a longtemps. Eh bien, jusqu'à aujourd'hui. Pendant que j'implémentais un système de surveillance, j'ai pu obtenir l'adresse IP source, la véritable IP source, à l'aide du journal NGINX, j'ai donc commencé à déboguer comment était-ce possible.

Voici un exemple de ce type de log

10.0.0.2 - - [19/Nov/2020:04:56:31 +0000] "GET / HTTP/1.1" 200 58 "-" req_t=0.003 upstream_t=0.004 "<browser-info>" "<source-ip-1,source-ip2,....>"

Remarque : il existe plusieurs adresses IP sources si vous utilisez un proxy (c'est-à-dire Cloudfare et autres).

L'info était là, ma vraie IP était là. Ensuite, j'ai revu le format de journalisation NGINX pour savoir comment la magie était possible, et j'ai trouvé ceci :

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      'req_t=$request_time upstream_t=$upstream_response_time '
                      '"$http_user_agent" "$http_x_forwarded_for"';

Ça veut dire, la magie est là -> $http_x_forwarded_for

Après cela, j'ai modifié les en-têtes de proxy comme proxy_set_header X-Real-IP $http_x_forwarded_for; .

Et enfin, le dernier test, utilisant ces informations sur un projet NodeJS, à l'intérieur du système de production, en utilisant Docker Swarm avec un réseau superposé, avec environ 4 VM, et devinez quoi, cela a fonctionné ! J'ai enfin pu obtenir la véritable adresse IP.

Je suis tellement content parce que ce problème est ouvert depuis longtemps mais je pense que c'est la réponse. Les versions que j'ai utilisées sont :

Docker version: 19.03.8
NGINX version: nginx/1.14.2

J'attends vos retours. J'espère que vous pourrez avoir les mêmes résultats que moi.

À votre santé!
Sébastien.

PS : Essayez ceci en utilisant une autre interface réseau, c'est-à-dire en dehors de localhost, car vous trouverez un "-" dans le journal, au lieu de votre véritable adresse IP. Essayez de le tester sur Internet, complètement en dehors de votre réseau domestique.

Bonus : je pourrais aussi mapper l'adresse IP à une géolocalisation, en utilisant une table de recherche, les compter et la mettre sur une carte, donc la réponse est oui, c'est ce que nous recherchions les gars :)

@sebastianfelipe c'est une grande revendication après toutes ces années. Vous êtes sûr de ne pas utiliser le mode hôte ou d'autres solutions de contournement dans ce fil?

@sebastianfelipe c'est une grande revendication après toutes ces années. Vous êtes sûr de ne pas utiliser le mode hôte ou d'autres solutions de contournement dans ce fil?

Je suis sûr. Je n'utilise pas d'hôte réseau sur tous ces services connectés. Je viens de déployer une pile, avec un réseau superposé dans un environnement de type production, y compris un équilibreur de charge Digital Ocean et cela a fonctionné. Je veux dire, je ne peux pas le tester mieux que ça. Est 100% réel.

@sebastianfelipe Je suppose que l'équilibreur de charge Digital Ocean

@beornf J'essayais de dormir, puis j'ai lu votre notification, j'ai donc dû me réveiller et essayer une approche sans équilibreur de charge Digital Ocean et cela a échoué. Vous avez raison, Digital Ocean y ajoute une magie lorsqu'un équilibreur de charge est ajouté. Cela arrive à la variable $http_x_forwarded_for . L'équilibreur de charge Digital Ocean ajoute des informations à une autre variable NGINX, des informations qui ne sont pas ajoutées directement par Docker Swarm. Cela pourrait probablement conduire à une approche "fictive" pour avoir une vraie solution pour chaque cas. Au moins, les clients de Digital Ocean peuvent être heureux de savoir comment gérer cela en ce moment.

@beornf @sebastianfelipe En plus du contexte, CloudFlare ajoute également X-Forwarded-For et est en grande partie gratuit.

@beornf @sebastianfelipe En plus du contexte, CloudFlare ajoute également X-Forwarded-For et est en grande partie gratuit.

Je pense que cela pourrait fonctionner pour beaucoup d'entre nous qui ont besoin d'un moyen d'obtenir la véritable IP. Cloudfare peut être ajusté en tant que proxy ou simplement DNS uniquement. Il convient parfaitement à aucun client de Digital Ocean. C'est la solution de contournement la plus propre jusqu'à présent. Mais je suis d'accord avec @beornf , nous avons besoin d'une vraie solution, sans dépendre de Digital Ocean ou de Cloudfare pour y parvenir.

Merci!

Cette page vous a été utile?
0 / 5 - 0 notes