Blue Green Deployment

Samarbetet kring vår open source Continuous Delivery Build Pipeline fortsätter i mobbprogrammeringsform. Den här gången bjöd Mikael Sennerholm in till Avega-kontoret på Östermalm eftersom det ryktades att någon en gång hade sett att man minsann kunde locka fram riktigt bra fart i det nätverket.

Vägen till DevOps-nirvanat visade sig gå genom att gräva fram det gamla sladdnätverket igen och plocka upp sin gamla RJ45-utrustning igen från längst ned i byrålådorna hemma, för Wifi fungerar fortfarande inte bra nog för att ladda ned alla maskinavbildningar på rimlig tid.

Men Avega är i gott sällskap, det tog år av tjat innan C.A.G fick ett på riktigt fungerande Wifi-nät med flås på Kista-kontoret. Så det borde väl inte vara helt omöjligt att få till det på Avega heller så småningom.

IMG_20150120_185748

Pipelinen bor just nu i ett repo på github under det missvisande namnet “dockerApplicationServer” (https://github.com/avegagroup/dockerapplicationserver). Namnet rättar vi någon regnig dag när allt annat som är viktigare har fixats.

Vi började med att kolla på vår backlog:

  • Centraliserad loggning med ELK
  • Blue-green deloyment
  • Integrera pipeline med Jira
  • Eget docker registry (måste man iaf göra när man gör det här på riktigt)
  • Lägga upp på docker.io?

Centraliserad loggning är väl egentligen inte centralt för Continuous Delivery och en pipeline, snarare en logisk följd av att produktionssätta med en massa Docker-instanser. Vi överenskom ändå att kolla på ELK-stacken vid nästa tillfälle (Elasticsearch-Logstash-Kibana).

Vi började treva på temat Jira-pipeline-integration.

Från molnfri höjd handlar det om att automatgenerera release notes från ärendehanteringssystem och från kodrepository. Vi började först resonera kring användningsfallen.

  • Underlag för ett manuellt deploy-steg.
  • Spårbarhet – att få en av människa enkelt läsbar logg på vad som produktionssatts.
  • Levererans av system till en part som behöver en sammanfattande beskrivning av vad som hänt i systemet sedan föregående leverans. I detta fall behöver vi en funktion där man matar in från-version och till-version.

Release notes innehåller följande sorters information: Nya och ändrade funktioner, åtgärdade felrapporter, kända fel och eventuella workarounds, migrering från föregående version

Den grundinformation vi har att tillgå är stängda issues i Jira, både i form av avklarade stories och åtgärdade felrapporter, fixade feature requests, öppna felrapporter, eventuell dedicerad release-notes information inuti ärendena samt listan med alla commit-kommentarer mellan de aktuella byggena.

Förmodligen behöver vi mangla innehållet manuellt om vi har ambitionen att skapa ett kompakt och läsbart dokument.

Var ska release-notes hamna, var ska vi spara dem? Ska vi skapa ett “release-ärende” som innehåller release informationen? Ska vi generera ett dokument med release-notes som vi committar i kodrepot?

Vi kanske inte skall spara det nånstans utan bara anse dokumentet att vara en alternativ vy av information som ändå sparas i kodrepo och ärendehanteringssystem.

Om vi manglar release-notes manuellt måste vi definitivt committa det manglade resultatet.

Här någonstans tyckte Daniel Fagerström att vi blev tråkiga och föreslog att vi skulle gå på blue-green deployment istället, och han fick bara lojt motstånd som snabbt mojnade från mig.

Över till blue green deployment

Vi måste ha två produktionsmiljöer alltså, som vi deployar varannan gång till. Det är väl bara att sätta igång. Först behöver vi en lastbalanserare. Vi landade snabbt utan någon vidare debatt på dockerfile/haproxy.

En blå dockerinstans, en grön dockerinstans, en lastbalanserare med haproxy. Vi struntar i sticky sessions och tänker stateless och RESTful, så slipper vi bygga börja dyrt och dåligt legacy-stöd.

Vi tar in dockerfile/haproxy, skapar en /haproxy/haproxy.cfg. Den hamnar på dockerinstansen under /haproxy-override. Överrids hela haproxy.cfg eller bara de parametrarna man skriver in där?

Hur gör man för att få haproxy att växla mellan blue och green? Ett par setuper vi sett gör det genom att automatiskt växla miljö beroende på vilken som är uppe. En annan variant är att låta applikationen själv tala om det på någon management-endpoint.

Ett argument emot att låta applikationen själv tala om huruvida den skall vara aktiv eller ej är att det kan vara något fel på applikationen som föranleder att vi vill deploya en ny version och att felet naturligtvis även kan omfatta denna mekanism.

Kan vi styra lastbalanseraren direkt, dvs vilket ben lastbalanseraren ska skicka till, utifrån utan att behöva ta ned, ändra konfig och sedan ta upp den? Det borde gå att växla ben med ett direktkommando. Finns det ett RESTful api kanske?

Andreas Folkesson grävde snabbt fram ett sådant: Snapr verkade vara precis det vi behövde:

snapr allows REST queries via HTTP in order to expose detailed haproxy statistics and allow various program control functions like enabling and disabling servers.

Det kändes bra ända tills:

It is currently in alpha and should be considered extremely messy and bleeding edge.

Bleeding edge tycker vi om, men Extremely messy låter inte så kul.

Mikael kör fortfarande sin gamla emacs med tangentbindningstrassel på mac på projektorn, Johan Elmström tar över rodret ett tag med en modern och fräsch Sublime.

Vi åker på att det är olika versioner av docker i go-agenten (alltid senaste) och docker i boot2docker. Socketprotokollet har tydligen ändrats mellan 1.4.1 som Go agenten använder och 1.3.0 som använda av boot2docker. Vi uppgraderar boot2docker till senaste, låser den versionen, kan vi låsa go-agentens docker version till samma? boot2dockers maintainer är seg att ta emot Mikaels pull requests.

Att rensa utan att ladda ned hela internet igen kräver lite tankearbete. Man skulle vilja kunna köra vagrant destroy -f men detta tar inte bort den underliggande vm-en. Mikael påpekar att det är fusk att direkt göra remove från Virtualbox. Rätt metod är att göra rm på vagrant-instansen som listas när man gör vagrant global-status | grep docker. Daniel Fagerström undrar om det också är fusk att kopiera docker id:t från listan eller om man måste skriva alla siffrorna själv på sitt tangentbord.

Vid deploy måste vi ta hänsyn till att haproxy redan är uppe eftersom den är gemensam mellan de två appserverinstanserna. Hur laddar vi om haproxy när konfigen ändrats? När laddar vi om docker-haproxy om den ändras?

Var lagrar vi vilken miljö som är igång? Ska Go komma ihåg det? Eller ska vi fråga haproxy? Vi kan inte heller kolla på versionen vilken som är nyast eftersom man även vill kunna backa versionen. Och man vill kunna deploya på ena benet utan att ta ned det andra, för att snabbt kunna backa tillbaka till det gamla benet om deployen inte blev bra.

Här nånstans beslutade vi att lösa allt det där senare och helt enkelt börja lägga in lastbalanseraren i vår exempelapplikation, doodleshop (https://github.com/dmarell/doodleshop).

Vi har en lite krånglig och svårarbetad setup med boot2docker. Men vi kommer förmodligen ha det länge än eftersom det nog kommer att ta år innan Docker stabiliserats så det duger med den Docker-versionen som skeppas med standard-OS-en.

När vi tar upp och ned grön och blå fick vi problem med docker-länkar på så vis att en länk som vi anger till en docker-instans tappas när man tar bort docker-instansen och skapar om den med samma namn. Då tappas länken. Vi går runt genom att mappa upp tjänsterna på blå och grön till olika portar och då istället använder gatewayens IP.

Vi råkade ut för standardfelet att namnet (i detta fall “haproxy”) är upptaget i boot2docker: ”The name haproxy is already assigned”. Man fixar det med:

$ vagrant global-status | grep docker
$ vagrant ssh <id>
$ docker ps a
$ docker rm haproxy

Detta står i vagrantfile under felsökning.

Vi förde en diskussion var lastbalanseraren egentligen borde höra hemma. Är det en del av pipelinen? Eller en del av applikationen? Ska vi se infrastrukturen som en egen ö mellan pipeline och applikation? Efter lite resonerande kom vi fram till den logiska lösningen att även lastbalanseraren var en del av applikationen och alltså ska dockerkonfigen för vår haproxy committas där.

Så vill man det skall vara i alla fall. Haproxy-konfigens exponering i docker-instansen krånglade till det så vi lade haproxy-konfigen i pipelinen tills vidare bara för att komma vidare.

John Blund hann ikapp oss ikväll också. Vi får fortsätta en annan kväll.

IT Consultant at CAG Edge. Cloud and Continuous Delivery specialist, software developer and architect, Node.js, Java.

Publicerad i Continuous Delivery, DevOps
2 comments on “Blue Green Deployment
  1. aravind skriver:

    Good write up. Can you please share how you are switching between blue-green clusters with HAProxy?

  2. Daniel Marell skriver:

    Good question, we talked about it a lot but never concluded our choice of solution that day.

    However, we saw a number of possibilities. One option is https://github.com/Snapt/snapr, a REST api for haproxy. Another is https://github.com/flores/haproxyctl which is using UNIX sockets (ipc) so the commands (enable/disable servers) has to be run on the haproxy docker instance, but we can do that using ”docker exec” from the Go agent. The option that has to work anyway is the scenario where we are deploying a new version with an updated haproxy config.

    But we have to get back to this and actually implement it to know.

Kategorier

LinkedIn Auto Publish Powered By : XYZScripts.com