O failover da Netflix: de 45 minutos para 7 sem custo adicional

Como Netflix diminuiu o tempo necessário para responder a uma interrupção de 45 minutos a sete sem custo adicional




Durante os horários de pico, os fluxos de vídeo da Netflix representam mais de um terço do tráfego da Internet. O Netflix deve ser transmitido ininterruptamente diante de problemas generalizados de rede, implementações incorretas de código, interrupções de serviço da AWS e muito mais. 
Failovers tornaram isso possível.



O failover é o processo de transferir todo o nosso tráfego de uma região da AWS para outra. Enquanto a maior parte do Netflix roda em Java, os failovers são totalmente alimentados pelo Python. 
A versatilidade e o rico ecossistema do Python significam que podemos usá-lo para tudo, desde a previsão de nossos padrões de tráfego até a orquestração do movimento do tráfego, enquanto lidamos com a consistência eventual da AWS.

Hoje, podemos mudar todos os nossos 100 milhões de usuários em menos de sete minutos. Um monte de trabalho de engenharia foi feito para tornar isso possível. Os problemas que enfrentamos e as soluções que criamos têm amplo aplicativo para as estratégias de disponibilidade na nuvem ou no datacenter.






Durante o inverno de 2012, a Netflix sofreu uma interrupção prolongada que durou sete horas devido a problemas no AWS Elastic Load Balancer na região Leste dos EUA.
A Netflix é executada no Amazon Web Services, AWS, não há datacenters próprios.
Todas as suas interações com a Netflix são fornecidas pela AWS, exceto a transmissão real do vídeo. Depois de clicar em "reproduzir", os arquivos de vídeo reais são atendidos por nosso próprio CDN. Durante a interrupção, nenhum dos tráfegos que entravam no leste dos EUA estava chegando aos nossos serviços.

Para evitar que isso aconteça novamente, decidimos criar um sistema de failovers regionais resiliente a falhas de nossos provedores de serviços subjacentes.
O failover é um método de proteger os sistemas de computador contra falhas nas quais o equipamento em espera assume automaticamente o controle quando o sistema principal falha.


Failovers regionais diminuíram o risco
Expandimos para um total de três regiões da AWS:
duas nos Estados Unidos (Leste dos EUA e Oeste dos EUA) e uma na União Europeia (UE).
Reservamos capacidade suficiente para realizar um failover, para que possamos absorver uma interrupção de uma única região.



Um failover típico é assim:


  1. Perceba que uma das regiões está com problemas.
  2. Escale as duas regiões do 'salvador'.
  3. Proxy algum tráfego da região conturbada para os 'salvadores'.
  4. Mude o DNS para longe da região problemática para as regiões mais seguras.

Vamos explorar cada passo.



1. Identifique o problema
Precisamos de métricas e, de preferência, de uma única métrica, que possa nos informar sobre a integridade do sistema. Na Netflix, usamos uma métrica de negócios chamada stream Starts Per Second (SPS, em resumo).
Esta é uma contagem do número de clientes que iniciaram com sucesso o streaming de um programa.

Temos esses dados particionados por região e, a qualquer momento, podemos plotar os dados do SPS para cada região e compará-los com o valor do SPS do dia anterior e da semana anterior. Quando notamos uma queda no gráfico do SPS, sabemos que nossos clientes não conseguem iniciar o streaming de programas, por isso estamos em apuros.

O problema não é necessariamente um problema de infraestrutura de nuvem. Pode ser um código incorreto implantado em uma das centenas de microservices que compõem o ecossistema Netflix, um corte em um cabo submarino, etc.
Podemos não saber o motivo; nós simplesmente sabemos que algo está errado.








Se essa falha no SPS for observada apenas em uma região, ela será uma ótima candidata para o failover regional. Se a queda é observada em várias regiões, estamos sem sorte porque só temos capacidade suficiente para evacuar uma região de cada vez. É exatamente por isso que escalonamos a implantação de nossos microsserviços para uma região por vez. Se houver um problema com uma implantação, poderemos evacuar imediatamente e depurar o problema mais tarde. Da mesma forma, queremos evitar o failover quando o problema seguir o redirecionamento de tráfego (como aconteceria em um ataque de DDoS ).




2. Expanda os 'salvadores'
Uma vez que identificamos a região doente, devemos preparar as outras regiões (os "salvadores") para receber o tráfego do doente. Antes de ligarmos a mangueira de incêndio, precisamos escalar a pilha nas regiões mais seguras.

O que significa dimensionamento apropriadamente neste contexto? 
O padrão de tráfego da Netflix não é estático ao longo do dia. Temos horas de pico, geralmente por volta das 18h às 21h. Mas às 6h chega em diferentes momentos em diferentes partes do mundo. O tráfego de pico no leste dos EUA é de três horas à frente do oeste dos Estados Unidos, oito horas atrás da região da UE.

Quando fazemos failover no leste dos EUA, enviamos tráfego do leste dos EUA para a UE e do tráfego da América do Sul para o oeste dos Estados Unidos. Isso é para reduzir a latência e fornecer a melhor experiência possível para nossos clientes.

Levando isso em consideração, podemos usar a regressão linear para prever o tráfego que será roteado para as regiões mais seguras para aquela hora do dia (e dia da semana) usando o comportamento histórico de escala de cada microsserviço.

Uma vez que tenhamos determinado o tamanho apropriado para cada microsserviço, acionamos o escalonamento para cada um deles, definindo o tamanho desejado de cada cluster e depois permitimos que a AWS faça sua mágica.



3. Tráfego de proxy
Agora que os clusters de microsserviços foram dimensionados, iniciamos o proxy do tráfego da região doente para as regiões mais seguras. A Netflix criou um proxy de borda cross-regional de alto desempenho chamado Zuul, que é open source: https://github.com/Netflix/zuul.

Esses serviços de proxy são projetados para autenticar solicitações, fazer shilling de carga, repetir solicitações com falha, etc. O proxy Zuul também pode fazer proxy de região cruzada. Usamos esse recurso para direcionar um pouco do tráfego para longe da região afetada e aumentar progressivamente a quantidade de tráfego redirecionado até atingir 100%.

Esse proxy progressivo permite que nossos serviços usem suas políticas de escalonamento para fazer qualquer escala reativa necessária para manipular o tráfego de entrada. Isso é para compensar qualquer alteração no volume de tráfego entre o momento em que fizemos nossas previsões de escala e o tempo necessário para dimensionar cada cluster.

Zuul faz o trabalho pesado neste momento para encaminhar todo o tráfego de entrada de uma região doente para as regiões saudáveis. Mas chegou a hora de abandonar completamente a região afetada. É aqui que a troca de DNS entra em ação.



4. Mude o DNS
A última etapa do failover é atualizar os registros DNS que apontam para a região afetada e redirecioná-los para as regiões saudáveis. Isso moverá completamente todo o tráfego de clientes da região doente. Todos os clientes que não expiram seu cache DNS ainda serão roteados pela camada Zuul na região afetada.

Essa é a informação de fundo de como o failover costumava funcionar na Netflix. Esse processo levou muito tempo para ser concluído - cerca de 45 minutos (em um bom dia).






Acelerando a resposta com novos processos brilhantes

Percebemos que a maior parte do tempo (aproximadamente 35 minutos) foi gasto esperando que as regiões do ambiente salvador aumentassem. Embora a AWS pudesse provisionar novas instâncias para nós em questão de minutos, iniciar os serviços, fazer o aquecimento just-in-time e lidar com outras tarefas de inicialização antes de registrar o UP na discovery (https://github.com/Netflix/eureka) dominando o processo de dimensionamento.

Nós decidimos que isso era muito longo. Queríamos que nossos failovers fossem concluídos em menos de 10 minutos. Queríamos fazer isso sem adicionar carga operacional aos proprietários do serviço. Também queríamos ficar neutros em termos de custos.

Reservamos capacidade nas três regiões para absorver o tráfego de failover; se já estamos pagando por toda essa capacidade, por que não usá-lo? Assim começou o Project Nimble.

Nossa idéia era manter um pool de instâncias em hot standby para cada microsserviço. Quando estamos prontos para fazer um failover, podemos simplesmente injetar nosso hot standby nos clusters para obter tráfego ao vivo.

A capacidade reservada não utilizada é chamada de vale. Algumas equipes da Netflix usam parte da capacidade mínima para executar trabalhos em lote, por isso não podemos simplesmente transformar toda a quantidade disponível em hot standby. Em vez disso, podemos manter um cluster de sombra para cada microsserviço que executamos e armazenar esse cluster de sombra com instâncias suficientes para obter o tráfego de failover para essa hora do dia. O restante das instâncias está disponível para que tarefas em lote sejam usadas como quiserem.

No momento do failover, em vez do método de escalonamento tradicional que aciona a AWS para provisionar instâncias para nós, injetamos as instâncias do cluster de sombra no cluster ativo. Esse processo leva cerca de quatro minutos, ao contrário dos 35 minutos que costumava levar.

Como a injeção de capacidade é rápida, não é necessário mover o tráfego com cautela por proxy para permitir que as políticas de dimensionamento reajam. Podemos simplesmente mudar o DNS e abrir as comportas, reduzindo ainda mais os preciosos minutos durante uma interrupção.

Adicionamos filtros no cluster de sombra para impedir que as instâncias obscuras relatem métricas. Caso contrário, eles poluirão o espaço métrico e confundirão o comportamento operacional normal.

Também impedimos que as instâncias nos clusters de sombra se registrassem na UP, modificando nosso cliente da discovery. Essas instâncias continuarão a permanecer no escuro (trocadilho intencional) até que acione um failover.

Agora podemos fazer failovers regionais em sete minutos. Como utilizamos nossa capacidade reservada existente, não incorremos em custos adicionais de infraestrutura. 
O software que orquestra o failover é escrito em Python por uma equipe de três engenheiros.


=====

Texto do Amjith Ramanujam (@amjithr), Senior Software Engineer da Netflix, criador do pgcli e mycli (dbcli.com)
Responsável por manter os serviços da Netflix rodando diante de adversidades extremas :-)

Em Maio deste ano Amjith Ramanujam apresentou esta implementação na PyCon2018, o video segue abaixo e em breve os slides estarão no Github da PyCon (https://github.com/PyCon)






Mais vistos no mês:

SSD no linux

Teste de Performance de Rede com Iperf

TuxMath - Tux, do Comando da Matemática. Ensino e diversão a crianças.

DHCP - Guia Completo

As melhores distribuições Linux para 2017

OPNsense - Firewall Open Source

Aula #14 - Os sistemas de arquivos ext2/ext3/ext4

Modelo Firewall Completo em Iptables para pequena rede/office