Isolamento de workload usando fragmentação aleatória
Arquitetura | NÍVEL 400
Introdução
Hoje, o Amazon Route 53 hospeda muitas das maiores empresas e sites mais populares do mundo, mas seu início foi muito mais humilde.
Como assumir a hospedagem de DNS
Pouco tempo depois que a AWS começou a oferecer serviços, os clientes da AWS deixaram claro que desejavam poder usar nossos serviços Amazon Simple Storage Service (S3), Amazon CloudFront e Elastic Load Balancing na "raiz" do domínio deles, ou seja, para nomes como "amazon.com" e não apenas para nomes como "www.amazon.com".
Isso pode parecer muito simples. No entanto, devido a uma decisão de design no protocolo DNS, tomada na década de 1980, é mais difícil do que parece. O DNS tem um recurso chamado CNAME que permite que o proprietário de um domínio transfira uma parte desse domínio para outro provedor hospedar, mas não funciona no nível raiz ou superior de um domínio. Para atender às necessidades de nossos clientes, teríamos que hospedar os domínios de nossos clientes na verdade. Quando hospedamos o domínio de um cliente, podemos retornar qualquer conjunto atual de endereços IP para o Amazon S3, Amazon CloudFront ou Elastic Load Balancing. Esses serviços estão constantemente expandindo e adicionando endereços IP, portanto, também não é algo que os clientes possam codificar com facilidade nas configurações de domínio.
Hospedar o DNS não é uma tarefa pequena. Se o DNS estiver com problemas, uma empresa inteira poderá ficar offline. No entanto, depois que identificamos a necessidade, decidimos resolvê-la da maneira típica da Amazon: com urgência. Criamos uma pequena equipe de engenheiros e começamos a trabalhar.
Como enfrentar ataques DDoS
Pergunte a qualquer provedor de DNS qual é o maior desafio e eles lhe dirão que está lidando com ataques de negação de serviço distribuída (DDoS). O DNS é criado com base no protocolo UDP, o que significa que as solicitações de DNS são falsificadas em grande parte da Internet do oeste selvagem. Como o DNS também é uma infraestrutura crítica, essa combinação o torna um alvo atraente para atores inescrupulosos que tentam extorquir negócios, "inicializadores" que pretendem desencadear interrupções por várias razões e o ocasional causador de problemas equivocado que parece não perceber que está cometendo um crime grave com consequências pessoais reais. Independentemente do motivo, todos os dias há milhares de ataques DDoS cometidos contra domínios.
Uma abordagem para atenuar esses ataques é usar grandes volumes de capacidade do servidor. Embora seja importante ter uma boa linha de base de capacidade, essa abordagem não é realmente escalável. Todo servidor adicionado por um provedor custa milhares de dólares, mas os invasores podem adicionar mais clientes falsos por centavos se estiverem usando botnets comprometidos. Para os provedores, adicionar grandes volumes de capacidade do servidor é uma estratégia perdida.
No momento em que criamos o Amazon Route 53, o estado da arte em defesa do DNS eram dispositivos de rede especializados que podiam usar uma variedade de truques para "eliminar" o tráfego a uma taxa muito alta. Tínhamos muitos desses dispositivos na Amazon para nossos serviços DNS internos existentes e conversamos com fornecedores de hardware sobre o que mais estava disponível. Descobrimos que comprar equipamentos suficientes para cobrir totalmente todos os domínios do Route 53 custaria dezenas de milhões de dólares e incluiria meses em nossa programação para que eles fossem entregues, instalados e ficassem operacionais. Isso não se encaixava com a urgência de nossos planos ou com nossos esforços para sermos frugais, por isso nunca avaliamos seriamente a possibilidade de usá-los. Precisávamos encontrar uma maneira de gastar recursos apenas na defesa de domínios que realmente estão enfrentando um ataque. Voltamos ao antigo princípio de que a necessidade é a mãe da invenção. Nossa necessidade era criar rapidamente um serviço DNS de classe mundial com 100% de tempo de atividade, usando uma quantidade modesta de recursos. Nossa invenção foi a fragmentação aleatória.
O que é fragmentação aleatória?
A fragmentação aleatória é simples, mas poderosa. É ainda mais poderosa do que imaginávamos a princípio. Nós a usamos repetidamente e tornou-se um padrão essencial que possibilita à AWS fornecer serviços de vários inquilinos econômicos que proporcionam a cada cliente uma experiência de inquilino único.
Para ver como a fragmentação aleatória funciona, primeiro considere como um sistema pode se tornar mais escalável e resiliente por meio da fragmentação comum. Imagine um sistema ou serviço escalável composto horizontalmente por oito funcionários. A imagem a seguir ilustra os trabalhadores e suas solicitações. Os operadores podem ser servidores, filas ou bancos de dados, qualquer “coisa” que componha seu sistema.

Sem nenhuma fragmentação, a frota de operadores processa todo o trabalho. Cada trabalhador deve ser capaz de processar qualquer solicitação. Isso é ótimo para eficiência e redundância. Se um trabalhador falhar, os outros sete poderão absorver o trabalho, portanto, é necessária uma capacidade relativamente reduzida de folga no sistema. No entanto, um grande problema surge se as falhas puderem ser acionadas por um tipo específico de solicitação ou por uma enxurrada de solicitações, como um ataque DDoS. As duas imagens a seguir mostram a progressão desse ataque.

O problema eliminará o primeiro operador afetado, mas continuará em cascata pelos outros operadores à medida que os demais assumirem o controle. O problema pode eliminar rapidamente todos os operadores e todo o serviço.

O escopo do impacto para esse tipo de falha é "tudo e todos". Todo o serviço cai. Todo cliente é afetado. Como dizemos na engenharia de disponibilidade: não é o ideal.
Com a fragmentação regular, podemos fazer melhor. Se dividirmos a frota em quatro fragmentos de trabalhadores, poderemos trocar a eficiência pelo escopo do impacto. As duas imagens a seguir mostram como a fragmentação pode limitar o impacto de um ataque DDoS.

Neste exemplo, cada fragmentação tem dois operadores. Dividimos recursos, como domínios de clientes, entre os fragmentos. Ainda temos redundância, mas como existem apenas dois trabalhadores por fragmentos, precisamos manter mais capacidade de folga no sistema para lidar com qualquer falha. Em troca, o escopo do impacto é reduzido consideravelmente.

Nesse mundo de fragmentação, o escopo do impacto é reduzido pelo número de fragmentos. Aqui, com quatro fragmentos, se um cliente tiver um problema, o fragmento que os hospeda poderá ser impactado, assim como todos os outros nesse fragmento. No entanto, esse fragmento representa apenas um quarto do serviço geral. Um impacto de 25% é muito melhor do que um impacto de 100%. Com a fragmentação aleatória, podemos melhorar exponencialmente de novo.
Com a fragmentação aleatória, criamos fragmentos virtuais de dois trabalhadores cada um e atribuímos nossos clientes ou recursos, ou o que quisermos isolar, a um desses fragmentos virtuais.
A imagem a seguir mostra um exemplo de layout de fragmentação aleatória com oito trabalhadores e oito clientes, cada um atribuído a dois trabalhadores. Normalmente, teríamos muito mais clientes que trabalhadores, mas é mais fácil acompanhar se mantivermos as coisas menores. Vamos nos concentrar em dois clientes: o cliente arco-íris e o cliente rosa.
Em nosso exemplo, atribuímos o cliente arco-íris ao primeiro e ao quarto trabalhador. A combinação desses dois funcionários compõe o fragmento aleatório desse cliente. Outros clientes irão para diferentes fragmentos virtuais, com sua própria mistura de dois trabalhadores. Por exemplo, o cliente rosa também é atribuído ao primeiro operador, mas seu outro operador é o oitavo.

Se o cliente arco-íris atribuído aos operadores um e quatro tiver um problema (como uma solicitação maliciosa ou uma enxurrada de solicitações), esse problema afetará o fragmento virtual, mas não afetará totalmente nenhum outro fragmento aleatório. De fato, no máximo um dos trabalhadores de outra fragmentação aleatória será afetado. Se os solicitantes forem tolerantes a falhas e puderem solucionar isso (com novas tentativas, por exemplo), o serviço poderá continuar ininterrupto para os clientes ou recursos nos fragmentos restantes, como mostra a imagem a seguir.

Dito de outra forma, enquanto todos os operadores que atendem o arco-íris podem estar enfrentando um problema ou um ataque, os outros operadores não são afetados. Para os clientes, isso significa que, embora o cliente rosa e o cliente girassol compartilhem um trabalhador com o arco-íris, eles não são afetados. O cliente rosa pode obter serviço do operador oito e o girassol pode obter serviço do operador seis, como pode ser visto na imagem a seguir.

Quando ocorre um problema, ainda podemos perder um quarto de todo o serviço, mas a maneira como os clientes ou os recursos são atribuídos significa que o escopo do impacto com a fragmentação aleatória é consideravelmente melhor. Com oito trabalhadores, há 28 combinações únicas de dois trabalhadores, o que significa que há 28 possíveis fragmentos aleatórios. Se temos centenas de clientes ou mais e atribuímos cada cliente a um fragmento aleatório, o escopo do impacto devido a um problema é de apenas 1/28º. Isso é sete vezes melhor que a fragmentação regular.
É muito emocionante ver que os números ficam exponencialmente melhores quanto mais trabalhadores e clientes você tiver. A maioria dos desafios de escalabilidade fica mais difícil nessas dimensões, mas a fragmentação aleatória fica mais eficaz. De fato, com operadores suficientes, pode haver mais fragmentos aleatórios do que clientes, e cada cliente pode ser isolado.
Amazon Route 53 e fragmentação aleatória
Como tudo isso ajuda o Amazon Route 53? Com o Route 53, decidimos organizar nossa capacidade em um total de 2048 servidores de nomes virtuais. Esses servidores são virtuais porque não correspondem aos servidores físicos que hospedam o Route 53. Podemos movê-los para ajudar a gerenciar a capacidade. Em seguida, atribuímos todos os domínios do cliente a um fragmento aleatório de quatro servidores de nomes virtuais. Com esses números, existem impressionantes 730 bilhões de fragmentos possíveis. Temos tantos fragmentos aleatórios possíveis que podemos atribuir um fragmento aleatório exclusivo a cada domínio. Na verdade, podemos ir além e garantir que nenhum domínio do cliente compartilhe mais de dois servidores de nome virtual com qualquer outro domínio do cliente.
Os resultados são surpreendentes. Se um domínio do cliente for alvo de um ataque DDoS, os quatro servidores de nomes virtuais atribuídos a esse domínio terão um pico no tráfego, mas nenhum domínio de outro cliente notará. Não renunciamos ao cliente alvo que está tendo um dia ruim. A fragmentação aleatória significa que podemos identificar e isolar o cliente alvo para uma capacidade de ataque dedicada especial. Além disso, também desenvolvemos nossa própria camada proprietária de lavadores de tráfego da AWS Shield. No entanto, a fragmentação aleatória faz uma enorme diferença ao garantir que a experiência geral do cliente do Route 53 seja perfeita, mesmo enquanto esses eventos estão ocorrendo.
Conclusão
Passamos a incorporar a fragmentação aleatória em muitos de nossos outros sistemas. Além disso, criamos refinamentos, como fragmentação aleatória recursiva, em que fragmentamos itens em várias camadas, isolando assim o cliente de um cliente. A fragmentação aleatória é extremamente adaptável. É uma maneira inteligente de organizar os recursos existentes. Também geralmente vem sem custo adicional, por isso é uma grande melhoria que a frugalidade e a economia podem gerar.
Se você estiver interessado em usar a fragmentação aleatória, confira nossa biblioteca do Route 53 Infima de código aberto. Esta biblioteca inclui várias implementações diferentes de fragmentação aleatória que podem ser usadas para atribuir ou organizar recursos.
Laboratório prático
Experimente alguns dos princípios que você aprendeu aqui com um laboratório prático.
Sobre o autor
Conteúdo relacionado
Você encontrou o que estava procurando hoje?
Informe-nos para que possamos melhorar a qualidade do conteúdo em nossas páginas