Puppet-moduulien ja manifestien uudelleenkäytettävyyden vuoksi on suositeltavaa pitää data niistä erillään. Tämä tapahtuu käyttämällä hieraa. Moduulit voivat esimerkiksi tuottaa erilaisia asetuksia käyttämällä hieran perusteella organisaatiohin tai sijainteihin määriteltyä dataa
Hieraan tallennetaan tyypillisesti myös sellaista yksityistä dataa mikä pitää olla suojattua, ja minkä ei haluta joutuvan ulkopuolisten saataville. Tyypillisesti data tallennetaan muun koodin ohella versionhallintajärjestelmään, joka voi olla organisaation rajojen ulkopuolella. Tällöin on käytettävä hieran encryptionta.
Aiemmin yleisesti käytetty hieran salauksen menetelmä oli hiera-gpg. Hiera-gpg:n avulla salattiin koko tiedosto. Hiera-eyaml parantaa tilannetta sallimalla hieratiedoston sisällä haluttujen datalohkojen salaamisen, mikä parantaa käytettävyyttä.
Hiera-yaml pitää ensin asentaa:
$ sudo gem install hiera-eyaml
$ sudo puppetserver gem install hiera-eyaml
Hiera-eyaml käyttää asymmetristä enkryptointia, oletuksena PKCS#7:ää. Sen käyttöön tarvitaan siis avainpari. Julkisella avaimella voidaan purkaa salattujen datalohkojen encryption ja yksityisellä avaimella salata. Avainpari luodaan komennolla:
$ eyaml createkeys
Avainpari luodaan sen hetkisen hakemiston keys-alihakemistoon. Luodut avaimet tulee suojata ja säilyttää huolellisesti. Salauksen tuottamiseen riittää että julkinen avain on käytettävissä. Salatun lohkon muokkaamiseen tarvitaan sekä julkinen että yksityinen avain. Henkilö, joka lisää tai muokkaa hiera-tiedostojen sisältöä tarvitsee siis molemmat avaimet. Avaimet tulee suojata vastaavasti kuten palvelimellakin, eli omistajaksi määritetään käyttäjä ja tiedostoille vain lukuoikeus käyttäjälle itselleen. Sopiva sijainti on esimerkiksi kotihakemiston keys-alihakemisto.
Puppetserver tarvitsee salauksen purkamiseen ja arvojen lukemiseen sekä julkisen että yksityisen avaimen. Puppetserverillä sopiva sijainti avaimille on esim.:
/etc/puppetlabs/puppet/eyaml
$ mkdir /etc/puppetlabs/puppet/eyaml $ chown -R puppet:puppet /etc/puppetlabs/puppet/eyaml $ chmod -R 0500 /etc/puppetlabs/puppet/eyaml $ chmod 0400 /etc/puppetlabs/puppet/eyaml/*.pem
$ ls -lha /etc/puppetlabs/puppet/eyaml
Omistajana tulee siis olla puppet, ryhmäomistajana puppet, ja lukuoikeus vain puppet-tunnukselle.
Jos käyttäjä haluaa muokata omalle koneellaan olemassaolevan hiera-tiedoston arvoja, tyypillisesti hallintarepon kopiossa, tarvitaan molemmat avaimet. Avaimet tulee siirtää omalle koneelle asianmukaisella turvallisella protokollalla, esim. scp:llä. Muokkaamisen helpottamiseksi on hyödyllistä luoda kotihakemistoon uusi hakemisto .eyaml, ja sinne konfigurointitiedosto config.yaml, jossa määritetään mistä avaimet löytyvät:
--- pkscs7_public_key: '/Users/tunnus/keys/public_key.pkcs7.pem' pkcs7_private_key: '/Users/tunnus/keys/private_key.pkcs7.pem'
Kun avaimet ovat palvelimella paikoillaan, voidaan määrittää hieran konfigurointitiedosto käyttämään näitä avaimia. Uudessa hiera-versiossa 5 on itsenäiset hierarkian määritykset jokaiselle environmentille ja moduulille. Hiera.yaml voidaan siis sijoittaa hallintarepoon ja sen haaroihin, ja viitata näissä edellä luotuihin avaimiin palvelimella. Oletetaan että yksityiselle avaimelle on annettu nimi private_key.pkcs7.pem ja julkiselle avaimelle public_key.pkcs7.pem.
--- version: 5 defaults: datadir: data data_hash: yaml_data hierarchy: - name: "Secret data" lookup_key: eyaml_lookup_key paths: - "secrets.eyaml" options: pkcs7_private_key: /etc/puppetlabs/puppet/eyaml/private_key.pkcs7.pem pkcs7_public_key: /etc/puppetlabs/puppet/eyaml/public_key.pkcs7.pem - name: "Per-node data" path: ”nodes/%{trusted.certname}.yaml" - name: "Common data" path: "common.yaml"
$ export EDITOR=emacs
$ eyaml edit secrets.eyaml
Eyaml avaa tällöin tiedoston ohjeen kera. Salattavaksi haluttu arvo laitetaan tällöin hakasulkeiden väliin muotoon DEC::PKCS7[]!
#| This is eyaml edit mode. This text (lines starting with #| at the top of the #| file) will be removed when you save and exit. #| - To edit encrypted values, change the content of the DEC(<num>)::PKCS7[]! #| block. #| WARNING: DO NOT change the number in the parentheses. #| - To add a new encrypted value copy and paste a new block from the #| appropriate example below. Note that: #| * the text to encrypt goes in the square brackets #| * ensure you include the exclamation mark when you copy and paste #| * you must not include a number when adding a new block #| e.g. DEC::PKCS7[]! --- # This value will not be encrypted plaintextvalue: plaintext # This value will be encrypted encryptedvalue: DEC::PKCS7[encrypted]!
Jos nyt katsotaan tiedostoa, voidaan todentaa että edellä määritetty arvo on salattu:
$ cat secrets.eyaml --- # This value will not be encrypted plaintextvalue: plaintext # This value will be encrypted encryptedvalue: ENC[PKCS7,MIIBeQYJKoZIhvcNAQcDoIIBajCCAWYCAQAxggEhMIIBHQIBADAFMAACAQEwDQYJKoZIhvcNAQEBBQAEggEAK/YGRbR2qbgpxHxrCic6ywXG6x0w0hZksNQqJPBYTq2FDyDO7H9L0XlVmnSP+wpjEleDGBJqUEyxgucYICvub5QaHQukBJ7/5ZeQ3grGIBOQkvEZVONWjNtdA+MkiIrc/erasgWYaU8lVJZ73RC6VzJQHYdphCsxue10kTAQw1uBKZOCbc9qHlhIwJuNERfUZBsfMpWgmnExph3kBsVlQ4FPTurkX2Kp0wEQlDVKm5llv4juq3dQLhDS4NkxmdopX/8jWP8+TMQB7vfW5kgS2U08vlm9QKgukO6GMeDrn/1Y66KnbokfGh4eJF7L94A1EYpKQx5eja+ITkvGarvCSTA8BgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBBn5gfCNVVsnRmQgIhE23pZgBAHsuh7FqP+XQMbJCQlREMN]
Linkkejä:
Mikäli muutosten tekeminen Puppet-koodiin ja Hieraan suoraan puppetmasterilla tuntuu liian kevyeltä ja helpolta, voi Puppet-työnkulusta tehdä asteittain vaikeammaksi oman sietokyvyn mukaan lisäämällä palettiin lisää komponentteja. Esimerkiksi ns. control repon ja r10k:n käyttö Puppetin environmentien ylläpitoon lisää heti useita vaiheita aiemmin yksinkertaiseen työnkulkuun. Toki tällä saavutetaan myös ihan oikeita etuja, joista lisää tuonnempana.
Control repo - tästä lähtien osin suomennettuna "hallintarepo" - on käytännössä Git repository, jonka jokaisesta haarasta (branch) luodaan (tai ainakin voidaan luoda) dynaamisesti Puppet masterille vastaava Puppet-environment. Hallintarepon oletushaaran nimi, "production", on tästä syystä sama, kuin Puppet agenttien oletuksena käyttämä environment. Hallintarepon haaroissa on pitkälti sama sisältö kuin tavanomaisessa /etc/puppetlabs/code/environments/production -kansiossakin olisi:
$ ls control-repo data environment.conf hiera.yaml Puppetfile README.md site site.pp
Puppetfileä käsiteltiin jo aiemmassa artikkelista, jossa luotiin Puppet-koodiin pohjautuvia Kafo-installereja. Tiivistetysti Puppetfile sisältää viittaukset niihin Puppet-moduuleihin, jotka environmentin moduulikansiossa halutaan olevan:
# Forgen osoite forge "https://forgeapi.puppetlabs.com" # Moduuli Puppet Forgesta mod 'puppetlabs/stdlib' # Moduuli Gitistä mod 'puppet-mymodule', :git => '[email protected]:myorg/puppet-mymodule.git'
Tiedosto site.pp on näinä aikoina usein äärimmäisen pelkistetty, koska sitä tulee usein käytettyä lähinnä luokkien lataamiseen Hieran "classes"-listasta:
# Oletusarvo [] estää Puppet-ajojen epäonnistumisen siinä # tapauksessa, että jollakin koneella ei ole classes-listassa yhtään # luokkaa. lookup('classes', {merge => unique, default_value => []}).include
Tiedosto environment.conf on sekin varsin pelkistetty:
# Environmentin manifesti (ks. yllä) manifest = site.pp # Puppet-moduulien latauspolku. Alla käytetään globaaleja, # environmentien ulkopuolisia moduuleja kansiosta # /etc/puppetlabs/code/modules, sitten etsitään environmentin # moduulikansiosta, sitten environmentin site-kansiosta. # Site-kansion moduulien tiedostojen oletetaan olevan suoraan # hallintarepossa, ts. niihin ei viitata Puppetfilessä. modulepath = $basemodulepath:modules:site # Varmistetaan, että noodit käyttävät aina tuoreinta koodia. Suurella # noodimäärällä tämän parametrin arvoa voi joutua miettimään # uudelleen. environment_timeout = 0
Tiedosto hiera.yaml on environment-kohtainen Hieran-asetustiedosto. Aiemmista versioista poiketen versio 5 hiera.yaml:ista sallii kolmitasoisen hierarkian, johon kuuluu globaali taso, environment-kohtainen taso ja moduulikohtainen taso. Viimeksi mainittu vaikuttaa suunnitellun vaihtoehdoksi hieman ikääntyneelle params.pp -patternille. Näillä seikoilla ei ole hallintarepon kannalta muuta merkitystä kuin se, että hallintarepon jokaisessa haarassa on hiera.yaml-tiedosto - esimerkiksi tällainen:
--- version: 5 defaults: datadir: data data_hash: yaml_data hierarchy: - name: "Per-node data" path: "nodes/%{trusted.certname}.yaml" - name: "Common data" path: "common.yaml"
Kansio site sisältää hallintarepossa suoraan ylläpidettävät Puppet-moduulit, kuten yllä site.pp:n kommenteissa mainittiinkin. Näin säästytään Puppetfilen ja erillisten moduulirepojen ylläpidolta.
Kansio data sisältää Hieran hierarkian, eli yllä olevaa hiera.yml-tiedostoa käytettäessä tiedoston common.yaml sekä kansion nodes, jossa on noodeille niiden omat yaml-tiedostot.
Edellisessä blogipostauksessa esiteltiin tyypillinen hallintarepon rakenne. Tässä artikkelissa käsitellään r10k:ta, jolla hallintarepon haaroista muodostetaan Puppet-palvelimelle vastaavat Puppet-environmentit. R10k:n asennus Puppet 4:een tai uudempaan on suoraviivaista Puppet-pakettien mukana tulevalla gem-ohjelmalla:
$ /opt/puppetlabs/puppet/bin/gem install r10k
Tämän jälkeen luodaan r10k:lle asetustiedosto /etc/puppetlabs/r10k/r10k.yaml:
--- :cachedir: /opt/puppetlabs/puppet/cache/r10k :sources: control: basedir: /etc/puppetlabs/code/environments prefix: false remote: [email protected]:myorg/control-repo.git
Yllä oletetaan, että hallintarepo ("control repo") on jo olemassa GitLabissa tai vastaavassa, ja että SSH-avaimet on luotu ja lisätty hallintarepoon sekä mahdollisiin yksityisiin Puppet-moduulirepoihin, joihin Puppetfilessä viitataan.
Mikäli hallintarepo ei ole julkinen - mikä on erittäin todennäköistä - pitää r10k:lle osoittaa, mitä SSH-avainta sen tulisi käyttää hallintarepon itsensä ja yksityisten Puppet-moduulien lataamiseen. Tämä onnistuu muokkaamalla pääkäyttäjän SSH-asetuksia eli tiedostoa /root/.ssh/config:
Host gitlab.com StrictHostKeyChecking no RSAAuthentication yes IdentityFile /etc/puppetlabs/r10k/ssh/id_rsa User git
SSH-avaimen yksityisen osan (esim. id_rsa) pitää toki olla yllä mainitussa polussa (/etc/puppetlabs/r10k/ssh/id_rsa) ja sen tiedosto-oikeuksien pitää olla riittävän rajatut (esim. 0400).
Lopuksi - jos kaikki meni hyvin, voidaan hallintarepon kaikki haarat muuntaa Puppet environmenteiksi r10k:lla:
$ r10k deploy environment -v --puppetfile
Parametri --puppetfile (alias -p) aiheuttaa sen, että r10k poistaa ensin environmentit ja luo ne sen jälkeen uudestaan tyhjästä. Sivuvaikutuksena tässä on se, että kaikki Puppetfilessä mainitut Puppet-moduulit päivitetään uusimpiin versioihin, ellei niiden versiota ole erikseen määritetty.
Ajan säästämiseksi on myös mahdollista päivittää vain yksittäinen environment:
$ r10k deploy environment -v my_feature
Yllä ei myöskään käytetä parametria --puppetfile, joten olemassa olevat environmentit ainoastaan päivitetään sen sijaan, että ne jyrättäisiin sileäksi. Tarkempia ohjeita löytyy r10k:n virallisesta dokumentaatiosta.
Edellisissä artikkeleissa käsiteltiin hallintarepoa ja r10k:ta. Vaikka mikään ei estäkään hallintarepon pitämistä Puppetmaster-koneella ja r10k.yaml:n osoittamista siihen, menetettäisiin silloin monta työvaihetta eikä ratkaisu siten sopisi tämän artikkelisarjan teemaan. Viimeinen puuttuva komponentti työnkulun läskiyttämisessä onkin GitLab tai vastaava, kuten GitHub tai Bitbucket. Näistä ensimmäinen soveltuu parhaiten tilanteeseen, jossa halutaan luoda paljon yksityisiä Git-repoja, joista ei haluta maksaa, eikä GitLabin edistyneemmille ominaisuuksille ole käyttöä. GitHubissa jokainen yksityinen repository maksaa, joten se on kallis ratkaisu yksityisten puppet-moduulien säilömiseen. Bitbucket sallii GitLabin tavoin rajoittamattomasti yksityisiä repositoryjä, mutta rajoittaa käyttäjien määrän tällä hetkellä viiteen, eikä tarjoa merkittävästi etuja, paitsi ehkä Trello-integraation, jos Kanbania haluaa käytellä. GitLabilla on puolellaan vielä se etu, että se on avointa lähdekoodia, joten sen voi asentaa myös omaan sisäverkkoon ja käyttää sieltä.
Työnkulku on GitLabin ja sen kaltaisten järjestelmien kanssa jokseenkin sama. Lisäksi valmisteluvaihe on jokseenkin identtinen:
Edellisessä artikkelissa kerrottiin, miten r10k konfiguroidaan käyttämään GitLabin kanssa oikeaa SSH-avainta eli "deploy keytä". Kun kaikki yllä mainitut valmistelut on tehty, voidaankin siirtyä varsinaiseen työnkulkuun, joka menee tyypillisesti näin.
Ensin käyttäjä päivättä oman hallintarepo-klooninsa production-haaran:
$ git branch * production $ git pull
luo paikalliseen hallintarepon klooniinsa uuden haaran (ns. "feature branch"):
$ git branch feature_a $ git checkout feature_a
Seuraavaksi hän tekee tarvittavat muokkaukset ja commitoi ("commit") muutokset:
$ git add <file> $ git commit -m "Add feature a"
Sitten hän julkaisee muutokset GitLabissa:
$ git push origin feature_a
Muutokset siis löytyvät nyt GitLab-reposityn haarasta feature_a.
Seuraavaksi käyttäjä tekee "Merge requestin" GitLabin käyttöliittymällä. Yleensä GitLab osaa valita oikean lähdehaaran automaattisesti, mutta jos näin ei ole, voi sen valita myös käsin. Merge requestin kohteeksi valitaan tyypillisesti production-haara, mutta mikään ei estä erillisen, pitkäikäisen testing tai staging-haaran käyttöä ennen production-haaraan siirtämistä.
Jonkun toisen käyttäjän olisi hyvä seuraavaksi tarkistaa Merge requestin sisältämät muutokset niiden laadun varmistamiseksi. Tässä vaiheessa on myös mahdollista ja jopa järkevää ajaa r10k Puppetmasterilla, jolloin se luo Puppet environmentin feature_a:
$ r10k deploy environment
Nyt uutta ominaisuutta ("feature_a") voi testata oikeilla Puppetiin liitetyillä koneilla tähän tapaan:
$ puppet agent -tv --environment=feature_a --noop
Testikoneilla komento voidaan turvallisesti ajaa myös ilman --noop -vipua.
Jos muutokset näyttävät hyviltä ja toimivat odotetulla tavalla, voi tarkistava käyttäjä liittää ("merge") ne hallintarepoon, jolloin ne päätyvät sen production-haaraan.
Seuraava ja viimeinen vaihe on uuden production-haaran sisällön vienti oikeasti tuotantoon r10k:lla:
$ r10k deploy environment
Sama prosessi toistetaan aina muutoksia tehdessä.
Jos (ja vain jos) Puppetia käyttää ainostaan yksi henkilö, voi merge requestit halutessaan unohtaa ja tarkistaa muutokset pelkästään Gitin omilla työkaluilla eli lähinnä "git diff"-komennolla. Erillisten feature-haarojen käyttö on kuitenkin perusteltua, koska se helpottaa uuden koodin testausta r10k:lla. Testien jälkeen muutokset voi liittää ("merge") production-haaraan ja julkaista suoraan:
$ git branch * feature_a production $ git push origin feature_a $ r10k deploy environment --- testaus --- $ git checkout production $ git merge feature_a $ git push