Quando o Linux conntrack não é mais seu amigo

Quando o Linux conntrack não é mais seu amigo

O rastreamento de conexão (“conntrack”) é um recurso central da pilha de rede do kernel Linux. Ele permite que o kernel acompanhe todas as conexões ou fluxos de rede lógica e, assim, identifique todos os pacotes que compõem cada fluxo para que possam ser processados ​​juntos sequencialmente.

Conntrack é um recurso importante do kernel usado em alguns casos básicos:

  • O NAT depende das informações do conntrack para poder tratar todos os pacotes do mesmo fluxo igualmente. Por exemplo, quando um pod acessa um serviço Kubernetes, o balanceador de carga kube-proxy usa NAT para direcionar o tráfego para um pod específico dentro do cluster. Conntrack registra que, para uma determinada conexão, todos os pacotes para o serviço IP devem ser enviados para o mesmo pod e que os pacotes retornados pelo pod de back-end devem ser enviados por NAT de volta para o pod de onde veio a solicitação.
  • Firewalls com estado, como o Calico, dependem de informações do connecttrack para colocar o tráfego de “resposta” na lista de permissões. Isso permite que você escreva uma política de rede que diga "permitir que meu pod se conecte a qualquer endereço IP remoto" sem precisar escrever uma política para permitir explicitamente o tráfego de resposta. (Sem isso, você teria que adicionar a regra muito menos segura "permitir pacotes para meu pod a partir de qualquer IP".)

Além disso, o conntrack normalmente melhora o desempenho do sistema (reduzindo o consumo de CPU e a latência de pacotes), uma vez que apenas o primeiro pacote em um fluxo
deve percorrer toda a pilha da rede para determinar o que fazer com ela. Veja a postagem "Comparação dos modos kube-proxy" para ver um exemplo de como funciona.

No entanto, conntrack tem suas limitações...

Então, onde é que tudo deu errado?

A tabela conntrack possui um tamanho máximo configurável e, caso fique cheia, as conexões geralmente começam a ser rejeitadas ou descartadas. Há espaço livre suficiente na tabela para lidar com o tráfego da maioria dos aplicativos e isso nunca se tornará um problema. No entanto, existem alguns cenários em que você pode querer considerar o uso da tabela conntrack:

  • O caso mais óbvio é se o seu servidor lida com um número extremamente grande de conexões ativas simultaneamente. Por exemplo, se sua tabela conntrack estiver configurada para 128k entradas, mas você tiver >128k conexões simultâneas, você certamente terá problemas!
  • Um caso um pouco menos óbvio: se o seu servidor processa um número muito grande de conexões por segundo. Mesmo que as conexões durem pouco, elas continuam a ser monitoradas pelo Linux por algum período de tempo (120s por padrão). Por exemplo, se sua tabela conntrack estiver configurada para entradas de 128k e você estiver tentando lidar com 1100 conexões por segundo, elas excederão o tamanho da tabela conntrack, mesmo que as conexões tenham vida muito curta (128k/120s = 1092 conexões/ e).

Existem vários tipos de aplicativos de nicho que se enquadram nessas categorias. Além disso, se você tiver muitos agentes mal-intencionados, preencher a tabela conntrack do seu servidor com muitas conexões semiabertas pode ser usado como parte de um ataque de negação de serviço (DOS). Em ambos os casos, o conntrack pode se tornar um gargalo limitante no seu sistema. Em alguns casos, ajustar os parâmetros da tabela conntrack pode ser suficiente para atender às suas necessidades - aumentando o tamanho ou reduzindo os tempos limite do conntrack (mas se você fizer isso errado, terá muitos problemas). Para outros casos será necessário contornar o conntrack para tráfego agressivo.

Exemplo real

Vamos dar um exemplo específico: um grande provedor de SaaS com o qual trabalhamos tinha vários servidores memcached em hosts (não em máquinas virtuais), cada um dos quais processava mais de 50 mil conexões de curto prazo por segundo.

Eles experimentaram a configuração do conntrack, aumentando o tamanho das tabelas e reduzindo o tempo de rastreamento, mas a configuração não era confiável, o consumo de RAM aumentou significativamente, o que era um problema (na ordem de GBytes!), e as conexões eram tão curtas que o conntrack não funcionou. criar seu benefício de desempenho usual (redução do consumo de CPU ou latência de pacotes).

Eles recorreram a Calico como alternativa. As políticas de rede Calico permitem que você não use o conntrack para determinados tipos de tráfego (usando a opção de política doNotTrack). Isto deu-lhes o nível de desempenho que precisavam, além do nível adicional de segurança fornecido pelo Calico.

Até onde você terá que ir para contornar o conntrack?

  • As políticas de rede do tipo “não rastrear” devem geralmente ser simétricas. No caso do provedor de SaaS: seus aplicativos eram executados dentro da zona protegida e, portanto, usando a política de rede, eles podiam colocar na lista branca o tráfego de outros aplicativos específicos que tinham acesso permitido ao memcached.
  • A política de não rastrear não leva em consideração a direção da conexão. Assim, se o servidor memcached for hackeado, você poderá, teoricamente, tentar se conectar a qualquer um dos clientes memcached, desde que use a porta de origem correta. No entanto, se você definiu corretamente a política de rede para seus clientes memcached, essas tentativas de conexão ainda serão rejeitadas no lado do cliente.
  • A política do-not-track é aplicada a todos os pacotes, ao contrário das políticas normais, que são aplicadas apenas ao primeiro pacote de um fluxo. Isto pode aumentar o consumo de CPU por pacote porque a política deve ser aplicada para cada pacote. Mas para conexões de curta duração, esta despesa é compensada pela redução no consumo de recursos para processamento conntrack. Por exemplo, no caso de um fornecedor SaaS, o número de pacotes para cada ligação era muito pequeno, pelo que se justificava o consumo adicional de CPU na aplicação de políticas a cada pacote.

Vamos começar a testar

Executamos o teste em um único pod com um servidor memcached e vários pods de cliente memcached em execução em nós remotos para que pudéssemos executar um grande número de conexões por segundo. O servidor com o pod de servidor memcached tinha 8 núcleos e 512 mil entradas na tabela conntrack (o tamanho de tabela padrão configurado para o host).
Medimos a diferença de desempenho entre: nenhuma política de rede; com apólice regular da Calico; e a política de não rastrear da Calico.

Para o primeiro teste, definimos o número de conexões em 4.000 por segundo, para que pudéssemos focar na diferença no consumo de CPU. Não houve diferenças significativas entre nenhuma política e política regular, mas não monitore o aumento do consumo de CPU em cerca de 20%:

Quando o Linux conntrack não é mais seu amigo

No segundo teste, lançamos tantas conexões quanto nossos clientes puderam gerar e medimos o número máximo de conexões por segundo que nosso servidor memcached poderia suportar. Como esperado, os casos “sem política” e “política regular” atingiram o limite conntrack de mais de 4,000 conexões por segundo (512k/120s = 4,369 conexões/s). Com uma política de não rastrear, nossos clientes enviaram 60,000 mil conexões por segundo sem problemas. Temos certeza de que poderíamos aumentar esse número adicionando mais clientes, mas sentimos que esses números já são suficientes para ilustrar o objetivo deste artigo!

Quando o Linux conntrack não é mais seu amigo

Conclusão

Conntrack é um recurso importante do kernel. Ele faz seu trabalho perfeitamente. É frequentemente usado pelos principais componentes do sistema. No entanto, em alguns cenários específicos, o congestionamento devido ao conntrack supera os benefícios normais que ele proporciona. Neste cenário, as políticas de rede Calico podem ser usadas para desativar seletivamente o uso do conntrack enquanto aumentam a segurança da rede. Para todos os outros tráfegos, a conntrack continua a ser sua amiga!

Leia também outros artigos em nosso blog:

Fonte: habr.com

Adicionar um comentário