Kubernetes: use iptables para el proxy en lugar del espacio de usuario

Creado en 23 ene. 2015  ·  187Comentarios  ·  Fuente: kubernetes/kubernetes

Ayer estuve jugando con iptables, e hice un prototipo (bueno, copié de Google hits y muté) un conjunto de reglas de iptables que esencialmente hacen todo el proxy por nosotros sin la ayuda del espacio de usuario. No es urgente, pero quiero archivar mis notas antes de perderlas.

Esto tiene el agradable efecto secundario adicional (por lo que puedo decir) de preservar la IP de origen y ser una gran simplificación neta. Ahora kube-proxy solo necesitaría sincronizar Servicios -> iptables. Esto tiene la desventaja de no ser compatible con iptables y kernels más antiguos. Tuvimos un problema con esto antes; en algún momento debemos decidir qué tan atrás en el tiempo nos preocupamos.

Esto probablemente se pueda optimizar aún más, pero en las pruebas básicas, veo sesiones pegajosas funcionando y si comento esa parte veo ~ la misma probabilidad de golpear cada backend. No pude hacer que el round robin determinista funcionara correctamente (con --nth en lugar de --probability) pero podríamos volver a eso si queremos.

Esto configura un portal de servicio con los backends que se enumeran a continuación

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

Todos 187 comentarios

¡Frio! Creo que definitivamente deberíamos fusionar esto. En una nota separada, estaba viendo que el proxy se comía ~ 30% de un núcleo bajo una carga pesada, tengo que creer que iptables nos dará un mejor rendimiento que eso.

Tenemos que priorizar esto: es casi una reescritura total de kube-proxy y
todas sus pruebas. También tiene problemas de compatibilidad con versiones anteriores (no funcionará en
kernels más antiguos o binarios de iptables más antiguos).

El lunes 26 de enero de 2015 a las 11:06 a. M., Brendan Burns [email protected]
escribió:

¡Frio! Creo que definitivamente deberíamos fusionar esto. En una nota separada,
Estaba viendo al proxy comer ~ 30% de un núcleo bajo una carga pesada, tengo que
creo que iptables nos dará un mejor rendimiento que eso.

Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -71517501
.

¿Quizás tener sentido implementarlo como una opción paralela y migrar lentamente?

El lunes 26 de enero de 2015 a las 12:01 p.m., Tim Hockin [email protected]
escribió:

Tenemos que priorizar esto: es casi una reescritura total de kube-proxy y
todas sus pruebas. También tiene problemas de compatibilidad con versiones anteriores (no funcionará en
kernels más antiguos o binarios de iptables más antiguos).

El lunes 26 de enero de 2015 a las 11:06 a. M., Brendan Burns [email protected]
escribió:

¡Frio! Creo que definitivamente deberíamos fusionar esto.
Nota,
Estaba viendo al proxy comer ~ 30% de un núcleo bajo una carga pesada, tengo que
creo que iptables nos dará un mejor rendimiento que eso.

Responda a este correo electrónico directamente o véalo en GitHub
<
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -71517501

.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -71527216
.

Estoy tratando de convencer a alguien que no conozca bien este código para que lo aprenda.
y asumirlo. Realmente quiero abordarlo, pero sería mejor si
alguien más aprendió este espacio (¡no tú! :)

Dicho esto, también envió un (buen) correo electrónico sobre la enorme lista P1, y yo
No creo que esto esté en esa lista todavía.

El lunes 26 de enero de 2015 a la 1:06 p.m., Brendan Burns [email protected]
escribió:

Tal vez implementarlo como una opción paralela y migrar lentamente hace
¿sentido?

El lunes 26 de enero de 2015 a las 12:01 p.m., Tim Hockin [email protected]
escribió:

Tenemos que priorizar esto: es casi una reescritura total de kube-proxy
y
todas sus pruebas. También tiene problemas de compatibilidad con versiones anteriores (no funcionará
sobre
kernels más antiguos o binarios de iptables más antiguos).

El lunes, 26 de enero de 2015 a las 11:06 a. M., Brendan Burns <
[email protected]>
escribió:

¡Frio! Creo que definitivamente deberíamos fusionar esto.
Nota,
Estaba viendo al proxy comer ~ 30% de un núcleo bajo una carga pesada, tengo que
creo que iptables nos dará un mejor rendimiento que eso.

Responda a este correo electrónico directamente o véalo en GitHub
<

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

.

Responda a este correo electrónico directamente o véalo en GitHub
<
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-71527216>

.

Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -71538256
.

¿Es esto un P2? ¿Valdría la pena convertirlo en un P3 por ahora?

Espero hacerlo funcionar, pero aún podemos degradarlo

El miércoles 11 de febrero de 2015 a las 2:49 p.m., Satnam Singh [email protected]
escribió:

¿Es esto un P2? ¿Valdría la pena convertirlo en un P3 por ahora?

Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -73982161
.

¿"Esperanza" no equivale a un P3 al que llegaremos si podemos?

De la discusión con @thockin : este es un requisito para admitir rangos de puertos de servicio, que no son necesarios para 1.0, pero nos gustaría admitirlos eventualmente.

@thockin "Esto tiene la desventaja de no ser compatible con iptables y kernels más antiguos". ¿Qué tan 'nuevo' tendría que ser el kernel?

No es DEMASIADO nuevo, pero tenemos algunos usuarios que REALMENTE quieren iptables de 2012 a
trabaja.

El lunes 23 de febrero de 2015 a las 2:44 p.m., Sidharta Seethana < [email protected]

escribió:

@thockin https://github.com/thockin "Esto tiene la desventaja de no ser
compatible con iptables y kernels más antiguos. "¿Qué tan 'nuevo' sería el kernel
¿tiene que ser?

Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -75654187
.

@thockin gracias. Estamos usando / probando con RHEL / CentOS 6, por ejemplo, por lo que sería bueno si no tuviéramos una dependencia estricta de los kernels 3.x recientes.

@ pweil- estuvimos discutiendo esto el otro día
El lunes 23 de febrero de 2015 a las 11:40 p.m. Sidharta Seethana [email protected]
escribió:

@thockin https://github.com/thockin gracias. Estamos usando / probando con
RHEL / CentOS 6, por ejemplo, por lo que sería bueno que no tuviéramos un
dependencia de kernels 3.x recientes.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -75698480
.

Bueno, es necesario que Docker se ejecute, y en algún momento tenemos que cortarlo.
El soporte de iptables back-rev no me impedirá (eventualmente) hacer
este cambio, y va a doler a algunas personas.

El lunes 23 de febrero de 2015 a las 8:40 p.m., Sidharta Seethana < [email protected]

escribió:

@thockin https://github.com/thockin gracias. Estamos usando / probando con
RHEL / CentOS 6, por ejemplo, por lo que sería bueno que no tuviéramos un
dependencia de kernels 3.x recientes.

Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -75698480
.

Con la ayuda de @thockin , intentamos lo mismo con udp.

Creamos un clúster de GCE Kubernetes con 3 controladores de replicación sky-dns.
En kubernetes-master, configuramos lo siguiente en iptables:
La ip del servicio dns era 10.0.0.10 y los puntos finales del pod que ejecutaban dns eran 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 reciente --nombre hostA --rcheck --segundos 1 --reap -j TESTSVC_A
iptables -t nat -A TESTSVC -m reciente --nombre hostB --rcheck --segundos 1 --reap -j TESTSVC_B
iptables -t nat -A TESTSVC -m reciente --nombre hostC --rcheck --segundos 1 --reap -j TESTSVC_C

iptables -t nat -A TESTSVC -m estadística --modo aleatorio --probabilidad 0.333 -j TESTSVC_A
iptables -t nat -A TESTSVC -m estadística --modo aleatorio --probabilidad 0.5 -j TESTSVC_B
iptables -t nat -A TESTSVC -m estadística --modo aleatorio --probabilidad 1.000 -j TESTSVC_C

iptables -t nat -A TESTSVC_A -m reciente --nombre hostA --set -j DNAT -p udp --to-destino 10.244.0.5:53
iptables -t nat -A TESTSVC_B -m reciente --nombre hostB --set -j DNAT -p udp --to-destino 10.244.3.6:53
iptables -t nat -A TESTSVC_C -m reciente --nombre hostC --set -j DNAT -p udp --to-destino 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 SALIDA -j KUBE-PORTALS-HOST


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

¡Recibimos una respuesta!

¡Buena cosa! Solo para su información (confirmando nuestra conversación cara a cara), no es seguro ejecutar múltiples comandos iptables concurrentes en general (diferentes cadenas parecen estar bien). iptables es un envoltorio de libiptc, y vea el comentario sobre iptc_commit: http://www.tldp.org/HOWTO/Querying-libiptc-HOWTO/mfunction.html

Esto aparentemente fue fijado en 2013, pero tal vez sólo si pasan --wait (?): Http://git.netfilter.org/iptables/commit/?id=93587a04d0f2511e108bbc4d87a8b9d28a5c5dd8

La causa principal de esto es que iptables llama efectivamente a iptables-save / iptables-restore (al menos por cadena); He visto una gran cantidad de código que, por lo tanto, llama a iptables-save & iptables-restore en lugar de hacer cosas mediante adiciones y eliminaciones. Incluso puedo tener algún código para hacer que podría desenterrar si eso es útil.

Me deja atónito que no haya forma de realizar operaciones de tipo CAS o LL / SC.

Deberíamos agregar soporte para --wait, aunque es lo suficientemente reciente como para que GCE
debian-backports no lo tiene.

Tal vez deberíamos hacer nuestro propio bloqueo dentro de nuestro código para al menos evitarnos
de pisarnos a nosotros mismos.

El jueves 26 de febrero de 2015 a las 1:56 p.m., Justin Santa Barbara <
[email protected]> escribió:

¡Buena cosa! Solo para su información (confirmando nuestra conversación cara a cara),
no es seguro ejecutar varios comandos iptables simultáneos en general
(diferentes cadenas suena como que podría estar bien). iptables es un envoltorio
libiptc y vea el comentario sobre iptc_commit:
http://www.tldp.org/HOWTO/Querying-libiptc-HOWTO/mfunction.html

Aparentemente, esto se solucionó en 2013, pero tal vez solo si pasa --espera (?):
http://git.netfilter.org/iptables/commit/?id=93587a04d0f2511e108bbc4d87a8b9d28a5c5dd8

La causa principal de esto es que iptables llama efectivamente a iptables-save /
iptables-restore (al menos por cadena); He visto mucho código que simplemente
por lo tanto, llama a iptables-save & iptables-restore en lugar de hacer cosas
a través de adiciones y eliminaciones. Incluso puedo tener algún código para hacer que podría cavar
arriba si eso es útil.

Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -76282629
.

¿Qué sucede en el caso de fallas en medio de la creación de un montón de reglas?

Pregunta justa: probablemente deberíamos pensar mucho sobre lo que significa
encuentro un error en medio de este

El jueves 26 de febrero de 2015 a las 8:47 p.m., Brian Grant [email protected]
escribió:

¿Qué sucede en el caso de fallas en medio de la creación de un montón de
¿normas?

Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -76331174
.

@thockin De irc hoy:

net.ipv4.conf.all.route_localnet permite que 127.0.0.1 sea el objetivo de las reglas DNAT . De los documentos :

route_localnet - BOOLEAN

No considere las direcciones de bucle invertido como origen o destino marciano
mientras se enruta. Esto permite el uso de 127/8 para propósitos de enrutamiento local.
predeterminado FALSO

¿Integraríamos esto en kubelet o lo mantendríamos en un demonio separado? Kubelet ya observa los servicios para poblar env vars.

Me gustaría mantenerlo como un binario separado. Hay razones por las que tu
es posible que desee ejecutar esto en otras máquinas (por ejemplo, máquinas virtuales de mascotas) fuera de un k8
cluster para obtener acceso a los servicios de k8s.

--brendan

El viernes 13 de marzo de 2015 a las 11:37 a. M., Brian Grant [email protected]
escribió:

¿Integraríamos esto en kubelet o lo mantendríamos en un demonio separado?
Kubelet ya observa los servicios para poblar env vars.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79230747
.

Alcanzando. Con respecto a lo que sucede en el caso de fallas (de las cuales habrá muchas, créame), soy un gran admirador del enfoque anti-entropía: almacene el estado deseado en algún lugar y reconcilie periódicamente el estado deseado y el real (mediante la mutación del estado real ). En este caso, quizás tan simple como:

while (verdadero) {
actualState = iptablesSave ()
if actualState! = deseadoState {iptablesRestore (deseadoState))
dormir_mientras ()
}

De acuerdo al 100% que es la manera correcta de lidiar con fallas al escribir iptables
normas.

El viernes 13 de marzo de 2015 a la 1:16 p. M., Quinton Hoole [email protected]
escribió:

Alcanzando. Respecto a lo que ocurre en el caso de fallas (de las cuales
habrá muchos, créame), soy un gran fanático del enfoque anti-entropía

  • almacenar el estado deseado en algún lugar, y reconciliar periódicamente el estado deseado y
    estado actual (mediante la mutación del estado actual). En este caso, quizás tan simple como:

while (verdadero) {
actualState = iptablesSave ()
if actualState! = deseadoState {iptablesRestore (deseadoState))
dormir_mientras ()
}

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79336296
.

Eso es más o menos lo que pasa ahora, ¿no? Para cada regla esperada,
compruebe si existe y si no, hágalo.

El viernes 13 de marzo de 2015 a las 2:02 p.m., Brendan Burns [email protected]
escribió:

De acuerdo al 100% que es la manera correcta de lidiar con fallas al escribir iptables
normas.

El viernes 13 de marzo de 2015 a la 1:16 p. M., Quinton Hoole [email protected]
escribió:

Alcanzando. Respecto a lo que ocurre en el caso de fallas (de las cuales
habrán muchos, créeme), soy un gran fan de la anti-entropía
Acercarse

  • almacenar el estado deseado en algún lugar, y reconciliar periódicamente el estado deseado y
    estado actual (mediante la mutación del estado actual). En este caso, quizás tan simple
    como:

while (verdadero) {
actualState = iptablesSave ()
if actualState! = deseadoState {iptablesRestore (deseadoState))
dormir_mientras ()
}

-
Responda a este correo electrónico directamente o véalo en GitHub
<
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79336296

.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79392626
.

Estoy de acuerdo en que hay utilidad en un binario separado, pero tal vez lo vinculemos a
kubelet (de la misma manera que lo hace cAdvisor) y hacerlo independiente en el
Mismo tiempo.

El viernes 13 de marzo de 2015 a las 12:03 p.m., Brendan Burns [email protected]
escribió:

Me gustaría mantenerlo como un binario separado. Hay razones por las que tu
es posible que desee ejecutar esto en otras máquinas (por ejemplo, máquinas virtuales de mascotas) fuera de un k8
cluster para obtener acceso a los servicios de k8s.

--brendan

El viernes 13 de marzo de 2015 a las 11:37 a. M., Brian Grant [email protected]
escribió:

¿Integraríamos esto en kubelet o lo mantendríamos en un demonio separado?
Kubelet ya observa los servicios para poblar env vars.

-
Responda a este correo electrónico directamente o véalo en GitHub
<
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79230747

.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79257059
.

Me gustaría saber qué tiene que decir la gente de Kubernetes-Mesos sobre si los componentes de los nodos deberían ser más integrados o modulares. @jdef?

[[EDITADO]] Me gusta mucho la modularidad de los componentes de k8s, por ejemplo, ejecutar un proceso de proxy separado de un proceso de kubelet. Si el proxy falla por cualquier motivo, no elimina el kubelet. Eso es bastante bueno, ya que los ejecutores de Mesos no tienen un modelo de conmutación por error muy elegante en este momento, y el ejecutor del marco de kubernetes-mesos es un híbrido de kubelet / ejecutor. Este modelo también me permite ejecutar un servicio proxy en un maestro de mesos y usarlo como un balanceador de turnos para clientes externos (como en la guía de introducción que enviamos).

En términos de binarios de empaquetado / envío, creo que es bastante útil tener la funcionalidad empaquetada, como en Hyperkube. También pensé en cómo empaquetar los componentes del marco de kubernetes-mesos en contenedores Docker mínimos . Iptables tiene dependencias de bibliotecas externas y eso complica las cosas. Por lo tanto, un buen compromiso podría ser enviar el marco k8sm como un Docker que contiene la imagen de un hiperkubo único, pero cuando ese marco se ejecuta y comienza a distribuir los ejecutores de kubelet en el clúster, básicamente envía una imagen de hiperkubo que puede transformarse en un kubelet- ejecutor o proxy, y cada proceso puede ejecutarse directamente en el host. Básicamente, esto soluciona el problema de dependencia de iptables- {binarios, bibliotecas} -in-Docker.

+1 para funcionalidad modular, +1 para imagen binaria única

@thockin re: anti-entropía: Ah, sí. Veo que proxier.SyncLoop () hace eso. En cuyo caso, ¿no es la respuesta a la pregunta de @ bgrant0607 del 26 de febrero de que los errores se pueden ignorar y se repararán en la próxima iteración de SyncLoop () (actualmente 1 minuto)? ¿O quizás me estoy perdiendo algo?

@thockin

  1. ¿Estamos preocupados por el tráfico de red que genera agujeros negros o es algo de lo que el autor del servicio / pod debe ocuparse?

Con proxy de espacio de usuario
Suponga que Virtual IP 10.0.0.11 tiene 3 puntos finales, por ejemplo, 10.240.1.1, 10.240.1.2, 10.240.1.3
Con un proxy de espacio de usuario, si un punto final dice que 10.240.1.1 no funcionó, el proxy se daría cuenta de que la conexión tcp no se estableció con 10.240.1.1 y podría recurrir a uno de los otros 2 puntos finales.

Con iptables
Cuando usamos iptables, no hay un mecanismo de respaldo ya que kubernetes no se da cuenta de si el punto final funcionó o no.
Podríamos mitigar esto si tuviéramos algún tipo de verificación de estado para los puntos finales, que eliminaría los puntos finales que no responden.

¿O tal vez, preocuparse por los puntos finales que no responden no es responsabilidad del sistema de kubernetes y es responsabilidad del autor del pod?

El usuario puede configurar sondas de preparación, que son realizadas por Kubelet. La falla de la sonda hará que un punto final sea eliminado de la lista de puntos finales por el controlador de puntos finales. A continuación, el proxy de servicio debería eliminar el punto final del conjunto de destino.

He estado investigando esto para GSoC y me pregunto:

Entonces, idealmente, detectaríamos si iptables es lo suficientemente nuevo para usar y, de lo contrario, continuará usando kube-proxy.

Desde https://github.com/GoogleCloudPlatform/kubernetes/issues/5419 parece que este sería el enfoque ideal; con kubelet determinando si usar ip-tables o iniciar kube-proxy.

También llego un poco tarde a GSoC (estaba en las vacaciones de primavera ...), por lo que también me pregunto si todavía puedo enviar una propuesta de GSoC mañana / más tarde hoy (excepto, por supuesto, la fecha límite 27, es esto todavía está abierto)?

@BenTheElder Sí, tienes hasta el viernes para enviar una propuesta. Hay otra persona potencialmente interesada en este tema, pero aún no hay una propuesta específica al respecto.

No me preocupan los kernels anteriores a 2012 tanto como los sistemas operativos sin iptables por completo, aunque ya están dañados hasta cierto punto.

@ bgrant0607 ¡gracias!
Creo que entonces puedo seleccionar este tema. Se ve interesante.

La sonda de preparación funcionará bien para el inicio de la aplicación, pero no estoy seguro de que la preparación sea adecuada para mitigar los fallos de la aplicación. En caso de falla del pod, la señal debe pasar de la aplicación -> kubelet -> apiserver -> endpoints_controller -> apiserver -> kube-proxy. Me interesaría comprender la latencia entre la falla de una aplicación y la eliminación de un punto final de la rotación de kube-proxy. Durante este período, las solicitudes se enviarán mediante proxy a un punto final que no responda.

Reintentar en caso de falla de conexión es una estrategia común y una característica razonablemente útil de muchos balanceadores de carga populares (por ejemplo, haproxy, AWS ELB) y se maneja mediante la implementación actual de kube-proxy. ¿Debería trasladarse esta responsabilidad al LB externo? ¿Qué pasa con el tráfico dentro del clúster?

Otro pensamiento, con iptables es probable que encontremos problemas con un drenaje elegante de la conexión tras la reconfiguración frente a un LB real.

Mike plantea buenos puntos.

El lunes 23 de marzo de 2015 a las 11:00 p.m., Mike Danese [email protected]
escribió:

Otro pensamiento, es probable que encontremos problemas de conexión elegante
drenaje tras la reconfiguración frente a un LB real.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -85354865
.

He estado leyendo la fuente de kube-proxy y el paquete de proxy; ¿No se está utilizando iptables en la revisión actual?

¿Qué es exactamente lo que se necesita hacer al respecto? Desde la fuente maestra actual, parece que iptables ya se está usando bastante en proxy.

@mikedanese @thockin Readiness es más útil para cortes planificados. Las interrupciones no planificadas siempre causarán algunos errores observables. El intervalo de sondeo generalmente debería ser largo en relación con la latencia de actualización, pero también podríamos implementar reglas de reenvío en el nodo de destino a través de la comunicación directa entre Kubelet y kube-proxy, si la latencia a través de apiserver y etcd es demasiado larga y / o eso La ruta no es lo suficientemente confiable.

@BenTheElder Las reglas existentes enrutan el tráfico a través del proxy. La idea aquí es usar las reglas para evitar el proxy.

@ bgrant0607 Gracias, ahora tiene mucho sentido. Otro leyó la fuente y los documentos de diseño y casi termino de escribir un borrador de propuesta.

Borrador de propuesta de GSoC: https://gist.github.com/BenTheElder/ac61900595a7ea9ea9b5

Agradecí especialmente los comentarios sobre la sección de programación. No estoy muy seguro de eso.
¿Debo terminar antes? Me encantaría trabajar en algunos otros problemas de GSoC (¿más pequeños?) No tomados como:
https://github.com/GoogleCloudPlatform/kubernetes/issues/1651.

Gracias de nuevo, Kubernetes se lleva la palma por ser el grupo más amigable.

Solo quiero decir que estoy muy feliz de decir que mi propuesta ha sido aceptada y que trabajaré en esto durante el verano. : smiley:

Estoy muy emocionado. Desafortunadamente, estoy en medio de mis finales en este momento, pero a partir de este fin de semana debería estar en mucho más y trabajando en ello, lo más probable es que comience con https://github.com/GoogleCloudPlatform/kubernetes/pull/7032 finalizado.

@thockin @brendanburns ¿Alguien puede opinar si queremos hacer esto en paralelo al proxy del espacio de usuario o cómo funcionaría la migración a la reimplementación?

Parece que ya preferimos iptables> = 1.4.11 (publicado el 26 de mayo de 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) {

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

¿Vemos realmente hosts más antiguos que eso?

Un enfoque sería, obviamente, detectar en tiempo de ejecución qué versión de iptables estamos ejecutando y hacer lo "mejor" que podamos dar la versión, por ejemplo, algo como:

if (versión antigua) {
cargar el módulo de proxy de espacio de usuario
}
demás {
cargar módulo de proxy iptables
}

Advierto contra tener demasiadas ramas en la declaración if anterior (idealmente solo 2), y evitar en la medida de lo posible tener este tipo de declaración if en más de un lugar en el código.

No he examinado el código en detalle para averiguar qué tan factible es el enfoque anterior.

Además, ¿todos los nodos deben implementar la misma estrategia (espacio de usuario vs proxy iptables), o cada uno puede decidir de forma independiente?

Si cada nodo decide de forma independiente, potencialmente aumentamos el área de la superficie de prueba proporcional al cuadrado del número de ramas en la declaración if anterior (es decir, source_mode x dest_mode), pero si podemos mantener el número de modos en 2, creo que está bien .

Q

Ah, y la respuesta a su pregunta de si vemos nodos antiguos es "sí", lamentablemente.

Hay mucha discusión sobre lo anterior en un número separado. Trataré de desenterrarlo para usted.

@ quinton-hoole ¡Gracias!

También estoy bastante seguro de que podemos ejecutar el espacio de usuario en un nodo e iptables en otro.

El número de modos debería ser solo 2 excepto por ese truco para cuando no tenemos -C pero los nodos que tienen -C deberían poder ejecutar la versión pura de iptables (creo).

Ah, sí, el número 7528 trata sobre las versiones del kernel y demás.

Gracias.
No vi eso cuando busqué requisitos para kubernetes. Los únicos requisitos que encontré fueron en los documentos de redes que discuten cómo asumimos ip únicas.

Probablemente deberíamos obtener alguna documentación escrita para los requisitos una vez que tengamos una mejor idea de cuáles son.

Empecé a piratear esto aquí: https://github.com/BenTheElder/kubernetes/tree/iptables_proxy

Específicamente, moví la implementación del espacio de usuario detrás de una interfaz aquí:
https://github.com/BenTheElder/kubernetes/commit/4e5d24bb74aca43b0dd37cf5cfee8a34f8eff2bf

Sin embargo, ahora no estoy seguro de si la selección de implementación debe estar en cmd / kube-proxy o en pkg / proxy, por lo que puedo eliminar esto y hacer que kube-proxy seleccione la implementación.

Editar: Creo que, en retrospectiva, probablemente tenga más sentido seleccionar la implementación de kube-proxy.

@BenTheElder Probé las reglas de Tim con Calico y funcionan bien. Hacemos todo nuestro trabajo en la tabla de filtros, por lo que las reglas DNAT aquí han establecido la IP src apropiada en ese punto.

De manera más general, sería bueno tener una discusión para definir cómo los complementos de red pueden alterar iptables de manera segura si Kubernetes también va a insertar reglas allí. No quiero pisotear (o ser pisoteado) las reglas de Kubernetes si cambian en el futuro.

@Simétrico Sí. Todavía no estoy seguro acerca de la parte de los complementos, pero eso parece bastante importante.

Probablemente voy a estar un poco ocupado este fin de semana, pero el lunes debería comenzar a trabajar en este tiempo completo para que GSoC implemente la primera iteración.
Me gustaría tener esto en cuenta al hacerlo, pero después de revisar la API de complementos de red, no estoy muy seguro de cuál es la forma más limpia de manejar esto.

¿Tiene alguna idea de cómo le gustaría que se vea o cómo debería funcionar?

FWIW, hice algo que nos funcionó porque el proxy de kube casi no respondía. Está aquí: https://github.com/MikaelCluseau/kubernetes-iptables-proxy/blob/master/iptables-routing.rb.

No vi este hilo antes, pero termino con algo parecido, excepto que cometí un error con mis estadísticas aleatorias con los pesos de coincidencia :-)

También me gustaría compartir que hemos llegado al nf_conntrack_max rápidamente. Probablemente debería aumentarse.

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

Puede que no haya entendido toda la necesidad de iptables , pero ¿por qué no usar IPVS lugar?
Parece ser más relevante para el proxy que iptables ...
Aquí hay una implementación de go simple: https://github.com/noxiouz/go-ipvs
Y solo para completar # 561, también está el proyecto ktcpvs .

IPVS también parece ser una abstracción de netfilter (como iptables). Podemos compartir algunas funciones con el código existente usando iptables; e iptables parece la solución más flexible / general para administrar netfilter.

En cuanto a # 561 y ktcpvs: ktcpvs no parece haber tenido ningún desarrollo desde 2004 y no parece tener características que los usuarios desearían como reescritura de URL. Independientemente, el # 561 está buscando una solución genérica que se pueda utilizar con equilibradores enchufables.

Nota al margen: ese proyecto de Go no parece tener una licencia.

iptables quedará obsoleto "un día" a favor de nftables ( nft cli).
Además, el uso de la CLI de iptables para crear reglas no parece ser muy sólido ...

Una búsqueda rápida me encuentra este otro proyecto del MIT: https://github.com/vieux/go-libipvs
Pero parece ser realmente bastante fácil crear uno simple y funcional, ya que toda la complejidad ya está a prueba de balas dentro del código del kernel.

Dudo que iptables se elimine de cualquiera de las principales distribuciones en el corto plazo, y la CLI de iptables es específicamente para crear y administrar reglas para netfilter ...

Un contenedor cgo incompleto como el vinculado parece mucho menos seguro que desembolsar a iptables y iptables-restore y ya necesitamos iptables para otras reglas (por ejemplo, nodeports) y con iptables-restore podemos hacer actualizaciones masivas con cierta atomicidad.

Además, IPVS parece estar diseñado para ser utilizado en una máquina host de equilibrio de carga por separado de los servidores "reales".
Esto sugiere que para ser el único uso admitido:

2.2. Problemas: necesita un cliente externo (el director y los servidores reales no pueden acceder al servicio virtual)

Para configurar y probar / ejecutar LVS, necesita un mínimo de 3 máquinas: cliente, director, servidor (es) real.

Desde el exterior, el LVS funciona como una sola máquina. El cliente no puede ser una de las máquinas del LVS (el director o el servidor real). Necesita un cliente externo. Si intenta acceder a un servicio controlado por LVS (por ejemplo, http, smtp, telnet) desde cualquiera de las máquinas del LVS; el acceso desde el director se bloqueará, el acceso desde un servidor real se conectará al servicio localmente, sin pasar por LVS.

También parece que IPVS / LVS agrega algunos requisitos adicionales como un demonio de latidos y procesos de monitoreo adicionales. Ya manejamos información de endpoints y monitoreo de estado de pod, etc. desde dentro de Kubernetes.

+1 para el enfoque de iptables. Usamos iptables ampliamente en Calico y han demostrado ser robustos y funcionan y escalan bien (suponiendo que diseñe bien sus reglas). @BenTheElder , si necesita ayuda con el trabajo de iptables, háganoslo saber, porque estaremos encantados de colaborar.

+1 para iptables e iptables-restore, es un enfoque mucho menos pesado
que IPVS / LVS y dicta menos requisitos del sistema (demonio de latido,
etc.)

El sábado 13 de junio de 2015 a las 11:27 a. M., Alex Pollitt [email protected]
escribió:

+1 para el enfoque de iptables. Usamos iptables ampliamente en Calico y
han demostrado ser robustos y funcionan y escalan bien (asumiendo que
diseña bien tus reglas). @BenTheElder https://github.com/BenTheElder ,
Si necesita ayuda con alguna de las iptables, deje que
nosotros lo sabemos, porque estaremos encantados de contribuir.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -111719474
.

Gracias Alex, te avisaré si lo hago.

Me vendrían bien algunos comentarios / aportaciones sobre la implementación actual (https://github.com/GoogleCloudPlatform/kubernetes/pull/9210) si alguien tiene tiempo.

Está en su mayoría completo y actualmente está actualizado con el maestro ascendente, necesito terminar de escribir el código que compara las reglas generadas con iptables-save y restaura los contadores, etc., pero las reglas se generan y (en su mayoría) funcionan, siguiendo prácticamente las reglas descritas en el OP aquí, con el cambio más grande solo en los nombres de la cadena, que era necesario para la generación automática de nombres que iptables aceptará.

Hay un caso de borde informado aquí: https://github.com/BenTheElder/kubernetes/issues/3 que puede requerir un cambio para manejar los pods que se conectan a sí mismos.

He tenido excelentes comentarios y discusiones con @MikaelCluseau y @Symmetric en particular sobre cómo hacer un rediseño para manejar esto y otras cosas (¡gracias de nuevo!); pero podríamos utilizar más información sobre el diseño de reglas en particular. Si alguien más tiene tiempo para echar un vistazo, se lo agradecería mucho, ya que no estoy seguro de cuál es la mejor ruta a seguir y quiero evitar hacer cambios importantes sin más información.

El PR en sí es bastante grande, pero la generación de reglas relevantes está en pkg/proxy/proxieriptables.go syncProxyRules() en: https://github.com/BenTheElder/kubernetes/blob/iptables_proxy/pkg/proxy/proxieriptables. ir # L286

La discusión existente se puede ver (aquí, por supuesto), así como en los comentarios de relaciones públicas y en https://github.com/BenTheElder/kubernetes/issues/3 , así como un poco más en https://github.com/ BenTheElder / kubernetes / issues / 4.

Otro problema que necesita información:

En el código actual, el proxy kube todavía está incluido, para manejar ÚNICAMENTE el caso de nodePort. Creo que también podemos eliminar kube-proxy en este caso, y hemos propuesto algunas reglas simples de iptables para hacerlo en el PR de Ben .

Pero estas reglas aún oscurecen la IP de origen de cualquier LB externo, por lo que no son ideales. El problema es que si solo usamos el tráfico DNAT del LB cuando llega a un nodo, entonces el paquete de respuesta podría provenir de un nodo diferente, por lo que no creo que el LB pueda correlacionar la respuesta con la sesión TCP de origen. . ¿Es válida esta preocupación? La implementación sería más sencilla si no tuviéramos que preocuparnos por esto.

Sospecho que hay algo de magia que podemos hacer para mantener contentos a los proxies HTTP, pero no veo una manera de hacer esto general en L4.

Estoy probando la magia negra de su PR, pero no genera nada para mí, parece que las reglas comenzaron a generarse con llamadas a iptables y luego se produce un archivo de restauración de iptables.

Hay una falta en la parte del encabezado en el archivo producido, generalmente los que se han llenado con la llamada iptables. Existe la parte relevante del registro:

I0807 11: 41: 24.560063 8369 iptables.go: 327] ejecutando iptables -N [KUBE-PORTALS-CONTAINER -t nat]
I0807 11: 41: 24.562361 8369 iptables.go: 327] ejecutando iptables -C [PREROUTING -t nat -m comment --comment handle ClusterIPs; NOTA: esto debe estar antes de las reglas de NodePort -j KUBE-PORTALS-CONTAINER]
I0807 11: 41: 24.563469 8369 iptables.go: 327] ejecutando iptables -N [KUBE-PORTALS-HOST -t nat]
I0807 11: 41: 24.565452 8369 iptables.go: 327] ejecutando iptables -C [SALIDA -t nat -m comentario - comentario maneja ClusterIPs; NOTA: esto debe ser antes de las reglas de NodePort -j KUBE-PORTALS-HOST]
I0807 11: 41: 24.566552 8369 iptables.go: 327] ejecutando iptables -N [KUBE-NODEPORT-CONTAINER -t nat]
I0807 11: 41: 24.568363 8369 iptables.go: 327] ejecutando iptables -C [PREROUTING -t nat -m addrtype --dst-type LOCAL -m comment --comment handle service NodePorts; NOTA: esta debe ser la última regla de la cadena -j KUBE-NODEPORT-CONTAINER]
I0807 11: 41: 24.569564 8369 iptables.go: 327] ejecutando iptables -N [KUBE-NODEPORT-HOST -t nat]
I0807 11: 41: 24.571458 8369 iptables.go: 327] ejecutando iptables -C [SALIDA -t nat -m addrtype --dst-type LOCAL -m comentario --comment handle service NodePorts; NOTA: esta debe ser la última regla de la cadena -j KUBE-NODEPORT-HOST]
I0807 11: 41: 24.573392 8369 iptables.go: 327] ejecutando iptables -C [POSTROUTING -t nat -m comment --comment handle pod conectándose a self -s 10.240.240.78/32 -d 10.240.240.78/32 -j MASQUERADE ]
I0807 11: 41: 24.574447 8369 proxier.go: 349] Sincronización de reglas de iptables.
I0807 11: 41: 24.575592 8369 proxier.go: 399] Cadena: PREROUTING, Regla:: PREROUTING ACCEPT [0: 0]
I0807 11: 41: 24.575615 8369 proxier.go: 401] Regla: -A PREROUTING -m comentario --comentar "manejar ClusterIPs; NOTA: esto debe estar antes de las reglas de NodePort" -j KUBE-PORTALS-CONTAINER
I0807 11: 41: 24.575625 8369 proxier.go: 401] Regla: -A PREROUTING -m addrtype --dst-type LOCAL -m comment --comment "handle service NodePorts; NOTA: esta debe ser la última regla de la cadena" -j CONTENEDOR-KUBE-NODEPORT
I0807 11: 41: 24.575633 8369 proxier.go: 399] Cadena: INPUT, Regla:: INPUT ACCEPT [0: 0]
I0807 11: 41: 24.575646 8369 proxier.go: 399] Cadena: SALIDA, Regla: SALIDA ACEPTAR [0: 0]
I0807 11: 41: 24.575658 8369 proxier.go: 401] Regla: -A OUTPUT -m comment --comment "maneja ClusterIPs; NOTA: esto debe estar antes de las reglas de NodePort" -j KUBE-PORTALS-HOST
I0807 11: 41: 24.575670 8369 proxier.go: 401] Regla: -A OUTPUT -m addrtype --dst-type LOCAL -m comment --comment "handle service NodePorts; NOTA: esta debe ser la última regla de la cadena" -j KUBE-NODEPORT-HOST
I0807 11: 41: 24.575683 8369 proxier.go: 399] Cadena: POSTROUTING, Regla:: POSTROUTING ACCEPT [0: 0]
I0807 11: 41: 24.575691 8369 proxier.go: 401] Regla: -A POSTROUTING! -d 10.0.0.0/8 -o eth0 -j MASCARADA
I0807 11: 41: 24.575699 8369 proxier.go: 401] Regla: -A POSTROUTING -s 10.240.240.78/32 -d 10.240.240.78/32 -m comentario --comment "manejar pod conectándose a uno mismo" -j MASQUERADE
I0807 11: 41: 24.575709 8369 proxier.go: 399] Cadena: KUBE-NODEPORT-CONTAINER, Regla:: KUBE-NODEPORT-CONTAINER - [0: 0]
I0807 11: 41: 24.575720 8369 proxier.go: 399] Cadena: KUBE-NODEPORT-HOST, Regla: KUBE-NODEPORT-HOST - [0: 0]
I0807 11: 41: 24.575729 8369 proxier.go: 399] Cadena: KUBE-PORTALS-CONTAINER, Regla:: KUBE-PORTALS-CONTAINER - [0: 0]
I0807 11: 41: 24.575740 8369 proxier.go: 399] Cadena: KUBE-PORTALS-HOST, Regla:: KUBE-PORTALS-HOST - [0: 0]
I0807 11: 41: 24.581897 8369 proxier.go: 603] Regla de sincronización:: 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]
[... SNIP ...]

La combinación de un iptable-save con el resultado producido en modo detallado se puede importar y hacer cosas buenas.

@bnprss gracias por el informe, recientemente hubo una serie de cambios no probados, incluido el uso de un archivo temporal y el uso de la bandera "-T table" para iptables-restore durante algunas reescrituras para el proceso de revisión. Lo arreglaré una vez que sepa qué causó la (s) regresión (es).

@bnprss Como dijiste, falta el encabezado de la tabla ("* nat" debería ser la primera línea), se eliminó por error y, después de volver a colocarlo, todo parece estar funcionando bien de nuevo, aparentemente sin otros errores (excluyendo: https: / /github.com/BenTheElder/kubernetes/issues/3). Gracias de nuevo, lo siento. Empujé la solución.

Buen trabajo, las reglas se están cargando y parece funcionar desde adentro, pero no tuve suerte con el balanceador de carga externo, ninguna comunicación desde el exterior dio respuesta.

Eh. ¿Podrías pasar al RP y proporcionar más detalles? Hasta aquí
ha funcionado bien, pero no me despliego más allá de las pruebas locales y
no creo que ninguno de los otros probadores estuviera usando un balanceador de carga externo.
El 7 de agosto de 2015 a las 13:29, "bnprss" [email protected] escribió:

Buen trabajo, las reglas se están cargando y parece funcionar desde adentro, pero no hubo suerte.
con balanceador de carga externo sin comunicación desde el exterior dar respuesta.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -128772763
.

Sí, para obtener más detalles, realizaré más consultas y produciré algunos registros o pistas sobre relaciones públicas, pero no antes de mañana, me gustaría tener un buen trabajo de respaldo para ejecutar antes de potencialmente romper algo.

¿Puede calcular el token de las reglas sin separadores "-_"?

@bnprss , genial.
Las cadenas de reglas generadas para los servicios son un hash del puerto / punto final del servicio y luego la URL base64 codificada y truncada. KUBE-SVC-. El código está aquí: https://github.com/GoogleCloudPlatform/kubernetes/pull/9210/files#diff -d51765b83fe795b469e8a86276b12dc9R321
Elegimos esto como una forma de generar nombres de cadena válidos que cumplirán con el límite de caracteres en iptables sin dejar de ser deterministas.
Entonces debería ser posible replicar externamente.
Si quiere decir, podemos dejar de usar separadores, probablemente podríamos, pero el "_" proviene de algunos hash codificados y el "-" simplemente siguen los patrones en los nombres de las reglas del proxy del espacio de usuario existente.
Probablemente podríamos usar otra cosa sin demasiados problemas si fuera necesario.

Estoy de acuerdo con eso, ¡y esto es realmente cosmético! :)
Pero esto difiere de las cosas que vi antes:
reglas de gce lb: a07f76b3b2ec311e59e2642010af0479
Reglas de gce fw: k8s-fw-a7ecad94f3ba511e59e2642010af0479
reglas de enrutamiento de gce: default-route-6973e029b504a0e8
Enrutamiento de gce al nodo: obfuscated_cluster_node-43506797-2eb2-11e5-9e26-42010af04793

este es bueno:
KUBE-SVC-6ADi2TVfn7mFPvBjC56
esos son divertidos:
KUBE-SVC-zU6ParcQ-UfW_LdRDUc
KUBE-SVC-y - z1xTUpHPT6sgAUCC

Sí, tampoco soy exactamente un fan de ellos, tal vez podríamos cambiar el hash
codificación.

El viernes 7 de agosto de 2015 a las 2:16 p.m., bnprss [email protected] escribió:

Estoy de acuerdo con eso, ¡y esto es realmente cosmético! :)
Pero esto difiere de las cosas que vi antes:
reglas de gce lb: a07f76b3b2ec311e59e2642010af0479
Reglas de gce fw: k8s-fw-a7ecad94f3ba511e59e2642010af0479
reglas de enrutamiento de gce: default-route-6973e029b504a0e8
Enrutamiento de gce al nodo:
obfuscated_cluster_node-43506797-2eb2-11e5-9e26-42010af04793

este es bueno:
KUBE-SVC-6ADi2TVfn7mFPvBjC56
esos son divertidos:
KUBE-SVC-zU6ParcQ-UfW_LdRDUc
KUBE-SVC-y - z1xTUpHPT6sgAUCC

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -128785914
.

Sí, solo es posible usar la parte truncada de SHA, git está bien con eso, docker también, y parece ser la forma en que se hace la otra referencia a las entidades de kube. En caso de colisión en el hash base64 generado, no ayudará. ;)
Supongo que @thockin podría asesorar sobre ese punto.

Estaba más preocupado por los caracteres válidos en iptables, para lo cual tuve dificultades para encontrar una buena referencia. Examinaré esto más a fondo en breve.

El viernes 7 de agosto de 2015 a las 2:29 p.m., bnprss [email protected] escribió:

Sí, solo es posible usar la parte truncada de SHA, git está bien con
eso, docker también, y parece ser la forma en que la otra referencia a kube
se hacen entidades. En caso de colisión en el hash generado, base64 no
ayuda. ;)
Supongo que @thockin https://github.com/thockin podría asesorar sobre ese punto.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -128788454
.

@bnprss para su información, el PR es bastante inestable y, por lo visto, estamos recortando NodePort, etc.por ahora y nos centraremos en obtener una versión más simple y limpia con soporte para portales, y luego trabajando de nuevo hasta la paridad completa.

_No_ trataría de ejecutar esto en este momento, pero espero que vuelva pronto. Dividiendo el PR en algunos relacionados más pequeños y luego presionando uno limpio con las cosas de iptables-proxy ahora mismo.

Para aquellos de ustedes que jueguen en casa, estoy seguro de que podemos lograrlo al máximo.
paridad, pero será mucho más fácil de revisar en etapas :)

El viernes 7 de agosto de 2015 a las 9:35 p.m., Benjamin Elder [email protected]
escribió:

Mi respuesta al comentario anterior, también pronto será eliminada:

Discutido en IRC:

  • todavía necesitará manejar contadores, pero querrá seguir analizando
    estado en el paquete util / iptables.
  • todavía necesita hash o similar para manejar los límites de longitud de la cadena

De lo contrario, parece una simplificación muy limpia, se implementará después
un poco más de discusión.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -128912169
.

Estado: la lógica "principal" está registrada y activada por bandera.

Ahora estoy trabajando en puertos de nodo. Hay muchos casos raros que necesitan un tratamiento especial. Mis notas hasta ahora:

# 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

He estado trabajando en una herramienta contrib para las pruebas.
Hasta ahora, estoy pensando que encenderé un servidor en un nodo, la latencia de tiempo de
solicitudes, consulte cómo obtener la carga de recursos de kube-proxy y volcar el
datos a CSV para graficar, etc.
Con suerte, estará listo antes del viernes, familiarizándome con kubectl ahora mismo.

El miércoles 12 de agosto de 2015 a las 8:48 p.m., Tim Hockin [email protected]
escribió:

Estado: la lógica "principal" está registrada y activada por bandera.

Ahora estoy trabajando en puertos de nodo. Hay muchos casos raros que necesitan
manejo especial. Mis notas hasta ahora:

Puertos de nodo básicos:

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

Para obtener tráfico de nodo a localhost: puerto de nodo al servicio:

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

Marque los paquetes que están destinados a servicios de localhost, luego enmascare esos

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

Para obtener tráfico de un pod a sí mismo a través de un servicio:

para intf en $ (lista de enlaces ip | grep veth | cut -f2 -d :); hacer brctl horquilla cbr0 $ intf on; hecho

Marque los paquetes que están destinados a cada punto final desde el mismo punto final y luego enmascare esos.

Esto es hacky, pero realmente no sé qué pods son "locales" y realmente no quiero saberlo en este momento. (pero eventualmente lo haré)

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

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130492394
.

@BenTheElder Acabo de realizar algunas mediciones de

netperf es una herramienta de rendimiento de cliente / servidor, he empaquetado tanto el cliente como el servidor en el contenedor docker paultiplady / netserver: ubuntu.2. Hay muchas opciones en netperf, pero algo como hacer girar dos pods de servidor de red y ejecutar

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

debería brindarle una distribución decente de estadísticas, incluida la latencia y el rendimiento. Puede ejecutar el contenedor netserver usando docker run --net=host para hacer pruebas de nodo-> pod también.

El dockerfile para este contenedor es bastante simple, puedo dispararlo si desea extenderlo a algo más delgado (por ejemplo, un contenedor basado en alpinelinux para una extracción más rápida).

Gracias, lo investigaré.

Sin embargo, a partir de este comentario , creo que queremos hacer algún tipo de latencia de solicitud de servicio. En este momento, estoy tratando de usar el contenedor nginx estándar como nodo X y estoy trabajando para tener un tiempo de prueba para presionarlo repetidamente para que podamos construir un gráfico en el nodo Y.

Sin embargo, miraré netperf / qperf, y siempre podemos tener múltiples pruebas.
Sin embargo, me gustaría hacer ese gráfico primero según la discusión anterior con @thockin

El jueves 13 de agosto de 2015 a las 12:02 a. M., Paul Tiplady [email protected]
escribió:

@BenTheElder https://github.com/BenTheElder Acabo de hacer algo razonablemente
mediciones de rendimiento de red detalladas en GCE: recomiendo echar un vistazo a
netperf (qperf también proporciona medidas de latencia).

netperf es una herramienta de rendimiento cliente / servidor, he empaquetado tanto el cliente como
el servidor en el contenedor docker paultiplady / netserver: ubuntu.2. Allí
hay muchas opciones en netperf, pero algo así como girar dos
pods de netserver y en ejecución

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

debería brindarle una distribución decente de estadísticas, incluida la latencia y el rendimiento.
Puede ejecutar el contenedor netserver usando docker run --net = host to do
Nodo-> pruebas de pod también.

El dockerfile para este contenedor es bastante simple, puedo dispararlo si
desea extenderlo a algo más delgado (por ejemplo, un basado en alpinelinux
contenedor para tirar más rápido).

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130524576
.

con respecto a los puertos de nodo: En # 9210 @Symmetric presentó este caso:

Si el tráfico fluye:
LB -> node1:nodePort
Y el pod de servicio está en el nodo2, entonces el flujo completo será:
LB -> node1:nodePort -> node2 -> pod:svcPort
El srcIP seguirá siendo el LB, por lo que la respuesta será
pod -> node2 -> LB
Dado que el nodo2 puede enrutar directamente al LB.

Ahora perdemos la oportunidad de anular DNAT para restaurar la IP de origen correcta para el paquete de retorno (eso solo puede suceder en el nodo1).

He reproducido el problema. RECONOCE que es un problema real. tcpdump muestra los paquetes que se están enviando por DNAT al puerto IP: del pod (fuera de la máquina), con src intacto, pero tcpdump en la máquina de destino no muestra nada. No estoy seguro de qué esperaría que sucediera incluso si los paquetes llegaran allí.

Creo que la única solución es SNAT. La solución menos impactante sería _sólo_ paquetes SNAT del LB que están destinados fuera del nodo, pero a) no tengo esa información en kube-proxy (podría obtenerla a costa del código) yb) ya que cualquier La política tendrá que considerar el caso SNAT de todos modos, puedo simplificar siempre SNATing paquetes LB externos. ¿Qué tan malo es eso para los motores de políticas?

Eventualmente, los LB serán lo suficientemente inteligentes como para apuntar solo a hosts con pods y el tráfico permanecerá local, y luego esto será discutible.

Sin embargo, se vuelve más complicado. Tenemos el campo obsoletoPublicIPs que probablemente desaprovecharemos con algunos ajustes en el comportamiento. Supongo que debemos hacer lo mismo con ellos. Pero se vuelve aún más complicado: en realidad, no CONOZCO todas las IP públicas (por ejemplo, la VM tiene una IP externa NAT 1 a 1). Respuesta fácil: siempre paquetes de puerto de nodo SNAT. ¿Qué pensar?

Probaré más mañana.

@BenTheElder Podrías convertir el pod de netserver en un servicio, de modo que el tráfico de perf <->
servidor va a través del servicio VIP. De esa manera no tienes que hacer el
cálculos de muestreo / latencia usted mismo ...

El miércoles 12 de agosto de 2015 a las 9:20 p.m., Benjamin Elder [email protected]
escribió:

Gracias, lo investigaré.

De este comentario
aunque creo que queremos hacer algún tipo de latencia de solicitud de servicio. Derecha
ahora estoy tratando de usar el contenedor nginx estándar como nodo X y trabajando en
tener un tiempo de prueba de la cápsula presionándolo repetidamente para que podamos construir un gráfico en
nodo Y.

Sin embargo, miraré netperf / qperf, y siempre podemos tener múltiples pruebas.
Me gustaría hacer ese gráfico primero, aunque según la discusión anterior con
@thockin

El jueves 13 de agosto de 2015 a las 12:02 a. M., Paul Tiplady [email protected]
escribió:

@BenTheElder https://github.com/BenTheElder Acabo de hacer algo razonablemente
mediciones de rendimiento de red detalladas en GCE: recomiendo echar un vistazo a
netperf (qperf también proporciona medidas de latencia).

netperf es una herramienta de rendimiento cliente / servidor, he empaquetado tanto el cliente como
el servidor en el contenedor docker paultiplady / netserver: ubuntu.2. Allí
hay muchas opciones en netperf, pero algo así como girar dos
pods de netserver y en ejecución

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

debería ofrecerle una distribución decente de estadísticas, incluida la latencia y
rendimiento.
Puede ejecutar el contenedor netserver usando docker run --net = host to do
Nodo-> pruebas de pod también.

El dockerfile para este contenedor es bastante simple, puedo dispararlo si
desea extenderlo a algo más delgado (por ejemplo, un basado en alpinelinux
contenedor para tirar más rápido).

-
Responda a este correo electrónico directamente o véalo en GitHub
<
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130524576

.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130527558
.

Verdadero. Creo que @thockin mencionó eventualmente querer una prueba de latencia e2e como
bien. Si el tiempo lo permite, habrá una serie de pruebas diferentes y
probablemente tenga que tener en cuenta gce vs AWS, etc.
El 13 de agosto de 2015 a las 13:47, "Paul Tiplady" [email protected] escribió:

Puede convertir el pod de servidor de red en un servicio, de modo que el tráfico de perf <->
servidor va a través del servicio VIP. De esa manera no tienes que hacer el
cálculos de muestreo / latencia usted mismo ...

El miércoles 12 de agosto de 2015 a las 9:20 p.m., Benjamin Elder [email protected]
escribió:

Gracias, lo investigaré.

De [este comentario] (

https://github.com/kubernetes/kubernetes/pull/9210#issuecomment-130154261)
aunque creo que queremos hacer algún tipo de latencia de solicitud de servicio. Derecha
ahora estoy tratando de usar el contenedor nginx estándar como nodo X y funcionando
sobre
tener un tiempo de prueba de la cápsula presionándolo repetidamente para que podamos construir un gráfico en
nodo Y.

Sin embargo, miraré netperf / qperf, y siempre podemos tener múltiples pruebas.
Me gustaría hacer ese gráfico primero, aunque según la discusión anterior con
@thockin

El jueves 13 de agosto de 2015 a las 12:02 a. M., Paul Tiplady < [email protected]

escribió:

@BenTheElder https://github.com/BenTheElder Acabo de hacer algunos
razonablemente
mediciones detalladas del rendimiento de la red en GCE: recomiendo echar un vistazo
a
netperf (qperf también proporciona medidas de latencia).

netperf es una herramienta de rendimiento de cliente / servidor, he empaquetado tanto el cliente
y
el servidor en el contenedor docker paultiplady / netserver: ubuntu.2.
Allí
hay muchas opciones en netperf, pero algo así como girar dos
pods de netserver y en ejecución

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

debería ofrecerle una distribución decente de estadísticas, incluida la latencia y
rendimiento.
Puede ejecutar el contenedor netserver usando docker run --net = host to do
Nodo-> pruebas de pod también.

El dockerfile para este contenedor es bastante simple, puedo dispararlo
si
desea extenderlo a algo más delgado (por ejemplo, un basado en alpinelinux
contenedor para tirar más rápido).

-
Responda a este correo electrónico directamente o véalo en GitHub
<

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

.

-
Responda a este correo electrónico directamente o véalo en GitHub
<
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130527558

.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130776866
.

@Symmetric las pruebas de netperf están funcionando bien. Gracias por la sugerencia :-)

Me gustaría revisar la prueba de una carga "real" como un servicio web más tarde posiblemente, pero después de obtener los argumentos correctos, está dando muy buenos datos hasta ahora. Publicaré los resultados más tarde, cuando haya terminado de limpiar las cosas.

Me alegra saber que está funcionando para usted, hay un número asombroso de
opciones en esa herramienta, pero ha demostrado ser muy útil para mi trabajo de creación de perfiles.
Definitivamente mejor que iperf ...

El jueves 13 de agosto de 2015 a las 2:32 p.m., Benjamin Elder [email protected]
escribió:

@Symmetric https://github.com/Symmetric las pruebas de netperf están funcionando
bien. Gracias por la sugerencia :-)

Me gustaría revisar la prueba de una carga "real" como un servicio web más tarde.
posiblemente, pero después de acertar con los argumentos, está dando muy buenos datos, así que
lejos. Publicaré los resultados más tarde, cuando haya terminado de limpiar las cosas.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130850398
.

@thockin Creo que podemos vivir con SNAT para el tráfico de LB. Mi opinión actual es que deberá especificar la política de acceso de un pod como una de las siguientes:

  • el valor predeterminado es 'permitir desde [mi espacio de nombres]', en cuyo caso los paquetes LB se eliminan
  • 'permitir desde [lista de espacios de nombres]', o 'permitir desde [todos los espacios de nombres en el clúster]', nuevamente los paquetes LB siempre se descartan
  • 'permitir de todos', en cuyo caso no nos importa si es de un LB, otro nodo o donde sea

Por lo tanto, perder la IP de origen solo para los LB no nos cuesta mucho.

Si podemos garantizar que LB está llegando al nodo correcto para el módulo de servicio, sería genial; en ese caso, no necesitamos SNAT, y podemos ejecutar un barco más ajustado al incluir en la lista blanca las IP de LB cuando se aprovisionan en un servicio y, de lo contrario, eliminar el tráfico.

Con respecto a los IP públicos, creo que tendrán las mismas consideraciones que nodePort, por lo que necesitaremos SNAT hasta que los LB puedan llegar a los hosts correctos. Lo que por lo anterior está bien, a menos que me falte alguna forma de que sean más malvados que nodePort ...

Como medida de seguridad, podría ser muy útil incluir una bandera para proxy para MASQUERADE todo (actuando muy cerca de un proxy de espacio de usuario). Creo que no es muy difícil de hacer y es una muy buena forma de diagnosticar o incluso retroceder en caso de problema (estoy pensando en casos de vxlan).

-------- Mensaje de origen --------
De: Paul Tiplady [email protected]
Fecha: 14/08/2015 12:50 (GMT + 11: 00)
À: kubernetes / kubernetes [email protected]
Cc: Mikaël Cluseau [email protected]
Objet: Re: [kubernetes] usa iptables para proxy en lugar de espacio de usuario
(# 3760)

@thockin Creo que podemos vivir con SNAT para el tráfico de LB. Mi opinión actual es que deberá especificar la política de acceso de un pod como una de las siguientes:

el valor predeterminado es 'permitir desde [mi espacio de nombres]', en cuyo caso los paquetes LB se eliminan
'permitir desde [lista de espacios de nombres]', o 'permitir desde [todos los espacios de nombres en el clúster]', nuevamente los paquetes LB siempre se descartan
'permitir de todos', en cuyo caso no nos importa si es de un LB, otro nodo o donde sea

Por lo tanto, perder la IP de origen solo para los LB no nos cuesta mucho.

Si podemos garantizar que LB está llegando al nodo correcto para el módulo de servicio, sería genial; en ese caso, no necesitamos SNAT, y podemos ejecutar un barco más ajustado al incluir en la lista blanca las IP de LB cuando se aprovisionan en un servicio y, de lo contrario, eliminar el tráfico.

Con respecto a los IP públicos, creo que tendrán las mismas consideraciones que nodePort, por lo que necesitaremos SNAT hasta que los LB puedan llegar a los hosts correctos. Lo que por lo anterior está bien, a menos que me falte alguna forma de que sean más malvados que nodePort ...

-
Responda a este correo electrónico directamente o véalo en GitHub.

@MikaelCluseau no es una mala idea. ¿Podrías abrir una nueva edición sobre eso específicamente para que no pierda la pista?

Aún TODO: arreglar horquilla, e2e, habilitar de forma predeterminada

Hola Tim, perdón por no volver contigo, pero tuvimos un lío que manejar aquí ... Creo que elegiré la horquilla de reparación el próximo sábado.

Esta fue una nota para mí, ¿estaba planeando abordar algo de esto? :)

Sí, claro, como dije cuando hablábamos de las pruebas e2e. Voy a ayudar, Kubernetes es de gran ayuda para mí, así que será mejor que lo domine tanto como sea posible, y ¿qué es mejor que eliminar errores? :-) Siéntase libre de sugerir cualquier cosa de mayor prioridad, pero creo que la horquilla es bastante buena para empezar. Debería tener lugar en el kubelet y tener una bandera para habilitar (deshabilitada por defecto al principio). Intentaré trabajar de 0,5 a 1 día a la semana.

AFAIK, la única parte que queda por hacer es convertirlo en el predeterminado, lo que puede suceder (suponiendo que no haya explosiones) algún tiempo después de la v1.1 y esto tiene algunas millas.

¡Whoo!

El jueves 24 de septiembre de 2015 a las 11:21 a. M., Tim Hockin [email protected]
escribió:

AFAIK, la única parte de esto que queda por hacer es convertirlo en el predeterminado que puede
suceder (asumiendo que no hay explosiones) algún tiempo después de v1.1 y esto tiene algunas millas
en eso.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -142960614
.

algún tiempo después de la v1.1 y esto tiene algunas millas.

Ay. Realmente estábamos contando con él para 1.1 ...
https://github.com/kubernetes/kubernetes/blob/master/docs/roadmap.md

@bgrieder todavía puede habilitarlo a través del parámetro.

Está IN pero no está activado de forma predeterminada. Puede optar por participar con una sola anotación por
nodo (y un reinicio de kube-proxy)

El jueves 24 de septiembre de 2015 a las 8:27 a.m., Bruno G. [email protected] escribió:

algún tiempo después de la v1.1 y esto tiene algunas millas.

Ay. Realmente estábamos contando con él para 1.1 ...
https://github.com/kubernetes/kubernetes/blob/master/docs/roadmap.md

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -142962932
.

@thockin @bnprss ok, pero esperamos que la versión 1.1 se ejecute en Google Container Engine después del lanzamiento. Me pregunto qué tipo de flexibilidad tendremos para 'optar por participar con una sola anotación por nodo'. ¿Podría darnos algunos detalles sobre cuál será el proceso o indicarnos alguna documentación?

Una vez actualizado a 1.1:

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

Luego SSH a cada nodo y reinicia kube-proxy (o reinicia cada nodo).

Si quieres ser más cauteloso, haz uno o dos nodos y luego pruébalo :)

He marcado este problema como "nota de lanzamiento" para que no olvidemos incluir ese bucle mágico en nuestra documentación 1.1.

@RichieEscarez

(¡Solo quería pasar y decir que hemos estado usando el proxy de iptables durante una semana y parece que todo está bien!)

@thockin ¿Debería cerrarse o eliminarse del hito 1.1?

Lo moveré a 1.2 solo para la habilitación predeterminada.

Disculpas por una pregunta potencialmente tonta, pero con respecto a la preservación de las IP de los clientes:

@thockin Vi en otro número del 2 de septiembre que "solo el tráfico intra-clúster retiene la IP del cliente". ¿Sigue siendo cierto para el alfa 1.2?

Lanzamos un nuevo clúster 1.2, aplicamos la anotación de nodo, reiniciamos y aún vemos 10.244.0.1 como la dirección de origen para todas las solicitudes realizadas a un pod que ejecuta HAProxy.

En este punto, solo estoy tratando de averiguar si nos hemos perdido o no una configuración o estoy tratando de lograr algo que aún no es posible, es decir, ver la dirección IP pública del cliente real que realiza la solicitud desde fuera del clúster.

El valor predeterminado todavía usa el modo de espacio de usuario. Tienes que establecer una anotación en
el nodo (net.beta.kubernetes. io / proxy-mode = iptables) y reinicie el
apoderado. Pero eso no expondrá las IP de los clientes externos, solo dentro del clúster
IPs.
El 23 de octubre de 2015 a las 5:09 p.m., "Ben Hundley" [email protected] escribió:

Disculpas por una pregunta potencialmente tonta, pero con respecto a la preservación
de las direcciones IP de los clientes:

@thockin https://github.com/thockin Lo vi en otro número el 2 de septiembre
que "solo el tráfico dentro del clúster retiene la IP del cliente", ¿sigue siendo
¿cierto para el 1.2 alfa?

Lanzamos un nuevo clúster 1.2, aplicamos la anotación de nodo, reiniciamos,
y aún ver 10.244.0.1 como la dirección de origen para todas las solicitudes realizadas a un
pod ejecutando HAProxy.

En este punto, solo estoy tratando de averiguar si nos hemos perdido un
o estoy tratando de lograr algo que aún no es posible: que
está viendo la dirección IP pública del cliente real que realiza la solicitud
desde fuera del clúster.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -150725513
.

Puedo mantener la IP del cliente externo mediante DNAT en el tráfico externo + enrutamiento a través de un proxy kube. Por ejemplo, si su red de servicio es 10.42.0.0/16 y tiene un proxy kube de alta disponibilidad en la IP 10.10.1.1, puede tener la siguiente regla de iptable:

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

y la siguiente ruta:

10.42.0.0/16 via 10.10.1.1 dev edge 

La vaina detrás ve la IP real:

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

Por supuesto, debe tener la ruta de retorno correcta del paquete.

Sí, si este DNAT se envía a un backend externo a la máquina, se forma un triángulo sin
SNAT. Este es el problema fundamental.

El viernes 23 de octubre de 2015 a las 8:12 p.m., Mikaël Cluseau [email protected]
escribió:

Puedo mantener la IP del cliente externo DNAT'ing tráfico externo +
enrutamiento a través de un proxy kube. Por ejemplo, si su red de servicio es
10.42.0.0/16 y tiene un proxy kube de alta disponibilidad en la IP
10.10.1.1, puede tener la siguiente regla de iptable:

-A PREROUTING -i público -p tcp -m tcp --dport 25 -j DNAT --to-destino 10.42.12.34

y la siguiente ruta:

10.42.0.0/16 a través de 10.10.1.1 dev edge

La vaina detrás ve la IP real:

24 de octubre 02:41:39 email-0yr7n mail.info postfix / smtpd [469]: conectarse desde zed.yyy.ru. [94.102.51.96]

Por supuesto, debe tener la ruta de retorno correcta del paquete.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -150747217
.

Suena interesante, ¿algún enlace? :-) Estoy tratando de encontrar una manera de asegurarme de que el paquete pasará por la regla de conntrack correcta. Estaba pensando en replicar el estado de Conntrack a través del clúster.

Estoy un poco perdido con lo que estás tratando de lograr.

La forma en que se supone que funciona el proxy iptables actual es que un paquete
llega a un nodo, detectamos que no se genera localmente, lo marcamos para
SNAT, elija un backend, avance al backend con SNAT, el backend responde
para nosotros, anulamos SNAT, anulamos DNAT y respondemos al usuario externo.

El viernes 23 de octubre de 2015 a las 21:32, Mikaël Cluseau [email protected]
escribió:

Suena interesante, ¿algún enlace? :-) Estoy tratando de encontrar una manera de asegurarme de que
paquete pasará por la regla de conntrack correcta. Estaba pensando en
replicando el estado de Conntrack a través del clúster.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -150753147
.

Oh, lo siento si no lo tengo claro. Estaba hablando del caso sin SNAT. Si cada proxy de kube tiene la misma lista de conntrack, cualquiera de ellos debería poder des-DNAT correctamente cuando el contenedor responda al cliente.

No pude ver una era sin replicación que no involucre HA para mantener una estructura en forma de línea como esta:

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

Pero si una cosa con forma de triángulo puede funcionar, debería abrir más posibilidades.

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

Eso sería lindo pero parece una locura complicado

El domingo, 25 de octubre de 2015 a las 11:20 p.m., Mikaël Cluseau [email protected]
escribió:

Oh, lo siento si no lo tengo claro. Estaba hablando del caso sin SNAT. Si
cada proxy de kube tiene la misma lista de conntrack, cualquiera de ellos debería poder
un-DNAT correctamente cuando el contenedor responde al cliente.

No pude ver una era sin replicación que no involucre HA para mantener una
estructura en forma de línea como esta:

[cliente] ----- [proxy en HA] ------ [nodo1]
`------- [nodo2]

Pero si una cosa con forma de triángulo puede funcionar, debería abrir más posibilidades.

[cliente] ----- [proxy1] ------ [nodo1]
`------ [proxy2] ------ [nodo2]

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -151037663
.

La forma en que tengo que explorar (no lo he hecho y no me gusta preguntar antes de una investigación adecuada, pero dado que el tema ahora está abierto ...) es el "Enrutamiento asimétrico de múltiples rutas" que puede ver aquí: http: // conntrack-tools.netfilter.org/manual.html#sync-aa. Y sí, eso sería realmente bueno :-)

Lo más simple que podría funcionar ...

  1. proxy1 recibe una nueva conexión a través de un gancho de iptables (creo que lo he visto en alguna parte), y su LB lo asigna al nodo del proxy2.
  2. proxy1 envía una solicitud como "configurar una entrada de conntrack para {src-ip}: {src-port} -> {pod-ip}: {pod-port}"
  3. proxy2 recibe la solicitud, configura la entrada de conntrack y ACK a proxy1
  4. proxy1 deja que el paquete pase por la regla DNAT (que también coloca una entrada conntrack en proxy1).
  5. cuando el pod responde, el host del proxy2 anula los DNAT en consecuencia.
  6. cuando el cliente envía otro paquete en este flujo a través de proxy1, la entrada conntrack también hace el DNAT correcto.

De esta manera, la sobrecarga es de 2 paquetes por nueva conexión, y se amortiza rápidamente evitando un enrutamiento extra SNAT + (ya que, de lo contrario, el paquete tiene que volver a través del proxy1).

No soy un tipo de la red, así que puedo asumir demasiado, pero eso parece razonable.

En mi caso, mi objetivo era establecer reglas de firewall, por servicio NodePort.

Parece que puedo agregar reglas simples ALLOW IP / DROP de todo lo demás en la cadena INPUT, así:

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

Para aplicar estas reglas, lo que estaba imaginando era usar anotaciones en los servicios de NodePort. Las anotaciones contendrían direcciones IP incluidas en la lista blanca.

Como puedo esperar un poco a que se apliquen estas reglas, imaginé una tarea cron minuciosa en cada minion que llega y actualiza la cadena INPUT del minion de todas las anotaciones del servicio.

¿Hay algo que pueda causar un problema aquí? ¿Estoy loco?

@thockin tiene una mejor vista que yo, pero no usaría una anotación para esto. Creo que la seguridad es ortogonal y debería dejarse a un lado en un sistema, o tal vez en un complemento de red / proxy. Si tiene Kubernetes, tiene etcd, por lo que simplemente podría almacenar un conjunto de reglas en una clave y actualizar con 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

Creo que quieres # 14505

El lunes 26 de octubre de 2015 a las 8:53 a. M., Ben Hundley [email protected]
escribió:

En mi caso, mi objetivo era establecer reglas de firewall, por servicio NodePort.

Parece que puedo agregar reglas simples PERMITIR IP / DROP todo lo demás en
la cadena INPUT, así:

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

Para aplicar estas reglas, lo que estaba imaginando era usar anotaciones en el
Servicios de NodePort. Las anotaciones contendrían direcciones IP incluidas en la lista blanca.

Como puedo esperar un poco a que se apliquen estas reglas, imaginé una minuciosa
tarea cron en cada minion que llega y actualiza la ENTRADA del minion
cadena de todas las anotaciones de servicio.

¿Hay algo que pueda causar un problema aquí? ¿Estoy loco?

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -151181267
.

Ese fue el enfoque inicial, con grupos de seguridad adjuntos a los balanceadores de carga. Acabo de alcanzar el límite de oyentes por interfaz de red bastante rápido en AWS y me encontré con una lógica complicada al tratar de difundir las reglas de firewall en múltiples SG y múltiples ELB para un solo clúster de kube.

Afortunadamente, estamos en una solución mejor que no implica jugar con iptables.

Si acaba de unirse, permítame resumirlo. Todos los problemas relacionados con la imposibilidad de obtener la IP del cliente se fusionaron en este problema, sin embargo, la solución propuesta (e implementada) no lo resuelve. Actualmente no tiene forma de acceder a la ip del cliente. Decir ah.

@ shaylevi2 simplemente no hay una buena manera de obtener la IP del cliente mientras se rebota a través de un LB en la nube y en un nodePort. Una vez que los LB de la nube se pongan al día, saltaré directamente sobre ella. Pero esto conserva la IP del cliente dentro del clúster

Pero esto conserva la IP del cliente dentro del clúster

Eso depende exactamente de cómo esté configurada la red de clúster; por ejemplo, no funciona correctamente en OpenShift en este momento, porque las reglas de iptables no se ejecutan en el tráfico interno de OVS. Entonces, los paquetes obtienen DNAT al ingresar al punto final del servicio, pero dado que la IP de origen es interna del clúster, la respuesta permanecerá dentro de OVS, por lo que no volverá a afectar a iptables, por lo que el DNAT no se invierte. por lo que el pod del cliente no reconoce los paquetes. Por el momento, la solución más simple para esto es enmascarar completamente los paquetes que ingresan al punto final, lo que los obliga a rebotar fuera de OVS nuevamente al salir. (Estoy trabajando para encontrar una forma de evitar esto).

¿OVS tiene una noción VIP internamente? Podrías simplemente deshacerte de
kube-proxy (cf opencontrail)

El viernes 20 de noviembre de 2015 a las 7:09 a.m., Dan Winship [email protected]
escribió:

Pero esto conserva la IP del cliente dentro del clúster

Eso depende exactamente de cómo esté configurada la red de clúster; por ejemplo, no lo hace
funcionan correctamente en OpenShift en este momento, porque las reglas de iptables no se ejecutan
en el tráfico interno de OVS. Entonces los paquetes obtienen DNAT al ingresar al servicio
endpoint, pero dado que la IP de origen es interna del clúster, la respuesta
permanecer dentro de OVS, para que no vuelva a afectar a iptables, por lo que el DNAT no
se invierten, por lo que el pod del cliente no reconoce los paquetes. En el
momento, la solución más simple para esto es enmascarar completamente los paquetes
yendo al punto final, lo que los obliga a rebotar fuera de OVS nuevamente en
el camino de salida. (Estoy trabajando para encontrar una forma de evitar esto).

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -158426296
.

Habíamos hablado de hacer esencialmente el equivalente de puro-iptables-proxying completamente dentro de OVS, pero eso requiere soporte de conntrack de OVS, que requiere un kernel muy reciente, del cual no queremos depender todavía. Sin embargo, ese es probablemente el plan a largo plazo.

(Por ahora, parece que podemos hacer que funcione agregando un salto adicional gratuito fuera de OVS para paquetes con un puerto IP + de origen que coincida con un punto final de servicio conocido que proviene de una interfaz de contenedor; el nodo posiblemente lo des-DNAT y luego devolverlo a OVS, donde se puede devolver al pod de cliente correctamente).

Espero escribir un documento sobre la abstracción Service VIP y hacerlo
claro que es una abstracción que puede ser reemplazada (y debería ser en algún
casos).

El lunes 23 de noviembre de 2015 a las 6:54 a. M., Dan Winship [email protected]
escribió:

Habíamos hablado de hacer esencialmente el equivalente de la
pure-iptables-proxying completamente dentro de OVS, pero eso requiere conntrack de OVS
soporte, que requiere un kernel muy reciente, del cual no queremos depender
encendido todavía. Sin embargo, ese es probablemente el plan a largo plazo.

(Por ahora parece que podemos hacer que funcione agregando un extra gratuito
Saltar de OVS para paquetes con un puerto IP + de origen que coincida con un servicio conocido
punto final que proviene de una interfaz de contenedor; el nodo entonces
posiblemente anular el DNAT y luego devolverlo a OVS donde puede obtener
entregado correctamente al pod del cliente).

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -158959014
.

Aunque iptables / nftables resolvería los casos de uso de equilibrio de carga de TCP y UDP, personalmente creo que IPVS https://github.com/kubernetes/kubernetes/issues/17470 encajaría mucho mejor porque está diseñado específicamente para el equilibrio de carga (lea: menos cambios / mantenimiento continuos para el equipo de k8s), ofrece un conjunto más rico de algoritmos de equilibrio de carga, ha demostrado estabilidad a velocidades cercanas a la línea, y también tiene bibliotecas golang listas para manipular reglas.

@thockin , otros, según https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -150743158, hice la anotación, pero como se mencionó correctamente, la aplicación que se encuentra en un contenedor aún no ve la IP del cliente externo .

¿Cómo lograr esto, es decir, obtener la IP del cliente externo? En mi configuración, no hay LB externo, el servicio está expuesto como puerto de nodo y el cliente está haciendo una conexión TCP simple (no http / Websocket) a mi aplicación en contenedor.

@ashishvyas ¿qué versión de kube-proxy estás ejecutando?

Estoy ejecutando v1.1.3

Siga las instrucciones en https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -143280584 y https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -150743158 pero en lugar de usar la anotación denominada net.beta.kubernetes.io/proxy-mode , use la anotación llamada 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

Debería ver declaraciones de registro al comienzo del inicio de kube-proxy como 'Anotación experimental encontrada' y 'La anotación permite el proxy iptables'

La primera versión en la que https://github.com/kubernetes/kubernetes/commit/da9a9a94d804c5bfdf3cc86ee76a2bc1a2742d16 fue 1.1.4, por lo que net.beta.kubernetes.io/proxy-mode no funciona para muchas personas. No eres la primera persona que se encuentra con esto.

Debido a la forma en que funciona el proxy, perdemos la IP del cliente cuando llega
un puerto de nodo. Sé que esto no es genial. Está muy en mi mente cómo
arreglar esto correctamente, pero sobre todo se reduce a las capacidades del
equilibradores de carga (u otras formas por las que el tráfico llega a un nodo, como
como DNS-RR)

El miércoles 13 de enero de 2016 a las 10:25 a. M., Mike Danese [email protected]
escribió:

Siga las instrucciones en # 3760 (comentario)
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -143280584
y # 3760 (comentario)
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -150743158
pero en lugar de usar la anotación llamada
net.beta.kubernetes.io/proxy-mode, use la anotación llamada
net.experimental.kubernetes.io/proxy-mode.

para nodo en $ (kubectl obtener nodos -o nombre); hacer
kubectl anotar $ node net.experimental.kubernetes.io/proxy-mode=iptables;
hecho

Debería ver las declaraciones de registro al comienzo del inicio de kube-proxy
como 'Anotación experimental encontrada' y 'La anotación permite el proxy iptables'

El primer lanzamiento que da9a9a9
https://github.com/kubernetes/kubernetes/commit/da9a9a94d804c5bfdf3cc86ee76a2bc1a2742d16
lo convirtió en 1.1.4. No eres la primera persona que se encuentra con esto.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -171387997
.

@thockin , ¿hay alguna solución para abordar esto temporalmente en este momento? En caso afirmativo, recomendaría proporcionar pasos detallados para mí y para otras personas en este hilo.

No, actualmente no existe una solución alternativa. El problema se reduce al
hecho de que cada kube-proxy puede elegir un backend en un nodo diferente.
El reenvío de tráfico con la IP del cliente original haría que el otro nodo
responder directamente que obviamente no funcionará.

La "solución" es _sólo_ enviar tráfico para el Servicio S a los nodos que tienen en
al menos 1 backend para que S _and_ envíe tráfico proporcional a cuántos
backends que tiene cada nodo. Kube-proxy podría elegir backends locales
exclusivamente.

Considere 2 nodos y 3 backends. Un nodo necesariamente termina con 2
backends. Cualquiera que sea la ruta que el tráfico tenga que enviar a un nodo, el doble de
hace a otro nodo. Simplemente no hemos abordado ese problema todavía, ninguno de
los equilibradores de carga en la nube admiten esto, por lo que es algo especulativo y
por lo tanto, es muy arriesgado comenzar a trabajar.

El miércoles 13 de enero de 2016 a las 12:17 p.m., Ashish Vyas [email protected]
escribió:

@thockin https://github.com/thockin , cualquier solución para temporalmente
abordar esto es posible ahora mismo? Si es así, recomendaría proporcionar
Los pasos detallados para mí y para otros en este hilo ayudarían.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -171420567
.

@mikedanese , parece que no puedo encontrar 1.1.4 en gcr.io:

$ sudo docker pull gcr.io/google_containers/ hyperkube: v1.1.4
Extrayendo el repositorio gcr.io/google_containers/hyperkube
Etiqueta v1.1.4 no encontrada en el repositorio gcr.io/google_containers/hyperkube
$ sudo docker pull gcr.io/google_containers/ hyperkube: v1.1.3
v1.1.3: Extracción de google_containers / hyperkube
Resumen: sha256: 004dde049951a4004d99e12846e1fc7274fdc5855752d50288e3be4748778ca2
Estado: la imagen está actualizada para gcr.io/google_containers/ hyperkube: v1.1.3

@thockin Disculpas por la larga respuesta, quería cubrir los dos métodos con los que intentamos resolver esto para que otros pudieran entender los desafíos que enfrentamos con ambos.

Como un poco de antecedentes, nuestra aplicación principal es una plataforma de DNS inteligente de muy alto rendimiento (es decir, necesita UDP y necesita hacer al menos 100k + solicitudes / seg por pod), y su aplicación de soporte en un proxy SNI que necesita ver a los clientes reales. Dirección IP (esto es un obstáculo para nosotros). No queríamos usar diferentes enfoques de redes para diferentes aplicaciones, por lo que decidimos estandarizar en un solo método de red para todos, y elegimos usar IPVS por las razones que mencioné anteriormente (rendimiento / estabilidad / flexibilidad / construcción de propósito SLB) , pero probablemente podría piratear algo usando solo iptables en estas mismas líneas también. Usamos vxlan (rápido, fácil, funciona entre sitios) pero ambos métodos también deberían funcionar con GRE / VXLAN con OVS o también con redes de host de Capa 2 estándar (asumiendo que sus hosts están todos en la misma red L2).

Distribuimos el tráfico entrante del usuario final utilizando una combinación de anycast y DNS, según los requisitos de velocidad de conmutación por error o lo que funcione mejor para el tipo de servicio en particular, por lo que tenemos una distribución bastante uniforme del tráfico del usuario final que ingresa a nuestros nodos, pero el El problema, como señaló, es obtener una distribución uniforme del tráfico entre los pods, independientemente de la ubicación del pod. El otro problema es asegurarse de que los servicios que se comunican con otros servicios tengan un equilibrio de carga eficaz.

Intentamos dos modelos para abordar esto:

El primer método que probamos fue 2 capas de VIP. VIP externos (1 por servicio), que distribuyen el tráfico entre los nodos (según el recuento de pods para ese servicio en el nodo), y luego VIP internos (que se ejecutan en el nodo con los pods), que distribuyen la carga dentro de los nodos (normalmente uniformemente en las vainas). La limitación de este modelo era que los nodos que ejecutaban VIP externos necesitaban ejecutar dos espacios de nombres de red diferentes o ejecutar sus propios nodos físicos. Lo bueno de IPVS en modo DSR (retorno directo del servidor) es que no necesita ver el tráfico de retorno, el tráfico va:

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

(1) IPVS (en modo DSR) en el host con un VIP externo elige un _nodo_ para enviar tráfico (un "servidor real" en términos de IPVS), y solo cambia la dirección MAC DST del paquete (es decir, el paquete IP llega sin cambios a nodo k8s). Equilibra la carga entre los nodos según la cantidad de pods que ejecutan ese servicio en el nodo.
(2) IPVS (también en modo DSR) en el nodo k8s equilibra la carga del tráfico entre los pods (a través de los veths hasta el nodo). Las respuestas de los contenedores (TCP y UDP) van directamente al consumidor del servicio.

La ventaja de este modelo es que fue muy sencillo de poner en marcha y el conjunto de reglas fue muy fácil de administrar. La desventaja de este modelo es que concentra todas nuestras solicitudes de servicio (pero no las respuestas) a través de varios nodos que ejecutan las VIP externas. Nos gusta "nada compartido", así que ingrese la versión 2:

El segundo modelo que ahora es entretenido es una capa única de VIP con una configuración de IPVS e iptables más inteligente.

Consumer >> Any node/local node >> (1) >> Container >> (any which way you want) >> Consumer
o podría ir a otro nodo:
Consumer >> Any node/local node >> (1) >> Remote Node >> (2) >> Container >> (any which way you want) >> Consumer

(1) El tráfico llega al VIP principal, la carga del tráfico se equilibra en todos los pods del clúster.
(2) El tráfico llega a VIP secundario, el tráfico se equilibra la carga solo en todos los pods locales. Esta VIP secundaria solo se utiliza para el tráfico que proviene de otros hosts de la red (es una VIP de FWMARK). Marcamos el tráfico que ingresa en cualquier interfaz externa con FWMARK = 1234, y eso obliga al tráfico a ir a un conjunto de reglas diferente, lo que evita bucles entre nodos.

El VIP principal tiene una lista de pods locales y hosts remotos con pods (con un peso de 100 para cada pod local y 100 * número de pods para nodos remotos). Entonces, por ejemplo, si 3 pods se están ejecutando localmente en el nodoA y hay dos pods ejecutándose en el nodoB, el conjunto de reglas en el nodoA se vería así:

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

Sin embargo, en el nodo B, la configuración de IPVS se vería un poco diferente porque solo tiene dos pods locales y tres pods remotos en el nodoA:

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

Otra forma sería cambiar los FWMARK y usar iptables para FWMARK cualquier cosa en las interfaces veth + (coincidencia de comodines) y hacer que la coincidencia de FWMARK solo se use para el equilibrio de carga local.

Debido a que no hay NAT involucrado aquí, debe agregar las IP SVC_XXX_YYY en el entorno a una interfaz de bucle invertido o ficticia cuando inicia cada pod, pero probablemente también podría cambiar las IPVS VIP para hacer DNAT también, no veo por qué eso no funcionaría.

El resultado final es la red más directa, sin necesidad de centralizar el procesamiento / enrutamiento de solicitudes, por lo que se escala mucho mejor. La desventaja son algunos conocimientos adicionales al crear las reglas de IPVS. Usamos un pequeño demonio (golang) para hacer todo esto, pero consideraría escribir un módulo k8s para esto si tuviera tiempo y hubiera suficiente interés.

Me estoy sumergiendo en este problema tarde, y probablemente no he leído el rastro completo con suficiente detalle, pero en caso de que ayude: si he entendido la publicación de

@lxpollitt Correcto, la IP de origen se mantiene cuando se usa IPVS, sin embargo, tenga en cuenta que con este método tuvimos que hacer prácticamente todo el trabajo en red nosotros mismos, porque la configuración de IPVS no es compatible con kube-proxy. También puede mantener la IP de origen con iptables, sin embargo, necesita dos capas de IPtables DNAT para que pueda "anular" el tráfico en el camino de regreso.

Por mi parte, con franela (en modo vxlan) administrando mi red de contenedores, uso kube-proxy (en modo iptables y no enmascarado) + franela en un espacio de nombres en mis nodos de enrutamiento. Las solicitudes externas se someten a DNAT para dar servicio a las direcciones IP y luego se reenvían a través del espacio de nombres con el proxy kube. No he realizado pruebas de clúster de enrutadores activo / activo, pero esta configuración me permite mantener la IP externa. Lo menciono FWIW, pero entiendo que no es la "red más directa".

Entiendo que si kube-proxy pudiera administrarlo sería bueno, pero dadas sus necesidades específicas y especialmente el hecho de que el equilibrio de carga ya está fuera de kube-proxy, ¿no tendría sentido codificar un administrador de reglas de iptables de cliente? observando el estado del clúster de Kubernetes y configurando las reglas para DNAT VIP solo para los pods del host en ejecución? Esto también podría ser un modo para kube-proxy, aunque, como ... bueno ... no soy bueno para los nombres ... --proxy-mode = iptables-to-node-pods-only.

Gracias por el informe detallado. Tu solución es interesante y pasé
una buena cantidad de tiempo hoy pensando en ello. Desafortunadamente has
cruzado a un territorio muy específico que no funciona en un sentido genérico.
Las nubes como GCE no pueden usar el modo de puerta de enlace IPVS debido al enrutamiento
la red. Incluso si la puerta de enlace funcionó, no admite la reasignación de puertos,
que hace Kubernetes, por lo que solo se aplica si el puerto de servicio == objetivo
Puerto.

El desafío con el núcleo de kubernetes es encontrar formas de manejar su
tipo de situación genéricamente o para salir de su camino y empoderarlo para
configúrelo usted mismo. Quizás podríamos hacer algo con el modo encap de ipvs,
pero no conozco las implicaciones de rendimiento de esto.

El jueves 14 de enero de 2016 a las 3:37 a.m., qoke [email protected] escribió:

@thockin https://github.com/thockin Disculpas por la larga respuesta, yo
quería cubrir ambos métodos con los que intentamos resolver esto para que otros pudieran
comprender los desafíos que enfrentamos con ambos.

Como antecedentes, nuestra aplicación principal es de muy alto rendimiento.
plataforma de DNS inteligente (es decir, necesita UDP y necesita hacer al menos 100k +
solicitudes / segundos por pod) y su aplicación de soporte en un proxy SNI
que necesita ver la dirección IP real del cliente (esto es un impedimento para mostrar
nosotros). No queríamos utilizar diferentes enfoques de redes para diferentes
aplicaciones, por lo que decidimos estandarizar en un único método de red para
todos, y elegimos usar IPVS por las razones que mencioné anteriormente
(rendimiento / estabilidad / flexibilidad / construcción de propósito SLB), pero podría
probablemente hackear algo juntos usando solo iptables en estas mismas líneas
también. Usamos vxlan (rápido, fácil, funciona entre sitios) pero ambos
Los métodos también deberían funcionar con GRE / VXLAN con OVS o con la Capa 2 estándar
red de host también (asumiendo que sus hosts están todos en la misma red L2).

Distribuimos el tráfico entrante del usuario final utilizando una combinación de anycast y
DNS, según los requisitos de velocidad de conmutación por error o lo que funcione mejor para
el tipo particular de servicio, por lo que tenemos una distribución bastante uniforme de
el tráfico del usuario final que ingresa a nuestros nodos, pero el problema, como señaló,
obtiene una distribución uniforme del tráfico en los grupos de anuncios, independientemente de
ubicación de la cápsula. El otro problema es asegurarse de que los servicios se comuniquen con otros
services tiene carga equilibrada de manera efectiva.

Intentamos dos modelos para abordar esto:

El primer método que probamos fue 2 capas de VIP. VIP externos (1 por
servicio), que distribuyen el tráfico entre los nodos (según el recuento de pods
ese servicio en el nodo), y luego los VIP internos (que se ejecutan en el nodo
con las vainas), que distribuyen la carga dentro de los nodos (normalmente
a través de las vainas). La limitación de este modelo fue que los nodos que se ejecutan externamente
Los VIP necesitaban ejecutar dos espacios de nombres de red diferentes o ejecutar los suyos propios.
nodos físicos. Lo bueno de IPVS en modo DSR (retorno directo del servidor)
modo es que no necesita ver el tráfico de retorno, el tráfico va:

Consumidor >> (sobre L3) >> Nodo VIP externo >> (1) >> Nodo VIP interno >>
(2) >> Contenedor >> (de la forma que desee) >> Consumidor

(1) IPVS (en modo DSR) en el host con un VIP externo elige un _nodo_ para
enviar tráfico a (un "servidor real" en términos de IPVS), y solo cambia DST MAC
dirección del paquete (es decir, el paquete IP llega sin cambios al nodo k8s). Se carga
equilibra los nodos en función de la cantidad de pods que ejecutan ese servicio en
el nodo.
(2) IPVS (también en modo DSR) en el nodo k8s equilibra el tráfico a través de
vainas (a través de las veths hasta el nodo). Las respuestas de los contenedores (TCP y UDP) van
directamente al consumidor del servicio.

La ventaja de este modelo es que fue muy sencillo de poner en marcha y la
El conjunto de reglas fue muy fácil de administrar. La desventaja de este modelo es que
concentra todas nuestras solicitudes de servicio (pero no las respuestas) a través de un
número de nodos que ejecutan las VIP externas. Nos gusta "nada compartido", así que
ingrese la versión 2:

El segundo modelo ahora entretenido es una capa única de VIP con
Configuración más inteligente de IPVS e iptables.

Consumidor >> Cualquier nodo / nodo local >> (1) >> Contenedor >> (de cualquier forma
querer) >> Consumidor
o podría ir a otro nodo:
Consumidor >> Cualquier nodo / nodo local >> (1) >> Nodo remoto >> (2) >> Contenedor

(de la forma que desee) >> Consumidor

(1) El tráfico llega al VIP principal, la carga del tráfico se equilibra en todos los pods de
el racimo.
(2) El tráfico llega a VIP secundario, el tráfico se equilibra la carga solo en todos
vainas locales. Este VIP secundario solo se usa para el tráfico que proviene de
otros hosts en la red (es un FWMARK VIP). Marcamos el tráfico entrante
cualquier interfaz externa con FWMARK = 1234, y eso obliga al tráfico a ir
a un conjunto de reglas diferente, lo que evita bucles entre nodos.

El VIP principal tiene una lista de pods locales y hosts remotos con pods (con
el peso es 100 por cada vaina local y 100 * número de vainas para
nodos remotos). Entonces, por ejemplo, si 3 pods se ejecutan localmente en el nodoA y
hay dos pods ejecutándose en el nodoB, el conjunto de reglas en el nodoA se vería así
esta:

Prot LocalAddress: Indicadores del programador de puertos
-> RemoteAddress: Port Forward Weight ActiveConn InActConn
TCP service.ip.address: 0 rr persistent 360
-> pod1.on.nodeA.ip: 80 Ruta 100 0 0
-> pod2.on.nodeA.ip: 80 Ruta 100 0 0
-> pod2.on.nodeA.ip: 80 Ruta 100 0 0
-> interfazip.of.nodeB: 80 Ruta 200 0 0
FWM 1234 rr
-> pod1.on.nodeA.ip: 80 Ruta 100 0 0
-> pod2.on.nodeA.ip: 80 Ruta 100 0 0
-> pod3.on.nodeA.ip: 80 Ruta 100 0 0

Sin embargo, en el nodo B, la configuración de IPVS se vería un poco diferente porque
solo tiene dos pods locales y tres pods remotos en el nodoA:

Prot LocalAddress: Indicadores del programador de puertos
-> RemoteAddress: Port Forward Weight ActiveConn InActConn
TCP service.ip.address: 0 rr persistent 360
-> pod1.on.nodeB.ip: 80 Ruta 100 0 0
-> pod2.on.nodeB.ip: 80 Ruta 100 0 0
-> interfazip.of.nodeA: 80 Ruta 300 0 0
FWM 1234 rr
-> pod1.on.nodeB.ip: 80 Ruta 100 0 0
-> pod2.on.nodeB.ip: 80 Ruta 100 0 0

Otra forma sería cambiar los FWMARK y usar iptables para
FWMARK cualquier cosa en veth + interfaces (coincidencia de comodines) y tenga el FWMARK
Match solo se utiliza para el equilibrio de carga local.

El resultado final es la red más directa, sin necesidad de centralizar
el procesamiento / enrutamiento de solicitudes se adapta mucho mejor. La desventaja es algo
inteligencia adicional al crear las reglas de IPVS.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -171619663
.

Creo que sería interesante probar un modo iptables-to-node-pods-only ,
pero tiene mucha ondulación. El potencial de desequilibrio es muy real y
al menos el controlador de servicio necesitaría saber cómo programar el
equilibradores de carga externos.

El jueves 14 de enero de 2016 a las 3:59 p.m., Mikaël Cluseau [email protected]
escribió:

Por mi parte, con franela (en modo vxlan) administrando mi red de contenedores,
use kube-proxy (en modo iptables y no enmascarando) + franela en un
espacio de nombres en mis nodos de enrutamiento. Las solicitudes externas son DNATed al servicio
IP y luego reenviadas a través del espacio de nombres con kube-proxy. Yo no he
He realizado pruebas de clúster de enrutadores activos / activos, pero esta configuración me permite mantener
la IP externa. Lo menciono FWIW, pero entiendo que no es el "más
networking directo ".

Entiendo que si kube-proxy pudiera administrarlo sería bueno, pero
dadas sus necesidades específicas y especialmente el hecho de que el equilibrio de carga
ya está fuera de kube-proxy, ¿no tendría sentido codificar un cliente
administrador de reglas de iptables observando el estado del clúster de Kubernetes y configurando
las reglas para DNAT VIP solo para los pods del host en ejecución? Esto podría
también ser un modo para kube-proxy, aunque, como ... bueno ... no soy bueno en
nombres ... --proxy-mode = iptables-to-node-pods-only.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -171821603
.

@thockin ¿ Te refieres a si 2 réplicas están en el mismo nodo, por ejemplo? Creo que podríamos poner el caso de "programar los equilibradores de carga externos" fuera del alcance del proxy kube, ya que tiene varias instancias y un programador externo de LB probablemente debería estar en un modo "maestro único". Por lo tanto, permitir el modo kube-proxy "iptables-to-node-pods-only" es solo el primero de un proceso de 2 pasos.

Creo que podría intentar implementar algo como eso mañana: modo "iptables-to-node-pods-only" en kube-proxy, más un contrib / ip-route-elb que mantendría una tabla de enrutamiento de Linux con una ruta por servicio , con el peso correcto para cada nodo en función de la cantidad de puntos finales que tiene el nodo para un servicio determinado.

@thockin ¿
equilibradores de carga externos "fuera del alcance del proxy kube, ya que tiene varias instancias y un LB externo
El programador probablemente debería estar en modo "maestro único". Por lo tanto, permitir el modo kube-proxy "iptables-to-node-
pods-only "es solo el primero de un proceso de 2 pasos.

"Solo proxy a pods locales" tiene que ser el paso 2 del proceso. Paso 1
tiene que estar cambiando el controlador de servicio para enviar balanceadores de carga solamente
a los nodos que tienen 1 o más backends para un servicio determinado. Ese paso
solo es PROBABLEMENTE razonable, pero requerirá muchas pruebas para
asegúrese de hacerlo bien. Creo que queremos hacer esto eventualmente
de todas formas.

Una vez hecho esto, podemos hablar de hacer que los puertos de nodo prefieran local
backends si es posible, pero este paso requiere mucho más cuidado
pensamiento ... ¿Eso significa _siempre_ (es decir, nunca elegir un control remoto
backend si hay uno local disponible) o probabilístico? Deberiamos hacer
que a través del mismo puerto de nodo (diferentes nodos se pondrán muy
diferentes comportamientos) o asignamos un puerto diferente que se utiliza
si y solo si este nodo tiene 1 o más backends? ¿Cómo manejamos el
problema de desequilibrio?

Creo que podría intentar implementar algo como eso mañana: modo "iptables-to-node-pods-only" en kube-proxy,
más un contrib / ip-route-elb que mantendría una tabla de enrutamiento de Linux con una ruta por servicio, con el peso correcto
para cada nodo en función de cuántos puntos finales tiene el nodo para un servicio determinado.

Si ELB admite pesos, funcionará mejor en algunos aspectos que
GCE, que no lo hace. Eso está bien, simplemente no pensé que fuera compatible
pesos. Sin embargo, no creo que pueda ser una contribución; es una bonita
parte fundamental del sistema.

El 16/01/2016 05:19 AM, Tim Hockin escribió:

"Solo proxy a pods locales" tiene que ser el paso 2 del proceso. Paso 1
tiene que estar cambiando el controlador de servicio para enviar balanceadores de carga solamente
a los nodos que tienen 1 o más backends para un servicio determinado. Ese paso
solo es PROBABLEMENTE razonable, pero requerirá muchas pruebas para
asegúrese de hacerlo bien. Creo que queremos hacer esto eventualmente
de todas formas.

Eso tiene sentido.

Una vez hecho esto, [...]

Así que veamos una vez que esté hecho :-)

Si ELB admite pesos, funcionará mejor en algunos aspectos que
GCE, que no lo hace. Eso está bien, simplemente no pensé que fuera compatible
pesos.

Dado que es del manual y probablemente tenga más de 10 veces mi
experiencia en este tipo de redes, debo ignorar por completo una trampa.
El hombre ip-route dice esto:

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

valor complejo con su propia sintaxis similar a las listas de argumentos de nivel superior:

                          via [ FAMILY ] ADDRESS - is the nexthop 

enrutador.

                          dev NAME - is the output device.

                          weight NUMBER - is a weight for this 

elemento de una ruta multitrayecto que refleja su ancho de banda relativo o su calidad.

Sin embargo, no creo que pueda ser una contribución; es una bonita
parte fundamental del sistema.

Dado que la "E" significa "externo", sentí que podría comenzar allí,
al menos para obtener algo de código para apoyar las ideas.

El viernes 15 de enero de 2016 a las 2:55 p.m., Mikaël Cluseau
[email protected] escribió:

El 16/01/2016 05:19 AM, Tim Hockin escribió:

"Solo proxy a pods locales" tiene que ser el paso 2 del proceso. Paso 1
tiene que estar cambiando el controlador de servicio para enviar balanceadores de carga solamente
a los nodos que tienen 1 o más backends para un servicio determinado. Ese paso
solo es PROBABLEMENTE razonable, pero requerirá muchas pruebas para
asegúrese de hacerlo bien. Creo que queremos hacer esto eventualmente
de todas formas.

Eso tiene sentido.

Hoy pensé más en esto, no creo que sea muy difícil.
Solo medio duro.

Una vez hecho esto, [...]

Así que veamos una vez que esté hecho :-)

bastante bien, solo me gusta saber a dónde va un conjunto de cambios :)

Si ELB admite pesos, funcionará mejor en algunos aspectos que
GCE, que no lo hace. Eso está bien, simplemente no pensé que fuera compatible
pesos.

Dado que es del manual y probablemente tenga más de 10 veces mi
experiencia en este tipo de redes, debo ignorar por completo una trampa.
El hombre ip-route dice esto:

nexthop NEXTHOP
el siguiente salto de una ruta multitrayecto. NEXTHOP es un
valor complejo con su propia sintaxis similar a las listas de argumentos de nivel superior:

a través de [FAMILY] ADDRESS - es el próximo salto
enrutador.

dev NAME: es el dispositivo de salida.

NÚMERO de peso: es un peso para esto.
elemento de una ruta multitrayecto que refleja su ancho de banda relativo o su calidad.

Sin embargo, realmente no usamos la noción de enrutamiento IP de Linux. Ninguno de los
Las implementaciones de LB sé que lo usan, de todos modos. GCE usa la nube de Google
balanceador, que no tiene pesos. No sé si es Amazon ELB
lo hace.

Sin embargo, no creo que pueda ser una contribución; es una bonita
parte fundamental del sistema.

Dado que la "E" significa "externo", sentí que podría comenzar allí,
al menos para obtener algo de código para apoyar las ideas.

Claro, podemos EMPEZAR en contrib :)

Además, si desea continuar con esto, debe abrir 2 errores, algo como:

1) los balanceadores de carga para un servicio solo deben apuntar a nodos que realmente
tener un backend para ese servicio

2) para preservar la IP del cliente en los balanceadores de carga, kube-proxy debería
siempre prefiero el backend local si está presente (xref # 1)

y luego explica la intención y la dirección

El viernes 15 de enero de 2016 a las 5:11 p.m., Tim Hockin [email protected] escribió:

El viernes 15 de enero de 2016 a las 2:55 p.m., Mikaël Cluseau
[email protected] escribió:

El 16/01/2016 05:19 AM, Tim Hockin escribió:

"Solo proxy a pods locales" tiene que ser el paso 2 del proceso. Paso 1
tiene que estar cambiando el controlador de servicio para enviar balanceadores de carga solamente
a los nodos que tienen 1 o más backends para un servicio determinado. Ese paso
solo es PROBABLEMENTE razonable, pero requerirá muchas pruebas para
asegúrese de hacerlo bien. Creo que queremos hacer esto eventualmente
de todas formas.

Eso tiene sentido.

Hoy pensé más en esto, no creo que sea muy difícil.
Solo medio duro.

Una vez hecho esto, [...]

Así que veamos una vez que esté hecho :-)

bastante bien, solo me gusta saber a dónde va un conjunto de cambios :)

Si ELB admite pesos, funcionará mejor en algunos aspectos que
GCE, que no lo hace. Eso está bien, simplemente no pensé que fuera compatible
pesos.

Dado que es del manual y probablemente tenga más de 10 veces mi
experiencia en este tipo de redes, debo ignorar por completo una trampa.
El hombre ip-route dice esto:

nexthop NEXTHOP
el siguiente salto de una ruta multitrayecto. NEXTHOP es un
valor complejo con su propia sintaxis similar a las listas de argumentos de nivel superior:

a través de [FAMILY] ADDRESS - es el próximo salto
enrutador.

dev NAME: es el dispositivo de salida.

NÚMERO de peso: es un peso para esto.
elemento de una ruta multitrayecto que refleja su ancho de banda relativo o su calidad.

Sin embargo, realmente no usamos la noción de enrutamiento IP de Linux. Ninguno de los
Las implementaciones de LB sé que lo usan, de todos modos. GCE usa la nube de Google
balanceador, que no tiene pesos. No sé si es Amazon ELB
lo hace.

Sin embargo, no creo que pueda ser una contribución; es una bonita
parte fundamental del sistema.

Dado que la "E" significa "externo", sentí que podría comenzar allí,
al menos para obtener algo de código para apoyar las ideas.

Claro, podemos EMPEZAR en contrib :)

El riesgo de un RP sin documentos es que va en la dirección equivocada. Está
mucho más fácil revisar algo como una propuesta. Voy a echar un vistazo a tu
PR cuando tenga la oportunidad, pronto espero.
El 15 de enero de 2016 a las 7:02 p.m., "Mikaël Cluseau" [email protected] escribió:

¿Está bien abrir una solicitud de extracción para (1) directamente con este nombre y algunos
explicaciones?

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172149777
.

Desafortunadamente, ha cruzado a un territorio muy específico que no funciona en un sentido genérico.
Las nubes como GCE no pueden usar el modo de puerta de enlace IPVS debido a la red enrutada. Incluso si la puerta de enlace funcionó, no admite la reasignación de puertos, lo que hace Kubernetes, por lo que solo se aplica si el puerto de servicio == puerto de destino.

En el lado de la puerta de enlace, esto funciona bien en una red de Capa 3 (usamos una superposición), y aunque podríamos habernos salido sin una red superpuesta, la construimos de esta manera porque queríamos que el enfoque que usamos fuera portátil y funcionara en nubes de terceros (como GCE).

Corregir la limitación con el modo DSR es que el puerto de servicio == puerto de destino, pero esto no es realmente un problema a menos que tenga dos aplicaciones _ en el mismo contenedor_ que deben ejecutarse en el mismo puerto (pasamos mucho tiempo pensando en esto, y asumiendo la directriz "1 aplicación por contenedor", no pudimos encontrar un solo caso de uso para esto). Tenemos muchos contenedores que se ejecutan en los mismos nodos con servicios dentro de ellos, todos en los mismos puertos, y todos tienen una carga equilibrada. Si usted _realmente_ necesita reasignar puertos (aunque me gusta entender las razones reales por las cuales), puede usar el modo IPVS NAT en lugar del modo "RUTA".

El desafío con el núcleo de kubernetes es encontrar formas de manejar su tipo de situación de manera genérica o salir de su camino y capacitarlo para configurarlo usted mismo. Tal vez podríamos hacer algo con el modo encap de ipvs, pero no conozco las implicaciones de rendimiento de esto.

Lo que hemos hecho es tan genérico como podríamos hacerlo (funciona aquí, funciona en Amazon y estoy seguro de que funcionará en GCE cuando tengamos la necesidad de expandirnos), con la única limitación con DSR es que la aplicación La ejecución en el pod / contenedor debe ejecutarse en el mismo puerto que el servicio, lo que, después de mucha discusión interna, nadie ha podido encontrar un escenario en el que esto sea limitante desde la perspectiva de la pila de aplicaciones E2E.

Dicho esto, si elimina DSR (modo de ruta IPVS) de la ecuación y usa el "modo NAT" de IPVS, los puertos se pueden reasignar y aún obtiene el beneficio de obtener características / rendimiento / etc. de IPVS. El único inconveniente es que NAT agrega algunos impuestos sobre el rendimiento, pero (a) es compatible con UDP y (b) sigue siendo increíblemente rápido en comparación con una solución de espacio de usuario.

@brendandburns @thockin Anteriormente en el hilo solicitó algunos números de rendimiento. No llamaría a esto el conjunto de pruebas más completo, pero espero que HTTP sea una de las cargas de trabajo más comunes en los contenedores, por lo que aquí hay algunos números de apache-bench como punto de partida:

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

DNAT se habilitó en IPVS para una comparación justa con las otras dos soluciones (esto también significa que el puerto de servicio puede ser diferente al puerto de servicio de destino). Nuestras cargas de trabajo pueden parecer un poco inusuales para algunos, pero nuestros objetivos de rendimiento probablemente no sean muy diferentes a los de otros (es decir, exprima el hardware para todo lo que pueda obtener).

¡Gracias!

No estoy seguro de dónde viene la idea de que kube-proxy no hace UDP:
absolutamente lo hace, aunque tal vez no perfectamente (sin una conexión viene
hasta los tiempos de espera).

También vale la pena aclarar iptables (nuevo) kube-proxy frente al espacio de usuario
modo (heredado).

El sábado 16 de enero de 2016 a las 9:45 p.m., qoke [email protected] escribió:

@thockin https://github.com/thockin Anteriormente en el hilo que solicitó
algunos números de rendimiento. No llamaría a este el conjunto más completo
de pruebas, pero espero que HTTP sea una de las cargas de trabajo más comunes en
contenedores, así que aquí hay algunos números de apache-bench como punto de partida:

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

DNAT se habilitó en IPVS para una comparación justa con las otras dos soluciones
(esto también significa que el puerto de servicio puede ser diferente al puerto de servicio de destino). Nuestro
Las cargas de trabajo pueden parecer un poco inusuales para algunos, pero nuestros objetivos de rendimiento
probablemente no sean diferentes a los demás (es decir, exprimir el hardware para todos
puedes obtener).

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172293881
.

Buena decisión sobre el modo nuevo vs heredado: anotado y actualizado.

También en el lado de UDP, gracias por la aclaración; No sabía que UDP era totalmente compatible con kube-proxy hasta ahora. Cuando probamos por primera vez kube-proxy con UDP, obtuvimos muchos bloqueos. No estoy seguro de por qué, pero aumentamos los tiempos de espera y aún tuvimos problemas. Teníamos que encontrar una solución rápidamente, así que terminamos trabajando con IPVS en lugar de depurarlo. En ese momento, solo funcionaba para cargas de trabajo de paquetes por segundo bastante bajas (menos de 1k pps), pero no lo hemos vuelto a probar recientemente.

El principal problema con iptables y cualquier servicio UDP de alta velocidad es el llenado de las tablas de netfilter conntrack. Incluso si aumenta el tamaño de la conntrack a 1 millón, algunos DDoS de usuario final infectados con malware intentan usarlo para un ataque de amplificación de DNS y luego su tabla de conntrack simplemente se llena de nuevo. En términos generales, la mejor práctica para los servidores DNS (o cualquier servicio UDP de alta velocidad) es deshabilitar conntrack (usando -j NOTRACK en la tabla sin procesar), y si deshabilita conntrack, iptables NAT y las cosas con estado (-m estado) se interrumpen.

Aparte del repositorio GIT, ¿cuál sería el mejor lugar para buscar antes de intentar crear un módulo / paquete "k8s.io/kubernetes/pkg/proxy/ipvs"? ¿O es mejor dejarlo en manos de alguien que conozca mejor el código base?

Además, si desea que se ejecuten puntos de referencia específicos, hágamelo saber y veré qué puedo hacer.

El 17/01/2016 08:50 PM, qoke escribió:

Aparte del repositorio de GIT, ¿cuál sería el mejor lugar para buscar antes?
intentando crear un módulo / paquete "k8s.io/kubernetes/pkg/proxy/ipvs"?

Creo que también puedes empezar con contrib.

FWIW ... Usé listas de relojes y tiendas undelta para hacer una
binay reaccionando al estado del clúster en
https://github.com/kubernetes/kubernetes/pull/19755. Si la informacion
en
https://github.com/kubernetes/kubernetes/pull/19755/files#diff -0becc97ac222c3f2838fbfe8446d5375R26
es suficiente, solo debería tener que cambiar la llamada unas pocas líneas a continuación
(https://github.com/kubernetes/kubernetes/pull/19755/files#diff-0becc97ac222c3f2838fbfe8446d5375R44).

Tenga en cuenta que solo soy compatible con los servicios clusterIP en esta PoC.

Desafortunadamente, ha cruzado a un territorio muy específico que no funciona en un sentido genérico.
Las nubes como GCE no pueden usar el modo de puerta de enlace IPVS debido a la red enrutada. Incluso si la puerta de enlace funcionó, no
admite la reasignación de puertos, lo que hace Kubernetes, por lo que solo se aplica si el puerto de servicio == puerto de destino.

En el lado de la puerta de enlace, esto funciona bien en una red de Capa 3 (usamos una superposición), y aunque podríamos habernos escapado
sin una red superpuesta, lo construimos de esta manera porque queríamos que el enfoque que usamos fuera portátil y funcionara en terceros
nubes (como GCE).

No estoy seguro de cómo puede funcionar. Las rutas estáticas a nivel de máquina no funcionan
en GCE. Tal vez me falte alguna técnica que hayas aplicado. I
admito libremente que NO soy un experto en esto :)

La limitación correcta es que el puerto de servicio == puerto de destino, pero esto no es realmente un problema a menos que tenga dos aplicaciones en el
mismo contenedor que debe ejecutarse en el mismo puerto (pasamos mucho tiempo pensando en esto y asumiendo que "1 aplicación
por contenedor ", no pudimos encontrar un solo caso de uso para esto). Tenemos muchos contenedores que se ejecutan en los mismos nodos
con servicios dentro de ellos, todos en los mismos puertos, y todos con carga equilibrada bien. En resumen, el enfoque que usamos no te detiene
de ejecutar varios servicios en los mismos puertos en el mismo nodo.

También se aplica si tiene backends que están cambiando de versión (p. Ej.
transición entre etcd1 y etcd2) o cualquier otra situación en la que
el puerto de backend solo necesita ser diferente. El problema es ese
Kubernetes permite que se exprese, por lo que debemos asegurarnos de que las personas
realmente puede usarlo (o de lo contrario desaprobarlo y EOL la característica que
parece poco probable).

El desafío con el núcleo de kubernetes es encontrar formas de manejar su tipo de situación de manera genérica o salir de su camino
y le permitirá configurarlo usted mismo. Tal vez podríamos hacer algo con el modo encap ipvs, pero no sé el perf
implicaciones de la misma.

Lo que hemos hecho es tan genérico como podríamos hacerlo (funciona aquí, funciona en Amazon y estoy seguro de que funcionará en
GCE cuando tenemos la necesidad de expandir), con la única limitación de que la aplicación que se ejecuta en el pod / contenedor necesita> ejecutarse en el mismo puerto que el servicio, que después de mucha discusión interna, nadie ha podido encontrar un escenario donde
esto sería una limitación desde la perspectiva de la pila de aplicaciones E2E.

Realmente quiero entender cómo. ¿Tienes algo más paso a paso?

También en el lado de UDP, gracias por la aclaración; No sabía que UDP era totalmente compatible con kube-proxy hasta ahora.
Cuando probamos por primera vez kube-proxy con UDP, obtuvimos muchos bloqueos. No estoy seguro de por qué, pero aumentamos los tiempos de espera y
todavía tenía problemas. Teníamos que encontrar una solución rápidamente, así que terminamos trabajando con IPVS en lugar de depurarlo. En el
vez, solo funcionó para cargas de trabajo de paquetes por segundo bastante bajas (menos de 1k pps), pero no hemos vuelto a probar recientemente.

El principal problema con iptables y cualquier servicio UDP de alta velocidad es el llenado de las tablas de netfilter conntrack. Incluso si aumenta el
Conntrack tamaño a 1 millón, luego algunos DDoS de usuario final infectados con malware usted o intenta usarlo para una amplificación de DNS
attack y luego su mesa de conntrack simplemente se llena de nuevo. En términos generales, las mejores prácticas para servidores DNS (o cualquier
Servicios UDP) es deshabilitar conntrack (usando -j NOTRACK en la tabla sin formato), y si deshabilita conntrack, iptables NAT y
el material con estado (-m estado) se rompe.

Sí, NAT para UDP es realmente desafortunado. Encontrar un no conntrack
La solución sería genial, pero tiene que aplicarse a todos
entornos o ser parametrizado por plataforma (lo cual es difícil en sí mismo
camino).

Aparte del repositorio de GIT, ¿cuál sería el mejor lugar para buscar antes de intentar crear un
¿Módulo / paquete "k8s.io/kubernetes/pkg/proxy/ipvs"? ¿O es mejor dejarlo en manos de alguien que conozca mejor el código base?

Abrí un problema de github sobre IPVS, pero estaba usando masquerade (NAT)
modo porque no pude hacerlo funcionar en GCE sin (y debido a
la función de reasignación de puertos). Si la reasignación de puertos desencadenaba una
modo de equilibrio, probablemente podría vivir con eso y simplemente documentarlo
como tal.

Deberíamos mover este convo allí, se perderá aquí.

El 18/01/2016 12:34 PM, Tim Hockin escribió:

Sí, NAT para UDP es realmente desafortunado. Encontrar un no conntrack
La solución sería genial, pero tiene que aplicarse a todos
entornos o ser parametrizado por plataforma (lo cual es difícil en sí mismo
camino).

¿Podría la NAT sin estado funcionar para el caso en el que una pareja (pod, puerto) tiene en
la mayoría de un servicio (muchos pods en un servicio)?

Esto se vería así:

{from: clientIP: clientPort, to: externalIP: externalPort} --- [el proxy selecciona un pod aleatorio] ---> {from: clientIP: clientPort, to: podIP: targetPort} ---> [enrutado a través del host correcto ...]

En el camino de regreso, el firewall tendrá una regla que diga un paquete {de:
podIP: targetPort , to: any} debe ser SNATed a {from:
e xternalIP: externalPort , to: sin cambios}.

Para expresarlo en el dialecto de 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

No veo dónde no funciona esto cuando el paquete viene de afuera
el racimo.

La forma en que se expresan los Servicios en Kubernetes permite que un solo pod sea
enfrentado por cualquier número de Servicios, por lo que esto se rompe, no sabemos qué
a SNAT a.

El domingo 17 de enero de 2016 a las 6:13 p.m., Mikaël Cluseau [email protected]
escribió:

El 18/01/2016 12:34 PM, Tim Hockin escribió:

Sí, NAT para UDP es realmente desafortunado. Encontrar un no conntrack
La solución sería genial, pero tiene que aplicarse a todos
entornos o ser parametrizado por plataforma (lo cual es difícil en sí mismo
camino).

¿Podría la NAT sin estado funcionar para el caso en el que una pareja (pod, puerto) tiene en
la mayoría de un servicio (muchos pods en un servicio)?

Esto se vería así:

{from: clientIP: clientPort, to: externalIP: externalPort} --- [el proxy selecciona
un pod aleatorio] ---> {desde: clientIP: clientPort, hasta: podIP: targetPort} --->
[enrutado a través del host correcto ...]

En el camino de regreso, el firewall tendrá una regla que diga un paquete {de:
podIP: targetPort , to: any} debe ser SNATed a {from:
e xternalIP: externalPort , to: sin cambios}.

Para expresarlo en el dialecto de 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

No veo dónde no funciona esto cuando el paquete viene de afuera
el racimo.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172408290
.

El 18/01/2016 03:31 PM, Tim Hockin escribió:

La forma en que se expresan los servicios en Kubernetes permite que un solo pod
ser
enfrentado por cualquier número de Servicios, por lo que esto se rompe, no sabemos
qué
a SNAT a.

Es por eso que limité el caso a varios a uno (mi primera oración :-)).
Solo estoy tratando de trazar una línea alrededor de lo que se puede hacer o no.

Claro, tengo el desafortunado trabajo de señalar por qué no es un
solución bastante general :(

El domingo 17 de enero de 2016 a las 8:34 p.m., Mikaël Cluseau [email protected]
escribió:

El 18/01/2016 03:31 PM, Tim Hockin escribió:

La forma en que se expresan los servicios en Kubernetes permite que un solo pod
ser
enfrentado por cualquier número de Servicios, por lo que esto se rompe, no sabemos
qué
a SNAT a.

Es por eso que limité el caso a varios a uno (mi primera oración :-)).
Solo estoy tratando de trazar una línea alrededor de lo que se puede hacer o no.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172421828
.

El 18/01/2016 03:46 PM, Tim Hockin escribió:

Claro, tengo el desafortunado trabajo de señalar por qué no es un
solución bastante general :(

Sí ... pero es una pregunta frecuente. También podríamos poner, en algún lugar, "si len (servicios)
== 1 {implementar sin estado} else {implementar con estado} ". Pero esto puede
parece un desastre para los novatos. También podría ser un contrib / elbs / algo ...

Ni siquiera es algo que rastreamos actualmente (la cantidad de servicios que
frente a una vaina determinada). Podríamos, supongo. No estoy en contra de eso (incluso si
parece un nicho). Parece un cambio sustancial para tener tan
muchas advertencias. Me gustaría pensar en mejores respuestas, todavía.

El domingo 17 de enero de 2016 a las 8:51 p.m., Mikaël Cluseau [email protected]
escribió:

El 18/01/2016 03:46 PM, Tim Hockin escribió:

Claro, tengo el desafortunado trabajo de señalar por qué no es un
solución bastante general :(

Sí ... pero es una pregunta frecuente. También podríamos poner, en algún lugar, "si len (servicios)
== 1 {implementar sin estado} else {implementar con estado} ". Pero esto puede
parece un desastre para los novatos. Yo también podría ser un
contrib / elbs / algo ...

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172425404
.

El 18/01/2016 04:07 PM, Tim Hockin escribió:

Ni siquiera es algo que rastreamos actualmente (la cantidad de servicios que
frente a una vaina determinada). Podríamos, supongo. No estoy en contra de eso (incluso si
parece un nicho). Parece un cambio sustancial para tener tan
muchas advertencias. Me gustaría pensar en mejores respuestas, todavía.

Estoy de acuerdo, pero no tengo una idea mejor por ahora :-(

Incluso una SDN especialmente diseñada necesitaría rastrear algo, supongo. Quizás
soluciones basadas en etiquetas como MPLS ..?

El 18/01/2016 04:18 PM, Mikaël Cluseau escribió:

Incluso una SDN especialmente diseñada necesitaría rastrear algo, supongo.
¿Quizás soluciones basadas en etiquetas como MPLS ..?

En la idea de etiquetar cosas ... si asignamos una IP por servicio + una
IP por punto final (servicio + par de pod) y agregue estas IP de punto final al
pods, debería funcionar completamente sin estado:

`` `` ``

  • Externo al host: {desde: clientIP: clientPort, to: externalIP: servicePort} ----- [ELB
    selecciona un punto final] --------> {desde: clientIP: clientPort, hasta:
    endpointServiceIP: podPort} -> ruta al host
  • Host a pod: {desde: clientIP: clientPort, to: endpointServiceIP: podPort} - [estándar
    enrutamiento a contenedores] -> {desde: clientIP: clientPort , hasta:
    punto final ServiceIP: podPort }

  • Pod al host: {desde: endpointServiceIP: podPort, a: clientIP: clientPort}
    -------- [enrutamiento estándar a enrutadores] -----> {desde:
    endpointServiceIP: podPort, a: clientIP: clientPort} - Host a externo: {desde: endpointServiceIP: podPort, a: clientIP: clientPort} -------- [ELB
    SNAT atrás] ------------------> {desde: clientIP: clientPort , a:
    e xternalIP: servicePort } `` `

Piensa que también podemos hacer que esto funcione para clusterIP.
`` `` ``

No puedo hacer que esto funcione en GCE, y no estoy seguro acerca de AWS; hay un
número limitado de rutas estáticas disponibles.

Me pregunto si podría hacerlo al combinar 2 rangos de IP en un solo
ruta. Es una gran cantidad de IP para gastar, pero supongo que solo importa para UDP.
Tendré que probarlo.

Editar: lo probé y no pude hacerlo funcionar, pero me falta algo.
Tendremos que agregar / eliminar direcciones IP en contenedores en respuesta a los servicios que vienen
y en marcha, pero no pude hacer que las direcciones IP "adicionales" en un contenedor funcionaran (podría
ping pero no TCP o UDP, no estoy seguro de por qué).

Tendré que intentarlo de nuevo en algún momento.

El domingo 17 de enero de 2016 a las 10:22 p.m., Mikaël Cluseau [email protected]
escribió:

El 18/01/2016 04:18 PM, Mikaël Cluseau escribió:

Incluso una SDN especialmente diseñada necesitaría rastrear algo, supongo.
¿Quizás soluciones basadas en etiquetas como MPLS ..?

En la idea de etiquetar cosas ... si asignamos una IP por servicio + una
IP por punto final (servicio + par de pod) y agregue estas IP de punto final al
pods, debería funcionar completamente sin estado:

`` `` ``

  • Externo al host: {de: clientIP: clientPort, a: externalIP: servicePort}
    ----- [ELB
    selecciona un punto final] --------> {desde: clientIP: clientPort, hasta:
    endpointServiceIP: podPort} -> ruta al host
  • Host a pod: {de: clientIP: clientPort, a: endpointServiceIP: podPort}
    --[estándar
    enrutamiento a contenedores] -> {desde: clientIP: clientPort , hasta:
    punto final ServiceIP: podPort }

  • Pod al host: {desde: endpointServiceIP: podPort, a: clientIP: clientPort}
    -------- [enrutamiento estándar a enrutadores] -----> {desde:
    endpointServiceIP: podPort, to: clientIP: clientPort} - Host a
    externo: {desde: endpointServiceIP: podPort, a: clientIP: clientPort}
    -------- [ELB
    SNAT atrás] ------------------> {desde: clientIP: clientPort , a:
    e xternalIP: servicePort } `` `

Piensa que también podemos hacer que esto funcione para clusterIP.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-172438133
.

`` `` ``

Estoy tratando de mi lado para obtener algo (con redes puras en mi host local
por ahora).

Estoy intentando un enfoque en el que afecto los rangos de IP de servicio a los hosts para
reducir el número de entradas de enrutamiento:

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)

Sin ping ATM (paquetes que no pasan por la cadena PREROUTING ...), y
necesito dormir. Más sobre esto mañana;)

El 18/01/2016 06:28 PM, Tim Hockin escribió:

No puedo hacer que esto funcione en GCE, y no estoy seguro acerca de AWS; hay un
número limitado de rutas estáticas disponibles.

Me pregunto si podría hacerlo al combinar 2 rangos de IP en un solo
ruta. Es una gran cantidad de IP para gastar, pero supongo que solo importa para UDP.
Tendré que probarlo.

Editar: lo probé y no pude hacerlo funcionar, pero me falta algo.
Tendremos que agregar / eliminar direcciones IP en contenedores en respuesta a los servicios que vienen
y en marcha, pero no pude hacer que las direcciones IP "adicionales" en un contenedor funcionaran (podría
ping pero no TCP o UDP, no estoy seguro de por qué).

Tendré que intentarlo de nuevo en algún momento.

Llegué un poco más lejos, pero sucedió algo que debería haber predicho.

Configuré un pod con 10.244.2.8/25 como interfaz principal y 10.244.2.250/25
como su interfaz "en un servicio". Esperaba poder enviar UDP a
.250 y detectar respuestas, para SNAT. Pero claro, si el cliente es
no en el mismo / 25 (que no puede ser) se activa la ruta por defecto, que
proviene de la dirección .8. tcpdump confirma que las respuestas provienen de .8
al usar UDP.

Estoy de nuevo en un lugar donde no estoy seguro de cómo hacer que funcione. pensaré
más sobre eso.

El lunes 18 de enero de 2016 a las 2:59 a. M., Mikaël Cluseau [email protected]
escribió:

Estoy tratando de mi lado para obtener algo (con redes puras en mi host local
por ahora).

Estoy intentando un enfoque en el que afecto los rangos de IP de servicio a los hosts para
reducir el número de entradas de enrutamiento:

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)

Sin ping ATM (paquetes que no pasan por la cadena PREROUTING ...), y
necesito dormir. Más sobre esto mañana;)

El 18/01/2016 06:28 PM, Tim Hockin escribió:

No puedo hacer que esto funcione en GCE, y no estoy seguro acerca de AWS; hay un
número limitado de rutas estáticas disponibles.

Me pregunto si podría lograrlo colocando 2 rangos de IP juntos en un
soltero
ruta. Es una gran cantidad de IP para gastar, pero supongo que solo importa para UDP.
Tendré que probarlo.

Editar: lo probé y no pude hacerlo funcionar, pero me falta
alguna cosa.
Tendremos que agregar / eliminar direcciones IP en contenedores en respuesta a los servicios que vienen
y en marcha, pero no pude hacer que las direcciones IP "adicionales" en un contenedor funcionaran (podría
ping pero no TCP o UDP, no estoy seguro de por qué).

Tendré que intentarlo de nuevo en algún momento.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172497456
.

Me doy cuenta (a través de Abhishek) que incluso si esto funciona, TODAVÍA tenemos que
la pista fluye en alguna parte, por lo que no es apátrida al final de todos modos.

El lunes 18 de enero de 2016 a las 9:50 p.m., Tim Hockin [email protected] escribió:

Llegué un poco más lejos, pero sucedió algo que debería haber predicho.

Configuré un pod con 10.244.2.8/25 como interfaz principal y
10.244.2.250/25 como su interfaz "en un servicio". Estaba esperando que yo
podría enviar UDP a .250 y detectar respuestas para SNAT. Pero por supuesto,
si el cliente no está en el mismo / 25 (que no puede ser) el predeterminado
se activa la ruta, que proviene de la dirección .8. tcpdump confirma que
las respuestas provienen de .8 cuando se usa UDP.

Estoy de nuevo en un lugar donde no estoy seguro de cómo hacer que funcione. pensaré
más sobre eso.

El lunes 18 de enero de 2016 a las 2:59 a. M., Mikaël Cluseau [email protected]
escribió:

Estoy tratando de mi lado para obtener algo (con redes puras en mi host local
por ahora).

Estoy intentando un enfoque en el que afecto los rangos de IP de servicio a los hosts para
reducir el número de entradas de enrutamiento:

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)

Sin ping ATM (paquetes que no pasan por la cadena PREROUTING ...), y
necesito dormir. Más sobre esto mañana;)

El 18/01/2016 06:28 PM, Tim Hockin escribió:

No puedo hacer que esto funcione en GCE, y no estoy seguro acerca de AWS; hay un
número limitado de rutas estáticas disponibles.

Me pregunto si podría lograrlo colocando 2 rangos de IP juntos en un
soltero
ruta. Es una gran cantidad de IP para gastar, pero supongo que solo importa para UDP.
Tendré que probarlo.

Editar: lo probé y no pude hacerlo funcionar, pero me falta
alguna cosa.
Tendremos que agregar / eliminar direcciones IP en contenedores en respuesta a los servicios
próximo
y en marcha, pero no pude hacer que las direcciones IP "adicionales" en un contenedor funcionaran
podría
ping pero no TCP o UDP, no estoy seguro de por qué).

Tendré que intentarlo de nuevo en algún momento.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172497456
.

Eso es lamentable :-( por cierto, no estoy seguro de por qué. Entonces intentaré algo con MPLS, quiero aprenderlo de todos modos.

Si tiene 2 backends para Service y desea enviar más de un
paquete, necesita realizar un seguimiento de los flujos de alguna manera, ¿no es así? O eres tu
asumiendo que es seguro rociar paquetes en diferentes backends?

El miércoles 20 de enero de 2016 a las 12:24 p.m., Mikaël Cluseau [email protected]
escribió:

Eso es lamentable :-( por cierto, no estoy seguro de por qué. Intentaré algo con
MPLS entonces, quiero aprenderlo de todos modos.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -173348973
.

Supuse que para cargas de trabajo UDP, sí. También puede ser opcional volverse sin estado incluso para UDP. @qoke ¿ algún comentario sobre esto?

Además, podríamos usar cosas como el hash de la IP del cliente para hacer que el flujo sea más estable mientras aún está equilibrado (no sé si podemos llamar a eso "algún tipo de seguimiento" :-)).

@MikaelCluseau usamos el comportamiento IPVS predeterminado, que hace una "adherencia" UDP muy liviana ...

Para programar datagramas UDP, el balanceador de carga IPVS registra la programación de datagramas UDP con tiempo de espera configurable, y el tiempo de espera UDP predeterminado es de 300 segundos. Antes de que se agote el tiempo de espera de la conexión UDP, todos los datagramas UDP del mismo socket (protocolo, dirección IP y puerto) se dirigirán al mismo servidor.

- Citado de http://kb.linuxvirtualserver.org/wiki/IPVS

Por supuesto, esto solo funciona si tiene muchos clientes hablando con un solo servicio, o un solo cliente con diferentes puertos de origen. Si tiene un solo cliente de alto volumen, todo el tráfico que envía desde el mismo puerto de origen, y desea equilibrar la carga en varios backends, entonces puede preferir utilizar un enfoque sin estado / rociar y rezar.

Equilibramos la carga de una gran cantidad de tráfico de DNS y RADIUS: el DNS generalmente se ubica en la primera categoría (muchos clientes o clientes con muchos puertos de origen), y RADIUS generalmente se ubica en la categoría posterior (pocos clientes, muchos paquetes, todos de la misma IP / puerto). En lugar de usar un hash sin estado para RADIUS, decidimos aleatorizar los puertos de origen para obtener una distribución uniforme.

Después de leer todo el hilo, todavía no puedo averiguar si la activación del modo iptables para kube-proxy debería solucionar el problema de que las direcciones IP externas están ocultas (# 10921) o no. Activamos el modo iptables con v1.1 como se sugiere aquí, pero todavía estamos viendo las IP del clúster, no las reales de los usuarios.

Nuestro clúster está en GCE y solo necesitamos un equilibrador de carga con soporte HTTPS antes de comenzar. Como GCE no es compatible con v.1.2 alpha, no podemos usar el nuevo Ingress (que AFAIK admite HTTPS Load Balancers), por lo que el Network Load Balancer es nuestra única opción. Pero obviamente no podemos poner en marcha sin la capacidad de registrar ips reales de nuestros usuarios.

Se agradecería alguna aclaración para los nuevos usuarios al respecto. La compatibilidad con HTTPS es obligatoria para muchos de nosotros. ¡Gracias!

He estado usando el proxy iptables de forma intermitente durante bastante tiempo y puedo confirmar que las IP externas de los clientes todavía están ocultas / muestran las IP del clúster.

Hemos solucionado esto hasta ahora ejecutando nuestro proxy HTTP / HTTPS frontend ejecutándose en modo de red de host para que vea la dirección IP de origen.

@maclof gracias por los comentarios. ¿Podría compartir más información sobre su solución? ¿Qué quiere decir con su HTTP / HTTPS ejecutándose en la red de host?

@javiercr usamos una especificación de pod similar a esta: http://pastie.org/private/zpdelblsob654zif7xus5g

El uso de la red de host significa que el pod se ejecuta en la red de las máquinas host, en lugar de que se le asigne una IP de clúster.

Eso significa que cuando nuestro servidor nginx se une al puerto 80/443, escuchará en una IP de host y verá las direcciones IP de origen.

Estoy usando kubernetes 1.1, /opt/bin/kube-proxy ... --proxy-mode=iptables --masquerade-all=false y enrutando la red IP del cluser a través de un host que tiene un proxy kube. En esta configuración, mis servicios ven la IP externa. Utilizo un espacio de nombres de red de alta disponibilidad que tiene una IP externa y una ruta a los hosts:

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

¡He aprendido mucho leyendo este hilo!

Para su información, este documento establece que AWS ELB utiliza round-robin para conexiones TCP y menos conexiones para http / https: http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/how-elb-works.html# solicitud -enrutamiento

Estoy de acuerdo en que centrarse en obtener solicitudes solo para los nodos que ejecutan pods y tratar de servir pods locales es la mejor manera de hacerlo. El buen beneficio secundario de esto es que habrá menos tráfico de nodo a nodo dentro del clúster y supongo que una mejora de la latencia al atender siempre las solicitudes locales del servicio al pod (lo que supongo que es aún más beneficioso si tiene nodos en múltiples zonas de disponibilidad en el mismo clúster).

En términos de trabajar con un equilibrador de carga que no admite la ponderación, entonces puede resolver esto con su controlador de replicación tratando de mantener siempre la misma cantidad de pods en un nodo (si hay más de 1 por nodo) y luego distribuir uniformemente entre ellos, incluso si esto significa tener que mover pods fuera de un nodo en ciertas situaciones y permitir solo ciertos recuentos de réplicas. Por ejemplo, para un clúster de 4 nodos con un servicio conectado a un equilibrador de carga, la única cantidad de réplicas de pod aceptables sería 1,2,3,4,6,8,9,12,16,20, etc.

También buscamos resolver si el tráfico se dirige solo a los pods locales. Estaría bien con el puerto de nodo desapareciendo en un nodo en momentos en que no hay pods presentes localmente para un servicio. De esta manera, una simple verificación de estado de TCP del equilibrador de carga evitaría que las solicitudes vayan a esos nodos. Creo que si al menos podemos resolver la parte iptables \ kube-proxy de esto, descubriremos cuáles son las implicaciones del equilibrio de carga cuando los pods no están equilibrados en todo el clúster. Creo que hay formas de resolver eso en los balanceadores de carga sin tener que establecer un peso para cada nodo con una llamada a la API.

Los equilibradores de carga ya se ocupan de esto utilizando otros métodos dinámicos. Además, dependiendo de lo que esté haciendo el servicio que está ejecutando dentro de ese contenedor para cada llamada de API, es posible que no pueda admitir el doble del tráfico cuando hay 2 pods en un nodo frente a uno de todos modos. Si se establecen los límites de Kubernetes y si se acercan los niveles máximos de uso en un podnode, esto también podría influir, lo que agrega otra capa de complejidad para tratar de encontrar la configuración de peso correcta en el equilibrador de carga externo.

Yo diría que se mantenga alejado de ese nivel de complejidad y no intente establecer el peso del equilibrador de carga de kubernetes.

@yoshiwaan ¿Puedo sugerir que se abra un nuevo problema para la sugerencia de tráfico entre nodos, ya que este problema ya está cerrado? Personalmente, creo que un buen primer paso sería asegurarse de que _si_ se está ejecutando un pod en el nodo local, que lo diremos al pod local. Sospecho que esto será suficiente, porque luego puede escalar su RC para que haya pods en cada nodo.

@justinsb +1, también nos encontramos con un problema ahora en el que necesitamos ver las direcciones IP de los clientes y es básicamente imposible con la configuración actual.

Esto podría ser demasiado ingenuo, pero me preguntaba cuál es la diferencia entre el modo de espacio de usuario e iptables. Realmente no puedo decirlo por el documento del usuario .

El modo Userland significa que kube-proxy maneja las conexiones en sí mismo al recibir la solicitud de conexión del cliente y abrir un socket al servidor, que (1) consume mucha más CPU y memoria y (2) está limitado a la cantidad de puertos que una sola lata abierto (<65k). El modo iptables funciona en un nivel inferior, en el kernel, y en su lugar utiliza el seguimiento de conexiones, por lo que es mucho más ligero y maneja muchas más conexiones *.

(editar) (*) Siempre que no pase los paquetes SNAT, lo que a su vez requiere una configuración en la que esté seguro de que los paquetes cruzarán las reglas de seguimiento de la conexión asociadas con ellos. Por ejemplo, el uso de un diseño de acceso enrutado le permite evitar SNAT, lo que significa que el punto final del servicio verá la IP real del cliente.

@MikaelCluseau
lo que significa que kube-proxy solo es responsable de configurar y mantener las reglas de iptables y ya no obtenemos un puerto local aleatorio para cada servicio en el modo iptables, ¿verdad?

El 19/04/2016 10:51 PM, Emma escribió:

lo que significa que kube-proxy solo es responsable de configurar y mantener
iptables y ya no obtenemos un puerto local aleatorio para cada servicio en
modo iptables, ¿verdad?

Si.

Lo siento, pero me perdí esto antes.

(editar) (*) Siempre que no pase los paquetes SNAT, lo que a su vez requiere una configuración en la que esté seguro de que los paquetes cruzarán las reglas de seguimiento de la conexión asociadas con ellos. Por ejemplo, el uso de un diseño de acceso enrutado le permite evitar SNAT, lo que significa que el punto final del servicio verá la IP real del cliente.

@MikaelCluseau Estaba pensando que iptables adopta SNAT y DNAT, que no es el caso según usted. ¿Podría aclararme esto?

El 20/04/2016 01:59 PM, Emma escribió:

@MikaelCluseau https://github.com/MikaelCluseau Estaba pensando
iptables adopta SNAT y DNAT, lo que según usted no es el caso.
¿Podría aclararme esto?

Es la parte complicada.

(1) El uso de IP de servicio / externas requiere DNAT.
(2) Si está seguro de que los paquetes de respuesta pasarán por el mismo conntrack
regla (es decir, la misma pila de red o una tabla conntrack replicada),
puede omitir la parte SNAT (es decir, reglas MASQUERADE).

La condición de (2) suele estar bien en los diseños de redes de acceso enrutado
(que es el diseño más simple que se me ocurre).

Por ejemplo, dado

  • un cliente 1.0.1.1,
  • un servicio 1.0.2.1,
  • un pod que implementa el servicio 1.0.3.1.

Luego,

  1. Su enrutador / firewall / equilibrador de carga / host / lo que sea que reciba un paquete
    para el servicio para que vea un paquete "1.0.1.1 -> 1.0.2.1";
  2. Lo envía mediante DNAT al punto final (pod), por lo que el paquete será "1.0.1.1 ->
    1.0.3.1 "en la red del clúster;
  3. El pod responde con un paquete "1.0.3.1 -> 1.0.1.1";
  4. El paquete pasa por un enrutador / firewall / equilibrador de carga / host / lo que sea
    teniendo la regla conntrack, el sistema conntrack reescribe el paquete
    a "1.0.2.1 -> 1.0.1.1" antes de devolverlo al cliente.

Si no se puede cumplir la condición de (2), debe usar SNAT / MASQUERADING
para estar seguro de que el paquete volverá a través del
enrutador / firewall / equilibrador de carga / host / lo que sea conntrack.

@MikaelCluseau - envíeme un correo electrónico a mi nombre de github en google.com - tengo
algo para ti

El martes 19 de abril de 2016 a las 20:20, Mikaël Cluseau [email protected]
escribió:

El 20/04/2016 01:59 PM, Emma escribió:

@MikaelCluseau https://github.com/MikaelCluseau Estaba pensando
iptables adopta SNAT y DNAT, lo que según usted no es el caso.
¿Podría aclararme esto?

Es la parte complicada.

(1) El uso de IP de servicio / externas requiere DNAT.
(2) Si está seguro de que los paquetes de respuesta pasarán por el mismo conntrack
regla (es decir, la misma pila de red o una tabla conntrack replicada),
puede omitir la parte SNAT (es decir, reglas MASQUERADE).

La condición de (2) suele estar bien en los diseños de redes de acceso enrutado
(que es el diseño más simple que se me ocurre).

Por ejemplo, dado

  • un cliente 1.0.1.1,
  • un servicio 1.0.2.1,
  • un pod que implementa el servicio 1.0.3.1.

Luego,

  1. Su enrutador / firewall / equilibrador de carga / host / lo que sea que reciba un paquete
    para el servicio para que vea un paquete "1.0.1.1 -> 1.0.2.1";
  2. Lo envía mediante DNAT al punto final (pod), por lo que el paquete será "1.0.1.1 ->
    1.0.3.1 "en la red del clúster;
  3. El pod responde con un paquete "1.0.3.1 -> 1.0.1.1";
  4. El paquete pasa por un enrutador / firewall / equilibrador de carga / host / lo que sea
    teniendo la regla conntrack, el sistema conntrack reescribe el paquete
    a "1.0.2.1 -> 1.0.1.1" antes de devolverlo al cliente.

Si no se puede cumplir la condición de (2), debe usar SNAT / MASQUERADING
para estar seguro de que el paquete volverá a través del
enrutador / firewall / equilibrador de carga / host / lo que sea conntrack.

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -212230959

@justinsb @yoshiwaan ¿Alguien alguna vez creó un problema para esto? Mi búsqueda me está fallando y tengo una necesidad similar.

¿Puedo sugerir abrir un nuevo problema para la sugerencia de tráfico entre nodos, ya que este problema ya está cerrado? Personalmente, creo que un buen primer paso sería asegurarse de que si un pod se está ejecutando en el nodo local, lo diremos hacia el pod local. Sospecho que esto será suficiente, porque luego puede escalar su RC para que haya pods en cada nodo.

No lo planteé yo mismo

Ahhhhh, creo que lo encontré, esta parece ser la característica / corrección: https://github.com/kubernetes/features/issues/27

Parece ser beta a partir de 1.5.x.

¿Fue útil esta página
0 / 5 - 0 calificaciones