Kahden CI/CD-palvelimen, Concourse ja Jenkinsin, perusteellinen vertailu.
Sofus Albertsen
Sofus is a Continuous Delivery Trainer and Consultant in Copenhagen. Before joining Eficode Praqma he was assistant professor on an Applied Science Bachelor program. He flies kites and in the summer he escapes the modern world by spending two weeks in a beach hut without electricity or network coverage.
Mitä tarvitsemme CI/CD-järjestelmältä? Miten päätämme, mitä niistä käyttää? Tässä blogissa pohdimme, millainen modernin CI/CD-järjestelmän tulisi olla, ja vertailemme kahta yleisesti käytettyä build-järjestelmää: Jenkins-pipelineja ja Concourse CI:tä.
Kriteerit build-järjestelmän arviointiin
Käyttäjät valitsevat usein build-järjestelmän, kuten Jenkinsin, Travisin tai VSTS:n, vähemmän kuin järkiperäisin perustein. Päätös voi perustua tunteeseen tai siihen, että joku tiimin jäsenistä on käyttänyt sitä aiemmin, eikä niinkään tietoon. Oikean CI/CD-järjestelmän valinnan tulisi perustua yrityksen ja tiimin tarpeisiin, ei vanhoihin tottumuksiin tai mututuntumaan.
Eficodella (entinen Praqma) autamme päivittäin kymmeniä eri yrityksiä niiden matkalla kohti Continuous Deliveryä. Kokemuksemme pohjalta olemme koonneet listan kriteereistä, jotka jokaisen CI/CD-järjestelmän tulisi täyttää.
Yritykselläsi voi olla erityistarpeita, ja jotkin kriteerit voivat olla sinulle muita tärkeämpiä. Siksi sinun on päätettävä, mikä työkalu sopii sinulle parhaiten.
Olemme jakaneet vaatimuksemme kahteen luokkaan: kehitykseen ja ylläpitoon. Tässä kirjoituksessa keskitymme CI-palvelimen kehityspuoleen.
Kehitykseen liittyvät vaatimukset
On avoimen lähdekoodin ratkaisu.
Näin voimme lisätä mukautettuja lisäosia, korjata bugeja ja ymmärtää teknologian vision.Tukee pipelineja koodina.
Infrastruktuuri koodina!Tulee tukea kaikkia keskeisiä käyttöjärjestelmiä.
Windowsia, OSX:ää ja Linuxia (vähintään Debian- ja Red Hat -pohjaisia jakeluita)Mahdollistaa pipelinen määrittämisen kaikille keskeisille ohjelmointialueille
Sulautetut järjestelmät, web, työpöytäsovellukset ja mobiiliOn käytettävissä sekä paikallisesti että palvelinpuolella.
Voi suorittaa määritetyt vaiheet rinnakkain
Saman lähdekoodin buildin kymmenessä käyttöjärjestelmässä tulisi tapahtua rinnakkain.Voi tallentaa artefakteja build-vaiheesta toiseen
Voi käynnistää pipeline-vaiheen uudelleen ongelman selvittämiseksi
Näin voimme lisätä mukautettuja lisäosia, korjata bugeja ja ymmärtää teknologian vision.
Windowsia, OSX:ää ja Linuxia (vähintään Debian- ja Red Hat -pohjaisia jakeluita)
Sulautetut järjestelmät, web, työpöytäsovellukset ja mobiili
Saman lähdekoodin buildin kymmenessä käyttöjärjestelmässä tulisi tapahtua rinnakkain.
Tarkempi katsaus Concourseen ja Jenkins-pipelineihin
Keskitymme Jenkinsissä vain "uusiin" pipeline-töihin, sillä Jenkins panostaa tällä hetkellä niihin. Aina kun siis puhumme Jenkinsistä, tarkoitamme Jenkins-pipelinea.
Historia
Concourse
cloudfoundry-projektin kehitystiimit kohtasivat Jenkins-pipelineissaan useita ongelmia. He yrittivät saada ne toimimaan, mutta heillä oli vaikeuksia CloudFoundryn tarvitsemien eri alustojen ja palveluiden kanssa, ja Jenkinsin lisäosa-arkkitehtuuri vei heidät mukanaan. Tästä syntyi Concourse CI, jota johtivat Alex Suraci ja hänen tiiminsä. Concoursen tavoitteena oli modernimpi ja vähemmän lisäosariippuvainen build-järjestelmä, joka voisi hyödyntää uudempia teknologioita, kuten kontteja, ja nostaa pipelinet keskeiseen rooliin. Koska CloudFoundry on avointa lähdekoodia, myös Concourse CI on sitä.
Jenkins
Jenkinsin historia on pitkä ja osoittaa, että sitä ympäröivä yhteisö on elinvoimainen ja vahva. Se pystyy vastustamaan suurta yritystä päättäessään omasta erillisestä suunnastaan.
Se on riittävän kypsä ja sillä on riittävän laaja käyttäjäkunta lähes kaikenlaisten alustalta vaadittavien tarpeiden täyttämiseen.
Jenkins on kuitenkin pitkälti Cloudbeesin hallinnassa. Sen luoja Kohsuke Kawaguchi on toiminut Cloudbeesin CTO:na vuodesta 2014 lähtien, joten mitä Cloudbees tekee, sitä Kohsuke tekee – ja siten myös yhteisö. Cloudbees muuttaa aktiivisesti Jenkinsiä vastaamaan CI-palvelinten uusia standardeja.
Terminologia ja arkkitehtuuri
Concourse
Concourse on pohjimmiltaan konttiteknologiaa, mutta sitä voidaan ajaa myös yksinkertaisesti virtuaalikoneissa.
Concourse-build-järjestelmä koostuu masterista, pysyvään tallennukseen käytettävästä PostgreSQL-tietokannasta sekä yhdestä tai useammasta workerista.
Concourse-master on käytännössä ATC (lyhenne sanoista air traffic control), joka on järjestelmän ytimessä. Korkean käytettävyyden varmistamiseksi voidaan ajaa useita ATC-instansseja, kunhan ne käyttävät samaa PostgreSQL-tietokantaa. ATC orkestroi pipelinen ja jakaa Concourse-kuormaa.
Workerit rekisteröidään TSA:n (lyhenne sanoista transportation security administration, lentoliikenteen ohjaukseen viittaava sanaleikki) kautta. Kyseessä on käytännössä SSH-protokolla, jonka avulla workerit voivat yhdistää masteriin TSA:sta muodostettavan käänteisen tunnelin kautta. Tämän jälkeen master voi ohjata liikennettä.
Koska Concourse ei salli kehittäjien määrittää pipelinea palvelimelta, uuden pipelinen määrittämiseen tarvitaan binääritiedosto nimeltä fly.
Concourse-pipeline koostuu kolmesta elementistä: resursseista, resurssityypeistä ja jobeista. Concourse-resurssi on kohde, joka täytyy hakea pipelineen tai viedä siitä ulos. Hyviä esimerkkejä ovat Git, artifact-tallennus ja sähköpostit, mutta myös abstraktit asiat, kuten aika, muut pipelinet ja palvelinkonfiguraatio.
Resurssityypeillä määritellään ulkoiset resurssit, joita Concourse-tiimi ei ole luonut. Ne haetaan ja niitä käsitellään samalla tavoin kuin natiiveja resursseja. Jobit puolestaan ovat suorittavia elementtejä, jotka buildaavat koodia tai ajavat resurssiin liittyvää automaatiota.
Jenkins
Jenkinsin terminologia on seuraava:
Jenkins-master on edistynyt ajastin, joka valvoo ja suorittaa buildit nodeissa job-määritysten perusteella. Job voidaan määritellä monella tavalla: Standard jobina, JobDSL:n kautta tai uuden Jenkins Pipeline -toiminnallisuuden avulla.
Arkkitehtuuriltaan Jenkins on ”vain” Java-pohjainen WAR-tiedosto palvelimelle ja JAR-tiedosto jobeja buildaaville nodeille. Se tallentaa kaikki konfiguraatiot ja lokit tiedostoihin masterin levylle. Jenkinsin ydin koostuu vain ajastimesta, nodejen välisestä viestinnästä ja suorituksesta. Muusta vastaavat pluginit – ja niitä riittää!
Jenkinsille on tällä hetkellä 1 431 pluginia, mikä on sekä vahvuus että heikkous. Vahvuus on se, että Jenkinsistä on tullut CI:n linkkuveitsi.
Jos tarvitset Jenkinsin tekevän jotain, joku on todennäköisesti jo tehnyt sitä varten pluginin! Pluginien runsaudella on kuitenkin hintansa: kaikki niistä eivät ole tuotantovalmiita tai toimi uuden Pipeline -konseptin kanssa.
Koska Jenkins on ollut käytössä huomattavasti kontteja pidempään, se keskittyy ajamaan buildin nodessa kontin sijaan. Se tukee kontteja silti hyvin joko suoraan shellistä tai pluginin kautta, joten niiden käyttö ja lokien kerääminen on helppoa.
Hello world
Concourse
Concourse-yml on yleensä jaettu useisiin tiedostoihin, mutta lukemisen helpottamiseksi kaikki on upotettu alle:
jobs:- name: hello-world public: true plan: - task: hello-world config: platform: linux image_resource: type: docker-image source: {repository: ubuntu} run: path: sh args: - -exc - | echo "hello world"Tämä luo yhden jobin ilman resursseja tai jobin syötteitä ja tulostaa ”hello world”. Sen voi käynnistää web-käyttöliittymästä tai fly-nimisellä komentorivikäyttöliittymällä: fly -t yourconcourses execute --config tests.yml
Tätä voidaan käyttää missä tahansa pipelinen taskissa, jolloin kehittäjä saa täyden pääsyn jobiin paikallisten binääritiedostojensa ja tiedostojensa avulla – myös myöhemmissä jobeissa.
Jenkins
Jenkinsissä on kaksi Pipeline DSL -versiota: declarative ja scripted pipeline.
Molemmissa tapauksissa sinun on määritettävä pipeline-työ joko Jenkinsin käyttöliittymässä tai sen API:n kautta. Jenkins tukee VCS:ssä olevaa pipelinea tai Jenkinsin työmääritykseen kirjoitettua pipelinea. Kun tämä on tehty, DSL-tiedosto on hyvin pelkistetty, ja hello world onnistuu lähes yhdellä rivillä.
#Declarative pipeline pipeline { agent any stages { stage('Build') { steps { echo 'hello world' } } } } #Scripted pipeline node { stage('Build') { echo 'hello world' } }Yhteenveto
Voittaja: Molemmat
Molempien järjestelmien käyttöönotto on suoraviivaista. Emme arvioisi niitä, jos emme saisi niitä käyntiin.
Käyttöjärjestelmät
Concourse
Concourse-workerin tai -masterin luot lataamalla Concourse-binäärin ja antamalla sille joko ”worker”- tai ”master”-argumentin. Prosessi on sama riippumatta siitä, käytätkö Windowsia, Linuxia vai OS X:ää, sillä Concourse on kirjoitettu GoLangilla.
Kaikki natiivit resurssit ja useimmat yhteisön resurssit toimivat kuitenkin konteissa, joten huomioon on otettava muutamia lisätekijöitä. Tämä tarkoittaa, että tyypillisessä Windows-kokoonpanossa tarvitaan silti vähintään yksi Linux-worker resurssien käyttämiseksi. Lisäksi vaikka Windows tekee konttien käytöstä mahdollista, Concourseen tämä ominaisuus on tulossa vasta tulevaisuudessa. Windows-worker ajaa siis prosessinsa aina virtuaalikoneessa ja erottaa ne kansiorakenteen avulla konttien tavan sijaan.
Katso Windowsissa ajettavan pipeline-työn esimerkki Git Phlow Windows -työstämme. OSX:ssä toteutus tehdään vastaavasti, mutta usein on yksinkertaisempaa käyttää Linux-slaveja.
Hyvä esimerkki löytyy täältä (huomaa ”platform: darwin”). Esimerkki on peräisin David Karlssonin blogista, jossa käsitellään Concoursen käyttöönottoa mobiili- ja OSX-kehitykseen.
Jenkins
Jenkins-nodet toimivat joko fyysisillä palvelimilla tai virtuaalikoneissa. Jos käyttöjärjestelmälle on JVM, Jenkins toimii siinä. Node-ympäristön määrittely riippuu sinusta: voit käyttää esimerkiksi Ansiblea, Chefiä tai Puppetia tai asentaa palvelimen manuaalisesti (Jos teet niin, harkitse myös tämän vaiheen automatisointia!). Nodeja voi lisätä palvelinryhmään masterin käyttöliittymän kautta tai Jenkins Swarm -lisäosalla, joka saa nodet ottamaan yhteyden masteriin.
Yhteenveto
Voittaja: Ratkaisematon
Konttien käytöstä on selkeitä hyötyjä, mutta se myös lisää tietyn määrän monimutkaisuutta. JVM on helppo ottaa käyttöön ja se toimii kaikkialla, mutta sen mahdollisuudet ovat rajallisemmat.
Pipelinet: sulautetuista järjestelmistä mobiiliin
Concourse
Concourse soveltuu erinomaisesti web-, mobiili- ja työpöytäsovelluskehitykseen. Sulautetuissa järjestelmissä taas monet FPGA-työkalut toimivat yleensä Windowsissa. Tämä ei estä Concoursen käyttöä, mutta teknologian hyödyt jäävät saamatta.
Linux-työkalut, kuten NT FPGA, ovat vahvasti GUI-pohjaisia, mikä aiheuttaa samankaltaisia haasteita. Concourse on parhaimmillaan, kun kontteja hyödynnetään, eikä kontteja kannata käyttää prosesseihin, joiden uudelleenajo on kallista. Jos build kestää puoli tuntia, konttien helppo uudelleenajo epäonnistumisen jälkeen ei juuri auta.
Monissa sulautetuissa järjestelmissä resurssit on lukittava build-virran varmistamiseksi, kun taas Concoursen prosessien on normaalisti tarkoitus olla täysin atomisia.
Jenkins
Kuten edellä todettiin
jos siinä on JVM, Jenkins toimii siinä.
Tässä suhteessa se ajaa kaikki pipelinet tasapuolisesti, olipa kyse mobiilisovelluksista (esimerkki täällä ja täällä), Haskell-kääntäjästä tai sulautetusta FPGA-kehityksestä.
Kun käytössä on niukka resurssi, Lockable Resources -lisäosa tarjoaa todella tehokkaan tavan jakaa resurssi eri noodien kesken.
Resurssin lukitseva koodi on todella yksinkertainen ja suoraviivainen:
echo 'Starting' lock('my-resource-name') { echo 'Do something here that requires unique access to the resource' // any other build will wait until the one locking the resource leaves this block } echo 'Finish'Voit jopa muuttaa resurssien kohdistusjärjestyksen FIFO-jonon käänteiseksi:
lock(resource: 'staging-server', inversePrecedence: true) { node { servers.deploy 'staging' } input message: "Does ${Url}staging/ look good?" }Yhteenveto
Voittaja: Jenkins
Jenkins voittaa tämän vertailun. Se toimii kaikkialla, ja resurssien lukitseminen on helppoa, mikä on monille välttämätöntä.
Kehittäjien käynnistämä työ
Concourse
Concourse antaa kehittäjille mahdollisuuden suorittaa töitä palvelimella omasta terminaalistaan komennolla:
fly -t myserver execute --config myjob.ymlSe käyttää tällöin annettua paikallista syötettä ja suorittaa työn. Tämä on todella hyödyllistä, sillä kehittäjät voivat debugata koodiaan ilman, että heidän tarvitsee käydä pipelinea läpi.
Tähän tarvitaan vain Concourse-palvelin, johon kehittäjät voivat kohdistaa työn ja joka suorittaa sen määrittelyjä vastaavassa eristetyssä tilassa tietyllä slave-palvelimella.
Jenkins
Tällä alueella Jenkins ei ole edes mukana. Tarvitsemme palvelimella määritellyn työn voidaksemme suorittaa jotain build-palvelimilla. Piste.
Jotta voit testata jotain, sinun on siis tehtävä Git-kierros:
Git push --> Jenkins pull --> Jenkins build --> Jenkins response --> Repeat
Multibranch pipeline -toiminnolla voit kuitenkin muokata pipelinea tarpeidesi mukaan ja puskea sen muuhun kuin master-haaraan nähdäksesi suorituksen.
Yritysympäristössä voisi ehkä esittää, että ”resursseja ei pitäisi käyttää sellaiseen, jolla ei ole kunnollista pipelinea”.
Myönnän, että haluaisin todella voida lähettää työn palvelimelle suoritettavaksi. Se olisi erinomainen ominaisuus.
Yhteenveto
Voittaja: Concourse
Concourse näyttää suuntaa kehittäjien käynnistämissä pipeline-suorituksissa. Jenkins, sinun on parannettava tässä!
Pipelinen rinnakkaistaminen
Concourse
Sekä yksittäisten töiden (aggregate), resurssien että kokonaisten pipelinejen rinnakkaista suorittamista tuetaan. Kun resurssissa tapahtuu muutos, se voi käynnistää kaikki siitä riippuvat työt. Jos resurssi muuttuu hetkeä myöhemmin uudelleen, työ suoritetaan rinnakkain uuden syötteen kanssa.
Jälleen git phlow'mme tarjoaa hyviä esimerkkejä tämän käytöstä tuotantokoodissa.
- name: afterburner plan: - aggregate: - get: praqma-tap - get: git-phlow #contains the formula update script - get: gp-version passed: [takeoff] - get: phlow-artifact-darwin-s3 passed: [takeoff] trigger: true - task: brew-release file: git-phlow/ci/brew/brew.yml on_failure: put: slack-alert params: text: | brew release failed https://concourse.bosh.praqma.cloud/teams/$BUILD_TEAM_NAME/pipelines/$BUILD_PIPELINE_NAME/jobs/$BUILD_JOB_NAME/builds/$BUILD_NAME - put: praqma-tap params: repository: updated-praqma-tapJenkins
Jenkins tukee tätä natiivisti molemmissa DSL-muodoissa. Se luo masteriin kevyen työn buildien koordinointia varten. Tämä tarkoittaa, että yhden vaiheen kaikkien rinnakkaisten suoritusten on valmistuttava ennen seuraavan vaiheen käynnistämistä.
Alla on esimerkkejä siitä, miltä rinnakkaisten suoritusten luettelo voi näyttää sekä scripted- että declarative-muodossa.
Jenkinsfile (Scripted Pipeline) stage('Test') { parallel linux: { node('linux') { try { sh 'run-tests.sh' } finally { junit '**/target/*.xml' } } }, windows: { node('windows') { try { sh 'run-tests.bat' } finally { junit '**/target/*.xml' } } } }Jenkinsfile (Declarative Pipeline) pipeline { agent none stages { stage('Test') { parallel { stage('Windows') { agent { label "windows" } steps { bat "run-tests.bat" } post { always { junit "**/TEST-*.xml" } } } stage('Linux') { agent { label "linux" } steps { sh "run-tests.sh" } post { always { junit "**/TEST-*.xml" } } } } } } }Yhteenveto
Voittaja: Concourse
Concourse voittaa tämän, joskin niukasti.
Kun suoritat tehtäviä rinnakkain Jenkinsissä, kaikkien on valmistuttava, ennen kuin työnkulku voi haarautua uudelleen. Concoursen määritelmä on huomattavasti väljempi, joten se voi riippua mielivaltaisista ehdoista.
Artefaktien hallinta
Concourse
Concoursen työnkulku erottaa resurssit ja työt tiukasti toisistaan. Työ voi koostua useista tehtävistä, jotka voivat jakaa artefakteja, mutta työ voi jakaa artefaktin toisen työn kanssa vain, jos resurssi siirretään ulos ja tallennetaan töiden välissä. Concourse ei itse koskaan tallenna artefakteja, vaan se pakottaa tähän pull/push-ajatteluun atomisten töiden varmistamiseksi.
Jenkins
Jenkins voi tallentaa artefakteja masteriin käyttämällä archive-avainsanaa, mutta yleensä suosittelemme tähän tarkoitukseen erillistä artefaktien hallintajärjestelmää, kuten Artifactorya.
Jos haluat siirtää tiedostoja pipeline-scriptin yhdestä nodesta toiseen, esimerkiksi kun haluat siirtää web-sovelluksesi kuormitustestiympäristöön, voit käyttää stash/unstash-ominaisuutta, joka toimittaa artefaktit tarvittaessa määritettyyn nodeen.
Yhteenveto
Voittaja: Jenkins
Molemmilla on kolmannen osapuolen ominaisuuksia, mutta Jenkinsissä on lisäksi sisäänrakennettu tuki artefaktien tallentamiseen masteriin.
Todellinen kysymys onkin: haluatko todella, että CI/CD-järjestelmäsi toimii myös artefaktien hallintajärjestelmänä?
Pipelinejen uudelleenkäynnistäminen
Concourse
Tämä onnistuu helposti joko siirtymällä web-käyttöliittymään ja napsauttamalla työn '+'-merkkiä tai ajamalla työn uudelleen fly-komentorivikäyttöliittymästä. Tällöin se yrittää suorittaa saman prosessin kuin aiemmin samoilla syötteillä tai uusilla, jos ne ovat päivittyneet.
Jenkins
Voit käynnistää koko pipelinen uudelleen milloin tahansa samoilla parametreilla.
Pipelinen sisäisen vaiheen käynnistäminen on (suureksi turhautumisekseni) vain Jenkins Enterprise -ominaisuus. Cloudbees kuitenkin kehittää ominaisuutta declarative-pipelineille, mutta ei edistyneemmille scripted-pipelineille. Mielestäni tämä on erittäin pettymys.
Yhteenveto
Voittaja: Concourse
Koska Concourse käsittelee jokaisen pipelinen jobin atomisena toimintona, uudelleenkäynnistys on itsestäänselvyys. Jenkinsin on (uudelleen)toteutettava tämä ominaisuus pysyäkseen Concoursein tasolla.
Lopullinen päätelmä
Ja voittaja on…
Rehellisesti sanottuna tällaista päätelmää ei ole, sillä kaikki riippuu siitä, mitä arvostat eniten omassa ympäristössäsi. Jenkins on asiakkaidemme keskuudessa de facto -standardi, mutta Concourseilla on vahvuuksia, jotka tekevät siitä varteenotettavan kilpailijan.
- CI/CD
Subscribe to our newsletter
Related blogs