Panimula sa Puppet

Ang puppet ay isang configuration management system. Ito ay ginagamit upang dalhin ang mga host sa nais na estado at mapanatili ang estado na ito.

Mahigit limang taon na akong nagtatrabaho sa Puppet. Ang tekstong ito ay mahalagang isinalin at muling inayos na compilation ng mga pangunahing punto mula sa opisyal na dokumentasyon, na magbibigay-daan sa mga nagsisimula upang mabilis na maunawaan ang kakanyahan ng Puppet.

Panimula sa Puppet

Pangunahing impormasyon

Ang operating system ng Puppet ay client-server, bagama't sinusuportahan din nito ang walang server na operasyon na may limitadong functionality.

Ginagamit ang isang pull model of operation: bilang default, isang beses bawat kalahating oras, ang mga kliyente ay nakikipag-ugnayan sa server para sa isang configuration at ilapat ito. Kung nagtrabaho ka sa Ansible, pagkatapos ay gumamit sila ng ibang modelo ng push: sinimulan ng administrator ang proseso ng paglalapat ng pagsasaayos, ang mga kliyente mismo ay hindi maglalapat ng anuman.

Sa panahon ng komunikasyon sa network, ginagamit ang two-way na TLS encryption: ang server at client ay may sariling mga pribadong key at kaukulang mga sertipiko. Kadalasan ang server ay nag-iisyu ng mga sertipiko para sa mga kliyente, ngunit sa prinsipyo posible na gumamit ng panlabas na CA.

Panimula sa mga manifesto

Sa terminolohiya ng Puppet sa puppet server kumonekta mga node (mga node). Ang pagsasaayos para sa mga node ay nakasulat sa mga manifesto sa isang espesyal na programming language - Puppet DSL.

Ang puppet DSL ay isang deklaratibong wika. Inilalarawan nito ang nais na estado ng node sa anyo ng mga deklarasyon ng mga indibidwal na mapagkukunan, halimbawa:

  • Ang file ay umiiral at ito ay may partikular na nilalaman.
  • Naka-install ang package.
  • Nagsimula na ang serbisyo.

Ang mga mapagkukunan ay maaaring magkakaugnay:

  • May mga dependency, nakakaapekto ang mga ito sa pagkakasunud-sunod kung saan ginagamit ang mga mapagkukunan.
    Halimbawa, "i-install muna ang package, pagkatapos ay i-edit ang configuration file, pagkatapos ay simulan ang serbisyo."
  • May mga notification - kung nagbago ang isang mapagkukunan, nagpapadala ito ng mga notification sa mga mapagkukunang naka-subscribe dito.
    Halimbawa, kung nagbago ang configuration file, maaari mong awtomatikong i-restart ang serbisyo.

Bukod pa rito, may mga function at variable ang Puppet DSL, pati na rin ang mga conditional statement at selector. Sinusuportahan din ang iba't ibang mekanismo ng pag-template - EPP at ERB.

Ang puppet ay nakasulat sa Ruby, kaya marami sa mga konstruksyon at termino ay kinuha mula doon. Pinapayagan ka ni Ruby na palawakin ang Puppet - magdagdag ng kumplikadong lohika, mga bagong uri ng mga mapagkukunan, mga function.

Habang tumatakbo ang Puppet, ang mga manifest para sa bawat partikular na node sa server ay pinagsama-sama sa isang direktoryo. Directory ay isang listahan ng mga mapagkukunan at ang kanilang mga relasyon pagkatapos kalkulahin ang halaga ng mga function, variable at pagpapalawak ng mga conditional statement.

Syntax at codestyle

Narito ang mga seksyon ng opisyal na dokumentasyon na makakatulong sa iyong maunawaan ang syntax kung hindi sapat ang mga halimbawang ibinigay:

Narito ang isang halimbawa ng kung ano ang hitsura ng manifest:

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

Ang indentation at line break ay hindi kinakailangang bahagi ng manifest, ngunit may inirerekomenda patnubay ng estilo. Buod:

  • Dalawang-space indents, hindi ginagamit ang mga tab.
  • Ang mga kulot na brace ay pinaghihiwalay ng isang puwang; ang mga colon ay hindi pinaghihiwalay ng isang puwang.
  • Mga kuwit pagkatapos ng bawat parameter, kasama ang huli. Ang bawat parameter ay nasa isang hiwalay na linya. Ang isang pagbubukod ay ginawa para sa kaso na walang mga parameter at isang parameter: maaari kang sumulat sa isang linya at walang kuwit (i.e. resource { 'title': } и resource { 'title': param => value }).
  • Ang mga arrow sa mga parameter ay dapat na nasa parehong antas.
  • Ang mga arrow sa ugnayan ng mapagkukunan ay nakasulat sa harap nila.

Lokasyon ng mga file sa pappetserver

Para sa karagdagang paliwanag, ipakikilala ko ang konsepto ng "root directory". Ang root directory ay ang direktoryo na naglalaman ng configuration ng Puppet para sa isang partikular na node.

Nag-iiba-iba ang root directory depende sa bersyon ng Puppet at sa mga environment na ginamit. Ang mga kapaligiran ay mga independiyenteng hanay ng configuration na nakaimbak sa magkahiwalay na mga direktoryo. Karaniwang ginagamit sa kumbinasyon ng git, kung saan ang mga kapaligiran ay nilikha mula sa mga sanga ng git. Alinsunod dito, ang bawat node ay matatagpuan sa isang kapaligiran o iba pa. Ito ay maaaring i-configure sa node mismo, o sa ENC, na pag-uusapan ko sa susunod na artikulo.

  • Sa ikatlong bersyon ("lumang Puppet") ang base na direktoryo ay /etc/puppet. Ang paggamit ng mga kapaligiran ay opsyonal - halimbawa, hindi namin ginagamit ang mga ito kasama ng lumang Puppet. Kung ginagamit ang mga kapaligiran, kadalasang nakaimbak ang mga ito /etc/puppet/environments, ang root directory ay ang environment directory. Kung hindi ginagamit ang mga kapaligiran, ang root directory ang magiging base na direktoryo.
  • Simula sa ikaapat na bersyon ("bagong Puppet"), ang paggamit ng mga kapaligiran ay naging mandatory, at ang base na direktoryo ay inilipat sa /etc/puppetlabs/code. Alinsunod dito, ang mga kapaligiran ay naka-imbak sa /etc/puppetlabs/code/environments, ang root directory ay ang environment directory.

Dapat mayroong subdirectory sa root directory manifests, na naglalaman ng isa o higit pang mga manifest na naglalarawan sa mga node. Bilang karagdagan, dapat mayroong isang subdirectory modules, na naglalaman ng mga module. Sasabihin ko sa iyo kung ano ang mga module sa ibang pagkakataon. Bilang karagdagan, ang lumang Puppet ay maaari ding magkaroon ng subdirectory files, na naglalaman ng iba't ibang mga file na kinokopya namin sa mga node. Sa bagong Puppet, lahat ng mga file ay inilalagay sa mga module.

Ang mga manifest file ay may extension .pp.

Isang pares ng mga halimbawa ng labanan

Paglalarawan ng node at mapagkukunan dito

Sa node server1.testdomain dapat gumawa ng file /etc/issue may nilalaman Debian GNU/Linux n l. Ang file ay dapat na pagmamay-ari ng isang user at grupo root, ang mga karapatan sa pag-access ay dapat 644.

Sumulat kami ng isang manifesto:

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

Mga ugnayan sa pagitan ng mga mapagkukunan sa isang node

Sa node server2.testdomain Ang nginx ay dapat na tumatakbo, nagtatrabaho sa isang naunang inihanda na pagsasaayos.

I-decompose natin ang problema:

  • Kailangang mai-install ang package nginx.
  • Kinakailangan na ang mga file ng pagsasaayos ay makopya mula sa server.
  • Kailangang tumakbo ang serbisyo nginx.
  • Kung na-update ang configuration, dapat na i-restart ang serbisyo.

Sumulat kami ng isang manifesto:

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

Para gumana ito, kailangan mo ng humigit-kumulang sumusunod na lokasyon ng file sa puppet server:

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

Mga Uri ng Mapagkukunan

Ang isang kumpletong listahan ng mga sinusuportahang uri ng mapagkukunan ay matatagpuan dito sa dokumentasyon, dito ay ilalarawan ko ang limang pangunahing uri, na sa aking pagsasanay ay sapat na upang malutas ang karamihan sa mga problema.

file

Namamahala ng mga file, direktoryo, symlink, mga nilalaman ng mga ito, at mga karapatan sa pag-access.

Parameter:

  • pangalan ng mapagkukunan — path sa file (opsyonal)
  • landas — path sa file (kung hindi ito tinukoy sa pangalan)
  • matiyak - uri ng file:
    • absent - magtanggal ng file
    • present — dapat mayroong isang file ng anumang uri (kung walang file, isang regular na file ang gagawin)
    • file - regular na file
    • directory - direktoryo
    • link - symlink
  • nilalaman — mga nilalaman ng file (angkop lamang para sa mga regular na file, hindi maaaring gamitin kasama ng pinagmulan o target)
  • pinagmulan — isang link sa landas kung saan mo gustong kopyahin ang mga nilalaman ng file (hindi maaaring gamitin kasama ng nilalaman o target). Maaaring tukuyin bilang alinman sa isang URI na may scheme puppet: (pagkatapos ay gagamitin ang mga file mula sa papet na server), at kasama ang scheme http: (Umaasa ako na malinaw kung ano ang mangyayari sa kasong ito), at kahit na sa diagram file: o bilang isang ganap na landas na walang schema (pagkatapos ay gagamitin ang file mula sa lokal na FS sa node)
  • target — kung saan dapat ituro ang symlink (hindi maaaring gamitin kasama ng nilalaman o pinagmulan)
  • may-ari — ang user na dapat nagmamay-ari ng file
  • grupo — ang pangkat kung saan dapat kabilang ang file
  • paraan — mga pahintulot ng file (bilang isang string)
  • magaling muli - nagbibigay-daan sa pagpoproseso ng recursive na direktoryo
  • pampadumi - nagbibigay-daan sa pagtanggal ng mga file na hindi inilarawan sa Puppet
  • pilitin - nagbibigay-daan sa pagtanggal ng mga direktoryo na hindi inilarawan sa Puppet

pakete

Nag-i-install at nag-aalis ng mga pakete. Kayang pangasiwaan ang mga notification - muling i-install ang package kung tinukoy ang parameter reinstall_on_refresh.

Parameter:

  • pangalan ng mapagkukunan — pangalan ng package (opsyonal)
  • pangalan — pangalan ng package (kung hindi tinukoy sa pangalan)
  • provider — package manager na gagamitin
  • matiyak - nais na estado ng pakete:
    • present, installed - anumang bersyon na naka-install
    • latest - pinakabagong bersyon na naka-install
    • absent - tinanggal (apt-get remove)
    • purged — tinanggal kasama ng mga configuration file (apt-get purge)
    • held - naka-lock ang bersyon ng package (apt-mark hold)
    • любая другая строка — naka-install ang tinukoy na bersyon
  • reinstall_on_refresh - kung true, pagkatapos ay sa pagtanggap ng abiso ang package ay muling mai-install. Kapaki-pakinabang para sa mga pamamahagi na nakabatay sa pinagmulan, kung saan maaaring kailanganin ang muling pagbuo ng mga pakete kapag binabago ang mga parameter ng build. Default false.

serbisyo

Namamahala ng mga serbisyo. Magagawang magproseso ng mga notification - i-restart ang serbisyo.

Parameter:

  • pangalan ng mapagkukunan — serbisyong pamamahalaan (opsyonal)
  • pangalan — ang serbisyo na kailangang pamahalaan (kung hindi tinukoy sa pangalan)
  • matiyak — gustong estado ng serbisyo:
    • running - inilunsad
    • stopped - tumigil
  • paganahin — kinokontrol ang kakayahang simulan ang serbisyo:
    • true — pinagana ang autorun (systemctl enable)
    • mask - nag disguise (systemctl mask)
    • false — hindi pinagana ang autorun (systemctl disable)
  • i-restart ang - utos na i-restart ang serbisyo
  • katayuan — utos upang suriin ang katayuan ng serbisyo
  • nag-restart — ipahiwatig kung sinusuportahan ng initscript ng serbisyo ang pag-restart. Kung false at ang parameter ay tinukoy i-restart ang — ang halaga ng parameter na ito ay ginagamit. Kung false at parameter i-restart ang hindi tinukoy - ang serbisyo ay huminto at nagsimulang mag-restart (ngunit ginagamit ng systemd ang command systemctl restart).
  • hasstatus — ipahiwatig kung sinusuportahan ng initscript ng serbisyo ang utos status. Kung false, pagkatapos ay gagamitin ang halaga ng parameter katayuan. Default true.

exec

Nagpapatakbo ng mga panlabas na utos. Kung hindi mo tinukoy ang mga parameter lumilikha, kung, maliban na lamang kung o refreshonly, ang utos ay tatakbo sa tuwing tatakbo ang Puppet. Magagawang magproseso ng mga abiso - nagpapatakbo ng isang utos.

Parameter:

  • pangalan ng mapagkukunan — utos na isasagawa (opsyonal)
  • utos — ang utos na isasagawa (kung hindi ito tinukoy sa pangalan)
  • landas — mga landas kung saan hahanapin ang executable file
  • kung — kung ang utos na tinukoy sa parameter na ito ay nakumpleto na may zero return code, ang pangunahing command ay isasagawa
  • maliban na lamang kung — kung ang utos na tinukoy sa parameter na ito ay nakumpleto na may isang non-zero return code, ang pangunahing utos ay isasagawa
  • lumilikha — kung ang file na tinukoy sa parameter na ito ay hindi umiiral, ang pangunahing utos ay isasagawa
  • refreshonly - kung true, pagkatapos ay tatakbo lamang ang command kapag nakatanggap ang exec na ito ng abiso mula sa ibang mga mapagkukunan
  • cwd — direktoryo kung saan tatakbo ang utos
  • gumagamit — ang gumagamit kung kanino patakbuhin ang utos
  • provider - kung paano patakbuhin ang utos:
    • posix — isang proseso ng bata ay ginawa lamang, siguraduhing tukuyin landas
    • talukap ng alimango - ang command ay inilunsad sa shell /bin/sh, maaaring hindi matukoy landas, maaari mong gamitin ang globbing, pipe at iba pang mga tampok ng shell. Karaniwang awtomatikong nakikita kung mayroong anumang mga espesyal na character (|, ;, &&, || atbp).

cron

Kinokontrol ang mga cronjob.

Parameter:

  • pangalan ng mapagkukunan - ilang uri lang ng identifier
  • matiyak - estado ng crownjob:
    • present - lumikha kung wala
    • absent - tanggalin kung mayroon
  • utos - anong utos ang tatakbo
  • kapaligiran — kung aling kapaligiran ang magpapatakbo ng command (listahan ng mga variable ng kapaligiran at ang kanilang mga halaga sa pamamagitan ng =)
  • gumagamit — kung saan user tatakbo ang command
  • minuto, oras, Linggo, buwan, buwanang araw — kung kailan tatakbo ng cron. Kung ang alinman sa mga katangiang ito ay hindi tinukoy, ang halaga nito sa crontab ay magiging *.

Sa Puppet 6.0 cron parang inalis sa kahon sa puppetserver, kaya walang dokumentasyon sa pangkalahatang site. Pero siya ay nasa kahon sa puppet-agent, kaya hindi na kailangang i-install ito nang hiwalay. Maaari mong makita ang dokumentasyon para dito sa dokumentasyon para sa ikalimang bersyon ng PuppetO sa GitHub.

Tungkol sa mga mapagkukunan sa pangkalahatan

Mga kinakailangan para sa pagiging natatangi ng mapagkukunan

Ang pinakakaraniwang pagkakamali na nararanasan natin ay Dobleng deklarasyon. Ang error na ito ay nangyayari kapag ang dalawa o higit pang mga mapagkukunan ng parehong uri na may parehong pangalan ay lumabas sa direktoryo.

Kaya naman, muli akong magsusulat: ang mga manifest para sa parehong node ay hindi dapat maglaman ng mga mapagkukunan ng parehong uri na may parehong pamagat!

Minsan may pangangailangan na mag-install ng mga package na may parehong pangalan, ngunit may iba't ibang mga manager ng package. Sa kasong ito, kailangan mong gamitin ang parameter namepara maiwasan ang error:

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

Ang ibang mga uri ng mapagkukunan ay may katulad na mga opsyon upang makatulong na maiwasan ang pagdoble − name у serbisyo, command у exec, at iba pa.

Mga metaparameter

Ang bawat uri ng mapagkukunan ay may ilang mga espesyal na parameter, anuman ang kalikasan nito.

Buong listahan ng mga meta parameter sa dokumentasyong Puppet.

Maikling listahan:

  • mangailangan — ang parameter na ito ay nagpapahiwatig kung aling mga mapagkukunan ang nakasalalay sa mapagkukunang ito.
  • bago - Tinutukoy ng parameter na ito kung aling mga mapagkukunan ang nakasalalay sa mapagkukunang ito.
  • sumuskribi — ang parameter na ito ay tumutukoy kung saang mga mapagkukunan ang mapagkukunang ito ay tumatanggap ng mga abiso.
  • ipagbigay-alam — Tinutukoy ng parameter na ito kung aling mga mapagkukunan ang tumatanggap ng mga abiso mula sa mapagkukunang ito.

Ang lahat ng nakalistang metaparameter ay tumatanggap ng alinman sa isang link ng mapagkukunan o isang hanay ng mga link sa mga square bracket.

Mga link sa mga mapagkukunan

Ang link ng mapagkukunan ay isang pagbanggit lamang ng mapagkukunan. Pangunahing ginagamit ang mga ito upang ipahiwatig ang mga dependency. Ang pagre-refer sa isang hindi umiiral na mapagkukunan ay magdudulot ng error sa compilation.

Ang syntax ng link ay ang mga sumusunod: uri ng mapagkukunan na may malaking titik (kung ang pangalan ng uri ay naglalaman ng mga dobleng tutuldok, kung gayon ang bawat bahagi ng pangalan sa pagitan ng mga tutuldok ay naka-capitalize), pagkatapos ay ang pangalan ng mapagkukunan sa mga square bracket (ang kaso ng pangalan hindi nagbabago!). Dapat walang mga puwang; ang mga square bracket ay nakasulat kaagad pagkatapos ng pangalan ng uri.

Halimbawa:

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

Dependencies at notification

Dokumentasyon dito.

Gaya ng nasabi kanina, ang mga simpleng dependency sa pagitan ng mga mapagkukunan ay palipat. Siyanga pala, mag-ingat sa pagdaragdag ng mga dependency - maaari kang lumikha ng mga cyclic na dependencies, na magdudulot ng error sa compilation.

Hindi tulad ng mga dependency, ang mga notification ay hindi palipat. Nalalapat ang mga sumusunod na panuntunan para sa mga abiso:

  • Kung ang mapagkukunan ay nakatanggap ng isang abiso, ito ay ina-update. Ang mga aksyon sa pag-update ay nakasalalay sa uri ng mapagkukunan − exec nagpapatakbo ng utos, serbisyo i-restart ang serbisyo, pakete muling i-install ang package. Kung ang mapagkukunan ay walang tinukoy na pagkilos sa pag-update, walang mangyayari.
  • Sa isang pagpapatakbo ng Puppet, ina-update ang mapagkukunan nang hindi hihigit sa isang beses. Posible ito dahil kasama sa mga notification ang mga dependency at ang graph ng dependency ay hindi naglalaman ng mga cycle.
  • Kung binago ng Puppet ang estado ng isang mapagkukunan, ang mapagkukunan ay nagpapadala ng mga abiso sa lahat ng mga mapagkukunang naka-subscribe dito.
  • Kung ang isang mapagkukunan ay na-update, nagpapadala ito ng mga abiso sa lahat ng mga mapagkukunang naka-subscribe dito.

Pangangasiwa sa mga hindi natukoy na parameter

Bilang panuntunan, kung walang default na value ang ilang resource parameter at hindi tinukoy ang parameter na ito sa manifest, hindi babaguhin ng Puppet ang property na ito para sa kaukulang resource sa node. Halimbawa, kung isang mapagkukunan ng uri file hindi tinukoy ang parameter owner, pagkatapos ay hindi babaguhin ng Puppet ang may-ari ng kaukulang file.

Panimula sa mga klase, variable at kahulugan

Ipagpalagay na mayroon kaming ilang mga node na may parehong bahagi ng pagsasaayos, ngunit mayroon ding mga pagkakaiba - kung hindi, maaari naming ilarawan ang lahat sa isang bloke node {}. Siyempre, maaari mo lamang kopyahin ang magkaparehong bahagi ng pagsasaayos, ngunit sa pangkalahatan ito ay isang masamang solusyon - lumalaki ang pagsasaayos, at kung babaguhin mo ang pangkalahatang bahagi ng pagsasaayos, kakailanganin mong i-edit ang parehong bagay sa maraming lugar. Kasabay nito, madaling magkamali, at sa pangkalahatan, ang DRY (huwag ulitin ang iyong sarili) na prinsipyo ay naimbento para sa isang dahilan.

Upang malutas ang problemang ito mayroong isang disenyo bilang klase.

Mga klase

klase ay isang pinangalanang bloke ng poppet code. Kailangan ng mga klase para magamit muli ang code.

Una kailangan ilarawan ang klase. Ang paglalarawan mismo ay hindi nagdaragdag ng anumang mga mapagkukunan kahit saan. Ang klase ay inilarawan sa mga manifest:

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

Pagkatapos nito ang klase ay maaaring gamitin:

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

Isang halimbawa mula sa nakaraang gawain - ilipat natin ang pag-install at pagsasaayos ng nginx sa isang klase:

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
}

Mga variable

Ang klase mula sa nakaraang halimbawa ay hindi nababaluktot dahil palagi itong nagdadala ng parehong pagsasaayos ng nginx. Gawin natin ang landas patungo sa variable ng pagsasaayos, pagkatapos ang klase na ito ay maaaring gamitin upang i-install ang nginx sa anumang pagsasaayos.

Pwedeng magawa gamit ang mga variable.

Pansin: ang mga variable sa Puppet ay hindi nababago!

Bilang karagdagan, ang isang variable ay maaari lamang ma-access pagkatapos na ito ay ideklara, kung hindi, ang halaga ng variable ay magiging undef.

Halimbawa ng pagtatrabaho sa mga variable:

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

May puppet mga namespace, at ang mga variable, nang naaayon, ay mayroon lugar ng visibility: Ang isang variable na may parehong pangalan ay maaaring tukuyin sa iba't ibang mga namespace. Kapag niresolba ang halaga ng isang variable, hahanapin ang variable sa kasalukuyang namespace, pagkatapos ay sa kalakip na namespace, at iba pa.

Mga halimbawa ng namespace:

  • global - ang mga variable sa labas ng klase o paglalarawan ng node ay napupunta doon;
  • node namespace sa paglalarawan ng node;
  • namespace ng klase sa paglalarawan ng klase.

Upang maiwasan ang kalabuan kapag ina-access ang isang variable, maaari mong tukuyin ang namespace sa pangalan ng variable:

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

Sumang-ayon tayo na ang landas sa pagsasaayos ng nginx ay nasa variable $nginx_conf_source. Pagkatapos ang klase ay magiging ganito:

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
}

Gayunpaman, ang ibinigay na halimbawa ay masama dahil mayroong ilang "lihim na kaalaman" na sa isang lugar sa loob ng klase ay ginagamit ang isang variable na may ganito at ganoong pangalan. Mas tama na gawing pangkalahatan ang kaalamang ito - maaaring magkaroon ng mga parameter ang mga klase.

Mga parameter ng klase ay mga variable sa namespace ng klase, tinukoy ang mga ito sa header ng klase at maaaring gamitin tulad ng mga regular na variable sa katawan ng klase. Tinukoy ang mga value ng parameter kapag ginagamit ang klase sa manifest.

Ang parameter ay maaaring itakda sa isang default na halaga. Kung walang default na value ang isang parameter at hindi nakatakda ang value kapag ginamit, magdudulot ito ng error sa compilation.

I-parameter natin ang klase mula sa halimbawa sa itaas at magdagdag ng dalawang parameter: ang una, kinakailangan, ay ang landas sa pagsasaayos, at ang pangalawa, opsyonal, ay ang pangalan ng package na may nginx (sa Debian, halimbawa, mayroong mga pakete 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',   # задаём параметры класса точно так же, как параметры для других ресурсов
  }
}

Sa Puppet, tina-type ang mga variable. Kumain maraming uri ng data. Karaniwang ginagamit ang mga uri ng data upang patunayan ang mga value ng parameter na ipinasa sa mga klase at kahulugan. Kung hindi tumugma ang naipasa na parameter sa tinukoy na uri, magkakaroon ng error sa compilation.

Ang uri ay nakasulat kaagad bago ang pangalan ng parameter:

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

Mga klase: isama ang classname vs class{'classname':}

Ang bawat klase ay isang uri ng mapagkukunan klase. Tulad ng anumang iba pang uri ng mapagkukunan, hindi maaaring magkaroon ng dalawang pagkakataon ng parehong klase sa parehong node.

Kung susubukan mong magdagdag ng isang klase sa parehong node nang dalawang beses gamit class { 'classname':} (walang pagkakaiba, na may magkaiba o magkaparehong mga parameter), magkakaroon ng error sa compilation. Ngunit kung gagamit ka ng isang klase sa istilo ng mapagkukunan, maaari mong malinaw na itakda kaagad ang lahat ng mga parameter nito sa manifest.

Gayunpaman, kung gagamitin mo include, pagkatapos ay maaaring idagdag ang klase nang maraming beses hangga't ninanais. Sa katotohanan ay include ay isang idempotent function na nagsusuri kung ang isang klase ay naidagdag sa direktoryo. Kung ang klase ay wala sa direktoryo, idinaragdag nito ito, at kung mayroon na ito, wala itong gagawin. Ngunit sa kaso ng paggamit include Hindi ka maaaring magtakda ng mga parameter ng klase sa panahon ng deklarasyon ng klase - lahat ng kinakailangang parameter ay dapat itakda sa isang panlabas na pinagmumulan ng data - Hiera o ENC. Pag-uusapan natin sila sa susunod na artikulo.

Tinutukoy

Tulad ng sinabi sa nakaraang bloke, ang parehong klase ay hindi maaaring naroroon sa isang node nang higit sa isang beses. Gayunpaman, sa ilang mga kaso kailangan mong magamit ang parehong bloke ng code na may iba't ibang mga parameter sa parehong node. Sa madaling salita, may pangangailangan para sa sarili nitong uri ng mapagkukunan.

Halimbawa, upang mai-install ang PHP module, ginagawa namin ang sumusunod sa Avito:

  1. I-install ang package gamit ang module na ito.
  2. Gumawa tayo ng configuration file para sa module na ito.
  3. Gumawa kami ng symlink sa config para sa php-fpm.
  4. Gumawa kami ng symlink sa config para sa php cli.

Sa ganitong mga kaso, isang disenyo tulad ng tukuyin (tukuyin, tinukoy na uri, tinukoy na uri ng mapagkukunan). Ang Define ay katulad ng isang klase, ngunit may mga pagkakaiba: una, ang bawat Define ay isang uri ng mapagkukunan, hindi isang mapagkukunan; pangalawa, ang bawat kahulugan ay may implicit na parameter $title, kung saan napupunta ang pangalan ng mapagkukunan kapag ito ay idineklara. Tulad ng sa kaso ng mga klase, ang isang kahulugan ay dapat munang ilarawan, pagkatapos ay maaari itong magamit.

Isang pinasimpleng halimbawa na may isang module para sa 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' }
}

Ang pinakamadaling paraan upang mahuli ang Duplicate na error sa deklarasyon ay sa Define. Nangyayari ito kung ang isang kahulugan ay may mapagkukunan na may palaging pangalan, at mayroong dalawa o higit pang mga pagkakataon ng kahulugang ito sa ilang node.

Madaling protektahan ang iyong sarili mula dito: ang lahat ng mapagkukunan sa loob ng kahulugan ay dapat na may pangalan depende sa $title. Ang isang alternatibo ay idempotent na pagdaragdag ng mga mapagkukunan; sa pinakasimpleng kaso, sapat na upang ilipat ang mga mapagkukunan na karaniwan sa lahat ng mga pagkakataon ng kahulugan sa isang hiwalay na klase at isama ang klase na ito sa kahulugan - function. include idempotent.

Mayroong iba pang mga paraan upang makamit ang idempotency kapag nagdaragdag ng mga mapagkukunan, katulad ng paggamit ng mga function defined и ensure_resources, ngunit sasabihin ko sa iyo ang tungkol dito sa susunod na episode.

Dependencies at notification para sa mga klase at kahulugan

Ang mga klase at kahulugan ay nagdaragdag ng mga sumusunod na panuntunan sa paghawak ng mga dependency at notification:

  • ang dependency sa isang klase/define ay nagdaragdag ng mga dependencies sa lahat ng mapagkukunan ng klase/define;
  • ang isang class/define dependency ay nagdaragdag ng mga dependencies sa lahat ng klase/define resources;
  • inaabisuhan ng class/define notification ang lahat ng resources ng class/define;
  • class/define subscription subscribes sa lahat ng resources ng class/define.

Mga pahayag na may kundisyon at tagapili

Dokumentasyon dito.

if

Ito ay simple dito:

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

maliban na lamang kung

maliban kung ang isang kung sa kabaligtaran: ang bloke ng code ay isasagawa kung ang expression ay mali.

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

kaso

Wala rin namang kumplikado dito. Maaari kang gumamit ng mga regular na halaga (mga string, numero, atbp.), mga regular na expression, at mga uri ng data bilang mga halaga.

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

Mga pumipili

Ang isang selector ay isang wikang construct na katulad ng case, ngunit sa halip na magsagawa ng isang bloke ng code, nagbabalik ito ng isang halaga.

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

Mga Modyul

Kapag maliit ang configuration, madali itong maitago sa isang manifest. Ngunit kung mas maraming mga pagsasaayos ang inilalarawan namin, mas maraming mga klase at node ang nasa manifest, lumalaki ito, at nagiging hindi komportable na magtrabaho kasama.

Bilang karagdagan, mayroong problema sa muling paggamit ng code - kapag ang lahat ng code ay nasa isang manifest, mahirap ibahagi ang code na ito sa iba. Upang malutas ang dalawang problemang ito, ang Puppet ay mayroong entity na tinatawag na modules.

Mga Modyul - ito ay mga hanay ng mga klase, mga kahulugan at iba pang Puppet entity na inilagay sa isang hiwalay na direktoryo. Sa madaling salita, ang isang module ay isang independiyenteng piraso ng Puppet logic. Halimbawa, maaaring mayroong isang module para sa pagtatrabaho sa nginx, at naglalaman ito ng kung ano at kung ano lamang ang kinakailangan upang gumana sa nginx, o maaaring mayroong isang module para sa pagtatrabaho sa PHP, at iba pa.

Ang mga module ay may bersyon, at ang mga dependency ng mga module sa isa't isa ay sinusuportahan din. Mayroong isang bukas na imbakan ng mga module - Puppet Forge.

Sa puppet server, ang mga module ay matatagpuan sa modules subdirectory ng root directory. Sa loob ng bawat module mayroong isang karaniwang scheme ng direktoryo - mga manifest, mga file, mga template, lib, at iba pa.

Istraktura ng file sa isang module

Ang ugat ng module ay maaaring maglaman ng mga sumusunod na direktoryo na may mga mapaglarawang pangalan:

  • manifests - naglalaman ito ng mga manifesto
  • files - naglalaman ito ng mga file
  • templates - naglalaman ito ng mga template
  • lib — naglalaman ito ng Ruby code

Ito ay hindi isang kumpletong listahan ng mga direktoryo at mga file, ngunit ito ay sapat na para sa artikulong ito sa ngayon.

Mga pangalan ng mapagkukunan at pangalan ng mga file sa module

Dokumentasyon dito.

Ang mga mapagkukunan (mga klase, mga kahulugan) sa isang module ay hindi maaaring pangalanan kung ano ang gusto mo. Bilang karagdagan, mayroong direktang pagsusulatan sa pagitan ng pangalan ng isang mapagkukunan at ang pangalan ng file kung saan hahanapin ng Puppet ang isang paglalarawan ng mapagkukunang iyon. Kung nilalabag mo ang mga panuntunan sa pagbibigay ng pangalan, hindi makikita ng Puppet ang paglalarawan ng mapagkukunan, at makakakuha ka ng error sa compilation.

Ang mga patakaran ay simple:

  • Ang lahat ng mga mapagkukunan sa isang module ay dapat na nasa namespace ng module. Kung tawagin ang modyul foo, pagkatapos ay dapat pangalanan ang lahat ng mga mapagkukunan sa loob nito foo::<anything>, o kaya lang foo.
  • Ang mapagkukunan na may pangalan ng module ay dapat na nasa file init.pp.
  • Para sa iba pang mapagkukunan, ang scheme ng pagpapangalan ng file ay ang sumusunod:
    • ang prefix na may pangalan ng module ay itinapon
    • lahat ng double colon, kung mayroon man, ay pinapalitan ng mga slash
    • idinagdag ang extension .pp

Ipapakita ko sa isang halimbawa. Sabihin nating nagsusulat ako ng isang module nginx. Naglalaman ito ng mga sumusunod na mapagkukunan:

  • klase nginx inilarawan sa manifest init.pp;
  • klase nginx::service inilarawan sa manifest service.pp;
  • tukuyin nginx::server inilarawan sa manifest server.pp;
  • tukuyin nginx::server::location inilarawan sa manifest server/location.pp.

Template

Tiyak na alam mo mismo kung ano ang mga template; hindi ko ilalarawan ang mga ito nang detalyado dito. Pero iiwan ko nalang kung sakali link sa Wikipedia.

Paano gumamit ng mga template: Ang kahulugan ng isang template ay maaaring palawakin gamit ang isang function template, na ipinasa ang landas patungo sa template. Para sa mga mapagkukunan ng uri file ginamit kasama ng parameter content. Halimbawa, tulad nito:

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

Tingnan ang landas <modulename>/<filename> nagpapahiwatig ng file <rootdir>/modules/<modulename>/templates/<filename>.

Bilang karagdagan, mayroong isang pagpapaandar inline_template — natatanggap nito ang teksto ng template bilang input, hindi ang pangalan ng file.

Sa loob ng mga template, maaari mong gamitin ang lahat ng variable ng Puppet sa kasalukuyang saklaw.

Sinusuportahan ng puppet ang mga template sa ERB at EPP na format:

Maikling tungkol sa ERB

Mga istruktura ng kontrol:

  • <%= ВЫРАЖЕНИЕ %> — ipasok ang halaga ng expression
  • <% ВЫРАЖЕНИЕ %> — kalkulahin ang halaga ng isang expression (nang hindi ipinapasok ito). Ang mga kondisyong pahayag (kung) at mga loop (bawat isa) ay karaniwang napupunta dito.
  • <%# КОММЕНТАРИЙ %>

Ang mga expression sa ERB ay nakasulat sa Ruby (Ang ERB ay talagang Naka-embed na Ruby).

Upang ma-access ang mga variable mula sa manifest, kailangan mong magdagdag @ sa variable na pangalan. Para mag-alis ng line break na lumalabas pagkatapos ng control construct, kailangan mong gumamit ng closing tag -%>.

Halimbawa ng paggamit ng template

Sabihin nating nagsusulat ako ng isang module upang kontrolin ang ZooKeeper. Ang klase na responsable sa paglikha ng config ay mukhang ganito:

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

At ang kaukulang template zoo.cfg.erb - Kaya:

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

Mga Katotohanan at Built-in na Variable

Kadalasan ang partikular na bahagi ng pagsasaayos ay nakasalalay sa kasalukuyang nangyayari sa node. Halimbawa, depende sa kung ano ang release ng Debian, kailangan mong mag-install ng isa o ibang bersyon ng package. Maaari mong subaybayan ang lahat ng ito nang manu-mano, muling pagsusulat ng mga manifest kung magbabago ang mga node. Ngunit ito ay hindi isang seryosong diskarte; ang automation ay mas mahusay.

Upang makakuha ng impormasyon tungkol sa mga node, ang Puppet ay may mekanismo na tinatawag na mga katotohanan. katotohanan - ito ay impormasyon tungkol sa node, na magagamit sa mga manifest sa anyo ng mga ordinaryong variable sa pandaigdigang namespace. Halimbawa, pangalan ng host, bersyon ng operating system, arkitektura ng processor, listahan ng mga user, listahan ng mga interface ng network at kanilang mga address, at marami pa. Available ang mga katotohanan sa mga manifest at template bilang mga regular na variable.

Isang halimbawa ng pagtatrabaho sa mga katotohanan:

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

Sa pormal na pagsasalita, ang isang katotohanan ay may pangalan (string) at isang halaga (iba't ibang uri ang magagamit: mga string, array, mga diksyunaryo). Kumain hanay ng mga built-in na katotohanan. Maaari ka ring sumulat ng iyong sarili. Inilalarawan ang mga fact collector tulad ng mga function sa Rubyalinman bilang mga executable na file. Ang mga katotohanan ay maaari ding ipakita sa anyo mga text file na may data sa mga node.

Sa panahon ng operasyon, kinokopya muna ng ahente ng papet ang lahat ng available na fact collector mula sa pappetserver patungo sa node, pagkatapos nito ay inilulunsad ang mga ito at ipinapadala ang mga nakolektang katotohanan sa server; Pagkatapos nito, magsisimula ang server sa pag-compile ng catalog.

Mga katotohanan sa anyo ng mga maipapatupad na file

Ang ganitong mga katotohanan ay inilalagay sa mga module sa direktoryo facts.d. Siyempre, ang mga file ay dapat na maipapatupad. Kapag tumakbo, dapat silang mag-output ng impormasyon sa karaniwang output sa alinman sa YAML o key=value na format.

Huwag kalimutan na ang mga katotohanan ay nalalapat sa lahat ng mga node na kinokontrol ng poppet server kung saan naka-deploy ang iyong module. Samakatuwid, sa script, mag-ingat upang suriin na ang system ay mayroong lahat ng mga programa at file na kinakailangan para gumana ang iyong katotohanan.

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

Mga katotohanan ni Ruby

Ang ganitong mga katotohanan ay inilalagay sa mga module sa direktoryo 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

Mga katotohanan sa teksto

Ang ganitong mga katotohanan ay inilalagay sa mga node sa direktoryo /etc/facter/facts.d sa lumang Puppet o /etc/puppetlabs/facts.d sa bagong Puppet.

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

Pagkuha sa Katotohanan

Mayroong dalawang paraan upang lapitan ang mga katotohanan:

  • sa pamamagitan ng diksyunaryo $facts: $facts['fqdn'];
  • gamit ang fact name bilang variable na pangalan: $fqdn.

Pinakamabuting gumamit ng diksyunaryo $facts, o mas mabuti pa, ipahiwatig ang pandaigdigang namespace ($::facts).

Narito ang nauugnay na seksyon ng dokumentasyon.

Mga Built-in na Variable

Bukod sa katotohanan, mayroon din ilang mga variable, available sa pandaigdigang namespace.

  • pinagkakatiwalaang katotohanan — mga variable na kinukuha mula sa certificate ng kliyente (dahil ang certificate ay karaniwang ibinibigay sa isang poppet server, ang ahente ay hindi maaaring basta-basta kunin at baguhin ang certificate nito, kaya ang mga variable ay “pinagkakatiwalaan”): pangalan ng certificate, host at domain name, mga extension mula sa sertipiko.
  • mga katotohanan ng server —mga variable na nauugnay sa impormasyon tungkol sa server—bersyon, pangalan, IP address ng server, kapaligiran.
  • mga katotohanan ng ahente — mga variable na direktang idinagdag ng puppet-agent, at hindi ng facter — pangalan ng certificate, bersyon ng ahente, bersyon ng papet.
  • master variable - Mga variable ng Pappetmaster (tama!). Ito ay halos kapareho ng sa mga katotohanan ng server, kasama ang mga halaga ng parameter ng pagsasaayos ay magagamit.
  • mga variable ng compiler — mga variable ng compiler na naiiba sa bawat saklaw: ang pangalan ng kasalukuyang module at ang pangalan ng module kung saan na-access ang kasalukuyang object. Maaaring gamitin ang mga ito, halimbawa, upang suriin na ang iyong mga pribadong klase ay hindi ginagamit nang direkta mula sa iba pang mga module.

Karagdagan 1: paano patakbuhin at i-debug ang lahat ng ito?

Ang artikulo ay naglalaman ng maraming halimbawa ng papet na code, ngunit hindi sinabi sa amin kung paano patakbuhin ang code na ito. Well, inaayos ko ang sarili ko.

Ang isang ahente ay sapat na upang magpatakbo ng Puppet, ngunit para sa karamihan ng mga kaso kakailanganin mo rin ng isang server.

Ahente

Hindi bababa sa mula sa bersyon XNUMX, puppet-agent packages mula sa opisyal na imbakan ng Puppetlabs naglalaman ng lahat ng mga dependency (ruby at ang kaukulang mga hiyas), kaya walang mga paghihirap sa pag-install (pinag-uusapan ko ang tungkol sa mga distribusyon na nakabatay sa Debian - hindi kami gumagamit ng mga distribusyon na nakabatay sa RPM).

Sa pinakasimpleng kaso, upang magamit ang pagsasaayos ng papet, sapat na upang ilunsad ang ahente sa mode na walang server: sa kondisyon na ang code ng papet ay kinopya sa node, ilunsad 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

Siyempre, mas mahusay na i-set up ang server at patakbuhin ang mga ahente sa mga node sa daemon mode - pagkatapos ay isang beses bawat kalahating oras ilalapat nila ang configuration na na-download mula sa server.

Maaari mong gayahin ang push model ng trabaho - pumunta sa node na interesado ka at magsimula sudo puppet agent -t. Susi -t (--test) aktwal na kasama ang ilang mga opsyon na maaaring paganahin nang paisa-isa. Kasama sa mga opsyong ito ang sumusunod:

  • huwag tumakbo sa daemon mode (bilang default ang ahente ay nagsisimula sa daemon mode);
  • shut down pagkatapos ilapat ang catalog (bilang default, ang ahente ay patuloy na gagana at ilapat ang pagsasaayos isang beses bawat kalahating oras);
  • magsulat ng isang detalyadong log ng trabaho;
  • ipakita ang mga pagbabago sa mga file.

Ang ahente ay may operating mode na walang mga pagbabago - maaari mong gamitin ito kapag hindi ka sigurado na naisulat mo ang tamang configuration at gusto mong suriin kung ano ang eksaktong babaguhin ng ahente sa panahon ng operasyon. Ang mode na ito ay pinagana ng parameter --noop sa command line: sudo puppet agent -t --noop.

Bilang karagdagan, maaari mong paganahin ang pag-debug ng log ng trabaho - sa loob nito, nagsusulat ang papet tungkol sa lahat ng mga aksyon na ginagawa nito: tungkol sa mapagkukunan na kasalukuyang pinoproseso nito, tungkol sa mga parameter ng mapagkukunang ito, tungkol sa kung anong mga programa ang inilulunsad nito. Siyempre ito ay isang parameter --debug.

Server

Hindi ko isasaalang-alang ang buong pag-setup ng pappetserver at ang pag-deploy ng code dito sa artikulong ito; Sasabihin ko lang na sa labas ng kahon mayroong isang fully functional na bersyon ng server na hindi nangangailangan ng karagdagang configuration upang gumana sa isang maliit bilang ng mga node (sabihin, hanggang sa isang daan). Ang isang mas malaking bilang ng mga node ay mangangailangan ng pag-tune - bilang default, ang puppetserver ay naglulunsad ng hindi hihigit sa apat na manggagawa, para sa mas mahusay na pagganap kailangan mong dagdagan ang kanilang bilang at huwag kalimutang dagdagan ang mga limitasyon ng memorya, kung hindi man ang server ay mangolekta ng basura sa halos lahat ng oras.

Pag-deploy ng code - kung kailangan mo ito nang mabilis at madali, pagkatapos ay tumingin (sa r10k)[https://github.com/puppetlabs/r10k], para sa maliliit na pag-install ito ay dapat na sapat na.

Addendum 2: Mga Alituntunin sa Pag-code

  1. Ilagay ang lahat ng lohika sa mga klase at mga kahulugan.
  2. Panatilihin ang mga klase at kahulugan sa mga module, hindi sa mga manifest na naglalarawan ng mga node.
  3. Gamitin ang mga katotohanan.
  4. Huwag gumawa ng kung batay sa mga hostname.
  5. Huwag mag-atubiling magdagdag ng mga parameter para sa mga klase at kahulugan - ito ay mas mahusay kaysa sa implicit logic na nakatago sa katawan ng klase/define.

Ipapaliwanag ko kung bakit inirerekomenda kong gawin ito sa susunod na artikulo.

Konklusyon

Tapusin na natin ang pagpapakilala. Sa susunod na artikulo sasabihin ko sa iyo ang tungkol sa Hiera, ENC at PuppetDB.

Ang mga rehistradong user lamang ang maaaring lumahok sa survey. Mag-sign in, pakiusap

Sa katunayan, marami pang materyal - maaari akong magsulat ng mga artikulo sa mga sumusunod na paksa, bumoto sa kung ano ang gusto mong basahin tungkol sa:

  • 59,1%Mga advanced na construct ng papet - ilang susunod na antas na shit: mga loop, pagmamapa at iba pang lambda expression, mga resource collector, na-export na mapagkukunan at inter-host na komunikasyon sa pamamagitan ng Puppet, tag, provider, abstract na uri ng data.13
  • 31,8%"Ako ang admin ng aking ina" o kung paano kami sa Avito ay nakipagkaibigan sa ilang mga poppet server ng iba't ibang bersyon, at, sa prinsipyo, ang bahagi tungkol sa pangangasiwa sa poppet server.7
  • 81,8%Paano namin isinusulat ang papet na code: instrumentasyon, dokumentasyon, pagsubok, CI/CD.18

22 na user ang bumoto. 9 user ang umiwas.

Pinagmulan: www.habr.com