Hyrje në Kukull

Puppet është një sistem i menaxhimit të konfigurimit. Përdoret për të sjellë hostet në gjendjen e dëshiruar dhe për të ruajtur këtë gjendje.

Unë kam punuar me Puppet për më shumë se pesë vjet. Ky tekst është në thelb një përmbledhje e përkthyer dhe e rirenditur e pikave kryesore nga dokumentacioni zyrtar, i cili do t'i lejojë fillestarët të kuptojnë shpejt thelbin e Kukullës.

Hyrje në Kukull

Informata themelore

Sistemi operativ i Puppet është klient-server, megjithëse ai gjithashtu mbështet funksionimin pa server me funksionalitet të kufizuar.

Përdoret një model tërheqjeje: si parazgjedhje, një herë në gjysmë ore, klientët kontaktojnë serverin për një konfigurim dhe e aplikojnë atë. Nëse keni punuar me Ansible, atëherë ata përdorin një model tjetër shtytjeje: administratori fillon procesin e aplikimit të konfigurimit, vetë klientët nuk do të aplikojnë asgjë.

Gjatë komunikimit në rrjet, përdoret enkriptimi i dyanshëm TLS: serveri dhe klienti kanë çelësat e tyre privatë dhe certifikatat përkatëse. Zakonisht serveri lëshon certifikata për klientët, por në parim është e mundur të përdoret një CA e jashtme.

Hyrje në manifeste

Në terminologjinë e kukullave te serveri i kukullave lidh nyjet (nyjet). Është shkruar konfigurimi për nyjet në manifeste në një gjuhë të veçantë programimi - Puppet DSL.

Puppet DSL është një gjuhë deklarative. Ai përshkruan gjendjen e dëshiruar të nyjes në formën e deklaratave të burimeve individuale, për shembull:

  • Skedari ekziston dhe ka përmbajtje specifike.
  • Paketa është e instaluar.
  • Shërbimi ka filluar.

Burimet mund të ndërlidhen:

  • Ka varësi, ato ndikojnë në rendin në të cilin përdoren burimet.
    Për shembull, "së pari instaloni paketën, më pas modifikoni skedarin e konfigurimit dhe më pas filloni shërbimin".
  • Ka njoftime - nëse një burim ka ndryshuar, ai dërgon njoftime te burimet e abonuara në të.
    Për shembull, nëse skedari i konfigurimit ndryshon, mund ta rinisni automatikisht shërbimin.

Përveç kësaj, Puppet DSL ka funksione dhe variabla, si dhe deklarata të kushtëzuara dhe përzgjedhës. Mbështeten gjithashtu mekanizma të ndryshëm modelimi - EPP dhe ERB.

Kukulla është shkruar në Ruby, kështu që shumë nga konstruktet dhe termat janë marrë nga atje. Ruby ju lejon të zgjeroni Puppet - shtoni logjikë komplekse, lloje të reja burimesh, funksione.

Ndërsa Puppet po funksionon, manifestet për secilën nyje specifike në server përpilohen në një direktori. Drejtoria është një listë e burimeve dhe marrëdhënieve të tyre pas llogaritjes së vlerës së funksioneve, variablave dhe zgjerimit të deklaratave të kushtëzuara.

Sintaksa dhe stili i kodit

Këtu janë pjesët e dokumentacionit zyrtar që do t'ju ndihmojnë të kuptoni sintaksën nëse shembujt e dhënë nuk janë të mjaftueshëm:

Ja një shembull se si duket manifesti:

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

Dhëmbja dhe ndërprerjet e rreshtave nuk janë pjesë e detyrueshme e manifestit, por ka një rekomandim stil udhëzues. Përmbledhje:

  • Indencat me dy hapësira, skedat nuk përdoren.
  • Kllapat kaçurrelë ndahen nga një hapësirë; dy pikat nuk ndahen nga një hapësirë.
  • Presja pas secilit parametër, duke përfshirë edhe atë të fundit. Çdo parametër është në një linjë të veçantë. Bëhet përjashtim për rastin pa parametra dhe një parametër: mund të shkruani në një rresht dhe pa presje (d.m.th. resource { 'title': } и resource { 'title': param => value }).
  • Shigjetat në parametra duhet të jenë në të njëjtin nivel.
  • Para tyre shkruhen shigjetat e marrëdhënieve të burimeve.

Vendndodhja e skedarëve në pappetserver

Për shpjegime të mëtejshme, unë do të prezantoj konceptin e "drejtorisë rrënjësore". Drejtoria rrënjësore është drejtoria që përmban konfigurimin e Puppet për një nyje specifike.

Drejtoria rrënjësore ndryshon në varësi të versionit të Puppet dhe mjediseve të përdorura. Mjediset janë grupe të pavarura konfigurimi që ruhen në drejtori të veçanta. Zakonisht përdoret në kombinim me git, me ç'rast mjediset krijohen nga degët git. Prandaj, çdo nyje ndodhet në një mjedis ose në një tjetër. Kjo mund të konfigurohet në vetë nyjen, ose në ENC, për të cilën do të flas në artikullin vijues.

  • Në versionin e tretë ("kukulla e vjetër") drejtoria bazë ishte /etc/puppet. Përdorimi i mjediseve është opsional - për shembull, ne nuk i përdorim ato me Kukullën e vjetër. Nëse përdoren mjedise, ato zakonisht ruhen në /etc/puppet/environments, direktoria rrënjësore do të jetë drejtoria e mjedisit. Nëse mjediset nuk përdoren, direktoria rrënjësore do të jetë direktoria bazë.
  • Duke filluar nga versioni i katërt ("Kukulla e re"), përdorimi i mjediseve u bë i detyrueshëm dhe drejtoria bazë u zhvendos në /etc/puppetlabs/code. Prandaj, mjediset ruhen në /etc/puppetlabs/code/environments, direktoria rrënjësore është drejtoria e mjedisit.

Duhet të ketë një nëndrejtori në direktorinë rrënjë manifests, i cili përmban një ose më shumë manifeste që përshkruajnë nyjet. Përveç kësaj, duhet të ketë një nëndrejtori modules, i cili përmban modulet. Unë do t'ju tregoj se cilat module janë pak më vonë. Përveç kësaj, Kukulla e vjetër mund të ketë gjithashtu një nëndrejtori files, i cili përmban skedarë të ndryshëm që i kopjojmë në nyje. Në Puppet-in e ri, të gjithë skedarët vendosen në module.

Skedarët e manifestit kanë shtesën .pp.

Disa shembuj luftarakë

Përshkrimi i nyjës dhe burimit në të

Në nyjë server1.testdomain duhet të krijohet një skedar /etc/issue me përmbajtje Debian GNU/Linux n l. Skedari duhet të jetë në pronësi të një përdoruesi dhe grupi root, të drejtat e aksesit duhet të jenë 644.

Ne shkruajmë një 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 в начале будет воспринято как записанное в восьмеричной системе, и всё пойдёт не так, как задумано
    }
}

Marrëdhëniet midis burimeve në një nyje

Në nyjë server2.testdomain nginx duhet të funksionojë, duke punuar me një konfigurim të përgatitur më parë.

Le ta zbërthejmë problemin:

  • Paketa duhet të instalohet nginx.
  • Është e nevojshme që skedarët e konfigurimit të kopjohen nga serveri.
  • Shërbimi duhet të funksionojë nginx.
  • Nëse konfigurimi është përditësuar, shërbimi duhet të riniset.

Ne shkruajmë një 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 получает уведомление,
  # соответствующий сервис перезапускается.
}

Që kjo të funksionojë, ju duhet afërsisht vendndodhjen e mëposhtme të skedarit në serverin e kukullave:

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

Llojet e burimeve

Një listë e plotë e llojeve të burimeve të mbështetura mund të gjendet këtu në dokumentacion, këtu do të përshkruaj pesë lloje themelore, të cilat në praktikën time janë të mjaftueshme për të zgjidhur shumicën e problemeve.

skedar

Menaxhon skedarët, drejtoritë, lidhjet simbolike, përmbajtjen e tyre dhe të drejtat e aksesit.

Mundësitë e zgjedhjes:

  • emri i burimit - rruga për në skedar (opsionale)
  • rrugë - rruga për në skedar (nëse nuk është e specifikuar në emër)
  • siguroj - lloji i skedarit:
    • absent - fshini një skedar
    • present - duhet të ketë një skedar të çdo lloji (nëse nuk ka skedar, do të krijohet një skedar i rregullt)
    • file - skedar i rregullt
    • directory - drejtoria
    • link - lidhje simbolike
  • përmbajtje — përmbajtja e skedarit (e përshtatshme vetëm për skedarë të rregullt, nuk mund të përdoret së bashku me burim ose objektiv)
  • burim — një lidhje në rrugën nga e cila dëshironi të kopjoni përmbajtjen e skedarit (nuk mund të përdoret së bashku me përmbajtje ose objektiv). Mund të specifikohet ose si një URI me një skemë puppet: (më pas do të përdoren skedarët nga serveri i kukullave), dhe me skemën http: (Shpresoj se është e qartë se çfarë do të ndodhë në këtë rast), madje edhe me diagramin file: ose si një shteg absolut pa një skemë (atëherë do të përdoret skedari nga FS lokale në nyje)
  • objektiv - ku duhet të tregojë lidhja simbolike (nuk mund të përdoret së bashku me përmbajtje ose burim)
  • pronar — përdoruesi që duhet të zotërojë skedarin
  • grup — grupi të cilit duhet t'i përkasë skedari
  • mënyrë — lejet e skedarit (si varg)
  • rikuperoj - mundëson përpunimin rekurziv të direktoriumit
  • spastrim - mundëson fshirjen e skedarëve që nuk janë përshkruar në Puppet
  • detyrojë - mundëson fshirjen e drejtorive që nuk janë përshkruar në Puppet

paketë

Instalon dhe heq paketat. Në gjendje të trajtojë njoftimet - riinstalon paketën nëse specifikohet parametri reinstall_on_refresh.

Mundësitë e zgjedhjes:

  • emri i burimit — emri i paketës (opsionale)
  • emër — emri i paketës (nëse nuk specifikohet në emër)
  • Provider — Menaxheri i paketave për t'u përdorur
  • siguroj — Gjendja e dëshiruar e paketës:
    • present, installed - çdo version i instaluar
    • latest - versioni i fundit i instaluar
    • absent - u fshi (apt-get remove)
    • purged - fshihet së bashku me skedarët e konfigurimit (apt-get purge)
    • held - versioni i paketës është i kyçur (apt-mark hold)
    • любая другая строка — është instaluar versioni i specifikuar
  • reinstall_on_refresh - nese nje true, më pas me marrjen e njoftimit paketa do të riinstalohet. I dobishëm për shpërndarjet e bazuara në burim, ku rindërtimi i paketave mund të jetë i nevojshëm kur ndryshoni parametrat e ndërtimit. E paracaktuar false.

shërbim

Menaxhon shërbimet. Mund të përpunojë njoftime - rinis shërbimin.

Mundësitë e zgjedhjes:

  • emri i burimit — shërbimi që do të menaxhohet (opsionale)
  • emër — shërbimi që duhet të menaxhohet (nëse nuk specifikohet në emër)
  • siguroj — gjendja e dëshiruar e shërbimit:
    • running - nisur
    • stopped - ndaloi
  • mundësoj — kontrollon aftësinë për të nisur shërbimin:
    • true - autorun është aktivizuar (systemctl enable)
    • mask - i maskuar (systemctl mask)
    • false - autorun është i çaktivizuar (systemctl disable)
  • restart - komanda për të rifilluar shërbimin
  • status — komandë për të kontrolluar statusin e shërbimit
  • ka rifilluar — tregoni nëse initscripti i shërbimit mbështet rinisjen. Nëse false dhe specifikohet parametri restart — përdoret vlera e këtij parametri. Nëse false dhe parametri restart nuk është specifikuar - shërbimi është ndalur dhe ka filluar të rifillojë (por systemd përdor komandën systemctl restart).
  • ka status — tregoni nëse initscripti i shërbimit e mbështet komandën status. nëse false, atëherë përdoret vlera e parametrit status. E paracaktuar true.

Exec

Ekzekuton komandat e jashtme. Nëse nuk specifikoni parametrat krijon, vetëm nëse, veç ose rifreskohet, komanda do të ekzekutohet sa herë që ekzekutohet Puppet. Në gjendje të përpunojë njoftimet - ekzekuton një komandë.

Mundësitë e zgjedhjes:

  • emri i burimit - komanda që do të ekzekutohet (opsionale)
  • komandë - komanda që do të ekzekutohet (nëse nuk është e specifikuar në emër)
  • rrugë — shtigjet në të cilat kërkohet skedari i ekzekutueshëm
  • vetëm nëse - nëse komanda e specifikuar në këtë parametër plotësohet me një kod kthimi zero, komanda kryesore do të ekzekutohet
  • veç — nëse komanda e specifikuar në këtë parametër plotësohet me një kod kthimi jo zero, komanda kryesore do të ekzekutohet
  • krijon — nëse skedari i specifikuar në këtë parametër nuk ekziston, komanda kryesore do të ekzekutohet
  • rifreskohet - nese nje true, atëherë komanda do të ekzekutohet vetëm kur ky ekzekutiv të marrë njoftim nga burime të tjera
  • cwd - drejtoria nga e cila do të ekzekutohet komanda
  • përdorues — përdoruesi nga i cili do të ekzekutohet komanda
  • Provider - si të ekzekutoni komandën:
    • POSIX — thjesht krijohet një proces fëmijësh, sigurohuni që të specifikoni rrugë
    • predhë - komanda niset në guaskë /bin/sh, mund të mos specifikohet rrugë, mund të përdorni globbing, tuba dhe veçori të tjera të guaskës. Zakonisht zbulohet automatikisht nëse ka ndonjë karakter të veçantë (|, ;, &&, || etj).

cron

Kontrollon cronjobs.

Mundësitë e zgjedhjes:

  • emri i burimit - vetëm një lloj identifikuesi
  • siguroj - shteti i kurorës:
    • present - krijoni nëse nuk ekziston
    • absent - fshini nëse ekziston
  • komandë - çfarë komande për të drejtuar
  • mjedis — në cilin mjedis të ekzekutohet komanda (lista e variablave të mjedisit dhe vlerat e tyre nëpërmjet =)
  • përdorues — nga cili përdorues duhet të ekzekutohet komanda
  • minutë, orë, dita e javes, muaj, ditë mujore - kur të kandidojë cron. Nëse ndonjë prej këtyre atributeve nuk specifikohet, vlera e tij në krontab do të jetë *.

Në Puppet 6.0 cron sikur hequr nga kutia në puppetserver, kështu që nuk ka asnjë dokumentacion në faqen e përgjithshme. Por ai është në kuti në kukull-agjent, kështu që nuk ka nevojë ta instaloni veçmas. Ju mund të shihni dokumentacionin për të në dokumentacionin për versionin e pestë të PuppetOse në GitHub.

Rreth burimeve në përgjithësi

Kërkesat për veçantinë e burimit

Gabimi më i zakonshëm që hasim është Deklaratë dublikatë. Ky gabim ndodh kur dy ose më shumë burime të të njëjtit lloj me të njëjtin emër shfaqen në drejtori.

Prandaj, do të shkruaj përsëri: manifestet për të njëjtën nyje nuk duhet të përmbajnë burime të të njëjtit lloj me të njëjtin titull!

Ndonjëherë ka nevojë për të instaluar paketa me të njëjtin emër, por me menaxherë të ndryshëm paketash. Në këtë rast, duhet të përdorni parametrin namepër të shmangur gabimin:

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

Llojet e tjera të burimeve kanë opsione të ngjashme për të ndihmuar në shmangien e dyfishimit - name у shërbim, command у Exec, dhe kështu me radhë.

Metaparametrat

Çdo lloj burimi ka disa parametra të veçantë, pavarësisht nga natyra e tij.

Lista e plotë e meta parametrave në dokumentacionin e Kukullave.

Lista e shkurtër:

  • kërkojnë — ky parametër tregon se nga cilat burime varet ky burim.
  • para - Ky parametër specifikon se cilat burime varen nga ky burim.
  • pajtohem — ky parametër specifikon se nga cilat burime merr njoftime ky burim.
  • njoftoj — Ky parametër specifikon se cilat burime marrin njoftime nga ky burim.

Të gjithë metaparametrat e listuar pranojnë ose një lidhje të vetme burimi ose një grup lidhjesh në kllapa katrore.

Lidhje me burimet

Një lidhje burimi është thjesht një përmendje e burimit. Ato përdoren kryesisht për të treguar varësitë. Referencimi i një burimi që nuk ekziston do të shkaktojë një gabim përpilimi.

Sintaksa e lidhjes është si më poshtë: lloji i burimit me shkronjë të madhe (nëse emri i tipit përmban dy pika, atëherë secila pjesë e emrit midis dy pikave shkruhen me shkronjë të madhe), pastaj emri i burimit në kllapa katrore (rasti i emrit nuk ndryshon!). Nuk duhet të ketë hapësira; kllapat katrore shkruhen menjëherë pas emrit të tipit.

Shembull:

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

Varësitë dhe njoftimet

Dokumentacioni këtu.

Siç u tha më herët, varësitë e thjeshta ndërmjet burimeve janë kalimtare. Nga rruga, kini kujdes kur shtoni varësi - mund të krijoni varësi ciklike, të cilat do të shkaktojnë një gabim përpilimi.

Ndryshe nga varësitë, njoftimet nuk janë kalimtare. Rregullat e mëposhtme zbatohen për njoftimet:

  • Nëse burimi merr një njoftim, ai përditësohet. Veprimet e përditësimit varen nga lloji i burimit − Exec ekzekuton komandën, shërbim rinis shërbimin, paketë riinstalon paketën. Nëse burimi nuk ka një veprim përditësues të përcaktuar, atëherë asgjë nuk ndodh.
  • Gjatë një ekzekutimi të Puppet, burimi përditësohet jo më shumë se një herë. Kjo është e mundur sepse njoftimet përfshijnë varësi dhe grafiku i varësisë nuk përmban cikle.
  • Nëse Puppet ndryshon gjendjen e një burimi, burimi dërgon njoftime për të gjitha burimet e abonuara në të.
  • Nëse një burim përditësohet, ai dërgon njoftime për të gjitha burimet e abonuara në të.

Trajtimi i parametrave të paspecifikuar

Si rregull, nëse disa parametër burimi nuk kanë një vlerë të paracaktuar dhe ky parametër nuk specifikohet në manifest, atëherë Puppet nuk do ta ndryshojë këtë veti për burimin përkatës në nyje. Për shembull, nëse një burim i llojit skedar parametri nuk është specifikuar owner, atëherë Puppet nuk do të ndryshojë pronarin e skedarit përkatës.

Hyrje në klasa, variabla dhe përkufizime

Supozoni se kemi disa nyje që kanë të njëjtën pjesë të konfigurimit, por ka edhe dallime - përndryshe ne mund t'i përshkruanim të gjitha në një bllok node {}. Sigurisht, thjesht mund të kopjoni pjesë identike të konfigurimit, por në përgjithësi kjo është një zgjidhje e keqe - konfigurimi rritet, dhe nëse ndryshoni pjesën e përgjithshme të konfigurimit, do të duhet të redaktoni të njëjtën gjë në shumë vende. Në të njëjtën kohë, është e lehtë të bësh një gabim, dhe në përgjithësi, parimi DRY (mos e përsëris veten) u shpik për një arsye.

Për të zgjidhur këtë problem ekziston një dizajn i tillë si klasë.

klasat

Klasë është një bllok i emërtuar i kodit poppet. Klasat janë të nevojshme për të ripërdorur kodin.

Së pari, klasa duhet të përshkruhet. Vetë përshkrimi nuk shton asnjë burim askund. Klasa përshkruhet në manifeste:

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

Pas kësaj, klasa mund të përdoret:

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

Një shembull nga detyra e mëparshme - le të zhvendosim instalimin dhe konfigurimin e nginx në një 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
}

variabla

Klasa nga shembulli i mëparshëm nuk është aspak fleksibël sepse sjell gjithmonë të njëjtin konfigurim nginx. Le të bëjmë shtegun për në ndryshoren e konfigurimit, atëherë kjo klasë mund të përdoret për të instaluar nginx me çdo konfigurim.

Mund të bëhet duke përdorur variabla.

Kujdes: variablat në Puppet janë të pandryshueshme!

Përveç kësaj, një ndryshore mund të aksesohet vetëm pasi të jetë deklaruar, përndryshe vlera e ndryshores do të jetë undef.

Shembull i punës me variabla:

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

Kukulla ka hapësirat e emrave, dhe variablat, në përputhje me rrethanat, kanë zona e dukshmërisë: Një variabël me të njëjtin emër mund të përcaktohet në hapësira të ndryshme emrash. Kur zgjidhet vlera e një ndryshoreje, ndryshorja kërkohet në hapësirën aktuale të emrave, pastaj në hapësirën e emrave të mbyllur, e kështu me radhë.

Shembuj të hapësirës së emrave:

  • globale - variablat jashtë përshkrimit të klasës ose nyjes shkojnë atje;
  • hapësira e emrit të nyjeve në përshkrimin e nyjeve;
  • hapësira e emrit të klasës në përshkrimin e klasës.

Për të shmangur paqartësinë kur aksesoni një ndryshore, mund të specifikoni hapësirën e emrave në emrin e ndryshores:

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

Le të pajtohemi që rruga drejt konfigurimit të nginx qëndron në variablin $nginx_conf_source. Atëherë klasa do të duket kështu:

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
}

Megjithatë, shembulli i dhënë është i keq, sepse ka disa "njohuri sekrete" që diku brenda klasës përdoret një ndryshore me një emër të tillë. Është shumë më e saktë ta bëjmë këtë njohuri të përgjithshme - klasat mund të kenë parametra.

Parametrat e klasës janë variabla në hapësirën e emrave të klasës, ato janë të specifikuara në kokën e klasës dhe mund të përdoren si variablat e rregullt në trupin e klasës. Vlerat e parametrave specifikohen kur përdoret klasa në manifest.

Parametri mund të vendoset në një vlerë të paracaktuar. Nëse një parametër nuk ka një vlerë të paracaktuar dhe vlera nuk vendoset kur përdoret, ai do të shkaktojë një gabim përpilimi.

Le të parametrizojmë klasën nga shembulli i mësipërm dhe të shtojmë dy parametra: i pari, i kërkuar, është shtegu i konfigurimit, dhe i dyti, opsional, është emri i paketës me nginx (në Debian, për shembull, ka paketa 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',   # задаём параметры класса точно так же, как параметры для других ресурсов
  }
}

Në Puppet, variablat shtypen. Hani shumë lloje të dhënash. Llojet e të dhënave zakonisht përdoren për të vërtetuar vlerat e parametrave të kaluara në klasa dhe përkufizime. Nëse parametri i kaluar nuk përputhet me llojin e specifikuar, do të ndodhë një gabim përpilimi.

Lloji shkruhet menjëherë përpara emrit të parametrit:

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

Klasat: përfshijnë emrin e klasës kundrejt class{'classname':}

Çdo klasë është një burim i llojit klasë. Ashtu si me çdo lloj tjetër burimi, nuk mund të ketë dy instanca të së njëjtës klasë në të njëjtën nyje.

Nëse përpiqeni të shtoni një klasë në të njëjtën nyje dy herë duke përdorur class { 'classname':} (pa dallim, me parametra të ndryshëm ose identikë), do të ketë një gabim përpilimi. Por nëse përdorni një klasë në stilin e burimit, mund të vendosni menjëherë të gjithë parametrat e saj në manifest.

Megjithatë, nëse përdorni include, atëherë klasa mund të shtohet sa herë të dëshironi. Fakti është se include është një funksion idempotent që kontrollon nëse një klasë është shtuar në drejtori. Nëse klasa nuk është në drejtori, ajo e shton atë, dhe nëse ekziston tashmë, nuk bën asgjë. Por në rast të përdorimit include Nuk mund të vendosni parametrat e klasës gjatë deklarimit të klasës - të gjithë parametrat e kërkuar duhet të vendosen në një burim të jashtëm të dhënash - Hiera ose ENC. Ne do të flasim për to në artikullin vijues.

Përcakton

Siç u tha në bllokun e mëparshëm, e njëjta klasë nuk mund të jetë e pranishme në një nyje më shumë se një herë. Megjithatë, në disa raste ju duhet të jeni në gjendje të përdorni të njëjtin bllok kodi me parametra të ndryshëm në të njëjtën nyje. Me fjalë të tjera, ekziston nevoja për një lloj burimi të vetin.

Për shembull, për të instaluar modulin PHP, ne bëjmë sa më poshtë në Avito:

  1. Instaloni paketën me këtë modul.
  2. Le të krijojmë një skedar konfigurimi për këtë modul.
  3. Ne krijojmë një lidhje simbolike në konfigurimin për php-fpm.
  4. Ne krijojmë një lidhje simbolike në konfigurimin për php cli.

Në raste të tilla, një dizajn si p.sh përcaktojnë (përcaktimi, lloji i përcaktuar, lloji i burimit të përcaktuar). Një Define është e ngjashme me një klasë, por ka dallime: së pari, çdo Define është një lloj burimi, jo një burim; së dyti, çdo përkufizim ka një parametër të nënkuptuar $title, ku shkon emri i burimit kur deklarohet. Ashtu si në rastin e klasave, fillimisht duhet të përshkruhet një përkufizim, pas së cilës mund të përdoret.

Një shembull i thjeshtuar me një modul për PHP:

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' }
}

Mënyra më e lehtë për të kapur gabimin e deklarimit Duplicate është në Define. Kjo ndodh nëse një përkufizim ka një burim me një emër konstant, dhe ka dy ose më shumë raste të këtij përkufizimi në disa nyje.

Është e lehtë të mbroheni nga kjo: të gjitha burimet brenda përkufizimit duhet të kenë një emër në varësi të $title. Një alternativë është shtimi i pafuqishëm i burimeve; në rastin më të thjeshtë, mjafton të zhvendosni burimet e përbashkëta për të gjitha rastet e përkufizimit në një klasë të veçantë dhe ta përfshini këtë klasë në përkufizimin - funksion. include idempotent.

Ka mënyra të tjera për të arritur idempotencë kur shtoni burime, përkatësisht duke përdorur funksione defined и ensure_resources, por unë do t'ju tregoj për këtë në episodin e ardhshëm.

Varësitë dhe njoftimet për klasat dhe përkufizimet

Klasat dhe përkufizimet shtojnë rregullat e mëposhtme për trajtimin e varësive dhe njoftimeve:

  • varësia nga një klasë/define shton varësi nga të gjitha burimet e klasës/përcaktimi;
  • varësia e klasës/përcaktimit shton varësi për të gjitha burimet e klasës/përcaktimit;
  • Njoftimi i klasës/përcaktimit njofton të gjitha burimet e klasës/përcaktojnë;
  • abonimi class/define pajtohet me të gjitha burimet e klasës/define.

Deklaratat e kushtëzuara dhe përzgjedhësit

Dokumentacioni këtu.

if

Është e thjeshtë këtu:

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

veç

përveç nëse është një if në të kundërt: blloku i kodit do të ekzekutohet nëse shprehja është false.

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

rast

As këtu nuk ka asgjë të komplikuar. Ju mund të përdorni vlera të rregullta (vargjet, numrat, etj.), Shprehjet e rregullta dhe llojet e të dhënave si vlera.

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

Përzgjedhës

Një përzgjedhës është një konstrukt gjuhësor i ngjashëm me case, por në vend që të ekzekutojë një bllok kodi, ai kthen një vlerë.

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

Модули

Kur konfigurimi është i vogël, ai mund të mbahet lehtësisht në një manifest. Por sa më shumë konfigurime që përshkruajmë, aq më shumë klasa dhe nyje ka në manifest, ai rritet dhe bëhet i papërshtatshëm për të punuar me të.

Përveç kësaj, ekziston problemi i ripërdorimit të kodit - kur i gjithë kodi është në një manifest, është e vështirë të ndash këtë kod me të tjerët. Për të zgjidhur këto dy probleme, Puppet ka një entitet të quajtur module.

Модули - këto janë grupe klasash, përkufizimesh dhe entitetesh të tjera Puppet të vendosura në një drejtori të veçantë. Me fjalë të tjera, një modul është një pjesë e pavarur e logjikës së Kukullave. Për shembull, mund të ketë një modul për të punuar me nginx, dhe ai do të përmbajë atë dhe vetëm atë që nevojitet për të punuar me nginx, ose mund të ketë një modul për të punuar me PHP, e kështu me radhë.

Modulet janë të versionuara dhe mbështeten edhe varësitë e moduleve nga njëri-tjetri. Ekziston një depo e hapur e moduleve - Forge kukullash.

Në serverin e kukullave, modulet janë të vendosura në nëndrejtorinë e moduleve të drejtorisë rrënjësore. Brenda çdo moduli ka një skemë standarde të drejtorive - manifeste, skedarë, shabllone, lib, etj.

Struktura e skedarit në një modul

Rrënja e modulit mund të përmbajë drejtoritë e mëposhtme me emra përshkrues:

  • manifests - përmban manifeste
  • files - përmban skedarë
  • templates - përmban shabllone
  • lib - përmban kodin Ruby

Kjo nuk është një listë e plotë e drejtorive dhe skedarëve, por mjafton për këtë artikull për momentin.

Emrat e burimeve dhe emrat e skedarëve në modul

Dokumentacioni këtu.

Burimet (klasat, përkufizimet) në një modul nuk mund të emërohen si të doni. Përveç kësaj, ekziston një korrespondencë e drejtpërdrejtë midis emrit të një burimi dhe emrit të skedarit në të cilin Puppet do të kërkojë një përshkrim të atij burimi. Nëse shkelni rregullat e emërtimit, atëherë Puppet thjesht nuk do të gjejë përshkrimin e burimit dhe do të merrni një gabim përpilimi.

Rregullat janë të thjeshta:

  • Të gjitha burimet në një modul duhet të jenë në hapësirën e emrave të modulit. Nëse thirret moduli foo, atëherë të gjitha burimet në të duhet të emërtohen foo::<anything>, ose thjesht foo.
  • Burimi me emrin e modulit duhet të jetë në skedar init.pp.
  • Për burime të tjera, skema e emërtimit të skedarit është si më poshtë:
    • prefiksi me emrin e modulit hidhet poshtë
    • të gjitha dy pikat e dyfishta, nëse ka, zëvendësohen me prerje
    • shtohet zgjerimi .pp

Unë do ta demonstroj me një shembull. Le të themi se po shkruaj një modul nginx. Ai përmban burimet e mëposhtme:

  • klasë nginx përshkruar në manifest init.pp;
  • klasë nginx::service përshkruar në manifest service.pp;
  • përcaktojnë nginx::server përshkruar në manifest server.pp;
  • përcaktojnë nginx::server::location përshkruar në manifest server/location.pp.

Shabllone

Me siguri ju vetë e dini se cilat janë shabllonet, unë nuk do t'i përshkruaj ato në detaje këtu. Por do ta lë për çdo rast lidhje me Wikipedia.

Si të përdorni shabllonet: Kuptimi i një shablloni mund të zgjerohet duke përdorur një funksion template, të cilit i është kaluar rruga për në shabllon. Për burimet e llojit skedar përdoret së bashku me parametrin content. Për shembull, si kjo:

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

Shiko rrugën <modulename>/<filename> nënkupton skedarin <rootdir>/modules/<modulename>/templates/<filename>.

Përveç kësaj, ekziston një funksion inline_template — merr tekstin e shabllonit si hyrje, jo emrin e skedarit.

Brenda shablloneve, mund të përdorni të gjitha variablat Puppet në shtrirjen aktuale.

Puppet mbështet shabllonet në formatin ERB dhe EPP:

Shkurtimisht për ERB

Strukturat e kontrollit:

  • <%= ВЫРАЖЕНИЕ %> - futni vlerën e shprehjes
  • <% ВЫРАЖЕНИЕ %> — njehsoni vlerën e një shprehjeje (pa e futur atë). Deklaratat e kushtëzuara (nëse) dhe sythe (secila) zakonisht shkojnë këtu.
  • <%# КОММЕНТАРИЙ %>

Shprehjet në ERB shkruhen në Ruby (ERB është në të vërtetë Embedded Ruby).

Për të hyrë në variablat nga manifesti, duhet të shtoni @ tek emri i ndryshores. Për të hequr një ndërprerje rreshti që shfaqet pas një konstruksioni kontrolli, duhet të përdorni një etiketë mbyllëse -%>.

Shembull i përdorimit të shabllonit

Le të themi se po shkruaj një modul për të kontrolluar ZooKeeper. Klasa përgjegjëse për krijimin e konfigurimit duket diçka si kjo:

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'),
  }
}

Dhe shabllonin përkatës zoo.cfg.erb - Kështu që:

<% 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 -%>

Fakte dhe variabla të integruar

Shpesh pjesa specifike e konfigurimit varet nga ajo që po ndodh aktualisht në nyje. Për shembull, në varësi të lëshimit të Debian, duhet të instaloni një ose një version tjetër të paketës. Ju mund t'i monitoroni të gjitha këto me dorë, rishkrimi shfaqet nëse nyjet ndryshojnë. Por kjo nuk është një qasje serioze; automatizimi është shumë më i mirë.

Për të marrë informacion rreth nyjeve, Puppet ka një mekanizëm të quajtur fakte. fakte - ky është informacion për nyjen, i disponueshëm në manifeste në formën e ndryshoreve të zakonshme në hapësirën globale të emrave. Për shembull, emri i hostit, versioni i sistemit operativ, arkitektura e procesorit, lista e përdoruesve, lista e ndërfaqeve të rrjetit dhe adresat e tyre dhe shumë, shumë më tepër. Faktet janë të disponueshme në manifeste dhe shabllone si variabla të rregullt.

Një shembull i punës me fakte:

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

Duke folur formalisht, një fakt ka një emër (varg) dhe një vlerë (lloje të ndryshme janë të disponueshme: vargje, vargje, fjalorë). Hani grup faktesh të integruara. Ju gjithashtu mund të shkruani tuajin. Përshkruhen mbledhësit e fakteve si funksionet në Rubyose si skedarë të ekzekutueshëm. Faktet mund të paraqiten edhe në formë skedarë teksti me të dhëna në nyjet.

Gjatë funksionimit, agjenti kukull fillimisht kopjon të gjithë mbledhësit e disponueshëm të fakteve nga pappetserver në nyje, pas së cilës i lëshon ato dhe i dërgon faktet e mbledhura në server; Pas kësaj, serveri fillon përpilimin e katalogut.

Fakte në formën e skedarëve të ekzekutueshëm

Fakte të tilla vendosen në module në drejtori facts.d. Natyrisht, skedarët duhet të jenë të ekzekutueshëm. Kur ekzekutohen, ata duhet të nxjerrin informacion në dalje standarde ose në formatin YAML ose key=value.

Mos harroni se faktet vlejnë për të gjitha nyjet që kontrollohen nga serveri poppet në të cilin është vendosur moduli juaj. Prandaj, në skript, kujdesuni të kontrolloni që sistemi të ketë të gjitha programet dhe skedarët e nevojshëm që fakti juaj të funksionojë.

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

Fakte rubin

Fakte të tilla vendosen në module në drejtori 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

Faktet e tekstit

Fakte të tilla vendosen në nyjet në drejtori /etc/facter/facts.d në Kukull e vjetër ose /etc/puppetlabs/facts.d në Kukullën e re.

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

Arritja tek faktet

Ka dy mënyra për t'iu qasur fakteve:

  • përmes fjalorit $facts: $facts['fqdn'];
  • duke përdorur emrin e faktit si emër të ndryshores: $fqdn.

Është më mirë të përdorni një fjalor $facts, ose edhe më mirë, tregoni hapësirën globale të emrave ($::facts).

Këtu është pjesa përkatëse e dokumentacionit.

Variablat e integruar

Përveç fakteve, ka edhe disa variabla, i disponueshëm në hapësirën globale të emrave.

  • fakte të besuara - variablat që merren nga certifikata e klientit (meqenëse certifikata lëshohet zakonisht në një server poppet, agjenti nuk mund të marrë dhe të ndryshojë thjesht certifikatën e tij, kështu që variablat janë "të besuar"): emri i certifikatës, emri i host dhe domen, shtesa nga certifikata.
  • faktet e serverit - variablat që lidhen me informacionin rreth serverit - versioni, emri, adresa IP e serverit, mjedisi.
  • faktet e agjentit - variablat e shtuara drejtpërdrejt nga agjenti kukull, dhe jo nga faktori - emri i certifikatës, versioni i agjentit, versioni i kukullës.
  • variablat master - Variablat Pappetmaster (siç!). Është pothuajse e njëjtë si në faktet e serverit, plus vlerat e parametrave të konfigurimit janë të disponueshme.
  • variablat e përpiluesit — variablat e përpiluesit që ndryshojnë në çdo fushë: emri i modulit aktual dhe emri i modulit në të cilin është aksesuar objekti aktual. Ato mund të përdoren, për shembull, për të kontrolluar që klasat tuaja private të mos përdoren drejtpërdrejt nga modulet e tjera.

Shtesa 1: si të ekzekutoni dhe korrigjoni të gjitha këto?

Artikulli përmbante shumë shembuj të kodit kukull, por nuk na tregoi fare se si ta ekzekutojmë këtë kod. Epo, po korrigjoj veten.

Mjafton një agjent për të ekzekutuar Puppet, por për shumicën e rasteve do t'ju duhet edhe një server.

agjent

Të paktën që nga versioni XNUMX, paketat e agjentëve të kukullave nga depoja zyrtare e Puppetlabs përmbajnë të gjitha varësitë (rubini dhe gurët përkatës), kështu që nuk ka vështirësi instalimi (po flas për shpërndarjet e bazuara në Debian - ne nuk përdorim shpërndarje të bazuara në RPM).

Në rastin më të thjeshtë, për të përdorur konfigurimin e kukullave, mjafton të nisni agjentin në modalitetin pa server: me kusht që kodi i kukullës të kopjohet në nyje, nisni 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

Është më mirë, natyrisht, të konfiguroni serverin dhe të ekzekutoni agjentët në nyjet në modalitetin daemon - atëherë një herë në gjysmë ore ata do të aplikojnë konfigurimin e shkarkuar nga serveri.

Ju mund të imitoni modelin shtytës të punës - shkoni te nyja që ju intereson dhe filloni sudo puppet agent -t. Celës -t (--test) në fakt përfshin disa opsione që mund të aktivizohen individualisht. Këto opsione përfshijnë sa vijon:

  • mos ekzekutoni në modalitetin daemon (si parazgjedhje agjenti fillon në modalitetin daemon);
  • mbyllet pas aplikimit të katalogut (si parazgjedhje, agjenti do të vazhdojë të punojë dhe do të zbatojë konfigurimin një herë në gjysmë ore);
  • shkruani një regjistër të detajuar të punës;
  • tregoni ndryshimet në skedarë.

Agjenti ka një mënyrë funksionimi pa ndryshime - mund ta përdorni kur nuk jeni të sigurt që keni shkruar konfigurimin e saktë dhe dëshironi të kontrolloni se çfarë saktësisht do të ndryshojë agjenti gjatë funksionimit. Ky modalitet aktivizohet nga parametri --noop në vijën e komandës: sudo puppet agent -t --noop.

Për më tepër, mund të aktivizoni regjistrin e korrigjimit të punës - në të, kukulla shkruan për të gjitha veprimet që kryen: për burimin që po përpunon aktualisht, për parametrat e këtij burimi, për cilat programe nis. Sigurisht, ky është një parametër --debug.

Serveri

Unë nuk do të marr parasysh konfigurimin e plotë të pappetserver dhe vendosjen e kodit në të në këtë artikull; do të them vetëm se jashtë kutisë ekziston një version plotësisht funksional i serverit që nuk kërkon konfigurim shtesë për të punuar me një numër të vogël të nyje (të themi, deri në njëqind). Një numër më i madh nyjesh do të kërkojnë akordim - si parazgjedhje, serveri i kukullave lëshon jo më shumë se katër punëtorë, për performancë më të madhe duhet të rrisni numrin e tyre dhe mos harroni të rritni kufijtë e memories, përndryshe serveri do të mbledhë mbeturinat shumicën e kohës.

Vendosja e kodit - nëse ju nevojitet shpejt dhe lehtë, atëherë shikoni (në r10k)[https://github.com/puppetlabs/r10k], për instalime të vogla duhet të jetë mjaft e mjaftueshme.

Shtojca 2: Udhëzimet e kodimit

  1. Vendosni të gjithë logjikën në klasa dhe përkufizime.
  2. Mbani klasat dhe përkufizimet në module, jo në manifeste që përshkruajnë nyjet.
  3. Përdorni faktet.
  4. Mos bëni if ​​bazuar në emrat e hosteve.
  5. Mos ngurroni të shtoni parametra për klasat dhe përkufizimet - kjo është më mirë se logjika e nënkuptuar e fshehur në trupin e klasës/përcaktojë.

Unë do të shpjegoj pse rekomandoj ta bëni këtë në artikullin vijues.

Përfundim

Le të përfundojmë me hyrjen. Në artikullin tjetër do t'ju tregoj për Hiera, ENC dhe PuppetDB.

Vetëm përdoruesit e regjistruar mund të marrin pjesë në anketë. Hyni, te lutem

Në fakt, ka shumë më tepër material - mund të shkruaj artikuj mbi temat e mëposhtme, të votoj për atë që do të të interesonte të lexosh:

  • 59,1%Konstruksione të avancuara të kukullave - disa gjëra të nivelit tjetër: sythe, harta dhe shprehje të tjera lambda, mbledhësit e burimeve, burimet e eksportuara dhe komunikimi ndërmjet hosteve nëpërmjet Puppet-it, etiketave, ofruesve, llojeve abstrakte të të dhënave.13
  • 31,8%"Unë jam administratori i nënës sime" ose si ne në Avito u miqësuam me disa serverë poppet të versioneve të ndryshme dhe, në parim, me pjesën rreth administrimit të serverit poppet.7
  • 81,8%Si shkruajmë kodin e kukullës: instrumente, dokumentacion, testim, CI/CD.18

22 përdorues kanë votuar. 9 përdorues abstenuan.

Burimi: www.habr.com