Magento 2 Deployment

18 april 2017 | Patrick
Back-end ontwikkelaar

In Magento 1 was het nog mogelijk om de code van een actieve webshop te wijzigen zonder hem te onderbreken. In Magento 2 is dit niet langer mogelijk. Een deployment-stap is nodig. In dit artikel leg ik uit wat deployment is, waarom het nodig is, en hoe wij dit op dit moment aanpakken.

Deployment is het proces van het verplaatsen van nieuwe code vanuit de veilige ontwikkelomgeving naar de harde realiteit van productie. Omdat Magento geschreven is in PHP, is het met name geschikt om individuele bestanden vanuit de ontwikkelomgeving naar productie te plaatsen zonder onderbreking van de actieve shop. Als de processen echter complexer worden, en de eisen aan de real-time performance steviger, nemen dingen als gegenereerde code en caching de plaats in van flexibiliteit. Verplaatsen naar productie wordt dan een proces op zichzelf.

Read this document in English

Standaard Magento Deployment

Magento beschrijft de stappen die nodig zijn om een productie-server te updaten in dit document.

  • php bin/magento maintenance:enable
  • composer require –no-update
  • composer update
  • php bin/magento setup:upgrade
  • php bin/magento setup:di:compile
  • php bin/magento setup:static-content:deploy
  • php bin/magento maintenance:disable

Dit zijn alleen de standaard stappen. Specifieke shops hebben hiernaast nog andere stappen nodig. Samen nemen ze meerdere minuten in beslag, afhankelijk van de complexiteit van de shop. Als dit build-proces direct op de productie-shop plaats vindt, moet het enkele minuten in maintenance mode gezet worden. Complexe shops met meerdere locales, themes en extensies hebben nog meer tijd nodig. Als niets speciaals gedaan wordt, is het updaten van een shop een complex proces dat een aanzienlijke tijd in beslag neemt. Tijd waarin de shop offline is. Voor veel shops is dit niet acceptabel.

De heilige graal van deployment is zero downtime: de shop is geen moment onbeschikbaar. Hoewel dit in de praktijk niet mogelijk is, kan men wel proberen om het te beperken tot een paar seconden. Sommige leden van de Magento community hebben hun aanpak van dit probleem gepubliceerd. Wijzelf hebben een proces gebouwd door een aantal bestaande technieken te combineren met wat uitbreidingen die nodig zijn voor onze eigen use-case.

De Build Server

Bij BigBridge beheren we webshops voor verschillende klanten. Deze shops worden gehost door verschillende hosting providers die zowel Apache 2 en Nginx als webserver gebruiken. Alle hosting providers (tot nu toe) gebruiken een op Linux gebaseerd OS. We slaan een complete shop op in een enkele Git repository, behalve (via .gitignore) de onderdelen die uit andere bronnen gehaald kunnen worden. We gebruiken de repository echter niet om te bepalen welke modulen ingeschakeld zijn; config.php wordt niet ingecheckt.

We wilden graag een build tool die alle benodigde stappen die nodig zijn voor een nieuwe release automatisch uitvoert, zonder menselijke tussenkomst. Eén commando, “deploy!”, zou genoeg moeten zijn om de shop te updaten naar de laatste versie.

Het is mogelijk om een nieuwe release op de productie-server zelf te bouwen, onafhankelijk van de live webshop, maar het kost veel CPU kracht van de shop, en vereist dat de productie-server toegang heeft tot de code repositories. Als Sass wordt gebruikt, is het daarnaast nog nodig om Node.js te installeren op the server. Om deze redenen is het beter om het bouwen in een andere omgeving te doen, op een speciale build server. Wij gebruiken hiervoor onze ontwikkel-machine.

Onze build-omgeving lijkt op de productie-omgeving; het heeft ook een database, draait in productie-modus, en heeft dezelfde extensies geïnstalleerd. Het bevat geen content, geen producten en geen klantrelaties.

Er is nog een reden waarom deployment beter op een aparte build server gedaan kan worden, of tenminste op een aparte build database. Als een nieuwe extensie wordt toegevoegd aan de shop, wordt het automatisch toegevoegd en geactiveerd in config.php door Magento via setup:upgrade. Dit betekent echter, dat setup:static-content:deploy pas kan worden uitgevoegd nadat de database is geüpgradet. Dit kost minuten aan downtime. Door het hele build proces te dupliceren op de build server, inclusief de setup:upgrade stap (die een build database nodig heeft) kan dit probleem worden voorkomen. Pas als setup:upgrade en setup:static-content:deploy complete zijn, wordt alle code gekopieerd naar productie.

Tool: Deployer

We hebben een eigen deployment tool gebouwd om Deployer heen. Deployer is een PHP tool waarmee een ontwikkel-machine makkelijk praat met een productie server. Ik zal enkele voorbeelden geven van de stappen die nodig zijn voor de deployment, maar we geven niet de volledige source code, omdat er niet één tool is die geschikt is voor alle omgevingen. Verschillende bedrijven die met Magento werken hebben verschillende eisen aan een deployment tool. Deployer is echter makkelijk om mee te werken en kan worden aangepast door elke developer met kennis van PHP.

Onze tool bevat een directory met één config file voor elke shop. Wijzigingen aan de deployment tool zijn hierdoor makkelijk op alle plaatsen door te voeren.

Directories en public_html

De productie-server directory structuur die we hebben opgesteld lijkt op de standaard Deployer structuur, met enkele verschillen:

shared is de directory die de bestanden bevat die gebruikt worden door alle releases: config files, afbeeldingen, feeds, sessies, logs. Het wordt één keer opgezet en daarna niet meer aangeraakt. behalve de database is de shared folder het enige essentiële onderdeel van de webshop dat ge- backupt moet worden.

De release directories (5, 6, 7, current) bevatten symlinks naar subdirectories van deze shared folder. De symlinks zijn bij voorkeur relatief. Absolute symlinks kunnen onderhevig zijn aan strengere permissie-beperkingen.

public_html, die normaal een directory is, is veranderd naar een symlink die wijst naar

deployments/releases/current/pub

Hosting providers bieden niet altijd de mogelijkheid om de document root in te stellen op de directory die je zou willen (d.i. pub). Door public_html te veranderen naar een symlink, neem je deze macht in eigen hand.

In onze setup is current geen symlink die wijst naar de laatste release dir, zoals dat het geval is in standaard Deployer. Het is een gewone directory. We hebben deze wijziging gemaakt omdat symlinks soms gecacht worden (door bijvoorbeeld webserver Apache) voor een bepaalde tijd en dit is problematisch. Met name, als een extensie wordt geüpdatet naar een nieuwe versie, moet de versie in de tabel “setup_module” overeenkomen met de versie in the “module.xml”. Als een nieuwe versie gedeployed is, hebben sommige langlevende Apache kind-processen nog enkele minuten een gecachte symlink naar de vorige release code. Database versie en code versie komen dan niet overeen en Magento toont een foutmelding. Door de symlink public_html altijd naar dezelfde directory te wijzen (current/pub) wordt dit probleem opgelost.

Als een nieuwe release gemaakt is, maakt het deployment proces een nieuwe release directory, zeg ‘8’.

In de switch fase, nadat maintenance mode ingeschakeld is, wisselen current en 8 van naam. Dit gebreurt met drie ‘mv’ instructies.

Hierna wordt de database is geüpdatet, caches geleegd (met name Redis) en maintenance mode wordt uitgezet. De shop is slechts enkele seconden offline.

Rollback

In noodgeval kunnen we een vorige release van de shop terugzetten door slechts enkele directories van naam te veranderen.

Dit werkt niet als een extensie een nieuwe versie heeft gekregen, omdat de versie van de code dan niet met de database versie overeenkomt. In dat geval is het handmatig wijzigen van de versie in the module.xml van de extensie de enige optie om de shop snel weer actief te krijgen.

Deployment fasen

Steeds als een nieuwe release nodig is, geven we een enkel commando aan de server om het deployment-proces te starten. De deployment tool gaat dan door vijf fasen:

  • maak een build versie van de shop
  • update de code, de module versies and de database
  • bereidt de nieuwe release voor op the productie-server
  • switch naar de nieuwe directory
  • ruim oude releases op

Deze fasen worden hieronder kort beschreven.

Maak de build shop

De eerste 2 fasen vinden plaats op de build server.

In de eerste release wordt een complete “build shop” gemaakt op de build server, programmatisch. Het bestaat uit een lege database en een Composer- install van een Magento installatie. Het is niet nodig de hele productie-database naar de build server te kopiëren, omdat we alleen geïnteresseerd zijn in de tabel “setup_module”, gesteld dat ons build proces het enige proces is dat extensies toevoegt aan de productie-server.

Update de build shop

De shop op de build server wordt geüpdatet naar de nieuwste version. De code wordt uit de BitBucket Git repository gehaald, en third party code wordt geïnstalleerd met Composer. Elke volgende update wordt gedaan op de laatste toestand van de build server, zodat “git pull” alleen de laatste wijzigingen sinds de vorige release hoeft te downloaden.

Al deze stappen worden uitgevoerd op de offline build shop:

  • git pull
  • maak een file pub/static/deployed_version.txt
  • composer install
  • pas een set patch files toe voor bekende Magento problemen
  • chmod +x bin/magento
  • bouw vendor/snowdog/frontools/node_modules voor Sass compilatie
  • set de build shop in production modus
  • bin/magento setup:upgrade
  • bin/magento di:compile
  • bin/magento setup:static-content:deploy
  • Doe ‘gulp styles’ om css files te compilen uit Sass files
  • git checkout pub/.htaccess (omdat het wordt overschreven door eerdere stappen)

Bereidt een nieuwe release voor op productie

Deployer regelt het maken van een nieuwe directory en een nieuwe symlink “release”.

rsync wordt gebruikt om efficiënt code te kopiëren naar de productie-server. Het volgende commando kopieert de folder $source naar de folder $target op the server via SSH. Het controleert of de directory $current op de productie-server de benodigde files al bevat, zodat ze niet nog eens overgezet hoeven te worden. Beter nog, het maakt hard links naar deze bestaande bestanden, en dat bespaart zowel tijd als diskruimte. Het sluit de .git directory uit.

rsync --link-dest {$current} --exclude ".git/" -e "ssh -p {$port}" -a {$source} {$target}

Als laatste wordt Magento in productie-modus gezet als dat niet al het geval was (alleen in de eerste release).

Switch

In deze fase wordt de release geactiveerd.

  • bin/magento maintenance:disable
  • mv {$new} {$temp} && mv {$current} {$new} && mv {$temp} {$current}
  • bin/magento setup:upgrade –keep-generated
  • bin/magento cache:flush
  • bin/magento maintenance:enable

Opruimen

We behouden tot 10 releases per shop. Oudere release worden verwijderd in deze fase.

Ten slotte

Een apart deployment proces is een must have voor een Magento 2 webshop. Het verzekert dat wijzigingen aan de webshop op een gecontroleerde manier worden doorgevoerd en zorgt voor een minimale downtime. Problemen in het upgrade-proces worden al in de offline build-omgeving zichtbaar waar ze nog opgelost kunnen worden. Mochten de problemen pas optreden nadat de release live staat, is er nog de mogelijkheid om snel terug te keren naar de vorige versie. Deze eigenschappen maken dat een deployment tool niet slechts een noodzakelijkheid is, het kan ook een toevoeging zijn aan de kwaliteit van het beheerproces.

Een deployment tool moet echter blijven evolueren om bij te blijven bij de veranderende omstandigheden. Magento 2.2 belooft een near-zero downtime deployment model, dus hierdoor kan alles weer veranderen!

Bekijk zeker Magento deployment pagina als je van plan bent een deployment proces op te zetten.

Patrick
Back-end ontwikkelaar
Als Magento developer ontwikkel ik maatwerk-functionaliteiten en extensies voor onze klanten. Het is voor mij een uitdaging om de wensen van de klant op de meest elegante manier vorm te geven, lettend op snelheid, stabiliteit en uitbreidbaarheid. Daarnaast vind ik het leuk mezelf continu te verdiepen op het gebied van nieuwe innovaties en de laatste ontwikkelingen op development gebied. Benieuwd waarin BigBridge en Magento het verschil maken? Neem contact op