Kubernetes: utiliser iptables pour le proxy au lieu de l'espace utilisateur

Créé le 23 janv. 2015  ·  187Commentaires  ·  Source: kubernetes/kubernetes

Je jouais avec iptables hier, et j'ai créé un prototype (enfin, copié à partir des hits de Google et muté) un ensemble de règles iptables qui font essentiellement tout le proxy pour nous sans l'aide de l'espace utilisateur. Ce n'est pas urgent, mais je veux classer mes notes avant de les perdre.

Cela a pour effet secondaire supplémentaire (pour autant que je sache) de préserver l'adresse IP source et d'être une grande simplification du réseau. Maintenant, kube-proxy aurait juste besoin de synchroniser les services -> iptables. Cela a l'inconvénient de ne pas être compatible avec les anciens iptables et noyaux. Nous avons déjà eu un problème avec cela - à un moment donné, nous devons décider à quel point nous nous soucions du passé.

Cela peut probablement être optimisé davantage, mais dans les tests de base, je vois des sessions persistantes fonctionner et si je commente cette partie, je vois une probabilité égale d'atteindre chaque backend. Je n'ai pas réussi à faire fonctionner correctement le round-robin déterministe (avec --nth au lieu de --probability) mais nous pourrions y revenir si nous le voulons.

Cela met en place un portail de services avec les backends répertoriés ci-dessous

iptables -t nat -N TESTSVC
iptables -t nat -F TESTSVC
iptables -t nat -N TESTSVC_A
iptables -t nat -F TESTSVC_A
iptables -t nat -N TESTSVC_B
iptables -t nat -F TESTSVC_B
iptables -t nat -N TESTSVC_C
iptables -t nat -F TESTSVC_C
iptables -t nat -A TESTSVC -m recent --name hostA --rcheck --seconds 1 --reap -j TESTSVC_A
iptables -t nat -A TESTSVC -m recent --name hostB --rcheck --seconds 1 --reap -j TESTSVC_B
iptables -t nat -A TESTSVC -m recent --name hostC --rcheck --seconds 1 --reap -j TESTSVC_C
iptables -t nat -A TESTSVC -m statistic --mode random --probability 0.333 -j TESTSVC_A
iptables -t nat -A TESTSVC -m statistic --mode random --probability 0.500 -j TESTSVC_B
iptables -t nat -A TESTSVC -m statistic --mode random --probability 1.000 -j TESTSVC_C

iptables -t nat -A TESTSVC_A -m recent --name hostA --set -j DNAT -p tcp --to-destination 10.244.4.6:9376
iptables -t nat -A TESTSVC_B -m recent --name hostB --set -j DNAT -p tcp --to-destination 10.244.1.15:9376
iptables -t nat -A TESTSVC_C -m recent --name hostC --set -j DNAT -p tcp --to-destination 10.244.4.7:9376

iptables -t nat -F KUBE-PORTALS-HOST
iptables -t nat -A KUBE-PORTALS-HOST -d 10.0.0.93/32 -m state --state NEW -p tcp -m tcp --dport 80 -j TESTSVC
iptables -t nat -F KUBE-PORTALS-CONTAINER
iptables -t nat -A KUBE-PORTALS-CONTAINER -d 10.0.0.93/32 -m state --state NEW -p tcp -m tcp --dport 80 -j TESTSVC
prioritawaiting-more-evidence release-note sinetwork siscalability

Tous les 187 commentaires

Frais! Je pense que nous devrions certainement fusionner cela. Sur une note distincte, je voyais le proxy manger environ 30% d'un cœur sous une charge lourde, je dois croire qu'iptables nous donnera de meilleures performances que cela.

Nous devons donner la priorité à cela - c'est presque une réécriture totale de kube-proxy et
tous les tests de celui-ci. Il a également des problèmes de compatibilité arrière (ne fonctionnera pas sur
noyaux plus anciens ou anciens binaires iptables).

Le lundi 26 janvier 2015 à 11h06, Brendan Burns [email protected]
a écrit:

Frais! Je pense que nous devrions certainement fusionner cela. Sur une note séparée,
Je voyais le proxy manger environ 30% d'un noyau sous une charge lourde, je dois
Je pense qu'iptables nous donnera de meilleures performances que cela.

Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-71517501
.

Peut-être que l'implémenter en tant qu'option parallèle et migrer lentement est logique ?

Le lundi 26 janvier 2015 à 12h01, Tim Hockin [email protected]
a écrit:

Nous devons donner la priorité à cela - c'est presque une réécriture totale de kube-proxy et
tous les tests de celui-ci. Il a également des problèmes de compatibilité arrière (ne fonctionnera pas sur
noyaux plus anciens ou anciens binaires iptables).

Le lundi 26 janvier 2015 à 11h06, Brendan Burns [email protected]
a écrit:

Frais! Je pense que nous devrions certainement fusionner cela. Sur un
Remarque,
Je voyais le proxy manger environ 30% d'un noyau sous une charge lourde, je dois
Je pense qu'iptables nous donnera de meilleures performances que cela.

Répondez directement à cet e-mail ou consultez-le sur GitHub
<
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-71517501

.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-71527216
.

J'essaie de persuader quelqu'un d'autre qui ne connaît pas bien ce code de l'apprendre
et l'assumer. Je _veux_ vraiment m'y attaquer, mais ce serait mieux si
quelqu'un d'autre a appris cet espace (pas vous ! :)

Cela dit, vous avez également envoyé un (bon) e-mail à propos de l'énorme liste P1 - et je
ne pensez pas que cela figure encore sur cette liste.

Le lundi 26 janvier 2015 à 13:06, Brendan Burns [email protected]
a écrit:

Peut-être que l'implémenter en tant qu'option parallèle et migrer lentement rend
sens?

Le lundi 26 janvier 2015 à 12h01, Tim Hockin [email protected]
a écrit:

Nous devons donner la priorité à cela - c'est presque une réécriture totale de kube-proxy
et
tous les tests de celui-ci. Il a également des problèmes de rétro-compat (ne fonctionnera pas
au
noyaux plus anciens ou anciens binaires iptables).

Le lundi 26 janvier 2015 à 11:06, Brendan Burns <
[email protected]>
a écrit:

Frais! Je pense que nous devrions certainement fusionner cela. Sur un
Remarque,
Je voyais le proxy manger environ 30% d'un noyau sous une charge lourde, je dois
Je pense qu'iptables nous donnera de meilleures performances que cela.

Répondez directement à cet e-mail ou consultez-le sur GitHub
<

https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-71517501

.

Répondez directement à cet e-mail ou consultez-le sur GitHub
<
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-71527216>

.

Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-71538256
.

Est-ce un P2 ? Cela vaudrait-il la peine d'en faire un P3 pour le moment ?

J'espère le faire fonctionner, mais nous pouvons encore le rétrograder

Le mercredi 11 février 2015 à 14h49, Satnam Singh [email protected]
a écrit:

Est-ce un P2 ? Cela vaudrait-il la peine d'en faire un P3 pour le moment ?

Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-73982161
.

Est-ce que « l'espoir » n'équivaut pas à un PPP auquel nous arriverons si nous le pouvons ?

D'après une discussion avec @thockin : Il s'agit d'une exigence afin de prendre en charge les plages de ports de service, qui ne sont pas requises pour la version 1.0, mais nous aimerions éventuellement les prendre en charge.

@thockin "Cela a l'inconvénient de ne pas être compatible avec les anciens iptables et noyaux." À quel point le noyau devrait-il être « nouveau » ?

Pas TROP nouveau, mais nous avons des utilisateurs qui veulent VRAIMENT des iptables de 2012 à
travail.

Le lundi 23 février 2015 à 14h44, Sidharta Seethana < [email protected]

a écrit:

@thockin https://github.com/thockin "Cela a l'inconvénient de ne pas être
compatible avec les anciens iptables et noyaux.
doit être?

Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-75654187
.

@thockin merci. Nous utilisons/testons avec RHEL/CentOS 6, par exemple - ce serait donc bien si nous n'avons pas de dépendance dure sur les noyaux 3.x récents.

@pweil- nous en discutions l'autre jour
Le lundi 23 février 2015 à 23h40 Sidharta Seethana [email protected]
a écrit:

@thockin https://github.com/thockin merci. Nous utilisons/testons avec
RHEL/CentOS 6, par exemple - ce serait donc bien si nous n'avons pas de disque dur
dépendance sur les noyaux 3.x récents.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-75698480
.

Eh bien, vous avez besoin de Docker pour fonctionner, et à un moment donné, nous devons le couper.
Le support back-rev iptables ne m'empêchera pas (éventuellement) de faire
ce changement, et ça va piquer pour certaines personnes.

Le lundi 23 février 2015 à 20h40, Sidharta Seethana < [email protected]

a écrit:

@thockin https://github.com/thockin merci. Nous utilisons/testons avec
RHEL/CentOS 6, par exemple - ce serait donc bien si nous n'avons pas de disque dur
dépendance sur les noyaux 3.x récents.

Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-75698480
.

Avec l' aide de

Nous avons créé un cluster GCE Kubernetes avec 3 contrôleurs de réplication sky-dns.
Sur le kubernetes-master, nous définissons les éléments suivants dans iptables :
L'adresse IP du service DNS était 10.0.0.10, et les points de terminaison du pod exécutant DNS étaient 10.244.0.5:53, 10.244.3.6:53, 10.244.0.6:53

iptables -t nat -N TESTSVC
iptables -t nat -F TESTSVC
iptables -t nat -N TESTSVC_A
iptables -t nat -F TESTSVC_A
iptables -t nat -N TESTSVC_B
iptables -t nat -F TESTSVC_B
iptables -t nat -N TESTSVC_C
iptables -t nat -F TESTSVC_C
iptables -t nat -N KUBE-PORTALS-HOST
iptables -t nat -F KUBE-PORTALS-HOST

iptables -t nat -A TESTSVC -m recent --name hostA --rcheck --seconds 1 --reap -j TESTSVC_A
iptables -t nat -A TESTSVC -m recent --name hostB --rcheck --seconds 1 --reap -j TESTSVC_B
iptables -t nat -A TESTSVC -m recent --name hostC --rcheck --seconds 1 --reap -j TESTSVC_C

iptables -t nat -A TESTSVC -m statistique --mode random --probability 0.333 -j TESTSVC_A
iptables -t nat -A TESTSVC -m statistique --mode random --probability 0.5 -j TESTSVC_B
iptables -t nat -A TESTSVC -m statistique --mode random --probability 1.000 -j TESTSVC_C

iptables -t nat -A TESTSVC_A -m recent --name hostA --set -j DNAT -p udp --to-destination 10.244.0.5:53
iptables -t nat -A TESTSVC_B -m recent --name hostB --set -j DNAT -p udp --to-destination 10.244.3.6:53
iptables -t nat -A TESTSVC_C -m recent --name hostC --set -j DNAT -p udp --to-destination 10.244.0.6:53
iptables -t nat -A KUBE-PORTALS-HOST -d 10.0.0.10/32 -p udp -m udp --dport 53 -j TESTSVC
iptables -t nat -A SORTIE -j KUBE-PORTALS-HOST


kubernetes-master>nslookup kubernetes.default.kuberenetes.local 10.0.0.10

Nous obtenons une réponse en retour !

Super trucs ! Juste pour info (confirmation de notre conversation en face à face), il n'est pas sûr d'exécuter plusieurs commandes iptables simultanées en général (différentes chaînes semblent être OK). iptables est un wrapper autour de libiptc, et voir le commentaire sur iptc_commit : http://www.tldp.org/HOWTO/Querying-libiptc-HOWTO/mfunction.html

Cela a apparemment été corrigé en 2013, mais peut-être seulement si vous passez --wait (?): http://git.netfilter.org/iptables/commit/?id=93587a04d0f2511e108bbc4d87a8b9d28a5c5dd8

La cause première de ceci est qu'iptables appelle effectivement iptables-save / iptables-restore (au moins par chaîne); J'ai vu beaucoup de code qui appelle donc iptables-save & iptables-restore plutôt que de faire des ajouts et des suppressions. J'ai peut-être même du code à faire que je pourrais trouver si cela est utile.

Cela me dépasse qu'il n'y a aucun moyen de faire des opérations de type CAS ou LL/SC.

Nous devrions ajouter le support de --wait, bien qu'il soit assez récent pour que GCE
debian-backports ne l'a pas.

Peut-être devrions-nous faire notre propre verrouillage à l'intérieur de notre code pour au moins nous empêcher
de marcher sur nous-mêmes.

Le jeu. 26 février 2015 à 13:56, Justin Santa Barbara <
[email protected]> a écrit :

Super trucs ! Juste pour info (confirmation de notre conversation en face à face),
il n'est pas sûr d'exécuter plusieurs commandes iptables simultanées en général
(différentes chaînes sonnent comme si cela pourrait être OK). iptables est un wrapper autour
libiptc, et voir le commentaire sur iptc_commit :
http://www.tldp.org/HOWTO/Querying-libiptc-HOWTO/mfunction.html

Cela a apparemment été corrigé en 2013, mais peut-être seulement si vous réussissez -- attendez (?):
http://git.netfilter.org/iptables/commit/?id=93587a04d0f2511e108bbc4d87a8b9d28a5c5dd8

La cause première de ceci est que iptables appelle effectivement iptables-save /
iptables-restore (au moins par chaîne); J'ai vu beaucoup de code qui vient
appelle donc iptables-save & iptables-restore plutôt que de faire les choses
via des ajouts et des suppressions. J'ai peut-être même du code à faire que je pourrais creuser
vers le haut si cela est utile.

Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -76282629
.

Que se passe-t-il en cas d'échec au milieu de la création d'un tas de règles ?

Question juste - nous devrions probablement réfléchir très sérieusement à ce que signifie
rencontrer une erreur au milieu de ce

Le jeu. 26 février 2015 à 20h47, Brian Grant [email protected]
a écrit:

Que se passe-t-il en cas d'échec au milieu de la création d'un tas de
règles?

Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-76331174
.

@thockin De l'irc aujourd'hui :

Le net.ipv4.conf.all.route_localnet permet à 127.0.0.1 d'être la cible des règles DNAT . A partir de la doc :

route_localnet - BOOLÉEN

Ne considérez pas les adresses de bouclage comme source ou destination martienne
lors du routage. Cela permet l'utilisation de 127/8 à des fins de routage local.
par défaut FAUX

L'intégrerions-nous dans kubelet ou le conserverions-nous dans un démon séparé ? Kubelet surveille déjà les services afin de remplir les vars env.

Je voudrais le garder en tant que binaire séparé. Il y a des raisons pour lesquelles vous
vous voudrez peut-être l'exécuter sur d'autres machines (par exemple, des machines virtuelles pour animaux de compagnie) en dehors d'un k8
cluster afin d'accéder aux services k8s.

--brendan

Le vendredi 13 mars 2015 à 11h37, Brian Grant [email protected]
a écrit:

L'intégrerions-nous dans kubelet ou le conserverions-nous dans un démon séparé ?
Kubelet surveille déjà les services afin de remplir les vars env.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-79230747
.

Rattraper. En ce qui concerne ce qui se passe en cas d'échec (dont il y en aura beaucoup, croyez-moi), je suis un grand fan de l'approche anti-entropie - stocker l'état souhaité quelque part, et réconcilier périodiquement l'état souhaité et réel (en faisant muter l'état réel ). Dans ce cas, peut-être aussi simple que :

tandis que (vrai) {
état réel = iptablesSave()
if état réel ! = état désiré { iptablesRestore(étatdésiré))
sleep_a_while()
}

D'accord à 100%, c'est la bonne façon de gérer l'échec de l'écriture d'iptables
règles.

Le ven 13 mars 2015 à 13:16, Quinton Hoole [email protected]
a écrit:

Rattraper. En ce qui concerne ce qui se passe en cas de défaillances (dont
il y en aura beaucoup, croyez-moi), je suis un grand fan de l'approche anti-entropique

  • stocker l'état souhaité quelque part, et réconcilier périodiquement
    état réel (par mutation de l'état réel). Dans ce cas, peut-être aussi simple que :

tandis que (vrai) {
état réel = iptablesSave()
if état réel ! = état désiré { iptablesRestore(étatdésiré))
sleep_a_while()
}

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79336296
.

C'est plus ou moins ce qui se passe maintenant, n'est-ce pas ? Pour chaque règle attendue,
vérifiez s'il existe et sinon, faites-le.

Le vendredi 13 mars 2015 à 14h02, Brendan Burns [email protected]
a écrit:

D'accord à 100%, c'est la bonne façon de gérer l'échec de l'écriture d'iptables
règles.

Le ven 13 mars 2015 à 13:16, Quinton Hoole [email protected]
a écrit:

Rattraper. En ce qui concerne ce qui se passe en cas de défaillances (dont
il y en aura beaucoup, croyez-moi), je suis un grand fan de l'anti-entropie
approcher

  • stocker l'état souhaité quelque part, et réconcilier périodiquement
    état réel (par mutation de l'état réel). Dans ce cas, peut-être aussi simple
    comme:

tandis que (vrai) {
état réel = iptablesSave()
if état réel ! = état désiré { iptablesRestore(étatdésiré))
sleep_a_while()
}

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
<
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79336296

.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79392626
.

Je suis d'accord qu'il y a une utilité dans un binaire séparé, mais peut-être que nous le lions dans
kubelet (de la même manière que cAdvisor) et en faire un standalone au
en même temps.

Le vendredi 13 mars 2015 à 12h03, Brendan Burns [email protected]
a écrit:

Je voudrais le garder en tant que binaire séparé. Il y a des raisons pour lesquelles vous
vous voudrez peut-être l'exécuter sur d'autres machines (par exemple, des machines virtuelles pour animaux de compagnie) en dehors d'un k8
cluster afin d'accéder aux services k8s.

--brendan

Le vendredi 13 mars 2015 à 11h37, Brian Grant [email protected]
a écrit:

L'intégrerions-nous dans kubelet ou le conserverions-nous dans un démon séparé ?
Kubelet surveille déjà les services afin de remplir les vars env.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
<
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-79230747

.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79257059
.

Je serais curieux d'entendre ce que les gens de Kubernetes-Mesos ont à dire sur la question de savoir si les composants de nœud devraient être plus intégrés ou modulaires. @jdef ?

[[EDITED]] J'aime beaucoup la modularité des composants k8s, par exemple l'exécution d'un processus proxy séparé d'un processus kubelet. Si le proxy échoue pour une raison quelconque, il ne supprime pas le kubelet. C'est plutôt bien car les exécuteurs Mesos n'ont pas de modèle de basculement très gracieux pour le moment - et l'exécuteur du framework kubernetes-mesos est un hybride kubelet/exécuteur. Ce modèle me permet également d'exécuter un service proxy sur un maître mesos et de l'utiliser comme équilibreur à tour de rôle pour les clients externes (comme dans le guide de démarrage que nous avons soumis).

En termes d'emballage/expédition de binaires, je pense qu'il est assez utile de regrouper les fonctionnalités, comme dans hyperkube. J'ai également réfléchi à la façon de conditionner les composants du framework kubernetes-mesos dans des conteneurs Docker

+1 pour la fonctionnalité modulaire, +1 pour une seule image binaire

@thockin re : anti-entropie : Ah oui. Je vois que proxier.SyncLoop() fait cela. Dans quel cas la réponse à la question de @ bgrant0607 du 26 février

@thockin

  1. Sommes-nous inquiets du trafic réseau qui crée des trous noirs ou est-ce quelque chose dont l'auteur du service/pod doit s'occuper ?

Avec proxy de l'espace utilisateur
Supposons que Virtual IP 10.0.0.11 ait 3 points de terminaison, par exemple 10.240.1.1, 10.240.1.2, 10.240.1.3
Avec un proxy d'espace utilisateur, si un point de terminaison dit que 10.240.1.1 ne fonctionnait pas, le proxy se rendrait compte que la connexion TCP n'a pas été établie avec 10.240.1.1, et il pourrait se replier sur l'un des 2 autres points de terminaison.

Avec iptable
Lorsque nous utilisons iptables, il n'y a pas de mécanisme de secours car kubernetes ne réalise pas si le point de terminaison a fonctionné ou non.
Nous pourrions atténuer cela si nous avions une sorte de contrôle de santé pour les points de terminaison, qui supprimerait les points de terminaison non réactifs.

Ou peut-être que s'inquiéter des points de terminaison non réactifs n'est pas de la responsabilité du système kubernetes et de la responsabilité de l'auteur du pod ?

L'utilisateur peut configurer des sondes de préparation, qui sont effectuées par Kubelet. L'échec de la sonde entraînera la suppression d'un point de terminaison de la liste des points de terminaison par le contrôleur de points de terminaison. Le proxy de service doit ensuite supprimer le point de terminaison de l'ensemble cible.

J'ai étudié cela pour GSoC, et je me demande:

Donc, idéalement, nous détecterions si iptables est suffisamment nouveau pour être utilisé et sinon continuerions à utiliser kube-proxy?

D'après https://github.com/GoogleCloudPlatform/kubernetes/issues/5419, il semble que ce soit l'approche idéale ; avec kubelet déterminant s'il faut utiliser ip-tables ou démarrer kube-proxy.

Je suis aussi un peu en retard pour GSoC (c'était pendant les vacances de printemps....), donc je me demande aussi si je peux encore soumettre une proposition GSoC demain/plus tard aujourd'hui (autre que bien sûr la 27e date limite, est c'est toujours ouvert) ?

@BenTheElder Oui, vous avez jusqu'à vendredi pour soumettre une proposition. Il y a une autre personne potentiellement intéressée par ce sujet, mais aucune proposition spécifique pour le moment.

Je ne m'inquiète pas autant des noyaux antérieurs à 2012 que des systèmes d'exploitation sans iptables entièrement, bien que ceux-ci soient déjà cassés dans une certaine mesure.

@bgrant0607 merci !
Je pense que je peux sélectionner cette question alors. Cela a l'air intéressant.

La sonde de préparation fonctionnera bien pour le démarrage de l'application, mais je ne suis pas sûr que la préparation soit adaptée pour atténuer l'échec de l'application. En cas d'échec du pod, le signal doit passer de l'application -> kubelet -> apiserver -> endpoints_controller -> apiserver -> kube-proxy. Je serais intéressé à comprendre la latence entre un échec d'application et la suppression d'un point de terminaison de la rotation kube-proxy. Pendant cette période, les demandes seront transmises par proxy à un point de terminaison non réactif.

Réessayer en cas d'échec de la connexion est une stratégie courante et une fonctionnalité raisonnablement utile de nombreux équilibreurs de charge populaires (par exemple, haproxy, AWS ELB) et est gérée par l'implémentation actuelle de kube-proxy. Cette responsabilité doit-elle être migrée vers le LB externe ? Qu'en est-il du trafic intra-cluster ?

Une autre idée, avec iptables, nous rencontrerons probablement des problèmes de connexion gracieusement drainés lors de la reconfiguration par rapport à un LB réel.

Mike soulève de bons points.

Le lundi 23 mars 2015 à 23h00, Mike Danese [email protected]
a écrit:

Une autre pensée, nous rencontrerons probablement des problèmes de connexion gracieusement
vidange lors de la reconfiguration par rapport à un LB réel.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -85354865
.

J'ai lu les sources de kube-proxy et du proxy pkg ; iptables n'est-il pas déjà utilisé dans la révision actuelle ?

Que faut-il faire exactement à ce sujet ? D'après la source principale actuelle, il semble que iptables soit déjà largement utilisé dans le proxy.

@mikedanese @thockin Readiness est très utile pour les pannes planifiées. Les pannes imprévues provoqueront toujours des erreurs observables. L'intervalle d'interrogation devrait généralement être long par rapport à la latence de mise à jour, mais nous pourrions également mettre en place des règles de re-transmission sur le nœud de destination via une communication directe entre Kubelet et kube-proxy, si la latence via apiserver et etcd est trop longue et/ou que chemin n'est pas suffisamment fiable.

@BenTheElder Les règles existantes acheminent le trafic via le proxy. L'idée ici est d'utiliser les règles pour contourner le proxy.

@ bgrant0607 Merci, cela prend tout son sens maintenant. Un autre a lu la source et les documents de conception et j'ai presque fini d'écrire un projet de proposition.

Projet de proposition GSoC : https://gist.github.com/BenTheElder/ac61900595a7ea9ea9b5

J'avais particulièrement apprécié les commentaires sur la section calendrier. Je ne suis pas tout à fait sûr de cela.
Si je termine plus tôt, j'aimerais travailler sur d'autres problèmes GSoC (plus petits ?) non traités comme :
https://github.com/GoogleCloudPlatform/kubernetes/issues/1651.

Merci encore, Kubernetes prend le gâteau pour le groupe le plus sympathique.

Je veux juste dire que je suis très heureux de dire que ma proposition a été acceptée et que je vais travailler dessus au cours de l'été. :souriant:

Je suis très excité. Malheureusement, je suis actuellement au milieu de mes finales, mais à partir de ce week-end, je devrais être beaucoup plus actif et travailler dessus, probablement en commençant par obtenir https://github.com/GoogleCloudPlatform/kubernetes/pull/7032 fini.

@thockin @brendanburns Quelqu'un peut-il nous dire si nous voulons le faire en parallèle avec le proxy de l'espace utilisateur ou comment la migration vers la réimplémentation fonctionnerait ?

Il semble que nous préférions déjà iptables >= 1.4.11 (publié le 26 mai 2011).

// Executes the rule check without using the "-C" flag, instead parsing iptables-save.
// Present for compatibility with <1.4.11 versions of iptables.  This is full
// of hack and half-measures.  We should nix this ASAP.
func (runner *runner) checkRuleWithoutCheck(table Table, chain Chain, args ...string) (bool, error) {

Source : https://github.com/GoogleCloudPlatform/kubernetes/blob/aec41967416cf3463b188d72c97e71465e00719d/pkg/util/iptables/iptables.go#L206

Voyons-nous réellement des hôtes plus âgés que cela ?

Une approche serait évidemment de détecter au moment de l'exécution quelle version d'iptables nous utilisons et de faire la "meilleure chose" que nous puissions donner à la version, par exemple quelque chose comme :

si (ancienne version) {
charger le module de proxy de l'espace utilisateur
}
autre {
charger le module de proxy iptables
}

Je vous déconseille d'avoir trop de branches dans l'instruction if ci-dessus (idéalement seulement 2), et j'évite autant que possible d'avoir ce genre d'instruction if à plus d'un endroit dans le code.

Je n'ai pas passé au crible le code en détail pour déterminer dans quelle mesure l'approche ci-dessus est réalisable.

De plus, tous les nœuds doivent-ils implémenter la même stratégie (espace utilisateur vs proxy iptables), ou chacun peut-il décider indépendamment ?

Si chaque nœud décide indépendamment, nous augmentons potentiellement la surface de test proportionnellement au carré du nombre de branches dans l'instruction if ci-dessus (c'est-à-dire source_mode x dest_mode), mais si nous pouvons garder le nombre de modes à 2, je pense que c'est bien .

Q

Oh, et la réponse à votre question de savoir si nous voyons d'anciens nœuds est "oui", malheureusement.

Il y a beaucoup de discussions sur ce qui précède dans un numéro séparé., je vais essayer de le déterrer pour vous.

@quinton-hoole Merci !

De plus, je suis à peu près sûr que nous pouvons exécuter l'espace utilisateur sur un nœud et iptables sur un autre.

Le nombre de modes ne devrait être que de 2, sauf pour ce hack lorsque nous n'avons pas -C mais que les nœuds qui ont -C devraient pouvoir exécuter la version pure d'iptables (je pense).

Ah oui, #7528 traite des versions du noyau et autres.

Merci.
Je n'ai pas vu cela lorsque j'ai recherché les exigences pour kubernetes. Les seules exigences que j'ai trouvées étaient dans les documents de mise en réseau expliquant comment nous supposons des adresses IP uniques.

Nous devrions probablement obtenir une documentation écrite pour les exigences une fois que nous aurons une meilleure idée de ce qu'elles sont.

J'ai commencé à hacker ici : https://github.com/BenTheElder/kubernetes/tree/iptables_proxy

Plus précisément, j'ai déplacé l'implémentation de l'espace utilisateur derrière une interface ici :
https://github.com/BenTheElder/kubernetes/commit/4e5d24bb74aca43b0dd37cf5cfee8a34f8eff2bf

Je ne sais pas maintenant si la sélection de l'implémentation doit être dans cmd/kube-proxy ou dans pkg/proxy, je peux donc la supprimer et faire en sorte que l'implémentation soit sélectionnée par kube-proxy à la place.

Edit : je pense qu'avec le recul, il est probablement plus logique de sélectionner l'implémentation à partir de kube-proxy.

@BenTheElder J'ai testé les règles de Tim avec Calico et elles fonctionnent bien. Nous faisons tout notre travail dans la table de filtrage, donc les règles DNAT ici ont défini l'adresse IP src appropriée à ce stade.

Plus généralement, il serait bon d'avoir une discussion pour définir comment les plugins réseau peuvent modifier en toute sécurité iptables si Kubernetes y insère également des règles. Vous ne voulez pas piétiner (ou être piétiné) les règles de Kubernetes si elles changent en cours de route.

@Symétrique Oui. Je ne suis pas encore du tout sûr de la partie plugins, mais cela semble assez important.

Je vais probablement être un peu occupé ce week-end, mais lundi, je devrais commencer à travailler à temps plein pour que GSoC implémente la première itération.
J'aimerais garder cela à l'esprit tout en faisant cela, mais après avoir examiné l'API des plugins réseau, je ne suis pas vraiment sûr de la façon la plus propre de gérer cela.

Avez-vous une idée de ce à quoi vous voudriez que cela ressemble / comment cela devrait fonctionner?

FWIW, j'ai fait quelque chose qui fonctionne pour nous parce que le kube-proxy devenait presque insensible. C'est ici : https://github.com/MikaelCluseau/kubernetes-iptables-proxy/blob/master/iptables-routing.rb.

Je n'avais pas vu ce fil auparavant, mais je me retrouve avec quelque chose de proche, sauf que j'ai fait une erreur avec mes poids de correspondance de statistiques aléatoires :-)

Je voudrais également partager que nous avons atteint le nf_conntrack_max rapidement. Il devrait probablement être augmenté.

# cat /etc/sysctl.d/nf_conntrack.conf 
net.netfilter.nf_conntrack_max = 1000000
net.nf_conntrack_max           = 1000000

Je n'ai peut-être pas compris tout le besoin de iptables , mais pourquoi ne pas utiliser IPVS place ?
Cela semble être plus pertinent pour le proxy que iptables...
Voici une implémentation simple de go : https://github.com/noxiouz/go-ipvs
Et pour compléter le #561, il y a aussi le projet ktcpvs .

IPVS semble également être une abstraction sur netfilter (comme iptables). Nous pouvons partager certaines fonctionnalités avec le code existant en utilisant iptables ; et iptables semble être la solution la plus flexible/générale pour gérer netfilter.

Quant à #561 et ktcpvs : ktcpvs ne semble pas avoir eu de développement depuis 2004 et ne semble pas avoir de fonctionnalités que les utilisateurs souhaiteraient comme la réécriture d'URL. Quoi qu'il en soit, #561 recherche une solution générique utilisable avec des équilibreurs enfichables.

Remarque : ce projet go ne semble pas avoir de licence.

iptables sera déprécié "un jour" au profit de nftables ( nft cli).
De plus, l'utilisation de la CLI iptables pour créer des règles ne semble pas être assez robuste ...

Une recherche rapide trouve moi cet autre projet du MIT : https://github.com/vieux/go-libipvs
Mais il semble être vraiment assez facile d'en créer un qui fonctionne car toute la complexité est déjà à l'épreuve des balles dans le code du noyau.

Je doute qu'iptables soit supprimé de l'une des principales distributions de sitôt, et la CLI iptables est spécifiquement destinée à créer et à gérer des règles pour netfilter ... ?

Un wrapper cgo incomplet comme celui lié semble beaucoup moins sûr que de bombarder iptables et iptables-restore et nous avons déjà besoin d'iptables pour d'autres règles (par exemple nodeports) et avec iptables-restore nous pouvons faire des mises à jour en masse avec une certaine atomicité.

IPVS semble en outre être conçu pour être utilisé sur une machine hôte d'équilibrage de charge séparément des serveurs "réels".
Cela suggère qu'il s'agit de la seule utilisation prise en charge :

2.2. Problèmes : vous avez besoin d'un client extérieur (le directeur et les serveurs réels ne peuvent pas accéder au service virtuel)

Pour configurer et tester/exécuter LVS, vous avez besoin d'un minimum de 3 machines : client, directeur, serveur(s) réel(s).

De l'extérieur, le LVS fonctionne comme une seule machine. Le client ne peut pas être l'une des machines du LVS (le directeur ou le serveur réel). Vous avez besoin d'un client extérieur. Si vous essayez d'accéder à un service contrôlé par LVS (par exemple http, smtp, telnet) à partir de l'une des machines du LVS ; l'accès depuis le directeur se bloquera, l'accès depuis un serveur réel se connectera au service localement, en contournant le LVS.

Il semble également qu'IPVS/LVS ajoute des exigences supplémentaires comme un démon de pulsation et des processus de surveillance supplémentaires. Nous gérons déjà les informations sur les points de terminaison et la surveillance de la santé des pods, etc. depuis kubernetes.

+1 pour l'approche iptables. Nous utilisons beaucoup iptables dans Calico et ils se sont avérés robustes, performants et évolutifs (en supposant que vous conceviez bien vos règles). @BenTheElder , si vous avez besoin d'aide pour quoi que ce soit du travail d'iptables, veuillez nous le faire savoir, car nous serions heureux de participer.

+1 pour iptables et iptables-restore, c'est une approche beaucoup moins lourde
qu'IPVS/LVS et dicte moins d'exigences système (démon heartbeat,
etc.)

Le samedi 13 juin 2015 à 11h27, Alex Pollitt [email protected]
a écrit:

+1 pour l'approche iptables. Nous utilisons beaucoup iptables dans Calico et
ils se sont avérés robustes et ils fonctionnent et évoluent bien (en supposant que vous
bien concevez vos règles). @BenTheElder https://github.com/BenTheElder ,
si vous avez besoin d'aide pour quoi que ce soit du travail d'iptables, veuillez laisser
nous le savons, car nous serions heureux de participer.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-111719474
.

Merci Alex, je vous ferai savoir si je le fais.

Je pourrais utiliser des commentaires/entrées sur la mise en œuvre actuelle (https://github.com/GoogleCloudPlatform/kubernetes/pull/9210) si quelqu'un a le temps.

C'est en grande partie complet et actuellement complet à jour avec le maître en amont, je dois finir d'écrire le code qui compare les règles générées à iptables-save et restaure les compteurs etc, mais les règles sont générées et (surtout) fonctionnent, à peu près en suivant les règles décrites dans le PO ici, le plus gros changement étant simplement les noms de chaîne, ce qui était nécessaire pour la génération automatique de noms qu'iptables acceptera.

Il existe un cas limite signalé ici : https://github.com/BenTheElder/kubernetes/issues/3 qui peut nécessiter une modification pour la gestion des pods se connectant à eux-mêmes.

J'ai eu d'excellents retours et discussions avec @MikaelCluseau et @Symmetric en particulier sur la refonte de la conception pour gérer cela et d'autres choses (merci encore !); mais nous pourrions utiliser plus d'informations sur la conception des règles en particulier. Si quelqu'un d'autre a le temps de jeter un coup d'œil, ce serait très apprécié car je ne sais pas quelle est la meilleure voie à suivre et je veux éviter de faire des changements majeurs sans plus d'entrée.

Le PR lui-même est assez gros, mais la génération de règles pertinentes est entièrement en pkg/proxy/proxieriptables.go syncProxyRules() sur : https://github.com/BenTheElder/kubernetes/blob/iptables_proxy/pkg/proxy/proxieriptables. aller#L286

La discussion existante peut être vue (ici bien sûr) ainsi que dans les commentaires des relations publiques et sur https://github.com/BenTheElder/kubernetes/issues/3 ainsi qu'un peu plus sur https://github.com/ BenTheElder/kubernetes/issues/4.

Un autre problème qui a besoin d'entrée:

Dans le code actuel, le kube-proxy est toujours inclus, pour gérer UNIQUEMENT le cas nodePort. Je pense que nous pouvons également supprimer kube-proxy dans ce cas, et avons proposé quelques règles iptables simples pour le faire sur le PR de Ben .

Mais ces règles masquent toujours l'adresse IP source de tout LB externe, elles ne sont donc pas idéales. Le problème est que si nous ne faisons que le trafic DNAT du LB lorsqu'il atteint un nœud, alors le paquet de réponse pourrait provenir d'un nœud différent, et donc je ne pense pas que le LB sera en mesure de corréler la réponse avec la session TCP d'origine . Cette préoccupation est-elle valable ? La mise en œuvre serait plus simple si nous n'avions pas à nous en soucier.

Je soupçonne qu'il y a de la magie que nous pouvons faire pour garder les proxys HTTP heureux, mais je ne vois pas de moyen de généraliser cela à L4.

J'essaie la magie noire de votre PR, mais cela ne génère rien pour moi, il semble que les règles aient commencé à être générées avec des appels à iptables puis un fichier iptables-restore est produit.

Il y a un manque dans la partie d'en-tête du fichier produit, généralement ceux qui ont été remplis avec l'appel iptables, il y a la partie pertinente du journal :

I0807 11:41:24.560063 8369 iptables.go:327] exécutant iptables -N [KUBE-PORTALS-CONTAINER -t nat]
I0807 11:41:24.562361 8369 iptables.go:327] exécution d'iptables -C [PRÉROUTING -t nat -m comment --comment handle ClusterIPs; REMARQUE : cela doit être avant les règles NodePort -j KUBE-PORTALS-CONTAINER]
I0807 11:41:24.563469 8369 iptables.go:327] exécutant iptables -N [KUBE-PORTALS-HOST -t nat]
I0807 11:41:24.565452 8369 iptables.go:327] exécution d'iptables -C [SORTIE -t nat -m comment --comment handle ClusterIPs; REMARQUE : cela doit être avant les règles NodePort -j KUBE-PORTALS-HOST]
I0807 11:41:24.566552 8369 iptables.go:327] exécutant iptables -N [KUBE-NODEPORT-CONTAINER -t nat]
I0807 11:41:24.568363 8369 iptables.go:327] exécution d'iptables -C [PRÉROUTING -t nat -m addrtype --dst-type LOCAL -m comment --comment handle service NodePorts; REMARQUE : cela doit être la dernière règle de la chaîne -j KUBE-NODEPORT-CONTAINER]
I0807 11:41:24.569564 8369 iptables.go:327] exécutant iptables -N [KUBE-NODEPORT-HOST -t nat]
I0807 11:41:24.571458 8369 iptables.go:327] en cours d'exécution iptables -C [OUTPUT -t nat -m addrtype --dst-type LOCAL -m comment --comment handle service NodePorts; REMARQUE : cela doit être la dernière règle de la chaîne -j KUBE-NODEPORT-HOST]
I0807 11:41:24.573392 8369 iptables.go:327] exécution d'iptables -C [POSTROUTING -t nat -m comment --comment handle pod se connectant à self -s 10.240.240.78/32 -d 10.240.240.78/32 -j MASQUERADE ]
I0807 11:41:24.574447 8369 proxier.go:349] Synchronisation des règles iptables.
I0807 11:41:24.575592 8369 proxier.go:399] Chaîne : PREROUTING, Règle : : PREROUTING ACCEPT [0:0]
I0807 11:41:24.575615 8369 proxier.go:401] Règle : -A PREROUTING -m comment --comment "handle ClusterIPs; NOTE: ceci doit être avant les règles NodePort" -j KUBE-PORTALS-CONTAINER
I0807 11:41:24.575625 8369 proxier.go:401] Règle : -A PREROUTING -m addrtype --dst-type LOCAL -m comment --comment "gérer le service NodePorts ; REMARQUE : ce doit être la dernière règle de la chaîne" -j KUBE-NODEPORT-CONTAINER
I0807 11:41:24.575633 8369 proxier.go:399] Chaîne : INPUT, Règle : : INPUT ACCEPT [0:0]
I0807 11:41:24.575646 8369 proxier.go:399] Chaîne : SORTIE, Règle : : SORTIE ACCEPTER [0:0]
I0807 11:41:24.575658 8369 proxier.go:401] Règle: -A OUTPUT -m comment --comment "handle ClusterIPs; NOTE: ceci doit être avant les règles NodePort" -j KUBE-PORTALS-HOST
I0807 11:41:24.575670 8369 proxier.go:401] Règle : -A OUTPUT -m addrtype --dst-type LOCAL -m comment --comment "gérer le service NodePorts ; REMARQUE : ce doit être la dernière règle de la chaîne" -j KUBE-NODEPORT-HOST
I0807 11:41:24.575683 8369 proxier.go:399] Chaîne : POSTROUTING, Règle : :POSTROUTING ACCEPT [0:0]
I0807 11:41:24.575691 8369 proxier.go:401] Règle : -A POSTROUTING ! -d 10.0.0.0/8 -o eth0 -j MASQUERADE
I0807 11:41:24.575699 8369 proxier.go:401] Règle : -A POSTROUTING -s 10.240.240.78/32 -d 10.240.240.78/32 -m comment --comment "handle pod connection to self" -j MASQUERADE
I0807 11:41:24.575709 8369 proxier.go:399] Chaîne : KUBE-NODEPORT-CONTAINER, Règle : :KUBE-NODEPORT-CONTAINER - [0:0]
I0807 11:41:24.575720 8369 proxier.go:399] Chaîne : KUBE-NODEPORT-HOST, Règle : :KUBE-NODEPORT-HOST - [0:0]
I0807 11:41:24.575729 8369 proxier.go:399] Chaîne : KUBE-PORTALS-CONTAINER, Règle : :KUBE-PORTALS-CONTAINER - [0:0]
I0807 11:41:24.575740 8369 proxier.go:399] Chaîne : KUBE-PORTALS-HOST, Règle : :KUBE-PORTALS-HOST - [0:0]
I0807 11:41:24.581897 8369 proxier.go:603] Règle de synchronisation : :KUBE-PORTALS-HOST - [0:0]
:KUBE-PORTALS-CONTAINER - [0:0]
:KUBE-NODEPORT-HOST - [0:0]
:KUBE-NODEPORT-CONTAINER - [0:0]
:KUBE-SVC-VO8JL93ZeRSf8cnsLpl - [0:0]
:KUBE-SVC-L26cB3JYuxdW5TF84ct - [0:0]
:KUBE-SVC-j2SF8q3nUajS8vOx2qL - [0:0]
:KUBE-SVC-shln2urO8W1aBiB2bWJ - [0:0]
:KUBE-SVC-8jQ3IvijvhJ4ppFj3Ui - [0:0]
[... COUPE ...]

Fusionner un iptable-save avec le résultat produit en mode verbeux peut être importé et faire de bonnes choses.

@bnprss merci pour le rapport, il y a eu récemment un certain nombre de modifications non testées, notamment l'utilisation d'un fichier temporaire et l'utilisation de l'indicateur "-T table" pour iptables-restore lors de certaines réécritures pour le processus de révision. Je mettrai un correctif une fois que je saurai ce qui a causé la ou les régressions.

@bnprss Comme vous l'avez dit, l'en-tête du tableau est manquant ("* nat" devrait être la première ligne), il a été supprimé par erreur et après l'avoir remis en place, tout semble fonctionner à nouveau correctement avec apparemment aucun autre bogue (à l'exception de : https :/ /github.com/BenTheElder/kubernetes/issues/3). Merci encore, désolé pour ça. J'ai poussé le correctif.

Beau travail, les règles se chargent et semblent fonctionner de l'intérieur mais pas de chance avec externalloadbalancer aucune communication de l'extérieur ne donne de réponse.

Hein. Pourriez-vous passer au PR et fournir plus de détails ? Jusque là
ça marche bien mais je ne me déploie pas au-delà des tests locaux et je
ne pensez pas que les autres testeurs utilisaient un équilibreur de charge externe.
Le 7 août 2015 à 13h29, "bnprss" [email protected] a écrit :

Beau travail, les règles se chargent et semblent fonctionner de l'intérieur mais pas de chance
avec externalloadbalancer aucune communication de l'extérieur ne donne de réponse.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-128772763
.

Oui, pour les détails, je mènerai d'autres enquêtes et produirai des journaux ou des pistes sur les relations publiques, mais pas avant demain, j'aimerais avoir un bon travail de sauvegarde à exécuter avant de casser quelque chose.

Pouvez-vous calculer le jeton des règles sans séparateurs "-_" ?

@bnprss , super.
Les chaînes de règles générées pour les services sont un hachage du port de service/du point de terminaison, puis l'URL base64 est codée et tronquée. KUBE-SVC-. Le code est ici : https://github.com/GoogleCloudPlatform/kubernetes/pull/9210/files#diff -d51765b83fe795b469e8a86276b12dc9R321
Nous avons choisi cela comme un moyen de générer des noms de chaînes valides qui respecteront la limite de caractères dans iptables tout en restant déterministes.
Il devrait donc être possible de répliquer en externe.
Si vous voulez dire, pouvons-nous arrêter d'utiliser des séparateurs, nous pourrions probablement le faire, mais le "_" provient de certains hachages codés et le "-" ne fait que suivre les modèles des noms de règles du proxy de l'espace utilisateur existant.
Nous pourrions probablement utiliser autre chose sans trop de problèmes si cela était nécessaire.

Je suis d'accord avec ça, et c'est vraiment cosmétique ! :)
Mais cela diffère des choses que j'ai vues avant :
règles gce lb : a07f76b3b2ec311e59e2642010af0479
règles gce fw : k8s-fw-a7ecad94f3ba511e59e2642010af0479
règles de routage gce : default-route-6973e029b504a0e8
routage gce vers le nœud : obfuscated_cluster_node-43506797-2eb2-11e5-9e26-42010af04793

celui-ci est sympa :
KUBE-SVC-6ADi2TVfn7mFPvBjC56
ceux-là sont marrants :
KUBE-SVC-zU6ParcQ-UfW_LdRDUc
KUBE-SVC-y--z1xTUpHPT6sgAUCC

Ouais j'suis pas franchement fan d'eux non plus, on pourrait peut-être changer le hash
codage.

Le vendredi 7 août 2015 à 14 h 16, bnprss [email protected] a écrit :

Je suis d'accord avec ça, et c'est vraiment cosmétique ! :)
Mais cela diffère des choses que j'ai vues avant :
règles gce lb : a07f76b3b2ec311e59e2642010af0479
règles gce fw : k8s-fw-a7ecad94f3ba511e59e2642010af0479
règles de routage gce : default-route-6973e029b504a0e8
routage gce vers le nœud :
obfuscated_cluster_node-43506797-2eb2-11e5-9e26-42010af04793

celui-ci est sympa :
KUBE-SVC-6ADi2TVfn7mFPvBjC56
ceux-là sont marrants :
KUBE-SVC-zU6ParcQ-UfW_LdRDUc
KUBE-SVC-y--z1xTUpHPT6sgAUCC

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -128785914
.

Oui, il est possible d'utiliser uniquement la partie tronquée de SHA, git est d'accord avec cela, docker aussi, et semble être la façon dont l'autre référence aux entités kube est faite. En cas de collision dans le hachage généré, base64 n'aidera pas. ;)
Je suppose que @thockin pourrait vous conseiller sur ce point.

J'étais plus préoccupé par les caractères valides dans iptables, pour lesquels j'avais du mal à trouver une bonne référence. Je vais étudier cela plus en détail sous peu.

Le vendredi 7 août 2015 à 14 h 29, bnprss [email protected] a écrit :

Oui, il est possible d'utiliser uniquement la partie tronquée de SHA, git est d'accord avec
ça, docker aussi, et semble être la façon dont l'autre référence à kube
les entités sont faites. En cas de collision dans le hash généré, base64 ne
aider. ;)
Je suppose que @thockin https://github.com/thockin pourrait vous conseiller sur ce point.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-128788454
.

@bnprss Pour l'instant, le PR est assez instable et en train d'être refait, par thockin, nous supprimons NodePort, etc.

Je n'essaierais pas de l'exécuter maintenant, mais ce sera bientôt de retour, espérons-le. Diviser le PR en quelques plus petits liés, puis en pousser un propre avec les trucs iptables-proxy en ce moment.

Pour ceux d'entre vous qui jouent à la maison, je suis convaincu que nous pouvons le faire au maximum
parité, mais ce sera beaucoup plus facile à revoir par étapes :)

Le vendredi 7 août 2015 à 21h35, Benjamin Elder [email protected]
a écrit:

Ma réponse au commentaire ci-dessus, également bientôt supprimée :

Discuté dans l'IRC :

  • devra toujours gérer les compteurs, mais souhaite continuer à analyser
    état dans le package util/iptables.
  • encore besoin de hachage ou similaire pour gérer les limites de longueur de chaîne

Sinon semble être une simplification très propre, sera mise en œuvre après
quelques discussions supplémentaires.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-128912169
.

Statut : la logique « principale » est vérifiée et signalée.

Je travaille sur les ports de nœuds maintenant. Il y a beaucoup de cas bizarres qui nécessitent un traitement spécial. Mes notes pour l'instant :

# Basic node ports:
iptables -t nat -N KUBE-NODEPORTS
iptables -t nat -A PREROUTING -j KUBE-NODEPORTS
iptables -t nat -A OUTPUT -j KUBE-NODEPORTS
iptables -t nat -A KUBE-NODEPORTS -p tcp -m comment --comment "TEST: default/nodeport:p" -m tcp --dport 30241 -j KUBE-SVC-EQKU6GMUKRXBR6NWW53

# To get traffic from node to localhost:nodeport to the service:
echo 1 > /proc/sys/net/ipv4/conf/all/route_localnet
# Mark packets that are destined for services from localhost, then masquerade those
iptables -t nat -I KUBE-SVC-EQKU6GMUKRXBR6NWW53 -s 127.0.0.0/16 -j MARK --set-mark 0x4b000001;
iptables -t nat -A POSTROUTING -m mark --mark 0x4b000001 -j MASQUERADE

# To get traffic from a pod to itself via a service:
for intf in $(ip link list | grep veth | cut -f2 -d:); do brctl hairpin cbr0 $intf on; done
# Mark packets that are destined for each endpoint from the same endpoint, then masquerade those.
# This is hacky, but I don't really know which pods are "local" and I don't really want to right now. (but I will eventually)
iptables -t nat -I KUBE-SEP-HHNEQBOLY57T5MQCFIY -s 10.244.1.6 -j MARK --set-mark 0x4b000001

J'ai travaillé sur un outil de contribution pour les tests.
Jusqu'à présent, je pense que je vais lancer un serveur sur un nœud, la latence de temps de
requêtes, voir comment obtenir la charge de la ressource kube-proxy et vider le
données au format CSV pour la représentation graphique, etc.
J'espère que c'est fait avant vendredi, pour se familiariser avec kubectl dès maintenant.

Le mer. 12 août 2015 à 20h48, Tim Hockin [email protected]
a écrit:

Statut : la logique « principale » est vérifiée et signalée.

Je travaille sur les ports de nœuds maintenant. Il y a beaucoup de cas bizarres qui ont besoin
traitement spécial. Mes notes pour l'instant :

Ports de nœud de base :

iptables -t nat -N KUBE-NODEPORTS
iptables -t nat -A PREROUTING -j KUBE-NODEPORTS
iptables -t nat -A SORTIE -j KUBE-NODEPORTS
iptables -t nat -A KUBE-NODEPORTS -p tcp -m comment --comment "TEST: default/ nodeport:p " -m tcp --dport 30241 -j KUBE-SVC-EQKU6GMUKRXBR6NWW53

Pour acheminer le trafic du nœud vers localhost:nodeport vers le service :

echo 1 > /proc/sys/net/ipv4/conf/all/route_localnet

Marquez les paquets destinés aux services de localhost, puis masquez-les

iptables -t nat -I KUBE-SVC-EQKU6GMUKRXBR6NWW53 -s 127.0.0.0/16 -j MARK --set-mark 0x4b000001;
iptables -t nat -A POSTROUTING -m mark --mark 0x4b000001 -j MASQUERADE

Pour acheminer le trafic d'un pod vers lui-même via un service :

pour intf dans $(ip link list | grep veth | cut -f2 -d:); faire brctl épingle à cheveux cbr0 $intf sur; terminé

Marquez les paquets destinés à chaque point de terminaison à partir du même point de terminaison, puis masquez-les.

C'est bidon, mais je ne sais pas vraiment quels pods sont "locaux" et je n'ai pas vraiment envie de le faire pour le moment. (mais je finirai par le faire)

iptables -t nat -I KUBE-SEP-HHNEQBOLY57T5MQCFIY -s 10.244.1.6 -j MARK --set-mark 0x4b000001

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130492394
.

@BenTheElder Je viens de faire des mesures de

netperf est un outil de perf client/serveur, j'ai emballé à la fois le client et le serveur dans le conteneur docker paultiplady/ netserver:ubuntu.2. Il y a beaucoup d'options sur netperf, mais quelque chose comme faire tourner deux pods netserver et exécuter

kubectl exec  -t $netserver-pod-1 -- netperf –l 30 -i 10 -I 99,1 -c -j -H $netserver-pod-2-ip -t OMNI --  -T tcp -D -O THROUGHPUT,THROUGHPUT_UNITS,MEAN_LATENCY,MIN_LATENCY,MAX_LATENCY,P50_LATENCY,P90_LATENCY,P99_LATENCY,STDDEV_LATENCY,LOCAL_CPU_UTIL

devrait vous donner une répartition décente des statistiques, y compris la latence et le débit. Vous pouvez exécuter le conteneur netserver en utilisant docker run --net=host pour effectuer également des tests node->pod.

Le fichier docker de ce conteneur est assez simple, je peux le renvoyer si vous souhaitez l'étendre en quelque chose de plus léger (par exemple, un conteneur basé sur alpinelinux pour une extraction plus rapide).

Merci je vais regarder ça.

D'après ce commentaire, je pense que nous voulons faire une sorte de latence de demande de service. En ce moment, j'essaie d'utiliser le conteneur nginx standard en tant que nœud X et de travailler sur un pod de test le frappant à plusieurs reprises afin que nous puissions créer un graphique sur le nœud Y.

Je vais regarder netperf/qperf cependant, et nous pouvons toujours avoir plusieurs tests.
J'aimerais d'abord faire ce graphique selon la discussion précédente avec @thockin

Le jeu. 13 août 2015 à 00h02, Paul Tiplady [email protected]
a écrit:

@BenTheElder https://github.com/BenTheElder Je viens d'en faire raisonnablement
mesures détaillées des performances du réseau sur GCE - je vous recommande de jeter un œil à
netperf (qperf donne également des mesures de latence).

netperf est un outil de perf client/serveur, j'ai emballé à la fois le client et
le serveur dans le conteneur docker paultiplady/ netserver:ubuntu.2.
il y a beaucoup d'options sur netperf, mais quelque chose comme en faire tourner deux
pods netserver et en cours d'exécution

kubectl exec -t $netserver-pod-1 -- netperf –l 30 -i 10 -I 99,1 -c -j -H $netserver-pod-2-ip -t OMNI -- -T tcp -D -O DÉBIT,THROUGHPUT_UNITS,MEAN_LATENCY,MIN_LATENCY,MAX_LATENCY,P50_LATENCY,P90_LATENCY,P99_LATENCY,STDDEV_LATENCY,LOCAL_CPU_UTIL

devrait vous donner une répartition décente des statistiques, y compris la latence et le débit.
Vous pouvez exécuter le conteneur netserver en utilisant docker run --net=host à faire
node->pod tests aussi.

Le fichier docker de ce conteneur est assez simple, je peux le déclencher si
vous voulez l'étendre à quelque chose de plus léger (par exemple, un
conteneur pour une traction plus rapide).

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-130524576
.

concernant les ports de nœud : Dans #9210, @Symmetric a apporté ce cas :

Si le trafic est fluide :
LB -> node1:nodePort
Et le pod de service est sur node2, alors le flux complet sera :
LB -> node1:nodePort -> node2 -> pod:svcPort
Le srcIP sera toujours le LB, donc la réponse ira
pod -> node2 -> LB
Étant donné que node2 peut router directement vers le LB.

Maintenant, nous perdons l'opportunité de dé-DNAT pour restaurer l'IP source correcte pour le paquet de retour (cela ne peut se produire que sur node1).

J'ai reproduit le problème. ACK que c'est un vrai problème. tcpdump affiche les paquets en cours de DNAT vers le pod IP:port (hors machine), avec src intact, mais tcpdump sur la machine de destination n'affiche rien. Je ne suis pas sûr de ce à quoi je m'attendrais même si les paquets arrivaient là-bas.

Je pense que la seule solution est de SNAT. La solution la moins impactante serait de _seulement_ les paquets SNAT du LB qui sont destinés hors nœud, mais a) je n'ai pas cette information dans kube-proxy (pourrait l'obtenir au prix du code) et b) puisque tout la politique devra de toute façon considérer le cas SNAT, je peux simplifier en effectuant toujours la SNAT des paquets LB externes. À quel point est-ce mauvais pour les moteurs de politique ?

Finalement, les LB seront suffisamment intelligents pour cibler uniquement les hôtes avec des pods et le trafic restera local, et cela deviendra alors sans objet.

Cela devient quand même plus compliqué. Nous avons le champ deprecatedPublicIPs que nous allons probablement annuler avec quelques ajustements de comportement. Je suppose que nous devons faire la même chose pour ceux-là. Mais cela devient encore plus compliqué - je ne connais pas réellement toutes les IP publiques (par exemple, la VM a une IP externe NAT 1-to-1). Réponse facile - toujours des paquets de port de nœud SNAT. Que pensez?

Je testerai plus demain.

@BenTheElder Vous pouvez faire du pod netserver un service, de sorte que le trafic de perf <->
serveur passe par le service VIP. De cette façon, vous n'avez pas à faire le
calculs d'échantillonnage/latence vous-même...

Le mer. 12 août 2015 à 21h20, Benjamin Elder [email protected]
a écrit:

Merci je vais regarder ça.

De ce commentaire
bien que je pense que nous voulons faire une sorte de latence de demande de service. Droit
maintenant, j'essaie d'utiliser le conteneur nginx standard en tant que nœud X et de travailler sur
avoir un temps de test pod le frappant à plusieurs reprises afin que nous puissions construire un graphique sur
nœud Y.

Je vais regarder netperf/qperf cependant, et nous pouvons toujours avoir plusieurs tests.
J'aimerais que ce graphique soit fait en premier, mais selon la discussion précédente avec
@thockin

Le jeu. 13 août 2015 à 00h02, Paul Tiplady [email protected]
a écrit:

@BenTheElder https://github.com/BenTheElder Je viens d'en faire raisonnablement
mesures détaillées des performances du réseau sur GCE - je vous recommande de jeter un œil à
netperf (qperf donne également des mesures de latence).

netperf est un outil de perf client/serveur, j'ai emballé à la fois le client et
le serveur dans le conteneur docker paultiplady/ netserver:ubuntu.2.
il y a beaucoup d'options sur netperf, mais quelque chose comme en faire tourner deux
pods netserver et en cours d'exécution

kubectl exec -t $netserver-pod-1 -- netperf –l 30 -i 10 -I 99,1 -c -j -H
$netserver-pod-2-ip -t OMNI -- -T tcp -D -O
DÉBIT,THROUGHPUT_UNITS,MEAN_LATENCY,MIN_LATENCY,MAX_LATENCY,P50_LATENCY,P90_LATENCY,P99_LATENCY,STDDEV_LATENCY,LOCAL_CPU_UTIL

devrait vous donner une répartition décente des statistiques, y compris la latence et
débit.
Vous pouvez exécuter le conteneur netserver en utilisant docker run --net=host à faire
node->pod tests aussi.

Le fichier docker de ce conteneur est assez simple, je peux le déclencher si
vous voulez l'étendre à quelque chose de plus léger (par exemple, un
conteneur pour une traction plus rapide).

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
<
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-130524576

.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-130527558
.

Vrai. Je pense que @thockin a mentionné vouloir éventuellement un test de latence e2e comme
bien. Si le temps le permet, il y aura un certain nombre de tests différents et nous
devra probablement tenir compte de gce vs AWS, etc.
Le 13 août 2015 à 13 h 47, "Paul Tiplady" [email protected] a écrit :

Vous pouvez faire du pod netserver un service, de sorte que le trafic de perf <->
serveur passe par le service VIP. De cette façon, vous n'avez pas à faire le
calculs d'échantillonnage/latence vous-même...

Le mer. 12 août 2015 à 21h20, Benjamin Elder [email protected]
a écrit:

Merci je vais regarder ça.

De [ce commentaire](

https://github.com/kubernetes/kubernetes/pull/9210#issuecomment-130154261)
bien que je pense que nous voulons faire une sorte de latence de demande de service. Droit
maintenant, j'essaie d'utiliser le conteneur nginx standard en tant que nœud X et de travailler
au
avoir un temps de test pod le frappant à plusieurs reprises afin que nous puissions construire un graphique sur
nœud Y.

Je vais regarder netperf/qperf cependant, et nous pouvons toujours avoir plusieurs tests.
J'aimerais que ce graphique soit fait en premier, mais selon la discussion précédente avec
@thockin

Le jeu. 13 août 2015 à 00:02, Paul Tiplady < [email protected]

a écrit:

@BenTheElder https://github.com/BenTheElder Je viens de faire quelques
raisonnablement
mesures détaillées des performances du réseau sur GCE - je vous recommande de jeter un œil
à
netperf (qperf donne également des mesures de latence).

netperf est un outil de perf client/serveur, j'ai empaqueté à la fois le client
et
le serveur dans le conteneur docker paultiplady/ netserver:ubuntu.2.

il y a beaucoup d'options sur netperf, mais quelque chose comme en faire tourner deux
pods netserver et en cours d'exécution

kubectl exec -t $netserver-pod-1 -- netperf –l 30 -i 10 -I 99,1 -c -j
-H
$netserver-pod-2-ip -t OMNI -- -T tcp -D -O

DÉBIT,THROUGHPUT_UNITS,MEAN_LATENCY,MIN_LATENCY,MAX_LATENCY,P50_LATENCY,P90_LATENCY,P99_LATENCY,STDDEV_LATENCY,LOCAL_CPU_UTIL

devrait vous donner une répartition décente des statistiques, y compris la latence et
débit.
Vous pouvez exécuter le conteneur netserver en utilisant docker run --net=host à faire
node->pod tests aussi.

Le fichier docker de ce conteneur est assez simple, je peux le déclencher
si
vous voulez l'étendre à quelque chose de plus léger (par exemple, un
conteneur pour une traction plus rapide).

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
<

https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-130524576

.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
<
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-130527558

.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-130776866
.

@Symmetric les tests netperf fonctionnent bien. Merci pour la suggestion :-)

J'aimerais revoir le test pour une charge "réelle" comme un service Web plus tard éventuellement, mais après avoir obtenu les bons arguments, cela donne de très bonnes données jusqu'à présent. Je posterai les résultats plus tard quand j'aurai fini de nettoyer les choses.

Heureux d'apprendre que cela fonctionne pour vous - il y a un nombre ahurissant de
options sur cet outil, mais il s'est avéré très utile pour mon travail de profilage.
Certainement mieux que iperf...

Le jeu. 13 août 2015 à 14:32, Benjamin Elder [email protected]
a écrit:

@Symmetric https://github.com/Symmetric les tests netperf fonctionnent
bien. Merci pour la suggestion :-)

J'aimerais revoir le test pour une "vraie" charge comme un service Web plus tard
peut-être, mais après avoir obtenu les bons arguments, cela donne de très bonnes données, donc
loin. Je posterai les résultats plus tard quand j'aurai fini de nettoyer les choses.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130850398
.

@thockin Je pense que nous pouvons vivre avec SNAT pour le trafic LB. Ma réflexion actuelle est que vous devrez spécifier la politique d'accès d'un pod comme l'une des suivantes :

  • la valeur par défaut est « autoriser à partir de [mon espace de noms] », auquel cas les paquets LB sont supprimés
  • 'autoriser à partir de [liste d'espaces de noms]', ou 'autoriser à partir de [tous les espaces de noms du cluster]', encore une fois les paquets LB sont toujours supprimés
  • 'autoriser de tous', auquel cas nous ne nous soucions pas de savoir si cela vient d'un LB, d'un autre nœud ou de n'importe où

Donc, perdre l'IP source pour les LB seulement ne nous coûte pas grand-chose.

Si nous pouvons garantir que le LB atteint le bon nœud pour le pod de service, ce serait formidable. service, et en diminuant le trafic autrement.

En ce qui concerne les publicIP, je pense qu'ils auront les mêmes considérations que nodePort, et nous devrons donc les SNAT jusqu'à ce que les LB puissent atteindre les bons hôtes. Ce qui, selon ce qui précède, est bien, à moins que je n'oublie qu'ils sont plus diaboliques que nodePort ...

Par mesure de sécurité, il pourrait être très utile d'inclure en fait un drapeau pour proxy à tout MASQUERADE (agissant très près d'un proxy en espace utilisateur). Je pense que ce n'est pas très compliqué à faire et un très bon moyen de diagnostiquer voire de repli en cas de problème (je pense aux cas vxlan).

-------- Message d'origine --------
De : Paul Tiplady [email protected]
Date : 14/08/2015 12:50 (GMT+11:00)
À : kubernetes/kubernetes [email protected]
Cc : Mikaël Cluseau [email protected]
Objet : Re : [kubernetes] utilise iptables pour le proxy au lieu de l'espace utilisateur
(#3760)

@thockin Je pense que nous pouvons vivre avec SNAT pour le trafic LB. Ma réflexion actuelle est que vous devrez spécifier la politique d'accès d'un pod comme l'une des suivantes :

la valeur par défaut est « autoriser à partir de [mon espace de noms] », auquel cas les paquets LB sont supprimés
'autoriser à partir de [liste d'espaces de noms]', ou 'autoriser à partir de [tous les espaces de noms du cluster]', encore une fois les paquets LB sont toujours supprimés
'autoriser de tous', auquel cas nous ne nous soucions pas de savoir si cela vient d'un LB, d'un autre nœud ou de n'importe où

Donc, perdre l'IP source pour les LB seulement ne nous coûte pas grand-chose.

Si nous pouvons garantir que le LB atteint le bon nœud pour le pod de service, ce serait formidable. service, et en diminuant le trafic autrement.

En ce qui concerne les publicIP, je pense qu'ils auront les mêmes considérations que nodePort, et nous devrons donc les SNAT jusqu'à ce que les LB puissent atteindre les bons hôtes. Ce qui, selon ce qui précède, est bien, à moins que je n'oublie qu'ils sont plus diaboliques que nodePort ...

-
Répondez directement à cet e-mail ou consultez-le sur GitHub.

@MikaelCluseau ce n'est pas une mauvaise idée - pouvez-vous s'il vous plaît ouvrir un nouveau numéro à ce sujet spécifiquement, afin que je ne le perde pas de vue ?

Toujours à FAIRE : corriger l'épingle à cheveux, e2e, activer par défaut

Salut Tim, désolé de ne pas être revenu vers toi, mais nous avons eu un peu de gâchis à gérer ici... Je vais choisir l'épingle à cheveux fixe samedi prochain je pense.

C'était une note pour moi - aviez-vous l'intention de vous attaquer à certains de ces problèmes ? :)

Oui, bien sûr, comme je l'ai dit lorsque nous parlions des tests e2e. Je vais aider, Kubernetes m'est d'une grande aide, donc je ferais mieux de le maîtriser au maximum, et quoi de mieux que de prendre des bugs ? :-) N'hésitez pas à suggérer quelque chose de plus prioritaire, mais je pense que l'épingle à cheveux est assez bonne pour commencer. Il doit avoir lieu dans le kubelet et avoir un drapeau à activer (désactivé par défaut au départ). Je vais essayer de travailler 0,5 à 1 jour par semaine.

AFAIK, il ne reste plus qu'à en faire la valeur par défaut, ce qui peut arriver (en supposant qu'il n'y ait pas d'explosion) quelque temps après la v1.1 et cela a quelques kilomètres.

Waouh !

Le jeu. 24 sept. 2015 à 11h21, Tim Hockin [email protected]
a écrit:

AFAIK, il ne reste plus qu'à en faire la valeur par défaut qui peut
arriver (en supposant qu'il n'y ait pas d'explosions) quelque temps après la v1.1 et cela a quelques kilomètres
dessus.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -142960614
.

quelque temps après la v1.1 et cela a quelques kilomètres dessus.

Aie. On comptait vraiment dessus pour 1.1....
https://github.com/kubernetes/kubernetes/blob/master/docs/roadmap.md

@bgrieder, vous pouvez toujours l'activer via le paramètre.

C'est IN mais pas activé par défaut. Vous pouvez vous inscrire avec une seule annotation par
node (et un redémarrage kube-proxy)

Le jeu. 24 sept. 2015 à 8h27, Bruno G. [email protected] a écrit :

quelque temps après la v1.1 et cela a quelques kilomètres dessus.

Aie. On comptait vraiment dessus pour 1.1....
https://github.com/kubernetes/kubernetes/blob/master/docs/roadmap.md

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -142962932
.

@thockin @bnprss ok mais nous nous attendons à ce que la version 1.1 s'exécute sur Google Container Engine après sa sortie. Je me demande quelle sorte de flexibilité nous aurons pour « s'inscrire avec une seule annotation par nœud ». Pourriez-vous s'il vous plaît nous donner quelques détails sur ce que sera le processus ou nous indiquer de la documentation ?

Une fois mis à niveau vers 1.1 :

$ for node in $(kubectl get nodes -o name); do kubectl annotate $node net.beta.kubernetes.io/proxy-mode=iptables; done

Ensuite, SSH sur chaque nœud et redémarrez kube-proxy (ou redémarrez chaque nœud).

Si vous voulez être plus prudent, faites un ou deux nœuds puis essayez-le :)

J'ai marqué ce problème comme "note de version" afin que nous n'oubliions pas d'inclure cette boucle magique dans notre documentation 1.1.

@RichieEscarez

(Je voulais juste passer et dire que nous utilisons le proxy iptables depuis une semaine maintenant et que tout semble ok!)

@thockin Cela doit-il être fermé ou supprimé du jalon 1.1 ?

Je vais le déplacer vers 1.2 juste pour l'activation par défaut.

Toutes nos excuses pour une question potentiellement stupide, mais concernant la préservation des adresses IP client :

@thockin J'ai vu dans un autre numéro du 2 septembre que "seul le trafic intra-cluster conserve l'adresse IP du client" - est-ce toujours vrai pour l'alpha 1.2 ?

Nous avons lancé un nouveau cluster 1.2, appliqué l'annotation de nœud, redémarré et toujours voir 10.244.0.1 comme adresse source pour toutes les requêtes adressées à un pod exécutant HAProxy.

À ce stade, j'essaie simplement de déterminer si nous avons manqué un paramètre ou si j'essaie de réaliser quelque chose qui n'est pas encore possible - c'est-à-dire voir l'adresse IP publique du client réel faisant la demande à partir de en dehors du cluster.

La valeur par défaut utilise toujours le mode espace utilisateur. Vous devez définir une annotation sur
le nœud (net.beta.kubernetes.io/proxy-mode=iptables) et redémarrez le
Procuration. Mais cela n'exposera pas les adresses IP des clients externes, juste intra cluster
IP.
Le 23 octobre 2015 à 17h09, "Ben Hundley" [email protected] a écrit :

Des excuses pour une question potentiellement stupide, mais concernant la préservation
des IP clientes :

@thockin https://github.com/thockin J'ai vu dans un autre numéro le 2 septembre
que "seul le trafic intra-cluster conserve l'adresse IP du client" - est-ce toujours
vrai pour l'alpha 1.2?

Nous avons lancé un nouveau cluster 1.2, appliqué l'annotation de nœud, redémarré,
et toujours voir 10.244.0.1 comme adresse source pour toutes les demandes faites à un
pod exécutant HAProxy.

À ce stade, j'essaie simplement de savoir si nous avons ou non raté un
réglage ou j'essaie de réaliser quelque chose qui n'est pas encore possible - qui
voit l'adresse IP publique du client effectuant la demande
de l'extérieur du cluster.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-150725513
.

Je suis capable de conserver l'adresse IP du client externe en effectuant le DNAT du trafic externe + le routage via un proxy kube. Par exemple, si votre réseau de service est 10.42.0.0/16 et que vous disposez d'un kube-proxy hautement disponible sur l'IP 10.10.1.1, vous pouvez avoir la règle iptable suivante :

-A PREROUTING -i public -p tcp -m tcp --dport 25 -j DNAT --to-destination 10.42.12.34

et le parcours suivant :

10.42.0.0/16 via 10.10.1.1 dev edge 

Le pod derrière voit alors la véritable IP :

Oct 24 02:41:39 email-0yr7n mail.info postfix/smtpd[469]: connect from zed.yyy.ru.[94.102.51.96]

Vous devez bien sûr avoir le bon chemin de retour du paquet.

Ouais, si ce DNAT vers un backend hors machine, vous formez un triangle sans
SNAT. C'est le problème fondamental.

Le ven 23 oct 2015 à 20h12, Mikaël Cluseau [email protected]
a écrit:

Je suis capable de garder l'IP du client externe en DNAT'ing le trafic externe +
routage via un kube-proxy. Par exemple, si votre réseau de service est
10.42.0.0/16 et vous disposez d'un kube-proxy hautement disponible sur l'IP
10.10.1.1, vous pouvez avoir la règle iptable suivante :

-A PREROUTING -i public -p tcp -m tcp --dport 25 -j DNAT --to-destination 10.42.12.34

et le parcours suivant :

10.42.0.0/16 via le bord de développement 10.10.1.1

Le pod derrière voit alors la véritable IP :

24 octobre 02:41:39 email-0yr7n mail.info postfix/smtpd[469] : connectez-vous à partir de zed.yyy.ru.[94.102.51.96]

Vous devez bien sûr avoir le bon chemin de retour du paquet.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-150747217
.

Cela semble intéressant, un lien? :-) J'essaie de trouver un moyen d'être sûr que le paquet passera par la bonne règle de conntrack. Je pensais à répliquer l'état de conntrack via le cluster.

Je suis un peu perdu avec ce que vous essayez de réaliser.

La façon dont le proxy iptables actuel est censé fonctionner est qu'un paquet
arrive à un nœud, nous détectons qu'il n'est pas généré localement, le signalons pour
SNAT, choisissez un backend, transférez vers le backend avec SNAT, le backend répond
pour nous, nous dé-SNAT, non-DNAT et répondons à un utilisateur externe.

Le ven 23 oct 2015 à 21h32, Mikaël Cluseau [email protected]
a écrit:

Cela semble intéressant, un lien? :-) J'essaie de trouver un moyen d'être sûr que le
paquet passera par la bonne règle conntrack. Je pensais à
réplication de l'état conntrack via le cluster.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-150753147
.

Oh, désolé si je ne suis pas clair. Je parlais du cas sans SNAT. Si chaque kube-proxy a la même liste de conntrack, n'importe lequel d'entre eux devrait être capable d'annuler le DNAT correctement lorsque le conteneur répond au client.

Je ne pouvais pas voir un was sans réplication qui n'implique pas HA pour conserver une structure en forme de ligne comme celle-ci :

[client] ----- [proxy in HA] ------ [node1]
                           `------- [node2]

Mais si une chose en forme de triangle peut fonctionner, elle devrait ouvrir plus de possibilités.

[client] ----- [proxy1] ------ [node1]
       `------ [proxy2] ------ [node2]

Ce serait mignon mais semble fou compliqué

Le dim 25 oct 2015 à 23h20, Mikaël Cluseau [email protected]
a écrit:

Oh, désolé si je ne suis pas clair. Je parlais du cas sans SNAT. Si
chaque kube-proxy a la même liste de conntrack, n'importe lequel d'entre eux devrait pouvoir
un-DNAT correctement lorsque le conteneur répond au client.

Je ne pouvais pas voir un was sans réplication qui n'implique pas HA pour garder un
structure en forme de ligne comme celle-ci :

[client] ----- [proxy dans HA] ------ [node1]
`------- [nœud2]

Mais si une chose en forme de triangle peut fonctionner, elle devrait ouvrir plus de possibilités.

[client] ----- [proxy1] ------ [node1]
`------ [proxy2] ------ [nœud2]

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -151037663
.

La voie que je dois explorer (je n'ai pas et n'aime pas demander avant une recherche appropriée mais puisque le sujet est maintenant ouvert...) est le "Routage multi-chemin asymétrique" que vous pouvez voir ici : http:// conntrack-tools.netfilter.org/manual.html#sync-aa . Et oui, ce serait vraiment très sympa :-)

La chose la plus simple qui puisse fonctionner...

  1. proxy1 reçoit une nouvelle connexion via un hook iptables (je pense l'avoir vu quelque part), et son LB l'affecte au nœud du proxy2.
  2. proxy1 envoie une requête du type "configurer une entrée conntrack pour {src-ip} :{src-port} -> {pod-ip} :{pod-port}"
  3. proxy2 reçoit la demande, configure l'entrée conntrack et l'accuse à proxy1
  4. proxy1 laisse le paquet passer par la règle DNAT (qui met également une entrée conntrack dans proxy1).
  5. lorsque le pod répond, l'hôte du proxy2 est unDNAT en conséquence.
  6. lorsque le client envoie un autre paquet sur ce flux via proxy1, l'entrée conntrack fait également le bon DNAT.

De cette façon, le surcoût est de 2 paquets par nouvelle connexion, et rapidement remboursé en évitant un-SNAT + routage supplémentaire (car sinon le paquet doit repasser par proxy1).

Je ne suis pas un gars du réseau, donc je suppose peut-être trop, mais cela semble raisonnable.

Dans mon cas, je visais à établir des règles de pare-feu, par service NodePort.

Il semble que je puisse ajouter de simples règles ALLOW IP / DROP tout le reste dans la chaîne INPUT, comme ceci :

iptables -A INPUT -s $WHITELISTED_IP -p tcp --dport $CONTAINER_PORT -j ACCEPT
iptables -A INPUT -p tcp --dport $CONTAINER_PORT -j DROP

Pour appliquer ces règles, j'envisageais d'utiliser des annotations sur les services NodePort. Les annotations contiendraient des adresses IP sur liste blanche.

Comme je peux attendre un peu que ces règles s'appliquent, j'ai imaginé une tâche cron minutieusement sur chaque serviteur et mettant à jour la chaîne INPUT du serviteur à partir de toutes les annotations de service.

Y a-t-il quelque chose qui pourrait causer un problème ici? Suis je fou?

@thockin a une meilleure vue que moi, mais je n'utiliserais pas d'annotation pour cela. Je pense que la sécurité est orthogonale et devrait être mise de côté dans un système, ou peut-être dans un plugin réseau/proxy. Si vous avez Kubernetes, vous avez etcd, vous pouvez donc simplement stocker un ensemble de règles dans une clé et mettre à jour avec etcdctl watch/exec :

# while true; do etcdctl watch "/iptables/$(hostname)" && etcdctl get /iptables/$(hostname) |iptables-restore --noflush; done &
# iptables -F my-filter
# iptables -nvL my-filter
Chain my-filter (0 references)
 pkts bytes target     prot opt in     out     source               destination      
# ~nwrk/go/bin/etcdctl set /iptables/$(hostname) >/dev/null <<EOF
*filter
:my-filter -
-A my-filter -j ACCEPT -s 1.2.3.4 -p tcp --dport 80
-A my-filter -j DROP -p tcp --dport 80
COMMIT
EOF
# iptables -nvL my-filter
Chain my-filter (0 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     tcp  --  *      *       1.2.3.4              0.0.0.0/0            tcp dpt:80
    0     0 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80

Je pense que tu veux #14505

Le lundi 26 octobre 2015 à 8h53, Ben Hundley [email protected]
a écrit:

Dans mon cas, je visais à établir des règles de pare-feu, par service NodePort.

Il semble que je puisse ajouter de simples règles ALLOW IP / DROP tout le reste dans
la chaîne INPUT, comme ceci :

iptables -A INPUT -s $WHITELISTED_IP -p tcp --dport $CONTAINER_PORT -j ACCEPTER
iptables -A INPUT -p tcp --dport $CONTAINER_PORT -j DROP

Pour appliquer ces règles, ce que j'envisageais était d'utiliser des annotations sur le
Services NodePort. Les annotations contiendraient des adresses IP sur liste blanche.

Comme je peux attendre un peu que ces règles s'appliquent, j'ai imaginé une minute
tâche cron sur chaque sbire entrant et mettant à jour l'ENTRÉE du sbire
chaîne de toutes les annotations de service.

Y a-t-il quelque chose qui pourrait causer un problème ici? Suis je fou?

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -151181267
.

C'était l'approche initiale, avec des groupes de sécurité attachés aux équilibreurs de charge. Je viens d'atteindre assez rapidement la limite d'auditeurs par interface réseau sur AWS et je suis tombé sur une logique velue en essayant de répartir les règles de pare-feu sur plusieurs SG et plusieurs ELB pour un seul cluster kube.

Heureusement, nous sommes sur une meilleure solution qui n'implique pas de déconner avec iptables.

Si vous venez de rejoindre, permettez-moi de résumer. Tous les problèmes concernant l'impossibilité d'obtenir l'adresse IP du client ont été fusionnés dans ce problème, mais la solution proposée (et mise en œuvre) ne le résout pas. Vous n'avez actuellement aucun moyen d'accéder à l'adresse IP du client. Ha.

@ shaylevi2 il n'y a actuellement aucun bon moyen d'obtenir l'adresse IP du client tout en rebondissant à travers un cloud LB et sur un nodePort. Une fois le cloud LB rattrapé, je sauterai dessus. Mais cela préserve l'adresse IP du client au sein du cluster

Mais cela préserve l'adresse IP du client au sein du cluster

Cela dépend exactement de la façon dont la mise en réseau du cluster est configurée ; par exemple, cela ne fonctionne pas correctement dans OpenShift pour le moment, car les règles iptables ne sont pas exécutées sur le trafic interne d'OVS. Ainsi, les paquets reçoivent un DNAT entrant dans le point de terminaison du service, mais comme l'adresse IP source est interne au cluster, la réponse restera dans OVS, de sorte qu'elle n'atteint plus iptables, de sorte que le DNAT ne soit pas inversé, le pod client ne reconnaît donc pas les paquets. Pour le moment, la solution de contournement la plus simple consiste à masquer complètement les paquets entrant dans le point de terminaison, les forçant à être à nouveau renvoyés d'OVS à la sortie. (Je travaille à trouver un moyen de contourner cela.)

OVS a-t-il une notion VIP en interne ? Tu pourrais juste te débarrasser
kube-proxy (cf opencontrail)

Le vendredi 20 novembre 2015 à 7h09, Dan Winship [email protected]
a écrit:

Mais cela préserve l'adresse IP du client au sein du cluster

Cela dépend exactement de la façon dont la mise en réseau du cluster est configurée ; par exemple, ce n'est pas le cas
fonctionne correctement dans OpenShift pour le moment, car les règles iptables ne sont pas exécutées
sur le trafic interne d'OVS. Donc les paquets sont DNAT pour entrer dans le service
point de terminaison, mais comme l'adresse IP source est interne au cluster, la réponse sera
rester dans OVS, donc il n'atteint plus iptables, donc le DNAT'ing ne le fait pas
être inversé, de sorte que le pod client ne reconnaît pas les paquets. Au
moment, la solution de contournement la plus simple consiste à masquer complètement les paquets
entrer dans le point de terminaison, les forçant à être à nouveau renvoyés d'OVS sur
l'issue. (Je travaille à trouver un moyen de contourner cela.)

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -158426296
.

Nous avions parlé de faire essentiellement l'équivalent du pur-iptables-proxying entièrement dans OVS, mais cela nécessite le support de conntrack OVS, qui nécessite un noyau très récent, dont nous ne voulons pas encore dépendre. C'est probablement le plan à long terme cependant.

(Pour l'instant, il semble que nous puissions le faire fonctionner en ajoutant un saut supplémentaire gratuit d'OVS pour les paquets avec un IP source + un port correspondant à un point de terminaison de service connu provenant d'une interface de conteneur ; le nœud le dé-DNAT alors éventuellement , puis renvoyez-le dans OVS où il peut être remis correctement au pod client.)

J'espère écrire un document sur l'abstraction Service VIP et le faire
clair que c'est une abstraction qui peut être remplacée (et devrait être dans certains
cas).

Le lundi 23 novembre 2015 à 6h54, Dan Winship [email protected]
a écrit:

Nous avions parlé de faire essentiellement l'équivalent de la
pure-iptables-proxying entièrement dans OVS, mais cela nécessite OVS conntrack
support, qui nécessite un noyau très récent, dont nous ne voulons pas dépendre
sur encore. C'est probablement le plan à long terme cependant.

(Pour l'instant, il semble que nous puissions le faire fonctionner en ajoutant un supplément gratuit
sortir d'OVS pour les paquets avec une source IP+port correspondant à un service connu
point de terminaison provenant d'une interface de conteneur ; le nœud sera alors
éventuellement un-DNAT, puis le renvoyer dans OVS où il peut obtenir
correctement renvoyé au pod client.)

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -158959014
.

Bien que iptables/nftables résolve à la fois les cas d'utilisation de l'équilibrage de charge TCP et UDP, je pense personnellement qu'IPVS https://github.com/kubernetes/kubernetes/issues/17470 serait un bien meilleur ajustement car il est spécialement conçu pour l'équilibrage de charge (lire : moins de changements/maintenance en cours pour l'équipe k8s), offre un ensemble plus riche d'algorithmes d'équilibrage de charge, a prouvé sa stabilité à des vitesses proches du débit de ligne, amd dispose également de bibliothèques golang prêtes à manipuler les règles.

@thockin , autres, selon https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -150743158, j'ai fait l'annotation, mais comme mentionné à juste titre, l'adresse IP du client externe n'est toujours pas vue par l'application située dans un conteneur .

Comment y parvenir, c'est-à-dire obtenir l'adresse IP du client externe ? Dans ma configuration, il n'y a pas de LB externe, le service est exposé en tant que nodeport et le client établit une connexion TCP simple (pas http/Websocket) à mon application conteneurisée.

@ashishvyas quelle version de kube-proxy utilisez-vous ?

J'utilise la v1.1.3

Suivez les instructions dans https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -143280584 et https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -150743158 mais au lieu d'utiliser l'annotation nommée net.beta.kubernetes.io/proxy-mode , utilisez l'annotation nommée net.experimental.kubernetes.io/proxy-mode .

for node in $(kubectl get nodes -o name); do
  kubectl annotate $node net.experimental.kubernetes.io/proxy-mode=iptables;
done

Vous devriez voir des instructions de journal au début du démarrage de kube-proxy telles que « Annotation expérimentale trouvée » et « Annotation autorise le proxy iptables »

La première version que https://github.com/kubernetes/kubernetes/commit/da9a9a94d804c5bfdf3cc86ee76a2bc1a2742d16 en a fait était 1.1.4 donc net.beta.kubernetes.io/proxy-mode ne fonctionne pas pour beaucoup de gens. Vous n'êtes pas la première personne à rencontrer cela.

En raison du fonctionnement du proxy, nous perdons l'IP du client lors de son passage
un port de nœud. Je sais que ce n'est pas génial. C'est très important dans mon esprit comment
résoudre ce problème correctement, mais cela dépend principalement des capacités du
équilibreurs de charge (ou les autres moyens par lesquels le trafic arrive à un nœud, comme
comme DNS-RR)

Le mercredi 13 janvier 2016 à 10h25, Mike Danese [email protected]
a écrit:

Suivez les indications au #3760 (commentaire)
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -143280584
et #3760 (commentaire)
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-150743158
mais au lieu d'utiliser l'annotation nommée
net.beta.kubernetes.io/proxy-mode, utilisez l'annotation nommée
net.experimental.kubernetes.io/proxy-mode.

pour le nœud dans $(kubectl get nodes -o name); faire
kubectl annoter $node net.experimental.kubernetes.io/proxy-mode=iptables ;
terminé

Vous devriez voir des instructions de journal au début du démarrage de kube-proxy
comme « Annotation expérimentale trouvée » et « L'annotation autorise le proxy iptables »

La première version que da9a9a9
https://github.com/kubernetes/kubernetes/commit/da9a9a94d804c5bfdf3cc86ee76a2bc1a2742d16
l'a fait était 1.1.4. Vous n'êtes pas la première personne à rencontrer cela.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-171387997
.

@thockin , une solution de contournement pour résoudre temporairement ce problème est-elle possible dès maintenant ? Si oui, je recommanderais de fournir des étapes détaillées pour moi et d'autres sur ce fil pourraient aider.

Non, il n'y a pas de véritable solution de contournement pour le moment. Le problème se résume au
fait que chaque kube-proxy peut choisir un backend sur un nœud différent.
Le transfert du trafic avec l'adresse IP du client d'origine aurait l'autre nœud
répondre directement, ce qui ne fonctionnera évidemment pas.

Le « correctif » consiste à envoyer _uniquement_ du trafic pour le service S aux nœuds qui ont au
au moins 1 backend pour que S _and_ envoie du trafic proportionnel au nombre
backends de chaque nœud. Kube-proxy pourrait alors choisir des backends locaux
exclusivement.

Considérez 2 nœuds et 3 backends. Un nœud finit nécessairement par 2
backends. Quelles que soient les routes, le trafic doit envoyer 2 fois plus à un nœud qu'il
fait à un autre nœud. Nous n'avons tout simplement pas encore abordé ce problème - aucun des
les équilibreurs de charge cloud prennent en charge cela, donc c'est en quelque sorte spéculatif et
donc très risqué de commencer à travailler dessus.

Le mercredi 13 janvier 2016 à 12h17, Ashish Vyas [email protected]
a écrit:

@thockin https://github.com/thockin , toute solution de contournement pour temporairement
l'adresse c'est possible en ce moment? Si oui, je recommanderais de fournir
des étapes détaillées pour moi et d'autres sur ce fil aideraient.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-171420567
.

@mikedanese , je ne semble pas pouvoir trouver 1.1.4 sur gcr.io :

$ sudo docker pull gcr.io/google_containers/ hyperkube:v1.1.4
Extraction du référentiel gcr.io/google_containers/hyperkube
Balise v1.1.4 introuvable dans le référentiel gcr.io/google_containers/hyperkube
$ sudo docker pull gcr.io/google_containers/ hyperkube:v1.1.3
v1.1.3 : Extraire de google_containers/hyperkube
Résumé : sha256:004dde049951a4004d99e12846e1fc7274fdc5855752d50288e3be4748778ca2
Statut : L'image est à jour pour gcr.io/google_containers/hyperkube:v1.1.3

@thockin Toutes mes excuses pour la longue réponse, je voulais couvrir les deux méthodes avec

En arrière-plan, notre application principale est une plate-forme DNS intelligente à très hautes performances (c'est-à-dire qu'elle a besoin d'UDP et doit faire au moins 100 000 requêtes/secondes par pod), et son application de support dans un proxy SNI qui a besoin de voir les clients réels Adresse IP (c'est un obstacle pour nous). Nous ne voulions pas utiliser différentes approches de mise en réseau pour différentes applications, nous avons donc décidé de standardiser sur une seule méthode de réseau pour tous, et nous avons choisi d'utiliser IPVS pour les raisons que j'ai mentionnées ci-dessus (performances/stabilité/flexibilité/construction SLB) , mais vous pourriez probablement pirater quelque chose ensemble en utilisant simplement iptables dans le même sens. Nous utilisons vxlan (rapide, facile, fonctionne entre les sites) mais ces deux méthodes devraient également fonctionner avec GRE/VXLAN avec OVS ou avec un réseau hôte standard de couche 2 (en supposant que vos hôtes soient tous sur le même réseau L2).

Nous distribuons le trafic d'utilisateur final entrant en utilisant un mélange d'anycast et de DNS, en fonction des exigences de vitesse de basculement ou de ce qui fonctionne le mieux pour le type de service particulier, nous avons donc une distribution assez uniforme du trafic d'utilisateur final entrant dans nos nœuds, mais le Le problème, comme vous l'avez souligné, est alors d'obtenir une répartition uniforme du trafic entre les pods, quel que soit l'emplacement des pods. L'autre problème est de s'assurer que les services qui communiquent avec d'autres services sont équilibrés de manière efficace.

Nous avons essayé deux modèles pour résoudre ce problème :

La première méthode que nous avons essayée était 2 couches de VIP. VIP externes (1 par service), qui distribuent le trafic entre les nœuds (en fonction du nombre de pods pour ce service sur le nœud), puis les VIP internes (qui s'exécutent sur le nœud avec les pods), qui distribuent la charge au sein des nœuds (généralement uniformément sur les gousses). La limitation de ce modèle était que les nœuds exécutant des VIP externes devaient exécuter deux espaces de noms de réseau différents ou exécuter leurs propres nœuds physiques. La bonne chose avec IPVS en mode DSR (direct server return) est qu'il n'a pas besoin de voir le trafic de retour, le trafic va :

Consumer >> (over L3) >> External VIP node >> (1) >> Internal VIP node >> (2) >> Container >> (any which way you want) >> Consumer

(1) IPVS (en mode DSR) sur l'hôte avec un VIP externe choisit un _nœud_ vers lequel envoyer le trafic (un "vrai serveur" en termes IPVS), et ne modifie que l'adresse MAC DST du paquet (c'est-à-dire que le paquet IP arrive inchangé à nœud k8s). Il équilibre la charge entre les nœuds en fonction du nombre de pods exécutant ce service sur le nœud.
(2) IPVS (également en mode DSR) sur le nœud k8s équilibre la charge du trafic entre les pods (via les veths vers le nœud). Les réponses des conteneurs (TCP et UDP) retournent directement au consommateur du service.

L'avantage de ce modèle, c'est qu'il était vraiment simple à démarrer et que l'ensemble de règles était très facile à gérer. L'inconvénient de ce modèle est qu'il concentre toutes nos demandes de service (mais pas les réponses) via un certain nombre de nœuds exécutant les VIP externes. Nous aimons "shared-nothing", alors, entrez la version 2 :

Le deuxième modèle est maintenant divertissant est une seule couche de VIP avec une configuration IPVS et iptables plus intelligente.

Consumer >> Any node/local node >> (1) >> Container >> (any which way you want) >> Consumer
ou, il peut aller vers un autre nœud :
Consumer >> Any node/local node >> (1) >> Remote Node >> (2) >> Container >> (any which way you want) >> Consumer

(1) Le trafic atteint le VIP principal, le trafic est équilibré sur tous les pods du cluster.
(2) Le trafic atteint le VIP secondaire, le trafic est équilibré en charge uniquement sur tous les pods locaux. Ce VIP secondaire n'est utilisé que pour le trafic provenant d'autres hôtes sur le réseau (c'est un VIP FWMARK). Nous marquons le trafic entrant dans n'importe quelle interface externe avec FWMARK=1234, et cela force le trafic à aller vers un ensemble de règles différent, ce qui empêche les boucles entre les nœuds.

Le VIP principal a une liste de pods locaux et d'hôtes distants avec des pods (le poids étant de 100 pour chaque pod local et de 100 * nombre de pods pour les nœuds distants). Ainsi, par exemple, si 3 pods s'exécutent localement sur nodeA et qu'il y a deux pods exécutés sur nodeB, l'ensemble de règles sur nodeA ressemblera à ceci :

Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP service.ip.address:0 rr persistent 360
-> pod1.on.nodeA.ip:80 Route 100 0 0
-> pod2.on.nodeA.ip:80 Route 100 0 0
-> pod2.on.nodeA.ip:80 Route 100 0 0
-> interfaceip.of.nodeB:80 Route 200 0 0
FWM 1234 rr
-> pod1.on.nodeA.ip:80 Route 100 0 0
-> pod2.on.nodeA.ip:80 Route 100 0 0
-> pod3.on.nodeA.ip:80 Route 100 0 0

Cependant, sur nodeB, la configuration IPVS serait un peu différente car elle n'a que deux pods locaux et trois pods distants sur nodeA :

Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP service.ip.address:0 rr persistent 360
-> pod1.on.nodeB.ip:80 Route 100 0 0
-> pod2.on.nodeB.ip:80 Route 100 0 0
-> interfaceip.of.nodeA:80 Route 300 0 0
FWM 1234 rr
-> pod1.on.nodeB.ip:80 Route 100 0 0
-> pod2.on.nodeB.ip:80 Route 100 0 0

Une autre façon serait de changer les FWMARK et d'utiliser iptables pour FWMARK n'importe quoi dans les interfaces veth + (concordance avec caractères génériques) et d'utiliser la correspondance FWMARK uniquement pour l'équilibrage de charge local.

Parce qu'il n'y a pas de NAT impliqué ici, vous devez ajouter les IP SVC_XXX_YYY dans l'environnement à une interface de bouclage ou factice lorsque vous démarrez chaque pod, mais vous pouvez probablement aussi changer les IPVS IPVS pour faire aussi DNAT, je ne vois pas pourquoi ça ne marcherait pas.

Le résultat final est la mise en réseau la plus directe, sans avoir besoin de centraliser le traitement/routage des demandes, ce qui permet une bien meilleure évolutivité. L'inconvénient réside dans l'intelligence supplémentaire lors de la création des règles IPVS. Nous utilisons un petit démon (golang) pour faire tout cela, mais j'envisagerais d'écrire un module k8s pour cela si j'avais le temps et qu'il y avait suffisamment d'intérêt.

Je me penche tard sur ce problème et je n'ai probablement pas lu le parcours complet avec suffisamment de détails, mais juste au cas où cela aiderait : si j'ai compris le @qoke ci-dessus, ils veulent utiliser des VIP, pas des ports de nœud . L'une des préoccupations soulevées plus tôt dans le fil était que l'adresse IP source n'était pas maintenue lors de l'utilisation du kubeproxy iptables. Cependant, il est maintenu si vous utilisez le service VIP et non la fonction de port de nœud, je crois. (De toute façon, comme je l'ai dit, je n'ai pas vraiment lu la piste complète, donc si ces commentaires sont évidents ou inutiles, alors s'il vous plaît ignorez! J'essaierai de prendre le temps de la lire en profondeur la semaine prochaine quand je serai de retour des vacances.)

@lxpollitt Correct, l'adresse IP source est conservée lors de l'utilisation d'IPVS, mais gardez à l'esprit qu'avec cette méthode, nous devions pratiquement tout mettre en réseau nous-mêmes, car la configuration d'IPVS n'est pas prise en charge par kube-proxy. Vous pouvez également conserver l'adresse IP source avec iptables, mais vous avez besoin de deux couches d'IPtables DNAT pour pouvoir "déconnecter" le trafic sur le chemin du retour.

De mon côté, avec Flannel (en mode vxlan) gérant mon réseau de conteneurs, j'utilise kube-proxy (en mode iptables et non masquage) + Flannel dans un namespace sur mes nœuds de routage. Les requêtes externes sont DNATed pour desservir les IP, puis transmises via l'espace de noms avec le kube-proxy. Je n'ai pas fait de test de cluster de routeur actif/actif, mais cette configuration me permet de conserver l'adresse IP externe. Je le mentionne FWIW, mais je comprends que ce n'est pas le "réseau le plus direct".

Je comprends que si kube-proxy pouvait le gérer ce serait bien, mais compte tenu de vos besoins spécifiques et surtout du fait que l'équilibrage de charge est déjà en dehors de kube-proxy, ne serait-il pas logique de coder un gestionnaire client iptables-rules regarder l'état du cluster kubernetes et configurer les règles pour les VIP DNAT uniquement pour les pods de l'hôte en cours d'exécution ? Cela pourrait aussi être un mode pour kube-proxy, comme... eh bien.. Je ne suis pas doué pour les noms... --proxy-mode=iptables-to-node-pods-only.

Merci pour la rédaction détaillée. Votre solution est intéressante, et j'ai passé
beaucoup de temps aujourd'hui à y penser. Malheureusement, vous avez
traversé dans un territoire très spécifique qui ne fonctionne pas dans un sens générique.
Les clouds comme GCE ne peuvent pas utiliser le mode de passerelle IPVS en raison du routage
réseau. Même si la passerelle a fonctionné, elle ne prend pas en charge le remappage des ports,
ce que fait Kubernetes, donc cela ne s'applique que si le port de service == cible
Port.

Le défi avec le cœur de kubernetes est de trouver des moyens de gérer votre
sorte de situation de manière générique ou pour vous écarter de votre chemin et vous donner les moyens de
configurez-le vous-même. Peut-être que nous pourrions faire quelque chose avec le mode ipvs encap,
mais je ne connais pas les implications perf de celui-ci.

Le jeu. 14 janvier 2016 à 03h37, qoke [email protected] a écrit :

@thockin https://github.com/thockin Excuses pour la longue réponse, je
voulait couvrir les deux méthodes avec lesquelles nous avons essayé de résoudre ce problème afin que d'autres puissent
comprendre les défis que nous avons rencontrés avec les deux.

En arrière-plan, notre application principale est une très haute performance
plate-forme DNS intelligente (c'est-à-dire qu'elle a besoin d'UDP et doit faire au moins 100k+
requêtes/s par pod) et son application de prise en charge dans un proxy SNI
qui a besoin de voir l'adresse IP réelle des clients (c'est un show stopper pour
nous). Nous ne voulions pas utiliser différentes approches de mise en réseau pour différents
applications, nous avons donc décidé de standardiser sur une méthode de réseau unique pour
tous, et nous avons choisi d'utiliser IPVS pour les raisons que j'ai mentionnées ci-dessus
(performances/stabilité/flexibilité/création d'objectif SLB), mais vous pourriez
pirater probablement quelque chose ensemble en utilisant juste iptables dans le même sens
trop. Nous utilisons vxlan (rapide, facile, fonctionne entre les sites) mais ces deux
les méthodes devraient également fonctionner avec GRE/VXLAN avec OVS ou avec la couche 2 standard
la mise en réseau des hôtes aussi (en supposant que vos hôtes soient tous sur le même réseau L2).

Nous distribuons le trafic entrant des utilisateurs finaux en utilisant un mélange d'anycast et
DNS, en fonction des exigences de vitesse de basculement ou de ce qui fonctionne le mieux pour
le type particulier de service, nous avons donc une répartition assez égale des
le trafic des utilisateurs finaux entrant dans nos nœuds, mais le problème, comme vous l'avez souligné,
obtient alors une répartition uniforme du trafic entre les pods, indépendamment de
emplacement de la cosse. L'autre problème est de s'assurer que les services communiquent avec d'autres
services est équilibré en charge de manière efficace.

Nous avons essayé deux modèles pour résoudre ce problème :

La première méthode que nous avons essayée était 2 couches de VIP. VIP externes (1 par
service), qui distribuent le trafic entre les nœuds (en fonction du nombre de pods pour
ce service sur le nœud), puis les VIP internes (qui s'exécutent sur le nœud
avec les pods), qui répartissent la charge dans les nœuds (généralement uniformément
à travers les gousses). La limitation de ce modèle était que les nœuds exécutant des
Les VIP devaient exécuter deux espaces de noms réseau différents ou exécuter le leur
nœuds physiques. Le truc sympa avec IPVS en mode DSR (retour serveur direct)
est qu'il n'a pas besoin de voir le trafic de retour, le trafic va :

Consommateur >> (sur L3) >> Nœud VIP externe >> (1) >> Nœud VIP interne >>
(2) >> Conteneur >> (comme vous le souhaitez) >> Consommateur

(1) IPVS (en mode DSR) sur l'hôte avec un VIP externe sélectionne un _nœud_ à
envoyer le trafic vers (un "vrai serveur" en termes IPVS), et ne change que DST MAC
l'adresse du paquet (c'est-à-dire que le paquet IP arrive inchangé au nœud k8s). Il charge
équilibre entre les nœuds en fonction du nombre de pods exécutant ce service sur
le nœud.
(2) IPVS (également en mode DSR) sur le nœud k8s équilibre la charge du trafic à travers
pods (via les veths vers le nœud). Les réponses des conteneurs (TCP et UDP) vont
directement au consommateur du service.

L'avantage de ce modèle, c'est qu'il était vraiment simple à démarrer et que le
jeu de règles était très facile à gérer. L'inconvénient de ce modèle est qu'il
concentre toutes nos demandes de service (mais pas les réponses) à travers un
nombre de nœuds exécutant les VIP externes. Nous aimons "rien-partagé", donc,
entrez la version 2 :

Le deuxième modèle est maintenant divertissant est une seule couche de VIP avec
une configuration IPVS et iptables plus intelligente.

Consommateur >> N'importe quel nœud/nœud local >> (1) >> Conteneur >> (de quelque manière que vous
voulez) >> Consommateur
ou, il peut aller vers un autre nœud :
Consommateur >> N'importe quel nœud/nœud local >> (1) >> Nœud distant >> (2) >> Conteneur

(comme vous le souhaitez) >> Consommateur

(1) Le trafic atteint le VIP principal, le trafic est équilibré sur tous les pods dans
la grappe.
(2) Le trafic atteint le VIP secondaire, le trafic est équilibré en charge uniquement sur tous
gousses locales. Ce VIP secondaire n'est utilisé que pour le trafic en provenance de
d'autres hôtes sur le réseau (c'est un VIP FWMARK). Nous marquons le trafic entrant
n'importe quelle interface externe avec FWMARK=1234, et cela force le trafic à aller
à un ensemble de règles différent, ce qui empêche les boucles entre les nœuds.

Le VIP principal a une liste de pods locaux et d'hôtes distants avec des pods (avec
le poids étant de 100 pour chaque dosette locale, et 100 * nombre de dosettes pour
nœuds distants). Ainsi, par exemple, si 3 pods s'exécutent localement sur nodeA, et
il y a deux pods en cours d'exécution sur nodeB, l'ensemble de règles sur nodeA ressemblerait à
cette:

Prot LocalAddress:Drapeaux du planificateur de ports
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP service.ip.address:0 rr persistant 360
-> pod1.on.nodeA.ip:80 Route 100 0 0
-> pod2.on.nodeA.ip:80 Route 100 0 0
-> pod2.on.nodeA.ip:80 Route 100 0 0
-> interfaceip.of.nodeB:80 Route 200 0 0
FWM 1234 rr
-> pod1.on.nodeA.ip:80 Route 100 0 0
-> pod2.on.nodeA.ip:80 Route 100 0 0
-> pod3.on.nodeA.ip:80 Route 100 0 0

Cependant sur nodeB, la configuration IPVS serait un peu différente car elle
n'a que deux pods locaux et trois pods distants sur nodeA :

Prot LocalAddress:Drapeaux du planificateur de ports
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP service.ip.address:0 rr persistant 360
-> pod1.on.nodeB.ip:80 Route 100 0 0
-> pod2.on.nodeB.ip:80 Route 100 0 0
-> interfaceip.of.nodeA:80 Route 300 0 0
FWM 1234 rr
-> pod1.on.nodeB.ip:80 Route 100 0 0
-> pod2.on.nodeB.ip:80 Route 100 0 0

Une autre façon serait de changer les FWMARK et d'utiliser iptables pour
FWMARK n'importe quoi dans les interfaces veth + (match générique) et avoir le FWMARK
match utilisé uniquement pour l'équilibrage de charge local.

Le résultat final est la mise en réseau la plus directe, sans besoin de centraliser
traitement/routage des demandes, donc s'adapte bien mieux. L'inconvénient est
plus d'intelligence lors de la création des règles IPVS.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-171619663
.

Je pense qu'un mode iptables-to-node-pods-only serait intéressant à essayer,
mais il a beaucoup d'ondulation. Le potentiel de déséquilibre est bien réel et
au moins le contrôleur de service devrait savoir comment programmer le
équilibreurs de charge externes.

Le jeu. 14 janv. 2016 à 15h59, Mikaël Cluseau [email protected]
a écrit:

De mon côté, avec Flannel (en mode vxlan) gérant mon réseau de conteneurs, je
utiliser kube-proxy (en mode iptables et non en masquage) + flanelle dans un
espace de noms sur mes nœuds de routage. Les requêtes externes sont DNATed au service
IPs, puis transmis via l'espace de noms avec le kube-proxy. je n'ai pas
fait des tests de cluster de routeurs actifs/actifs, mais cette configuration me permet de garder
l'IP externe. Je le mentionne FWIW, mais je comprends que ce n'est pas le "plus
mise en réseau directe".

Je comprends que si kube-proxy pouvait le gérer, ce serait bien, mais
compte tenu de vos besoins spécifiques et surtout du fait que l'équilibrage de charge
est déjà en dehors de kube-proxy, ne serait-il pas logique de coder un client
le gestionnaire iptables-rules surveille l'état du cluster kubernetes et configure
les règles aux VIP DNAT uniquement aux pods de l'hôte en cours d'exécution ? Cela pourrait
être également un mode pour kube-proxy, cependant, comme... eh bien.. je ne suis pas doué pour
noms... --proxy-mode=iptables-to-node-pods-only.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-171821603
.

@thockin Vous voulez dire si 2 répliques sont sur le même nœud par exemple ? Je pense que nous pourrions mettre le cas "programmer les équilibreurs de charge externes" en dehors de la portée du proxy kube, car il a plusieurs instances et un programmeur LB externe devrait probablement être en mode "maître unique". Ainsi, autoriser le mode kube-proxy "iptables-to-node-pods-only" n'est que la première d'un processus en 2 étapes.

Je pense que je pourrais essayer d'implémenter quelque chose comme ça demain: le mode "iptables-to-node-pods-only" dans kube-proxy, plus un contrib/ip-route-elb qui maintiendrait une table de routage Linux avec une route par service , avec le bon poids pour chaque nœud en fonction du nombre de points de terminaison du nœud pour un service donné.

@thockin Vous voulez dire que 2 répliques sont sur le même nœud par exemple ? Je pense qu'on pourrait mettre le cas "programmer le
équilibreurs de charge externes" en dehors de la portée du kube-proxy, car il a plusieurs instances et un LB externe
le programmeur devrait probablement être en mode "maître unique". Ainsi, autoriser le mode kube-proxy "iptables-to-node-
pods-only" n'est que la première d'un processus en 2 étapes.

"Uniquement proxy vers les pods locaux" doit être l'étape 2 du processus. Étape 1
doit changer le contrôleur de service pour envoyer uniquement des équilibreurs de charge
aux nœuds qui ont 1 ou plusieurs backends pour un service donné. Cette étape
est PROBABLEMENT raisonnable, mais nécessitera de nombreux tests pour
assurez-vous de bien faire les choses. Je pense que nous voulons le faire éventuellement,
De toute façon.

Une fois cela fait, nous pouvons parler de faire en sorte que les nœuds-ports préfèrent le local
backends si possible, mais cette étape nécessite beaucoup plus de prudence
pensé .. Cela signifie-t-il _toujours_ (c'est-à-dire ne jamais choisir une télécommande
backend si un local est disponible) ou probabiliste ? Doit-on faire
que via le même port de nœud (différents nœuds deviendront très
comportements différents) ou allouons-nous un port différent qui est utilisé
si et seulement si ce nœud a 1 ou plusieurs backends ? Comment gérons-nous les
problème de déséquilibre ?

Je pense que je pourrais essayer d'implémenter quelque chose comme ça demain: mode "iptables-to-node-pods-only" dans kube-proxy,
plus un contrib/ip-route-elb qui maintiendrait une table de routage Linux avec une route par service, avec le bon poids
pour chaque nœud en fonction du nombre de points de terminaison du nœud pour un service donné.

Si ELB prend en charge les poids, cela fonctionnera mieux à certains égards que
GCE, ce qui n'est pas le cas. C'est bien, je ne pensais tout simplement pas que cela était pris en charge
poids. Je ne pense pas que cela puisse être une contribution, cependant - c'est une jolie
élément fondamental du système.

Le 16/01/2016 à 05h19, Tim Hockin a écrit :

"Uniquement proxy vers les pods locaux" doit être l'étape 2 du processus. Étape 1
doit changer le contrôleur de service pour envoyer uniquement des équilibreurs de charge
aux nœuds qui ont 1 ou plusieurs backends pour un service donné. Cette étape
est PROBABLEMENT raisonnable, mais nécessitera de nombreux tests pour
assurez-vous de bien faire les choses. Je pense que nous voulons le faire éventuellement,
De toute façon.

Ça a du sens.

Une fois cela fait, [...]

Alors voyons une fois que c'est fait :-)

Si ELB prend en charge les poids, cela fonctionnera mieux à certains égards que
GCE, ce qui n'est pas le cas. C'est bien, je ne pensais tout simplement pas que cela était pris en charge
poids.

Depuis son du manuel et vous avez probablement plus de 10x ma
expérience dans ce genre de réseautage, je dois complètement ignorer un hic.
Le man ip-route dit ceci :

           nexthop NEXTHOP
                  the nexthop of a multipath route.  NEXTHOP is a 

valeur complexe avec sa propre syntaxe similaire aux listes d'arguments de niveau supérieur :

                          via [ FAMILY ] ADDRESS - is the nexthop 

routeur.

                          dev NAME - is the output device.

                          weight NUMBER - is a weight for this 

élément d'une route à trajets multiples reflétant sa bande passante ou sa qualité relative.

Je ne pense pas que cela puisse être une contribution, cependant - c'est une jolie
élément fondamental du système.

Puisque le "E" signifie "externe", j'avais l'impression que cela pouvait commencer par là,
au moins pour obtenir du code pour soutenir les idées.

Le ven. 15 janv. 2016 à 14:55, Mikaël Cluseau
[email protected] a écrit :

Le 16/01/2016 à 05h19, Tim Hockin a écrit :

"Uniquement proxy vers les pods locaux" doit être l'étape 2 du processus. Étape 1
doit changer le contrôleur de service pour envoyer uniquement des équilibreurs de charge
aux nœuds qui ont 1 ou plusieurs backends pour un service donné. Cette étape
est PROBABLEMENT raisonnable, mais nécessitera de nombreux tests pour
assurez-vous de bien faire les choses. Je pense que nous voulons le faire éventuellement,
De toute façon.

Ça a du sens.

J'y ai pensé plus aujourd'hui, je ne pense pas que ce sera très difficile.
Juste moyennement dur.

Une fois cela fait, [...]

Alors voyons une fois que c'est fait :-)

assez juste, j'aime juste savoir où va un ensemble de changements :)

Si ELB prend en charge les poids, cela fonctionnera mieux à certains égards que
GCE, ce qui n'est pas le cas. C'est bien, je ne pensais tout simplement pas que cela était pris en charge
poids.

Depuis son du manuel et vous avez probablement plus de 10x ma
expérience dans ce genre de réseautage, je dois complètement ignorer un hic.
Le man ip-route dit ceci :

nexthop NEXTHOP
le prochain saut d'une route à trajets multiples. NEXTHOP est un
valeur complexe avec sa propre syntaxe similaire aux listes d'arguments de niveau supérieur :

via [ FAMILLE ] ADRESSE - est le prochain saut
routeur.

dev NAME - est le périphérique de sortie.

poids NUMBER - est un poids pour cela
élément d'une route à trajets multiples reflétant sa bande passante ou sa qualité relative.

Cependant, nous n'utilisons pas vraiment la notion de routage IP de Linux. Aucun des
Les implémentations LB que je connais l'utilisent, de toute façon. GCE utilise le cloud de Google
équilibreur, qui n'a pas de poids. Je ne sais pas c'est Amazon ELB
Est-ce que.

Je ne pense pas que cela puisse être une contribution, cependant - c'est une jolie
élément fondamental du système.

Puisque le "E" signifie "externe", j'avais l'impression que cela pouvait commencer par là,
au moins pour obtenir du code pour soutenir les idées.

Bien sûr, nous pouvons COMMENCER en contrib :)

De plus, si vous voulez continuer, vous devez ouvrir 2 bogues, quelque chose comme :

1) les équilibreurs de charge pour un service ne doivent cibler que les nœuds qui
avoir un backend pour ce service

2) pour préserver l'adresse IP du client à travers les équilibreurs de charge, kube-proxy devrait
préférez toujours le backend local s'il est présent (xréf #1)

puis expliquer l'intention et la direction

Le vendredi 15 janvier 2016 à 17h11, Tim Hockin [email protected] a écrit :

Le ven. 15 janv. 2016 à 14:55, Mikaël Cluseau
[email protected] a écrit :

Le 16/01/2016 à 05h19, Tim Hockin a écrit :

"Uniquement proxy vers les pods locaux" doit être l'étape 2 du processus. Étape 1
doit changer le contrôleur de service pour envoyer uniquement des équilibreurs de charge
aux nœuds qui ont 1 ou plusieurs backends pour un service donné. Cette étape
est PROBABLEMENT raisonnable, mais nécessitera de nombreux tests pour
assurez-vous de bien faire les choses. Je pense que nous voulons le faire éventuellement,
De toute façon.

Ça a du sens.

J'y ai pensé plus aujourd'hui, je ne pense pas que ce sera très difficile.
Juste moyennement dur.

Une fois cela fait, [...]

Alors voyons une fois que c'est fait :-)

assez juste, j'aime juste savoir où va un ensemble de changements :)

Si ELB prend en charge les poids, cela fonctionnera mieux à certains égards que
GCE, ce qui n'est pas le cas. C'est bien, je ne pensais tout simplement pas que cela était pris en charge
poids.

Depuis son du manuel et vous avez probablement plus de 10x ma
expérience dans ce genre de réseautage, je dois complètement ignorer un hic.
Le man ip-route dit ceci :

nexthop NEXTHOP
le prochain saut d'une route à trajets multiples. NEXTHOP est un
valeur complexe avec sa propre syntaxe similaire aux listes d'arguments de niveau supérieur :

via [ FAMILLE ] ADRESSE - est le prochain saut
routeur.

dev NAME - est le périphérique de sortie.

poids NUMBER - est un poids pour cela
élément d'une route à trajets multiples reflétant sa bande passante ou sa qualité relative.

Cependant, nous n'utilisons pas vraiment la notion de routage IP de Linux. Aucun des
Les implémentations LB que je connais l'utilisent, de toute façon. GCE utilise le cloud de Google
équilibreur, qui n'a pas de poids. Je ne sais pas c'est Amazon ELB
Est-ce que.

Je ne pense pas que cela puisse être une contribution, cependant - c'est une jolie
élément fondamental du système.

Puisque le "E" signifie "externe", j'avais l'impression que cela pouvait commencer par là,
au moins pour obtenir du code pour soutenir les idées.

Bien sûr, nous pouvons COMMENCER en contrib :)

Le risque d'un PR sans docs, c'est qu'il va dans la mauvaise direction. Il est
beaucoup plus facile d'examiner quelque chose comme une proposition. je vais jeter un oeil a ton
PR quand j'en ai l'occasion, bientôt j'espère.
Le 15 janvier 2016 à 19h02, "Mikaël Cluseau" [email protected] a écrit :

Est-il possible d'ouvrir une pull-request pour (1) directement avec ce nom et certains
explications ?

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172149777
.

Malheureusement, vous avez traversé un territoire très spécifique qui ne fonctionne pas dans un sens générique.
Les clouds comme GCE ne peuvent pas utiliser le mode de passerelle IPVS en raison du réseau routé. Même si la passerelle a fonctionné, elle ne prend pas en charge le remappage des ports, ce que fait Kubernetes, elle ne s'applique donc que si le port de service == port cible.

Du côté de la passerelle, cela fonctionne bien sur un réseau de couche 3 (nous utilisons une superposition), et même si nous aurions pu nous en sortir sans réseau de superposition, nous l'avons construit de cette façon parce que nous voulions que l'approche que nous utilisons soit portable et fonctionne dans des clouds tiers (comme GCE).

Corrigez la limitation avec le mode DSR est que le port de service == port cible, mais ce n'est pas vraiment un problème à moins que vous n'ayez deux applications _dans le même conteneur_ qui doivent s'exécuter sur le même port (nous avons passé beaucoup de temps à réfléchir à ceci, et en supposant la directive "1 application par conteneur", nous n'avons pas pu trouver un seul cas d'utilisation pour cela). Nous avons de nombreux conteneurs qui s'exécutent tous sur les mêmes nœuds avec des services à l'intérieur, tous sur les mêmes ports, et tous sont bien équilibrés en charge. Si vous avez _vraiment_ besoin de remapper les ports (j'aime bien comprendre les vraies raisons derrière), vous pouvez utiliser le mode IPVS NAT au lieu du mode "ROUTE".

Le défi au cœur de kubernetes est de trouver des moyens de gérer votre type de situation de manière générique ou de vous écarter de votre chemin et de vous donner les moyens de le configurer vous-même. Peut-être que nous pourrions faire quelque chose avec le mode ipvs encap, mais je ne connais pas les implications de perf.

Ce que nous avons fait est aussi générique que possible (fonctionne ici, fonctionne sur Amazon, et je suis certain que cela fonctionnera dans GCE lorsque nous aurons besoin de nous développer), la seule limitation avec DSR étant que l'application s'exécutant dans le pod/conteneur doit s'exécuter sur le même port que le service qui, après de nombreuses discussions internes, n'a pas été en mesure de trouver un scénario où cela serait limitatif du point de vue de la pile d'applications E2E.

Cela dit, si vous supprimez le DSR (mode Route IPVS) de l'équation et utilisez le "mode NAT" d'IPVS à la place, les ports peuvent être remappés et vous bénéficiez toujours des fonctionnalités/performances IPVS/etc. Le seul inconvénient est que NAT ajoute une taxe sur les performances, mais (a) il prend en charge UDP et (b) il est toujours aussi rapide que l'éclair par rapport à une solution d'espace utilisateur.

@brendandburns @thockin Plus tôt dans le fil, vous avez demandé des chiffres de performance. Je n'appellerais pas cela l'ensemble de tests le plus complet, mais je m'attends à ce que HTTP soit l'une des charges de travail les plus courantes dans les conteneurs. Voici donc quelques numéros d'Apache-bench comme point de départ :

https://docs.google.com/presentation/d/1vv5Zszt4HDGbuyVlvOe76unHskxPuZQseQnarNbhQVc

DNAT a été activé sur IPVS pour une comparaison équitable avec les deux autres solutions (cela signifie également que le port de service peut être différent du port de service cible). Nos charges de travail peuvent sembler un peu inhabituelles pour certains, mais nos objectifs de performances ne sont probablement pas très différents des autres (c'est-à-dire compresser le matériel pour tout ce que vous pouvez obtenir).

Merci!

Je ne sais pas d'où vient l'idée que kube-proxy ne fait pas UDP - il
le fait absolument, mais peut-être pas parfaitement (sans connexion, il vient
jusqu'aux temporisations).

Cela vaut également la peine de clarifier le (nouveau) kube-proxy d'iptables par rapport à l'espace utilisateur
mode (héritage).

Le samedi 16 janvier 2016 à 21h45, qoke [email protected] a écrit :

@thockin https://github.com/thockin Plus tôt dans le fil que vous avez demandé
quelques chiffres de performances. Je n'appellerais pas cela l'ensemble le plus complet
de tests, mais je pense que HTTP est l'une des charges de travail les plus courantes dans
conteneurs, voici donc quelques numéros d'apache-bench comme point de départ :

https://docs.google.com/presentation/d/1vv5Zszt4HDGbuyVlvOe76unHskxPuZQseQnarNbhQVc

DNAT a été activé sur IPVS pour une comparaison équitable avec les deux autres solutions
(cela signifie également que le port de service peut être différent du port de service cible). Notre
les charges de travail peuvent sembler un peu inhabituelles pour certains, mais nos objectifs de performance
ne sont probablement pas très différents des autres (c'est-à-dire comprimez le matériel pour tous
Tu peux recevoir).

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172293881
.

Bon appel au mode nouveau vs ancien - noté et mis à jour.

Du côté de l'UDP également, merci pour la clarification ; Je ne savais pas qu'UDP était entièrement pris en charge dans kube-proxy jusqu'à présent. Lorsque nous avons essayé pour la première fois kube-proxy avec UDP, nous avons eu beaucoup, beaucoup de blocages. Je ne sais pas pourquoi, mais nous avons augmenté les délais d'attente et avons toujours eu des problèmes. Nous avons dû trouver une solution rapidement, nous avons donc fini par la contourner avec IPVS plutôt que de la déboguer. À l'époque, cela ne fonctionnait que pour des charges de travail de paquets par seconde assez faibles (moins de 1 000 pps), mais nous n'avons pas retesté récemment.

Le problème majeur avec iptables et tout service UDP à haut débit est le remplissage des tables de conntrack netfilter. Même si vous augmentez la taille de conntrack à 1 million, certains utilisateurs finaux DDoS infectés par des logiciels malveillants vous utilisent ou essaient de vous utiliser pour une attaque d'amplification DNS, puis votre table de conntrack se remplit à nouveau. De manière générale, la meilleure pratique pour les serveurs DNS (ou tout service UDP à haut débit) consiste à désactiver conntrack (en utilisant -j NOTRACK dans la table brute) , et si vous désactivez conntrack, iptables NAT et stateful stuff (-m state) s'interrompent.

En dehors du référentiel GIT, quel serait le meilleur endroit à regarder avant d'essayer de créer un module/package "k8s.io/kubernetes/pkg/proxy/ipvs" ? ou vaut-il mieux laisser quelqu'un qui connaît mieux la base de code ?

De plus, si vous souhaitez exécuter des tests de performances spécifiques, faites-le moi savoir et je verrai ce que je peux faire.

Le 17/01/2016 à 20h50, qoke a écrit :

En dehors du repo GIT, où serait le meilleur endroit pour regarder avant
essayer de créer un module/package "k8s.io/kubernetes/pkg/proxy/ipvs" ?

Je pense que vous pouvez aussi commencer dans contrib.

FWIW... J'ai utilisé des montres de liste et des magasins undelta pour faire un indépendant
binay réagissant à l'état du cluster dans
https://github.com/kubernetes/kubernetes/pull/19755. Si les informations
dans
https://github.com/kubernetes/kubernetes/pull/19755/files#diff -0becc97ac222c3f2838fbfe8446d5375R26
suffit, vous ne devriez avoir à modifier l'appel que quelques lignes en dessous
(https://github.com/kubernetes/kubernetes/pull/19755/files#diff-0becc97ac222c3f2838fbfe8446d5375R44).

Veuillez noter que je ne prends en charge que les services clusterIP dans ce PoC.

Malheureusement, vous avez traversé un territoire très spécifique qui ne fonctionne pas dans un sens générique.
Les clouds comme GCE ne peuvent pas utiliser le mode de passerelle IPVS en raison du réseau routé. Même si la passerelle a fonctionné, cela ne fonctionne pas
prend en charge le remappage des ports, ce que fait Kubernetes, il ne s'applique donc que si le port de service == port cible.

Côté passerelle, cela fonctionne bien sur un réseau de couche 3 (nous utilisons une superposition), et même si nous aurions pu nous en sortir
sans réseau superposé, nous l'avons construit de cette façon parce que nous voulions que l'approche que nous utilisons soit portable et fonctionne en tiers
nuages ​​(comme GCE).

Je ne sais pas comment cela peut fonctionner. Les routes statiques au niveau de la machine ne fonctionnent pas
au GCE. Peut-être qu'il me manque une technique que vous avez appliquée. je
admettre librement que je ne suis PAS un expert dans ce domaine :)

Corrigez la limitation est que le port de service == port cible, mais ce n'est pas vraiment un problème à moins que vous n'ayez deux applications dans le
même conteneur qui doit s'exécuter sur le même port (nous avons passé beaucoup de temps à y réfléchir et à supposer que la "1 application
par conteneur", nous n'avons pas pu trouver un seul cas d'utilisation pour cela). Nous avons de nombreux conteneurs fonctionnant tous sur les mêmes nœuds
avec des services à l'intérieur d'eux tous sur les mêmes ports, et tous bien équilibrés en charge. Bref, l'approche que nous utilisons ne vous arrête pas
d'exécuter plusieurs services sur les mêmes ports sur le même nœud.

Cela s'applique également si vous avez des backends qui changent de version (par exemple
transition entre etcd1 et etcd2) ou toute autre situation où
le port principal doit juste être différent. Le problème est que
Kubernetes permet de l'exprimer, nous devons donc nous assurer que les gens
peut réellement l'utiliser (ou bien le déprécier et EOL la fonctionnalité qui
semble improbable).

Le défi au cœur de kubernetes est de trouver des moyens de gérer votre type de situation de manière générique ou de vous écarter de votre chemin.
et vous donner les moyens de le configurer vous-même. Peut-être qu'on pourrait faire quelque chose avec le mode ipvs encap, mais je ne connais pas la perf
implications de celui-ci.

Ce que nous avons fait est aussi générique que possible (fonctionne ici, fonctionne sur Amazon, et je suis certain que cela fonctionnera dans
GCE lorsque nous avons besoin d'étendre), avec la seule limitation étant que l'application s'exécutant dans le pod/conteneur doit > s'exécuter sur le même port que le service qui après de nombreuses discussions internes, personne n'a été en mesure de trouver un scénario où
cela serait limitatif du point de vue de la pile d'applications E2E.

Je veux vraiment comprendre comment. Avez-vous quelque chose de plus étape par étape?

Du côté de l'UDP également, merci pour la clarification ; Je ne savais pas qu'UDP était entièrement pris en charge dans kube-proxy jusqu'à présent.
Lorsque nous avons essayé pour la première fois kube-proxy avec UDP, nous avons eu beaucoup, beaucoup de blocages. Je ne sais pas pourquoi, mais nous avons augmenté les délais d'attente et
avait encore des problèmes. Nous avons dû trouver une solution rapidement, nous avons donc fini par la contourner avec IPVS plutôt que de la déboguer. Au
Cela ne fonctionnait que pour des charges de travail de paquets par seconde assez faibles (moins de 1 000 pps), mais nous n'avons pas re-testé récemment.

Le problème majeur avec iptables et tout service UDP à haut débit est le remplissage des tables de conntrack netfilter. Même si vous augmentez le
conntrack taille à 1 million, puis certains utilisateurs finaux DDoS infectés par des logiciels malveillants vous ou essaient de vous utiliser pour une amplification DNS
attaque, puis votre table de conntrack se remplit à nouveau. De manière générale, les meilleures pratiques pour les serveurs DNS (ou tout autre
services UDP) consiste à désactiver conntrack (en utilisant -j NOTRACK dans la table brute), et si vous désactivez conntrack, iptables NAT et
les trucs avec état (état -m) s'interrompent.

Oui, NAT pour UDP est vraiment malheureux. Trouver un non-conntrack
la solution serait géniale, mais elle doit s'appliquer à tous
environnements ou être paramétré par plate-forme (ce qui est difficile en soi
manière).

En dehors du repo GIT, quel serait le meilleur endroit à regarder avant de tenter de créer un
Module/paquet "k8s.io/kubernetes/pkg/proxy/ipvs" ? ou vaut-il mieux laisser quelqu'un qui connaît mieux la base de code ?

J'ai ouvert un problème github à propos d'IPVS, mais j'utilisais mascarade (NAT)
mode parce que je ne pouvais pas le faire fonctionner sur GCE sans (et à cause de
la fonction de remappage des ports). Si le remappage des ports déclenchait une erreur moins idéale
mode d'équilibrage, je pourrais probablement vivre avec ça et simplement le documenter
En tant que tel.

Nous devrions déplacer ce convo là-bas - il va se perdre ici.

Le 18/01/2016 à 12h34, Tim Hockin a écrit :

Oui, NAT pour UDP est vraiment malheureux. Trouver un non-conntrack
la solution serait géniale, mais elle doit s'appliquer à tous
environnements ou être paramétré par plate-forme (ce qui est difficile en soi
manière).

le NAT sans état pourrait fonctionner dans le cas où un couple (pod, port) a au
la plupart d'un service (plusieurs pods pour un service) ?

Cela ressemblerait à ceci :

{de : clientIP:clientPort, vers : externalIP:externalPort} ---[le proxy sélectionne un pod aléatoire]---> {de : clientIP:clientPort, vers : podIP:targetPort} ---> [routé via le bon hôte ...]

Sur le chemin du retour, le pare-feu aura une règle indiquant un paquet {de :
podIP:targetPort , to : any} doit être SNATé vers {from :
e xternalIP:externalPort , à : inchangé}.

Pour l'énoncer en dialecte iptables :

iptables -t nat -N stateless-svc-in

iptables -t nat -N stateless-svc-out

iptables -t nat -A stateless-svc-in  -j DNAT -s 1.2.3.4  -p udp --dport 53 --to-destination 10.1.0.1 -m statistic --mode random --probability 0.3333

iptables -t nat -A stateless-svc-in  -j DNAT -s 1.2.3.4  -p udp --dport 53 --to-destination 10.2.0.1 -m statistic --mode random --probability 0.5

iptables -t nat -A stateless-svc-in  -j DNAT -s 1.2.3.4  -p udp --dport 53 --to-destination 10.2.0.2 -m statistic --mode random --probability 1

iptables -t nat -A stateless-svc-out -j SNAT -s 10.1.0.1 -p udp --sport 53 --to-source 1.2.3.4

iptables -t nat -A stateless-svc-out -j SNAT -s 10.2.0.1 -p udp --sport 53 --to-source 1.2.3.4

iptables -t nat -A stateless-svc-out -j SNAT -s 10.2.0.2 -p udp --sport 53 --to-source 1.2.3.4

Je ne vois pas où cela ne fonctionne pas lorsque le paquet vient de l'extérieur
la grappe.

La façon dont les Services sont exprimés dans Kubernetes permet à un seul pod d'être
front par un certain nombre de services, donc cela tombe en panne - nous ne savons pas ce que
à SNAT à.

Le dimanche 17 janvier 2016 à 18h13, Mikaël Cluseau [email protected]
a écrit:

Le 18/01/2016 à 12h34, Tim Hockin a écrit :

Oui, NAT pour UDP est vraiment malheureux. Trouver un non-conntrack
la solution serait géniale, mais elle doit s'appliquer à tous
environnements ou être paramétré par plate-forme (ce qui est difficile en soi
manière).

le NAT sans état pourrait fonctionner dans le cas où un couple (pod, port) a au
la plupart d'un service (plusieurs pods pour un service) ?

Cela ressemblerait à ceci :

{de : clientIP:clientPort, à : externalIP:externalPort} ---[le proxy sélectionne
un pod aléatoire]---> {de : clientIP:clientPort, vers : podIP:targetPort} --->
[acheminement via le bon hôte...]

Sur le chemin du retour, le pare-feu aura une règle indiquant un paquet {de :
podIP:targetPort , to : any} doit être SNATé vers {from :
e xternalIP:externalPort , à : inchangé}.

Pour l'énoncer en dialecte iptables :

iptables -t nat -N stateless-svc-in

iptables -t nat -N stateless-svc-out

iptables -t nat -A stateless-svc-in -j DNAT -s 1.2.3.4 -p udp --dport 53
--to-destination 10.1.0.1 -m statistic --mode random --probability 0.3333

iptables -t nat -A stateless-svc-in -j DNAT -s 1.2.3.4 -p udp --dport 53
--to-destination 10.2.0.1 -m statistic --mode random --probability 0.5

iptables -t nat -A stateless-svc-in -j DNAT -s 1.2.3.4 -p udp --dport 53
--to-destination 10.2.0.2 -m statistic --mode random --probability 1

iptables -t nat -A stateless-svc-out -j SNAT -s 10.1.0.1 -p udp --sport 53
--to-source 1.2.3.4

iptables -t nat -A stateless-svc-out -j SNAT -s 10.2.0.1 -p udp --sport 53
--to-source 1.2.3.4

iptables -t nat -A stateless-svc-out -j SNAT -s 10.2.0.2 -p udp --sport 53
--to-source 1.2.3.4

Je ne vois pas où cela ne fonctionne pas lorsque le paquet vient de l'extérieur
la grappe.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-172408290
.

Le 18/01/2016 à 15h31, Tim Hockin a écrit :

La façon dont les Services sont exprimés dans Kubernetes permet un seul pod
être
front par un certain nombre de services, donc cela tombe en panne - nous ne savons pas
Quel
à SNAT à.

C'est pourquoi j'ai limité le cas à un plusieurs-à-un (ma première phrase :-)).
J'essaie juste de tracer une ligne autour de ce qui peut être fait ou non.

Bien sûr, j'ai juste la tâche malheureuse de souligner pourquoi ce n'est pas un
solution assez générale :(

Le dimanche 17 janvier 2016 à 20h34, Mikaël Cluseau [email protected]
a écrit:

Le 18/01/2016 à 15h31, Tim Hockin a écrit :

La façon dont les Services sont exprimés dans Kubernetes permet un seul pod
être
front par un certain nombre de services, donc cela tombe en panne - nous ne savons pas
Quel
à SNAT à.

C'est pourquoi j'ai limité le cas à un plusieurs-à-un (ma première phrase :-)).
J'essaie juste de tracer une ligne autour de ce qui peut être fait ou non.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-172421828
.

Le 18/01/2016 à 15h46, Tim Hockin a écrit :

Bien sûr, j'ai juste la tâche malheureuse de souligner pourquoi ce n'est pas un
solution assez générale :(

Ouais... mais c'est une FAQ. On pourrait aussi mettre, quelque part, "si len(services)
== 1 { implémenter sans état } else { implémenter avec état }". Mais cela peut
ressemble à un gâchis pour les débutants. Je pourrais aussi être une contrib/elbs/quelque chose...

Ce n'est même pas quelque chose que nous suivons actuellement (le nombre de services qui
devant une nacelle donnée). Nous pourrions, je suppose. Je ne suis pas contre (même s'il
semble niche). Cela ressemble à un changement substantiel à faire pour avoir si
de nombreuses mises en garde. J'aimerais encore réfléchir à de meilleures réponses.

Le dimanche 17 janvier 2016 à 20h51, Mikaël Cluseau [email protected]
a écrit:

Le 18/01/2016 à 15h46, Tim Hockin a écrit :

Bien sûr, j'ai juste la tâche malheureuse de souligner pourquoi ce n'est pas un
solution assez générale :(

Ouais... mais c'est une FAQ. On pourrait aussi mettre, quelque part, "si len(services)
== 1 { implémenter sans état } else { implémenter avec état }". Mais cela peut
ressemble à un gâchis pour les débutants. Je pourrais aussi être un
contrib/elbs/quelque chose...

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172425404
.

Le 18/01/2016 16:07, Tim Hockin a écrit :

Ce n'est même pas quelque chose que nous suivons actuellement (le nombre de services qui
devant une nacelle donnée). Nous pourrions, je suppose. Je ne suis pas contre (même s'il
semble niche). Cela ressemble à un changement substantiel à faire pour avoir si
de nombreuses mises en garde. J'aimerais encore réfléchir à de meilleures réponses.

Je suis d'accord, mais je n'ai pas de meilleure idée pour l'instant :-(

Même un SDN spécialement conçu aurait besoin de suivre quelque chose, je suppose. Peut-être
des solutions basées sur des étiquettes comme MPLS..?

Le 18/01/2016 16:18, Mikaël Cluseau a écrit :

Même un SDN spécialement conçu aurait besoin de suivre quelque chose, je suppose.
Peut-être des solutions basées sur des étiquettes comme MPLS.. ?

Dans l'idée d'étiqueter les choses... si on attribue une IP par service + une
IP par point de terminaison (couple service+pod), et ajoutez ces IP de point de terminaison au
pods, cela devrait fonctionner entièrement sans état :

``````

  • Externe à l'hôte :{de : clientIP:clientPort, à : externalIP:servicePort} -----[ELB
    sélectionne un point de terminaison]--------> {de : clientIP:clientPort, à :
    endpointServiceIP:podPort} --> route vers l'hôte
  • Host to pod :{de : clientIP:clientPort, to : endpointServiceIP:podPort} --[standard
    routage vers les conteneurs]--> {de : clientIP:clientPort , vers :
    point de terminaison ServiceIP:podPort }

  • Pod à héberger :{de : endpointServiceIP:podPort, to : clientIP:clientPort}
    --------[routage standard vers les routeurs]-----> {de :
    endpointServiceIP:podPort, to: clientIP:clientPort} - Host to external:{from: endpointServiceIP:podPort, to: clientIP:clientPort} --------[ELB
    SNATs back]-----------------> {de : clientIP:clientPort , vers :
    e xternalIP:servicePort } ```

Il pense que nous pouvons également faire en sorte que cela fonctionne pour les clusterIP.
``````

Je ne peux pas faire fonctionner cela sur GCE, et je ne suis pas sûr d'AWS - il y a un
nombre limité de routes statiques disponibles.

Je me demande si je pourrais le faire en superposant 2 plages d'adresses IP en une seule
route. C'est beaucoup d'adresses IP à dépenser, mais je suppose que cela n'a d'importance que pour UDP.
Je vais devoir l'essayer.

Edit: je l'ai essayé et je n'ai pas réussi à le faire fonctionner, mais il me manque quelque chose.
Nous devrons ajouter/supprimer des IP dans des conteneurs en réponse aux services à venir
et en cours, mais je ne pouvais pas faire fonctionner les IP "supplémentaires" dans un conteneur (cela pourrait
ping mais pas TCP ou UDP, je ne sais pas pourquoi).

Je vais devoir réessayer un jour.

Le dimanche 17 janvier 2016 à 22h22, Mikaël Cluseau [email protected]
a écrit:

Le 18/01/2016 16:18, Mikaël Cluseau a écrit :

Même un SDN spécialement conçu aurait besoin de suivre quelque chose, je suppose.
Peut-être des solutions basées sur des étiquettes comme MPLS.. ?

Dans l'idée d'étiqueter les choses... si on attribue une IP par service + une
IP par point de terminaison (couple service+pod), et ajoutez ces IP de point de terminaison au
pods, cela devrait fonctionner entièrement sans état :

``````

  • Externe à l'hôte :{de : clientIP:clientPort, à : externalIP:servicePort}
    -----[ELB
    sélectionne un point de terminaison]--------> {de : clientIP:clientPort, à :
    endpointServiceIP:podPort} --> route vers l'hôte
  • Hôte vers pod :{de : clientIP:clientPort, to : endpointServiceIP:podPort}
    --[la norme
    routage vers les conteneurs]--> {de : clientIP:clientPort , vers :
    point de terminaison ServiceIP:podPort }

  • Pod à héberger :{de : endpointServiceIP:podPort, to : clientIP:clientPort}
    --------[routage standard vers les routeurs]-----> {de :
    endpointServiceIP:podPort, to: clientIP:clientPort} - Hôte vers
    external :{de : endpointServiceIP:podPort, à : clientIP:clientPort}
    --------[ELB
    SNATs back]-----------------> {de : clientIP:clientPort , vers :
    e xternalIP:servicePort } ```

Il pense que nous pouvons également faire en sorte que cela fonctionne pour les clusterIP.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-172438133
.

``````

J'essaie de mon côté d'obtenir quelque chose (avec des netns purs sur mon hébergeur local
pour l'instant).

J'essaie une approche où j'affecte les plages d'adresses IP de service aux hôtes pour
réduire le nombre d'entrées de routage :

cli -- elb -- h1 -- c1

| `--- c2

`--- h2 -- c2

h1_ep_ip_ranges=( 10.1.1.0/24 10.1.2.0/24 )
h2_ep_ip_ranges=( 10.1.3.0/24 )

Pas de ping ATM (paquets ne passant pas par la chaîne PREROUTING...), et
besoin de dormir. Plus à ce sujet demain ;)

Le 18/01/2016 à 18h28, Tim Hockin a écrit :

Je ne peux pas faire fonctionner cela sur GCE, et je ne suis pas sûr d'AWS - il y a un
nombre limité de routes statiques disponibles.

Je me demande si je pourrais le faire en superposant 2 plages d'adresses IP en une seule
route. C'est beaucoup d'adresses IP à dépenser, mais je suppose que cela n'a d'importance que pour UDP.
Je vais devoir l'essayer.

Edit: je l'ai essayé et je n'ai pas réussi à le faire fonctionner, mais il me manque quelque chose.
Nous devrons ajouter/supprimer des IP dans des conteneurs en réponse aux services à venir
et en cours, mais je ne pouvais pas faire fonctionner les IP "supplémentaires" dans un conteneur (cela pourrait
ping mais pas TCP ou UDP, je ne sais pas pourquoi).

Je vais devoir réessayer un jour.

Je suis allé un peu plus loin, mais quelque chose que j'aurais dû prévoir s'est produit.

J'ai configuré un pod avec 10.244.2.8/25 comme interface principale et 10.244.2.250/25
comme son interface "in-a-service". J'espérais pouvoir envoyer UDP à
.250 et détecter les réponses, pour les SNAT. Mais bien sûr, si le client est
pas dans le même /25 (ce qui ne peut pas être) la route par défaut entre en jeu, ce qui
vient de l'adresse .8. tcpdump confirme que les réponses proviennent de .8
lors de l'utilisation d'UDP.

Je suis de nouveau à un endroit où je ne sais pas comment le faire fonctionner. pensera
plus là-dessus.

Le lundi 18 janvier 2016 à 02h59, Mikaël Cluseau [email protected]
a écrit:

J'essaie de mon côté d'obtenir quelque chose (avec des netns purs sur mon hébergeur local
pour l'instant).

J'essaie une approche où j'affecte les plages d'adresses IP de service aux hôtes pour
réduire le nombre d'entrées de routage :

cli -- elb -- h1 -- c1

| `--- c2

`--- h2 -- c2

h1_ep_ip_ranges=( 10.1.1.0/24 10.1.2.0/24 )
h2_ep_ip_ranges=( 10.1.3.0/24 )

Pas de ping ATM (paquets ne passant pas par la chaîne PREROUTING...), et
besoin de dormir. Plus à ce sujet demain ;)

Le 18/01/2016 à 18h28, Tim Hockin a écrit :

Je ne peux pas faire fonctionner cela sur GCE, et je ne suis pas sûr d'AWS - il y a un
nombre limité de routes statiques disponibles.

Je me demande si je pourrais le faire en superposant 2 plages d'adresses IP ensemble dans un
Célibataire
route. C'est beaucoup d'adresses IP à dépenser, mais je suppose que cela n'a d'importance que pour UDP.
Je vais devoir l'essayer.

Edit: je l'ai essayé et je n'ai pas pu le faire fonctionner, mais il me manque
quelque chose.
Nous devrons ajouter/supprimer des IP dans des conteneurs en réponse aux services à venir
et en cours, mais je ne pouvais pas faire fonctionner les IP "supplémentaires" dans un conteneur (cela pourrait
ping mais pas TCP ou UDP, je ne sais pas pourquoi).

Je vais devoir réessayer un jour.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-172497456
.

Il me vient à l'esprit (via Abhishek) que même si cela fonctionne, nous devons TOUJOURS
la piste coule quelque part, donc ce n'est pas apatride à la fin de toute façon.

Le lundi 18 janvier 2016 à 21h50, Tim Hockin [email protected] a écrit :

Je suis allé un peu plus loin, mais quelque chose que j'aurais dû prévoir s'est produit.

J'ai configuré un pod avec 10.244.2.8/25 comme interface principale et
10.244.2.250/25 comme son interface "en service". j'espérais que je
pourrait envoyer UDP à .250 et détecter les réponses, pour les SNAT. Mais bien sûr,
si le client n'est pas dans le même /25 (ce qui ne peut pas être) la valeur par défaut
la route démarre, qui vient de l'adresse .8. tcpdump confirme que
les réponses proviennent de 0,8 lors de l'utilisation d'UDP.

Je suis de nouveau à un endroit où je ne sais pas comment le faire fonctionner. pensera
plus là-dessus.

Le lundi 18 janvier 2016 à 02h59, Mikaël Cluseau [email protected]
a écrit:

J'essaie de mon côté d'obtenir quelque chose (avec des netns purs sur mon hébergeur local
pour l'instant).

J'essaie une approche où j'affecte les plages d'adresses IP de service aux hôtes pour
réduire le nombre d'entrées de routage :

cli -- elb -- h1 -- c1

| `--- c2

`--- h2 -- c2

h1_ep_ip_ranges=( 10.1.1.0/24 10.1.2.0/24 )
h2_ep_ip_ranges=( 10.1.3.0/24 )

Pas de ping ATM (paquets ne passant pas par la chaîne PREROUTING...), et
besoin de dormir. Plus à ce sujet demain ;)

Le 18/01/2016 à 18h28, Tim Hockin a écrit :

Je ne peux pas faire fonctionner cela sur GCE, et je ne suis pas sûr d'AWS - il y a un
nombre limité de routes statiques disponibles.

Je me demande si je pourrais le faire en superposant 2 plages d'adresses IP ensemble dans un
Célibataire
route. C'est beaucoup d'adresses IP à dépenser, mais je suppose que cela n'a d'importance que pour UDP.
Je vais devoir l'essayer.

Edit: je l'ai essayé et je n'ai pas pu le faire fonctionner, mais il me manque
quelque chose.
Nous devrons ajouter/supprimer des IP dans des conteneurs en réponse aux services
à venir
et en cours, mais je ne pouvais pas faire fonctionner les IP "supplémentaires" dans un conteneur (il
pourrait
ping mais pas TCP ou UDP, je ne sais pas pourquoi).

Je vais devoir réessayer un jour.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-172497456
.

C'est malheureux :-( je ne sais pas pourquoi d'ailleurs. Je vais essayer quelque chose avec MPLS alors, je veux l'apprendre de toute façon.

Si vous avez 2 backends pour le service et que vous souhaitez envoyer plus d'un
paquet, vous devez suivre les flux d'une manière ou d'une autre, n'est-ce pas ? Ou es-tu
en supposant qu'il est sûr de pulvériser des paquets sur différents backends ?

Le mer. 20 janv. 2016 à 12:24, Mikaël Cluseau [email protected]
a écrit:

C'est malheureux :-( je ne sais pas pourquoi au fait. Je vais essayer quelque chose avec
MPLS donc, je veux l'apprendre quand même.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -173348973
.

J'ai en quelque sorte supposé que pour les charges de travail UDP, oui. Il peut également être facultatif de devenir sans état, même pour UDP. @qoke un commentaire à ce sujet?

De plus, nous pourrions utiliser des choses comme le hachage IP client pour rendre le flux plus stable tout en restant équilibré (je ne sais pas si nous pouvons appeler cela "une sorte de suivi" :-)).

@MikaelCluseau, nous utilisons le comportement IPVS par défaut, qui crée une "adhérence" UDP très légère...

Pour planifier les datagrammes UDP, l'équilibreur de charge IPVS enregistre la planification des datagrammes UDP avec un délai d'expiration configurable, et le délai d'expiration UDP par défaut est de 300 secondes. Avant l'expiration du délai de connexion UDP, tous les datagrammes UDP du même socket (protocole, adresse IP et port) seront dirigés vers le même serveur.

-- Cité de http://kb.linuxvirtualserver.org/wiki/IPVS

Bien sûr, cela ne fonctionne que si vous avez de nombreux clients qui parlent à un seul service ou à un seul client avec différents ports source. Si vous avez un seul client à volume élevé, qui envoie tous du trafic à partir du même port source, et que vous souhaitez équilibrer la charge sur plusieurs backends, vous préférerez peut-être utiliser une approche sans état/spray-and-pray.

Nous équilibrons beaucoup de trafic DNS et RADIUS - DNS tombe généralement dans la première catégorie (beaucoup de clients, ou clients avec beaucoup de ports sources), et RADIUS tombe généralement dans la dernière catégorie (peu de clients, beaucoup de paquets tous provenant du même IP/port). Plutôt que d'utiliser un hachage sans état pour RADIUS, nous avons plutôt décidé de randomiser les ports sources pour obtenir une répartition uniforme.

Après avoir lu tout le fil, je ne peux toujours pas savoir si l'activation du mode iptables pour kube-proxy devrait résoudre le problème des adresses IP externes masquées (#10921) ou non. Nous avons activé le mode iptables avec la v1.1 comme suggéré ici, mais nous voyons toujours les IP du cluster, pas les vraies des utilisateurs.

Notre cluster est dans GCE et nous avons juste besoin d'un équilibreur de charge avec prise en charge HTTPS avant de passer en ligne. Comme GCE ne prend pas en charge la version alpha de la v.1.2, nous ne pouvons pas utiliser la nouvelle entrée (dont AFAIK prend en charge les équilibreurs de charge HTTPS), donc l'équilibreur de charge réseau est notre seule option. Mais évidemment, nous ne pouvons pas passer en direct sans la possibilité d'enregistrer les adresses IP réelles de nos utilisateurs.

Quelques éclaircissements pour les nouveaux utilisateurs à ce sujet seraient appréciés. La prise en charge du HTTPS est obligatoire pour beaucoup d'entre nous. Merci!

J'utilise et désactive le proxy iptables depuis un certain temps et je peux confirmer que les adresses IP externes des clients sont toujours masquées/affichent les adresses IP de cluster.

Nous avons contourné ce problème jusqu'à présent en exécutant notre proxy HTTP/HTTPS frontal en mode réseau hôte afin qu'il voie l'adresse IP source.

@maclof merci pour le retour. Pourriez-vous partager plus d'informations sur la façon dont votre solution de contournement? Qu'entendez-vous par votre HTTP/HTTPS exécuté dans le réseau hôte ?

@javiercr, nous utilisons une spécification de pod comme celle-ci : http://pastie.org/private/zpdelblsob654zif7xus5g

L'utilisation du réseau hôte signifie que le pod s'exécute sur le réseau des machines hôtes, au lieu de se voir attribuer une adresse IP de cluster.

Cela signifie que lorsque notre serveur nginx se connecte au port 80/443, il écoutera sur une adresse IP hôte et verra les adresses IP sources.

J'utilise kubernetes 1.1, /opt/bin/kube-proxy ... --proxy-mode=iptables --masquerade-all=false et le routage du réseau IP du cluster via un hôte ayant un kube-proxy. Dans cette configuration, mes services voient l'adresse IP externe. J'utilise un espace de noms réseau hautement disponible qui a une adresse IP externe et une route vers les hôtes :

I0221 01:20:32.695440       1 main.go:224] <A6GSXEKN> Connection from 202.22.xxx.yyy:51954 closed.

J'ai beaucoup appris en lisant ce fil !

À titre d'information, ce document indique qu'AWS ELB utilise le round-robin pour les connexions TCP et le moins de connexions pour http/https : http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/how-elb-works.html# requête -routage

Je suis d'accord que se concentrer sur l'obtention de requêtes uniquement vers les nœuds qui exécutent des pods et essayer de servir les pods locaux est la meilleure façon de s'y prendre. L'avantage secondaire est qu'il y aura moins de trafic de nœud à nœud au sein du cluster et je suppose une amélioration de la latence en répondant toujours aux demandes locales de service à pod (ce qui, je suppose, est encore plus avantageux si vous avez des nœuds dans plusieurs zones de disponibilité dans le même cluster).

En termes de travail avec un équilibreur de charge qui ne prend pas en charge la pondération, vous pouvez résoudre ce problème avec votre contrôleur de réplication en essayant de toujours garder le même nombre de pods sur un nœud (s'il y en a plus d'un par nœud), puis en répartissant uniformément entre eux, même si cela signifie devoir déplacer des pods hors d'un nœud dans certaines situations et n'autoriser que certains nombres de réplicas. Par exemple, pour un cluster à 4 nœuds avec un service connecté à un équilibreur de charge, le seul nombre de réplicas de pod acceptables serait 1,2,3,4,6,8,9,12,16,20, etc.

Nous cherchons également à résoudre le problème du trafic à acheminer uniquement vers les pods locaux. Je serais d'accord pour que le nodeport disparaisse sur un nœud à des moments où aucun pod n'est présent localement pour un service. De cette façon, une simple vérification de l'état TCP de l'équilibreur de charge empêcherait les requêtes d'aller vers ces nœuds. Je pense que si nous pouvons au moins résoudre la partie iptables\kube-proxy de cela, nous découvrirons alors quelles sont les implications de l'équilibrage de charge lorsque les pods ne sont pas équilibrés dans le cluster. Je pense qu'il existe des moyens de résoudre ce problème sur les équilibreurs de charge sans avoir à définir un poids pour chaque nœud avec un appel d'API.

Les équilibreurs de charge traitent déjà cela en utilisant d'autres méthodes dynamiques. De plus, selon ce que le service que vous exécutez fait réellement à l'intérieur de ce conteneur pour chaque appel d'API, il peut ne pas être en mesure de prendre en charge 2 fois le trafic lorsqu'il y a 2 pods sur un nœud contre un de toute façon. Si les limites Kubernetes sont définies et si les niveaux d'utilisation maximum sont approchés sur un podnode, cela peut également jouer un rôle, ce qui ajoute encore une couche de complexité pour essayer de trouver le bon paramètre de poids sur l'équilibreur de charge externe.

Je dirais, restez à l'écart de ce niveau de complexité et n'essayez pas de définir le poids de l'équilibreur de charge à partir de kubernetes.

@yoshiwaan Puis-je suggérer d'ouvrir un nouveau problème pour la suggestion de trafic inter-nœud, car ce problème est maintenant fermé. Personnellement, je pense qu'une bonne première étape serait de s'assurer que _si_ un pod est en cours d'exécution sur le nœud local, que nous acheminons vers le pod local. Je soupçonne que cela sera suffisant, car vous pouvez ensuite mettre à l'échelle votre RC afin qu'il y ait des pods sur chaque nœud.

@justinsb +1, nous rencontrons également un problème maintenant où nous devons voir les adresses IP des clients et c'est fondamentalement impossible avec la configuration actuelle.

Cela pourrait être beaucoup trop naïf, mais je me demandais quelle est la différence entre le mode espace utilisateur et iptables? Je ne peux pas vraiment dire d'après la doc de l'

Le mode Userland signifie que kube-proxy gère lui-même les connexions en recevant la demande de connexion du client et en ouvrant un socket vers le serveur, qui (1) consomme beaucoup plus de CPU et de mémoire et (2) est limité au nombre de ports qu'un seul peut ouvert (<65k). Le mode iptables fonctionne à un niveau inférieur, dans le noyau, et utilise le suivi des connexions à la place, il est donc beaucoup plus léger et gère beaucoup plus de connexions*.

(modifier) ​​(*) Tant que vous ne faites pas transiter de paquets SNAT, ce qui nécessite à son tour une configuration où vous êtes sûr que les paquets traverseront les règles de suivi de connexion qui leur sont associées. Par exemple, l'utilisation d'une conception d'accès routé vous permet d'éviter SNAT, ce qui signifie que le point de terminaison du service verra l'adresse IP du client réel.

@MikaelCluseau
ce qui signifie que kube-proxy est uniquement responsable de la configuration et de la maintenance des règles iptables et nous n'obtenons plus de port local aléatoire pour chaque service en mode iptables, n'est-ce pas ?

Le 19/04/2016 à 22h51, Emma He a écrit :

ce qui signifie que kube-proxy est uniquement responsable de la configuration et de la maintenance
iptables et nous n'obtenons plus de port local aléatoire pour chaque service dans
mode iptables, non?

Oui.

Désolé mais j'ai absolument raté ça plus tôt.

(modifier) ​​(*) Tant que vous ne faites pas transiter de paquets SNAT, ce qui nécessite à son tour une configuration où vous êtes sûr que les paquets traverseront les règles de suivi de connexion qui leur sont associées. Par exemple, l'utilisation d'une conception d'accès routé vous permet d'éviter SNAT, ce qui signifie que le point de terminaison du service verra l'adresse IP du client réel.

@MikaelCluseau Je pensais qu'iptables adopte SNAT et DNAT, ce qui n'est pas le cas selon vous. Pourriez-vous s'il vous plaît clarifier cela pour moi?

Le 20/04/2016 13:59, Emma He a écrit :

@MikaelCluseau https://github.com/MikaelCluseau je pensais
iptables adopte SNAT et DNAT, ce qui n'est pas le cas selon vous.
Pourriez-vous s'il vous plaît clarifier cela pour moi?

C'est la partie délicate.

(1) L'utilisation de services/IP externes nécessite DNAT.
(2) Si vous êtes sûr que les paquets de réponse passeront par le même conntrack
règle (c'est-à-dire la même pile réseau ou une table de conntrack répliquée), vous
peut ignorer la partie SNAT (c'est-à-dire les règles MASQUERADE).

La condition de (2) est généralement correcte dans les conceptions de réseau d'accès routé
(qui est la conception la plus simple à laquelle je puisse penser).

Par exemple, étant donné

  • un client 1.0.1.1,
  • un service 1.0.2.1,
  • un pod implémentant le service 1.0.3.1.

Puis,

  1. Votre routeur/firewall/loadbalancer/host/whatever reçoit un paquet
    pour le service, il voit donc un paquet "1.0.1.1 -> 1.0.2.1" ;
  2. Il le transfère au point de terminaison (pod) afin que le paquet soit "1.0.1.1 ->
    1.0.3.1" dans le réseau du cluster ;
  3. Le pod répond avec un paquet "1.0.3.1 -> 1.0.1.1" ;
  4. Le paquet passe par un routeur/firewall/loadbalancer/host/whatever
    ayant la règle conntrack, le système conntrack réécrit le paquet
    à "1.0.2.1 -> 1.0.1.1" avant de le renvoyer au client.

Si la condition de (2) ne peut pas être remplie, vous devez utiliser SNAT/MASQUERADING
pour être sûr que le paquet repassera par le
router/firewall/loadbalancer/host/whatever's conntrack.

@MikaelCluseau -
quelque chose pour vous

Le Mar 19 Avr 2016 à 20h20, Mikaël Cluseau [email protected]
a écrit:

Le 20/04/2016 13:59, Emma He a écrit :

@MikaelCluseau https://github.com/MikaelCluseau je pensais
iptables adopte SNAT et DNAT, ce qui n'est pas le cas selon vous.
Pourriez-vous s'il vous plaît clarifier cela pour moi?

C'est la partie délicate.

(1) L'utilisation de services/IP externes nécessite DNAT.
(2) Si vous êtes sûr que les paquets de réponse passeront par le même conntrack
règle (c'est-à-dire la même pile réseau ou une table de conntrack répliquée), vous
peut ignorer la partie SNAT (c'est-à-dire les règles MASQUERADE).

La condition de (2) est généralement correcte dans les conceptions de réseau d'accès routé
(qui est la conception la plus simple à laquelle je puisse penser).

Par exemple, étant donné

  • un client 1.0.1.1,
  • un service 1.0.2.1,
  • un pod implémentant le service 1.0.3.1.

Puis,

  1. Votre routeur/firewall/loadbalancer/host/whatever reçoit un paquet
    pour le service, il voit donc un paquet "1.0.1.1 -> 1.0.2.1" ;
  2. Il le transfère au point de terminaison (pod) afin que le paquet soit "1.0.1.1 ->
    1.0.3.1" dans le réseau du cluster ;
  3. Le pod répond avec un paquet "1.0.3.1 -> 1.0.1.1" ;
  4. Le paquet passe par un routeur/firewall/loadbalancer/host/whatever
    ayant la règle conntrack, le système conntrack réécrit le paquet
    à "1.0.2.1 -> 1.0.1.1" avant de le renvoyer au client.

Si la condition de (2) ne peut pas être remplie, vous devez utiliser SNAT/MASQUERADING
pour être sûr que le paquet repassera par le
router/firewall/loadbalancer/host/whatever's conntrack.

-
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -212230959

@justinsb @yoshiwaan est-ce que quelqu'un a déjà créé un problème pour cela? Ma recherche fu me fait défaut, et j'ai un besoin similaire.

Puis-je suggérer d'ouvrir un nouveau problème pour la suggestion de trafic inter-nœud, car ce problème est maintenant fermé. Personnellement, je pense qu'une bonne première étape serait de s'assurer que si un pod s'exécute sur le nœud local, nous acheminons vers le pod local. Je soupçonne que cela sera suffisant, car vous pouvez ensuite mettre à l'échelle votre RC afin qu'il y ait des pods sur chaque nœud.

je ne l'ai pas élevé moi-même

Ahhhhh, je pense l'avoir trouvé, cela semble être la fonctionnalité/correction : https://github.com/kubernetes/features/issues/27

Semble être bêta à partir de 1.5.x.

Cette page vous a été utile?
0 / 5 - 0 notes