Ներածություն տիկնիկային

Puppet-ը կոնֆիգուրացիայի կառավարման համակարգ է: Այն օգտագործվում է հյուրընկալողներին ցանկալի վիճակին բերելու և այս վիճակը պահպանելու համար:

Ես աշխատում եմ Puppet-ի հետ արդեն ավելի քան հինգ տարի: Այս տեքստը, ըստ էության, պաշտոնական փաստաթղթերի հիմնական կետերի թարգմանված և վերադասավորված հավաքածու է, որը թույլ կտա սկսնակներին արագ հասկանալ Տիկնիկայինի էությունը:

Ներածություն տիկնիկային

Հիմնական տեղեկություններ

Puppet-ի օպերացիոն համակարգը հաճախորդ-սերվեր է, թեև այն նաև աջակցում է առանց սերվերի աշխատանքին սահմանափակ ֆունկցիոնալությամբ:

Օգտագործվում է աշխատանքի ձգման մոդել. լռելյայն, յուրաքանչյուր կես ժամը մեկ հաճախորդները կապվում են սերվերի հետ կոնֆիգուրացիայի համար և կիրառում այն: Եթե ​​դուք աշխատել եք Ansible-ի հետ, ապա նրանք օգտագործում են այլ push մոդել՝ ադմինիստրատորը նախաձեռնում է կոնֆիգուրացիայի կիրառման գործընթացը, հաճախորդներն իրենք ոչինչ չեն կիրառի։

Ցանցային հաղորդակցության ընթացքում օգտագործվում է երկկողմանի TLS կոդավորումը. սերվերը և հաճախորդն ունեն իրենց անձնական բանալիները և համապատասխան վկայականները: Սովորաբար սերվերը սերտիֆիկատներ է տալիս հաճախորդների համար, բայց սկզբունքորեն հնարավոր է օգտագործել արտաքին CA:

Մանիֆեստների ներածություն

Տիկնիկային տերմինաբանությամբ դեպի տիկնիկային սերվեր միացնել հանգույցներ (հանգույցներ): Հանգույցների կոնֆիգուրացիան գրված է մանիֆեստներում հատուկ ծրագրավորման լեզվով՝ Puppet DSL:

Տիկնիկային DSL-ը դեկլարատիվ լեզու է: Այն նկարագրում է հանգույցի ցանկալի վիճակը անհատական ​​ռեսուրսների հայտարարագրերի տեսքով, օրինակ.

  • Ֆայլը գոյություն ունի և ունի կոնկրետ բովանդակություն:
  • Փաթեթը տեղադրված է։
  • Ծառայությունը մեկնարկել է.

Ռեսուրսները կարող են փոխկապակցված լինել.

  • Կախվածություններ կան, դրանք ազդում են ռեսուրսների օգտագործման հերթականության վրա։
    Օրինակ, «նախ տեղադրեք փաթեթը, այնուհետև խմբագրեք կազմաձևման ֆայլը, այնուհետև սկսեք ծառայությունը»:
  • Կան ծանուցումներ. եթե ռեսուրսը փոխվել է, այն ծանուցումներ է ուղարկում դրան բաժանորդագրված ռեսուրսներին:
    Օրինակ, եթե կազմաձևման ֆայլը փոխվի, կարող եք ավտոմատ կերպով վերագործարկել ծառայությունը:

Բացի այդ, Puppet DSL-ն ունի գործառույթներ և փոփոխականներ, ինչպես նաև պայմանական հայտարարություններ և ընտրիչներ: Աջակցվում են նաև ձևանմուշների տարբեր մեխանիզմներ՝ EPP և ERB:

Տիկնիկը գրված է Ruby-ով, ուստի շատ կոնստրուկցիաներ և տերմիններ վերցված են այնտեղից: Ruby-ն թույլ է տալիս ընդլայնել Puppet-ը` ավելացնել բարդ տրամաբանություն, նոր տեսակի ռեսուրսներ, գործառույթներ:

Մինչ Puppet-ը աշխատում է, սերվերի յուրաքանչյուր կոնկրետ հանգույցի մանիֆեստները կազմվում են գրացուցակի մեջ: Տեղեկատու ռեսուրսների և դրանց փոխհարաբերությունների ցանկն է՝ ֆունկցիաների, փոփոխականների արժեքը և պայմանական հայտարարությունների ընդլայնումից հետո:

Շարահյուսություն և կոդի ոճ

Ահա պաշտոնական փաստաթղթերի բաժիններ, որոնք կօգնեն ձեզ հասկանալ շարահյուսությունը, եթե ներկայացված օրինակները բավարար չեն.

Ահա մի օրինակ, թե ինչ տեսք ունի մանիֆեստը.

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

Նահանջը և տողերի ընդմիջումները մանիֆեստի պարտադիր մաս չեն, սակայն կա խորհուրդ ոճով ուղեցույցը. Ամփոփում:

  • Երկու բացատ նահանջներ, ներդիրներ չեն օգտագործվում:
  • Գանգուր բրեկետները բաժանված են բացատով, հաստիքները չեն բաժանվում բացատով:
  • Ստորակետներ յուրաքանչյուր պարամետրից հետո, ներառյալ վերջինը: Յուրաքանչյուր պարամետր առանձին տողում է: Բացառություն է արվում առանց պարամետրերի և մեկ պարամետրի դեպքի համար. կարող եք գրել մեկ տողի վրա և առանց ստորակետի (այսինքն. resource { 'title': } и resource { 'title': param => value }).
  • Պարամետրերի վրա սլաքները պետք է լինեն նույն մակարդակի վրա:
  • Դրանց դիմաց գրված են ռեսուրսների հարաբերությունների սլաքները:

Ֆայլերի գտնվելու վայրը pappetserver-ում

Լրացուցիչ բացատրության համար ես կներկայացնեմ «արմատային գրացուցակ» հասկացությունը: Արմատային գրացուցակը այն գրացուցակն է, որը պարունակում է Տիկնիկային կոնֆիգուրացիան որոշակի հանգույցի համար:

Արմատային գրացուցակը տատանվում է կախված Puppet-ի տարբերակից և օգտագործվող միջավայրերից: Միջավայրերը կոնֆիգուրացիայի անկախ հավաքածուներ են, որոնք պահվում են առանձին գրացուցակներում: Սովորաբար օգտագործվում է git-ի հետ համատեղ, որի դեպքում միջավայրերը ստեղծվում են git ճյուղերից։ Համապատասխանաբար, յուրաքանչյուր հանգույց գտնվում է այս կամ այն ​​միջավայրում: Սա կարող է կազմաձևվել բուն հանգույցում կամ ENC-ում, որի մասին ես կխոսեմ հաջորդ հոդվածում:

  • Երրորդ տարբերակում («հին տիկնիկային») բազային գրացուցակը եղել է /etc/puppet. Միջավայրերի օգտագործումը կամընտիր է, օրինակ, մենք դրանք չենք օգտագործում հին Տիկնիկի հետ: Եթե ​​օգտագործվում են միջավայրեր, դրանք սովորաբար պահվում են /etc/puppet/environments, արմատային գրացուցակը կլինի շրջակա միջավայրի գրացուցակը: Եթե ​​միջավայրերը չեն օգտագործվում, արմատային գրացուցակը կլինի հիմնական գրացուցակը:
  • Սկսած չորրորդ տարբերակից («նոր տիկնիկային») միջավայրերի օգտագործումը դարձավ պարտադիր, և բազային գրացուցակը տեղափոխվեց. /etc/puppetlabs/code. Համապատասխանաբար, միջավայրերը պահվում են /etc/puppetlabs/code/environments, արմատային գրացուցակը շրջակա միջավայրի գրացուցակն է:

Արմատային գրացուցակում պետք է լինի ենթացուցակ manifests, որը պարունակում է հանգույցները նկարագրող մեկ կամ մի քանի մանիֆեստներ։ Բացի այդ, պետք է լինի ենթատեղեկատու modules, որը պարունակում է մոդուլներ։ Թե ինչ մոդուլներ կան, կասեմ մի փոքր ուշ: Բացի այդ, հին Տիկնիկը կարող է ունենալ նաև ենթատեղեկատու files, որը պարունակում է տարբեր ֆայլեր, որոնք մենք պատճենում ենք հանգույցներում։ Նոր Puppet-ում բոլոր ֆայլերը տեղադրվում են մոդուլներում:

Manifest ֆայլերն ունեն ընդլայնում .pp.

Մի երկու մարտական ​​օրինակ

Հանգույցի և դրա վրա գտնվող ռեսուրսի նկարագրությունը

Հանգույցի վրա server1.testdomain պետք է ստեղծվի ֆայլ /etc/issue բովանդակությամբ Debian GNU/Linux n l. Ֆայլը պետք է պատկանի օգտագործողին և խմբին root, մուտքի իրավունքները պետք է լինեն 644.

Մենք գրում ենք մանիֆեստ.

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

Հանգույցի վրա ռեսուրսների միջև հարաբերությունները

Հանգույցի վրա server2.testdomain nginx-ը պետք է գործարկվի՝ աշխատելով նախկինում պատրաստված կոնֆիգուրացիայի հետ:

Եկեք տարանջատենք խնդիրը.

  • Փաթեթը պետք է տեղադրվի nginx.
  • Անհրաժեշտ է, որ կազմաձևման ֆայլերը պատճենվեն սերվերից:
  • Ծառայությունը պետք է գործարկվի nginx.
  • Եթե ​​կոնֆիգուրացիան թարմացվի, ծառայությունը պետք է վերագործարկվի:

Մենք գրում ենք մանիֆեստ.

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

Որպեսզի դա աշխատի, ձեզ անհրաժեշտ է մոտավորապես հետևյալ ֆայլի գտնվելու վայրը տիկնիկային սերվերի վրա.

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

Ռեսուրսների տեսակները

Աջակցվող ռեսուրսների տեսակների ամբողջական ցանկը կարող եք գտնել այստեղ փաստաթղթերում, այստեղ ես նկարագրելու եմ հինգ հիմնական տեսակներ, որոնք իմ պրակտիկայում բավարար են խնդիրների մեծ մասը լուծելու համար։

ֆայլ

Կառավարում է ֆայլերը, գրացուցակները, սիմհղումները, դրանց բովանդակությունը և մուտքի իրավունքները:

Պարամետրեր.

  • ռեսուրսի անվանումը - ֆայլի ուղի (ըստ ցանկության)
  • ճանապարհ — ֆայլի ուղին (եթե այն նշված չէ անվանման մեջ)
  • ապահովել - ֆայլի տեսակը:
    • absent - ջնջել ֆայլը
    • present — պետք է լինի ցանկացած տեսակի ֆայլ (եթե ֆայլ չկա, կստեղծվի սովորական ֆայլ)
    • file - սովորական ֆայլ
    • directory - գրացուցակ
    • link - սիմվոլիկ
  • պարունակություն — ֆայլի բովանդակությունը (հարմար է միայն սովորական ֆայլերի համար, չի կարող օգտագործվել դրա հետ միասին աղբյուր կամ թիրախ)
  • աղբյուր — հղում դեպի այն ուղին, որտեղից ցանկանում եք պատճենել ֆայլի բովանդակությունը (չի կարող օգտագործվել հետ միասին պարունակություն կամ թիրախ) Կարող է նշվել որպես սխեմայով URI puppet: (այնուհետև կօգտագործվեն տիկնիկային սերվերի ֆայլերը), և սխեմայով http: (Հուսով եմ, որ պարզ է, թե ինչ կլինի այս դեպքում), և նույնիսկ գծապատկերով file: կամ որպես բացարձակ ուղի առանց սխեմայի (այնուհետև կօգտագործվի հանգույցի տեղական FS ֆայլը)
  • թիրախ — որտեղ պետք է մատնանշվի սիմհղակը (չի կարող օգտագործվել հետ միասին պարունակություն կամ աղբյուր)
  • սեփականատեր - օգտատերը, ով պետք է տիրապետի ֆայլին
  • խումբ — խումբը, որին պետք է պատկանի ֆայլը
  • ռեժիմ — ֆայլի թույլտվություններ (որպես տող)
  • վերականգնել - հնարավորություն է տալիս ռեկուրսիվ գրացուցակի մշակումը
  • զտել - հնարավորություն է տալիս ջնջել այն ֆայլերը, որոնք նկարագրված չեն Puppet-ում
  • ստիպել - հնարավորություն է տալիս ջնջել դիրեկտորիաները, որոնք նկարագրված չեն Puppet-ում

փաթեթ

Տեղադրում և հեռացնում է փաթեթները: Ծանուցումներին կառավարելու ունակություն - վերատեղադրում է փաթեթը, եթե պարամետրը նշված է reinstall_on_refresh.

Պարամետրեր.

  • ռեսուրսի անվանումը - փաթեթի անվանումը (ըստ ցանկության)
  • անուն - փաթեթի անվանումը (եթե անվանման մեջ նշված չէ)
  • մատակարար - փաթեթի կառավարիչ օգտագործելու համար
  • ապահովել - փաթեթի ցանկալի վիճակը.
    • present, installed - տեղադրված ցանկացած տարբերակ
    • latest - տեղադրված է վերջին տարբերակը
    • absent - ջնջված է (apt-get remove)
    • purged — ջնջվել է կազմաձևման ֆայլերի հետ միասին (apt-get purge)
    • held - փաթեթի տարբերակը կողպված է (apt-mark hold)
    • любая другая строка — նշված տարբերակը տեղադրված է
  • reinstall_on_refresh - եթե true, ապա ծանուցումը ստանալուց հետո փաթեթը կվերատեղադրվի։ Օգտակար է աղբյուրի վրա հիմնված բաշխումների համար, որտեղ կառուցման պարամետրերը փոխելու ժամանակ կարող է անհրաժեշտ լինել փաթեթների վերակառուցում: Կանխադրված false.

ծառայություն

Կառավարում է ծառայությունները: Հնարավորություն է մշակել ծանուցումները - վերագործարկում է ծառայությունը:

Պարամետրեր.

  • ռեսուրսի անվանումը — կառավարվող ծառայություն (ըստ ցանկության)
  • անուն — ծառայությունը, որը պետք է կառավարվի (եթե անվանման մեջ նշված չէ)
  • ապահովել — ծառայության ցանկալի վիճակը.
    • running - գործարկվել է
    • stopped - կանգ առավ
  • հնարավորություն — վերահսկում է ծառայությունը սկսելու հնարավորությունը.
    • true — autorun-ը միացված է (systemctl enable)
    • mask - քողարկված (systemctl mask)
    • false — autorun-ը անջատված է (systemctl disable)
  • մեքենայական ծրագրի կրկնական գործարկումը - ծառայությունը վերագործարկելու հրաման
  • կարգավիճակ — ծառայության կարգավիճակը ստուգելու հրաման
  • hasrestart — նշեք, թե արդյոք ծառայության սկզբնագիրն աջակցում է վերագործարկմանը: Եթե false և պարամետրը նշված է մեքենայական ծրագրի կրկնական գործարկումը - օգտագործվում է այս պարամետրի արժեքը: Եթե false և պարամետր մեքենայական ծրագրի կրկնական գործարկումը նշված չէ - ծառայությունը դադարեցվել է և սկսվել է վերագործարկվել (բայց systemd-ն օգտագործում է հրամանը systemctl restart).
  • վիճակ — նշեք, թե արդյոք ծառայության սկզբնագիրն աջակցում է հրամանին status. Եթե false, ապա օգտագործվում է պարամետրի արժեքը կարգավիճակ. Կանխադրված true.

exec

Գործարկում է արտաքին հրամաններ: Եթե ​​դուք պարամետրեր չեք նշում ստեղծում, միայն եթե, եթե կամ թարմացնելով, հրամանը կգործարկվի ամեն անգամ, երբ Puppet-ը գործարկվի: Կարող է մշակել ծանուցումները - գործարկում է հրաման:

Պարամետրեր.

  • ռեսուրսի անվանումը - հրաման, որը պետք է կատարվի (ըստ ցանկության)
  • հրաման - հրամանը, որը պետք է կատարվի (եթե այն նշված չէ անվանման մեջ)
  • ճանապարհ — ուղիները, որոնցով կարելի է փնտրել գործարկվող ֆայլը
  • միայն եթե - եթե այս պարամետրում նշված հրամանը լրացված է զրոյական վերադարձի կոդով, հիմնական հրամանը կկատարվի
  • եթե — եթե այս պարամետրում նշված հրամանը լրացված է ոչ զրոյական վերադարձի կոդով, ապա հիմնական հրամանը կկատարվի
  • ստեղծում — եթե այս պարամետրում նշված ֆայլը գոյություն չունի, հիմնական հրամանը կկատարվի
  • թարմացնելով - եթե true, ապա հրամանը կգործարկվի միայն այն ժամանակ, երբ այս exec-ը ծանուցում ստանա այլ ռեսուրսներից
  • cwd — գրացուցակ, որտեղից պետք է գործարկել հրամանը
  • Տեղ - օգտվողը, ումից պետք է գործարկել հրամանը
  • մատակարար - ինչպես գործարկել հրամանը.
    • պոզիք — պարզապես ստեղծվել է երեխայի պրոցես, անպայման նշեք ճանապարհ
    • կլպել - հրամանը գործարկվում է պատյանում /bin/sh, չի կարող նշված լինել ճանապարհ, կարող եք օգտագործել գլոբբինգ, խողովակներ և կեղևի այլ առանձնահատկություններ: Սովորաբար ինքնաբերաբար հայտնաբերվում է, եթե կան հատուկ նիշեր (|, ;, &&, || և այլն):

cron

Վերահսկում է cronjob-երը:

Պարամետրեր.

  • ռեսուրսի անվանումը - պարզապես ինչ-որ նույնացուցիչ
  • ապահովել - թագի վիճակ.
    • present - ստեղծել, եթե գոյություն չունի
    • absent - ջնջել, եթե կա
  • հրաման - ինչ հրաման գործարկել
  • միջավայր — որ միջավայրում գործարկել հրամանը (միջավայրի փոփոխականների ցանկը և դրանց արժեքները =)
  • Տեղ — որ օգտագործողից գործարկել հրամանը
  • րոպե, ժամ, աշխատանքային օր, ամիս, ամսվա օր — երբ գործարկել cron. Եթե ​​նշված հատկանիշներից որևէ մեկը նշված չէ, ապա դրա արժեքը crontab-ում կլինի *.

Տիկնիկային 6.0-ում cron ասես հանվել է տուփից puppetserver-ում, ուստի ընդհանուր կայքում ոչ մի փաստաթուղթ չկա: Բայց նա տուփի մեջ է տիկնիկային-գործակալում, այնպես որ առանձին տեղադրելու կարիք չկա: Դուք կարող եք տեսնել դրա համար նախատեսված փաստաթղթերը Puppet-ի հինգերորդ տարբերակի փաստաթղթերումԿամ GitHub-ում.

Ընդհանուր ռեսուրսների մասին

Պահանջներ ռեսուրսների եզակիության համար

Ամենատարածված սխալը, որին մենք հանդիպում ենք Կրկնօրինակ հայտարարություն. Այս սխալն առաջանում է, երբ գրացուցակում հայտնվում են նույն տեսակի երկու կամ ավելի ռեսուրսներ՝ նույն անունով:

Ուստի նորից գրեմ. նույն հանգույցի մանիֆեստները չպետք է պարունակեն նույն տեսակի ռեսուրսներ՝ նույն վերնագրով:

Երբեմն անհրաժեշտություն է առաջանում տեղադրել նույն անունով փաթեթներ, բայց տարբեր փաթեթների կառավարիչներով: Այս դեպքում դուք պետք է օգտագործեք պարամետրը nameսխալից խուսափելու համար.

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

Ռեսուրսների այլ տեսակներ ունեն նմանատիպ տարբերակներ, որոնք կօգնեն խուսափել կրկնօրինակումից − name у ծառայություն, command у exec, և այլն։

Մետապարամետրեր

Ռեսուրսի յուրաքանչյուր տեսակ ունի որոշ հատուկ պարամետրեր՝ անկախ դրա բնույթից:

Մետա պարամետրերի ամբողջական ցանկը Տիկնիկային փաստաթղթերում.

Կարճ ցուցակ.

  • պահանջել — այս պարամետրը ցույց է տալիս, թե որ ռեսուրսներից է կախված այս ռեսուրսը:
  • մինչեւ - Այս պարամետրը սահմանում է, թե որ ռեսուրսներն են կախված այս ռեսուրսից:
  • Բաժանորդագրվել — այս պարամետրը սահմանում է, թե որ ռեսուրսներից է այս ռեսուրսը ստանում ծանուցումներ:
  • տեղեկացնել — Այս պարամետրը սահմանում է, թե որ ռեսուրսներն են ստանում ծանուցումներ այս ռեսուրսից:

Թվարկված բոլոր մետապարամետրերն ընդունում են կա՛մ մեկ ռեսուրսային հղում, կա՛մ քառակուսի փակագծերում գտնվող հղումների զանգված:

Հղումներ ռեսուրսներին

Ռեսուրսի հղումը պարզապես ռեսուրսի հիշատակումն է: Դրանք հիմնականում օգտագործվում են կախվածությունը ցույց տալու համար։ Գոյություն չունեցող ռեսուրսի հղումը կառաջացնի կոմպիլյացիայի սխալ:

Հղման շարահյուսությունը հետևյալն է. ռեսուրսի տեսակը մեծատառով (եթե տիպի անվանումը պարունակում է կրկնակի երկու կետ, ապա երկու կետի միջև ընկած անվան յուրաքանչյուր մասը գրված է մեծատառով), ապա ռեսուրսի անվանումը քառակուսի փակագծերում (անունի դեպքը): չի փոխվում): Բացատներ չպետք է լինեն, քառակուսի փակագծերը գրվում են տիպի անունից անմիջապես հետո:

Example:

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

Կախվածություններ և ծանուցումներ

Փաստաթղթերն այստեղ:

Ինչպես նշվեց ավելի վաղ, ռեսուրսների միջև պարզ կախվածությունը անցողիկ է: Ի դեպ, զգույշ եղեք կախվածություններ ավելացնելիս. կարող եք ստեղծել ցիկլային կախվածություններ, ինչը կառաջացնի կոմպիլացիոն սխալ։

Ի տարբերություն կախվածության, ծանուցումները անցումային չեն: Ծանուցումների համար կիրառվում են հետևյալ կանոնները.

  • Եթե ​​ռեսուրսը ծանուցում է ստանում, այն թարմացվում է: Թարմացման գործողությունները կախված են ռեսուրսի տեսակից − exec գործարկում է հրամանը, ծառայություն վերսկսում է ծառայությունը, փաթեթ վերատեղադրում է փաթեթը: Եթե ​​ռեսուրսը չունի թարմացման գործողություն սահմանված, ապա ոչինչ չի պատահում:
  • Puppet-ի մեկ գործարկման ընթացքում ռեսուրսը թարմացվում է ոչ ավելի, քան մեկ անգամ: Դա հնարավոր է, քանի որ ծանուցումները ներառում են կախվածություններ, իսկ կախվածության գրաֆիկը չի պարունակում ցիկլեր:
  • Եթե ​​Puppet-ը փոխում է ռեսուրսի վիճակը, ռեսուրսը ծանուցումներ է ուղարկում դրան բաժանորդագրված բոլոր ռեսուրսներին:
  • Եթե ​​ռեսուրսը թարմացվում է, այն ծանուցումներ է ուղարկում դրան բաժանորդագրված բոլոր ռեսուրսներին:

Չճշտված պարամետրերի կառավարում

Որպես կանոն, եթե ռեսուրսի որոշ պարամետր չունի լռելյայն արժեք, և այս պարամետրը նշված չէ մանիֆեստում, ապա Puppet-ը չի փոխի այս հատկությունը հանգույցի համապատասխան ռեսուրսի համար։ Օրինակ, եթե տեսակի ռեսուրս ֆայլ պարամետրը նշված չէ owner, ապա Puppet-ը չի փոխի համապատասխան ֆայլի տիրոջը։

Դասերի, փոփոխականների և սահմանումների ներածություն

Ենթադրենք, որ մենք ունենք մի քանի հանգույց, որոնք ունեն կոնֆիգուրացիայի նույն մասը, բայց կան նաև տարբերություններ, հակառակ դեպքում մենք կարող ենք նկարագրել այդ ամենը մեկ բլոկում: node {}. Իհարկե, դուք կարող եք պարզապես պատճենել կոնֆիգուրացիայի նույնական մասերը, բայց ընդհանուր առմամբ սա վատ լուծում է. կոնֆիգուրացիան աճում է, և եթե փոխեք կոնֆիգուրացիայի ընդհանուր մասը, ապա ստիպված կլինեք նույն բանը խմբագրել շատ տեղերում: Միևնույն ժամանակ, հեշտ է սխալվել, և ընդհանրապես, DRY (մի կրկնվես) սկզբունքը հորինվել է մի պատճառով:

Այս խնդիրը լուծելու համար կա այնպիսի դիզայն, ինչպիսին է դաս.

Դասեր

Դաս poppet կոդի անվանված բլոկ է: Կոդը նորից օգտագործելու համար անհրաժեշտ են դասեր:

Նախ պետք է նկարագրել դասը: Նկարագրությունն ինքնին ոչ մի տեղ որևէ ռեսուրս չի ավելացնում: Դասը նկարագրված է մանիֆեստներով.

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

Դրանից հետո դասը կարող է օգտագործվել.

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

Օրինակ նախորդ առաջադրանքից. եկեք տեղափոխենք nginx-ի տեղադրումն ու կազմաձևումը դասի մեջ.

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
}

Փոփոխականներ

Նախորդ օրինակի դասը ընդհանրապես ճկուն չէ, քանի որ այն միշտ բերում է նույն nginx կոնֆիգուրացիան: Եկեք դարձնենք կոնֆիգուրացիայի փոփոխականի ուղին, այնուհետև այս դասը կարող է օգտագործվել ցանկացած կոնֆիգուրացիայով nginx-ը տեղադրելու համար։

Դա կարելի է անել օգտագործելով փոփոխականներ.

Ուշադրություն. Puppet-ի փոփոխականներն անփոփոխ են:

Բացի այդ, փոփոխականին կարելի է մուտք գործել միայն այն հայտարարելուց հետո, հակառակ դեպքում փոփոխականի արժեքը կլինի undef.

Փոփոխականների հետ աշխատելու օրինակ.

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

Տիկնիկն ունի անունների տարածքներ, իսկ փոփոխականները, համապատասխանաբար, ունեն տեսանելիության տարածքՆույն անունով փոփոխականը կարող է սահմանվել տարբեր անվանատարածքներում: Փոփոխականի արժեքը լուծելիս փոփոխականը որոնվում է ներկայիս անվանատարածքում, այնուհետև կից անվանատարածքում և այլն։

Անվան տարածության օրինակներ.

  • գլոբալ - դասի կամ հանգույցի նկարագրությունից դուրս փոփոխականները գնում են այնտեղ;
  • հանգույցի անվանատարածք հանգույցի նկարագրության մեջ;
  • դասի անվանատարածք դասի նկարագրության մեջ:

Փոփոխական մուտք գործելիս երկիմաստությունից խուսափելու համար կարող եք փոփոխականի անվանման մեջ նշել անվանատարածքը.

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

Եկեք համաձայնենք, որ nginx կոնֆիգուրացիայի ճանապարհը գտնվում է փոփոխականում $nginx_conf_source. Այնուհետև դասը կունենա հետևյալ տեսքը.

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
}

Այնուամենայնիվ, բերված օրինակը վատ է, քանի որ կա որոշակի «գաղտնի գիտելիք», որ դասի ներսում ինչ-որ տեղ օգտագործվում է այսինչ անունով փոփոխական: Շատ ավելի ճիշտ է այս գիտելիքը դարձնել ընդհանուր՝ դասերը կարող են ունենալ պարամետրեր։

Դասի պարամետրերը փոփոխականներ են դասի անվանատարածքում, դրանք նշված են դասի վերնագրում և կարող են օգտագործվել դասի մարմնի սովորական փոփոխականների նման: Պարամետրերի արժեքները նշվում են մանիֆեստում դասը օգտագործելիս:

Պարամետրը կարող է սահմանվել լռելյայն արժեքի: Եթե ​​պարամետրը չունի լռելյայն արժեք, և արժեքը սահմանված չէ, երբ օգտագործվում է, դա կառաջացնի կոմպիլյացիայի սխալ:

Եկեք պարամետրացնենք դասը վերևի օրինակից և ավելացնենք երկու պարամետր. առաջինը, պահանջվում է, կոնֆիգուրացիայի ուղին է, իսկ երկրորդը, ըստ ցանկության, փաթեթի անունն է nginx-ով (օրինակ, Debian-ում կան փաթեթներ. 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',   # задаём параметры класса точно так же, как параметры для других ресурсов
  }
}

Puppet-ում փոփոխականները տպագրվում են: Ուտել տվյալների բազմաթիվ տեսակներ. Տվյալների տեսակները սովորաբար օգտագործվում են դասերին և սահմանումներին փոխանցված պարամետրերի արժեքները վավերացնելու համար: Եթե ​​անցած պարամետրը չի համընկնում նշված տեսակի հետ, կառաջանա կոմպիլյացիայի սխալ:

Տեսակը գրված է պարամետրի անունից անմիջապես առաջ.

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

Դասեր՝ ներառել classname ընդդեմ class{'classname':}

Յուրաքանչյուր դաս տիպի ռեսուրս է դաս. Ինչպես ցանկացած այլ տեսակի ռեսուրս, չի կարող լինել նույն դասի երկու օրինակ նույն հանգույցում:

Եթե ​​փորձեք նույն հանգույցին դաս ավելացնել երկու անգամ՝ օգտագործելով class { 'classname':} (տարբերություն չկա, տարբեր կամ նույնական պարամետրերով), կլինի կազմման սխալ: Բայց եթե դուք օգտագործում եք դասը ռեսուրսի ոճով, կարող եք անմիջապես բացահայտորեն սահմանել դրա բոլոր պարամետրերը մանիֆեստում:

Այնուամենայնիվ, եթե դուք օգտագործում եք include, ապա դասը կարող է ավելացվել այնքան անգամ, որքան ցանկանաք: Փաստն այն է, որ include idempotent ֆունկցիա է, որը ստուգում է, թե արդյոք դաս է ավելացվել գրացուցակում: Եթե ​​դասը գրացուցակում չէ, այն ավելացնում է, իսկ եթե արդեն գոյություն ունի, ոչինչ չի անում։ Բայց օգտագործման դեպքում include Դուք չեք կարող դասի պարամետրեր սահմանել դասի հայտարարման ժամանակ. բոլոր պահանջվող պարամետրերը պետք է տեղադրվեն արտաքին տվյալների աղբյուրում՝ Hiera կամ ENC: Նրանց մասին կխոսենք հաջորդ հոդվածում։

Սահմանում է

Ինչպես ասվեց նախորդ բլոկում, նույն դասը չի կարող մեկից ավելի անգամ ներկա լինել հանգույցի վրա: Այնուամենայնիվ, որոշ դեպքերում դուք պետք է կարողանաք օգտագործել նույն հանգույցի տարբեր պարամետրերով կոդի նույն բլոկը: Այսինքն՝ կա ռեսուրսի սեփական տեսակի կարիք։

Օրինակ, PHP մոդուլը տեղադրելու համար Avito-ում անում ենք հետևյալը.

  1. Տեղադրեք փաթեթը այս մոդուլով:
  2. Եկեք ստեղծենք կազմաձևման ֆայլ այս մոդուլի համար:
  3. Մենք ստեղծում ենք php-fpm կոնֆիգուրայի սիմհղում:
  4. Մենք ստեղծում ենք php cli կոնֆիգուրայի սիմվոլիկ:

Նման դեպքերում այնպիսի դիզայն, ինչպիսին է սահմանել (սահմանել, սահմանված տեսակ, սահմանված ռեսուրսի տեսակ): A Define-ը նման է դասի, բայց կան տարբերություններ. նախ՝ յուրաքանչյուր Define ռեսուրսի տեսակ է, ոչ թե ռեսուրս; երկրորդ, յուրաքանչյուր սահմանում ունի ենթադրյալ պարամետր $title, որտեղ նշվում է ռեսուրսի անունը, երբ այն հայտարարվում է: Ինչպես դասերի դեպքում, նախ պետք է նկարագրել սահմանումը, որից հետո այն կարող է օգտագործվել։

Պարզեցված օրինակ 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' }
}

Կրկնօրինակ հայտարարագրման սխալը հայտնաբերելու ամենահեշտ ձևը Սահմանելն է: Դա տեղի է ունենում, եթե սահմանումն ունի հաստատուն անունով ռեսուրս, և կան այս սահմանման երկու կամ ավելի օրինակներ ինչ-որ հանգույցում:

Հեշտ է պաշտպանվել ձեզ դրանից. սահմանման ներսում գտնվող բոլոր ռեսուրսները պետք է ունենան անուն՝ կախված նրանից $title. Այլընտրանքը ռեսուրսների անիմաստ ավելացումն է, ամենապարզ դեպքում բավական է սահմանման բոլոր ատյանների համար ընդհանուր ռեսուրսները տեղափոխել առանձին դաս և ներառել այս դասը սահմանման մեջ՝ ֆունկցիա: include անզոր.

Ռեսուրսներ ավելացնելիս անզորության հասնելու այլ եղանակներ կան, մասնավորապես՝ ֆունկցիաների օգտագործումը defined и ensure_resources, բայց ես ձեզ այդ մասին կպատմեմ հաջորդ դրվագում։

Կախվածություններ և ծանուցումներ դասերի և սահմանումների համար

Դասերը և սահմանումները ավելացնում են հետևյալ կանոնները կախվածությունների և ծանուցումների հետ աշխատելու համար.

  • կախվածությունը դասից/սահմանում ավելացնում է կախվածություն դասի/սահմանման բոլոր ռեսուրսներից.
  • դասի/սահմանելու կախվածությունը կախվածություն է ավելացնում բոլոր դասի/սահմանելու ռեսուրսներին.
  • class/define ծանուցումը տեղեկացնում է դասի/սահմանման բոլոր ռեսուրսներին;
  • class/define բաժանորդագրությունը բաժանորդագրվում է դասի/սահմանման բոլոր ռեսուրսներին:

Պայմանական հայտարարություններ և ընտրիչներ

Փաստաթղթերն այստեղ:

if

Այստեղ պարզ է.

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

եթե

եթե եթե հակառակը չէ. կոդի բլոկը կկատարվի, եթե արտահայտությունը կեղծ է:

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

դեպք

Այստեղ էլ ոչ մի բարդ բան չկա։ Որպես արժեքներ կարող եք օգտագործել կանոնավոր արժեքներ (տողեր, թվեր և այլն), կանոնավոր արտահայտություններ և տվյալների տեսակներ:

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

Ընտրիչներ

Ընտրիչը լեզվական կառուցվածք է, որը նման է case, բայց կոդի բլոկ գործարկելու փոխարեն այն վերադարձնում է արժեք։

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

Մոդուլներ

Երբ կոնֆիգուրացիան փոքր է, այն հեշտությամբ կարելի է պահել մեկ մանիֆեստում: Բայց որքան շատ կոնֆիգուրացիաներ ենք նկարագրում, այնքան ավելի շատ դասեր և հանգույցներ կան մանիֆեստում, այն մեծանում է և անհարմար է դառնում աշխատելը:

Բացի այդ, կա կոդի վերօգտագործման խնդիր. երբ ամբողջ կոդը գտնվում է մեկ մանիֆեստում, դժվար է այս ծածկագիրը կիսել ուրիշների հետ: Այս երկու խնդիրները լուծելու համար Puppet-ն ունի մի էություն, որը կոչվում է մոդուլներ:

Մոդուլներ - սրանք դասերի, սահմանումների և այլ տիկնիկային միավորների հավաքածուներ են, որոնք տեղադրված են առանձին գրացուցակում: Այլ կերպ ասած, մոդուլը Տիկնիկային տրամաբանության անկախ մասն է: Օրինակ, կարող է լինել nginx-ի հետ աշխատելու մոդուլ, և այն պարունակի այն, ինչ և միայն այն, ինչ անհրաժեշտ է nginx-ի հետ աշխատելու համար, կամ կարող է լինել PHP-ի հետ աշխատելու մոդուլ և այլն։

Մոդուլները տարբերակված են, և մոդուլների միմյանցից կախվածությունը նույնպես ապահովված է: Կա մոդուլների բաց պահոց. Տիկնիկային Դարբնոց.

Տիկնիկային սերվերի վրա մոդուլները տեղակայված են արմատային գրացուցակի մոդուլների ենթագրքում: Յուրաքանչյուր մոդուլի ներսում կա գրացուցակի ստանդարտ սխեման՝ մանիֆեստներ, ֆայլեր, կաղապարներ, lib և այլն:

Ֆայլի կառուցվածքը մոդուլում

Մոդուլի արմատը կարող է պարունակել նկարագրական անուններով հետևյալ գրացուցակները.

  • manifests - այն պարունակում է մանիֆեստներ
  • files - այն պարունակում է ֆայլեր
  • templates - այն պարունակում է կաղապարներ
  • lib - այն պարունակում է Ruby կոդը

Սա դիրեկտորիաների և ֆայլերի ամբողջական ցանկ չէ, բայց այս հոդվածի համար առայժմ բավարար է։

Մոդուլի ռեսուրսների և ֆայլերի անունները

Փաստաթղթերն այստեղ:

Մոդուլի ռեսուրսները (դասեր, սահմանումներ) չեն կարող անվանվել այնպես, ինչպես ցանկանում եք: Բացի այդ, կա ուղիղ համապատասխանություն ռեսուրսի անվան և ֆայլի անվան միջև, որում Puppet-ը կփնտրի այդ ռեսուրսի նկարագրությունը: Եթե ​​դուք խախտում եք անվանման կանոնները, ապա Puppet-ը պարզապես չի գտնի ռեսուրսի նկարագրությունը, և դուք կստանաք կազմման սխալ:

Կանոնները պարզ են.

  • Մոդուլի բոլոր ռեսուրսները պետք է լինեն մոդուլի անվանման տարածքում: Եթե ​​մոդուլը կոչվում է foo, ապա դրա մեջ եղած բոլոր ռեսուրսները պետք է անվանվեն foo::<anything>, կամ պարզապես foo.
  • Մոդուլի անվանումով ռեսուրսը պետք է լինի ֆայլում init.pp.
  • Այլ ռեսուրսների համար ֆայլի անվանման սխեման հետևյալն է.
    • մոդուլի անվան հետ նախածանցը հանված է
    • բոլոր կրկնակի երկու կետերը, եթե այդպիսիք կան, փոխարինվում են շեղերով
    • ավելացվել է ընդլայնում .pp

Ես ցույց կտամ օրինակով. Ասենք՝ մոդուլ եմ գրում nginx. Այն պարունակում է հետևյալ ռեսուրսները.

  • դաս nginx նկարագրված է մանիֆեստում init.pp;
  • դաս nginx::service նկարագրված է մանիֆեստում service.pp;
  • սահմանել nginx::server նկարագրված է մանիֆեստում server.pp;
  • սահմանել nginx::server::location նկարագրված է մանիֆեստում server/location.pp.

Templates

Իհարկե, դուք ինքներդ գիտեք, թե ինչ կաղապարներ են, ես դրանք մանրամասն չեմ նկարագրի այստեղ: Բայց ամեն դեպքում կթողնեմ հղում դեպի Վիքիպեդիա.

Ինչպես օգտագործել կաղապարներ. Կաղապարի իմաստը կարելի է ընդլայնել՝ օգտագործելով ֆունկցիան template, որը փոխանցվում է կաղապարի ուղին։ Տիպի ռեսուրսների համար ֆայլ օգտագործվում է պարամետրի հետ միասին content. Օրինակ, այսպես.

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

Դիտել ուղին <modulename>/<filename> ենթադրում է ֆայլ <rootdir>/modules/<modulename>/templates/<filename>.

Բացի այդ, կա գործառույթ inline_template — այն ստանում է ձևանմուշի տեքստը որպես մուտքագրում, ոչ թե ֆայլի անվանումը:

Կաղապարների ներսում դուք կարող եք օգտագործել տիկնիկային բոլոր փոփոխականները ընթացիկ շրջանակում:

Puppet-ն աջակցում է ERB և EPP ձևաչափերի ձևանմուշներին.

Համառոտ ERB-ի մասին

Վերահսկիչ կառույցներ.

  • <%= ВЫРАЖЕНИЕ %> - մուտքագրեք արտահայտության արժեքը
  • <% ВЫРАЖЕНИЕ %> - հաշվարկել արտահայտության արժեքը (առանց այն մտցնելու): Պայմանական հայտարարությունները (եթե) և հանգույցները (յուրաքանչյուրը) սովորաբար գնում են այստեղ:
  • <%# КОММЕНТАРИЙ %>

ERB-ի արտահայտությունները գրված են Ruby-ով (ERB-ն իրականում Embedded Ruby է):

Մանիֆեստից փոփոխականներ մուտք գործելու համար անհրաժեշտ է ավելացնել @ փոփոխականի անվան նկատմամբ։ Վերահսկիչ կառուցվածքից հետո հայտնված տողերի ընդմիջումը հեռացնելու համար դուք պետք է օգտագործեք փակող պիտակ -%>.

Կաղապարի օգտագործման օրինակ

Ենթադրենք, ես մոդուլ եմ գրում ZooKeeper-ը կառավարելու համար: Կազմաձևի ստեղծման համար պատասխանատու դասը ունի հետևյալ տեսքը.

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

Եվ համապատասխան կաղապարը zoo.cfg.erb - Այսպիսով.

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

Փաստեր և ներկառուցված փոփոխականներ

Հաճախ կոնֆիգուրացիայի կոնկրետ մասը կախված է նրանից, թե ինչ է կատարվում տվյալ պահին հանգույցում: Օրինակ, կախված նրանից, թե որն է Debian թողարկումը, դուք պետք է տեղադրեք փաթեթի այս կամ այն ​​տարբերակը: Դուք կարող եք վերահսկել այս ամենը ձեռքով, վերաշարադրումը դրսևորվում է, եթե հանգույցները փոխվեն: Բայց սա լուրջ մոտեցում չէ, ավտոմատացումը շատ ավելի լավ է:

Հանգույցների մասին տեղեկատվություն ստանալու համար Փիփեթն ունի մեխանիզմ, որը կոչվում է փաստեր: փաստեր - սա հանգույցի մասին տեղեկատվություն է, որը հասանելի է մանիֆեստներում սովորական փոփոխականների տեսքով գլոբալ անվանատարածքում: Օրինակ՝ հոսթի անունը, օպերացիոն համակարգի տարբերակը, պրոցեսորի ճարտարապետությունը, օգտատերերի ցանկը, ցանցային միջերեսների և դրանց հասցեների ցուցակը և շատ ու շատ ավելին: Փաստերը հասանելի են մանիֆեստներում և կաղապարներում՝ որպես կանոնավոր փոփոխականներ:

Փաստերի հետ աշխատելու օրինակ.

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

Ֆորմալ ասած՝ փաստն ունի անուն (տող) և արժեք (առկա են տարբեր տեսակներ՝ տողեր, զանգվածներ, բառարաններ)։ Ուտել ներկառուցված փաստերի հավաքածու. Կարող եք նաև գրել ձեր սեփականը։ Փաստահավաքները նկարագրված են ինչպես գործառույթները Ruby-ումկամ ինչպես գործարկվող ֆայլեր. Փաստերը կարող են ներկայացվել նաև ձևով տեքստային ֆայլեր տվյալների հետ հանգույցների վրա.

Գործողության ընթացքում տիկնիկային գործակալը նախ պատճենում է բոլոր առկա փաստահավաքիչները pappetserver-ից դեպի հանգույց, որից հետո գործարկում է դրանք և ուղարկում հավաքագրված փաստերը սերվերին; Դրանից հետո սերվերը սկսում է կատալոգի կազմումը:

Փաստեր գործարկվող ֆայլերի տեսքով

Նման փաստերը տեղադրվում են գրացուցակի մոդուլներում facts.d. Իհարկե, ֆայլերը պետք է գործարկելի լինեն: Երբ գործարկվում է, նրանք պետք է տեղեկատվություն տան ստանդարտ արդյունքի կամ YAML կամ key=value ձևաչափով:

Մի մոռացեք, որ փաստերը վերաբերում են բոլոր հանգույցներին, որոնք վերահսկվում են poppet սերվերի կողմից, որի վրա տեղակայված է ձեր մոդուլը: Հետևաբար, սկրիպտում ստուգեք, որ համակարգն ունի ձեր փաստի աշխատանքի համար անհրաժեշտ բոլոր ծրագրերն ու ֆայլերը:

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

Ռուբինի փաստեր

Նման փաստերը տեղադրվում են գրացուցակի մոդուլներում 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

Տեքստային փաստեր

Նման փաստերը տեղադրվում են գրացուցակի հանգույցների վրա /etc/facter/facts.d հին Տիկնիկում կամ /etc/puppetlabs/facts.d նոր Տիկնիկում:

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

Հասնելով փաստերին

Փաստերին մոտենալու երկու եղանակ կա.

  • բառարանի միջոցով $facts: $facts['fqdn'];
  • օգտագործելով փաստի անունը որպես փոփոխականի անուն. $fqdn.

Ավելի լավ է բառարան օգտագործել $facts, կամ նույնիսկ ավելի լավ, նշեք գլոբալ անվանատարածքը ($::facts).

Ահա փաստաթղթի համապատասխան բաժինը.

Ներկառուցված փոփոխականներ

Բացի փաստերից, կա նաև որոշ փոփոխականներ, հասանելի է գլոբալ անվանումների տարածքում:

  • վստահելի փաստեր - փոփոխականներ, որոնք վերցված են հաճախորդի վկայականից (քանի որ վկայագիրը սովորաբար տրվում է poppet սերվերի վրա, գործակալը չի ​​կարող պարզապես վերցնել և փոխել իր վկայականը, ուստի փոփոխականները «վստահելի» են). վկայագրի անվանումը, անունը. հոսթ և տիրույթ, ընդլայնումներ վկայականից:
  • սերվերի փաստեր - փոփոխականներ՝ կապված սերվերի մասին տեղեկատվության հետ՝ տարբերակ, անվանում, սերվերի IP հասցե, միջավայր:
  • գործակալի փաստեր - փոփոխականներ ավելացված ուղղակիորեն տիկնիկային-գործակալի կողմից, և ոչ ըստ փաստարկի. վկայագրի անունը, գործակալի տարբերակը, տիկնիկային տարբերակը:
  • վարպետ փոփոխականներ - Pappetmaster փոփոխականներ (sic!): Դա մոտավորապես նույնն է, ինչ ներսում սերվերի փաստեր, գումարած կազմաձևման պարամետրի արժեքները հասանելի են:
  • կոմպիլյատոր փոփոխականներ — Կազմողի փոփոխականներ, որոնք տարբերվում են յուրաքանչյուր տիրույթում. ընթացիկ մոդուլի անվանումը և մոդուլի անվանումը, որով հասանելի է եղել ընթացիկ օբյեկտը: Դրանք կարող են օգտագործվել, օրինակ, ստուգելու համար, որ ձեր մասնավոր դասերը ուղղակիորեն չեն օգտագործվում այլ մոդուլներից:

Հավելում 1. ինչպե՞ս գործարկել և կարգաբերել այս ամենը:

Հոդվածը պարունակում էր տիկնիկային կոդի բազմաթիվ օրինակներ, բայց մեզ ընդհանրապես չէր ասում, թե ինչպես գործարկել այս կոդը: Դե, ես ինքս ինձ ուղղում եմ.

Գործակալը բավական է Puppet-ը գործարկելու համար, բայց շատ դեպքերում ձեզ նույնպես պետք է սերվեր:

Գործակալ

Առնվազն XNUMX-րդ տարբերակից սկսած՝ տիկնիկային-գործակալների փաթեթներ Տիկնիկների պաշտոնական շտեմարան պարունակում է բոլոր կախվածությունները (ռուբին և համապատասխան գոհարները), այնպես որ տեղադրման դժվարություններ չկան (ես խոսում եմ Debian-ի վրա հիմնված բաշխումների մասին. մենք չենք օգտագործում RPM-ի վրա հիմնված բաշխումներ):

Ամենապարզ դեպքում, տիկնիկային կոնֆիգուրացիան օգտագործելու համար բավական է գործարկել գործակալը առանց սերվերի ռեժիմով. պայմանով, որ տիկնիկային կոդը պատճենված է հանգույցում, գործարկել 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

Ավելի լավ է, իհարկե, կարգավորել սերվերը և գործարկել գործակալները հանգույցների վրա daemon ռեժիմով, այնուհետև կես ժամը մեկ անգամ նրանք կկիրառեն սերվերից ներբեռնված կոնֆիգուրացիան:

Դուք կարող եք ընդօրինակել աշխատանքի push մոդելը - գնացեք դեպի ձեզ հետաքրքրող հանգույցը և սկսեք sudo puppet agent -t. Բանալի -t (--test) իրականում ներառում է մի քանի տարբերակ, որոնք կարելի է առանձին միացնել: Այս տարբերակները ներառում են հետևյալը.

  • մի գործարկեք daemon ռեժիմով (ըստ լռելյայն, գործակալը սկսվում է daemon ռեժիմով);
  • կատալոգը կիրառելուց հետո անջատել (լռելյայն, գործակալը կշարունակի աշխատել և կիրառի կոնֆիգուրացիան յուրաքանչյուր կես ժամը մեկ անգամ);
  • գրել մանրամասն աշխատանքային մատյան;
  • ցույց տալ փոփոխությունները ֆայլերում:

Գործակալն ունի աշխատանքային ռեժիմ առանց փոփոխությունների. դուք կարող եք օգտագործել այն, երբ վստահ չեք, որ գրել եք ճիշտ կոնֆիգուրացիան և ցանկանում եք ստուգել, ​​թե կոնկրետ ինչ է փոխելու գործակալը շահագործման ընթացքում: Այս ռեժիմը միացված է պարամետրով --noop հրամանի տողում. sudo puppet agent -t --noop.

Բացի այդ, դուք կարող եք միացնել աշխատանքի վրիպազերծման մատյանը. դրանում տիկնիկը գրում է իր կատարած բոլոր գործողությունների մասին. այն ռեսուրսի մասին, որը ներկայումս մշակում է, այս ռեսուրսի պարամետրերի մասին, այն մասին, թե ինչ ծրագրեր է այն գործարկում: Իհարկե, սա պարամետր է --debug.

Սերվեր

Այս հոդվածում ես չեմ դիտարկի pappetserver-ի ամբողջական կարգավորումը և դրա վրա կոդի տեղակայումը, ես միայն կասեմ, որ տուփից դուրս կա սերվերի լիարժեք ֆունկցիոնալ տարբերակ, որը չի պահանջում լրացուցիչ կոնֆիգուրացիա փոքր թվով աշխատողների հետ աշխատելու համար: հանգույցներ (ասենք, մինչև հարյուր): Ավելի մեծ թվով հանգույցներ կպահանջեն թյունինգ. լռելյայնորեն, տիկնիկային սերվերը գործարկում է ոչ ավելի, քան չորս աշխատող, ավելի մեծ կատարողականության համար դուք պետք է ավելացնեք նրանց թիվը և մի մոռացեք ավելացնել հիշողության սահմանները, հակառակ դեպքում սերվերը ժամանակի մեծ մասը կհավաքի աղբը:

Կոդի տեղակայում. եթե դրա կարիքն ունեք արագ և հեշտությամբ, ապա նայեք (r10k-ում)[https://github.com/puppetlabs/r10k], փոքր տեղակայման համար այն պետք է բավականաչափ լինի։

Հավելված 2. Կոդավորման ուղեցույցներ

  1. Տեղադրեք ամբողջ տրամաբանությունը դասերի և սահմանումների մեջ:
  2. Դասերը և սահմանումները պահեք մոդուլներում, այլ ոչ թե հանգույցներում նկարագրող մանիֆեստներում:
  3. Օգտագործեք փաստերը.
  4. Եթե-ներ մի արեք՝ հիմնվելով հյուրընկալողների անունների վրա:
  5. Ազատորեն ավելացրեք պարամետրեր դասերի և սահմանումների համար. սա ավելի լավ է, քան դասի մարմնում թաքնված անուղղակի տրամաբանությունը/սահմանումը:

Ես կբացատրեմ, թե ինչու եմ խորհուրդ տալիս դա անել հաջորդ հոդվածում:

Ամփոփում

Ավարտենք ներածությամբ: Հաջորդ հոդվածում ես ձեզ կպատմեմ Hiera-ի, ENC-ի և PuppetDB-ի մասին:

Հարցմանը կարող են մասնակցել միայն գրանցված օգտվողները։ Մուտք գործել, խնդրում եմ:

Իրականում շատ ավելի շատ նյութ կա. ես կարող եմ հոդվածներ գրել հետևյալ թեմաներով, քվեարկել այն մասին, թե ինչի մասին կհետաքրքրի ձեզ կարդալ.

  • 59,1%Ընդլայնված տիկնիկային կոնստրուկցիաներ. հաջորդ մակարդակի որոշ խայտառակություններ. օղակներ, քարտեզագրում և այլ լամբդա արտահայտություններ, ռեսուրսների հավաքիչներ, արտահանվող ռեսուրսներ և միջհյուրընկալող հաղորդակցություն Puppet-ի, պիտակների, մատակարարների, վերացական տվյալների տեսակների միջոցով:13
  • 31,8%«Ես մորս ադմին եմ» կամ ինչպես մենք Avito-ում ընկերացանք տարբեր տարբերակների մի քանի poppet սերվերների հետ, և, սկզբունքորեն, poppet սերվերի կառավարման մասին:
  • 81,8%Ինչպես ենք գրում տիկնիկային կոդը՝ գործիքավորում, փաստաթղթեր, թեստավորում, CI/CD.18

Քվեարկել է 22 օգտատեր։ 9 օգտատեր ձեռնպահ է մնացել։

Source: www.habr.com