Kuvittele kaksi ohjelmistotiimiä.
Ensimmäinen valmistelee sovelluksesta uuden version.
Ohjelmoija saa tehtävän valmiiksi. Joku tarkistaa koodin. Sitten pitää ajaa testit. Joku valmistelee paketin. Joku toinen kirjautuu palvelimelle. Sen jälkeen täytyy tehdä muutama manuaalinen toimenpide, tarkistaa asetukset ja seurata järjestelmää käyttöönoton jälkeen. Jos kaikki menee hyvin, uusi versio on saatavilla.
Toinen tiimi toimii eri tavalla.
Koodi päätyy repositorioon. Testit, laadun analyysi ja turvallisuustarkistukset käynnistyvät automaattisesti. Järjestelmä rakentaa sovellusversion, ottaa sen käyttöön testiympäristössä, suorittaa seuraavat tarkistukset ja määriteltyjen ehtojen täyttyessä voi ottaa sen käyttöön tuotantoon. Jos jokin menee pieleen, käyttöönotto keskeytetään tai järjestelmä voi palata edelliseen versioon.
Molemmat tiimit tekevät ohjelmistoa.
Mutta vain toinen niistä rakensi toistettavan ohjelmiston toimitusprosessin.
Juuri siitä CI/CD:ssä on kyse.
"Toimii tuotannossa" ei vielä ole kypsä prosessi
Monet yritykset mittaavat menestystä hyvin yksinkertaisella mittarilla: sovellus toimii.
Se on tietysti perusedellytys.
Mutta järjestelmän kehittyessä esiin nousee uusia kysymyksiä:
- Kuinka nopeasti voimme ottaa korjauksen käyttöön?
- Kuinka usein voimme julkaista uusia ominaisuuksia?
- Kuinka paljon manuaalisia toimenpiteitä teemme jokaisen käyttöönoton yhteydessä?
- Voiko jokainen ohjelmoija käynnistää käyttöönottoprosessin samoilla periaatteilla?
- Tiedämmekö, mikä versio on tällä hetkellä käytössä?
- Pystymmekö palaamaan edelliseen versioon?
- Tarkistammeko käyttöönoton jälkeen automaattisesti, toimiiko järjestelmä oikein?
- Onko meillä valvonta?
- Tiedämmekö, että käyttöönotto aiheutti ongelman ennen kuin asiakas ilmoittaa siitä?
Nämä ovat software deliveryn, eivät vain itse ohjelmoinnin, kysymyksiä.
CI ja CD - kaksi osaa yhdestä prosessista
CI eli Continuous Integration tarkoittaa muutosten jatkuvaa integrointia.
Käytännössä kyse on siitä, että muutokset päätyvät yhteiseen repositorioon usein ja ne tarkistetaan automaattisesti.
Tyypillinen pipeline voi käynnistää muun muassa:
-
sovelluksen käännöksen tai rakentamisen,
-
yksikkötestit,
-
integraatiotestit,
-
linttauksen,
-
koodin staattisen analyysin,
-
riippuvuuksien skannauksen,
-
tietoturvatarkistukset,
-
käyttöönottoartefaktien rakentamisen.
Näin ongelma voidaan havaita ennen kuin koodi päätyy tuotantoon.
CD eli Continuous Delivery tai Continuous Deployment koskee seuraavaa vaihetta - muutosten toimittamista.
Valitusta mallista riippuen järjestelmä voi valmistella valmiin version käyttöönottoa varten tai ottaa sen automaattisesti käyttöön sen läpäistyä tietyt tarkistukset.
Tämä on tärkeä ero.
Continuous Delivery ei välttämättä tarkoita jokaisen muutoksen automaattista käyttöönottoa tuotantoon.
Se voi tarkoittaa yksinkertaisesti sitä, että jokainen versio valmistellaan toistettavasti käyttöönottoa varten.
Miksi manuaalisista käyttöönottoista tulee ongelma?
Manuaalinen käyttöönotto ei välttämättä ole huono.
Pienessä projektissa se voi olla täysin riittävä.
Ongelma alkaa, kun prosessi kasvaa sovelluksen mukana.
Ensin meillä on yksi henkilö, joka tietää, miten järjestelmä otetaan käyttöön. Sitten tulee toinen palvelin. Myöhemmin testiympäristö. Sen jälkeen tietokanta, välimuisti, jonot, tallennus, useita palveluita ja ulkoisia API-rajapintoja. Lisäksi tulevat erilaiset asetukset kehitystä, testejä ja tuotantoa varten.
Muutaman vuoden kuluttua prosessi voi näyttää suunnilleen tältä:
"Ensin käynnistä X, sitten muuta parametria Y, sen jälkeen käynnistä palvelu Z uudelleen, mutta tee sitä ennen tietokannasta kopio. Ja jos ilmenee virhe, soita henkilölle, joka otti tämän käyttöön viimeksi."
Tämä ei ole enää prosessi. Tämä on ihmisen päähän piilotettua tietoa. Ja juuri silloin riski kasvaa.
Automaatio ei ole olemassa vain ohjelmoijien mukavuuden vuoksi
Usein CI/CD esitetään työkaluna, joka parantaa kehittäjien käyttömukavuutta. Se on totta, mutta se on vain osa kuvaa.
Toimituksen automatisointi ennen kaikkea lisää prosessin toistettavuutta.
Jos käyttöönoton tekee ihminen, on mahdollista, että hän tekee joka kerta jotakin hieman eri tavalla.
Jos sen tekee pipeline, voidaan määritellä tarkka vaiheiden järjestys.
Sama versio.
Samat testit.
Samat tarkistukset.
Samat säännöt.
Tämä on erityisen tärkeää projekteissa, joita kehittää useampi henkilö tai useampi tiimi.
Käyttöönottoa edeltävät testit ovat tärkeämpiä kuin käyttöönoton nopeus
Automaatio ilman testejä voi vain nopeuttaa virheiden ilmaantumista.
Siksi hyvin suunnitellun pipelinen ei pitäisi olla vain mekanismi: "koodi → tuotanto".
Sen pitäisi olla laadunvalvontajärjestelmä.
Projektista riippuen siihen voi kuulua:
- Yksikkötestit - yksittäisiä logiikan osia tarkistavat testit.
- Integraatiotestit - komponenttien yhteistyötä tarkistavat testit.
- Päästä päähän -testit - todellisia käyttäjäskenaarioita simuloivat testit.
- Tietoturvatestit - tarkistavat muun muassa riippuvuuksia ja tunnettuja haavoittuvuuksia.
- Suorituskykytestit - tarpeen siellä, missä tietyn kuormituksen käsittely on tärkeää.
Jokainen sovellus ei tarvitse kaikkia näitä kerroksia samassa laajuudessa.
Ja se on tärkeää.
CI/CD ei tarkoita mahdollisimman monen työkalun heittämistä pipelineen.
Kyse on tarkistusten valitsemisesta kyseisen järjestelmän riskien mukaan.
Mitä tapahtuu, kun testi ei mene läpi?
Tämä on yksi koko prosessin tärkeimmistä kysymyksistä.
Kypsällä pipeline-prosessilla pitäisi olla selkeästi määritellyt säännöt.
Jos kriittinen testi ei mene läpi, versiota ei pitäisi pitää valmiina käyttöönottoon.
Jos tietoturvaskannaus löytää tietyn riskitason, pipeline voi pysäyttää prosessin.
Jos buildi ei onnistu, ei ole mitään otettavaa käyttöön.
Se kuulostaa itsestään selvältä. Mutta juuri tällaiset automaattiset "portit" varmistavat, että laatu ei riipu vain ihmisen muistista ja tarkkuudesta.
Entä jos käyttöönotto kuitenkin epäonnistuu?
Edes paras prosessi ei poista kaikkia virheitä. Siksi kypsän deliveryn toinen osa on mahdollisuus muutoksen hallittuun palauttamiseen.
Rollback voi tarkoittaa paluuta edelliseen artefaktiin, konttikuvastoon tai sovellusversioon. Mutta tässä tulee esiin tärkeä ongelma. Koodin rollback ei aina tarkoita datan rollbackia.
Jos uusi versio muutti tietokannan rakennetta, tilanteesta tulee monimutkaisempi.
Siksi tietokantamigraatiot kannattaa suunnitella niin, että koko prosessi on mahdollisimman turvallinen ja palautettavissa tai ainakin yhteensopiva sovelluksen edellisen version kanssa.
Tämä on yksi esimerkki siitä, että ammattimainen CI/CD on arkkitehtoninen ongelma, ei vain työkalun konfigurointia.
Blue-green, canary ja muut käyttöönoton strategiat
Vaativammissa järjestelmissä kaikkia käyttäjiä ei tarvitse siirtää heti uuteen versioon. Voidaan käyttää erilaisia deployment-strategioita.
Blue-green deployment
Käytössä on kaksi ympäristöversiota.
Toinen palvelee liikennettä, toinen valmistellaan ottamaan liikenne vastaan.
Onnistuneen varmistuksen jälkeen tehdään vaihto.
Etuna on mahdollisuus palata nopeasti edelliseen ympäristöön.
Haittana voi olla suurempi infrastruktuurin kulutus.
Canary deployment
Uusi versio menee ensin pienelle osalle käyttäjistä tai liikenteestä.
Jos valvonta ei osoita ongelmia, käyttöönoton laajuutta voidaan kasvattaa vähitellen.
Tämä rajoittaa virheen mahdollista vaikutusalaa.
Se vaatii kuitenkin asianmukaisen infrastruktuurin, valvonnan ja tavan hallita liikennettä.
Feature flags
Toiminto voidaan ottaa järjestelmään käyttöön, mutta pitää sen käyttäjiltä poissa päältä.
Näin koodin käyttöönotto ja toiminnallisuuden aktivointi muuttuvat kahdeksi erilliseksi prosessiksi.
Tämä antaa enemmän hallintaa, erityisesti suurten muutosten yhteydessä.
Se ei kuitenkaan tarkoita, että feature flagit olisivat ratkaisu jokaiseen projektiin. Myös niiden liiallinen käyttö voi lisätä järjestelmän monimutkaisuutta.
Seuranta käyttöönoton jälkeen
Voidaan suorittaa kaikki testit. Voi olla erinomainen pipeline. Uusi versio voidaan ottaa käyttöön ilman ainoatakaan virhettä. Ja muutamaa minuuttia myöhemmin sovellus voi alkaa käyttäytyä toisin todellisessa kuormituksessa.
Siksi prosessi ei saisi päättyä deploymendiin. Tarvitaan observabilitya, eli kykyä ymmärtää, mitä toimivan järjestelmän sisällä tapahtuu.
Arkkitehtuurista riippuen siihen kuuluvat muun muassa:
-
lokit,
-
metriikat,
-
tracing,
-
infrastruktuurin valvonta,
-
sovelluksen valvonta,
-
hälytykset,
-
virhetiedot,
-
liiketoiminnan mittarit.
Kyse ei ole kaiken keräämisestä. Kyse on siitä, että tärkeisiin kysymyksiin voidaan vastata datan perusteella.
Toimiiko sovellus?
Toimiiko se hitaammin kuin aiemmin?
Onko virheiden määrä kasvanut?
Mikä palvelu aiheuttaa ongelman?
Vaikuttaako ongelma kaikkiin käyttäjiin vai vain osaan?
100 käyttöönottoa päivässä ei aina ole tavoite
Tämän artikkelin otsikko puhuu 100 käyttöönotosta päivässä, mutta tarkoituksena ei ole asettaa sitä tavoitteeksi.
Sisäisessä järjestelmässä, jota päivitetään kerran kuukaudessa, ei ole järkeä pyrkiä keinotekoisesti satoihin deploymenteihin. Hyvin intensiivisesti kehitettävässä järjestelmässä tällainen taajuus voi kuitenkin olla teknisesti mahdollinen.
Keskeistä on kyky toimittaa muutoksia turvallisesti, ei itse käyttöönottojen määrä. Tämä on perustavanlaatuinen ero.
Prosessin kypsyyttä mitataan ei sillä, kuinka usein otamme käyttöön, vaan sillä, kuinka ennustettavasti ja turvallisesti osaamme sen tehdä.
Milloin CI/CD voi olla muodon voittoa sisällöstä?
Kaikki sovellukset eivät tarvitse monimutkaista deployment-infrastruktuuria.
Jos kyseessä on pieni sovellus, pieni tiimi ja muutama käyttöönotto vuodessa, laaja pipeline voi maksaa enemmän kuin ongelmat, joita sen on tarkoitus ratkaista.
Samoin hyvin erikoistuneissa järjestelmissä, joissa käyttöönotto vaatii manuaalista valvontaa turvallisuussyistä, sääntelyn vuoksi tai infrastruktuurin luonteen takia.
Siksi delivery-arkkitehtuurin tulisi perustua järjestelmän tarpeisiin. Ei muotiin.
Milloin käyttöönottojen automaatio tuo erityisen paljon hyötyä?
Sitä kannattaa harkita erityisesti silloin, kun:
-
järjestelmää kehitetään säännöllisesti,
-
koodin parissa työskentelee useita henkilöitä,
-
ympäristöjä on enemmän kuin yksi,
-
käyttöönottoja tehdään usein,
-
manuaaliset käyttöönotot aiheuttavat virheitä,
-
järjestelmä on liiketoiminnallisesti kriittinen,
-
tarvitsemme nopean rollbackin,
-
sovelluksessa on useita komponentteja,
-
tarvitaan auditointeja tai muutosten jäljitettävyyttä,
-
toiminnallisuuden toimitusaika on liiketoiminnallisesti merkityksellinen.
Tällaisissa tapauksissa hyvin suunniteltu pipeline voi olla yksi ohjelmistokehitysprosessin tärkeimmistä osista.
CI/CD ei korjaa huonoa arkkitehtuuria
Tämäkin on hyvä korostaa.
Voidaan rakentaa erinomainen pipeline huonolle sovellukselle.
Testata automaattisesti huonoa koodia.
Ottaa automaattisesti käyttöön huonoa arkkitehtuuria.
Skaalata automaattisesti huonosti suunniteltua järjestelmää.
Automaatio ei siis korvaa arkkitehtuuria, testejä eikä tiimin osaamista.
Se vahvistaa olemassa olevaa prosessia.
Jos prosessi on hyvä, se auttaa skaalaamaan sitä.
Jos prosessi on huono, se voi vain tehdä huonoja asioita nopeammin.
Miltä kypsä prosessi näyttää?
Yhtä universaalia pipelinea ei ole.
Mutta kypsällä prosessilla pitäisi olla muutama perusominaisuus.
Toistettavuus - käyttöönotto tehdään määriteltyjen vaiheiden mukaisesti.
Automaatio - koneet tekevät mahdollisimman suuren osan toistuvasta työstä.
Testattavuus - muutokset varmennetaan automaattisesti.
Turvallisuus - prosessi sisältää asianmukaiset turvallisuustarkistukset.
Havaittavuus - käyttöönoton jälkeen tiedetään, mitä järjestelmässä tapahtuu.
Palautettavuus - on olemassa suunniteltu tapa reagoida epäonnistuneeseen muutokseen.
Muutosten seuranta - tiedetään, mikä versio otettiin käyttöön ja mistä se muodostui.
Käyttöoikeuksien hallinta - kuka tahansa ei voi vapaasti ottaa mitä tahansa tuotantoon.
Juuri tällaisista elementeistä syntyy ammattimainen software delivery -prosessi.
Tärkein muutos alkaa eri kysymyksestä
Yritykset kysyvät usein: "Kuinka nopeasti voimme rakentaa tämän ominaisuuden?"
Kannattaa lisätä toinen kysymys: "Kuinka nopeasti ja turvallisesti voimme toimittaa seuraavat 50 ominaisuutta?"
Yksittäisen käyttöönoton voi tehdä käsin. Sovellusta voi jopa ottaa käyttöön käsin useiden vuosien ajan. Mutta tuotteen, tiimin, käyttäjämäärän ja muutosten määrän kasvaessa kasvaa myös tällaisen lähestymistavan hinta.
Siksi CI/CD, automaattiset testit, valvonta ja kontrolloidut deploymentit eivät ole vain suurten yritysten ratkaisuja.
Ne ovat prosessi-infrastruktuurin osia, joiden avulla voidaan kehittää ohjelmistoa lisäämättä tarpeetonta riskiä jokaiseen seuraavaan muutokseen.
Ja lopulta juuri siitä on kyse.
Ei 100 käyttöönotosta päivässä.
Ei trendikkäistä työkaluista.
Ei kaikkein monimutkaisimmasta putkesta.
Vaan kyvystä sanoa:
"Meillä on muutos. Olemme tarkistaneet sen. Tiedämme, mitä otamme käyttöön. Tiedämme, miten sitä seurataan. Ja tiedämme, mitä teemme, jos jokin menee pieleen."
