Kubernetes: use iptables para proxy em vez de espaço de usuário

Criado em 23 jan. 2015  ·  187Comentários  ·  Fonte: kubernetes/kubernetes

Eu estava jogando com iptables ontem e protoyed (bem, copiei de hits do Google e mudei) um conjunto de regras de iptables que essencialmente fazem todo o proxy para nós sem a ajuda do espaço do usuário. Não é urgente, mas quero arquivar minhas anotações antes de perdê-las.

Isso tem o efeito colateral adicional agradável (até onde eu posso dizer) de preservar o IP de origem e ser uma grande simplificação da rede. Agora, o kube-proxy precisa apenas sincronizar os Serviços -> iptables. Isso tem a desvantagem de não ser compatível com iptables e kernels mais antigos. Já tivemos um problema com isso antes - em algum momento precisamos decidir o quanto nos importamos.

Isso provavelmente pode ser otimizado ainda mais, mas em testes básicos, vejo sessões pegajosas funcionando e, se eu comentar essa parte, vejo probabilidade igual de acertar cada backend. Não consegui fazer o rodízio determinístico funcionar corretamente (com --nth em vez de --probability), mas poderíamos voltar a isso se quisermos.

Isso configura um portal de serviço com os back-ends listados abaixo

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 comentários

Legal! Acho que deveríamos definitivamente mesclar isso. Em uma nota separada, eu estava vendo o proxy consumir cerca de 30% de um núcleo sob carga pesada, tenho que acreditar que o iptables nos dará um desempenho melhor do que isso.

Temos que priorizar isso - é quase uma reescrita total do kube-proxy e
todos os seus testes. Ele também tem problemas de compatibilidade traseira (não funcionará no
kernels mais antigos ou binários iptables mais antigos).

Na segunda-feira, 26 de janeiro de 2015 às 11h06, Brendan Burns [email protected]
escreveu:

Legal! Acho que devemos definitivamente mesclar isso. Em uma nota separada,
Eu estava vendo o proxy comer cerca de 30% de um núcleo sob carga pesada, eu tenho que
acreditamos que o iptables nos dará um desempenho melhor do que isso.

Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -71517501
.

Será que implementá-lo como uma opção paralela e migrar lentamente faz sentido?

Na segunda-feira, 26 de janeiro de 2015 às 12:01, Tim Hockin [email protected]
escreveu:

Temos que priorizar isso - é quase uma reescrita total do kube-proxy e
todos os seus testes. Ele também tem problemas de compatibilidade traseira (não funcionará no
kernels mais antigos ou binários iptables mais antigos).

Na segunda-feira, 26 de janeiro de 2015 às 11h06, Brendan Burns [email protected]
escreveu:

Legal! Acho que devemos definitivamente mesclar isso. Em um
Nota,
Eu estava vendo o proxy comer cerca de 30% de um núcleo sob carga pesada, eu tenho que
acreditamos que o iptables nos dará um desempenho melhor do que isso.

Responda a este e-mail diretamente ou visualize-o no GitHub
<
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -71517501

.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -71527216
.

Estou tentando persuadir alguém que não conhece bem este código a aprendê-lo
e assumir. Eu realmente _quero_ resolver isso, mas seria melhor se
outra pessoa aprendeu este espaço (não você! :)

Dito isso, você também enviou (bom) e-mail sobre a enorme lista P1 - e eu
não pense que isso ainda está na lista.

Na segunda-feira, 26 de janeiro de 2015 às 13h06, Brendan Burns [email protected]
escreveu:

Talvez implementá-lo como uma opção paralela e migrar lentamente torna
senso?

Na segunda-feira, 26 de janeiro de 2015 às 12:01, Tim Hockin [email protected]
escreveu:

Temos que priorizar isso - é quase uma reescrita total do kube-proxy
e
todos os seus testes. Também tem problemas de compatibilidade posterior (não funcionará
sobre
kernels mais antigos ou binários iptables mais antigos).

Na segunda-feira, 26 de janeiro de 2015 às 11h06, Brendan Burns <
notificaçõ[email protected]>
escreveu:

Legal! Acho que devemos definitivamente mesclar isso. Em um
Nota,
Eu estava vendo o proxy comer cerca de 30% de um núcleo sob carga pesada, eu tenho que
acreditamos que o iptables nos dará um desempenho melhor do que isso.

Responda a este e-mail diretamente ou visualize-o no GitHub
<

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

.

Responda a este e-mail diretamente ou visualize-o no GitHub
<
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment-71527216>

.

Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -71538256
.

Este é um P2? Vale a pena torná-lo um P3 por enquanto?

Espero fazer funcionar, mas ainda podemos rebaixá-lo

Na quarta-feira, 11 de fevereiro de 2015 às 14h49, Satnam Singh [email protected]
escreveu:

Este é um P2? Vale a pena torná-lo um P3 por enquanto?

Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -73982161
.

"Esperança" não equivale a um P3 que chegaremos se pudermos?

Da discussão com @thockin : Este é um requisito para oferecer suporte a intervalos de portas de serviço, que não são necessários para 1.0, mas gostaríamos de oferecer suporte eventualmente.

@thockin "Isso tem a desvantagem de não ser compatível com iptables e kernels mais antigos." Quão 'novo' o kernel teria que ser?

Não é muito novo, mas temos alguns usuários que REALMENTE querem iptables de 2012 a
trabalhar.

Na segunda-feira, 23 de fevereiro de 2015 às 14h44, Sidharta Seethana < notificaçõ[email protected]

escreveu:

@thockin https://github.com/thockin "Isso tem a desvantagem de não ser
compatível com iptables e kernels mais antigos. "Quão 'novo' seria o kernel
tem que ser?

Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -75654187
.

@thockin obrigado. Estamos usando / testando com RHEL / CentOS 6, por exemplo - então seria bom se não tivéssemos uma dependência rígida nos kernels 3.x recentes.

@ pweil- estávamos discutindo isso outro dia
Na segunda-feira, 23 de fevereiro de 2015 às 23h40 Sidharta Seethana [email protected]
escreveu:

@thockin https://github.com/thockin obrigado. Estamos usando / testando com
RHEL / CentOS 6, por exemplo - seria bom se não tivéssemos um disco rígido
dependência de kernels 3.x recentes.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -75698480
.

Bem, você precisa do Docker para ser executado e, em algum momento, teremos que interrompê-lo.
O suporte a iptables back-rev não vai me impedir de (eventualmente) fazer
essa mudança, e vai doer para algumas pessoas.

Na segunda-feira, 23 de fevereiro de 2015 às 20:40, Sidharta Seethana < notificaçõ[email protected]

escreveu:

@thockin https://github.com/thockin obrigado. Estamos usando / testando com
RHEL / CentOS 6, por exemplo - seria bom se não tivéssemos um disco rígido
dependência de kernels 3.x recentes.

Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -75698480
.

Com a ajuda de @thockin , tentamos o mesmo com o udp.

Criamos um cluster GCE Kubernetes com 3 controladores de replicação sky-dns.
No kubernetes-master, definimos o seguinte no iptables:
O ip do serviço dns era 10.0.0.10 e os endpoints do pod que executavam dns eram 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 recente --name hostA --rcheck --seconds 1 --reap -j TESTSVC_A
iptables -t nat -A TESTSVC -m recente --name hostB --rcheck --seconds 1 --reap -j TESTSVC_B
iptables -t nat -A TESTSVC -m recente --name hostC --rcheck --seconds 1 --reap -j TESTSVC_C

iptables -t nat -A TESTSVC -m estatística --mode random --probability 0,333 -j TESTSVC_A
iptables -t nat -A TESTSVC -m estatística --mode random --probability 0,5 -j TESTSVC_B
iptables -t nat -A TESTSVC -m estatística --mode random --probability 1.000 -j TESTSVC_C

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


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

Recebemos uma resposta de volta!

Coisas boas! Apenas para sua informação (confirmando nossa conversa face a face), não é seguro executar vários comandos simultâneos de iptables em geral (correntes diferentes parecem estar OK). iptables é um wrapper para libiptc e veja o comentário em iptc_commit: http://www.tldp.org/HOWTO/Querying-libiptc-HOWTO/mfunction.html

Isso foi aparentemente corrigido em 2013, mas talvez apenas se você passar --wait (?): Http://git.netfilter.org/iptables/commit/?id=93587a04d0f2511e108bbc4d87a8b9d28a5c5dd8

A causa raiz disso é que o iptables efetivamente chama iptables-save / iptables-restore (pelo menos por cadeia); Já vi muitos códigos que apenas chamam iptables-save e iptables-restore em vez de fazer coisas por meio de adições e exclusões. Posso até ter algum código para fazer que eu poderia desenterrar, se isso for útil.

Fico pasmo ao saber que não há maneira de fazer operações do tipo CAS ou LL / SC.

Devemos adicionar suporte para --wait, embora seja recente o suficiente para que o GCE
debian-backports não tem.

Talvez devêssemos fazer nosso próprio bloqueio dentro de nosso código para, pelo menos, nos impedir
de pisar em nós mesmos.

Na quinta-feira, 26 de fevereiro de 2015 às 13h56, Justin Santa Bárbara <
notificaçõ[email protected]> escreveu:

Coisas boas! Apenas para sua informação (confirmando nossa conversa cara a cara),
não é seguro executar vários comandos iptables simultâneos em geral
(correntes diferentes soam como se estivessem OK). iptables é um invólucro
libiptc, e veja o comentário em iptc_commit:
http://www.tldp.org/HOWTO/Querying-libiptc-HOWTO/mfunction.html

Isso foi aparentemente corrigido em 2013, mas talvez apenas se você passar --wait (?):
http://git.netfilter.org/iptables/commit/?id=93587a04d0f2511e108bbc4d87a8b9d28a5c5dd8

A causa raiz disso é que o iptables efetivamente chama iptables-save /
iptables-restore (pelo menos por cadeia); Eu vi muitos códigos que apenas
portanto, chama iptables-save & iptables-restore em vez de fazer coisas
por meio de adições e exclusões. Posso até ter algum código para fazer que eu poderia cavar
se isso for útil.

Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -76282629
.

O que acontece no caso de falhas no meio da criação de um monte de regras?

Boa pergunta - provavelmente devemos pensar muito sobre o que significa
encontrar um erro no meio disso

Em quinta-feira, 26 de fevereiro de 2015 às 20:47, Brian Grant [email protected]
escreveu:

O que acontece no caso de falhas no meio da criação de um monte de
as regras?

Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -76331174
.

@thockin do irc hoje:

O net.ipv4.conf.all.route_localnet permite que 127.0.0.1 seja o alvo das regras de DNAT . Dos documentos :

route_localnet - BOOLEANO

Não considere os endereços de loopback como origem ou destino marciano
durante o roteamento. Isso permite o uso de 127/8 para fins de roteamento local.
padrão FALSE

Vamos integrar isso ao kubelet ou mantê-lo em um daemon separado? Kubelet já vigia os serviços para preencher env vars.

Eu gostaria de mantê-lo como um binário separado. Existem razões pelas quais você
pode querer executá-lo em outras máquinas (por exemplo, VMs pet) fora de um K8s
cluster para obter acesso aos serviços k8s.

--brendan

Na sexta-feira, 13 de março de 2015 às 11h37, Brian Grant [email protected]
escreveu:

Vamos integrar isso ao kubelet ou mantê-lo em um daemon separado?
Kubelet já vigia os serviços para preencher env vars.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79230747
.

Colocar o papo em dia. Em relação ao que acontece no caso de falhas (das quais haverá muitas, acredite em mim), sou um grande fã da abordagem anti-entropia - armazene o estado desejado em algum lugar e, periodicamente, reconcilie o estado desejado e o atual (alterando o estado real ) Neste caso, talvez tão simples como:

enquanto (verdadeiro) {
actualState = iptablesSave ()
if actualState! = neededState {iptablesRestore (neededState))
sleep_a_while ()
}

Concordo 100% que é a maneira certa de lidar com falhas na escrita de iptables
as regras.

Na sexta-feira, 13 de março de 2015 às 13h16, Quinton Hoole [email protected]
escreveu:

Colocar o papo em dia. Em relação ao que acontece em caso de falhas (das quais
haverá muitos, acredite em mim), sou um grande fã da abordagem anti-entropia

  • armazenar o estado desejado em algum lugar e, periodicamente, reconciliar o desejado e
    estado real (alterando o estado real). Neste caso, talvez tão simples como:

enquanto (verdadeiro) {
actualState = iptablesSave ()
if actualState! = neededState {iptablesRestore (neededState))
sleep_a_while ()
}

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79336296
.

É mais ou menos o que acontece agora, não é? Para cada regra esperada,
verifique se existe e se não, faça-o.

Na sexta-feira, 13 de março de 2015 às 14h02, Brendan Burns [email protected]
escreveu:

Concordo 100% que é a maneira certa de lidar com falhas na escrita de iptables
as regras.

Na sexta-feira, 13 de março de 2015 às 13h16, Quinton Hoole [email protected]
escreveu:

Colocar o papo em dia. Em relação ao que acontece em caso de falhas (das quais
serão muitos, acredite em mim), sou um grande fã do anti-entropia
abordagem

  • armazenar o estado desejado em algum lugar e, periodicamente, reconciliar o desejado e
    estado real (alterando o estado real). Neste caso, talvez tão simples
    Como:

enquanto (verdadeiro) {
actualState = iptablesSave ()
if actualState! = neededState {iptablesRestore (neededState))
sleep_a_while ()
}

-
Responda a este e-mail diretamente ou visualize-o no GitHub
<
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79336296

.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79392626
.

Eu concordo que há utilidade em um binário separado, mas talvez possamos ligá-lo a
kubelet (da mesma forma que o cAdvisor está indo) e torná-lo um autônomo no
mesmo tempo.

Na sexta-feira, 13 de março de 2015 às 12h03, Brendan Burns [email protected]
escreveu:

Eu gostaria de mantê-lo como um binário separado. Existem razões pelas quais você
pode querer executá-lo em outras máquinas (por exemplo, VMs pet) fora de um K8s
cluster para obter acesso aos serviços k8s.

--brendan

Na sexta-feira, 13 de março de 2015 às 11h37, Brian Grant [email protected]
escreveu:

Vamos integrar isso ao kubelet ou mantê-lo em um daemon separado?
Kubelet já vigia os serviços para preencher env vars.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
<
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79230747

.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -79257059
.

Eu ficaria curioso para ouvir o que o pessoal do Kubernetes-Mesos tem a dizer sobre se os componentes do nó devem ser mais integrados ou modulares. @jdef?

[[EDITADO]] Eu realmente gosto da modularidade dos componentes k8s, por exemplo, executando um processo proxy separado de um processo kubelet. Se o proxy falhar por qualquer motivo, ele não derrubará o kubelet. Isso é muito bom, pois os executores do Mesos não têm um modelo de failover muito elegante agora - e o executor da estrutura kubernetes-mesos é um híbrido kubelet / executor. Este modelo também me permite executar um serviço de proxy em um mesos master e usá-lo como um balanceador round-robin para clientes externos (como no guia de introdução que enviamos).

Em termos de embalagem / envio de binários, acho muito útil ter a funcionalidade compactada, como no hyperkube. Também pensei em como empacotar os componentes da estrutura kubernetes-mesos em contêineres Docker mínimos . Iptables tem dependências de bibliotecas externas e isso complica as coisas. Portanto, um bom compromisso pode ser enviar o framework k8sm como um Docker que contém a única imagem de hipercubo - mas quando esse framework é executado e começa a distribuir executores de kubelet pelo cluster, basicamente envia uma imagem de hipercubo que pode se transformar em um kubelet- executor ou proxy - e cada processo pode ser executado diretamente no host. Isso basicamente executa um end-run em torno do problema de dependência iptables- {binários, bibliotecas} -in-Docker.

+1 para funcionalidade modular, +1 para imagem binária única

@thockin re: anti-entropia: Ah, sim. Vejo que proxier.SyncLoop () faz isso. Nesse caso, não é a resposta à pergunta de @ bgrant0607 de 26 de fevereiro que os erros podem ser ignorados e serão reparados na próxima iteração de SyncLoop () (atualmente 1 minuto)? Ou talvez eu esteja faltando alguma coisa?

@thockin

  1. Estamos preocupados com o "buraco negro" do tráfego de rede ou é algo que o autor do serviço / pod precisa cuidar?

Com proxy de espaço de usuário
Suponha que o IP virtual 10.0.0.11 tenha 3 pontos de extremidade, digamos, 10.240.1.1, 10.240.1.2, 10.240.1.3
Com um proxy de espaço do usuário, se um endpoint disser 10.240.1.1 não funcionasse, o proxy perceberia que a conexão tcp não foi estabelecida com 10.240.1.1 e poderia retroceder para um dos outros 2 endpoints.

Com iptables
Quando usamos iptables, não há mecanismo de fallback, pois o kubernetes não percebe se o endpoint funcionou ou não.
Poderíamos mitigar isso se tivéssemos algum tipo de verificação de integridade para os endpoints, que removeria endpoints não responsivos.

Ou talvez, se preocupar com endpoints não responsivos não seja responsabilidade do sistema kubernetes e sim do autor do pod?

O usuário pode configurar testes de prontidão, que são executados pelo Kubelet. A falha do probe fará com que um nó de extremidade seja removido da lista de nós de extremidade pelo controlador de nós de extremidade. O proxy de serviço deve então remover o nó de extremidade do conjunto de destino.

Estive investigando isso para o GSoC e me pergunto:

Então, idealmente, detectaríamos se o iptables é suficientemente novo para usar e, caso contrário, continuaríamos usando o kube-proxy?

De https://github.com/GoogleCloudPlatform/kubernetes/issues/5419 , parece que essa seria a abordagem ideal; com kubelet determinando se usar ip-tables ou iniciar kube-proxy.

Também estou um pouco atrasado para o GSoC (estava nas férias de primavera ...), então também estou me perguntando se ainda posso enviar uma proposta do GSoC amanhã / mais tarde hoje (exceto, é claro, o prazo 27, é ainda está aberto)?

@BenTheElder Sim, você tem até sexta-feira para enviar uma proposta. Existe outra pessoa potencialmente interessada neste tópico, mas nenhuma proposta específica para ele ainda.

Não estou preocupado com os kernels anteriores a 2012 tanto quanto com os sistemas operacionais sem iptables, embora eles já estejam corrompidos até certo ponto.

@ bgrant0607 obrigado!
Acho que posso selecionar esse problema então. Parece interessante.

A análise de prontidão funcionará bem para a inicialização do aplicativo, mas não tenho certeza se a prontidão é adequada para atenuar a falha do aplicativo. Após a falha do pod, o sinal deve passar do aplicativo -> kubelet -> apiserver -> endpoints_controller -> apiserver -> kube-proxy. Eu estaria interessado em entender a latência entre uma falha de aplicativo e uma remoção de endpoint da rotação kube-proxy. Durante este período, as solicitações serão encaminhadas para um endpoint sem resposta.

Tentar novamente em caso de falha de conexão é uma estratégia comum e um recurso razoavelmente útil de muitos balanceadores de carga populares (por exemplo, haproxy, AWS ELB) e é gerenciado pela implementação atual do kube-proxy. Essa responsabilidade deve ser migrada para o LB externo? E quanto ao tráfego intra-cluster?

Outra ideia, com o iptables, provavelmente encontraremos problemas que diminuem normalmente a conexão após a reconfiguração em comparação com um LB real.

Mike levanta bons pontos.

Na segunda-feira, 23 de março de 2015 às 23h, Mike Danese [email protected]
escreveu:

Pensando bem, provavelmente encontraremos problemas de conexão normal
drenando após a reconfiguração vs um LB real.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -85354865
.

Tenho lido o código-fonte do kube-proxy e do pacote de proxy; O iptables ainda não está sendo usado na revisão atual?

O que exatamente precisa ser feito nisso? A partir da fonte master atual, parece que o iptables já está sendo usado extensivamente no proxy.

@mikedanese @thockin Readiness é mais útil para interrupções planejadas. Interrupções não planejadas sempre causarão alguns erros observáveis. O intervalo de sondagem geralmente deve ser longo em relação à latência de atualização, mas também podemos implementar regras de reencaminhamento no nó de destino por meio de comunicação direta entre Kubelet e kube-proxy, se a latência via apiserver e etcd for muito longa e / ou que caminho não é suficientemente confiável.

@BenTheElder As regras existentes roteiam o tráfego por meio do proxy. A ideia aqui é usar as regras para contornar o proxy.

@ bgrant0607 Obrigado, agora faz todo o sentido. Outro leu o código-fonte e os documentos de design e estou quase terminando de escrever um rascunho de proposta.

Rascunho da proposta GSoC: https://gist.github.com/BenTheElder/ac61900595a7ea9ea9b5

Apreciei especialmente o feedback sobre a seção de programação. Não tenho muita certeza disso.
Devo terminar mais cedo. Adoraria trabalhar em alguns outros problemas (menores?) Não resolvidos do GSoC, como:
https://github.com/GoogleCloudPlatform/kubernetes/issues/1651.

Obrigado mais uma vez, o Kubernetes leva o bolo para o grupo mais amigável.

Só quero dizer que estou muito feliz em dizer que minha proposta foi aceita e que estarei trabalhando nisso durante o verão. :risonho:

Estou muito animada. Infelizmente, estou no meio das minhas provas finais agora, mas começando em algum momento deste fim de semana, devo estar trabalhando muito mais nisso, provavelmente começando com https://github.com/GoogleCloudPlatform/kubernetes/pull/7032 finalizado.

@thockin @brendanburns Alguém pode avaliar se queremos fazer isso em paralelo ao proxy do espaço do usuário ou como a migração para a reimplementação funcionaria?

Parece que já preferimos iptables> = 1.4.11 (lançado em 26 de maio 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) {

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

Nós realmente vemos hosts mais antigos do que isso?

Uma abordagem obviamente seria detectar em tempo de execução qual versão do iptables estamos executando e fazer a "melhor coisa" que pudermos com a versão, por exemplo, algo como:

if (versão antiga) {
carregar módulo de proxy do espaço do usuário
}
outro {
carregar módulo de proxy iptables
}

Eu advertiria contra ter muitos ramos na instrução if acima (de preferência apenas 2) e evitar, tanto quanto possível, ter esse tipo de instrução if em mais de um lugar no código.

Não vasculhei o código em detalhes para descobrir como a abordagem acima é viável.

Além disso, todos os nós precisam implementar a mesma estratégia (espaço do usuário vs proxy iptables) ou cada um pode decidir de forma independente?

Se cada nó decidir de forma independente, aumentamos potencialmente a área da superfície de teste proporcional ao quadrado do número de ramos na instrução if acima (ou seja, source_mode x dest_mode), mas se pudermos manter o número de modos em 2, acho que está tudo bem .

Q

Ah, e a resposta à sua pergunta sobre se vemos nós antigos é "sim", infelizmente.

Há muita discussão sobre isso em uma edição separada. Vou tentar descobrir para você.

@ quinton-hoole Obrigado!

Além disso, tenho quase certeza de que podemos executar o espaço do usuário em um nó e o iptables em outro.

O número de modos deve ser apenas 2, exceto para aquele hack para quando não temos -C, mas os nós que têm -C devem ser capazes de executar a versão iptables puro (eu acho).

Ah sim, # 7528 discute as versões do kernel e outras coisas.

Obrigado.
Não vi isso quando procurei os requisitos para kubernetes. Os únicos requisitos que encontrei foram nos documentos de rede discutindo como assumimos IPs exclusivos.

Provavelmente deveríamos escrever alguma documentação para os requisitos, uma vez que tenhamos uma ideia melhor do que eles são.

Comecei a hackear aqui: https://github.com/BenTheElder/kubernetes/tree/iptables_proxy

Especificamente, movi a implementação do espaço do usuário para trás de uma interface aqui:
https://github.com/BenTheElder/kubernetes/commit/4e5d24bb74aca43b0dd37cf5cfee8a34f8eff2bf

Não tenho certeza agora, porém, se a seleção de implementação deve ser em cmd / kube-proxy ou em pkg / proxy, então posso remover isso e fazer com que a implementação seja selecionada por kube-proxy.

Edit: Acho que, em retrospecto, provavelmente faz mais sentido selecionar a implementação do kube-proxy.

@BenTheElder Eu testei as regras de Tim com Calico e elas funcionam bem. Fazemos todo o nosso trabalho na tabela de filtros, então as regras DNAT aqui definiram o IP src apropriado naquele ponto.

De forma mais geral, seria bom ter uma discussão para definir como os plug-ins de rede podem alterar o iptables com segurança se o Kubernetes também for inserir regras lá. Não queira atropelar (ou ser atropelado por) as regras do Kubernetes se elas mudarem no futuro.

@Symmetric Sim. Ainda não tenho certeza sobre a parte dos plug-ins, mas isso parece muito importante.

Provavelmente estarei um pouco ocupado neste fim de semana, mas na segunda-feira devo começar a trabalhar em tempo integral para o GSoC implementar a primeira iteração.
Gostaria de manter isso em mente ao fazer isso, mas depois de examinar a API de plug-ins de rede, não tenho certeza de qual é a maneira mais limpa de lidar com isso.

Você tem alguma ideia de como gostaria que isso fosse / como deveria funcionar?

FWIW, eu fiz algo que funciona para nós porque o kube-proxy estava quase parando de responder. Ele está aqui: https://github.com/MikaelCluseau/kubernetes-iptables-proxy/blob/master/iptables-routing.rb.

Eu não vi esse tópico antes, mas acabei com algo parecido, exceto que cometi um erro com minhas estatísticas aleatórias de correspondência de pesos :-)

Também gostaria de compartilhar que atingimos o nf_conntrack_max rapidamente. Provavelmente deve ser aumentado.

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

Posso não ter entendido toda a necessidade de iptables , mas por que não usar IPVS vez disso?
Parece ser mais relevante para proxy do que iptables ...
Aqui está uma implementação go simples: https://github.com/noxiouz/go-ipvs
E apenas para completar # 561, existe também o projeto ktcpvs .

O IPVS também parece ser uma abstração do netfilter (como o iptables). Podemos compartilhar algumas funcionalidades com o código existente usando iptables; e o iptables parece ser a solução mais flexível / geral para gerenciar o netfilter.

Quanto a # 561 e ktcpvs: ktcpvs não parece ter tido nenhum desenvolvimento desde 2004 e não parece ter recursos que os usuários gostariam de reescrever URL. Independentemente disso, o # 561 está procurando uma solução genérica para ser usada com balanacers conectáveis.

Nota lateral: esse projeto go não parece ter uma licença.

iptables será descontinuado "um dia" em favor de nftables ( nft cli).
Também usar iptables CLI para criar regras não parece ser muito robusto ...

Uma busca rápida me encontre este outro projeto do MIT: https://github.com/vieux/go-libipvs
Mas parece ser realmente muito fácil criar um funcional simples, já que toda a complexidade já está à prova de balas dentro do código do kernel.

Duvido que o iptables seja removido de qualquer uma das principais distros em breve, e a CLI do iptables é especificamente para criar e gerenciar regras para netfilter ...?

Um invólucro cgo incompleto como o linkado parece muito menos seguro do que gastar com iptables e iptables-restore e já precisamos do iptables para outras regras (por exemplo, nodeports) e com iptables-restore podemos fazer atualizações em massa com alguma atomicidade.

Além disso, o IPVS parece ter sido projetado para ser usado em uma máquina host de balanceamento de carga separada dos servidores "reais".
Isso sugere que esse é o único uso compatível:

2.2. Pegadinhas: você precisa de um cliente externo (o diretor e os servidores reais não podem acessar o serviço virtual)

Para configurar e testar / executar o LVS, você precisa de no mínimo 3 máquinas: cliente, direcionador, servidor (es) real (es).

Do lado de fora, o LVS funciona como uma máquina. O cliente não pode ser uma das máquinas do LVS (o direcionador ou servidor real). Você precisa de um cliente externo. Se você tentar acessar um serviço controlado LVS (por exemplo, http, smtp, telnet) de qualquer uma das máquinas no LVS; o acesso do direcionador irá travar, o acesso de um servidor real irá se conectar ao serviço localmente, contornando o LVS.

Também parece que o IPVS / LVS adiciona alguns requisitos extras, como um daemon de pulsação e processos de monitoramento extras. Já lidamos com informações de endpoint e monitoramento de integridade de pod etc. de dentro do kubernetes.

1 para a abordagem iptables. Usamos iptables extensivamente no Calico e eles provaram ser robustos e têm um bom desempenho e escalabilidade (assumindo que você projete bem suas regras). @BenTheElder , se você precisar de alguma ajuda com o funcionamento do iptables, por favor, avise-nos, pois ficaremos felizes em ajudar.

+1 para iptables e iptables-restore, é uma abordagem muito menos pesada
do que IPVS / LVS e dita menos requisitos de sistema (daemon de pulsação,
etc.)

No sábado, 13 de junho de 2015 às 11h27, Alex Pollitt [email protected]
escreveu:

1 para a abordagem iptables. Usamos iptables extensivamente em Calico e
eles provaram ser robustos e têm um bom desempenho e escalabilidade (assumindo que você
projete bem suas regras). @BenTheElder https://github.com/BenTheElder ,
se você precisar de alguma ajuda com o funcionamento do iptables, por favor, deixe
nós sabemos, porque ficaríamos felizes em contribuir.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -111719474
.

Obrigado Alex, avisarei você se eu fizer isso.

Eu poderia usar algum feedback / entrada sobre a implementação atual (https://github.com/GoogleCloudPlatform/kubernetes/pull/9210) se alguém tiver tempo.

Está quase completo e atualmente totalmente atualizado com o mestre upstream, preciso terminar de escrever o código que compara as regras geradas com iptables-save e restaura os contadores etc, mas as regras são geradas e (principalmente) funcionam, praticamente seguindo as regras descritas no OP aqui, com a maior mudança sendo apenas os nomes da cadeia, que eram necessários para a geração automática de nomes que o iptables aceitará.

Há um caso extremo relatado aqui: https://github.com/BenTheElder/kubernetes/issues/3 que pode exigir uma mudança para lidar com pods que se conectam a si mesmos.

Tive excelentes comentários e discussões com @MikaelCluseau e @Symmetric em particular sobre fazer algumas reformulações para lidar com isso e outras coisas (obrigado novamente!); mas poderíamos usar mais informações sobre o design da regra em particular. Se alguém mais tiver tempo para dar uma olhada, ficaria muito grato, pois não tenho certeza de qual é o melhor caminho a seguir e desejo evitar fazer grandes alterações sem mais informações.

O PR em si é muito grande, mas a geração de regra relevante está toda em pkg/proxy/proxieriptables.go syncProxyRules() em: https://github.com/BenTheElder/kubernetes/blob/iptables_proxy/pkg/proxy/proxieriptables. vá # L286

A discussão existente pode ser vista (aqui, é claro), bem como nos comentários de relações públicas e em https://github.com/BenTheElder/kubernetes/issues/3 , bem como um pouco mais em https://github.com/ BenTheElder / kubernetes / issues / 4.

Um outro problema que precisa de contribuição:

No código atual, o kube-proxy ainda está incluído, para tratar APENAS o caso nodePort. Acho que podemos acabar com o kube-proxy neste caso também, e propusemos algumas regras simples de iptables para fazer isso no PR de Ben .

Mas essas regras ainda obscurecem o IP de origem de qualquer LB externo, portanto, não são ideais. O problema é que, se apenas DNAT o tráfego do LB quando atinge um nó, o pacote de resposta pode vir de um nó diferente e, portanto, não acho que o LB será capaz de correlacionar a resposta com a sessão TCP de origem . Essa preocupação é válida? A implementação seria mais simples se não tivermos que nos preocupar com isso.

Suspeito que podemos fazer alguma mágica para manter os proxies HTTP felizes, mas não vejo uma maneira de tornar isso geral no L4.

Estou testando a magia negra do seu PR, mas não gera nada para mim, parece que as regras começaram a ser geradas com chamadas para iptables então um arquivo iptables-restore é produzido.

Há uma falha na parte do cabeçalho do arquivo produzido, normalmente aqueles que foram preenchidos com a chamada de iptables. Existe a parte relevante do log:

I0807 11: 41: 24.560063 8369 iptables.go: 327] executando iptables -N [KUBE-PORTALS-CONTAINER -t nat]
I0807 11: 41: 24.562361 8369 iptables.go: 327] executando iptables -C [PREROUTING -t nat -m comentário --comment manipular ClusterIPs; NOTA: isso deve ser antes das regras NodePort -j KUBE-PORTALS-CONTAINER]
I0807 11: 41: 24.563469 8369 iptables.go: 327] executando iptables -N [KUBE-PORTALS-HOST -t nat]
I0807 11: 41: 24.565452 8369 iptables.go: 327] executando iptables -C [OUTPUT -t nat -m comentário --comment manipular ClusterIPs; NOTA: isso deve ser antes das regras NodePort -j KUBE-PORTALS-HOST]
I0807 11: 41: 24.566552 8369 iptables.go: 327] executando iptables -N [KUBE-NODEPORT-CONTAINER -t nat]
I0807 11: 41: 24.568363 8369 iptables.go: 327] executando iptables -C [PREROUTING -t nat -m addrtype --dst-type LOCAL -m comentário --comment lidar com serviço NodePorts; NOTA: esta deve ser a última regra na cadeia -j KUBE-NODEPORT-CONTAINER]
I0807 11: 41: 24.569564 8369 iptables.go: 327] executando iptables -N [KUBE-NODEPORT-HOST -t nat]
I0807 11: 41: 24.571458 8369 iptables.go: 327] executando iptables -C [SAÍDA -t nat -m addrtype --dst-type LOCAL -m comentário --comment lidar com serviço NodePorts; NOTA: esta deve ser a última regra na cadeia -j KUBE-NODEPORT-HOST]
I0807 11: 41: 24.573392 8369 iptables.go: 327] executando iptables -C [POSTROUTING -t nat -m comentário - pod de identificador de comentário conectando-se a si mesmo -s 10.240.240.78/32 -d 10.240.240.78/32 -j MASQUERADE ]
I0807 11: 41: 24.574447 8369 proxier.go: 349] Sincronizando regras de iptables.
I0807 11: 41: 24.575592 8369 proxier.go: 399] Cadeia: PREROUTING, Regra:: PREROUTING ACCEPT [0: 0]
I0807 11: 41: 24.575615 8369 proxier.go: 401] Regra: -A PREROUTING -m comentário --comment "lidar com ClusterIPs; NOTA: deve ser antes das regras NodePort" -j KUBE-PORTALS-CONTAINER
I0807 11: 41: 24.575625 8369 proxier.go: 401] Regra: -A PREROUTING -m addrtype --dst-type LOCAL -m comentário --comment "lidar com NodePorts de serviço; NOTA: esta deve ser a última regra na cadeia" -j KUBE-NODEPORT-CONTAINER
I0807 11: 41: 24.575633 8369 proxier.go: 399] Cadeia: INPUT, Regra:: INPUT ACCEPT [0: 0]
I0807 11: 41: 24.575646 8369 proxier.go: 399] Cadeia: SAÍDA, Regra:: ACEITAR SAÍDA [0: 0]
I0807 11: 41: 24.575658 8369 proxier.go: 401] Regra: -A SAÍDA -m comentário --comment "lidar com ClusterIPs; NOTA: deve ser antes das regras NodePort" -j KUBE-PORTALS-HOST
I0807 11: 41: 24.575670 8369 proxier.go: 401] Regra: -A SAÍDA -m addrtype --dst-type LOCAL -m comentário --comment "lidar com NodePorts de serviço; NOTA: esta deve ser a última regra na cadeia" -j KUBE-NODEPORT-HOST
I0807 11: 41: 24.575683 8369 proxier.go: 399] Cadeia: POSTROUTING, Regra:: POSTROUTING ACCEPT [0: 0]
I0807 11: 41: 24.575691 8369 proxier.go: 401] Regra: -A POSTROUTING! -d 10.0.0.0/8 -o eth0 -j MASQUERADE
I0807 11: 41: 24.575699 8369 proxier.go: 401] Regra: -A POSTROUTING -s 10.240.240.78/32 -d 10.240.240.78/32 -m comentário --comment "lidar com pod conectando-se a si mesmo" -j MASQUERADE
I0807 11: 41: 24.575709 8369 proxier.go: 399] Cadeia: KUBE-NODEPORT-CONTAINER, Regra:: KUBE-NODEPORT-CONTAINER - [0: 0]
I0807 11: 41: 24.575720 8369 proxier.go: 399] Cadeia: KUBE-NODEPORT-HOST, Regra:: KUBE-NODEPORT-HOST - [0: 0]
I0807 11: 41: 24.575729 8369 proxier.go: 399] Cadeia: KUBE-PORTALS-CONTAINER, Regra:: KUBE-PORTALS-CONTAINER - [0: 0]
I0807 11: 41: 24.575740 8369 proxier.go: 399] Cadeia: KUBE-PORTALS-HOST, Regra:: KUBE-PORTALS-HOST - [0: 0]
I0807 11: 41: 24.581897 8369 proxier.go: 603] Regra de sincronização:: 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 ...]

Mesclar um iptable-save com o resultado produzido no modo detalhado pode ser importado e fazer coisas boas.

@bnprss obrigado pelo relatório, recentemente houve uma série de mudanças não testadas, incluindo o uso de um arquivo temporário e o uso do sinalizador "-T table" para iptables-restore durante algumas reescritas para o processo de revisão. Vou fazer uma correção assim que souber o que causou a (s) regressão (ões).

@bnprss Como você disse, o cabeçalho da tabela está faltando ("* nat" deve ser a primeira linha), ele foi removido por engano e depois de colocá-lo de volta em tudo parece estar funcionando bem novamente, aparentemente sem outros bugs (excluindo: https: / /github.com/BenTheElder/kubernetes/issues/3). Obrigado novamente, desculpe por isso. Eu empurrei a correção.

Bom trabalho, as regras estão carregando e parecem funcionar de dentro, mas sem sorte com o balanceador externo, nenhuma comunicação de fora dá resposta.

Huh. Você poderia passar para o PR e fornecer mais alguns detalhes? Até aqui
tem funcionado bem, mas não me implanto além dos testes locais e
não acho que nenhum dos outros testadores estava usando um balanceador de carga externo.
Em 7 de agosto de 2015, 13h29, "bnprss" [email protected] escreveu:

Bom trabalho, as regras estão carregando e parecem funcionar por dentro, mas sem sorte
com externalloadbalancer nenhuma comunicação do lado de fora dá resposta.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -128772763
.

Sim, para obter os detalhes, conduzirei mais investigações e produzirei alguns registros ou pistas sobre RP, mas não antes de amanhã, gostaria de ter um bom trabalho de backup para executar antes de potencialmente quebrar algo.

Você pode calcular o token das regras sem separadores "-_"?

@bnprss , ótimo.
As cadeias de regras geradas para serviços são um hash da porta / terminal de serviço e, em seguida, url base64 codificado e truncado. KUBE-SVC-. O código está aqui: https://github.com/GoogleCloudPlatform/kubernetes/pull/9210/files#diff -d51765b83fe795b469e8a86276b12dc9R321
Escolhemos isso como uma forma de gerar nomes de cadeia válidos que atenderão ao limite de caracteres em iptables, embora ainda sejam determinísticos.
Portanto, deve ser possível replicar externamente.
Se você quer dizer, podemos parar de usar separadores, provavelmente poderíamos, mas o "_" vem de algum hash codificado e o "-" está apenas seguindo os padrões nos nomes de regra do proxy de espaço de usuário existente.
Provavelmente poderíamos usar outra coisa sem muitos problemas, se necessário.

Estou bem com isso, e isso é realmente cosmético! :)
Mas isso difere das coisas que vi antes:
regras gce lb: a07f76b3b2ec311e59e2642010af0479
regras gce fw: k8s-fw-a7ecad94f3ba511e59e2642010af0479
regras de roteamento gce: default-route-6973e029b504a0e8
roteamento gce para o nó: ofuscated_cluster_node-43506797-2eb2-11e5-9e26-42010af04793

este é bom:
KUBE-SVC-6ADi2TVfn7mFPvBjC56
esses são engraçados:
KUBE-SVC-zU6ParcQ-UfW_LdRDUc
KUBE-SVC-y - z1xTUpHPT6sgAUCC

Sim, eu também não sou exatamente um fã deles, talvez pudéssemos mudar o hash
codificação.

Na sexta-feira, 7 de agosto de 2015 às 14h16, bnprss [email protected] escreveu:

Estou bem com isso, e isso é realmente cosmético! :)
Mas isso difere das coisas que vi antes:
regras gce lb: a07f76b3b2ec311e59e2642010af0479
regras gce fw: k8s-fw-a7ecad94f3ba511e59e2642010af0479
regras de roteamento gce: default-route-6973e029b504a0e8
roteamento gce para o nó:
ofuscated_cluster_node-43506797-2eb2-11e5-9e26-42010af04793

este é bom:
KUBE-SVC-6ADi2TVfn7mFPvBjC56
esses são engraçados:
KUBE-SVC-zU6ParcQ-UfW_LdRDUc
KUBE-SVC-y - z1xTUpHPT6sgAUCC

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -128785914
.

Sim, pode ser possível usar apenas a parte truncada do SHA, git está ok com isso, docker também, e parece ser a forma como as outras referências a entidades kube são feitas. Em caso de colisão, o hash base64 gerado não ajudará. ;)
Acho que @thockin poderia aconselhar sobre esse ponto.

Eu estava mais preocupado com caracteres válidos em iptables, para os quais tive dificuldade em encontrar uma boa referência. Analisarei isso mais detalhadamente em breve.

Na sexta-feira, 7 de agosto de 2015 às 14h29, bnprss [email protected] escreveu:

Sim, pode ser possível usar apenas a parte truncada do SHA, o git está ok com
isso, docker também, e parece ser a forma como a outra referência ao kube
entidades são feitas. Em caso de colisão no hash base64 gerado não
ajuda. ;)
Eu acho que @thockin https://github.com/thockin poderia aconselhar sobre esse ponto.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -128788454
.

@bnprss fyi o PR é bastante instável e sendo refeito, por pensar, estamos cortando NodePort etc por enquanto e nos concentrando em obter uma versão mais simples e limpa com suporte para portais, em seguida, trabalhando de volta até a paridade total.

Eu _não_ tentaria executá-lo agora, mas, com sorte, estará de volta em breve. Dividindo o PR em alguns menores relacionados e, em seguida, empurrando um limpo com as coisas do iptables-proxy agora mesmo.

Para aqueles de vocês que jogam em casa, estou confiante de que podemos aumentá-lo ao máximo
paridade, mas será muito mais fácil de revisar em etapas :)

Na sexta-feira, 7 de agosto de 2015 às 21h35, Benjamin Elder [email protected]
escreveu:

Minha resposta ao comentário acima, também a ser eliminada em breve:

Discutido no IRC:

  • ainda precisará lidar com contadores, mas deseja manter a análise de
    estado no pacote util / iptables.
  • ainda precisa de hash ou similar para lidar com os limites de comprimento da corrente

Caso contrário, parece uma simplificação muito limpa, implementará após
um pouco mais de discussão.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/GoogleCloudPlatform/kubernetes/issues/3760#issuecomment -128912169
.

Status: a lógica "principal" é verificada e ativada por flag.

Estou trabalhando em portas de nó agora. Existem muitos casos estranhos que precisam de tratamento especial. Minhas notas até agora:

# 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

Tenho trabalhado em uma ferramenta contrib para os testes.
Até agora, estou pensando em iniciar um servidor em um nó, latência de tempo de
solicitações para ele, veja como obter o carregamento do recurso kube-proxy e despeje o
dados em CSV para gráficos etc.
Esperançosamente concluído antes de sexta-feira, familiarizando-se mais com o kubectl agora.

Na quarta-feira, 12 de agosto de 2015 às 20:48, Tim Hockin [email protected]
escreveu:

Status: a lógica "principal" é verificada e ativada por flag.

Estou trabalhando em portas de nó agora. Existem muitos casos estranhos que precisam
manuseio especial. Minhas notas até agora:

Portas de nó básicas:

iptables -t nat -N KUBE-NODEPORTS
iptables -t nat -A PREROUTING -j KUBE-NODEPORTS
iptables -t nat -A SAÍDA -j KUBE-NODEPORTS
iptables -t nat -A KUBE-NODEPORTS -p tcp -m comentário --comment "TESTE: default / nodeport: p " -m tcp --dport 30241 -j KUBE-SVC-EQKU6GMUKRXBR6NWW53

Para obter o tráfego de nó para localhost: nodeport para o serviço:

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

Marque os pacotes que são destinados a serviços do host local e, em seguida, disfarce-os

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

Para obter o tráfego de um pod para si mesmo por meio de um serviço:

para intf em $ (lista de links IP | grep veth | cut -f2 -d :); fazer brctl hairpin cbr0 $ intf on; feito

Marque os pacotes destinados a cada ponto de extremidade a partir do mesmo ponto de extremidade e, a seguir, disfarce-os.

Isso é hacky, mas eu realmente não sei quais pods são "locais" e eu realmente não quero saber agora. (mas irei eventualmente)

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

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130492394
.

@BenTheElder Acabei de fazer algumas medições de desempenho de rede razoavelmente detalhadas no GCE - recomendo dar uma olhada no netperf (qperf também fornece medições de latência).

netperf é uma ferramenta cliente / servidor de desempenho, eu empacotei o cliente e o servidor no container docker paultiplady / netserver: ubuntu.2. Existem muitas opções no netperf, mas algo como girar dois pods netserver e executar

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

deve fornecer uma distribuição decente de estatísticas, incluindo latência e taxa de transferência. Você pode executar o contêiner netserver usando docker run --net=host para fazer testes de nó-> pod também.

O dockerfile para este contêiner é muito simples, posso dispará-lo se você quiser estendê-lo para algo mais enxuto (por exemplo, um contêiner baseado em alpinelinux para puxar mais rápido).

Obrigado, vou olhar para isso.

A partir deste comentário, porém, acho que queremos fazer algum tipo de latência de solicitação de serviço. No momento, estou tentando usar o contêiner nginx padrão como nó X e trabalhando para ter um pod de teste atingindo-o repetidamente para que possamos construir um gráfico no nó Y.

No entanto, vou olhar para netperf / qperf e sempre podemos ter vários testes.
Eu gostaria de terminar esse gráfico primeiro, embora de acordo com a discussão anterior com @thockin

Em quinta-feira, 13 de agosto de 2015 às 12h02, Paul Tiplady [email protected]
escreveu:

@BenTheElder https://github.com/BenTheElder Acabei de fazer alguns razoavelmente
medições detalhadas de desempenho de rede no GCE - recomendo dar uma olhada em
netperf (qperf também fornece medições de latência).

netperf é uma ferramenta de desempenho cliente / servidor, empacotei o cliente e
o servidor no contêiner docker paultiplady / netserver: ubuntu.2.
há muitas opções no netperf, mas algo como girar dois
pods netserver e em execução

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

deve fornecer uma distribuição decente de estatísticas, incluindo latência e taxa de transferência.
Você pode executar o contêiner netserver usando docker run --net = host para fazer
node-> pod tests também.

O dockerfile para este contêiner é muito simples, posso dispará-lo se
você deseja estendê-lo para algo mais enxuto (por exemplo, um baseado em alpinelinux
recipiente para puxar mais rápido).

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130524576
.

em relação às portas do nó: Em # 9210 @Symmetric trouxe este caso:

Se o tráfego flui:
LB -> node1:nodePort
E o pod de serviço está no node2, então o fluxo completo será:
LB -> node1:nodePort -> node2 -> pod:svcPort
O srcIP ainda será o LB, então a resposta irá
pod -> node2 -> LB
Uma vez que o node2 pode rotear diretamente para o LB.

Agora perdemos a oportunidade de cancelar o DNAT para restaurar o IP de origem correto para o pacote de retorno (isso só pode acontecer no nó 1).

Eu reproduzi o problema. ACK que é um problema real. tcpdump mostra os pacotes sendo DNAT'ed para o pod IP: port (fora da máquina), com src intacto, mas tcpdump na máquina de destino não mostra nada. Não tenho certeza do que eu esperava que acontecesse mesmo se os pacotes chegassem lá.

Acho que a única solução é SNAT. A solução menos impactante seria _apenas_ pacotes SNAT do LB que são destinados fora do nó, mas a) Eu não tenho essa informação no kube-proxy (poderia obtê-lo com o custo do código) eb) uma vez que qualquer a política terá que considerar o caso SNAT de qualquer maneira, posso simplificar sempre SNATing pacotes LB externos. Isso é ruim para os mecanismos de política?

Eventualmente, os LBs serão inteligentes o suficiente para direcionar apenas hosts com pods e o tráfego permanecerá local, e então isso será discutível.

Porém, fica mais complicado. Temos o campo deprecatedPublicIPs, que provavelmente removeremos com alguns ajustes de comportamento. Acho que precisamos fazer o mesmo por eles. Mas fica ainda mais complicado - eu realmente não SEI todos os IPs públicos (por exemplo, a VM tem um IP externo NAT 1 para 1). Resposta fácil - sempre pacotes de porta de nó SNAT. O que pensar?

Vou testar mais amanhã.

@BenTheElder Você poderia tornar o pod netserver um serviço, para que o tráfego de perf <->
servidor está passando por meio do serviço VIP. Dessa forma, você não tem que fazer o
cálculos de amostragem / latência você mesmo ...

Na quarta-feira, 12 de agosto de 2015 às 21h20, Benjamin Elder [email protected]
escreveu:

Obrigado, vou olhar para isso.

Deste comentário
embora eu ache que queremos fazer algum tipo de latência de solicitação de serviço. Direito
agora estou tentando usar o contêiner nginx padrão como nó X e trabalhando em
ter um pod de teste atingindo-o repetidamente para que possamos construir um gráfico
nó Y.

No entanto, vou olhar para netperf / qperf e sempre podemos ter vários testes.
Eu gostaria de fazer esse gráfico primeiro, embora por discussão anterior com
@thockin

Em quinta-feira, 13 de agosto de 2015 às 12h02, Paul Tiplady [email protected]
escreveu:

@BenTheElder https://github.com/BenTheElder Acabei de fazer alguns razoavelmente
medições detalhadas de desempenho de rede no GCE - recomendo dar uma olhada em
netperf (qperf também fornece medições de latência).

netperf é uma ferramenta de desempenho cliente / servidor, empacotei o cliente e
o servidor no contêiner docker paultiplady / netserver: ubuntu.2.
há muitas opções no netperf, mas algo como girar dois
pods netserver e em execução

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

deve fornecer uma distribuição decente de estatísticas, incluindo latência e
Taxa de transferência.
Você pode executar o contêiner netserver usando docker run --net = host para fazer
node-> pod tests também.

O dockerfile para este contêiner é muito simples, posso dispará-lo se
você deseja estendê-lo para algo mais enxuto (por exemplo, um baseado em alpinelinux
recipiente para puxar mais rápido).

-
Responda a este e-mail diretamente ou visualize-o no GitHub
<
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130524576

.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130527558
.

Verdade. Acho que @thockin mencionou, eventualmente, querer um teste de latência e2e como
Nós vamos. Se o tempo permitir, haverá uma série de testes diferentes e nós
provavelmente terá que levar em conta gce vs AWS etc.
Em 13 de agosto de 2015, 13h47, "Paul Tiplady" [email protected] escreveu:

Você poderia tornar o pod netserver um serviço, para que o tráfego de perf <->
servidor está passando por meio do serviço VIP. Dessa forma, você não tem que fazer o
cálculos de amostragem / latência você mesmo ...

Na quarta-feira, 12 de agosto de 2015 às 21h20, Benjamin Elder [email protected]
escreveu:

Obrigado, vou olhar para isso.

De [este comentário] (

https://github.com/kubernetes/kubernetes/pull/9210#issuecomment-130154261)
embora eu ache que queremos fazer algum tipo de latência de solicitação de serviço. Direito
agora estou tentando usar o contêiner nginx padrão como nó X e funcionando
sobre
ter um pod de teste atingindo-o repetidamente para que possamos construir um gráfico
nó Y.

No entanto, vou olhar para netperf / qperf e sempre podemos ter vários testes.
Eu gostaria de fazer esse gráfico primeiro, embora por discussão anterior com
@thockin

Em quinta-feira, 13 de agosto de 2015 às 12h02, Paul Tiplady < notificaçõ[email protected]

escreveu:

@BenTheElder https://github.com/BenTheElder Acabei de fazer alguns
razoavelmente
medições detalhadas de desempenho de rede no GCE - recomendo dar uma olhada
no
netperf (qperf também fornece medições de latência).

netperf é uma ferramenta de desempenho cliente / servidor, empacotei tanto o cliente
e
o servidor no contêiner docker paultiplady / netserver: ubuntu.2.

há muitas opções no netperf, mas algo como girar dois
pods netserver e em execução

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

deve fornecer uma distribuição decente de estatísticas, incluindo latência e
Taxa de transferência.
Você pode executar o contêiner netserver usando docker run --net = host para fazer
node-> pod tests também.

O dockerfile para este contêiner é muito simples, posso dispará-lo
E se
você deseja estendê-lo para algo mais enxuto (por exemplo, um baseado em alpinelinux
recipiente para puxar mais rápido).

-
Responda a este e-mail diretamente ou visualize-o no GitHub
<

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

.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
<
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130527558

.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130776866
.

@Symmetric os testes

Eu gostaria de revisar o teste para uma carga "real" como um serviço da web mais tarde, possivelmente, mas depois de acertar os argumentos, ele está fornecendo dados muito bons até agora. Postarei os resultados mais tarde, quando terminar de limpar as coisas.

Fico feliz em saber que está funcionando para você - há um número surpreendente de
opções nessa ferramenta, mas ela se mostrou muito útil para meu trabalho de criação de perfil.
Definitivamente melhor que iperf ...

Em quinta-feira, 13 de agosto de 2015 às 14h32, Benjamin Elder [email protected]
escreveu:

@Symmetric https://github.com/Symmetric os testes
agradável. Obrigado pela sugestão :-)

Eu gostaria de revisar o teste para uma carga "real" como um serviço da web mais tarde
possivelmente, mas depois de acertar os argumentos, ele está fornecendo dados muito bons, então
longe. Postarei os resultados mais tarde, quando terminar de limpar as coisas.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -130850398
.

@thockin Acho que podemos viver com SNAT para tráfego LB. Meu pensamento atual é que você precisará especificar a política de acesso de um pod como uma das seguintes:

  • o padrão é 'permitir de [meu namespace]', caso em que os pacotes LB são descartados
  • 'permitir de [lista de namespaces]', ou 'permitir de [todos os namespaces no cluster]', novamente os pacotes LB são sempre descartados
  • 'permitir de todos', caso em que não nos importamos se é de um LB, outro nó ou qualquer outro lugar

Portanto, perder o IP de origem apenas para LBs não nos custa muito.

Se pudermos garantir que o LB está atingindo o nó certo para o pod de serviço, isso seria ótimo - nesse caso, não precisamos de SNAT e podemos executar um navio mais restrito ao colocar IPs LB na lista de permissões quando eles são provisionados em um serviço, e diminuindo o tráfego de outra forma.

Com relação a publicIPs, acho que eles terão as mesmas considerações que nodePort, e por isso precisaremos SNAT-los até que os LBs possam atingir os hosts corretos. O que está certo, de acordo com o acima, a menos que esteja faltando alguma forma de que eles sejam mais malignos do que nodePort ...

Como medida de segurança, pode ser muito útil incluir um sinalizador para proxy para MASQUERADE tudo (agindo muito perto de um proxy de espaço de usuário). Acho que não é muito difícil de fazer e é uma maneira muito boa de diagnosticar ou até mesmo retroceder em caso de problema (estou pensando em casos de vxlan).

-------- Message d'origine --------
De: Paul Tiplady [email protected]
Data: 14/08/2015 12:50 (GMT + 11: 00)
À: kubernetes / kubernetes [email protected]
Cc: Mikaël Cluseau [email protected]
Objet: Re: [kubernetes] use iptables para proxy em vez de espaço do usuário
(# 3760)

@thockin Acho que podemos viver com SNAT para tráfego LB. Meu pensamento atual é que você precisará especificar a política de acesso de um pod como uma das seguintes:

o padrão é 'permitir de [meu namespace]', caso em que os pacotes LB são descartados
'permitir de [lista de namespaces]', ou 'permitir de [todos os namespaces no cluster]', novamente os pacotes LB são sempre descartados
'permitir de todos', caso em que não nos importamos se é de um LB, outro nó ou qualquer outro lugar

Portanto, perder o IP de origem apenas para LBs não nos custa muito.

Se pudermos garantir que o LB está atingindo o nó certo para o pod de serviço, isso seria ótimo - nesse caso, não precisamos de SNAT e podemos executar um navio mais restrito ao colocar IPs LB na lista de permissões quando eles são provisionados em um serviço, e diminuindo o tráfego de outra forma.

Com relação a publicIPs, acho que eles terão as mesmas considerações que nodePort, e por isso precisaremos SNAT-los até que os LBs possam atingir os hosts corretos. O que está certo, de acordo com o acima, a menos que esteja faltando alguma forma de que eles sejam mais malignos do que nodePort ...

-
Responda a este e-mail diretamente ou visualize-o no GitHub.

@MikaelCluseau, essa não é uma má ideia - você poderia abrir uma nova edição especificamente sobre isso, para que eu não a perca?

Ainda TODO: consertar hairpin, e2e, habilitar por padrão

Oi Tim, desculpe por não ter voltado para você, mas nós tivemos uma bagunça para resolver aqui ... Vou pegar o grampo de cabelo no próximo sábado, eu acho.

Esta foi uma nota para mim - você estava planejando lidar com isso? :)

Sim, claro, como eu disse quando falamos sobre o teste e2e. Vou ajudar, o Kubernetes é de grande ajuda para mim, então é melhor eu dominá-lo o máximo possível, e o que é melhor do que corrigir bugs? :-) Sinta-se à vontade para sugerir qualquer coisa de maior prioridade, mas acho que o hairpin é muito bom para começar. Deve ocorrer no kubelet e ter um sinalizador para ativar (desativado por padrão no início). Vou tentar trabalhar 0,5 a 1 dia por semana.

AFAIK, a única parte que resta a fazer é torná-lo o padrão, o que pode acontecer (assumindo que não haja explosões) algum tempo após a v1.1 e isso tem algumas milhas nele.

Uau!

Na quinta-feira, 24 de setembro de 2015 às 11h21, Tim Hockin [email protected]
escreveu:

AFAIK, a única parte que resta a fazer é torná-lo o padrão, que pode
acontecer (assumindo que não haja explosões) algum tempo após a v1.1 e isso tem algumas milhas
nele.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -142960614
.

algum tempo depois da v1.1 e isso tem algumas milhas nele.

Ai. Estávamos realmente contando com isso para 1.1 ....
https://github.com/kubernetes/kubernetes/blob/master/docs/roadmap.md

@bgrieder você ainda pode habilitá-lo por meio de parâmetro.

Ele está IN, mas não ativado por padrão. Você pode optar por receber uma única anotação por
nó (e uma reinicialização kube-proxy)

Na quinta-feira, 24 de setembro de 2015 às 8h27, Bruno G. [email protected] escreveu:

algum tempo depois da v1.1 e isso tem algumas milhas nele.

Ai. Estávamos realmente contando com isso para 1.1 ....
https://github.com/kubernetes/kubernetes/blob/master/docs/roadmap.md

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -142962932
.

@thockin @bnprss ok, mas esperamos que a versão 1.1 seja executada no Google Container Engine após o lançamento. Eu me pergunto que tipo de flexibilidade teremos para 'optar por uma única anotação por nó'. Você poderia nos dar alguns detalhes sobre como será o processo ou nos indicar alguma documentação?

Depois de atualizado para 1.1:

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

Em seguida, execute SSH em cada nó e reinicie o kube-proxy (ou reinicie cada nó).

Se você quiser ser mais cauteloso, faça um ou dois nós e experimente :)

Eu marquei esse problema como "nota de lançamento" para que não nos esqueçamos de incluir esse loop mágico em nossa documentação 1.1.

@RichieEscarez

(Só queria passar por aqui e dizer que estamos usando o proxy iptables há uma semana e parece que está tudo bem!)

@thockin Deve ser fechado ou removido do marco 1.1?

Vou movê-lo para 1.2 apenas para a ativação padrão.

Desculpas por uma pergunta potencialmente idiota, mas em relação à preservação de IPs de clientes:

@thockin Eu vi em outra edição em 2 de setembro que "apenas o tráfego

Lançamos um novo cluster 1.2, aplicamos a anotação de nó, reiniciamos e ainda vemos 10.244.0.1 como o endereço de origem para todas as solicitações feitas a um pod executando HAProxy.

Neste ponto, estou apenas tentando descobrir se perdemos ou não uma configuração ou estou tentando alcançar algo que ainda não é possível - que é ver o endereço IP público do cliente real que está fazendo a solicitação de fora do cluster.

O padrão ainda usa o modo de espaço do usuário. Você deve definir uma anotação em
o nó (net.beta.kubernetes. io / proxy-mode = iptables) e reinicie o
proxy. Mas isso não vai expor IPs de clientes externos, apenas intra cluster
IPs.
Em 23 de outubro de 2015, às 17h09, "Ben Hundley" [email protected] escreveu:

Desculpas por uma pergunta potencialmente idiota, mas em relação à preservação
de IPs de cliente:

@thockin https://github.com/thockin Eu vi em outra edição em 2 de setembro
que "apenas o tráfego intra-cluster retém o IP do cliente" - isso ainda é
verdade para 1.2 alfa?

Lançamos um novo cluster 1.2, aplicamos a anotação de nó, reiniciou,
e ainda ver 10.244.0.1 como o endereço de origem para todas as solicitações feitas a um
pod executando o HAProxy.

Neste ponto, estou apenas tentando descobrir se perdemos ou não um
configuração ou estou tentando alcançar algo que ainda não é possível - que
está vendo o endereço IP público do cliente real que está fazendo a solicitação
de fora do cluster.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -150725513
.

Consigo manter o IP do cliente externo DNAT'ing tráfego externo + roteamento através de um proxy kube. Por exemplo, se sua rede de serviço for 10.42.0.0/16 e você tiver um kube-proxy altamente disponível no IP 10.10.1.1, você pode ter a seguinte regra de iptable:

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

e a seguinte rota:

10.42.0.0/16 via 10.10.1.1 dev edge 

O pod atrás vê então o IP real:

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

Você tem que ter o caminho de retorno correto do pacote, é claro.

Sim, se este DNAT for para um back-end fora da máquina, você forma um triângulo sem
SNAT. Este é o problema fundamental.

Na sexta-feira, 23 de outubro de 2015 às 20:12, Mikaël Cluseau [email protected]
escreveu:

Consigo manter o IP do cliente externo DNAT'ing tráfego externo +
roteamento por meio de um proxy kube. Por exemplo, se sua rede de serviço é
10.42.0.0/16 e você tem um kube-proxy altamente disponível no IP
10.10.1.1, você pode ter a seguinte regra de iptable:

-A PREROUTING -i public -p tcp -m tcp --dport 25 -j DNAT --para o destino 10.42.12.34

e a seguinte rota:

10.42.0.0/16 via 10.10.1.1 dev edge

O pod atrás vê então o IP real:

24 de outubro 02:41:39 email-0yr7n mail.info postfix / smtpd [469]: conectar-se a partir de zed.yyy.ru. [94.102.51.96]

Você tem que ter o caminho de retorno correto do pacote, é claro.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -150747217
.

Parece interessante, algum link? :-) Estou tentando encontrar uma maneira de ter certeza de que o pacote passará pela regra conntrack correta. Eu estava pensando em replicar o estado conntrack por meio do cluster.

Estou um pouco perdido com o que você está tentando alcançar.

A forma como o proxy iptables atual deve funcionar é que um pacote
chega a um nó, detectamos que não é gerado localmente, sinalizamos para
SNAT, escolha um back-end, encaminhe para o back-end com SNAT, o back-end responde
para nós, retiramos o SNAT, o DNAT e respondemos ao usuário externo.

Na sexta-feira, 23 de outubro de 2015 às 21h32, Mikaël Cluseau [email protected]
escreveu:

Parece interessante, algum link? :-) Estou tentando encontrar uma maneira de ter certeza de que
o pacote seguirá a regra certa conntrack. Eu estava pensando sobre
replicando o estado conntrack através do cluster.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -150753147
.

Oh, desculpe se não estou claro. Eu estava falando sobre o caso sem SNAT. Se todos os kube-proxy tiverem a mesma lista conntrack, qualquer um deles deverá ser capaz de cancelar o DNAT corretamente quando o contêiner responder ao cliente.

Não consegui ver um era sem replicação que não envolvesse HA para manter uma estrutura em forma de linha como esta:

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

Mas se uma coisa em forma de triângulo pode funcionar, deve abrir mais possibilidades.

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

Isso seria fofo, mas parece muito complicado

No domingo, 25 de outubro de 2015 às 23h20, Mikaël Cluseau [email protected]
escreveu:

Oh, desculpe se não estou claro. Eu estava falando sobre o caso sem SNAT. Se
todo kube-proxy tem a mesma lista conntrack, qualquer um deles deve ser capaz de
un-DNAT corretamente quando o contêiner responde ao cliente.

Não consegui ver um estava sem replicação que não envolvesse HA para manter um
estrutura em forma de linha como esta:

[cliente] ----- [proxy em HA] ------ [nó1]
`------- [node2]

Mas se uma coisa em forma de triângulo pode funcionar, deve abrir mais possibilidades.

[cliente] ----- [proxy1] ------ [nó1]
`------ [proxy2] ------ [node2]

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -151037663
.

A forma que tenho de explorar (não tenho e não gosto de perguntar antes de uma pesquisa adequada, mas já que o assunto agora está aberto ...) é o "Roteamento assimétrico de múltiplos caminhos" que você pode ver aqui: http: // conntrack-tools.netfilter.org/manual.html#sync-aa. E sim, isso seria muito bom :-)

A coisa mais simples que poderia funcionar ...

  1. O proxy1 recebe uma nova conexão por meio de um gancho iptables (acho que já vi isso em algum lugar), e seu LB a atribui ao nó do proxy2.
  2. proxy1 envia uma solicitação como "configurar uma entrada conntrack para {src-ip}: {src-port} -> {pod-ip}: {pod-port}"
  3. proxy2 recebe a solicitação, configura a entrada conntrack e ACK para proxy1
  4. O proxy1 permite que o pacote passe pela regra DNAT (que também coloca uma entrada conntrack no proxy1).
  5. quando o pod responde, o host do proxy2 unDNATs de acordo.
  6. quando o cliente envia outro pacote neste fluxo por meio do proxy1, a entrada conntrack também faz o DNAT correto.

Desta forma, a sobrecarga é de 2 pacotes por nova conexão, e rapidamente paga de volta evitando o roteamento extra un-SNAT + (caso contrário, o pacote terá que voltar pelo proxy1).

Não sou um cara de rede, então posso presumir muito, mas isso parece razoável.

No meu caso, pretendia estabelecer regras de firewall, por serviço NodePort.

Parece que posso adicionar regras simples ALLOW IP / DROP tudo o resto na cadeia INPUT, assim:

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 essas regras, o que eu estava imaginando era usar anotações nos serviços NodePort. As anotações manteriam IPs permitidos.

Já que posso esperar um pouco para que essas regras se apliquem, imaginei uma tarefa cron minuciosa em cada lacaio chegando e atualizando a cadeia INPUT do lacaio de todas as anotações de serviço.

Existe algo que pode causar um problema aqui? Eu sou insano?

@thockin tem uma visão melhor do que a minha, mas eu não usaria uma anotação para isso. Acho que a segurança é ortogonal e deve ser colocada em um sistema à parte, ou talvez um plugin de rede / proxy. Se você tiver o Kubernetes, terá o etcd, então você pode simplesmente armazenar um conjunto de regras em uma chave e atualizar com 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

Eu acho que você quer # 14505

Na segunda-feira, 26 de outubro de 2015 às 8:53 AM, Ben Hundley [email protected]
escreveu:

No meu caso, pretendia estabelecer regras de firewall, por serviço NodePort.

Parece que posso adicionar regras simples de ALLOW IP / DROP em todas as outras
a cadeia INPUT, assim:

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

Para aplicar essas regras, o que eu estava imaginando era usar anotações no
Serviços NodePort. As anotações manteriam IPs permitidos.

Como posso esperar um pouco para que essas regras se apliquem, imaginei um minucioso
tarefa cron em cada lacaio que passa e atualiza o INPUT do lacaio
cadeia de todas as anotações de serviço.

Existe algo que pode causar um problema aqui? Eu sou insano?

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -151181267
.

Essa foi a abordagem inicial, com grupos de segurança anexados a balanceadores de carga. Acabei de atingir o limite de ouvintes por interface de rede muito rápido no AWS e encontrei uma lógica complicada tentando espalhar regras de firewall em vários SGs e vários ELBs para um único cluster Kube.

Felizmente, encontramos uma solução melhor que não envolve mexer com o iptables.

Se você acabou de entrar, permita-me resumir. Todos os problemas relacionados à incapacidade de obter o ip do cliente foram incorporados a esse problema, porém a solução proposta (e implementada) não o resolve. Atualmente você não tem como acessar o ip do cliente. Ha.

@ shaylevi2 simplesmente não há uma boa maneira de obter o IP do cliente enquanto salta através de um LB de nuvem e para um nodePort. Assim que a nuvem LB for alcançada, irei direto para ela. Mas isso preserva o IP do cliente dentro do cluster

Mas isso preserva o IP do cliente dentro do cluster

Isso depende exatamente de como a rede de cluster está configurada; por exemplo, ele não funciona direito no OpenShift no momento, porque as regras do iptables não são executadas no tráfego OVS interno. Assim, os pacotes são DNAT'ed indo para o endpoint de serviço, mas como o IP de origem é interno do cluster, a resposta permanecerá dentro de OVS, portanto, não atinge iptables novamente, então o DNAT'ing não é revertido, para que o pod cliente não reconheça os pacotes. No momento, a solução mais simples para isso é mascarar totalmente os pacotes que vão para o terminal, forçando-os a serem devolvidos para fora do OVS novamente na saída. (Estou trabalhando para descobrir uma maneira de contornar isso.)

A OVS tem uma noção de VIP internamente? Você poderia simplesmente se livrar de
kube-proxy (cf opencontrail)

Na sexta-feira, 20 de novembro de 2015 às 7h09, Dan Winship [email protected]
escreveu:

Mas isso preserva o IP do cliente dentro do cluster

Isso depende exatamente de como a rede de cluster está configurada; por exemplo, não
funcionam bem no OpenShift no momento, porque as regras do iptables não são executadas
no tráfego OVS interno. Assim, os pacotes são DNAT'ed indo para o serviço
endpoint, mas como o IP de origem é interno do cluster, a resposta
ficar dentro do OVS, para que não acerte iptables novamente, então o DNAT'ing não
seja revertido, para que o pod cliente não reconheça os pacotes. No
momento, a solução mais simples para isso é disfarçar totalmente os pacotes
indo para o ponto de extremidade, forçando-os a serem expulsos do OVS novamente em
a saída. (Estou trabalhando para descobrir uma maneira de contornar isso.)

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -158426296
.

Havíamos conversado sobre fazer essencialmente o equivalente a pure-iptables-proxying inteiramente dentro do OVS, mas isso requer suporte a conntrack OVS, que requer um kernel muito recente, do qual não queremos depender ainda. No entanto, esse é provavelmente o plano de longo prazo.

(Por enquanto, parece que podemos fazê-lo funcionar adicionando um salto extra gratuito do OVS para pacotes com uma porta IP + de origem correspondente a um ponto de extremidade de serviço conhecido que vem de uma interface de contêiner; o nó então possivelmente removerá o DNAT e, em seguida, devolva-o ao OVS, onde pode ser devolvido ao pod do cliente corretamente.)

Espero escrever um documento sobre a abstração do Serviço VIP e torná-lo
claro que é uma abstração que pode ser substituída (e deve ser em alguns
casos).

Na segunda-feira, 23 de novembro de 2015 às 6h54, Dan Winship [email protected]
escreveu:

Tínhamos conversado sobre fazer essencialmente o equivalente do
pure-iptables-proxying inteiramente dentro de OVS, mas isso requer OVS conntrack
suporte, que requer um kernel muito recente, do qual não queremos depender
ainda. No entanto, esse é provavelmente o plano de longo prazo.

(Por enquanto, parece que podemos fazer funcionar adicionando um extra gratuito
pule fora do OVS para pacotes com uma porta IP + de origem correspondendo a um serviço conhecido
endpoint que vêm de uma interface de contêiner; o nó então
possivelmente removê-lo do DNAT e, em seguida, devolvê-lo ao OVS, onde pode obter
entregue de volta ao pod do cliente corretamente.)

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -158959014
.

Embora iptables / nftables resolvesse os casos de uso de balanceamento de carga TCP e UDP, eu pessoalmente acho que o IPVS https://github.com/kubernetes/kubernetes/issues/17470 seria um ajuste muito melhor porque foi desenvolvido especificamente para balanceamento de carga (leia-se: mudança / manutenção menos contínua para a equipe k8s), oferece um conjunto mais rico de algoritmos de balanceamento de carga, comprovou estabilidade em velocidades de taxa próxima à linha, amd também tem bibliotecas golang prontas para manipular regras.

@thockin , outros, de acordo com https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -150743158, eu fiz a anotação, mas como corretamente mencionado, o IP do cliente externo ainda não é visto pelo aplicativo em um contêiner .

Como fazer isso, ou seja, obter o IP do cliente externo? Em minha configuração, não há LB externo, o serviço é exposto como nodeport e o cliente está fazendo uma conexão TCP simples (não http / Websocket) com meu aplicativo em contêiner.

@ashishvyas qual versão do kube-proxy você está executando?

Estou executando a v1.1.3

Siga as instruções em https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -143280584 e https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -150743158, mas em vez de usar a anotação chamada net.beta.kubernetes.io/proxy-mode , use a anotação chamada 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

Você deve ver as instruções de log no início da inicialização do kube-proxy, como 'Encontrada anotação experimental' e 'Anotação permite proxy iptables'

A primeira versão em que https://github.com/kubernetes/kubernetes/commit/da9a9a94d804c5bfdf3cc86ee76a2bc1a2742d16 fez foi 1.1.4, então net.beta.kubernetes.io/proxy-mode não está funcionando para muitas pessoas. Você não é a primeira pessoa a topar com isso.

Devido à forma como o proxy funciona, perdemos o IP do cliente quando ele passa
uma porta de nó. Eu sei que isso não é ótimo. Estou muito pensando em como
consertar isso de forma adequada, mas a maioria se resume aos recursos do
balanceadores de carga (ou as outras maneiras pelas quais o tráfego chega a um nó, como
como DNS-RR)

Na quarta-feira, 13 de janeiro de 2016 às 10:25, Mike Danese [email protected]
escreveu:

Siga as instruções em # 3760 (comentário)
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -143280584
e # 3760 (comentário)
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -150743158
mas em vez de usar a anotação chamada
net.beta.kubernetes.io/proxy-mode, use a anotação chamada
net.experimental.kubernetes.io/proxy-mode.

para o nó em $ (kubectl get nodes -o name); Faz
kubectl annotate $ node net.experimental.kubernetes.io/proxy-mode=iptables;
feito

Você deve ver as instruções de log no início da inicialização do kube-proxy
como 'Encontrada anotação experimental' e 'Anotação permite proxy iptables'

O primeiro lançamento que da9a9a9
https://github.com/kubernetes/kubernetes/commit/da9a9a94d804c5bfdf3cc86ee76a2bc1a2742d16
feito em era 1.1.4. Você não é a primeira pessoa a topar com isso.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -171387997
.

@thockin , alguma solução alternativa para resolver temporariamente isso é possível agora? Se sim, eu recomendaria fornecer etapas detalhadas para mim e outras pessoas neste tópico ajudariam.

Não, não há uma solução alternativa real, atualmente. O problema se resume ao
fato de que cada kube-proxy pode escolher um back-end em um nó diferente.
O encaminhamento de tráfego com o IP do cliente original teria o outro nó
responder diretamente, o que obviamente não funcionará.

A "correção" é _apenas_ enviar tráfego para o Serviço S para nós que têm
pelo menos 1 back-end para S _and_ para enviar tráfego proporcional a quantos
backends que cada nó possui. O Kube-proxy pode então escolher back-ends locais
exclusivamente.

Considere 2 nós e 3 back-ends. Um nó termina necessariamente com 2
backends. Quaisquer que sejam as rotas, o tráfego deve enviar 2x mais para um nó do que para ele
faz para outro nó. Nós apenas não resolvemos esse problema ainda - nenhum de
os balanceadores de carga da nuvem suportam isso, então é meio especulativo e
portanto, é muito arriscado começar a trabalhar.

Na quarta-feira, 13 de janeiro de 2016 às 12h17, Ashish Vyas [email protected]
escreveu:

@thockin https://github.com/thockin , qualquer solução temporária para
resolver isso é possível agora? Se sim, eu recomendaria fornecer
etapas detalhadas para mim e outras pessoas neste tópico ajudariam.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -171420567
.

@mikedanese , não consigo encontrar 1.1.4 no gcr.io:

$ sudo docker pull gcr.io/google_containers/ hyperkube: v1.1.4
Extraindo repositório gcr.io/google_containers/hyperkube
Tag v1.1.4 não encontrada no repositório gcr.io/google_containers/hyperkube
$ sudo docker pull gcr.io/google_containers/ hyperkube: v1.1.3
v1.1.3: puxando de google_containers / hyperkube
Resumo: sha256: 004dde049951a4004d99e12846e1fc7274fdc5855752d50288e3be4748778ca2
Status: a imagem está atualizada para gcr.io/google_containers/ hyperkube: v1.1.3

@thockin Desculpas pela longa resposta, eu queria cobrir os dois métodos com os quais tentamos resolver isso para que outros pudessem entender os desafios que enfrentamos com ambos.

Como um pouco de contexto, nosso aplicativo principal é uma plataforma DNS inteligente de alto desempenho (ou seja, precisa de UDP e precisa fazer pelo menos 100k + solicitações / s por pod) e seu aplicativo de suporte em um proxy SNI que precisa ver os clientes reais Endereço IP (isso é um obstáculo para nós). Não queríamos usar abordagens de rede diferentes para aplicativos diferentes, então decidimos padronizar em um único método de rede para todos e optamos por usar IPVS pelos motivos que mencionei acima (desempenho / estabilidade / flexibilidade / construção de propósito SLB) , mas você provavelmente poderia hackear algo junto usando apenas iptables nas mesmas linhas também. Usamos vxlan (rápido, fácil, funciona entre sites), mas ambos os métodos também devem funcionar com GRE / VXLAN com OVS ou com rede de host padrão Camada 2 (assumindo que todos os hosts estejam na mesma rede L2).

Distribuímos o tráfego de entrada do usuário final usando uma mistura de anycast e DNS, dependendo dos requisitos de velocidade de failover ou o que funcionar melhor para o tipo específico de serviço, portanto, temos uma distribuição bastante uniforme do tráfego do usuário final entrando em nossos nós, mas o O problema, como você apontou, é obter uma distribuição uniforme do tráfego entre os pods, independentemente da localização do pod. O outro problema é garantir que os serviços que se comunicam com outros serviços tenham balanceamento de carga eficaz.

Tentamos dois modelos para resolver isso:

O primeiro método que tentamos foi 2 camadas de VIPs. VIPs externos (1 por serviço), que distribuem o tráfego entre os nós (com base na contagem de pods para esse serviço no nó), e VIPs internos (que são executados no nó com os pods), que distribuem a carga nos nós (normalmente uniformemente entre os pods). A limitação desse modelo era que os nós que executavam VIPs externos precisavam executar dois namespaces de rede diferentes ou executar seus próprios nós físicos. O bom do IPVS no modo DSR (retorno direto do servidor) é que ele não precisa ver o tráfego de retorno, o tráfego vai:

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

(1) IPVS (no modo DSR) no host com um VIP externo escolhe um _nó_ para enviar tráfego (um "servidor real" em termos de IPVS) e apenas altera o endereço MAC DST do pacote (ou seja, o pacote IP chega inalterado em nó k8s). Ele faz o balanceamento de carga entre os nós com base no número de pods que executam esse serviço no nó.
(2) IPVS (também no modo DSR) no nó k8s equilibra a carga do tráfego entre pods (via veths para o nó). As respostas dos contêineres (TCP e UDP) voltam diretamente para o consumidor do serviço.

A vantagem desse modelo é que ele era muito simples de usar e o conjunto de regras era muito fácil de gerenciar. A desvantagem desse modelo é que ele concentra todas as nossas solicitações de serviço (mas não as respostas) por meio de vários nós que executam os VIPs externos. Gostamos de "nada compartilhado", então, entre na versão 2:

O segundo modelo agora é divertido é uma única camada de VIPs com IPVS e configuração de iptables mais inteligentes.

Consumer >> Any node/local node >> (1) >> Container >> (any which way you want) >> Consumer
ou pode ir para outro nó:
Consumer >> Any node/local node >> (1) >> Remote Node >> (2) >> Container >> (any which way you want) >> Consumer

(1) O tráfego atinge o VIP primário, o tráfego é balanceado por carga em todos os pods no cluster.
(2) O tráfego atinge o VIP secundário, o tráfego tem balanceamento de carga apenas em todos os pods locais. Este VIP secundário é usado apenas para tráfego vindo de outros hosts na rede (é um VIP FWMARK). Marcamos o tráfego vindo de qualquer interface externa com FWMARK = 1234, e isso força o tráfego a ir para um conjunto de regras diferente, o que evita loops entre os nós.

O VIP principal tem uma lista de pods locais e hosts remotos com pods (com peso de 100 para cada pod local e 100 * número de pods para nós remotos). Portanto, por exemplo, se 3 pods estiverem sendo executados localmente no nodeA, e houver dois pods em execução no nodeB, o conjunto de regras no nodeA terá a seguinte aparência:

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

No entanto, no nodeB, a configuração do IPVS seria um pouco diferente porque tem apenas dois pods locais e três pods remotos no nodeA:

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

Outra maneira seria alternar os FWMARKs e usar iptables para FWMARK qualquer coisa nas interfaces veth + (correspondência curinga) e ter a correspondência FWMARK usada apenas para balanceamento de carga local.

Como não há NAT envolvido aqui, você precisa adicionar os IPs SVC_XXX_YYY no ambiente a um loopback ou interface fictícia ao iniciar cada pod, mas você provavelmente também pode alterar os VIPs IPVS para fazer DNAT também, não vejo por que isso não funcionaria.

O resultado final é a rede mais direta, sem a necessidade de centralizar o processamento / roteamento de solicitações, de modo que é escalonado muito melhor. A desvantagem são algumas habilidades extras ao criar as regras IPVS. Usamos um pequeno daemon (golang) para fazer tudo isso, mas eu consideraria escrever um módulo k8s para isso se eu tivesse tempo e houvesse interesse suficiente.

Estou examinando este problema tarde e provavelmente não li a trilha completa com detalhes suficientes, mas apenas no caso de ajudar: Se eu entendi a postagem de

@lxpollitt Correto, o IP de origem é mantido ao usar IPVS, no entanto, tenha em mente que com este método tivemos que fazer quase toda a rede nós mesmos, porque a configuração do IPVS não é suportada pelo kube-proxy. Você também pode manter o IP de origem com iptables, no entanto, você precisa de duas camadas de IPtables DNAT para que possa "desnaturar" o tráfego no caminho de volta

Do meu lado, com a flanela (no modo vxlan) gerenciando minha rede de contêineres, eu uso o kube-proxy (no modo iptables e não masquerading) + flanela em um namespace nos meus nós de roteamento. As solicitações externas são DNATed para serviço IPs e, em seguida, encaminhadas por meio do namespace com o kube-proxy. Eu não fiz o teste de cluster de roteador ativo / ativo, mas esta configuração me permite manter o IP externo. Eu menciono FWIW, mas entendo que não é a "rede mais direta".

Eu entendo que se o kube-proxy pudesse gerenciá-lo, seria bom, mas dadas suas necessidades específicas e especialmente o fato de que o balanceamento de carga já está fora do kube-proxy, não faria sentido codificar um gerenciador de regras de iptables do cliente observar o estado do cluster do kubernetes e configurar as regras para VIPs DNAT apenas para os pods do host em execução? Este também pode ser um modo para kube-proxy, como ... bem ... Não sou bom com nomes ... --proxy-mode = iptables-to-node-pods-only.

Obrigado pela redação detalhada. Sua solução é interessante, e eu gastei
uma boa quantidade de tempo hoje pensando nisso. Infelizmente você
cruzou em um território muito específico que não funciona em um sentido genérico.
Nuvens como a GCE não podem usar o modo de gateway IPVS por causa do roteamento
rede. Mesmo que o gateway funcione, ele não suporta o remapeamento de porta,
que o Kubernetes faz, por isso só se aplica se a porta de serviço == target
porta.

O desafio com o núcleo do kubernetes é encontrar maneiras de lidar com o seu
tipo de situação genericamente ou para sair do seu caminho e capacitá-lo a
configure você mesmo. Talvez pudéssemos fazer algo com o modo encap ipvs,
mas não sei as implicações de desempenho disso.

Na quinta-feira, 14 de janeiro de 2016 às 03h37, qoke [email protected] escreveu:

@thockin https://github.com/thockin Peço desculpas pela longa resposta, eu
queríamos cobrir os dois métodos com os quais tentamos resolver isso para que outros pudessem
compreender os desafios que enfrentamos com ambos.

Como um pouco de pano de fundo, nosso aplicativo principal é um desempenho muito alto
plataforma DNS inteligente (ou seja, precisa de UDP e precisa fazer pelo menos 100k +
solicitações / s por pod) e seu aplicativo de suporte em um proxy SNI
que precisa ver o endereço IP real do cliente (isto é um obstáculo para
nós). Não queríamos usar abordagens de rede diferentes para diferentes
aplicativos, então decidimos padronizar em um único método de rede para
todos, e optamos por usar IPVS pelas razões que mencionei acima
(desempenho / estabilidade / flexibilidade / finalidade de construção SLB), mas você poderia
provavelmente hackear algo junto usando apenas iptables ao longo dessas mesmas linhas
também. Usamos vxlan (rápido, fácil, funciona entre sites), mas ambos
métodos também devem funcionar com GRE / VXLAN com OVS ou com Camada 2 padrão
rede de host também (assumindo que seus hosts estão todos na mesma rede L2).

Distribuímos o tráfego de entrada do usuário final usando uma mistura de anycast e
DNS, dependendo dos requisitos de velocidade de failover ou o que funcionar melhor para
o tipo específico de serviço, por isso temos uma distribuição bastante uniforme de
o tráfego do usuário final entrando em nossos nós, mas o problema, como você apontou,
está obtendo uma distribuição uniforme do tráfego entre os pods, independentemente do
localização do pod. O outro problema é garantir que os serviços se comuniquem com outros
serviços são balanceados de forma eficaz.

Tentamos dois modelos para resolver isso:

O primeiro método que tentamos foi 2 camadas de VIPs. VIPs externos (1 por
serviço), que distribui o tráfego entre os nós (com base na contagem de pods para
esse serviço no nó) e, em seguida, VIPs internos (que são executados no nó
com os pods), que distribuem a carga nos nós (normalmente de maneira uniforme
entre vagens). A limitação deste modelo era que os nós rodando externos
VIPs precisavam executar dois namespaces de rede diferentes ou executar seus próprios
nós físicos. A coisa boa com IPVS no modo DSR (retorno direto do servidor)
modo é que ele não precisa ver o tráfego de retorno, o tráfego vai:

Consumidor >> (sobre L3) >> Nodo VIP externo >> (1) >> Nodo VIP interno >>
(2) >> Container >> (da maneira que você quiser) >> Consumidor

(1) IPVS (no modo DSR) no host com um VIP externo escolhe um _node_ para
enviar tráfego para (um "servidor real" em termos de IPVS), e apenas alterar DST MAC
endereço do pacote (ou seja, o pacote IP chega inalterado no nó k8s). Carrega
equilibra os nós com base no número de pods executando esse serviço em
o nó.
(2) IPVS (também no modo DSR) na carga do nó k8s equilibra o tráfego entre
pods (via veths para o nó). Respostas de contêineres (TCP e UDP) vão
diretamente de volta ao consumidor do serviço.

A vantagem deste modelo é que era muito simples de começar e
conjunto de regras era muito fácil de gerenciar. A desvantagem deste modelo é que
concentra todas as nossas solicitações de serviço (mas não as respostas) por meio de um
número de nós executando os VIPs externos. Nós gostamos de "nada compartilhado", então,
insira a versão 2:

O segundo modelo agora é divertido é uma única camada de VIPs com
configuração mais inteligente de IPVS e iptables.

Consumidor >> Qualquer nodo / nodo local >> (1) >> Container >> (qualquer maneira que você
quer) >> Consumidor
ou pode ir para outro nó:
Consumidor >> Qualquer nó / nó local >> (1) >> Nó Remoto >> (2) >> Contêiner

(da maneira que você quiser) >> Consumidor

(1) O tráfego atinge o VIP primário, o tráfego tem balanceamento de carga em todos os pods em
o cluster.
(2) O tráfego atinge o VIP secundário, o tráfego tem balanceamento de carga apenas em todos
vagens locais. Este VIP secundário é usado apenas para tráfego vindo de
outros hosts na rede (é um FWMARK VIP). Nós marcamos o tráfego entrando
qualquer interface externa com FWMARK = 1234, e isso força o tráfego a ir
para um conjunto de regras diferente, que evita loops entre os nós.

O VIP principal tem uma lista de pods locais e hosts remotos com pods (com
o peso sendo 100 para cada pod local e 100 * número de pods para
nós remotos). Por exemplo, se 3 pods estiverem sendo executados localmente no nodeA, e
há dois pods em execução no nodeB, o conjunto de regras no nodeA seria semelhante
isto:

Prot LocalAddress: Sinalizadores do agendador de porta
-> RemoteAddress: Port Forward Weight ActiveConn InActConn
TCP service.ip.address: 0 rr persistent 360
-> pod1.on.nodeA.ip: 80 Rota 100 0 0
-> pod2.on.nodeA.ip: 80 Rota 100 0 0
-> pod2.on.nodeA.ip: 80 Rota 100 0 0
-> interfaceip.of.nodeB: 80 Rota 200 0 0
FWM 1234 rr
-> pod1.on.nodeA.ip: 80 Rota 100 0 0
-> pod2.on.nodeA.ip: 80 Rota 100 0 0
-> pod3.on.nodeA.ip: 80 Rota 100 0 0

No entanto, no nodeB, a configuração do IPVS seria um pouco diferente porque
tem apenas dois pods locais e três pods remotos no nodeA:

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

Outra maneira seria alternar os FWMARKs e usar iptables para
FWMARK qualquer coisa nas interfaces veth + (correspondência curinga) e tem o FWMARK
match usado apenas para balanceamento de carga local.

O resultado final é a rede mais direta, sem necessidade de centralizar
processamento / roteamento de solicitações para escalonar muito melhor. A desvantagem é alguma
inteligência extra ao criar as regras IPVS.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -171619663
.

Acho que seria interessante tentar um modo iptables-to-node-pods-only ,
mas tem muita ondulação. O potencial de desequilíbrio é muito real e
pelo menos o controlador de serviço precisaria saber como programar o
balanceadores de carga externos.

Na quinta-feira, 14 de janeiro de 2016 às 15:59, Mikaël Cluseau [email protected]
escreveu:

Do meu lado, com a flanela (em modo vxlan) gerenciando minha rede de contêineres, eu
use kube-proxy (no modo iptables e não masquerading) + flanela em um
namespace em meus nós de roteamento. As solicitações externas são DNATed para serviço
IPs e, em seguida, encaminhados por meio do namespace com o kube-proxy. Eu não tenho
fiz testes de cluster de roteador ativo / ativo, mas esta configuração me permite manter
o IP externo. Eu mencionei FWIW, mas entendo que não é o "mais
rede direta ".

Eu entendo que se o kube-proxy pudesse gerenciá-lo, seria bom, mas
dadas suas necessidades específicas e especialmente o fato de que o balanceamento de carga
já está fora do kube-proxy, não faria sentido codificar um cliente
gerenciador de regras iptables observando o estado do cluster kubernetes e configurando
as regras para DNAT VIPs apenas para os pods do host em execução? Isso poderia
também ser um modo para kube-proxy, como ... bem ... eu não sou bom em
nomes ... --proxy-mode = iptables-to-node-pods-only.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -171821603
.

@thockin Você quer dizer se 2 réplicas estão no mesmo nó, por exemplo? Acho que poderíamos colocar o caso "programar os balanceadores de carga externos" fora do escopo do kube-proxy, pois ele tem várias instâncias e um programador de LB externo provavelmente deve estar em um modo "único mestre". Portanto, permitir o modo kube-proxy "iptables-to-node-pods-only" é apenas o primeiro de um processo de 2 etapas.

Acho que poderia tentar implementar algo assim amanhã: modo "iptables-to-node-pods-only" no kube-proxy, mais um contrib / ip-route-elb que manteria uma tabela de roteamento Linux com uma rota por serviço , com o peso certo para cada nó com base em quantos terminais o nó possui para um determinado serviço.

@thockin Você quer dizer que 2 réplicas estão no mesmo nó, por exemplo? Acho que poderíamos colocar o caso "programar o
balanceadores de carga externos "fora do escopo do kube-proxy, pois tem várias instâncias e um LB externo
o programador provavelmente deve estar em um modo "único mestre". Assim, permitindo o modo kube-proxy "iptables-to-node-
pods-only "é apenas a primeira de um processo de 2 etapas.

"Somente proxy para pods locais" deve ser a etapa 2 do processo. Passo 1
tem que mudar o controlador de serviço para enviar balanceadores de carga apenas
para nós que têm um ou mais back-ends para um determinado serviço. Essa etapa
por si só é PROVAVELMENTE razoável, mas exigirá muitos testes para
certifique-se de que acertamos. Acho que queremos fazer isso eventualmente,
qualquer forma.

Uma vez feito isso, podemos falar sobre como fazer as portas do nó preferirem o local
backends se possível, mas esta etapa requer muito mais cuidado
pensei .. Isso significa _sempre_ (ou seja, nunca escolha um controle remoto
backend se houver um local disponível) ou probabilístico? Devemos fazer
que através da mesma porta de nó (nós diferentes ficarão muito
diferentes comportamentos) ou alocamos uma porta diferente que é usada
se e somente se este nó tiver 1 ou mais back-ends? Como lidamos com o
problema de desequilíbrio?

Acho que poderia tentar implementar algo assim amanhã: modo "iptables-to-node-pods-only" no kube-proxy,
mais um contrib / ip-route-elb que manteria uma tabela de roteamento Linux com uma rota por serviço, com o peso certo
para cada nó com base em quantos terminais o nó possui para um determinado serviço.

Se o ELB suportar pesos, funcionará melhor em alguns aspectos do que
GCE, que não funciona. Tudo bem, só não achei que fosse compatível
pesos. Eu não acho que isso possa contribuir, embora - é uma bela
parte fundamental do sistema.

Em 16/01/2016 05:19, Tim Hockin escreveu:

"Somente proxy para pods locais" deve ser a etapa 2 do processo. Passo 1
tem que mudar o controlador de serviço para enviar balanceadores de carga apenas
para nós que têm um ou mais back-ends para um determinado serviço. Essa etapa
por si só é PROVAVELMENTE razoável, mas exigirá muitos testes para
certifique-se de que acertamos. Acho que queremos fazer isso eventualmente,
qualquer forma.

Isso faz sentido.

Feito isso, [...]

Então, vamos ver quando isso for feito :-)

Se o ELB suportar pesos, funcionará melhor em alguns aspectos do que
GCE, que não funciona. Tudo bem, só não achei que fosse compatível
pesos.

Já que é do manual e você provavelmente tem mais de 10x meu
experiência neste tipo de rede, devo ignorar completamente um problema.
O man ip-route diz o seguinte:

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

valor complexo com sua própria sintaxe semelhante às listas de argumentos de nível superior:

                          via [ FAMILY ] ADDRESS - is the nexthop 

roteador.

                          dev NAME - is the output device.

                          weight NUMBER - is a weight for this 

elemento de uma rota de caminhos múltiplos refletindo sua largura de banda relativa ou qualidade.

Eu não acho que isso possa contribuir, embora - é uma bela
parte fundamental do sistema.

Como o "E" significa "externo", senti que poderia começar aí,
pelo menos para obter algum código para apoiar as ideias.

Na sexta-feira, 15 de janeiro de 2016 às 14h55, Mikaël Cluseau
notificaçõ[email protected] escreveu:

Em 16/01/2016 05:19, Tim Hockin escreveu:

"Somente proxy para pods locais" deve ser a etapa 2 do processo. Passo 1
tem que mudar o controlador de serviço para enviar balanceadores de carga apenas
para nós que têm um ou mais back-ends para um determinado serviço. Essa etapa
por si só é PROVAVELMENTE razoável, mas exigirá muitos testes para
certifique-se de que acertamos. Acho que queremos fazer isso eventualmente,
qualquer forma.

Isso faz sentido.

Pensei mais nisso hoje, não acho que vai ser muito difícil.
Apenas meio duro.

Feito isso, [...]

Então, vamos ver quando isso for feito :-)

justo, eu só gosto de saber para onde vai um conjunto de mudanças :)

Se o ELB suportar pesos, funcionará melhor em alguns aspectos do que
GCE, que não funciona. Tudo bem, só não achei que fosse compatível
pesos.

Já que é do manual e você provavelmente tem mais de 10x meu
experiência neste tipo de rede, devo ignorar completamente um problema.
O man ip-route diz o seguinte:

nexthop NEXTHOP
o próximo passo de uma rota de caminhos múltiplos. NEXTHOP é um
valor complexo com sua própria sintaxe semelhante às listas de argumentos de nível superior:

via [FAMILY] ADDRESS - é o próximo
roteador.

dev NAME - é o dispositivo de saída.

peso NUMBER - é um peso para isso
elemento de uma rota de caminhos múltiplos refletindo sua largura de banda relativa ou qualidade.

Nós realmente não usamos a noção de roteamento IP do Linux. Nenhum dos
As implementações de LB que eu conheço usam, de qualquer maneira. GCE usa nuvem do Google
balanceador, que não tem pesos. Eu não sei é Amazon ELB
faz.

Eu não acho que isso possa contribuir, embora - é uma bela
parte fundamental do sistema.

Como o "E" significa "externo", senti que poderia começar aí,
pelo menos para obter algum código para apoiar as ideias.

Claro, podemos COMEÇAR em contrib :)

Além disso, se você quiser prosseguir, deve abrir 2 bugs, algo como:

1) balanceadores de carga para um serviço devem visar apenas nós que realmente
ter um back-end para esse serviço

2) para preservar o IP do cliente nos balanceadores de carga, o kube-proxy deve
sempre prefira back-end local, se presente (xref # 1)

e então explicar a intenção e direção

Na sexta-feira, 15 de janeiro de 2016 às 17:11, Tim Hockin [email protected] escreveu:

Na sexta-feira, 15 de janeiro de 2016 às 14h55, Mikaël Cluseau
notificaçõ[email protected] escreveu:

Em 16/01/2016 05:19, Tim Hockin escreveu:

"Somente proxy para pods locais" deve ser a etapa 2 do processo. Passo 1
tem que mudar o controlador de serviço para enviar balanceadores de carga apenas
para nós que têm um ou mais back-ends para um determinado serviço. Essa etapa
por si só é PROVAVELMENTE razoável, mas exigirá muitos testes para
certifique-se de que acertamos. Acho que queremos fazer isso eventualmente,
qualquer forma.

Isso faz sentido.

Pensei mais nisso hoje, não acho que vai ser muito difícil.
Apenas meio duro.

Feito isso, [...]

Então, vamos ver quando isso for feito :-)

justo, eu só gosto de saber para onde vai um conjunto de mudanças :)

Se o ELB suportar pesos, funcionará melhor em alguns aspectos do que
GCE, que não funciona. Tudo bem, só não achei que fosse compatível
pesos.

Já que é do manual e você provavelmente tem mais de 10x meu
experiência neste tipo de rede, devo ignorar completamente um problema.
O man ip-route diz o seguinte:

nexthop NEXTHOP
o próximo passo de uma rota de caminhos múltiplos. NEXTHOP é um
valor complexo com sua própria sintaxe semelhante às listas de argumentos de nível superior:

via [FAMILY] ADDRESS - é o próximo
roteador.

dev NAME - é o dispositivo de saída.

peso NUMBER - é um peso para isso
elemento de uma rota de caminhos múltiplos refletindo sua largura de banda relativa ou qualidade.

Nós realmente não usamos a noção de roteamento IP do Linux. Nenhum dos
As implementações de LB que eu conheço usam, de qualquer maneira. GCE usa nuvem do Google
balanceador, que não tem pesos. Eu não sei é Amazon ELB
faz.

Eu não acho que isso possa contribuir, embora - é uma bela
parte fundamental do sistema.

Como o "E" significa "externo", senti que poderia começar aí,
pelo menos para obter algum código para apoiar as ideias.

Claro, podemos COMEÇAR em contrib :)

O risco de um RP sem médicos é que ele está na direção errada. Isto é
muito mais fácil revisar algo como uma proposta. Vou dar uma olhada no seu
PR quando eu tiver uma chance, espero que logo.
Em 15 de janeiro de 2016, 19h02, "Mikaël Cluseau" [email protected] escreveu:

Posso abrir uma solicitação pull para (1) diretamente com este nome e alguns
explicações?

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172149777
.

Infelizmente, você cruzou um território muito específico que não funciona em um sentido genérico.
Nuvens como a GCE não podem usar o modo de gateway IPVS por causa da rede roteada. Mesmo que o gateway funcione, ele não é compatível com o remapeamento de porta, o que o Kubernetes oferece, portanto, só se aplica se a porta de serviço == porta de destino.

No lado do gateway, isso funciona bem em uma rede Camada 3 (usamos uma sobreposição) e, embora pudéssemos ter escapado sem uma rede sobreposta, nós a construímos desta forma porque queríamos que a abordagem que usamos fosse portátil e funcionasse em nuvens de terceiros (como GCE).

Corrigir a limitação com o modo DSR é que a porta de serviço == porta de destino, mas isso não é realmente um problema, a menos que você tenha dois aplicativos _no mesmo contêiner_ que precisam ser executados na mesma porta (passamos muito tempo pensando sobre isso, e assumindo a diretriz "1 aplicativo por contêiner", não conseguimos encontrar um único caso de uso para isso). Temos muitos contêineres, todos em execução nos mesmos nós, com serviços dentro deles, todos nas mesmas portas, e todos com balanceamento de carga perfeito. Se você _realmente_ precisa remapear as portas (eu gosto de entender as verdadeiras razões por trás disso), você pode usar o modo IPVS NAT em vez do modo "ROUTE".

O desafio com o núcleo do kubernetes é encontrar maneiras de lidar com seu tipo de situação genericamente ou sair do seu caminho e capacitá-lo para configurá-lo sozinho. Talvez pudéssemos fazer algo com o modo encap ipvs, mas não sei as implicações de desempenho disso.

O que fizemos é tão genérico quanto poderíamos torná-lo (funciona aqui, funciona na Amazon e tenho certeza de que funcionará no GCE quando tivermos a necessidade de expandir), com a única limitação do DSR sendo que o aplicativo a execução no pod / contêiner precisa ser executada na mesma porta do serviço que, após muita discussão interna, ninguém conseguiu encontrar um cenário em que isso seria uma limitação do ponto de vista da pilha de aplicativos E2E.

Dito isso, se você remover o DSR (modo IPVS Route) da equação e usar o "modo NAT" do IPVS, então as portas podem ser remapeadas e você ainda terá o benefício de obter recursos / desempenho / etc do IPVS. A única desvantagem é que o NAT adiciona alguma taxa de desempenho, mas (a) suporta UDP e (b) ainda é rápido em comparação com uma solução de espaço do usuário.

@brendandburns @thockin No início do tópico, você pediu alguns números de desempenho. Eu não chamaria isso de o conjunto de testes mais abrangente, mas espero que HTTP seja uma das cargas de trabalho mais comuns em contêineres, então aqui estão alguns números de banco de dados do Apache como ponto de partida:

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

O DNAT foi habilitado no IPVS para uma comparação justa com as outras duas soluções (isso também significa que a porta de serviço pode ser diferente da porta de serviço de destino). Nossas cargas de trabalho podem parecer um pouco incomuns para alguns, mas nossas metas de desempenho provavelmente não são muito diferentes de outras (ou seja, aperte o hardware para tudo o que puder).

Obrigado!

Não tenho certeza de onde vem a ideia de que o kube-proxy não usa UDP - ele
com certeza, embora talvez não perfeitamente (sem uma conexão, ele vem
até tempos limite).

Também vale a pena esclarecer o iptables (novo) kube-proxy vs o espaço do usuário
modo (legado).

No sábado, 16 de janeiro de 2016 às 21h45, qoke [email protected] escreveu:

@thockin https://github.com/thockin Anteriormente no tópico que você solicitou
alguns números de desempenho. Eu não chamaria este de o conjunto mais abrangente
de testes, mas espero que o HTTP seja uma das cargas de trabalho mais comuns em
contêineres, então aqui estão alguns números do banco de dados do Apache como ponto de partida:

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

DNAT foi habilitado no IPVS para uma comparação justa com as outras duas soluções
(isso também significa que a porta de serviço pode ser diferente da porta de serviço de destino). Nosso
cargas de trabalho podem parecer um pouco incomuns para alguns, mas nossas metas de desempenho
provavelmente não são diferentes dos outros (ou seja, espremer o hardware para todos
você pode ter).

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172293881
.

Boa ideia sobre o novo modo vs legado - anotado e atualizado.

Também no lado UDP das coisas, obrigado pelo esclarecimento; Eu não sabia que o UDP era totalmente compatível com o kube-proxy até agora. Quando tentamos o kube-proxy pela primeira vez com UDP, recebemos muitos e muitos travamentos. Não sei por que, mas aumentamos os tempos limite e ainda tínhamos problemas. Tivemos que encontrar uma solução rápida, então acabamos trabalhando com o IPVS em vez de depurá-la. Na época, funcionava apenas para cargas de trabalho de pacotes por segundo muito baixas (abaixo de 1k pps), mas não testamos novamente recentemente.

O principal problema com o iptables e qualquer serviço UDP de alta taxa é o preenchimento das tabelas netfilter conntrack. Mesmo que você aumente o tamanho do conntrack para 1 milhão, alguns usuários finais infectados por malware irão atacar ou tentar usá-lo para um ataque de amplificação de DNS e então sua tabela conntrack será preenchida novamente. De modo geral, a melhor prática para servidores DNS (ou quaisquer serviços UDP de alta taxa) é desabilitar conntrack (usando -j NOTRACK na tabela bruta) e, se você desabilitar conntrack, iptables NAT e coisas com estado (-m state) quebras.

Além do repositório GIT, onde seria o melhor lugar para procurar antes de tentar criar um módulo / pacote "k8s.io/kubernetes/pkg/proxy/ipvs"? ou é melhor deixar isso para alguém que conhece melhor a base de código?

Além disso, se desejar executar qualquer benchmark específico, me avise e verei o que posso fazer.

Em 17/01/2016, 20h50, qoke escreveu:

Além do repositório GIT, onde seria o melhor lugar para procurar antes
está tentando criar um módulo / pacote "k8s.io/kubernetes/pkg/proxy/ipvs"?

Eu acredito que você pode começar no contrib também.

FWIW ... Eu usei listas de relógios e lojas undelta para fazer um independente
binay reagindo ao estado do cluster em
https://github.com/kubernetes/kubernetes/pull/19755. Se a informação
no
https://github.com/kubernetes/kubernetes/pull/19755/files#diff -0becc97ac222c3f2838fbfe8446d5375R26
é o suficiente, você só deve ter que mudar a chamada algumas linhas abaixo
(https://github.com/kubernetes/kubernetes/pull/19755/files#diff-0becc97ac222c3f2838fbfe8446d5375R44).

Observe que só apóio serviços clusterIP nesta PoC.

Infelizmente, você cruzou um território muito específico que não funciona em um sentido genérico.
Nuvens como a GCE não podem usar o modo de gateway IPVS por causa da rede roteada. Mesmo que o gateway funcione, ele não
suporta remapeamento de porta, que o Kubernetes faz, portanto, só se aplica se a porta de serviço == porta de destino.

No lado do gateway, isso funciona bem em uma rede de Camada 3 (usamos uma sobreposição), e mesmo que pudéssemos ter escapado
sem uma rede de sobreposição, nós a construímos dessa forma porque queríamos que a abordagem que usamos fosse portátil e funcionasse em terceiros
nuvens (como GCE).

Não tenho certeza de como isso pode funcionar. Rotas estáticas no nível da máquina não funcionam
no GCE. Talvez esteja faltando alguma técnica que você aplicou. eu
admito livremente que NÃO sou um especialista nisso :)

A limitação correta é que a porta de serviço == porta de destino, mas isso não é realmente um problema, a menos que você tenha dois aplicativos no
mesmo contêiner que precisa ser executado na mesma porta (passamos muito tempo pensando sobre isso e assumindo o "1 aplicativo
por contêiner ", não foi possível encontrar um único caso de uso para isso). Temos muitos contêineres em execução nos mesmos nós
com serviços dentro deles, todos nas mesmas portas, e todos com balanceamento de carga bem. Em suma, a abordagem que usamos não impede você
de executar vários serviços nas mesmas portas no mesmo nó.

Também se aplica se você tiver back-ends que estão mudando de versão (por exemplo,
transição entre etcd1 e etcd2) ou qualquer outra situação onde
a porta de back-end só precisa ser diferente. O problema é que
O Kubernetes permite que isso seja expresso, por isso precisamos ter certeza de que as pessoas
pode realmente usá-lo (ou então descontinuá-lo e EOL o recurso que
parece improvável).

O desafio com o núcleo do kubernetes é encontrar maneiras de lidar com seu tipo de situação genericamente ou sair do seu caminho
e capacitá-lo a configurá-lo sozinho. Talvez pudéssemos fazer algo com o modo encap ipvs, mas não sei o desempenho
implicações disso.

O que fizemos é o mais genérico que poderíamos fazer (funciona aqui, funciona na Amazon e tenho certeza de que funcionará na
GCE quando temos a necessidade de expandir), com a única limitação sendo que o aplicativo em execução no pod / contêiner precisa> ser executado na mesma porta do serviço que, após muita discussão interna, ninguém conseguiu encontrar um cenário onde
isso seria um fator limitante de uma perspectiva de pilha de aplicativos E2E.

Eu realmente quero entender como. Você tem algo mais passo a passo?

Também no lado UDP das coisas, obrigado pelo esclarecimento; Eu não sabia que o UDP era totalmente compatível com o kube-proxy até agora.
Quando tentamos o kube-proxy pela primeira vez com UDP, recebemos muitos e muitos travamentos. Não sei por que, mas aumentamos os tempos limite e
ainda tinha problemas. Tivemos que encontrar uma solução rápida, então acabamos trabalhando com o IPVS em vez de depurá-la. No
vez que funcionou apenas para cargas de trabalho de pacotes por segundo bastante baixas (abaixo de 1k pps), mas não testamos novamente recentemente.

O principal problema com o iptables e qualquer serviço UDP de alta taxa é o preenchimento das tabelas netfilter conntrack. Mesmo se você aumentar o
conntrack size para 1 milhão, então algum usuário final infectado com malware DDoS você ou tenta usá-lo para uma amplificação de DNS
ataque e, em seguida, sua tabela conntrack apenas se enche novamente. De um modo geral, a prática recomendada para servidores DNS (ou qualquer
Serviços UDP) é desabilitar conntrack (usando -j NOTRACK na tabela bruta), e se você desabilitar conntrack, iptables NAT e
stateful stuff (-m state) quebra.

Sim, NAT para UDP é realmente lamentável. Encontrando um non-conntrack
solução seria ótimo, mas tem que se aplicar a todos
ambientes ou ser parametrizado por plataforma (o que é difícil em seu próprio
caminho).

Além do repositório GIT, onde seria o melhor lugar para olhar antes de tentar criar um
Módulo / pacote "k8s.io/kubernetes/pkg/proxy/ipvs"? ou é melhor deixar isso para alguém que conhece melhor a base de código?

Abri um problema no github sobre IPVS, mas estava usando masquerade (NAT)
modo porque não consegui fazê-lo funcionar no GCE sem (e por causa de
o recurso de remapeamento de porta). Se o remapeamento de porta desencadeasse um menos ideal
modo de equilíbrio, provavelmente poderia conviver com isso e apenas documentá-lo
Como tal.

Devíamos mover este convo para lá - ele vai se perder aqui.

Em 18/01/2016, 12:34, Tim Hockin escreveu:

Sim, NAT para UDP é realmente lamentável. Encontrando um non-conntrack
solução seria ótimo, mas tem que se aplicar a todos
ambientes ou ser parametrizado por plataforma (o que é difícil em seu próprio
caminho).

poderia funcionar o NAT sem estado para o caso em que um par (pod, porta) tem
mais um serviço (muitos pods para um serviço)?

Isso ficaria assim:

{from: clientIP: clientPort, to: externalIP: externalPort} --- [proxy seleciona um pod aleatório] ---> {from: clientIP: clientPort, to: podIP: targetPort} ---> [roteado pelo host certo ...]

No caminho de volta, o firewall terá uma regra dizendo um pacote {de:
podIP: targetPort , to: any} deve ser SNATed para {from:
e xternalIP: externalPort , para: inalterado}.

Para declarar no dialeto 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

Não vejo onde isso não funciona quando o pacote vem de fora
o cluster.

A maneira como os serviços são expressos no Kubernetes permite que um único pod seja
liderado por qualquer número de serviços, então isso se divide - não sabemos o que
para SNAT para.

No domingo, 17 de janeiro de 2016 às 18:13, Mikaël Cluseau [email protected]
escreveu:

Em 18/01/2016, 12:34, Tim Hockin escreveu:

Sim, NAT para UDP é realmente lamentável. Encontrando um non-conntrack
solução seria ótimo, mas tem que se aplicar a todos
ambientes ou ser parametrizado por plataforma (o que é difícil em seu próprio
caminho).

poderia funcionar o NAT sem estado para o caso em que um par (pod, porta) tem
mais um serviço (muitos pods para um serviço)?

Isso ficaria assim:

{from: clientIP: clientPort, to: externalIP: externalPort} --- [seleção de proxy
um pod aleatório] ---> {from: clientIP: clientPort, to: podIP: targetPort} --->
[encaminhado através do host certo ...]

No caminho de volta, o firewall terá uma regra dizendo um pacote {de:
podIP: targetPort , to: any} deve ser SNATed para {from:
e xternalIP: externalPort , para: inalterado}.

Para declarar no dialeto 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

Não vejo onde isso não funciona quando o pacote vem de fora
o cluster.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172408290
.

Em 18/01/2016 15:31, Tim Hockin escreveu:

A maneira como os serviços são expressos no Kubernetes permite um único pod
ser estar
liderado por qualquer número de serviços, então isso se divide - nós não sabemos
o que
para SNAT para.

É por isso que limitei o caso a muitos para um (minha primeira frase :-)).
Estou apenas tentando traçar uma linha em torno do que pode ser feito ou não.

Claro, só tenho o infeliz trabalho de apontar por que não é um
solução geral suficiente :(

No domingo, 17 de janeiro de 2016 às 20:34, Mikaël Cluseau [email protected]
escreveu:

Em 18/01/2016 15:31, Tim Hockin escreveu:

A maneira como os serviços são expressos no Kubernetes permite um único pod
ser estar
liderado por qualquer número de serviços, então isso se divide - nós não sabemos
o que
para SNAT para.

É por isso que limitei o caso a muitos para um (minha primeira frase :-)).
Estou apenas tentando traçar uma linha em torno do que pode ser feito ou não.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172421828
.

Em 18/01/2016 15:46, Tim Hockin escreveu:

Claro, só tenho o infeliz trabalho de apontar por que não é um
solução geral suficiente :(

Sim ... mas é um FAQ. Também poderíamos colocar, em algum lugar, "if len (serviços)
== 1 {implementar sem estado} else {implementar com estado} ". Mas isso pode
parece uma bagunça para os novatos. Eu também poderia ser um contrib / elbs / alguma coisa ...

Não é nem mesmo algo que rastreamos atualmente (o número de serviços que
frente a um determinado pod). Poderíamos, suponho. Eu não sou contra isso (mesmo que seja
parece nicho). Parece uma mudança substancial a ser feita por ter
muitas advertências. Eu gostaria de pensar em respostas melhores, ainda.

No domingo, 17 de janeiro de 2016 às 20:51, Mikaël Cluseau [email protected]
escreveu:

Em 18/01/2016 15:46, Tim Hockin escreveu:

Claro, só tenho o infeliz trabalho de apontar por que não é um
solução geral suficiente :(

Sim ... mas é um FAQ. Também poderíamos colocar, em algum lugar, "if len (serviços)
== 1 {implementar sem estado} else {implementar com estado} ". Mas isso pode
parece uma bagunça para os novatos. Eu também poderia ser um
contrib / elbs / alguma coisa ...

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172425404
.

Em 18/01/2016 16h07, Tim Hockin escreveu:

Não é nem mesmo algo que rastreamos atualmente (o número de serviços que
frente a um determinado pod). Poderíamos, suponho. Eu não sou contra isso (mesmo que seja
parece nicho). Parece uma mudança substancial a ser feita por ter
muitas advertências. Eu gostaria de pensar em respostas melhores, ainda.

Eu concordo, mas não tenho nenhuma ideia melhor por agora :-(

Mesmo um SDN criado para esse fim precisaria rastrear algo, suponho. Pode ser
soluções baseadas em rótulos como MPLS ..?

Em 18/01/2016 16:18, Mikaël Cluseau escreveu:

Mesmo um SDN criado para esse fim precisaria rastrear algo, suponho.
Talvez soluções baseadas em rótulos como MPLS ..?

Na ideia de rotular as coisas ... se atribuirmos um IP por serviço + um
IP por endpoint (serviço + par de pod) e adicione esses IPs de endpoint ao
pods, ele deve funcionar totalmente sem estado:

`` `` ``

  • Externo para o host: {from: clientIP: clientPort, to: externalIP: servicePort} ----- [ELB
    seleciona um ponto de extremidade] --------> {from: clientIP: clientPort, to:
    endpointServiceIP: podPort} -> rota para o host
  • Host para pod: {from: clientIP: clientPort, to: endpointServiceIP: podPort} - [padrão
    roteamento para contêineres] -> {from: clientIP: clientPort , to:
    endpoint ServiceIP: podPort }

  • Pod para hospedar: {from: endpointServiceIP: podPort, to: clientIP: clientPort}
    -------- [roteamento padrão para roteadores] -----> {de:
    endpointServiceIP: podPort, to: clientIP: clientPort} - Host para externo: {from: endpointServiceIP: podPort, to: clientIP: clientPort} -------- [ELB
    SNATs back] ------------------> {from: clientIP: clientPort , to:
    e xternalIP: servicePort } `` `

Acho que podemos fazer isso funcionar para clusterIPs também.
`` `` ``

Não consigo fazer isso funcionar no GCE e não tenho certeza sobre a AWS - há um
número limitado de rotas estáticas disponíveis.

Eu me pergunto se eu poderia fazer isso pegando carona em 2 intervalos de IP juntos em um único
rota. É uma grande quantidade de IPs para gastar, mas acho que isso só importa para UDP.
Vou ter que experimentar.

Edit: Eu tentei e não consegui fazer funcionar, mas estou perdendo algo.
Teremos que adicionar / remover IPs em contêineres em resposta aos serviços que chegam
e continuando, mas não consegui fazer IPs "extras" em um contêiner funcionar (poderia
ping, mas não TCP ou UDP, não sei por quê).

Vou ter que tentar novamente algum dia.

No domingo, 17 de janeiro de 2016 às 22h22, Mikaël Cluseau [email protected]
escreveu:

Em 18/01/2016 16:18, Mikaël Cluseau escreveu:

Mesmo um SDN criado para esse fim precisaria rastrear algo, suponho.
Talvez soluções baseadas em rótulos como MPLS ..?

Na ideia de rotular as coisas ... se atribuirmos um IP por serviço + um
IP por endpoint (serviço + par de pod) e adicione esses IPs de endpoint ao
pods, ele deve funcionar totalmente sem estado:

`` `` ``

  • Externo para o host: {from: clientIP: clientPort, to: externalIP: servicePort}
    ----- [ELB
    seleciona um ponto de extremidade] --------> {from: clientIP: clientPort, to:
    endpointServiceIP: podPort} -> rota para o host
  • Host para pod: {from: clientIP: clientPort, to: endpointServiceIP: podPort}
    --[padrão
    roteamento para contêineres] -> {from: clientIP: clientPort , to:
    endpoint ServiceIP: podPort }

  • Pod para hospedar: {from: endpointServiceIP: podPort, to: clientIP: clientPort}
    -------- [roteamento padrão para roteadores] -----> {de:
    endpointServiceIP: podPort, to: clientIP: clientPort} - Host para
    external: {from: endpointServiceIP: podPort, to: clientIP: clientPort}
    -------- [ELB
    SNATs back] ------------------> {from: clientIP: clientPort , to:
    e xternalIP: servicePort } `` `

Acho que podemos fazer isso funcionar para clusterIPs também.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment-172438133
.

`` `` ``

Estou tentando do meu lado conseguir algo (com redes puras no meu host local
por enquanto).

Estou tentando uma abordagem em que afetam os intervalos de IP de serviço para hosts para
reduza o número de entradas de roteamento:

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)

Sem ping ATM (pacotes não passando pela cadeia PREROUTING ...), e
precisa dormir. Mais sobre isso amanhã;)

Em 18/01/2016 18:28, Tim Hockin escreveu:

Não consigo fazer isso funcionar no GCE e não tenho certeza sobre a AWS - há um
número limitado de rotas estáticas disponíveis.

Eu me pergunto se eu poderia fazer isso pegando carona em 2 intervalos de IP juntos em um único
rota. É uma grande quantidade de IPs para gastar, mas acho que isso só importa para UDP.
Vou ter que experimentar.

Edit: Eu tentei e não consegui fazer funcionar, mas estou perdendo algo.
Teremos que adicionar / remover IPs em contêineres em resposta aos serviços que chegam
e continuando, mas não consegui fazer IPs "extras" em um contêiner funcionar (poderia
ping, mas não TCP ou UDP, não sei por quê).

Vou ter que tentar novamente algum dia.

Avancei um pouco mais, mas algo que deveria ter previsto aconteceu.

Eu configurei um pod com 10.244.2.8/25 como interface principal e 10.244.2.250/25
como sua interface "em serviço". Eu esperava poder enviar UDP para
.250 e detectar respostas, para SNAT-los. Mas é claro, se o cliente for
não no mesmo / 25 (o que não pode ser), a rota padrão entra em ação, que
vem do endereço .8. tcpdump confirma que as respostas vêm de .8
ao usar UDP.

Estou novamente em um lugar onde não tenho certeza de como fazer funcionar. pensará
mais sobre isso.

Na segunda-feira, 18 de janeiro de 2016 às 2h59, Mikaël Cluseau [email protected]
escreveu:

Estou tentando do meu lado conseguir algo (com redes puras no meu host local
por enquanto).

Estou tentando uma abordagem em que afetam os intervalos de IP de serviço para hosts para
reduza o número de entradas de roteamento:

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)

Sem ping ATM (pacotes não passando pela cadeia PREROUTING ...), e
precisa dormir. Mais sobre isso amanhã;)

Em 18/01/2016 18:28, Tim Hockin escreveu:

Não consigo fazer isso funcionar no GCE e não tenho certeza sobre a AWS - há um
número limitado de rotas estáticas disponíveis.

Eu me pergunto se eu poderia fazer isso pegando carona em 2 intervalos de IP juntos em um
solteiro
rota. É uma grande quantidade de IPs para gastar, mas acho que isso só importa para UDP.
Vou ter que experimentar.

Edit: Eu tentei e não consegui fazer funcionar, mas estou perdendo
algo.
Teremos que adicionar / remover IPs em contêineres em resposta aos serviços que chegam
e continuando, mas não consegui fazer IPs "extras" em um contêiner funcionar (poderia
ping, mas não TCP ou UDP, não sei por quê).

Vou ter que tentar novamente algum dia.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172497456
.

Percebo (via Abhishek) que mesmo que funcione, AINDA temos que
trilha flui em algum lugar, então não é sem estado no final de qualquer maneira.

Na segunda-feira, 18 de janeiro de 2016 às 21h50, Tim Hockin [email protected] escreveu:

Avancei um pouco mais, mas algo que deveria ter previsto aconteceu.

Eu configurei um pod com 10.244.2.8/25 como sua interface principal e
10.244.2.250/25 como sua interface "em serviço". Eu estava esperando que eu
poderia enviar UDP para .250 e detectar respostas, para SNAT-los. Mas é claro,
se o cliente não estiver no mesmo / 25 (o que não pode ser) o default
a rota entra em ação, que vem do endereço .8. tcpdump confirma que
as respostas vêm de 0,8 ao usar UDP.

Estou novamente em um lugar onde não tenho certeza de como fazer funcionar. pensará
mais sobre isso.

Na segunda-feira, 18 de janeiro de 2016 às 2h59, Mikaël Cluseau [email protected]
escreveu:

Estou tentando do meu lado conseguir algo (com redes puras no meu host local
por enquanto).

Estou tentando uma abordagem em que afetam os intervalos de IP de serviço para hosts para
reduza o número de entradas de roteamento:

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)

Sem ping ATM (pacotes não passando pela cadeia PREROUTING ...), e
precisa dormir. Mais sobre isso amanhã;)

Em 18/01/2016 18:28, Tim Hockin escreveu:

Não consigo fazer isso funcionar no GCE e não tenho certeza sobre a AWS - há um
número limitado de rotas estáticas disponíveis.

Eu me pergunto se eu poderia fazer isso pegando carona em 2 intervalos de IP juntos em um
solteiro
rota. É uma grande quantidade de IPs para gastar, mas acho que isso só importa para UDP.
Vou ter que experimentar.

Edit: Eu tentei e não consegui fazer funcionar, mas estou perdendo
algo.
Teremos que adicionar / remover IPs em contêineres em resposta aos serviços
chegando
e continuando, mas não consegui fazer IPs "extras" em um contêiner funcionar (
poderia
ping, mas não TCP ou UDP, não sei por quê).

Vou ter que tentar novamente algum dia.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -172497456
.

Isso é lamentável :-( não sei por que, a propósito. Vou tentar algo com MPLS então, quero aprender de qualquer maneira.

Se você tiver 2 back-ends para o serviço e quiser enviar mais de um
pacote, você precisa rastrear os fluxos de alguma forma, não é? Ou você está
presumindo que é seguro pulverizar pacotes em back-ends diferentes?

Na quarta-feira, 20 de janeiro de 2016 às 12h24, Mikaël Cluseau [email protected]
escreveu:

Isso é lamentável :-( não sei por que, a propósito. Vou tentar algo com
MPLS então, quero aprender de qualquer maneira.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -173348973
.

Eu meio que presumi que, para cargas de trabalho UDP, sim. Também pode ser opcional ficar sem estado, mesmo para UDP. @qoke algum comentário sobre isso?

Além disso, poderíamos usar coisas como hashing de IP do cliente para tornar o fluxo mais estável enquanto ainda está equilibrado (não sei se podemos chamar isso de "algum tipo de rastreamento" :-)).

@MikaelCluseau , usamos o comportamento IPVS padrão, que faz alguma "aderência" UDP muito leve ...

Para agendar datagramas UDP, o balanceador de carga IPVS registra o agendamento do datagrama UDP com tempo limite configurável e o tempo limite UDP padrão é 300 segundos. Antes do tempo limite da conexão UDP, todos os datagramas UDP do mesmo soquete (protocolo, endereço IP e porta) serão direcionados ao mesmo servidor.

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

Claro, isso só funciona se você tiver muitos clientes conversando com um único serviço ou um único cliente com portas de origem variadas. Se você tiver um único cliente de alto volume, todos enviando tráfego da mesma porta de origem, e quiser balancear a carga em vários back-ends, talvez prefira usar uma abordagem stateless / spray-and-pray.

Balanceamos a carga de muito tráfego DNS e RADIUS - DNS normalmente cai na primeira categoria (muitos clientes ou clientes com muitas portas de origem), e RADIUS normalmente cai na categoria posterior (poucos clientes, muitos pacotes, todos do mesmo IP / porta). Em vez de usar um hash sem estado para RADIUS, decidimos randomizar as portas de origem para obter uma distribuição uniforme.

Depois de ler todo o tópico, ainda não consigo descobrir se a ativação do modo iptables para kube-proxy deve resolver o problema de IPs externos sendo ocultados (# 10921) ou não. Nós habilitamos o modo iptables com v1.1 como sugerido aqui, mas ainda estamos vendo os IPs do cluster, não os reais dos usuários.

Nosso cluster está no GCE e só precisamos de um balanceador de carga com suporte HTTPS antes de entrar em operação. Como o GCE não oferece suporte a v.1.2 alpha, não podemos usar o novo Ingress (que AFAIK oferece suporte a balanceadores de carga HTTPS), portanto, o balanceador de carga de rede é nossa única opção. Mas obviamente não podemos ir ao vivo sem a capacidade de registrar ips reais de nossos usuários.

Agradecemos alguns esclarecimentos para novos usuários sobre isso. O suporte a HTTPS é obrigatório para muitos de nós. Obrigado!

Eu tenho usado o proxy iptables ligado e desligado há algum tempo e posso confirmar que os IPs externos dos clientes ainda estão ocultos / mostram IPs do cluster.

Conseguimos contornar isso até agora executando nosso proxy HTTP / HTTPS de front-end em modo de rede host para que ele veja o endereço IP de origem.

@maclof obrigado pelo feedback. Você poderia compartilhar mais informações sobre como sua solução alternativa? O que você quer dizer com HTTP / HTTPS rodando na rede host?

@javiercr , usamos uma especificação de pod parecida com esta: http://pastie.org/private/zpdelblsob654zif7xus5g

Usar a rede host significa que o pod é executado na rede das máquinas host, em vez de receber um IP de cluster.

Isso significa que quando nosso servidor nginx se conecta à porta 80/443, ele escuta em um IP de host e vê os endereços IP de origem.

Estou usando o kubernetes 1.1, /opt/bin/kube-proxy ... --proxy-mode=iptables --masquerade-all=false e roteando a rede IP do cluser por meio de um host com um proxy kube. Nesta configuração, meus serviços estão vendo o IP externo. Eu uso um namespace de rede altamente disponível que tem um IP externo e uma rota para os hosts:

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

Aprendi muito lendo este tópico!

Como um FYI, este documento afirma que o AWS ELB usa round-robin para conexões TCP e menos conexões para http / https: http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/how-elb-works.html# solicitação -roteamento

Concordo que focar em receber solicitações apenas para nós que executam pods e tentar servir pods locais é a melhor maneira de fazer isso. O lado bom disso é que haverá menos tráfego de nó a nó dentro do cluster e suponho que haja uma melhoria na latência ao atender sempre as solicitações locais do serviço ao pod (o que acho que é ainda mais benéfico se você tiver nós em várias zonas de disponibilidade no mesmo cluster).

Em termos de trabalho com um balanceador de carga que não oferece suporte à ponderação, você pode resolver isso com seu controlador de replicação tentando sempre manter o mesmo número de pods em um nó (se houver mais de 1 por nó) e, em seguida, distribuir uniformemente entre eles, mesmo que isso signifique ter que mover pods para fora de um nó em certas situações e permitir apenas certas contagens de réplicas. por exemplo, para um cluster de 4 nós com um serviço conectado a um balanceador de carga, o único número de réplicas de pod aceitáveis ​​seria 1,2,3,4,6,8,9,12,16,20 etc.

Também estamos tentando resolver o tráfego para rotear apenas os pods locais. Eu ficaria bem com o nodeport indo embora em um nó quando não houver pods presentes localmente para um serviço. Dessa forma, uma verificação de integridade de TCP do balanceador de carga simples evitaria que as solicitações fossem para esses nós. Acho que se pudermos pelo menos resolver para a parte iptables \ kube-proxy disso, então descobriremos quais são as implicações do balanceamento de carga quando os pods não são balanceados no cluster. Acho que há maneiras de resolver isso em balanceadores de carga sem ter que definir um peso para cada nó com uma chamada de API.

Os balanceadores de carga já lidam com isso usando outros métodos dinâmicos. Além disso, dependendo do que o serviço que você está executando está realmente fazendo dentro desse contêiner para cada chamada de API, ele pode não ser capaz de suportar 2x o tráfego quando há 2 pods em um nó contra um de qualquer maneira. Se os limites do Kubernetes forem definidos e se os níveis máximos de uso estiverem sendo atingidos em um podnode, isso também poderá afetar, o que adiciona outra camada de complexidade para tentar encontrar a configuração de peso certa no balanceador de carga externo.

Eu diria, fique longe desse nível de complexidade e não tente definir o peso do balanceador de carga do kubernetes.

@yoshiwaan Posso sugerir a abertura de um novo problema para a sugestão de tráfego entre nós, já que esse problema foi encerrado. Pessoalmente, acho que um bom primeiro passo seria garantir que _se_ um pod esteja em execução no nó local, que rotearemos para o pod local. Suspeito que isso seja suficiente, porque você pode dimensionar seu RC para que haja pods em cada nó.

@justinsb +1, também estamos tendo um problema agora em que precisamos ver os IPs dos clientes e isso é basicamente impossível com a configuração atual.

Isso pode ser muito ingênuo, mas eu estava me perguntando qual é a diferença entre o modo userspace e iptables? Eu realmente não posso dizer a partir do documento do

O modo Userland significa que o kube-proxy lida com as próprias conexões, recebendo a solicitação de conexão do cliente e abrindo um soquete para o servidor, que (1) consome muito mais CPU e memória e (2) é limitado ao número de portas que uma única pode aberto (<65k). O modo iptables funciona em um nível inferior, no kernel, e usa rastreamento de conexão, então é muito mais leve e lida com muito mais conexões *.

(editar) (*) Contanto que você não faça SNAT nos pacotes, o que, por sua vez, requer uma configuração onde você tenha certeza de que os pacotes cruzarão as regras de rastreamento de conexão associadas a eles. Por exemplo, usar um design de acesso roteado permite evitar SNAT, o que significa que o terminal do serviço verá o IP do cliente real.

@MikaelCluseau
o que significa que o kube-proxy é apenas responsável por configurar e manter as regras do iptables e não temos mais uma porta local aleatória para cada serviço no modo iptables, certo?

Em 19/04/2016 10:51, Emma Ele escreveu:

o que significa que o kube-proxy é apenas responsável por configurar e manter
iptables e não temos mais uma porta local aleatória para cada serviço em
modo iptables, certo?

sim.

Desculpe, mas eu absolutamente perdi isso antes.

(editar) (*) Contanto que você não faça SNAT nos pacotes, o que, por sua vez, requer uma configuração onde você tenha certeza de que os pacotes cruzarão as regras de rastreamento de conexão associadas a eles. Por exemplo, usar um design de acesso roteado permite evitar SNAT, o que significa que o terminal do serviço verá o IP do cliente real.

@MikaelCluseau Eu estava pensando que o iptables adota SNAT e DNAT, o que não é o caso para você. Você poderia esclarecer isso para mim?

Em 20/04/2016 13h59, Emma Ele escreveu:

@MikaelCluseau https://github.com/MikaelCluseau eu estava pensando
O iptables adota SNAT e DNAT, o que não é o caso para você.
Você poderia esclarecer isso para mim?

É a parte complicada.

(1) O uso de IPs de serviço / externos requer DNAT.
(2) Se você tiver certeza de que os pacotes de resposta passarão pelo mesmo conntrack
regra (ou seja, a mesma pilha de rede ou uma tabela conntrack replicada), você
pode pular a parte SNAT (ou seja, regras MASQUERADE).

A condição de (2) é geralmente ok em projetos de rede de acesso roteado
(que é o design mais simples que eu posso pensar).

Por exemplo, dado

  • um cliente 1.0.1.1,
  • um serviço 1.0.2.1,
  • um pod implementando o serviço 1.0.3.1.

Então,

  1. Seu roteador / firewall / balanceador de carga / host / o que quer que receba um pacote
    para o serviço para que veja um pacote "1.0.1.1 -> 1.0.2.1";
  2. Ele faz o DNAT para o endpoint (pod) para que o pacote seja "1.0.1.1 ->
    1.0.3.1 "na rede de cluster;
  3. O pod responde com um pacote "1.0.3.1 -> 1.0.1.1";
  4. O pacote passa por um roteador / firewall / balanceador de carga / host / qualquer que seja
    tendo a regra conntrack, o sistema conntrack reescreve o pacote
    para "1.0.2.1 -> 1.0.1.1" antes de enviá-lo de volta ao cliente.

Se a condição de (2) não puder ser atendida, você deve usar SNAT / MASQUERADING
para ter certeza de que o pacote retornará ao
roteador / firewall / balanceador de carga / host / qualquer que seja o conntrack.

@MikaelCluseau -
algo para você

Na terça - feira, 19 de abril de 2016 às 20:20, Mikaël Cluseau
escreveu:

Em 20/04/2016 13h59, Emma Ele escreveu:

@MikaelCluseau https://github.com/MikaelCluseau eu estava pensando
O iptables adota SNAT e DNAT, o que não é o caso para você.
Você poderia esclarecer isso para mim?

É a parte complicada.

(1) O uso de IPs de serviço / externos requer DNAT.
(2) Se você tiver certeza de que os pacotes de resposta passarão pelo mesmo conntrack
regra (ou seja, a mesma pilha de rede ou uma tabela conntrack replicada), você
pode pular a parte SNAT (ou seja, regras MASQUERADE).

A condição de (2) é geralmente ok em projetos de rede de acesso roteado
(que é o design mais simples que eu posso pensar).

Por exemplo, dado

  • um cliente 1.0.1.1,
  • um serviço 1.0.2.1,
  • um pod implementando o serviço 1.0.3.1.

Então,

  1. Seu roteador / firewall / balanceador de carga / host / o que quer que receba um pacote
    para o serviço para que veja um pacote "1.0.1.1 -> 1.0.2.1";
  2. Ele faz o DNAT para o endpoint (pod) para que o pacote seja "1.0.1.1 ->
    1.0.3.1 "na rede de cluster;
  3. O pod responde com um pacote "1.0.3.1 -> 1.0.1.1";
  4. O pacote passa por um roteador / firewall / balanceador de carga / host / qualquer que seja
    tendo a regra conntrack, o sistema conntrack reescreve o pacote
    para "1.0.2.1 -> 1.0.1.1" antes de enviá-lo de volta ao cliente.

Se a condição de (2) não puder ser atendida, você deve usar SNAT / MASQUERADING
para ter certeza de que o pacote retornará ao
roteador / firewall / balanceador de carga / host / qualquer que seja o conntrack.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/kubernetes/kubernetes/issues/3760#issuecomment -212230959

@justinsb @yoshiwaan , alguém já criou um problema para isso? Minha busca fu está falhando, e eu tenho uma necessidade semelhante.

Posso sugerir a abertura de um novo problema para a sugestão de tráfego entre nós, já que esse problema foi encerrado. Pessoalmente, acho que um bom primeiro passo seria garantir que, se um pod estiver em execução no nó local, rotearemos para o pod local. Suspeito que isso seja suficiente, porque você pode dimensionar seu RC para que haja pods em cada nó.

Eu não levantei sozinho

Ahhhhh, acho que encontrei, esse parece ser o recurso / correção: https://github.com/kubernetes/features/issues/27

Parece ser beta em 1.5.x.

Esta página foi útil?
0 / 5 - 0 avaliações