Įvadas į lėlę

Puppet yra konfigūracijos valdymo sistema. Jis naudojamas norint atvesti šeimininkus į norimą būseną ir palaikyti šią būseną.

Su Puppet dirbu jau daugiau nei penkerius metus. Šis tekstas iš esmės yra išverstas ir pertvarkytas pagrindinių oficialios dokumentacijos punktų rinkinys, kuris leis pradedantiesiems greitai suprasti lėlių esmę.

Įvadas į lėlę

Pagrindinė informacija

Lėlių operacinė sistema yra kliento-serverio, nors ji taip pat palaiko veikimą be serverio su ribotomis funkcijomis.

Naudojamas traukimo modelis: pagal numatytuosius nustatymus kartą per pusvalandį klientai susisiekia su serveriu dėl konfigūracijos ir ją taiko. Jei dirbote su Ansible, tai jie naudoja kitokį „push“ modelį: administratorius inicijuoja konfigūracijos taikymo procesą, patys klientai nieko netaikys.

Tinklo ryšio metu naudojamas dvipusis TLS šifravimas: serveris ir klientas turi savo privačius raktus ir atitinkamus sertifikatus. Paprastai serveris išduoda sertifikatus klientams, tačiau iš esmės galima naudoti išorinę CA.

Įvadas į manifestus

Lėlių terminologija į lėlių serverį Prisijungti mazgai (mazgai). Parašyta mazgų konfigūracija manifestuose specialia programavimo kalba – Puppet DSL.

Lėlių DSL yra deklaratyvi kalba. Jis apibūdina norimą mazgo būseną atskirų išteklių deklaracijų forma, pavyzdžiui:

  • Failas egzistuoja ir turi konkretų turinį.
  • Paketas įdiegtas.
  • Paslauga prasidėjo.

Ištekliai gali būti susieti tarpusavyje:

  • Yra priklausomybių, jos turi įtakos išteklių naudojimo tvarkai.
    Pavyzdžiui, „pirmiausia įdiekite paketą, tada redaguokite konfigūracijos failą, tada paleiskite paslaugą“.
  • Yra pranešimai – pasikeitus ištekliui, jis siunčia pranešimus į jį prenumeruojamus išteklius.
    Pavyzdžiui, jei pasikeičia konfigūracijos failas, galite automatiškai paleisti paslaugą iš naujo.

Be to, lėlių DSL turi funkcijas ir kintamuosius, taip pat sąlyginius teiginius ir parinkiklius. Taip pat palaikomi įvairūs šablonų mechanizmai – EPP ir ERB.

Lėlė parašyta rubinų kalba, todėl daugelis konstrukcijų ir terminų paimti iš ten. „Ruby“ leidžia išplėsti „Puppet“ - pridėti sudėtingos logikos, naujų išteklių tipų, funkcijų.

Kai veikia „Puppet“, kiekvieno konkretaus serverio mazgo aprašai sukompiliuojami į katalogą. katalogas yra išteklių ir jų ryšių sąrašas, apskaičiavus funkcijų, kintamųjų reikšmę ir sąlyginių teiginių išplėtimą.

Sintaksė ir kodo stilius

Čia yra oficialios dokumentacijos skyriai, kurie padės suprasti sintaksę, jei pateiktų pavyzdžių nepakanka:

Štai pavyzdys, kaip atrodo manifestas:

# Комментарии пишутся, как и много где, после решётки.
#
# Описание конфигурации ноды начинается с ключевого слова node,
# за которым следует селектор ноды — хостнейм (с доменом или без)
# или регулярное выражение для хостнеймов, или ключевое слово default.
#
# После этого в фигурных скобках описывается собственно конфигурация ноды.
#
# Одна и та же нода может попасть под несколько селекторов. Про приоритет
# селекторов написано в статье про синтаксис описания нод.
node 'hostname', 'f.q.d.n', /regexp/ {
  # Конфигурация по сути является перечислением ресурсов и их параметров.
  #
  # У каждого ресурса есть тип и название.
  #
  # Внимание: не может быть двух ресурсов одного типа с одинаковыми названиями!
  #
  # Описание ресурса начинается с его типа. Тип пишется в нижнем регистре.
  # Про разные типы ресурсов написано ниже.
  #
  # После типа в фигурных скобках пишется название ресурса, потом двоеточие,
  # дальше идёт опциональное перечисление параметров ресурса и их значений.
  # Значения параметров указываются через т.н. hash rocket (=>).
  resource { 'title':
    param1 => value1,
    param2 => value2,
    param3 => value3,
  }
}

Įtrauka ir eilučių lūžiai nėra privaloma aprašo dalis, tačiau yra rekomenduojama stiliaus vadovas. Santrauka:

  • Dviejų tarpų įtraukos, skirtukai nenaudojami.
  • Garbanotos petnešos atskiriamos tarpeliu;
  • Kableliai po kiekvieno parametro, įskaitant paskutinį. Kiekvienas parametras yra atskiroje eilutėje. Išimtis daroma atvejams be parametrų ir vieno parametro: galima rašyti vienoje eilutėje ir be kablelio (t.y. resource { 'title': } и resource { 'title': param => value }).
  • Rodyklės ant parametrų turi būti tame pačiame lygyje.
  • Prieš juos parašytos išteklių santykių rodyklės.

Failų vieta pappetserveryje

Norėdami daugiau paaiškinti, pristatysiu „šakninio katalogo“ sąvoką. Šakninis katalogas yra katalogas, kuriame yra konkretaus mazgo lėlių konfigūracija.

Šakninis katalogas skiriasi priklausomai nuo Puppet versijos ir naudojamos aplinkos. Aplinkos yra nepriklausomi konfigūracijos rinkiniai, saugomi atskiruose kataloguose. Paprastai naudojamas kartu su git, tokiu atveju aplinkos kuriamos iš git šakų. Atitinkamai kiekvienas mazgas yra vienoje ar kitoje aplinkoje. Tai galima sukonfigūruoti pačiame mazge arba ENC, apie kurį kalbėsiu kitame straipsnyje.

  • Trečiojoje versijoje („senoji lėlė“) buvo bazinis katalogas /etc/puppet. Aplinkų naudojimas yra neprivalomas – pavyzdžiui, nenaudojame jų su senuoju Puppet. Jei naudojamos aplinkos, jos dažniausiai saugomos /etc/puppet/environments, šakninis katalogas bus aplinkos katalogas. Jei aplinkos nenaudojamos, pagrindinis katalogas bus šakninis katalogas.
  • Nuo ketvirtosios versijos („naujos lėlės“) aplinkų naudojimas tapo privalomas, o bazinis katalogas buvo perkeltas į /etc/puppetlabs/code. Atitinkamai, aplinkos saugomos /etc/puppetlabs/code/environments, šakninis katalogas yra aplinkos katalogas.

Šakniniame kataloge turi būti pakatalogis manifests, kuriame yra vienas ar daugiau manifestų, apibūdinančių mazgus. Be to, turėtų būti pakatalogis modules, kuriame yra moduliai. Aš jums pasakysiu, kokie moduliai yra šiek tiek vėliau. Be to, senoji lėlė taip pat gali turėti pakatalogį files, kuriame yra įvairių failų, kuriuos nukopijuojame į mazgus. Naujojoje lėlėje visi failai dedami į modulius.

Manifestų failai turi plėtinį .pp.

Pora kovos pavyzdžių

Mazgo aprašymas ir jame esantys ištekliai

Ant mazgo server1.testdomain turi būti sukurtas failas /etc/issue su turiniu Debian GNU/Linux n l. Failas turi priklausyti vartotojui ir grupei root, prieigos teisės turi būti 644.

Rašome manifestą:

node 'server1.testdomain' {   # блок конфигурации, относящийся к ноде server1.testdomain
    file { '/etc/issue':   # описываем файл /etc/issue
        ensure  => present,   # этот файл должен существовать
        content => 'Debian GNU/Linux n l',   # у него должно быть такое содержимое
        owner   => root,   # пользователь-владелец
        group   => root,   # группа-владелец
        mode    => '0644',   # права на файл. Они заданы в виде строки (в кавычках), потому что иначе число с 0 в начале будет воспринято как записанное в восьмеричной системе, и всё пойдёт не так, как задумано
    }
}

Ryšiai tarp mazgo išteklių

Ant mazgo server2.testdomain nginx turi veikti, dirbti su anksčiau paruošta konfigūracija.

Išskaidykime problemą:

  • Reikia įdiegti paketą nginx.
  • Būtina, kad konfigūracijos failai būtų nukopijuoti iš serverio.
  • Paslauga turi veikti nginx.
  • Jei konfigūracija atnaujinama, paslauga turi būti paleista iš naujo.

Rašome manifestą:

node 'server2.testdomain' {   # блок конфигурации, относящийся к ноде server2.testdomain
    package { 'nginx':   # описываем пакет nginx
        ensure => installed,   # он должен быть установлен
    }
  # Прямая стрелка (->) говорит о том, что ресурс ниже должен
  # создаваться после ресурса, описанного выше.
  # Такие зависимости транзитивны.
    -> file { '/etc/nginx':   # описываем файл /etc/nginx
        ensure  => directory,   # это должна быть директория
        source  => 'puppet:///modules/example/nginx-conf',   # её содержимое нужно брать с паппет-сервера по указанному адресу
        recurse => true,   # копировать файлы рекурсивно
        purge   => true,   # нужно удалять лишние файлы (те, которых нет в источнике)
        force   => true,   # удалять лишние директории
    }
  # Волнистая стрелка (~>) говорит о том, что ресурс ниже должен
  # подписаться на изменения ресурса, описанного выше.
  # Волнистая стрелка включает в себя прямую (->).
    ~> service { 'nginx':   # описываем сервис nginx
        ensure => running,   # он должен быть запущен
        enable => true,   # его нужно запускать автоматически при старте системы
    }
  # Когда ресурс типа service получает уведомление,
  # соответствующий сервис перезапускается.
}

Kad tai veiktų, jums reikia maždaug šios failo vietos lėlių serveryje:

/etc/puppetlabs/code/environments/production/ # (это для нового Паппета, для старого корневой директорией будет /etc/puppet)
├── manifests/
│   └── site.pp
└── modules/
    └── example/
        └── files/
            └── nginx-conf/
                ├── nginx.conf
                ├── mime.types
                └── conf.d/
                    └── some.conf

Išteklių tipai

Visą palaikomų išteklių tipų sąrašą galite rasti čia dokumentacijoje, čia aprašysiu penkis pagrindinius tipus, kurių mano praktikoje pakanka daugumai problemų išspręsti.

failas

Tvarko failus, katalogus, simbolius, jų turinį ir prieigos teises.

Pasirinkimai:

  • ištekliaus pavadinimas - kelias į failą (neprivaloma)
  • kelias - kelias į failą (jei jis nenurodytas pavadinime)
  • užtikrinti - Failo tipas:
    • absent - ištrinti failą
    • present — turi būti bet kokio tipo failas (jei failo nėra, bus sukurtas įprastas failas)
    • file - įprastas failas
    • directory - katalogas
    • link - simbolinė nuoroda
  • turinys — failo turinys (tinka tik įprastiems failams, negali būti naudojamas kartu su Šaltinis arba taikinys)
  • Šaltinis — nuoroda į kelią, iš kurio norite kopijuoti failo turinį (negalima naudoti kartu su turinys arba taikinys). Galima nurodyti kaip URI su schema puppet: (tada bus naudojami failai iš lėlių serverio), ir su schema http: (Tikiuosi, aišku, kas nutiks šiuo atveju), ir net su diagrama file: arba kaip absoliutus kelias be schemos (tada bus naudojamas failas iš vietinio FS mazge)
  • taikinys — kur turėtų būti nuoroda (negalima naudoti kartu su turinys arba Šaltinis)
  • savininkas — vartotojas, kuriam turėtų priklausyti failas
  • grupė — grupė, kuriai turėtų priklausyti byla
  • režimas - failo leidimai (kaip eilutė)
  • pasikartoti - įgalina rekursinį katalogų apdorojimą
  • išvalymas - leidžia ištrinti failus, kurie neaprašyti lėlių
  • stiprumas - įgalina ištrinti katalogus, kurie nėra aprašyti lėlėje

paketas

Įdiegia ir pašalina paketus. Gali tvarkyti pranešimus – iš naujo įdiegia paketą, jei nurodytas parametras reinstall_on_refresh.

Pasirinkimai:

  • ištekliaus pavadinimas - paketo pavadinimas (neprivaloma)
  • pavadinimas - paketo pavadinimas (jei nenurodytas pavadinime)
  • tiekėjas - naudoti paketų tvarkyklę
  • užtikrinti — pageidaujama pakuotės būsena:
    • present, installed - bet kokia įdiegta versija
    • latest - įdiegta naujausia versija
    • absent - ištrintas (apt-get remove)
    • purged - ištrintas kartu su konfigūracijos failais (apt-get purge)
    • held - paketo versija užrakinta (apt-mark hold)
    • любая другая строка — įdiegta nurodyta versija
  • reinstall_on_refresh - jei true, tada gavus pranešimą paketas bus įdiegtas iš naujo. Naudinga šaltiniu pagrįstiems platinimams, kai keičiant kūrimo parametrus gali prireikti atstatyti paketus. Numatytas false.

tarnyba

Tvarko paslaugas. Gali apdoroti pranešimus – iš naujo paleidžia paslaugą.

Pasirinkimai:

  • ištekliaus pavadinimas — tvarkoma paslauga (neprivaloma)
  • pavadinimas — paslauga, kurią reikia valdyti (jei nenurodyta pavadinime)
  • užtikrinti — pageidaujama paslaugos būsena:
    • running - paleistas
    • stopped - sustojo
  • leisti - kontroliuoja galimybę paleisti paslaugą:
    • true - įjungtas automatinis paleidimas (systemctl enable)
    • mask - užmaskuotas (systemctl mask)
    • false - automatinis paleidimas išjungtas (systemctl disable)
  • restartas - komanda iš naujo paleisti paslaugą
  • statusas - komanda, skirta patikrinti paslaugos būseną
  • paleisti iš naujo — nurodykite, ar paslaugos pradinis scenarijus palaiko paleidimą iš naujo. Jeigu false ir parametras nurodytas restartas — naudojama šio parametro reikšmė. Jeigu false ir parametras restartas nenurodyta - paslauga sustabdoma ir pradedama paleisti iš naujo (bet systemd naudoja komandą systemctl restart).
  • hasstatus — nurodyti, ar paslaugos pradinis scenarijus palaiko komandą status. Jei false, tada naudojama parametro reikšmė statusas. Numatytas true.

exec

Vykdo išorines komandas. Jei nenurodysite parametrų sukuria, tik jeigu, nebent arba gaiviai, komanda bus vykdoma kiekvieną kartą, kai bus paleista lėlė. Gali apdoroti pranešimus – vykdo komandą.

Pasirinkimai:

  • ištekliaus pavadinimas - vykdytina komanda (neprivaloma)
  • komanda - vykdoma komanda (jei ji nenurodyta pavadinime)
  • kelias - keliai, kuriuose reikia ieškoti vykdomojo failo
  • tik jeigu — jei šiame parametre nurodyta komanda užbaigiama nuliniu grąžinimo kodu, bus vykdoma pagrindinė komanda
  • nebent — jei šiame parametre nurodyta komanda užbaigiama nuliniu grąžinimo kodu, bus vykdoma pagrindinė komanda
  • sukuria — jei šiame parametre nurodyto failo nėra, bus vykdoma pagrindinė komanda
  • gaiviai - jei true, tada komanda bus paleista tik tada, kai šis vykdytojas gaus pranešimą iš kitų išteklių
  • cwd - katalogas, iš kurio paleisti komandą
  • vartotojas — vartotojas, iš kurio paleisti komandą
  • tiekėjas - kaip paleisti komandą:
    • posix — tiesiog sukuriamas antrinis procesas, būtinai nurodykite kelias
    • apvalkalas - komanda paleidžiama apvalkale /bin/sh, gali būti nenurodytas kelias, galite naudoti gaubtus, vamzdžius ir kitas apvalkalo funkcijas. Paprastai aptinkama automatiškai, jei yra kokių nors specialių simbolių (|, ;, &&, || ir tt).

cron

Valdo cronjobs.

Pasirinkimai:

  • ištekliaus pavadinimas - tik kažkoks identifikatorius
  • užtikrinti — Crownjob valstija:
    • present - sukurti, jei nėra
    • absent - ištrinti, jei yra
  • komanda - kokią komandą paleisti
  • aplinka - kurioje aplinkoje paleisti komandą (aplinkos kintamųjų sąrašas ir jų reikšmės per =)
  • vartotojas - iš kurio vartotojo paleisti komandą
  • minutė, valanda, darbo diena, mėnuo, mėnesio diena — kada paleisti cron. Jei kuris nors iš šių atributų nenurodytas, jo reikšmė crontab bus tokia *.

„Lėlių 6.0“ versijoje cron tarsi išimtas iš dėžutės lėlių serveryje, todėl bendrojoje svetainėje nėra jokios dokumentacijos. Bet jis yra dėžutėje lėlių agente, todėl nereikia jo montuoti atskirai. Galite pamatyti jo dokumentaciją penktosios „Lėlių“ versijos dokumentacijojeArba „GitHub“..

Apie išteklius apskritai

Išteklių unikalumo reikalavimai

Dažniausia klaida, su kuria susiduriame, yra Deklaracijos dublikatas. Ši klaida atsiranda, kai kataloge atsiranda du ar daugiau to paties tipo išteklių tuo pačiu pavadinimu.

Todėl vėl parašysiu: to paties mazgo aprašuose neturėtų būti to paties tipo išteklių su tuo pačiu pavadinimu!

Kartais reikia įdiegti paketus su tuo pačiu pavadinimu, bet su skirtingais paketų tvarkytuvais. Tokiu atveju turite naudoti parametrą nameNorėdami išvengti klaidų:

package { 'ruby-mysql':
  ensure   => installed,
  name     => 'mysql',
  provider => 'gem',
}
package { 'python-mysql':
  ensure   => installed,
  name     => 'mysql',
  provider => 'pip',
}

Kiti išteklių tipai turi panašias parinktis, padedančias išvengti dubliavimo – name у tarnyba, command у exec, ir taip toliau.

Metaparametrai

Kiekvienas išteklių tipas turi tam tikrus specialius parametrus, nepaisant jo pobūdžio.

Visas meta parametrų sąrašas lėlių dokumentacijoje.

Trumpas sąrašas:

  • reikalauti — šis parametras nurodo, nuo kurių išteklių šis išteklius priklauso.
  • prieš - Šis parametras nurodo, kurie ištekliai priklauso nuo šio šaltinio.
  • prenumeruoti — šis parametras nurodo, iš kokių išteklių šis šaltinis gauna pranešimus.
  • pranešti — Šis parametras nurodo, kurie ištekliai gauna pranešimus iš šio šaltinio.

Visi išvardyti metaparametrai priima arba vieną šaltinio nuorodą, arba nuorodų masyvą laužtiniuose skliaustuose.

Nuorodos į išteklius

Ištekliaus nuoroda yra tiesiog šaltinio paminėjimas. Jie daugiausia naudojami priklausomybėms nurodyti. Nuoroda į neegzistuojantį šaltinį sukels kompiliavimo klaidą.

Nuorodos sintaksė yra tokia: ištekliaus tipas su didžiosiomis raidėmis (jei tipo pavadinime yra dvigubi dvitaškiai, tada kiekviena pavadinimo dalis tarp dvitaškių rašoma didžiosiomis raidėmis), tada ištekliaus pavadinimas laužtiniuose skliaustuose (pavadinimo didžioji raidė nesikeičia!). Neturi būti tarpų; laužtiniai skliaustai rašomi iškart po tipo pavadinimo.

Pavyzdys:

file { '/file1': ensure => present }
file { '/file2':
  ensure => directory,
  before => File['/file1'],
}
file { '/file3': ensure => absent }
File['/file1'] -> File['/file3']

Priklausomybės ir pranešimai

Dokumentacija čia.

Kaip minėta anksčiau, paprastos priklausomybės tarp išteklių yra tranzityvinės. Beje, būkite atsargūs pridėdami priklausomybes – galite sukurti ciklines priklausomybes, kurios sukels kompiliavimo klaidą.

Skirtingai nuo priklausomybių, pranešimai nėra laikini. Pranešimams taikomos šios taisyklės:

  • Jei šaltinis gauna pranešimą, jis atnaujinamas. Atnaujinimo veiksmai priklauso nuo išteklių tipo − exec vykdo komandą, tarnyba iš naujo paleidžia paslaugą, paketas iš naujo įdiegia paketą. Jei ištekliui nenustatytas atnaujinimo veiksmas, nieko neįvyksta.
  • Vieno „Lėlių“ paleidimo metu išteklius atnaujinamas ne daugiau kaip vieną kartą. Tai įmanoma, nes pranešimuose yra priklausomybių, o priklausomybės diagramoje nėra ciklų.
  • Jei lėlė pakeičia ištekliaus būseną, išteklius siunčia pranešimus visiems jo prenumeruojamiems ištekliams.
  • Jei išteklius atnaujinamas, jis siunčia pranešimus visiems jo prenumeruojamiems ištekliams.

Nenurodytų parametrų tvarkymas

Paprastai, jei kuris nors ištekliaus parametras neturi numatytosios reikšmės ir šis parametras nenurodytas manifeste, tada „Lėlė“ nepakeis šios atitinkamo resurso mazgo ypatybės. Pavyzdžiui, jei tipo šaltinis failas parametras nenurodytas owner, tada Puppet nepakeis atitinkamo failo savininko.

Įvadas į klases, kintamuosius ir apibrėžimus

Tarkime, kad turime kelis mazgus, turinčius tą pačią konfigūracijos dalį, tačiau yra ir skirtumų – kitaip galėtume viską aprašyti viename bloke node {}. Žinoma, galima tiesiog nukopijuoti identiškas konfigūracijos dalis, bet apskritai tai yra blogas sprendimas – konfigūracija auga, o pakeitus bendrąją konfigūracijos dalį daug kur teks redaguoti tą patį. Tuo pačiu metu nesunku suklysti, o apskritai DRY (nekartok savęs) principas buvo sugalvotas ne be priežasties.

Norėdami išspręsti šią problemą, yra toks dizainas kaip klasė.

Klasės

Klasė yra pavadintas poppet kodo blokas. Klasės reikalingos norint pakartotinai naudoti kodą.

Pirmiausia reikia apibūdinti klasę. Pats aprašymas niekur neprideda jokių išteklių. Klasė aprašyta manifestuose:

# Описание класса начинается с ключевого слова class и его названия.
# Дальше идёт тело класса в фигурных скобках.
class example_class {
    ...
}

Po to klasė gali būti naudojama:

# первый вариант использования — в стиле ресурса с типом class
class { 'example_class': }
# второй вариант использования — с помощью функции include
include example_class
# про отличие этих двух вариантов будет рассказано дальше

Pavyzdys iš ankstesnės užduoties – perkelkime nginx diegimą ir konfigūraciją į klasę:

class nginx_example {
    package { 'nginx':
        ensure => installed,
    }
    -> file { '/etc/nginx':
        ensure => directory,
        source => 'puppet:///modules/example/nginx-conf',
        recure => true,
        purge  => true,
        force  => true,
    }
    ~> service { 'nginx':
        ensure => running,
        enable => true,
    }
}

node 'server2.testdomain' {
    include nginx_example
}

Kintamieji

Ankstesnio pavyzdžio klasė nėra lanksti, nes ji visada pateikia tą pačią nginx konfigūraciją. Padarykime kelią į konfigūracijos kintamąjį, tada ši klasė gali būti naudojama diegti nginx su bet kokia konfigūracija.

Tai galima padaryti naudojant kintamuosius.

Dėmesio: lėlių kintamieji yra nekintantys!

Be to, kintamąjį galima pasiekti tik jį paskelbus, kitaip kintamojo reikšmė bus tokia undef.

Darbo su kintamaisiais pavyzdys:

# создание переменных
$variable = 'value'
$var2 = 1
$var3 = true
$var4 = undef
# использование переменных
$var5 = $var6
file { '/tmp/text': content => $variable }
# интерполяция переменных — раскрытие значения переменных в строках. Работает только в двойных кавычках!
$var6 = "Variable with name variable has value ${variable}"

Lėlė turi vardų erdvės, o kintamieji atitinkamai turi matomumo sritis: kintamasis tuo pačiu pavadinimu gali būti apibrėžtas skirtingose ​​vardų srityse. Sprendžiant kintamojo reikšmę, kintamojo ieškoma dabartinėje vardų erdvėje, po to apgaubiančioje vardų erdvėje ir pan.

Vardų erdvės pavyzdžiai:

  • global - kintamieji, esantys už klasės ar mazgo aprašymo ribų, patenka ten;
  • mazgo vardų erdvė mazgo aprašyme;
  • klasės vardų erdvė klasės aprašyme.

Norėdami išvengti dviprasmybių, kai pasiekiate kintamąjį, kintamojo pavadinime galite nurodyti vardų erdvę:

# переменная без пространства имён
$var
# переменная в глобальном пространстве имён
$::var
# переменная в пространстве имён класса
$classname::var
$::classname::var

Sutikime, kad kelias į nginx konfigūraciją yra kintamajame $nginx_conf_source. Tada klasė atrodys taip:

class nginx_example {
    package { 'nginx':
        ensure => installed,
    }
    -> file { '/etc/nginx':
        ensure => directory,
        source => $nginx_conf_source,   # здесь используем переменную вместо фиксированной строки
        recure => true,
        purge  => true,
        force  => true,
    }
    ~> service { 'nginx':
        ensure => running,
        enable => true,
    }
}

node 'server2.testdomain' {
    $nginx_conf_source = 'puppet:///modules/example/nginx-conf'
    include nginx_example
}

Tačiau pateiktas pavyzdys yra blogas, nes yra tam tikras „slaptas žinojimas“, kad kažkur klasės viduje naudojamas kintamasis tokiu ir tokiu pavadinimu. Daug teisingiau šias žinias apibendrinti – klasės gali turėti parametrus.

Klasės parametrai yra kintamieji klasės vardų erdvėje, jie nurodomi klasės antraštėje ir gali būti naudojami kaip įprasti kintamieji klasės turinyje. Parametrų reikšmės nurodomos naudojant klasę manifeste.

Parametras gali būti nustatytas į numatytąją reikšmę. Jei parametras neturi numatytosios reikšmės, o reikšmė nenustatyta, kai naudojamasi, tai sukels kompiliavimo klaidą.

Parametruokime klasę pagal aukščiau pateiktą pavyzdį ir pridėkime du parametrus: pirmasis, būtinas, yra kelias į konfigūraciją, o antrasis, neprivalomas, yra paketo su nginx pavadinimas (pvz., Debian'e yra paketų nginx, nginx-light, nginx-full).

# переменные описываются сразу после имени класса в круглых скобках
class nginx_example (
  $conf_source,
  $package_name = 'nginx-light', # параметр со значением по умолчанию
) {
  package { $package_name:
    ensure => installed,
  }
  -> file { '/etc/nginx':
    ensure  => directory,
    source  => $conf_source,
    recurse => true,
    purge   => true,
    force   => true,
  }
  ~> service { 'nginx':
    ensure => running,
    enable => true,
  }
}

node 'server2.testdomain' {
  # если мы хотим задать параметры класса, функция include не подойдёт* — нужно использовать resource-style declaration
  # *на самом деле подойдёт, но про это расскажу в следующей серии. Ключевое слово "Hiera".
  class { 'nginx_example':
    conf_source => 'puppet:///modules/example/nginx-conf',   # задаём параметры класса точно так же, как параметры для других ресурсов
  }
}

Lėlių programoje kintamieji įvedami. Valgyk daug duomenų tipų. Duomenų tipai paprastai naudojami klasėms ir apibrėžimams perduotoms parametrų reikšmėms patvirtinti. Jei perduotas parametras neatitinka nurodyto tipo, įvyks kompiliavimo klaida.

Tipas rašomas prieš pat parametro pavadinimą:

class example (
  String $param1,
  Integer $param2,
  Array $param3,
  Hash $param4,
  Hash[String, String] $param5,
) {
  ...
}

Klasės: įtraukti klasės pavadinimą prieš klasę{'classname':}

Kiekviena klasė yra tam tikro tipo šaltinis klasė. Kaip ir bet kurio kito tipo išteklių atveju, tame pačiame mazge negali būti dviejų tos pačios klasės egzempliorių.

Jei bandysite pridėti klasę prie to paties mazgo du kartus naudodami class { 'classname':} (jokio skirtumo, su skirtingais arba vienodais parametrais), bus kompiliavimo klaida. Bet jei naudojate klasę išteklių stiliumi, galite iš karto aiškiai nustatyti visus jos parametrus manifeste.

Tačiau jei naudojate include, tada klasę galima pridėti tiek kartų, kiek norite. Faktas yra tas include yra idempotentinė funkcija, kuri tikrina, ar klasė buvo įtraukta į katalogą. Jei klasės nėra kataloge, ji ją prideda, o jei jau yra, nieko nedaro. Tačiau naudojimo atveju include Klasės deklaravimo metu negalite nustatyti klasės parametrų – visi reikalingi parametrai turi būti nustatyti išoriniame duomenų šaltinyje – Hiera arba ENC. Apie juos kalbėsime kitame straipsnyje.

Apibrėžia

Kaip buvo pasakyta ankstesniame bloke, ta pati klasė mazge negali būti daugiau nei vieną kartą. Tačiau kai kuriais atvejais tame pačiame mazge turite turėti galimybę naudoti tą patį kodo bloką su skirtingais parametrais. Kitaip tariant, reikia savo išteklių tipo.

Pavyzdžiui, norėdami įdiegti PHP modulį, „Avito“ atliekame šiuos veiksmus:

  1. Įdiekite paketą su šiuo moduliu.
  2. Sukurkime šio modulio konfigūracijos failą.
  3. Sukuriame simbolinę nuorodą į php-fpm konfigūraciją.
  4. Sukuriame simbolinę nuorodą į php cli konfigūraciją.

Tokiais atvejais toks dizainas kaip apibrėžti (apibrėžti, apibrėžtas tipas, apibrėžtas išteklių tipas). A Define yra panašus į klasę, tačiau yra skirtumų: pirma, kiekvienas Define yra ištekliaus tipas, o ne šaltinis; antra, kiekvienas apibrėžimas turi numanomą parametrą $title, kur nurodomas ištekliaus pavadinimas, kai jis deklaruojamas. Kaip ir klasių atveju, pirmiausia reikia aprašyti apibrėžimą, po kurio jį galima naudoti.

Supaprastintas pavyzdys su PHP moduliu:

define php74::module (
  $php_module_name = $title,
  $php_package_name = "php7.4-${title}",
  $version = 'installed',
  $priority = '20',
  $data = "extension=${title}.son",
  $php_module_path = '/etc/php/7.4/mods-available',
) {
  package { $php_package_name:
    ensure          => $version,
    install_options => ['-o', 'DPkg::NoTriggers=true'],  # триггеры дебиановских php-пакетов сами создают симлинки и перезапускают сервис php-fpm - нам это не нужно, так как и симлинками, и сервисом мы управляем с помощью Puppet
  }
  -> file { "${php_module_path}/${php_module_name}.ini":
    ensure  => $ensure,
    content => $data,
  }
  file { "/etc/php/7.4/cli/conf.d/${priority}-${php_module_name}.ini":
    ensure  => link,
    target  => "${php_module_path}/${php_module_name}.ini",
  }
  file { "/etc/php/7.4/fpm/conf.d/${priority}-${php_module_name}.ini":
    ensure  => link,
    target  => "${php_module_path}/${php_module_name}.ini",
  }
}

node server3.testdomain {
  php74::module { 'sqlite3': }
  php74::module { 'amqp': php_package_name => 'php-amqp' }
  php74::module { 'msgpack': priority => '10' }
}

Paprasčiausias būdas nustatyti pasikartojančios deklaracijos klaidą yra Nustatyti. Taip atsitinka, jei apibrėžime yra išteklius su pastoviu pavadinimu, o tam tikrame mazge yra du ar daugiau šio apibrėžimo atvejų.

Apsisaugoti nuo to lengva: visi apibrėžime esantys ištekliai turi turėti pavadinimą, priklausomai nuo to $title. Alternatyva yra idempotentas išteklių papildymas paprasčiausiu atveju, užtenka perkelti visiems apibrėžimo egzemplioriams bendrus išteklius į atskirą klasę ir įtraukti šią klasę į apibrėžimą - funkciją; include idempotentas.

Yra ir kitų būdų, kaip pasiekti idempotenciją pridedant išteklius, būtent naudojant funkcijas defined и ensure_resources, bet apie tai papasakosiu kitame epizode.

Klasių ir apibrėžimų priklausomybės ir pranešimai

Klasės ir apibrėžimai prideda šias priklausomybių ir pranešimų tvarkymo taisykles:

  • priklausomybė nuo klasės/define prideda priklausomybes nuo visų klasės/define išteklių;
  • klasė/apibrėžti priklausomybė prideda priklausomybes prie visų klasės/apibrėžti išteklių;
  • class/define pranešimas praneša apie visus klasės/define išteklius;
  • class/define prenumerata prenumeruoja visus class/define išteklius.

Sąlyginiai teiginiai ir selektoriai

Dokumentacija čia.

if

Čia viskas paprasta:

if ВЫРАЖЕНИЕ1 {
  ...
} elsif ВЫРАЖЕНИЕ2 {
  ...
} else {
  ...
}

nebent

nebent jei yra atvirkštinis: kodo blokas bus vykdomas, jei išraiška klaidinga.

unless ВЫРАЖЕНИЕ {
  ...
}

atvejis

Čia taip pat nėra nieko sudėtingo. Kaip reikšmes galite naudoti įprastas reikšmes (eilutes, skaičius ir kt.), reguliariąsias išraiškas ir duomenų tipus.

case ВЫРАЖЕНИЕ {
  ЗНАЧЕНИЕ1: { ... }
  ЗНАЧЕНИЕ2, ЗНАЧЕНИЕ3: { ... }
  default: { ... }
}

Selektoriai

selektorius yra kalbos konstrukcija, panaši į case, bet vietoj kodo bloko vykdymo grąžina reikšmę.

$var = $othervar ? { 'val1' => 1, 'val2' => 2, default => 3 }

Moduliai

Kai konfigūracija nedidelė, ją galima lengvai laikyti viename manifeste. Tačiau kuo daugiau konfigūracijų aprašome, tuo daugiau klasių ir mazgų yra manifeste, jis auga ir su juo dirbti tampa nepatogu.

Be to, iškyla kodo pakartotinio naudojimo problema – kai visas kodas yra viename manifeste, sunku pasidalinti šiuo kodu su kitais. Kad išspręstų šias dvi problemas, „Lėlė“ turi objektą, vadinamą moduliais.

Moduliai - tai klasių, apibrėžimų ir kitų lėlių objektų rinkiniai, patalpinti į atskirą katalogą. Kitaip tariant, modulis yra nepriklausoma lėlių logikos dalis. Pavyzdžiui, gali būti modulis, skirtas darbui su nginx, o jame bus tai, kas ir tik tai, ko reikia darbui su nginx, arba gali būti modulis darbui su PHP ir pan.

Moduliai yra versijuojami, taip pat palaikomos modulių priklausomybės vienas nuo kito. Yra atvira modulių saugykla - Lėlių kalvė.

Lėlių serveryje moduliai yra šakninio katalogo modulių pakatalogyje. Kiekvieno modulio viduje yra standartinė katalogų schema – manifestai, failai, šablonai, lib ir pan.

Failo struktūra modulyje

Modulio šaknyje gali būti šie katalogai su aprašomaisiais pavadinimais:

  • manifests – jame yra manifestai
  • files - jame yra failai
  • templates - jame yra šablonų
  • lib - jame yra Rubino kodas

Tai nėra visas katalogų ir failų sąrašas, tačiau kol kas to pakanka šiam straipsniui.

Modulio išteklių ir failų pavadinimai

Dokumentacija čia.

Ištekliai (klasės, apibrėžimai) modulyje negali būti pavadinti taip, kaip norite. Be to, yra tiesioginis ištekliaus pavadinimo ir failo, kuriame „Lėlė“ ieškos to ištekliaus aprašymo, pavadinimo. Jei pažeisite pavadinimo taisykles, „Lėlė“ tiesiog neras šaltinio aprašymo ir gausite kompiliavimo klaidą.

Taisyklės paprastos:

  • Visi modulio ištekliai turi būti modulio vardų erdvėje. Jei iškviečiamas modulis foo, tada visi jame esantys ištekliai turėtų būti pavadinti foo::<anything>, arba tiesiog foo.
  • Išteklius su modulio pavadinimu turi būti faile init.pp.
  • Kitų išteklių failų pavadinimų schema yra tokia:
    • priešdėlis su modulio pavadinimu atmetamas
    • visi dvigubi dvitaškiai, jei tokių yra, pakeičiami pasviraisiais brūkšniais
    • pridedamas plėtinys .pp

Parodysiu pavyzdžiu. Tarkime, aš rašau modulį nginx. Jame yra šie ištekliai:

  • klasė nginx aprašyta manifeste init.pp;
  • klasė nginx::service aprašyta manifeste service.pp;
  • apibrėžti nginx::server aprašyta manifeste server.pp;
  • apibrėžti nginx::server::location aprašyta manifeste server/location.pp.

šablonai

Žinoma, jūs patys žinote, kas yra šablonai, aš jų čia išsamiai neaprašysiu. Bet paliksiu bet kokiu atveju nuoroda į Vikipediją.

Kaip naudoti šablonus: šablono reikšmę galima išplėsti naudojant funkciją template, kuris perduodamas šablono keliui. Dėl tokių išteklių kaip failas naudojamas kartu su parametru content. Pavyzdžiui, taip:

file { '/tmp/example': content => template('modulename/templatename.erb')

Žiūrėti kelią <modulename>/<filename> reiškia failą <rootdir>/modules/<modulename>/templates/<filename>.

Be to, yra funkcija inline_template — kaip įvestį gauna šablono tekstą, o ne failo pavadinimą.

Šablonuose galite naudoti visus dabartinės apimties lėlių kintamuosius.

Puppet palaiko ERB ir EPP formatų šablonus:

Trumpai apie ERB

Valdymo struktūros:

  • <%= ВЫРАЖЕНИЕ %> — įterpti išraiškos reikšmę
  • <% ВЫРАЖЕНИЕ %> — apskaičiuoti išraiškos reikšmę (jos neįterpiant). Čia dažniausiai pateikiami sąlyginiai teiginiai (jei) ir kilpos (kiekvienas).
  • <%# КОММЕНТАРИЙ %>

Išraiškos ERB rašomos rubino kalba (ERB iš tikrųjų yra Embedded Ruby).

Norėdami pasiekti kintamuosius iš manifesto, turite pridėti @ į kintamojo pavadinimą. Norėdami pašalinti eilutės lūžį, atsirandantį po valdymo konstrukcijos, turite naudoti uždarymo žymą -%>.

Šablono naudojimo pavyzdys

Tarkime, aš rašau modulį, skirtą valdyti ZooKeeper. Už konfigūracijos kūrimą atsakinga klasė atrodo maždaug taip:

class zookeeper::configure (
  Array[String] $nodes,
  Integer $port_client,
  Integer $port_quorum,
  Integer $port_leader,
  Hash[String, Any] $properties,
  String $datadir,
) {
  file { '/etc/zookeeper/conf/zoo.cfg':
    ensure  => present,
    content => template('zookeeper/zoo.cfg.erb'),
  }
}

Ir atitinkamas šablonas zoo.cfg.erb - Taigi:

<% if @nodes.length > 0 -%>
<% @nodes.each do |node, id| -%>
server.<%= id %>=<%= node %>:<%= @port_leader %>:<%= @port_quorum %>;<%= @port_client %>
<% end -%>
<% end -%>

dataDir=<%= @datadir %>

<% @properties.each do |k, v| -%>
<%= k %>=<%= v %>
<% end -%>

Faktai ir integruoti kintamieji

Dažnai konkreti konfigūracijos dalis priklauso nuo to, kas šiuo metu vyksta mazge. Pavyzdžiui, priklausomai nuo to, kas yra Debian leidimas, reikia įdiegti vieną ar kitą paketo versiją. Visa tai galite stebėti rankiniu būdu, perrašydami manifestus, jei pasikeičia mazgai. Bet tai nėra rimtas požiūris, automatizavimas yra daug geresnis.

Norėdami gauti informacijos apie mazgus, lėlė turi mechanizmą, vadinamą faktais. duomenys - tai informacija apie mazgą, pasiekiama manifestuose įprastų kintamųjų pavidalu globalioje vardų erdvėje. Pavyzdžiui, pagrindinio kompiuterio pavadinimas, operacinės sistemos versija, procesoriaus architektūra, vartotojų sąrašas, tinklo sąsajų sąrašas ir jų adresai ir daug daugiau. Faktai pateikiami manifestuose ir šablonuose kaip įprasti kintamieji.

Darbo su faktais pavyzdys:

notify { "Running OS ${facts['os']['name']} version ${facts['os']['release']['full']}": }
# ресурс типа notify просто выводит сообщение в лог

Formaliai kalbant, faktas turi pavadinimą (eilą) ir reikšmę (galimi įvairūs tipai: eilutės, masyvai, žodynai). Valgyk integruotų faktų rinkinys. Taip pat galite parašyti savo. Aprašyti faktų rinkėjai kaip Ruby funkcijos, arba kaip vykdomuosius failus. Faktai taip pat gali būti pateikti formoje tekstinius failus su duomenimis ant mazgų.

Veikimo metu lėlių agentas pirmiausia nukopijuoja visus turimus faktų rinkėjus iš pappetserverio į mazgą, po to juos paleidžia ir surinktus faktus siunčia į serverį; Po to serveris pradeda kompiliuoti katalogą.

Faktai vykdomųjų failų pavidalu

Tokie faktai dedami į katalogo modulius facts.d. Žinoma, failai turi būti vykdomi. Kai jie vykdomi, jie turi išvesti informaciją į standartinę išvestį YAML arba rakto = vertės formatu.

Nepamirškite, kad faktai taikomi visiems mazgams, kuriuos valdo poppet serveris, kuriame yra įdiegtas jūsų modulis. Todėl scenarijuje patikrinkite, ar sistema turi visas programas ir failus, reikalingus jūsų faktui veikti.

#!/bin/sh
echo "testfact=success"
#!/bin/sh
echo '{"testyamlfact":"success"}'

Rubino faktai

Tokie faktai dedami į katalogo modulius lib/facter.

# всё начинается с вызова функции Facter.add с именем факта и блоком кода
Facter.add('ladvd') do
# в блоках confine описываются условия применимости факта — код внутри блока должен вернуть true, иначе значение факта не вычисляется и не возвращается
  confine do
    Facter::Core::Execution.which('ladvdc') # проверим, что в PATH есть такой исполняемый файл
  end
  confine do
    File.socket?('/var/run/ladvd.sock') # проверим, что есть такой UNIX-domain socket
  end
# в блоке setcode происходит собственно вычисление значения факта
  setcode do
    hash = {}
    if (out = Facter::Core::Execution.execute('ladvdc -b'))
      out.split.each do |l|
        line = l.split('=')
        next if line.length != 2
        name, value = line
        hash[name.strip.downcase.tr(' ', '_')] = value.strip.chomp(''').reverse.chomp(''').reverse
      end
    end
    hash  # значение последнего выражения в блоке setcode является значением факта
  end
end

Teksto faktai

Tokie faktai pateikiami katalogo mazguose /etc/facter/facts.d senajame Lėlė arba /etc/puppetlabs/facts.d naujojoje Lėlėje.

examplefact=examplevalue
---
examplefact2: examplevalue2
anotherfact: anothervalue

Priėjimas prie faktų

Yra du būdai, kaip priartėti prie faktų:

  • per žodyną $facts: $facts['fqdn'];
  • naudojant fakto pavadinimą kaip kintamojo pavadinimą: $fqdn.

Geriausia naudoti žodyną $facts, arba dar geriau, nurodykite pasaulinę vardų erdvę ($::facts).

Čia yra atitinkama dokumentacijos dalis.

Integruoti kintamieji

Be faktų, taip pat yra kai kurie kintamieji, pasiekiama pasaulinėje vardų erdvėje.

  • patikimi faktai — kintamieji, paimti iš kliento sertifikato (kadangi sertifikatas paprastai išduodamas poppet serveryje, agentas negali tiesiog paimti ir pakeisti savo sertifikato, todėl kintamieji yra „patikimi“): sertifikato pavadinimas, sertifikato pavadinimas. priegloba ir domenas, plėtiniai iš sertifikato.
  • serverio faktai – kintamieji, susiję su informacija apie serverį – versija, pavadinimas, serverio IP adresas, aplinka.
  • agento faktai — kintamieji, kuriuos tiesiogiai pridėjo lėlių agentas, o ne faktorius — sertifikato pavadinimas, agento versija, lėlių versija.
  • pagrindiniai kintamieji - Pappetmaster kintamieji (sic!). Tai maždaug toks pat kaip ir serverio faktai, taip pat yra konfigūracijos parametrų vertės.
  • kompiliatoriaus kintamieji — kompiliatoriaus kintamieji, kurie skiriasi kiekvienoje srityje: dabartinio modulio pavadinimas ir modulio, kuriame buvo pasiektas dabartinis objektas, pavadinimas. Jie gali būti naudojami, pavyzdžiui, norint patikrinti, ar jūsų privačios klasės nėra naudojamos tiesiogiai iš kitų modulių.

1 papildymas: kaip visa tai paleisti ir derinti?

Straipsnyje buvo daug lėlių kodo pavyzdžių, tačiau visiškai nepasakyta, kaip paleisti šį kodą. Na, taisau save.

Puppet paleisti pakanka agento, tačiau daugeliu atvejų taip pat reikės serverio.

Agentas

Bent jau nuo 5 versijos, marionet-agent paketai iš oficiali Puppetlabs saugykla yra visos priklausomybės (rubinas ir atitinkami brangakmeniai), todėl nėra jokių diegimo sunkumų (kalbu apie Debian pagrindu sukurtus paskirstymus - mes nenaudojame RPM pagrįstų paskirstymų).

Paprasčiausiu atveju, norint naudoti lėlių konfigūraciją, pakanka paleisti agentą be serverio režimu: jei lėlės kodas nukopijuotas į mazgą, paleiskite puppet apply <путь к манифесту>:

atikhonov@atikhonov ~/puppet-test $ cat helloworld.pp 
node default {
    notify { 'Hello world!': }
}
atikhonov@atikhonov ~/puppet-test $ puppet apply helloworld.pp 
Notice: Compiled catalog for atikhonov.localdomain in environment production in 0.01 seconds
Notice: Hello world!
Notice: /Stage[main]/Main/Node[default]/Notify[Hello world!]/message: defined 'message' as 'Hello world!'
Notice: Applied catalog in 0.01 seconds

Žinoma, geriau nustatyti serverį ir paleisti agentus mazguose demono režimu - tada kartą per pusvalandį jie taikys iš serverio atsisiųstą konfigūraciją.

Galite imituoti „push“ darbo modelį – eikite į jus dominantį mazgą ir pradėkite sudo puppet agent -t. Raktas -t (--test) iš tikrųjų apima kelias parinktis, kurias galima įjungti atskirai. Šios parinktys apima:

  • nevykdyti demono režimu (pagal numatytuosius nustatymus agentas paleidžiamas demono režimu);
  • išjungti pritaikius katalogą (pagal numatytuosius nustatymus agentas toliau dirbs ir taikys konfigūraciją kartą per pusvalandį);
  • parašyti išsamų darbų žurnalą;
  • rodyti pakeitimus failuose.

Agentas turi darbo režimą be pakeitimų – juo galite naudotis, kai nesate tikri, kad parašėte teisingą konfigūraciją ir norite patikrinti, ką tiksliai agentas pakeis veikimo metu. Šis režimas įjungiamas pagal parametrą --noop komandinėje eilutėje: sudo puppet agent -t --noop.

Be to, galite įjungti darbo derinimo žurnalą – jame lėlė rašo apie visus savo atliekamus veiksmus: apie šiuo metu apdorojamą resursą, apie šio resurso parametrus, kokias programas paleidžia. Žinoma, tai yra parametras --debug.

Serveris

Šiame straipsnyje nenagrinėsiu visos pappetserverio sąrankos ir kodo įdiegimo, pasakysiu tik tiek, kad yra pilnai veikianti serverio versija, kuriai nereikia papildomos konfigūracijos, kad būtų galima dirbti su nedideliu skaičiumi; mazgų (tarkim, iki šimto). Didesniam mazgų skaičiui reikės derinti - pagal numatytuosius nustatymus lėlių serveris paleidžia ne daugiau kaip keturis darbuotojus, norėdami didesnio našumo turite padidinti jų skaičių ir nepamirškite padidinti atminties limitų, kitaip serveris didžiąją laiko dalį rinks šiukšles.

Kodo diegimas – jei jums jo reikia greitai ir lengvai, pažiūrėkite (r10k)[https://github.com/puppetlabs/r10k], mažiems įrenginiams to turėtų visiškai pakakti.

2 priedas: kodavimo gairės

  1. Sudėkite visą logiką į klases ir apibrėžimus.
  2. Klases ir apibrėžimus laikykite moduliuose, o ne mazgus aprašančiuose manifestuose.
  3. Pasinaudokite faktais.
  4. Nekurkite jei pagal pagrindinio kompiuterio pavadinimus.
  5. Nedvejodami pridėkite parametrų klasėms ir apibrėžimams – tai geriau nei numanoma logika, paslėpta klasės / apibrėžties turinyje.

Kitame straipsnyje paaiškinsiu, kodėl rekomenduoju tai padaryti.

išvada

Baigkime įžanga. Kitame straipsnyje papasakosiu apie Hiera, ENC ir PuppetDB.

Apklausoje gali dalyvauti tik registruoti vartotojai. Prisijungti, Prašau.

Tiesą sakant, medžiagos yra daug daugiau – galiu rašyti straipsnius šiomis temomis, balsuoti už tai, apie ką būtų įdomu paskaityti:

  • 59,1%Išplėstinės lėlių konstrukcijos – kai kurie naujo lygio šūdai: kilpos, atvaizdavimas ir kitos lambda išraiškos, išteklių rinkėjai, eksportuoti ištekliai ir lėlių ryšys tarp kompiuterių, žymos, teikėjai, abstrakčių duomenų tipai.13
  • 31,8%„I'm my mamos admin“ arba kaip mes „Avito“ susidraugavome su keliais skirtingų versijų poppet serveriais, ir iš esmės dalis apie poppet serverio administravimą.7
  • 81,8%Kaip rašome lėlių kodą: prietaisai, dokumentacija, testavimas, CI/CD.18

Balsavo 22 vartotojai. 9 vartotojų susilaikė.

Šaltinis: www.habr.com