Project deployment met PM2

CI/CD kan een groot en uitgebreid proces worden waar er veel tijd in gaat. Voor grote projecten kan die tijd ook uitgetrokken worden. Een pipeline kan gemaakt worden die automatisch taken uitvoert en developers programmeren lokaal en duwen hun code snel door naar een online omgeving op een snelle, veilige manier... Maar wat met projecten die het niet toelaten om een volledige CI/CD pipeline op te zetten?

Laat het duidelijk zijn... Dit artikelt omschrijft een snelle maar manuele manier om integratie en deployment uit te voeren. Daarom is dit meer geschikt voor kleinere projecten. In het voorbeeld wordt geen Docker gebruikt, maar het is mogelijk.

PM2 Logo

PM2

PM2 werd in het leven geroepen (en is nog steeds) een process manager voor NodeJS. Na verloop van tijd is er echter ook deployment bij gekomen, en die deployment kan in principe ook voor andere scripting en programmeer talen gebruikt worden.

CI/CD

CI/CD bestaat uit 2 onderdelen... Continuous Integrations & Continuous Deployment (of delivery).

Met integratie wordt vaak omschreven als een werkwijze om problemen/bugs vroeg in het development stadium tegen te komen en uit de code te halen maar ook het snel oplossen van bugs als die voorkomen.  (Geautomatiseerde testen)

Deployment is de werkwijze om code op een geautomatiseerde wijze van een lokale naar een online omgeving te verhuizen. Delivery is een werkwijze waar de code afgeleverd wordt in een centraal beheer, maar nog niet op een online omgeving geplaatst wordt. (Delivery gaat vaak gepaard met versiebeheer)

icons of a team working out

Praktijk voorbeeld

We hebben een team van een aantal mensen. Bob is de teamleider en is verantwoordelijk voor de afgeleverde projecten. Bob kent een basis van terminal commando’s en versiebeheer. De rest van het team zijn webdevelopers.

Bob is verantwoordelijk voor een interessant project en zou graag met zekerheid kunnen zeggen dat alles altijd werkt. Bovendien wilt Bob downtime vermijden.
Automatische testen moeten er zijn, maar Bob wilt zelf (als een soort buffer) ook de nieuwe functionaliteiten in een staging omgeving testen vooraleer die op de productie omgeving geplaatst worden.

Er zijn dus een paar omgevingen in dit project:

-          Lokale development (Computer van de developers)

-          Versiebeheer (GIT)

-          Test omgeving (online server – development branches)

-          Staging/Development omgeving (online server – development of beta branch)

-          Productie omgeving (online server – master branch)

De test en staging omgeving zijn niet verplicht, maar natuurlijk wel sterk aan te raden.

Bob heeft een paar machtigingen die zijn teamleden niet hebben...
Zo is Bob hoofd van het project op het versiebeheer en heeft hij (SSH) toegang tot de productie omgeving. De teamleden hebben toegang tot alle servers behalve productie. Ook kunnen teamleden niet rechtstreeks op de master branch werken in het versiebeheer.

Deploying

In het project wordt een ecosystem.config.js bestand gemaakt. Daarin wordt een omschrijving gemaakt van hoeveel server “kracht” het project mag gebruiken. Ook worden de verschillende omgevingen omschreven.

 

module.exports = {
    apps: [{
        name: "projectx",
        script: "server.js",
        instances: 1,
        autorestart: true,
        watch: false,
        max_memory_restart: "128M",
        env: {
            "BASIC_VAR": "all-environments"
        },
        env_test: {
            "NODE_ENV": "test"
        },
        env_development: {
            "NODE_ENV": "development"
        },
        env_production: {
            "NODE_ENV": "production"
        }
    }],
    deploy: {
	  test: {
            user: "someuser",
            host: "10.10.10.10",
            ref: "origin/test-branch",
            repo: "git@gitlab.com:example/projectx.git",
            path: "/home/projectx",
            ssh_options: ["StrictHostKeyChecking=no", "PasswordAuthentication=no"],
            "pre-setup": "apt-get install git",
            "post-setup": "ls -la",
            "pre-deploy": "git fetch && git status",
            "post-deploy": "npm install --no-save && pm2 reload ecosystem.config.js --env development",
        },
        development: {
            user: "someuser",
            host: "10.10.10.11",
            ref: "origin/beta-branch",
            repo: "git@gitlab.com:example/projectx.git",
            path: "/home/projectx",
            ssh_options: ["StrictHostKeyChecking=no", "PasswordAuthentication=no"],
            "pre-setup": "apt-get install git",
            "post-setup": "ls -la",
            "pre-deploy": "git fetch && git status",
            "post-deploy": "npm install --no-save && pm2 reload ecosystem.config.js --env development",
        },
	  production: {
            user: "someuser",
            host: "10.10.10.12",
            ref: "origin/master",
            repo: "git@gitlab.com:example/projectx.git",
            path: "/home/projectx",
            ssh_options: ["StrictHostKeyChecking=no", "PasswordAuthentication=no"],
            "pre-setup": "apt-get install git",
            "post-setup": "ls -la",
            "pre-deploy": "git fetch && git status",
            "post-deploy": "npm install --no-save && pm2 reload ecosystem.config.js --env development",
        }

    }
};

 

Een groot bestand, maar eigenlijk is het wel logisch opgesplitst in 2 delen :

-          Definitie van het project / server resources

-          Definitie van de omgevingen

Het eerste deel van het bestand is een definitie van hoe de applicatie gestart moet worden. Tevens kunnen environment/process variables meegegeven worden voor specifieke omgevingen of alle omgevingen.

Het 2de deel is de plaats waar de omgevingen omschreven staan. (In dit voorbeeld wordt er verbinding gemaakt via SSH public/private key. Interactive modus om met paswoord te werken is ook mogelijk.)

De meeste zaken spreken voor zich, maar de pre-setup, post-setup, pre-deploy en post-deploy zijn wel belangrijk om iets verder op in te gaan...

Het deploy commando van pm2 is als volgt opgebouwd:
pm2 deploy <environment/omgeving/server> <actie>

De actie kan setup of update zijn...
- Setup dient om de eerste keer de git repository te kopiëren, nodige installaties te doen, eventuel bestanden te kopiëren.
- Update dient om een update te doen van de code en de server te herstarten.

Project flow

development flow met pm2

Elk teamlid kan een deploy uitvoeren op de test en development omgeving... Maar niet op production. Doordat enkel teamlead Bob SSH toegang heeft tot de productie server, kan enkel hij een deploy uitvoeren naar productie.

Let op: Aangezien dit bestand in de git repository geplaatst wordt, is het belangrijk om geen gevoelige gegevens in dit bestand te plaatsen.

Voordelen

  • Snel opgezet
  • Weinig onderdelen
  • Controle in eigen handen

Nadelen

  • Elke stap is manueel te starten
  • Control in eigen handen 
    (slechte code kan nog altijd doorgeduwd worden en is verantwoordelijkheid van de developer)

Extra: Monitoring PM2 processen

Ik heb een projectje beschikbaar gemaakt voor iedereen. Dit is een zeer simpele dashboard om PM2 processen te visualiseren.
Link: https://github.com/Jozzeh/pm2-visualised