Inimigos da realidade por 12f-2No final de abril, enquanto os caminhantes brancos sitiavam Winterfell, algo mais interessante aconteceu para nós, fizemos um lançamento incomum. Em princípio, lançamos constantemente novos recursos no prod (como todos os outros). Mas este não era como todos os outros. Sua escala era tal que quaisquer possíveis erros que pudéssemos cometer afetariam todos os nossos serviços e usuários. Como resultado, lançamos tudo de acordo com o plano, no tempo de inatividade planejado e anunciado, sem consequências para a venda. O artigo é sobre como conseguimos isso e como aqueles que desejam podem repetir isso em casa.
Agora não vou descrever nossas decisões arquitetônicas e técnicas, contar como tudo funciona. Essas são notas marginais mais prováveis de como ocorreu um dos lançamentos mais difíceis, que observei e em que participei diretamente. Não pretendo ser detalhes completos ou técnicos, talvez eles apareçam em outro artigo.
Histórico + que tipo de funcionalidade é essa
Estamos construindo a plataforma de nuvem
Mail.ru Cloud Solutions (MCS), onde trabalho como CTO. E agora - é hora de conectar-se à nossa plataforma IAM (Identity and Access Management), que fornece gerenciamento unificado de todas as contas de usuários, usuários, senhas, funções, serviços e muito mais. Por que é necessário na nuvem é uma pergunta óbvia: todas as informações do usuário são armazenadas nela.
Normalmente, essas coisas começam a ser construídas no início de qualquer projeto. Mas o MCS tem sido historicamente um pouco diferente. O MCS foi construído em duas partes:
- Openstack com seu próprio módulo de autorização Keystone,
- Hotbox (armazenamento S3) com base no projeto Cloud Mail.ru,
em torno do qual novos serviços apareceram.
Em essência, esses eram dois tipos diferentes de autorização. Além disso, usamos alguns desenvolvimentos separados do Mail.ru, por exemplo, o armazenamento geral de senhas do Mail.ru, além de um conector openid auto-escrito, que habilitou o SSO (autorização de passagem) no painel Horizon de máquinas virtuais (UI nativa OpenStack).
Fazer o IAM significava combinar tudo isso em um único sistema, completamente nosso. Ao mesmo tempo, não perca nenhuma funcionalidade ao longo do caminho, crie uma reserva para o futuro, o que nos permitirá modificá-la de forma transparente sem refatorar e escalá-la em termos de funcionalidade. Também no início, os usuários apareciam como um modelo de acesso a serviços (RBAC central, controle de acesso baseado em funções) e algumas outras pequenas coisas.
A tarefa acabou não sendo trivial: python e perl, vários backends, serviços escritos independentemente, várias equipes de desenvolvimento e administradores. E o mais importante, milhares de usuários ativos no sistema de produção de combate. Tudo isso tinha que ser escrito e, o mais importante, lançado sem vítimas.
O que vamos lançar
Se for muito rude, em algum momento em quatro meses, preparamos o seguinte:
- Eles criaram vários novos demônios que agregavam funções que anteriormente funcionavam em diferentes partes da infraestrutura. Outros serviços receberam um novo back-end na forma desses demônios.
- Criamos nosso próprio repositório central de senhas e chaves, disponível para todos os nossos serviços, que podem ser modificados livremente conforme necessário.
- Do zero, eles escreveram quatro novos back-ends para o Keystone (usuários, projetos, funções, atribuições de funções), que, de fato, substituíram sua base e agora atuam como um repositório único de nossas senhas de usuários.
- Ensinamos todos os nossos serviços Openstack a buscar suas políticas em um serviço de política de terceiros em vez de ler essas políticas localmente em cada servidor (sim, por padrão, o Openstack funciona assim!)
Uma alteração tão grande requer alterações grandes, complexas e, o mais importante, síncronas em vários sistemas escritos por diferentes equipes de desenvolvimento. Após a montagem, todo o sistema deve funcionar.
Como lançar essas alterações e não estragar tudo? Primeiro, decidimos olhar um pouco para o futuro.
Estratégia de implantação
- Seria possível lançar em várias etapas, mas isso aumentaria o tempo de desenvolvimento em três vezes. Além disso, por algum tempo, teríamos uma dessincronização completa de dados nos bancos de dados. Eu precisaria escrever minhas próprias ferramentas de sincronização e viver com vários data warehouses por um longo tempo. E isso cria uma grande variedade de riscos.
- Tudo o que eles poderiam preparar de forma transparente para o usuário foi feito com antecedência. Demorou 2 meses.
- Permitimos um tempo de inatividade por várias horas - apenas para operações do usuário para criar e modificar recursos.
- Para o trabalho de todos os recursos já criados, o tempo de inatividade era inaceitável. Planejamos que, ao implantar, os recursos funcionem sem tempo de inatividade e afetem os clientes.
- Para reduzir o impacto em nossos clientes, se algo der errado, decidimos lançar no domingo à noite. À noite, menos clientes gerenciam máquinas virtuais.
- Avisamos a todos os nossos clientes que, durante o período escolhido para a implantação, o gerenciamento de serviços não estará disponível.
Digressão: o que é lançamento?
<filosofia do cuidado>Cada especialista em TI responderá com facilidade o que é o lançamento. Você coloca CI / CD e automaticamente tudo é entregue ao produto. :)
Claro, isso é verdade. Mas a dificuldade é que, com as ferramentas modernas para automatizar a entrega de códigos, o entendimento de rolar em si é perdido. Como você se esquece da invenção épica da roda, olhando para veículos modernos. Tudo é tão automatizado que o lançamento é feito sem a realização de todo o cenário.
E a imagem toda é a seguinte. A distribuição consiste em quatro grandes aspectos:
- Entrega de código, incluindo modificação de dados. Por exemplo, sua migração.
- Reversão de código - a capacidade de retornar se algo der errado. Por exemplo, através da criação de backups.
- O tempo de cada operação de lançamento / reversão. É preciso entender o tempo de qualquer operação dos dois primeiros pontos.
- Funcionalidade afetada. É necessário avaliar os efeitos positivos e possíveis negativos negativos.
Todos esses aspectos devem ser levados em consideração para a implementação bem-sucedida. Geralmente, eles avaliam apenas o primeiro, na melhor das hipóteses, o segundo ponto e, em seguida, o lançamento é considerado bem-sucedido. Mas o terceiro e o quarto são ainda mais importantes. Qual usuário gostará se o lançamento demorar 3 horas em vez de um minuto? Ou se algo supérfluo afeta a distribuição? Ou o tempo de inatividade de um serviço levará a consequências imprevisíveis?
Ato 1..n, preparação para liberação
A princípio, pensei em descrever brevemente nossas reuniões: toda a equipe, suas partes, montes de discussões em pontos de café, disputas, testes, tempestades cerebrais. Então pensei que seria supérfluo. Quatro meses de desenvolvimento sempre consistem nisso, especialmente quando você escreve não algo que possa ser entregue constantemente, mas um grande recurso em um sistema vivo. O que afeta todos os serviços, mas os usuários não devem alterar nada, exceto o "botão único na interface da web".
Nosso entendimento de como implementar, mudou a cada nova reunião e de maneira muito significativa. Por exemplo, atualizaríamos toda a nossa base de faturamento. Mas eles calcularam o tempo e perceberam que era impossível fazer isso em um tempo razoável de implementação. Levamos quase uma semana adicional para fragmentar e arquivar o banco de dados de cobrança. E quando a velocidade de lançamento prevista não funcionou depois disso, eles solicitaram um ferro adicional mais poderoso, onde arrastaram toda a base. Não que não quiséssemos fazer isso antes, mas a atual necessidade de implementação não nos deixou nenhuma opção.
Quando um de nós tinha dúvidas de que o lançamento poderia afetar a disponibilidade de nossas máquinas virtuais, passamos uma semana para testar, experimentar, analisar o código e entendemos claramente que isso não aconteceria em nossa produção, e mesmo as pessoas mais duvidosas concordaram com isso.
Enquanto isso, o pessoal do suporte técnico realizou seus experimentos independentes para escrever aos clientes instruções sobre como se conectar, que deveriam mudar após o lançamento. Eles trabalharam em um UX fácil de usar, prepararam instruções e forneceram conselhos pessoais.
Automatizamos todas as operações de implementação possíveis. Qualquer operação era roteirizada, mesmo a mais simples, fazia testes constantemente. Eles discutiram sobre a melhor forma de desativar o serviço - abaixe o daemon ou bloqueie o acesso ao serviço com um firewall. Uma lista de verificação das equipes foi criada para cada estágio de implantação, sendo constantemente atualizada. Desenhamos e atualizamos constantemente o gráfico de Gantt para todos os trabalhos de lançamento, com horários.
E assim ...
Ato final, antes do lançamento
... é hora de lançar.
Como diz o ditado, uma obra de arte não pode ser concluída, apenas para terminar de trabalhar nela. É necessário fazer um esforço de força de vontade, entendendo que você não encontrará tudo, mas acreditando que fez todas as suposições razoáveis, desde todos os casos possíveis, fechou todos os bugs críticos e todos os participantes fizeram tudo o que podiam. Quanto mais código você distribuir, mais difícil será convencer-se disso (além disso, alguém entende que é impossível prever tudo).
Tomamos a decisão de que estávamos prontos para lançar quando estávamos convencidos de que fizemos todo o possível para fechar todos os riscos para nossos usuários associados a efeitos e paradas inesperadas. Ou seja, tudo pode dar errado, exceto:
- O efeito (sagrado para nós, o mais precioso) da infraestrutura do usuário,
- Funcionalidade: o uso do nosso serviço após a implantação deve ser o mesmo de antes.
Lançamento
Dois estão rolando, 8 não interferemLevamos um tempo de inatividade para todas as solicitações de usuários em 7 horas. No momento, temos um plano de implementação e um plano de reversão.
- O lançamento em si leva cerca de 3 horas.
- 2 horas - para teste.
- 2 horas - uma reserva para uma possível reversão de alterações.
Um gráfico de Gantt foi compilado para cada ação, quanto tempo leva, o que ocorre em sequência, o que é feito em paralelo.
Uma fatia do gráfico de distribuição de Gantt, uma das versões anteriores (sem execução paralela). A ferramenta de sincronização mais valiosaTodos os participantes têm seu papel na implementação, de quais tarefas executam e pelas quais são responsáveis. Estamos tentando ativar cada estágio automaticamente, reverter, coletar feedback e rever novamente.
Crônica de eventos
Então, 15 pessoas vieram trabalhar no domingo, 28 de abril, às 22 horas. Além dos principais participantes, alguns vieram apenas para apoiar a equipe, pelos quais agradecemos especialmente a eles.
Separadamente, vale ressaltar que nosso testador de chave está de férias. É impossível lançar sem teste, estamos trabalhando em opções. Uma colega concorda em nos testar fora das férias, pelas quais ela tem uma gratidão imensurável de toda a equipe.
00:00. PararParamos as solicitações dos usuários, desligamos a placa de identificação, dizem eles, o trabalho técnico. Monitorando grita, mas tudo está normal. Verificamos que nada caiu, exceto que deveria. E começamos a trabalhar na migração.
Todo mundo tem um plano de implementação impresso para os pontos, todo mundo sabe quem está fazendo o que e em que momento. Após cada ação, verificamos os horários que não os excedem e tudo corre conforme o planejado. Aqueles que não estão envolvidos no lançamento diretamente no estágio atual, preparam-se lançando um brinquedo on-line (Xonotic, tipo 3 kwaki), para não interferir com os colegas. :)
02:00 LançadoUma surpresa agradável - terminamos o lançamento uma hora antes, devido à otimização de nossos bancos de dados e scripts de migração. O grito universal "rolou!" Todas as novas funções no prod, mas até agora só podemos ver a interface. Todo mundo entra no modo de teste, organizado em montões e começa a ver o que aconteceu no final.
Não deu muito certo, entendemos isso após 10 minutos, quando nada está conectado e não funciona nos projetos dos membros da equipe. Sincronização rápida, exprima nossos problemas, priorize, entre em equipes e entre em depuração.
2:30 da manhã Dois grandes problemas vs quatro olhosEncontramos dois grandes problemas. Percebemos que os clientes não verão alguns serviços conectados e haverá problemas com as contas dos parceiros. Ambos estão associados a scripts de migração imperfeitos para alguns casos extremos. Precisamos consertar isso agora.
Nós escrevemos consultas que corrigem isso, pelo menos 4 olhos. Nós rolamos no pré-portão para garantir que eles funcionem e não quebrem nada. Você pode continuar. Paralelamente, começa nosso teste de integração usual, que detecta mais alguns problemas. Todos eles são pequenos, mas também precisam ser reparados.
03:00 -2 problemas +2 problemasOs dois grandes problemas anteriores foram corrigidos, quase todos os menores também. Todos desocupados em correções trabalham ativamente em suas contas e relatam o que encontram. Priorizamos, distribuímos por comandos, deixamos acríticos pela manhã.
Executando os testes novamente, eles revelam dois novos grandes problemas. Nem todas as políticas de serviço chegaram corretamente, portanto, algumas solicitações de usuário não são autenticadas. Além de um novo problema com as contas de parceiros. Corremos para assistir.
03:20. Sincronização de emergênciaUm novo problema foi corrigido. Para o segundo, organizamos uma sincronização de emergência. Entendemos o que está acontecendo: a correção anterior corrigiu um problema, mas criou outro. Damos um tempo para descobrir como fazê-lo da maneira certa e sem consequências.
03:30 Seis olhosEstamos cientes do que deve ser o estado final da base para que tudo seja bom para todos os parceiros. Nós escrevemos um pedido em 6 olhos, rolamos na pré-haste, testamos, rolamos no prod.
04:00. Tudo funcionaTodos os testes foram aprovados, nenhum problema crítico é visível. De tempos em tempos, algo não funciona em equipe, respondemos rapidamente. Na maioria das vezes, o alarme é falso. Mas às vezes algo não chegou, em algum lugar uma página separada não funciona. Nós sentamos, consertamos, consertamos, consertamos. Uma equipe separada lança o último grande recurso - cobrança.
04:30. Ponto sem retornoO ponto de não retorno está próximo, ou seja, o momento em que, se começarmos a retroceder, não encontraremos o tempo de inatividade que nos é dado. Há problemas com o faturamento, que sabe tudo e anota, mas teimosamente não deseja anular o dinheiro dos clientes. Existem vários erros em páginas individuais, ações e status. A principal funcionalidade funciona, todos os testes passam com sucesso. Decidimos que a distribuição ocorreu, não iremos reverter.
06:00 Abrimos em tudo na interface do usuárioOs erros foram corrigidos. Alguns usuários que não afetam são deixados para mais tarde. Abrimos a interface para todos. Continuamos a invocar o faturamento, aguardamos o feedback dos usuários e monitoramos os resultados.
07:00 Problemas de carregamento da APITorna-se claro que temos um pouco de carga planejada incorretamente em nossa API e testamos essa carga, o que não conseguiu identificar o problema. Como resultado, ± 5% dos pedidos falham. Estamos nos mobilizando, procurando uma razão.
O faturamento é teimoso, também não quer funcionar. Decidimos adiá-lo para mais tarde, a fim de fazer alterações em um modo calmo. Ou seja, todos os recursos nele são acumulados, mas as baixas contábeis dos clientes não são aprovadas. Obviamente, isso é um problema, mas, comparado ao lançamento geral, não parece fundamental.
08:00. Fix APILançamos uma correção para a carga, as falhas restantes. Começamos a ir para casa.
10h TodosTudo está consertado. No monitoramento e os clientes ficam quietos, a equipe vai gradualmente para a cama. O faturamento permanece, nós o restauraremos amanhã.
Depois, durante o dia, ocorreram lançamentos que corrigiam os registros, notificações, códigos de retorno e códigos personalizados de alguns de nossos clientes.
Portanto, o lançamento foi bem-sucedido! É claro que poderia ser melhor, mas tiramos conclusões sobre o que não tínhamos o suficiente para alcançar a perfeição.
Total
Dois meses após a preparação ativa para o lançamento, 43 tarefas foram concluídas, com duração de algumas horas a vários dias.
Durante o lançamento:
- demônios novos e modificados - 5 peças, substituindo 2 monólitos;
- alterações dentro dos bancos de dados - todos os 6 bancos de dados com dados do usuário são afetados, descarregamentos de três bancos de dados antigos para um novo são concluídos;
- frontend completamente refeito;
- o número de código extraído - 33 mil linhas de novo código, thousand 3 mil linhas de código nos testes, ≈ 5 mil linhas de código de migração;
- todos os dados estão intactos, nenhuma máquina virtual do cliente sofreu. :)
Boas práticas para uma boa implantação
Fomos guiados por eles nessa situação difícil. Mas, de um modo geral, é útil observá-los em qualquer implementação. Porém, quanto mais difícil o lançamento, maior o papel que eles desempenham.
- A primeira coisa que você precisa fazer é entender como a distribuição pode afetar ou afetar os usuários. Haverá tempo de inatividade? Se sim, então o que é tempo de inatividade? Como isso afetará os usuários? Quais são os melhores e os piores cenários? E feche os riscos.
- Planeje tudo. Em cada estágio, você precisa entender todos os aspectos da implementação:
- entrega de código;
- reversão de código;
- hora de cada operação;
- funcionalidade afetada.
- Execute cenários até que todos os estágios de lançamento sejam claros, bem como os riscos em cada um deles. Em caso de dúvida, você pode fazer uma pausa e explorar o estágio duvidoso separadamente.
- Cada estágio pode e deve ser aprimorado se ajudar nossos usuários. Por exemplo, reduzirá o tempo de inatividade ou removerá alguns riscos.
- O teste de reversão é muito mais importante do que a entrega de código. É necessário verificar se, como resultado da reversão, o sistema retornará ao seu estado original, confirme com testes.
- Tudo o que pode ser automatizado deve ser automatizado. Tudo o que não pode ser automatizado deve ser pré-escrito na folha de dicas.
- Registre critérios de sucesso. Que funcionalidade deve estar disponível e a que horas? Se isso não acontecer, inicie um plano de reversão.
- E o mais importante, pessoas. Todos devem estar cientes do que ele está fazendo, do que e do que depende de suas ações no processo de implantação.
E se em uma frase, com um bom planejamento e elaboração, você poderá implementar o que quiser, sem consequências para a venda. Mesmo isso afeta todos os seus serviços em prod.