Unha historia de lanzamento que afectou todo

Unha historia de lanzamento que afectou todo
Inimigos da Realidade por 12f-2

A finais de abril, mentres os White Walkers asediaban Winterfell, pasounos algo máis interesante; fixemos un lanzamento inusual. En principio, estamos constantemente lanzando novas funcións na produción (como todo o mundo). Pero este era diferente. A escala foi tal que calquera posible erro que puidésemos cometer afectaría a todos os nosos servizos e usuarios. Como resultado, desenrolamos todo segundo o plan, dentro do período de inactividade planificado e anunciado, sen consecuencias para as vendas. O artigo trata de como conseguimos isto e como calquera pode repetilo na casa.

Non vou describir agora as decisións arquitectónicas e técnicas que tomamos nin contar como funciona todo. Son máis ben notas nas marxes sobre como se produciu un dos lanzamentos máis difíciles, que observei e no que estiven directamente implicado. Non reclamo a integridade nin os detalles técnicos; quizais aparezan noutro artigo.

Fondo + que tipo de funcionalidade é esta?

Estamos construíndo unha plataforma na nube Solucións na nube Mail.ru (MCS), onde traballo como director técnico. E agora é o momento de engadir IAM (Identity and Access Management) á nosa plataforma, que ofrece unha xestión unificada de todas as contas de usuarios, usuarios, contrasinais, roles, servizos e moito máis. Por que é necesario na nube é unha pregunta obvia: toda a información do usuario almacénase nela.

Normalmente tales cousas comezan a construírse ao comezo de calquera proxecto. Pero historicamente as cousas foron un pouco diferentes en MCS. MCS foi construído en dúas partes:

  • Openstack co seu propio módulo de autorización Keystone,
  • Hotbox (almacenamento S3) baseado no proxecto Mail.ru Cloud,

arredor do cal apareceron entón novos servizos.

En esencia, trátase de dous tipos diferentes de autorización. Ademais, usamos algúns desenvolvementos separados de Mail.ru, por exemplo, un almacenamento xeral de contrasinais de Mail.ru, así como un conector openid autoescrito, grazas ao cal se proporcionou SSO (autorización de extremo a extremo) no panel Horizon. de máquinas virtuais (UI nativa de OpenStack).

Facer IAM para nós significou conectalo todo nun único sistema, completamente noso. Ao mesmo tempo, non perderemos ningunha funcionalidade no camiño, senón que crearemos unha base para o futuro que nos permita perfeccionala de forma transparente sen refactorizar e escalala en función da funcionalidade. Tamén ao principio, os usuarios tiñan un modelo para o acceso aos servizos (RBAC central, control de acceso por roles) e algunhas outras pequenas cousas.

A tarefa resultou ser non trivial: python e perl, varios backends, servizos escritos de forma independente, varios equipos de desenvolvemento e administradores. E o máis importante, hai miles de usuarios en directo no sistema de produción de combate. Todo isto houbo que escribir e, o máis importante, desenrolar sen baixas.

Que imos lanzar?

Para dicilo de xeito moi groso, nuns 4 meses preparamos o seguinte:

  • Creamos varios daemons novos que agregaban funcións que funcionaban anteriormente en diferentes partes da infraestrutura. O resto dos servizos prescribiuse un novo backend en forma destes demos.
  • Escribimos o noso propio almacenamento central de contrasinais e claves, dispoñible para todos os nosos servizos, que pode ser modificado libremente segundo o precisemos.
  • Escribimos 4 novos backends para Keystone desde cero (usuarios, proxectos, roles, asignacións de roles), que, de feito, substituíron a súa base de datos e agora actúan como un único repositorio para os contrasinais dos nosos usuarios.
  • Ensinamos a todos os nosos servizos de Openstack a ir a un servizo de políticas de terceiros para as súas políticas en lugar de ler estas políticas localmente desde cada servidor (si, é así como funciona Openstack por defecto!)

Unha reelaboración tan importante require cambios grandes, complexos e, o máis importante, sincrónicos en varios sistemas escritos por diferentes equipos de desenvolvemento. Unha vez montado, todo o sistema debería funcionar.

Como implementar tales cambios e non arruinalos? Primeiro decidimos mirar un pouco ao futuro.

Estratexia de implantación

  • Sería posible lanzar o produto en varias etapas, pero isto aumentaría o tempo de desenvolvemento en tres veces. Ademais, durante algún tempo teríamos unha completa desincronización dos datos nas bases de datos. Terías que escribir as túas propias ferramentas de sincronización e vivir con varios almacéns de datos durante moito tempo. E isto xera unha gran variedade de riscos.
  • Todo o que se podía preparar de forma transparente para o usuario fíxose con antelación. Levou 2 meses.
  • Permitimos tempo de inactividade durante varias horas, só para que as operacións dos usuarios creasen e cambiasen recursos.
  • Para o funcionamento de todos os recursos xa creados, o tempo de inactividade era inaceptable. Planeamos que durante o lanzamento, os recursos funcionasen sen tempo de inactividade e afectasen aos clientes.
  • Para reducir o impacto nos nosos clientes se algo sae mal, decidimos lanzar o domingo á noite. Menos clientes xestionan máquinas virtuais pola noite.
  • Avisamos a todos os nosos clientes de que durante o período seleccionado para a súa posta en marcha, a xestión do servizo non estará dispoñible.

Digresión: que é un lanzamento?

<precaución, filosofía>

Todo especialista en TI pode responder facilmente o que é un lanzamento. Instalas CI/CD e todo entrégase automaticamente á tenda. 🙂

Por suposto, isto é certo. Pero a dificultade é que coas ferramentas modernas de automatización de entrega de código, pérdese a comprensión do propio lanzamento. Como se esquece da épica da invención da roda ao mirar o transporte moderno. Todo está tan automatizado que o lanzamento adoita realizarse sen comprender o panorama completo.

E toda a imaxe é así. O lanzamento consta de catro aspectos principais:

  1. Entrega de código, incluída a modificación de datos. Por exemplo, as súas migracións.
  2. A recuperación do código é a capacidade de volver atrás se algo sae mal. Por exemplo, mediante a creación de copias de seguridade.
  3. Hora de cada operación de lanzamento/reversión. Debe comprender o momento de calquera operación dos dous primeiros puntos.
  4. Funcionalidade afectada. É necesario avaliar tanto os efectos positivos esperados como os posibles negativos.

Todos estes aspectos deben ser tidos en conta para un lanzamento exitoso. Normalmente só se avalía o primeiro punto, ou no mellor dos casos, o segundo, e entón o lanzamento considérase exitoso. Pero o terceiro e o cuarto son aínda máis importantes. A que usuario lle gustaría que o lanzamento tardase 3 horas en lugar dun minuto? Ou se algo innecesario se ve afectado durante o lanzamento? Ou o tempo de inactividade dun servizo levará a consecuencias imprevisibles?

Acto 1..n, preparación para o lanzamento

Nun primeiro momento pensei en describir brevemente as nosas reunións: todo o equipo, as súas partes, moreas de discusións nos cafés, discusións, probas, chuvias de ideas. Entón pensei que sería innecesario. Catro meses de desenvolvemento sempre consisten nisto, especialmente cando non estás escribindo algo que se poida entregar constantemente, senón unha gran característica para un sistema en directo. O que afecta a todos os servizos, pero nada debería cambiar para os usuarios, excepto "un botón na interface web".

A nosa comprensión de como implementar cambiou con cada nova reunión, e de forma bastante significativa. Por exemplo, iamos actualizar toda a nosa base de datos de facturación. Pero calculamos o tempo e decatámonos de que era imposible facelo nun tempo de lanzamento razoable. Levamos case unha semana máis fragmentar e arquivar a base de datos de facturación. E cando a velocidade de lanzamento esperada aínda non era satisfactoria, pedimos hardware adicional e máis potente, onde se arrastraba toda a base. Non é que non quixeramos facelo antes, pero a necesidade actual de lanzarnos deixou sen opcións.

Cando un de nós tivo dúbidas de que o lanzamento puidese afectar á dispoñibilidade das nosas máquinas virtuais, pasamos unha semana realizando probas, experimentos, análises de código e recibimos unha clara comprensión de que isto non sucedería na nosa produción, e ata as persoas máis dubidosas coincidiron. con este.

Mentres tanto, os mozos do soporte técnico realizaron os seus propios experimentos independentes para escribir instrucións para os clientes sobre os métodos de conexión, que deberían cambiar despois do lanzamento. Traballaron na UX do usuario, prepararon instrucións e proporcionaron consultas persoais.

Automatizamos todas as operacións de lanzamento posibles. Todas as operacións foron scriptadas, incluso as máis sinxelas, e realizáronse constantemente probas. Discutiron sobre a mellor forma de desactivar o servizo: omitir o daemon ou bloquear o acceso ao servizo cun firewall. Creamos unha lista de verificación de equipos para cada fase de lanzamento e actualizámola constantemente. Debuxamos e actualizamos constantemente un diagrama de Gantt para todos os traballos de lanzamento, con horarios.

E entón…

O acto final, antes de lanzarse

...é hora de lanzar.

Como se di, unha obra de arte non se pode rematar, só se acaba de traballar nela. Tes que facer un esforzo de vontade, entendendo que non atoparás todo, pero crendo que fixeches todas as suposicións razoables, previu todos os casos posibles, pechaches todos os erros críticos e todos os participantes fixeron todo o que puideron. Canto máis código desenvolvas, máis difícil será convencerte diso (ademais, todos entenden que é imposible prever todo).

Decidimos que estabamos preparados para o lanzamento cando estabamos convencidos de que fixeramos todo o posible para cubrir todos os riscos para os nosos usuarios asociados a afectacións e tempo de inactividade inesperados. É dicir, calquera cousa pode saír mal, excepto:

  1. Afectar (sagrada para nós, máis preciada) a infraestrutura de usuarios,
  2. Funcionalidade: o uso do noso servizo despois do lanzamento debería ser o mesmo que antes.

Desenrolando

Unha historia de lanzamento que afectou todo
Dous tirados, 8 non interfiren

Levamos un tempo de inactividade para todas as solicitudes dos usuarios durante 7 horas. Neste momento, temos un plan de lanzamento e un plan de retroceso.

  • O lanzamento en si leva aproximadamente 3 horas.
  • 2 horas para probas.
  • 2 horas: reserva para unha posible reversión dos cambios.

Elaborouse un diagrama de Gantt para cada acción, canto tempo leva, que sucede secuencialmente, que se fai en paralelo.

Unha historia de lanzamento que afectou todo
Unha peza dun diagrama de Gantt, unha das primeiras versións (sen execución paralela). A ferramenta de sincronización máis valiosa

Todos os participantes teñen determinado o seu papel no lanzamento, que tarefas realizan e de que son responsables. Intentamos levar cada etapa ao automatismo, desenrolalo, retrocede, recolle comentarios e lanzámolo de novo.

Crónica dos acontecementos

Así, 15 persoas acudiron a traballar o domingo 29 de abril ás 10 horas. Ademais dos participantes clave, algúns acudiron simplemente para apoiar ao equipo, polo que lles agradecemos especialmente.

Tamén paga a pena mencionar que o noso probador clave está de vacacións. É imposible lanzar sen probar, estamos explorando opcións. Unha compañeira acepta probarnos das vacacións, polo que recibe un inmenso agradecemento de todo o equipo.

00:00. Pare
Deixamos as solicitudes dos usuarios, colgamos un cartel que indica traballo técnico. A vixilancia berra, pero todo é normal. Comprobamos que non caeu nada máis que o que debía caer. E comezamos a traballar sobre a migración.

Todo o mundo ten un plan de lanzamento impreso punto por punto, todos saben quen fai que e en que momento. Despois de cada acción, comprobamos os tempos para asegurarnos de que non os excedemos e todo vai segundo o previsto. Aqueles que non participan directamente no lanzamento na fase actual prepáranse lanzando un xoguete en liña (Xonotic, charlatanes tipo 3) para non molestar aos seus compañeiros. 🙂

02:00. Desenrolado
Unha agradable sorpresa: rematamos o lanzamento unha hora antes, debido á optimización das nosas bases de datos e scripts de migración. O berro xeral: "¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡ Todas as novas funcións están en produción, pero ata agora só podemos velas na interface. Todo o mundo pasa ao modo de proba, clasifícaos en grupos e comeza a ver o que pasou ao final.

Non resultou moi ben, decatámonos diso despois de 10 minutos, cando nada está conectado nin traballa nos proxectos dos membros do equipo. Sincronización rápida, expresamos os nosos problemas, establecemos prioridades, formamos equipos e pasamos á depuración.

02:30. Dous grandes problemas contra catro ollos
Atopamos dous grandes problemas. Démonos conta de que os clientes non verían algúns servizos conectados e que xurdirían problemas coas contas dos socios. Ambos débense a scripts de migración imperfectos para algúns casos extremos. Temos que arranxalo agora.

Escribimos consultas que rexistran isto, con polo menos 4 ollos. Probámolos durante a preprodución para asegurarnos de que funcionan e non rompen nada. Podes rodar máis aló. Ao mesmo tempo, realizamos as nosas probas de integración regulares, que revelan algúns problemas máis. Son todos pequenos, pero tamén hai que reparalos.

03:00. -2 problemas +2 problemas
Os dous grandes problemas anteriores foron solucionados, e case todos os pequenos tamén. Todos os que están desocupados en correccións están traballando activamente nas súas contas e informando do que atopan. Priorizamos, distribuímos entre os equipos e deixamos elementos non críticos para a mañá.

Facemos de novo as probas, descobren dous novos grandes problemas. Non todas as políticas de servizo chegaron correctamente, polo que algunhas solicitudes de usuarios non pasan a autorización. Ademais, un novo problema coas contas dos socios. Apurémonos a mirar.

03:20. Sincronización de emerxencia
Solucionouse un novo problema. Para o segundo, estamos organizando unha sincronización de emerxencia. Entendemos o que está a suceder: a corrección anterior solucionou un problema, pero creou outro. Facemos un descanso para descubrir como facelo correctamente e sen consecuencias.

03:30. Seis ollos
Entendemos cal debe ser o estado final da base para que todo saia ben para todos os socios. Escribimos unha solicitude con 6 ollos, desenrolámola en preprodución, probámola, lanzámola para a produción.

04:00. Todo está funcionando
Todas as probas superadas, non hai problemas críticos visibles. De cando en vez, algo no equipo non lle funciona a alguén, reaccionamos pronto. Na maioría das veces a alarma é falsa. Pero ás veces algo non chega ou non funciona unha páxina separada. Sentamos, arranxamos, arranxamos, arranxamos. Un equipo separado está a lanzar a última gran función: a facturación.

04:30. Punto de non retorno
Achégase o punto de non retorno, é dicir, o momento no que, se comezamos a retroceder, non cumpriremos co tempo de inactividade que se nos deu. Hai problemas coa facturación, que o sabe e rexistra todo, pero négase obstinadamente a cancelar o diñeiro dos clientes. Hai varios erros en páxinas individuais, accións e estados. A función principal funciona, todas as probas pasan con éxito. Decidimos que o lanzamento tivo lugar, non retrocederemos.

06:00. Aberto para todos os usuarios da IU
Erros corrixidos. Algunhas que non atraen aos usuarios quedan para máis tarde. Abrimos a interface para todos. Seguimos traballando na facturación, agardando os comentarios dos usuarios e os resultados do seguimento.

07:00. Problemas coa carga da API
Queda claro que planificamos un pouco mal a carga na nosa API e probamos esta carga, que non puido identificar o problema. Como resultado, ≈5 % das solicitudes fallan. Mobilizámonos e busquemos a razón.

A facturación é teimuda e tampouco quere traballar. Decidimos aprazala para máis adiante para poder levar a cabo os cambios con calma. É dicir, todos os recursos están acumulados nel, pero as baixas dos clientes non pasan. Por suposto, este é un problema, pero en comparación co lanzamento xeral parece pouco importante.

08:00. Fix API
Lanzamos unha solución para a carga, os fallos desapareceron. Comezamos a ir a casa.

10:00. Todos
Todo está arranxado. É tranquilo na vixilancia e no lugar dos clientes, o equipo vaise durmir aos poucos. A facturación segue sendo, restablecerémola mañá.

Despois durante o día houbo lanzamentos que arranxaron rexistros, notificacións, códigos de devolución e personalizacións para algúns dos nosos clientes.

Entón, o lanzamento foi exitoso! Por suposto, podería ser mellor, pero sacamos conclusións sobre o que non foi suficiente para acadar a perfección.

En total

Durante 2 meses de preparación activa para o lanzamento, realizáronse 43 tarefas, que duraron desde un par de horas ata varios días.

Durante o lanzamento:

  • demos novos e cambiados - 5 pezas, substituíndo 2 monolitos;
  • cambios nas bases de datos: as 6 bases de datos con datos de usuarios víronse afectadas, realizáronse descargas de tres bases de datos antigas a unha nova;
  • frontend completamente redeseñado;
  • cantidade de código descargado: 33 mil liñas de código novo, ≈ 3 mil liñas de código en probas, ≈ 5 mil liñas de código de migración;
  • todos os datos están intactos, non se danou a máquina virtual dun só cliente. 🙂

Boas prácticas para un bo lanzamento

Guiáronnos nesta difícil situación. Pero, en xeral, é útil seguilos durante calquera lanzamento. Pero canto máis complexo sexa o lanzamento, maior será o papel que desempeñan.

  1. O primeiro que cómpre facer é comprender como pode ou afectará o lanzamento aos usuarios. Haberá tempo de inactividade? Se é así, cal é o tempo de inactividade? Como afectará isto aos usuarios? Cales son os mellores e os peores escenarios posibles? E cubrir os riscos.
  2. Planifica todo. En cada etapa, cómpre comprender todos os aspectos do lanzamento:
    • entrega de código;
    • reversión do código;
    • tempo de cada operación;
    • funcionalidade afectada.
  3. Xoga cos escenarios ata que todas as fases do lanzamento, así como os riscos en cada unha delas, se fagan evidentes. Se tes algunha dúbida, podes facer un descanso e examinar a fase cuestionable por separado.
  4. Cada etapa pode e debe ser mellorada se axuda aos nosos usuarios. Por exemplo, reducirá o tempo de inactividade ou eliminará algúns riscos.
  5. As probas de retroceso son moito máis importantes que as probas de entrega de código. É imperativo comprobar que, como resultado da recuperación, o sistema volverá ao seu estado orixinal e confirmalo con probas.
  6. Todo o que se pode automatizar debe ser automatizado. Todo o que non se pode automatizar debe escribirse con antelación nunha folla de trucos.
  7. Rexistrar o criterio de éxito. Que funcionalidades debería estar dispoñible e a que hora? Se isto non ocorre, executa un plan de retroceso.
  8. E o máis importante - persoas. Todo o mundo debe ser consciente do que está a facer, por que e que depende das súas accións no proceso de lanzamento.

E nunha soa frase, cunha boa planificación e elaboración podes lanzar todo o que queiras sen consecuencias para as vendas. Mesmo algo que afectará a todos os teus servizos en produción.

Fonte: www.habr.com

Engadir un comentario