Escrito por Rhandeev Singh e Sebastian Kirsch with Vivek Rau
Editado por Betsy Beyer
Empresas de Internet como a Google são capazes de lançar novos produtos e funcionalidades em iterações muito mais rápidas do que as empresas tradicionais. O papel da confiabilidade do site neste processo é permitir um ritmo de mudança rápido sem comprometer a estabilidade do site. Criamos uma equipe dedicada de “Engenheiros de Coordenação de Lançamento” para consultar as equipes de engenharia sobre os aspectos técnicos de um lançamento bem sucedido.
A equipe também organizou uma “lista de verificação de lançamento” de perguntas comuns a fazer sobre um lançamento, e receitas para resolver questões comuns. A lista de verificação provou ser uma ferramenta útil para assegurar lançamentos confiáveis e reprodutíveis.
Considere um serviço normal do Google – por exemplo, o Keyhole, que fornece imagens de satélite para o Google Maps e Google Earth. Num dia normal, o Keyhole oferece até várias milhares de imagens de satélite por segundo. Mas na véspera de Natal de 2011, recebeu 25 vezes o seu pico normal de tráfego – acima de um milhão de pedidos por segundo. O que causou este enorme aumento do tráfego?
O Papai Noel estava chegando
Há alguns anos, o Google colaborou com o NORAD (o Comando de Defesa Aeroespacial Norte-Americano) para hospedar um site temático de Natal que seguia o progresso do Papai Noel em todo o mundo, permitindo aos usuários assistirem a entrega de presentes em tempo real. Parte da experiência foi um “fly-over virtual”, que utilizou imagens de satélite para acompanhar o progresso do Pai Natal num mundo simulado.
Embora um projeto como o NORAD acompanha o Papai Noel possa parecer caprichoso, tinha todas as características que definem um lançamento difícil e arriscado: um prazo difícil (o Google não podia pedir ao Papai Noel para vir uma semana mais tarde se o site não estivesse pronto), muita publicidade, uma audiência de milhões, e uma subida de tráfego muito acentuada (todos iam estar assistindo o site na véspera de Natal). Nunca subestime o poder de milhões de crianças ansiosas por presentes – este projeto tinha uma possibilidade muito real de colocar os servidores do Google de joelhos.
A equipe de engenharia de confiabilidade do Site da Google trabalhou arduamente para preparar a nossa infraestrutura para este lançamento, assegurando que o Papai Noel pudesse entregar todos os seus presentes a tempo sob os olhos atentos de uma audiência ansiosa. A última coisa que queríamos era fazer as crianças chorarem porque não conseguiam ver o Papai Noel entregar presentes. De fato, apelidamos os vários kill switches incorporados na experiência para proteger os nossos serviços de “Fazer com que as crianças chorem”. Antecipar as várias maneiras pelas quais esse lançamento poderia dar errado e a coordenação entre os diferentes grupos de engenharia envolvidos no lançamento coube a uma equipe especial dentro da Engenharia de confiabilidade do Local: os Engenheiros de Coordenação de Lançamento (LCE).
Lançar um novo produto ou característica é o momento da verdade para cada empresa – o ponto em que meses ou anos de esforço são apresentados ao mundo. As empresas tradicionais lançam novos produtos a uma taxa bastante baixa. O ciclo de lançamento nas empresas da Internet é marcadamente diferente. Os lançamentos e as iterações rápidas são muito mais fáceis porque as novas funcionalidades podem ser lançadas no lado do servidor, em vez de exigirem a implementação de software em workstations individuais dos clientes.
O Google define um lançamento como qualquer novo código que introduza uma alteração visível externamente em um aplicativo. Dependendo das características de um lançamento – a combinação de atributos, o tempo, o número de passos envolvidos, e a complexidade – o processo de lançamento pode variar muito. De acordo com esta definição, o Google realiza por vezes até 70 lançamentos por semana.
Esta rápida taxa de mudança fornece tanto a fundamentação como a oportunidade para criar um processo de lançamento racionalizado. Uma empresa que só lança um produto de três em três anos não precisa de um processo de lançamento detalhado. Quando ocorre um novo lançamento, a maioria dos componentes do processo de lançamento previamente desenvolvido estará desatualizada. As empresas tradicionais também não têm a oportunidade de conceber um processo de lançamento detalhado, porque não acumulam experiência suficiente para realizar lançamentos de forma a gerar um processo robusto e maduro.
Engenharia de Coordenação de Lançamento
Os bons engenheiros de software têm uma grande experiência em codificação e design, e compreendem muito bem a tecnologia dos seus próprios produtos. Contudo, os mesmos engenheiros podem não estar familiarizados com os desafios e armadilhas do lançamento de um produto a milhões de usuários, ao mesmo tempo que minimizam as interrupções e maximizam o desempenho.
A Google abordou os desafios inerentes aos lançamentos criando uma equipe de consultoria dedicada dentro da SRE encarregada da vertente técnica do lançamento de um novo produto ou característica. Equipada por engenheiros de software e engenheiros de sistemas – alguns com experiência noutras equipes da SRE – esta equipe é especializada em orientar os programadores para a construção de produtos confiáveis e rápidos que satisfaçam os padrões de robustez, escalabilidade e confiabilidade da Google. Esta equipe de consultoria, a Launch Coordination Engineering (LCE), facilita de poucas formas um processo de lançamento suave:
- Auditar produtos e serviços para o cumprimento das normas de confiabilidade e melhores práticas da Google, e fornecer ações específicas para melhorar a confiabilidade
- Atuar como ligação entre as múltiplas equipes envolvidas num lançamento
- Conduzir os aspectos técnicos de um lançamento certificando-se de que as tarefas mantêm o ímpeto
- Atuar como guardiões e assinar os lançamentos determinados como “seguro”
- Educar os programadores sobre as melhores práticas e sobre como integrar com os serviços do Google, dotando-os de documentação interna e recursos de formação para acelerar a sua aprendizagem
Membros da equipe LCE auditam serviços em vários momentos durante o ciclo de vida do serviço. A maioria das auditorias é realizada antes do lançamento de um novo produto ou serviço. Se uma equipe de desenvolvimento de produto realizar um lançamento sem apoio do SRE, o LCE fornece o conhecimento de domínio adequado para assegurar um lançamento sem problemas. Mas mesmo os produtos que já têm um forte apoio SRE, muitas vezes se envolvem com a equipe LCE durante os lançamentos críticos. Os desafios que as equipes enfrentam ao lançar um novo produto são substancialmente diferentes do funcionamento cotidiano de um serviço confiável (uma tarefa em que as equipes SRE já se destacam), e a equipe LCE pode tirar partido da experiência de centenas de lançamentos. A equipe LCE também facilita auditorias de serviço quando novos serviços se envolvem pela primeira vez com o SRE.
O papel do Engenheiro de Coordenação de Lançamento
A nossa equipe de Engenharia de Coordenação de Lançamento é composta por Engenheiros de Coordenação de Lançamento (LCEs), que ou são contratados diretamente para esta função, ou são SREs com experiência prática na gestão de serviços Google. Os LCEs são mantidos com os mesmos requisitos técnicos que qualquer outro SRE, e espera-se também que tenham fortes capacidades de comunicação e liderança – um LCE reúne partes díspares para trabalhar para um objetivo comum, medeia conflitos ocasionais, e orienta, treina e educa colegas engenheiros.
Uma equipa dedicada à coordenação de lançamentos oferece as seguintes vantagens:
Amplitude de experiência
Como uma verdadeira equipe de produtos cruzados, os membros estão ativos em quase todas as áreas de produtos da Google. O extenso conhecimento e relações cruzadas com muitas equipes em toda a empresa tornam os LCEs excelentes veículos para a transferência de conhecimento.
Perspectiva interfuncional
Os LCE têm uma visão holística do lançamento, o que lhes permite coordenar entre equipes desiguais em SRE, desenvolvimento e gestão de produtos. Esta abordagem holística é particularmente importante para lançamentos complicados que podem abranger mais de meia dúzia de equipes em múltiplos fusos horários.
Objetividade
Como consultor não partidário, um LCE desempenha um papel de equilíbrio e mediação entre as partes interessadas, incluindo SRE, desenvolvedores de produtos, gestores de produtos, e marketing.
Porque o Launch Coordination Engineer é um papel de SRE, os LCEs são incentivados a dar prioridade à confiabilidade em relação a outras preocupações. Uma empresa que não partilha os objetivos de confiabilidade do Google, mas que partilha a sua rápida taxa de mudança, pode escolher uma estrutura de incentivos diferente.
Estabelecimento de um processo de lançamento
O Google aperfeiçoou o seu processo de lançamento ao longo de um período de mais de 10 anos. Ao longo do tempo, identificamos uma série de critérios que caracterizam um bom processo de lançamento:
Peso leve
Fácil para os programadores
Robusto
Detecta erros óbvios
Exaustivo
Trata detalhes importantes de forma consistente e reprodutível
Escalonável
Acomoda um grande número de lançamentos simples e lançamentos menos complexos
Adaptável
Funciona bem para tipos comuns de lançamentos (por exemplo, adição de uma nova linguagem UI a um produto) e novos tipos de lançamentos (por exemplo, o lançamento inicial do navegador Chrome ou Google Fiber).
Como pode ver, alguns destes requisitos estão em conflito óbvio. Por exemplo, é difícil conceber um processo que seja simultaneamente leve e minucioso. Equilibrar estes critérios uns contra os outros requer um trabalho contínuo. A Google tem utilizado com sucesso algumas táticas para nos ajudar a alcançar estes critérios:
Simplicidade
Acertar no básico. Não planejar para todas as eventualidades.
Uma abordagem de alto toque
Engenheiros experientes personalizam o processo de acordo com cada lançamento.
Caminhos comuns rápidos
Identificar classes de lançamentos que seguem sempre um padrão comum (como o lançamento de um produto num novo país), e proporcionar um processo de lançamento simplificado para esta classe.
A experiência tem demonstrado que os engenheiros são suscetíveis de contornar processos que consideram demasiado onerosos ou que agregam valor insuficiente – especialmente quando uma equipe já está em modo “crunch”, e o processo de lançamento é visto como apenas mais um item bloqueando o seu lançamento. Por esta razão, a LCE deve otimizar continuamente a experiência de lançamento para atingir o equilíbrio certo entre custo e benefício.
A Lista de Controle de Lançamento
As listas de verificação são utilizadas para reduzir as falhas e assegurar a consistência e a integralidade de uma variedade de disciplinas. Exemplos comuns incluem listas de verificação pré-voo de aviação e listas de verificação cirúrgica . Da mesma forma, a LCE emprega uma lista de verificação de lançamento para qualificação de lançamento. A lista de verificação (Lista de Verificação de Coordenação de Lançamento) ajuda um LCE a avaliar o lançamento e fornece à equipe de lançamento itens de ação e indicações para mais informações. Aqui estão alguns exemplos de itens que uma lista de verificação pode incluir:
- Pergunta: Precisa de um novo nome de domínio?
- Item de ação: Coordenar com a comercialização do seu nome de domínio desejado, e solicitar o registro do domínio. Aqui está um link para o formulário de marketing.
- Pergunta: Está armazenando dados persistentes?
- Item de ação: Assegurar a implementação de backups. Aqui estão as instruções para a implementação de backups.
- Pergunta: Poderá um usuário abusar potencialmente do seu serviço?
- Item de ação: Implementar limitação de taxas e cotas. Utilize o seguinte serviço partilhado.
Na prática, há um número quase infinito de perguntas a fazer sobre qualquer sistema, e é fácil para a lista de verificação crescer até um tamanho impossível de gerir. A manutenção de uma carga controlável para os programadores requer uma curadoria cuidadosa da lista de verificação. Num esforço para travar o seu crescimento, a certa altura, acrescentar novas perguntas à lista de verificação de lançamento do Google exigiu a aprovação de um vice-presidente. A LCE utiliza agora as seguintes diretrizes:
- A importância de cada questão deve ser substanciada, idealmente por um desastre de lançamento anterior.
- Todas as instruções devem ser concretas, práticas e razoáveis para que os promotores as realizem.
A lista de controle necessita de atenção contínua para se manter relevante e atualizada: as recomendações mudam com o tempo, os sistemas internos são substituídos por sistemas diferentes, e as áreas de preocupação de lançamentos anteriores tornam-se obsoletas devido a novas políticas e processos. Os LCEs elaboram continuamente a lista de verificação e fazem pequenas atualizações quando os membros da equipe notam itens que precisam ser modificados. Uma ou duas vezes por ano, um membro da equipe revê toda a lista de verificação para identificar itens obsoletos, e depois trabalha com proprietários de serviços e peritos no assunto para modernizar seções da lista de verificação.
Conduzir a Convergência e a Simplificação
Numa grande organização, os engenheiros podem não ter conhecimento das infraestruturas disponíveis para tarefas comuns (tais como a limitação de taxas). Na falta de uma orientação adequada, é provável reimplementarem as soluções existentes. A convergência num conjunto de bibliotecas de infraestruturas comuns evita este cenário, e proporciona benefícios óbvios à empresa: reduz a duplicação de esforços, torna o conhecimento mais facilmente transferível entre serviços, e resulta num nível mais elevado de engenharia e qualidade de serviço, devido à atenção concentrada dada às infraestruturas.
Quase todos os grupos no Google participam num processo de lançamento comum, o que faz da lista de verificação de lançamento um veículo para conduzir a convergência em infraestruturas comuns. Em vez de implementar uma solução personalizada, a LCE pode recomendar infraestruturas existentes como blocos de construção – infraestruturas que já são reforçadas através de anos de experiência e que podem ajudar a mitigar os riscos de capacidade, desempenho, ou escalabilidade. Exemplos incluem infraestruturas comuns para limitação de taxas ou cotas de usuários, empurrando novos dados para servidores, ou lançando novas versões de um binário. Este tipo de padronização ajudou a simplificar radicalmente a lista de verificação de lançamento: por exemplo, longas seções da lista de verificação que tratam dos requisitos de limitação de taxas poderiam ser substituídas por uma única linha que dizia, “Implementar limitação de taxas utilizando o sistema X”.
Devido à sua vasta experiência em todos os produtos do Google, os LCE estão também numa posição única para identificar oportunidades de simplificação. Enquanto trabalham num lançamento, testemunham os obstáculos em primeira mão: que partes de um lançamento estão causando mais problemas, que medidas levam um tempo desproporcional, que problemas são resolvidos de forma independente vezes sem conta de forma semelhante, onde faltam infraestruturas comuns, ou onde existe duplicação em infraestruturas comuns. Os LCE têm várias formas de racionalizar a experiência de lançamento e de agir como defensores das equipes de lançamento. Por exemplo, os LCEs podem trabalhar com os proprietários de um processo de aprovação particularmente árduo para simplificar os seus critérios e implementar aprovações automáticas para casos comuns. Os LCEs podem também aumentar os pontos problemáticos para os proprietários de infraestruturas comuns e criar um diálogo com os clientes. Ao aproveitar a experiência adquirida ao longo de vários lançamentos anteriores, os LCEs podem dedicar mais atenção às preocupações e sugestões individuais.
Lançamento do Inesperado
Quando um projeto entra num novo produto espacial ou vertical, um LCE pode precisar criar uma lista de verificação apropriada a partir do zero. Fazê-lo envolve frequentemente a sintetização da experiência de peritos de domínio relevante. Ao elaborar uma nova lista de verificação, pode ser útil estruturar a lista de verificação em torno de temas amplos tais como confiabilidade, modos de falha, e processos.
Por exemplo, antes de lançar o Android, o Google raramente tinha lidado com dispositivos de consumo de massa com lógica do lado do cliente que não controlávamos diretamente. Embora possamos mais ou menos facilmente corrigir um bug no Gmail em horas ou dias, empurrando novas versões de JavaScript para os navegadores, tais correções não são uma opção com dispositivos móveis. Por conseguinte, os LCEs que trabalham em lançamentos móveis contrataram peritos em domínios móveis para determinar que seções das listas de verificação existentes aplicavam ou não, e onde eram necessárias novas questões de lista de verificação. Em tais conversas, é importante ter em mente a intenção de cada pergunta, a fim de evitar a aplicação irracional de uma pergunta concreta ou item de ação que não seja relevante para a concepção do produto único a ser lançado. Um LCE confrontado com um lançamento incomum deve voltar aos princípios abstratos primeiro de como executar um lançamento seguro, depois respeitar para tornar a lista de verificação concreta e útil aos programadores.
Desenvolvimento de uma lista de verificação de lançamento
Uma lista de verificação é fundamental para lançar novos serviços e produtos com confiabilidade reprodutível. A nossa lista de verificação de lançamento cresceu com o tempo e foi periodicamente selecionada por membros da equipe de Engenharia de Coordenação de Lançamento. Os detalhes de uma lista de verificação de lançamento serão diferentes para cada empresa, porque os detalhes específicos devem ser adaptados aos serviços e infraestruturas internas de uma empresa. Nas seções seguintes, extraímos uma série de temas das listas de verificação LCE do Google e damos exemplos de como tais temas podem ser desenvolvidos.
Arquitetura e Dependências
Uma revisão da arquitetura permite determinar se o serviço está utilizando corretamente a infraestrutura partilhada e identifica os proprietários da infraestrutura partilhada como partes interessadas adicionais no lançamento. A Google tem um grande número de serviços internos que são utilizados como blocos de construção para novos produtos. Durante fases posteriores de planejamento da capacidade, a lista de dependências identificadas nesta seção da lista de verificação pode ser utilizada para garantir que cada dependência é corretamente provisionada.
Exemplo de perguntas da lista de verificação
- Qual é o fluxo do seu pedido do usuário para o frontend e backend?
- Existem diferentes tipos de pedidos com diferentes requisitos de latência?
Exemplos de itens de ação
- Isolar solicitações voltadas para o usuário de solicitações não voltadas para o usuário.
- Validar as hipóteses de volume de pedidos. A visualização de uma página pode transformar-se em muitos pedidos.
Integração
Muitos serviços das empresas funcionam num ecossistema interno que implica orientações sobre como configurar máquinas, configurar novos serviços, estabelecer monitorização, integrar com balanceamento de carga, estabelecer endereços DNS, etc. Estes ecossistemas internos crescem normalmente com o tempo, e muitas vezes têm as suas próprias idiossincrasias e armadilhas para navegar. Assim, esta seção da lista de verificação variará muito de empresa para empresa.
Exemplos de itens de ação
- Estabeleça um novo nome DNS para o seu serviço.
- Configure equilibradores de carga para falar com o seu serviço.
- Configure a monitorização para o seu novo serviço.
Planejamento de capacidade
Novas características podem exibir um aumento temporário na utilização no lançamento que subsidia dentro de dias. O tipo de carga de trabalho ou de mistura de tráfego de um pico de lançamento pode ser substancialmente diferente do estado estacionário, lançando resultados de testes de carga. O interesse público é notoriamente difícil de prever, e alguns produtos Google tiveram de acomodar picos de lançamento até 15 vezes superiores aos inicialmente estimados. O lançamento inicial numa região ou país de cada vez ajuda a desenvolver a confiança para lidar com lançamentos maiores.
A capacidade interage com a redundância e a disponibilidade. Por exemplo, se precisar de três implementações replicadas para servir 100% do seu tráfego no pico, precisa manter quatro ou cinco implementações, uma ou duas das quais são redundantes, a fim de proteger os usuários de manutenção e de avarias inesperadas. O datacenter e os recursos da rede têm frequentemente um longo tempo de espera e precisam ser solicitados com antecedência suficiente para que a sua empresa os obtenha.
Exemplo de perguntas da lista de verificação
- Este lançamento está ligado a um comunicado de imprensa, publicidade, publicação num blog ou outra forma de promoção?
- Quanto tráfego e taxa de crescimento se espera durante e após o lançamento?
- Obteve todos os recursos computacionais necessários para suportar o seu tráfego?
Modos de falha
Uma análise sistemática dos possíveis modos de falha de um novo serviço garante uma elevada confiabilidade desde o início. Nesta parte da lista de verificação, examine cada componente e dependência e identifique o impacto da sua falha. O serviço pode lidar com falhas individuais da máquina? Falhas de datacenter? Falhas de rede? Como lidamos com dados de entrada ruins? Estamos preparados para a possibilidade de um ataque de negação de serviço (DoS)? O serviço pode continuar a servir em modo degradado se uma das suas dependências falhar? Como é que lidamos com a indisponibilidade de uma dependência após a inicialização do serviço? Durante o tempo de execução?
Exemplo de perguntas da lista de verificação
- Você tem algum ponto único de falha em seu design?
- Como mitiga a indisponibilidade das suas dependências?
Exemplos de itens de ação
- Implementar prazos de pedido para evitar esgotar os recursos para pedidos a longo prazo.
- Implementar a redução de carga para rejeitar novos pedidos com antecedência em situações de sobrecarga.
Comportamento do cliente
Num website tradicional, raramente há necessidade de ter em conta o comportamento abusivo de usuários legítimos. Quando cada pedido é desencadeado por uma ação do usuário, tal como um clique num link, as taxas de pedido são limitadas pela rapidez com que os usuários podem clicar. Para duplicar a carga, o número de usuário teria de duplicar.
Este axioma já não se aplica quando consideramos clientes que iniciam ações sem a entrada do usuário – por exemplo, uma aplicativo de celular que sincroniza periodicamente os seus dados na nuvem, ou um website que atualiza periodicamente. Em qualquer destes cenários, o comportamento abusivo do cliente pode muito facilmente ameaçar a estabilidade de um serviço. (Há também o tópico da proteção de um serviço contra o tráfego abusivo, como scrapers e ataques de negação de serviço – o que é diferente de projetar um comportamento seguro para clientes de primeira viagem).
Exemplo de pergunta de lista de controle
- Tem a funcionalidade de auto-salvamento/auto-completar/heartbeat?
Exemplos de itens de ação
- Assegure-se de que o seu cliente recue exponencialmente em caso de falha.
- Certifique-se de agitar as solicitações automáticas.
Processos e Automatização
O Google encoraja os engenheiros a utilizar ferramentas padrão para automatizar processos comuns. Contudo, a automatização nunca é perfeita, e cada serviço tem processos que precisam ser executados por um humano: criar uma nova versão, mover o serviço para um datacenter diferente, restaurar dados de backups, e assim por diante. Por razões de confiabilidade, nos esforçamos por minimizar pontos únicos de falha, que incluem humanos.
Estes processos restantes devem ser documentados antes do lançamento para assegurar que a informação é traduzida da mente de um engenheiro para o papel enquanto ainda está fresca, e que está disponível numa emergência. Os processos devem ser documentados de modo a que qualquer membro da equipe possa executar um determinado processo em caso de emergência.
Exemplo de pergunta de lista de controle
- Há algum processo manual necessário para manter o serviço funcionando?
Exemplos de itens de ação
- Documente todos os processos manuais.
- Documente o processo de deslocação do seu serviço para um novo datacenter.
- Automatize o processo de construção e lançamento de uma nova versão.
Processo de desenvolvimento
O Google é um utilizador extensivo do controle de versões, e quase todos os processos de desenvolvimento estão profundamente integrados com o sistema de controle de versões. Muitas das nossas melhores práticas giram em torno de como utilizar o sistema de controle de versões de forma eficaz. Por exemplo, realizamos a maior parte do desenvolvimento no ramo da linha principal, mas as versões são construídas em ramos separados por versão. Esta configuração facilita a correção de bugs numa versão, sem puxar por alterações não relacionadas a partir da linha principal.
O Google também utiliza o controle de versões para outros fins, tais como o armazenamento de ficheiros de configuração. Muitas das vantagens do controle de versão – rastreio de histórico, atribuição de alterações a indivíduos, e revisões de código – aplicam-se também a ficheiros de configuração. Em alguns casos, também propagamos automaticamente as alterações do sistema de controle de versões para os servidores ativos, de modo que um engenheiro só precisa enviar uma alteração para ativá-la.
Exemplos de itens de ação
- Verificar todos os ficheiros de código e configuração no sistema de controle de versões.
- Cortar cada lançamento num novo ramo de lançamento.
Dependências externas
Por vezes, um lançamento depende de fatores fora do controle da empresa. A identificação destes fatores permite mitigar a imprevisibilidade que eles implicam. Por exemplo, a dependência pode ser uma biblioteca de códigos mantida por terceiros, ou um serviço ou dados fornecidos por outra empresa. Quando uma falha de fornecedor, bug, erro sistemático, problema de segurança, ou limite de escalabilidade inesperado ocorre de fato, o planejamento prévio permitirá evitar ou mitigar os danos aos seus usuários. No histórico de lançamentos do Google, utilizamos filtragem e/ou reescrita de proxies, pipelines de transcodificação de dados e caches para mitigar alguns desses riscos.
Exemplo de perguntas da lista de verificação
- De que código, dados, serviços ou eventos de terceiros depende o serviço ou o lançamento?
- Algum parceiro depende do seu serviço? Em caso afirmativo, precisam ser notificados do seu lançamento?
- O que acontece se você ou o fornecedor não conseguirem cumprir um prazo de lançamento difícil?
Planejamento de lançamento
Em grandes sistemas distribuídos, poucos eventos acontecem instantaneamente. Por razões de confiabilidade, tal imediatismo não é normalmente o ideal de qualquer forma. Um lançamento complicado pode exigir a ativação de características individuais em vários subsistemas diferentes, e cada uma dessas alterações de configuração pode demorar horas para completar. Ter uma configuração funcional numa instância de teste não garante que a mesma configuração possa ser estendida para a instância ativa. Por vezes, é necessária uma dança complicada ou uma funcionalidade especial para que todos os componentes sejam lançados de forma limpa e na ordem correta.
Requisitos externos de equipes como marketing e relações públicas podem acrescentar mais complicações. Por exemplo, uma equipe pode precisar que um recurso esteja disponível a tempo para a palestra em uma conferência, mas precisa manter o recurso invisível antes da palestra.
As medidas de contingência são outra parte do planejamento do lançamento. E se não conseguir ativar a funcionalidade a tempo para a palestra principal? Por vezes, estas medidas de contingência são tão simples como preparar um slide deck de apoio que diz: “Vamos lançar esta funcionalidade nos próximos dias” em vez de “Lançamos esta funcionalidade”.
Exemplos de itens de ação
- Estabelecer um plano de lançamento que identifique as ações a empreender para lançar o serviço. Identificar quem é responsável por cada item.
- Identificar o risco nas etapas individuais de lançamento e implementar medidas de contingência.
Técnicas Selecionadas para Lançamentos Confiáveis
Como descrito noutras partes deste livro, a Google desenvolveu ao longo dos anos uma série de técnicas para o funcionamento de sistemas confiáveis. Algumas destas técnicas são particularmente bem adaptadas ao lançamento de produtos em segurança. Também oferecem vantagens durante o funcionamento regular do serviço, mas é particularmente importante acertá-las durante a fase de lançamento.
Lançamentos graduais e encenados
Um adágio da administração do sistema é “nunca mude um sistema em funcionamento”. Qualquer mudança representa risco, e o risco deve ser minimizado de modo a assegurar a confiabilidade de um sistema. O que é verdade para qualquer sistema pequeno é duplamente verdade para sistemas altamente replicados, distribuídos globalmente como os geridos pela Google.
Muito poucos lançamentos no Google são da variedade “push-button”, em que lançamos um novo produto num momento específico para que o mundo inteiro o utilize. Ao longo do tempo, a Google desenvolveu uma série de padrões que nos permitem lançar produtos e características gradualmente e assim minimizar o risco; ver A Collection of Best Practices for Production Services.
Quase todas as atualizações dos serviços da Google procedem gradualmente, de acordo com um processo definido, com etapas de verificação adequadas intercaladas. Um novo servidor poderá ser instalado em algumas máquinas num único datacenter e observado durante um período de tempo definido. Se tudo parecer bem, o servidor é instalado em todas as máquinas num único datacenter, observado novamente, e depois instalado em todas as máquinas globalmente. As primeiras fases de uma implantação são normalmente chamadas “canários” – uma alusão a canários transportados pelos mineiros para uma mina de carvão para detectar gases perigosos. Os nossos servidores canários detectam efeitos perigosos do comportamento do novo software sob tráfego real de usuários.
Os testes canários são um conceito incorporado em muitas das ferramentas internas da Google utilizadas para fazer alterações automáticas, bem como para sistemas que alteram ficheiros de configuração. Ferramentas que gerem a instalação de novo software normalmente observam o servidor recém-iniciado durante algum tempo, certificando-se de que o servidor não trava ou se comporta mal. Se a alteração não passar o período de validação, é automaticamente revertida.
O conceito de lançamentos graduais se aplica até mesmo a softwares que não são executados nos servidores do Google. Novas versões de um aplicativo Android podem ser lançadas de forma gradual, em que a versão atualizada é oferecida a um subconjunto das instalações para atualização. A percentagem de instâncias atualizadas aumenta gradualmente ao longo do tempo até atingir 100%. Este tipo de implementação é particularmente útil se a nova versão resultar em tráfego adicional para os servidores backend nos datacenters do Google. Desta forma, podemos observar o efeito nos nossos servidores à medida que lançamos gradualmente a nova versão e detectamos problemas antecipadamente.
O sistema de convite é outro tipo de implementação gradual. Frequentemente, em vez de permitir inscrições gratuitas para um novo serviço, apenas um número limitado de usuários é autorizado a se inscrever por dia. As inscrições de taxa limitada são frequentemente associadas a um sistema de convites, no qual um usuário pode enviar um número limitado de convites a amigos.
Estruturas de Feature Flag
O Google aumenta frequentemente os testes pré-lançamento com estratégias que mitigam o risco de uma interrupção. Um mecanismo para lançar mudanças lentamente, permitindo a observação do comportamento total do sistema sob cargas de trabalho reais, pode pagar pelo seu investimento de engenharia em confiabilidade, velocidade de engenharia, e tempo de colocação no mercado. Estes mecanismos têm-se mostrado particularmente úteis nos casos em que os ambientes de teste realistas são impraticáveis, ou para lançamentos particularmente complexos, cujos efeitos podem ser difíceis de prever.
Além disso, nem todas as mudanças são iguais. Por vezes, simplesmente se pretende verificar se um pequeno ajuste na interface do usuário melhora a experiência dos seus usuários. Tais pequenas alterações não devem envolver milhares de linhas de código ou um processo de lançamento pesado. Poderá querer testar centenas de tais alterações em paralelo.
Finalmente, por vezes se quer descobrir se uma pequena amostra de usuário gosta de utilizar um protótipo inicial de uma nova funcionalidade difícil de implementar. Não se quer passar meses de esforço de engenharia para fortalecer uma nova funcionalidade para atender a milhões de usuários, apenas para descobrir que a funcionalidade é um fracasso.
Para acomodar os cenários anteriores, vários produtos Google criaram estruturas de Feature Flag. Algumas dessas estruturas foram criadas para lançar gradualmente novas funcionalidades de 0% a 100% dos usuários. Sempre que um produto introduzia uma tal estrutura, a própria estrutura era reforçada tanto quanto possível para que a maioria de seus aplicativos não precisassem de qualquer envolvimento da LCE. Tais estruturas satisfazem geralmente os seguintes requisitos:
- Fazer muitas mudanças em paralelo, cada uma em poucos servidores, usuários, entidades, ou datacenters
- Aumentar gradualmente para um grupo maior mas limitado de usuários, normalmente entre 1 e 10 por cento
- Tráfego direto através de diferentes servidores dependendo dos usuários, sessões, objetos, e/ou localizações
- Tratar automaticamente a falha dos novos caminhos de código por concepção, sem afetar os usuários
- Reverter de forma independente cada uma dessas alterações imediatamente no caso de bugs graves ou efeitos secundários
- Medir até que ponto cada alteração melhora a experiência do usuário
Os quadros de estruturas de feature flag do Google dividem-se em duas classes gerais:
- As que facilitam principalmente melhorias na interface do usuário
- Aqueles que suportam mudanças arbitrárias no lado do servidor e na lógica empresarial
A estrutura mais simples de feature flag para alterações de interface de usuário num serviço sem estado é um reescritor de carga útil HTTP em servidores de aplicativos frontend, limitado a um subconjunto de cookies ou outro atributo de pedido/resposta HTTP semelhante. Um mecanismo de configuração pode especificar um identificador associado aos novos caminhos de código e ao âmbito da alteração (por exemplo, intervalos de módulos hash cookies), listas brancas, e listas negras.
Os serviços estatais tendem a limitar as feature flags a um subconjunto de identificadores únicos de usuários com sessão iniciada ou às entidades reais do produto acessadas, tais como a identificação de documentos, folhas de cálculo, ou objetos de armazenamento. Em vez de reescrever as cargas úteis HTTP, os serviços estatais são mais propensos a substituir ou reencaminhar pedidos para servidores diferentes, dependendo da alteração, conferindo a capacidade de testar uma lógica empresarial melhorada e novas características mais complexas.
Lidar com o Comportamento Abusivo do Cliente
O exemplo mais simples de comportamento abusivo do cliente é um erro de julgamento das taxas de atualização. Um novo cliente que sincroniza a cada 60 segundos, em oposição a cada 600 segundos, causa 10 vezes a carga no serviço. O comportamento de nova tentativa tem uma série de armadilhas que afetam os pedidos iniciados pelo usuário, bem como os pedidos iniciados pelo cliente. Tomemos o exemplo de um serviço que está sobrecarregado e que, por isso, está falhando em algumas solicitações: se os clientes tentarem novamente as solicitações com falha, eles adicionarão carga a um serviço já sobrecarregado, resultando em mais tentativas e ainda mais solicitações. Em vez disso, os clientes precisam reduzir a frequência das tentativas, normalmente adicionando um atraso exponencialmente crescente entre tentativas, além de considerarem cuidadosamente os tipos de erros que justificam uma nova tentativa. Por exemplo, um erro de rede geralmente justifica uma nova tentativa, mas um erro 4xx HTTP (que indica um erro do lado do cliente) normalmente não o justifica.
A sincronização intencional ou inadvertida de pedidos automatizados num rebanho estrondoso (muito semelhante aos descritos nos capítulos Programação Periódica Distribuída com Cron e Pipelines de Processamento de Dados) é outro exemplo comum de comportamento abusivo do cliente. Um desenvolvedor de aplicativo de telefone pode decidir que 2 da manhã é um bom momento para baixar atualizações, porque o usuário provavelmente está dormindo e não será incomodado pelo download. No entanto, esse design resulta em uma enxurrada de solicitações ao servidor de download às 2 da manhã todas as noites e quase nenhuma solicitação em nenhum outro momento. Em vez disso, cada cliente deve escolher a hora para este tipo de pedido de forma aleatória.
A aleatoriedade também precisa ser injetada noutros processos periódicos. Para voltar às tentativas anteriormente mencionadas: tomemos o exemplo de um cliente que envia um pedido, e quando se depara com uma falha, faz a tentativa após 1 segundo, depois 2 segundos, depois 4 segundos, e assim por diante. Sem aleatoriedade, um breve pico de pedido que leva a um aumento da taxa de erro poderia repetir-se devido a tentativas após 1 segundo, depois 2 segundos, depois 4 segundos, e assim por diante. A fim de equilibrar estes eventos sincronizados, cada atraso precisa ser agitado (ou seja, ajustado por uma quantidade aleatória).
A capacidade de controlar o comportamento de um cliente a partir do lado do servidor provou ser uma ferramenta importante no passado. Para um aplicativo em um dispositivo, esse controle pode significar instruir o cliente a fazer check-in periodicamente com o servidor e baixar um arquivo de configuração. O arquivo pode habilitar ou desabilitar determinados recursos ou definir parâmetros, tais como a frequência com que o cliente sincroniza ou a frequência com que volta a testar.
A configuração do cliente pode até habilitar uma funcionalidade totalmente nova voltada para o usuário. Ao hospedar o código que dá suporte à nova funcionalidade no aplicativo do cliente antes de ativar esse recurso, reduzimos bastante o risco associado a um lançamento. O lançamento de uma nova versão torna-se muito mais fácil se não precisarmos manter pistas de lançamento paralelas para uma versão com a nova funcionalidade versus sem a funcionalidade. Isto é particularmente verdade se não estivermos lidando com uma única peça de nova funcionalidade, mas sim com um conjunto de funcionalidades independentes que podem ser lançadas em horários diferentes, o que implicaria manter uma explosão combinatória de versões diferentes.
Ter este tipo de funcionalidade adormecida também facilita o aborto de lançamentos quando são descobertos efeitos adversos durante uma implementação. Nesses casos, podemos simplesmente desligar a funcionalidade, iterar, e lançar uma versão atualizada do aplicativo. Sem este tipo de configuração de cliente, teríamos de fornecer uma nova versão do aplicativo sem a funcionalidade, e atualizar o aplicativo em todos os telefones dos usuários.
Comportamento de sobrecarga e testes de carga
As situações de sobrecarga são um modo de falha particularmente complexo, pelo que merecem atenção adicional. O sucesso em fuga é normalmente a causa mais bem-vinda de sobrecarga quando um novo serviço é lançado, mas existem inúmeras outras causas, incluindo falhas de equilíbrio de carga, interrupções de máquinas, comportamento sincronizado do cliente, e ataques externos.
Um modelo ingênuo pressupõe que a utilização de CPU numa máquina que forneça um determinado serviço é linearmente dimensionada com a carga (por exemplo, número de pedidos ou quantidade de dados processados), e uma vez esgotada a CPU disponível, o processamento torna-se simplesmente mais lento. Infelizmente, os serviços raramente se comportam desta forma ideal no mundo real. Muitos serviços são muito mais lentos quando não são carregados, geralmente devido ao efeito de vários tipos de caches, tais como caches de CPU, caches JIT, e caches de dados específicos do serviço. À medida que a carga aumenta, há normalmente uma janela em que o uso e a carga da CPU no serviço correspondem linearmente, e os tempos de resposta permanecem na sua maioria constantes.
A dada altura, muitos serviços atingem um ponto de não linearidade à medida que se aproximam da sobrecarga. Nos casos mais benignos, os tempos de resposta começam simplesmente a aumentar, resultando numa experiência degradada do usuário, mas não necessariamente causando uma interrupção (embora uma dependência lenta possa causar erros visíveis ao usuário na stack, devido à ultrapassagem dos prazos de RPC). Nos casos mais drásticos, um serviço fica completamente bloqueado em resposta a uma sobrecarga.
Para citar um exemplo específico de comportamento de sobrecarga: um serviço registra informações de depuração em resposta a erros de backend. Verificou-se que a informação de depuração de registro era mais cara do que o tratamento da resposta de backend num caso normal. Portanto, à medida que o serviço se tornava sobrecarregado e temporizava as respostas backend dentro da sua própria stack RPC, o serviço gastava ainda mais tempo da CPU a registrar estas respostas, temporizando entretanto mais pedidos até que o serviço parasse completamente. Nos serviços executados na Máquina Virtual Java (JVM), um efeito semelhante de travamento é às vezes chamado de “GC (recolha de lixo) de trituração”. Neste cenário, a gestão da memória interna da máquina virtual corre em ciclos cada vez mais próximos, tentando liberar memória até que a maior parte do tempo da CPU seja consumido pela gestão da memória.
Infelizmente, é muito difícil prever desde os primeiros princípios como um serviço irá reagir à sobrecarga. Portanto, os testes de carga são uma ferramenta inestimável, tanto por razões de confiabilidade como de planejamento da capacidade, e os testes de carga são necessários para a maioria dos lançamentos.
Desenvolvimento da LCE
Nos anos de formação da Google, o tamanho da equipe de engenharia duplicou todos os anos durante vários anos seguidos, fragmentando o departamento de engenharia em muitas pequenas equipes que trabalham em muitos novos produtos e características experimentais. Num tal clima, engenheiros novatos correm o risco de repetir os erros dos seus antecessores, especialmente quando se trata de lançar com sucesso novas características e produtos.
Para mitigar a repetição de tais erros, capturando as lições aprendidas de lançamentos passados, um pequeno grupo de engenheiros experientes, chamados “Engenheiros de Lançamento”, voluntariaram-se para atuar como uma equipe de consultores. Os Engenheiros de Lançamento desenvolveram listas de verificação para o lançamento de novos produtos, cobrindo tópicos como por exemplo:
- Quando consultar o departamento jurídico
- Como selecionar nomes de domínio
- Como registrar novos domínios sem erros de configuração do DNS
- Desenho de engenharia comum e armadilhas de implantação da produção
As “Revisões de Lançamento”, como vieram a ser chamadas as sessões de consultoria dos Engenheiros de Lançamento, tornaram-se uma prática comum dias a semanas antes do lançamento de muitos novos produtos.
No espaço de dois anos, os requisitos de implementação de produtos na lista de verificação de lançamento tornaram-se longos e complexos. Combinado com a crescente complexidade do ambiente de implementação do Google, tornou-se cada vez mais difícil para os engenheiros de produto manter-se atualizados sobre a forma de efetuar alterações em segurança. Ao mesmo tempo, a organização SRE estava crescendo rapidamente, e as SREs inexperientes eram por vezes excessivamente cautelosas e avessas a mudanças. A Google corria o risco de que as negociações resultantes entre estas duas partes reduziriam a velocidade de lançamento de produtos/funções.
Para mitigar este cenário do ponto de vista da engenharia, a SRE contou com uma pequena equipe de LCEs em tempo integral, em 2004. Foram responsáveis por acelerar os lançamentos de novos produtos e funcionalidades, ao mesmo tempo que aplicavam os conhecimentos especializados da SRE para garantir que a Google enviasse produtos confiáveis com alta disponibilidade e baixa latência.
Os LCEs foram responsáveis por assegurar que os lançamentos fossem executados rapidamente sem que os serviços caíssem, e que se um lançamento falhasse, não derrubaria outros produtos. Os LCEs eram também responsáveis por manter os interessados informados sobre a natureza e probabilidade de tais falhas sempre que os cantos fossem cortados, a fim de acelerar o tempo de chegada ao mercado. As suas sessões de consultoria foram formalizadas como Revisões de Produção.
Evolução da lista de verificação da LCE
À medida que o ambiente do Google se tornou mais complexo, o mesmo aconteceu com a lista de verificação da Engenharia de Coordenação de Lançamento (ver Lista de Verificação da Coordenação de Lançamento) e com o volume de lançamentos. Em 3,5 anos, um LCE realizou 350 lançamentos através da Lista de Controle LCE. Como a equipe teve em média cinco engenheiros durante este período de tempo, isto traduz-se numa produção de lançamento Google de mais de 1.500 lançamentos em 3,5 anos!
Embora cada pergunta da lista de verificação LCE seja simples, muita complexidade é incorporada no que motivou a pergunta e as implicações da sua resposta. Para compreender plenamente este grau de complexidade, uma nova contratação LCE requer cerca de seis meses de formação.
À medida que o volume de lançamentos crescia, acompanhando a duplicação anual da equipe de engenharia do Google, os LCEs procuravam formas de racionalizar as suas revisões. Os LCEs identificaram categorias de lançamentos de baixo risco que eram altamente improváveis de enfrentar ou causar percalços. Por exemplo, um lançamento de funcionalidades que não envolvesse novos executáveis de servidor e um aumento de tráfego inferior a 10% seria considerado de baixo risco. Tais lançamentos eram confrontados com uma lista de verificação quase trivial, enquanto os lançamentos de maior risco eram submetidos a uma gama completa de verificações e saldos. Até 2008, 30% das revisões foram consideradas de baixo risco.
Simultaneamente, o ambiente do Google foi aumentando, eliminando as restrições a muitos lançamentos. Por exemplo, a aquisição do YouTube forçou a Google a construir a sua rede e a utilizar a largura de banda de forma mais eficiente. Isto significava que muitos produtos mais pequenos “caberiam dentro das brechas”, evitando complexos processos de planejamento e aprovisionamento da capacidade da rede, acelerando assim os seus lançamentos. A Google também começou a construir datacenters muito grandes, capazes de alojar vários serviços dependentes sob o mesmo teto. Este desenvolvimento simplificou o lançamento de novos produtos que necessitavam de grandes quantidades de capacidade em múltiplos serviços pré-existentes dos quais dependiam.
Problemas que a LCE não resolveu
Embora os LCEs tentassem manter a burocracia das revisões a um nível mínimo, tais esforços eram insuficientes. Em 2009, as dificuldades de lançar um pequeno serviço novo no Google tinham-se tornado uma lenda. Serviços que cresceram a uma escala maior enfrentaram o seu próprio conjunto de problemas que a Coordenação de Lançamento não conseguiu resolver.
Mudanças de escalabilidade
Quando os produtos são bem sucedidos muito para além de quaisquer estimativas iniciais, e a sua utilização aumenta em mais de duas ordens de grandeza, o acompanhamento da sua carga exige muitas mudanças no design. Tais alterações de escalabilidade, combinadas com adições contínuas de características, tornam frequentemente o produto mais complexo, frágil, e difícil de operar. A dada altura, a arquitetura original do produto torna-se incontrolável e o produto precisa ser completamente rearquitetado. Pesquisar o produto e depois migrar todos os usuários da arquitetura antiga para a nova arquitetura requer um grande investimento de tempo e recursos tanto dos programadores como das SREs, diminuindo a taxa de desenvolvimento de novas funcionalidades durante esse período.
Crescente carga operacional
Ao executar um serviço após o seu lançamento, a carga operacional, a quantidade de engenharia manual e repetitiva necessária para manter um sistema funcionando, tende a crescer com o tempo, a menos que sejam feitos esforços para controlar tal carga. O ruído das notificações automáticas, a complexidade dos procedimentos de implementação, e as despesas gerais do trabalho de manutenção manual tendem a aumentar com o tempo e a consumir quantidades crescentes da largura de banda do proprietário do serviço, deixando à equipe menos tempo para o desenvolvimento de funcionalidades. A SRE tem um objetivo anunciado internamente de manter o trabalho operacional abaixo de um máximo de 50%; ver Eliminação do Trabalho. Ficar abaixo deste máximo requer um acompanhamento constante das fontes de trabalho operacional, bem como um esforço dirigido para remover essas fontes.
Rotatividade da infraestrutura
Se a infraestrutura subjacente (tais como sistemas de gestão de clusters, armazenamento, monitorização, balanceamento de carga e transferência de dados) estiver mudando devido ao desenvolvimento ativo pelas equipes de infraestruturas, os proprietários dos serviços que funcionam nas infraestruturas devem investir grandes quantidades de trabalho para simplesmente acompanharem as mudanças na infraestrutura. Como as características da infraestrutura em que os serviços dependem são depreciadas e substituídas por novas características, os proprietários dos serviços devem modificar continuamente as suas configurações e reconstruir os seus executáveis, consequentemente “funcionando rapidamente apenas para se manterem no mesmo local”. A solução para este cenário é decretar algum tipo de política de redução de rotatividade que proíba os engenheiros de infraestruturas de liberar funcionalidades incompatíveis com o passado até que também automatizem a migração dos seus clientes para a nova funcionalidade. A criação de ferramentas de migração automática para acompanhar as novas funcionalidades minimiza o trabalho imposto aos proprietários de serviços para acompanharem a rotatividade da infraestrutura.
Resolver esses problemas exige esforços de toda a empresa que estão muito além do escopo da LCE: uma combinação de melhores APIs e estruturas de plataforma (ver Capítulo 32), automação contínua de construção e teste, e melhor padronização e automatização em todos os serviços de produção do Google.
Conclusão
As empresas em rápido crescimento com uma elevada taxa de mudança nos produtos e serviços podem se beneficiar do equivalente a uma função de Engenharia de Coordenação de Lançamento. Uma tal equipe é especialmente valiosa se uma empresa planeja duplicar os seus criadores de produtos a cada um ou dois anos, se deve dimensionar os seus serviços para centenas de milhões de usuários, e se a confiabilidade apesar de uma elevada taxa de mudança é importante para os seus usuários.
A equipe LCE foi a solução do Google para o problema de alcançar a segurança sem impedir a mudança. Este capítulo introduziu algumas das experiências acumuladas pelo nosso papel único de LCE ao longo de um período de 10 anos, exatamente em tais circunstâncias. Esperamos que a nossa abordagem ajude a inspirar outros que enfrentam desafios semelhantes nas suas respectivas organizações.