Kuklaya Giriş

Puppet bir konfigürasyon yönetim sistemidir. Konakçıları istenilen duruma getirmek ve bu durumu korumak için kullanılır.

Beş yılı aşkın bir süredir Puppet'la çalışıyorum. Bu metin esasen resmi belgelerdeki önemli noktaların çevrilmiş ve yeniden düzenlenmiş bir derlemesidir ve yeni başlayanların Puppet'ın özünü hızlı bir şekilde anlamalarını sağlayacaktır.

Kuklaya Giriş

Temel bilgiler

Puppet'ın işletim sistemi istemci-sunucudur, ancak aynı zamanda sınırlı işlevsellikle sunucusuz çalışmayı da destekler.

Çekme işlemi modeli kullanılır: Varsayılan olarak, her yarım saatte bir, istemciler bir yapılandırma için sunucuyla iletişime geçer ve bunu uygular. Ansible ile çalıştıysanız farklı bir push modeli kullanırlar: Yönetici yapılandırmayı uygulama sürecini başlatır, istemcilerin kendisi hiçbir şey uygulamaz.

Ağ iletişimi sırasında iki yönlü TLS şifrelemesi kullanılır: sunucu ve istemcinin kendi özel anahtarları ve ilgili sertifikaları vardır. Tipik olarak sunucu, istemciler için sertifikalar verir, ancak prensipte harici bir CA kullanmak mümkündür.

Manifestolara giriş

Kukla terminolojisinde kukla sunucusuna bağlamak düğümler (düğümler). Düğümlerin konfigürasyonu yazılmıştır manifestolarda özel bir programlama dilinde - Puppet DSL.

Puppet DSL bildirimsel bir dildir. Düğümün istenen durumunu bireysel kaynakların bildirimleri şeklinde açıklar, örneğin:

  • Dosya mevcut ve belirli bir içeriğe sahip.
  • Paket kurulur.
  • Servis başladı.

Kaynaklar birbirine bağlanabilir:

  • Bağımlılıklar vardır ve kaynakların kullanım sırasını etkilerler.
    Örneğin, "önce paketi kurun, ardından yapılandırma dosyasını düzenleyin, ardından hizmeti başlatın."
  • Bildirimler var; bir kaynak değiştiyse, kendisine abone olan kaynaklara bildirim gönderir.
    Örneğin, yapılandırma dosyası değişirse hizmeti otomatik olarak yeniden başlatabilirsiniz.

Ek olarak, Puppet DSL'de koşullu ifadeler ve seçicilerin yanı sıra işlevler ve değişkenler de bulunur. Çeşitli şablon oluşturma mekanizmaları da desteklenmektedir - EPP ve ERB.

Puppet Ruby'de yazılmıştır, pek çok yapı ve terim buradan alınmıştır. Ruby, Puppet'ı genişletmenize, karmaşık mantık, yeni kaynak türleri ve işlevler eklemenize olanak tanır.

Puppet çalışırken, sunucudaki her bir düğüme ilişkin bildirimler bir dizinde derlenir. Rehber fonksiyonların, değişkenlerin değeri ve koşullu ifadelerin genişletilmesi hesaplandıktan sonra kaynakların ve bunların ilişkilerinin bir listesidir.

Sözdizimi ve kod stili

Sağlanan örnekler yeterli değilse, sözdizimini anlamanıza yardımcı olacak resmi belgelerin bölümleri şunlardır:

İşte manifestin neye benzediğine dair bir örnek:

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

Girinti ve satır sonları bildirimin zorunlu bir parçası değildir, ancak önerilen bir bölüm vardır. stil rehberi. Özet:

  • İki boşluklu girintiler, sekmeler kullanılmaz.
  • Kıvrımlı ayraçlar boşlukla ayrılır; iki nokta üst üste boşlukla ayrılmaz.
  • Sonuncusu da dahil olmak üzere her parametreden sonra virgül. Her parametre ayrı bir satırdadır. Parametresiz ve tek parametreli durum için bir istisna yapılmıştır: tek satıra ve virgülsüz yazabilirsiniz (ör. resource { 'title': } и resource { 'title': param => value }).
  • Parametrelerdeki oklar aynı seviyede olmalıdır.
  • Kaynak ilişkisi okları önlerine yazılır.

Pappet sunucusundaki dosyaların konumu

Daha fazla açıklama için “kök dizin” kavramını tanıtacağım. Kök dizin, belirli bir düğüm için Puppet yapılandırmasını içeren dizindir.

Kök dizin, Puppet sürümüne ve kullanılan ortamlara bağlı olarak değişir. Ortamlar, ayrı dizinlerde depolanan bağımsız yapılandırma kümeleridir. Genellikle git ile birlikte kullanılır; bu durumda ortamlar git dallarından oluşturulur. Buna göre her düğüm bir veya başka bir ortamda bulunur. Bu, düğümün kendisinde veya bir sonraki makalede bahsedeceğim ENC'de yapılandırılabilir.

  • Üçüncü versiyonda ("eski Kukla") temel dizin şuydu: /etc/puppet. Ortamların kullanımı isteğe bağlıdır; örneğin, bunları eski Puppet'ta kullanmıyoruz. Ortamlar kullanılıyorsa, bunlar genellikle /etc/puppet/environmentskök dizin ortam dizini olacaktır. Ortamlar kullanılmıyorsa kök dizin, temel dizin olacaktır.
  • Dördüncü versiyondan itibaren (“yeni Kukla”) ortamların kullanımı zorunlu hale geldi ve temel dizin şuraya taşındı: /etc/puppetlabs/code. Buna göre ortamlar depolanır. /etc/puppetlabs/code/environments, kök dizin ortam dizinidir.

Kök dizinde bir alt dizin bulunmalıdır manifestsDüğümleri açıklayan bir veya daha fazla bildirimi içeren. Ayrıca bir alt dizin bulunmalıdır. modulesmodülleri içeren . Hangi modüllerin olduğunu biraz sonra anlatacağım. Ayrıca eski Puppet'ın bir alt dizini de olabilir filesDüğümlere kopyaladığımız çeşitli dosyaları içeren. Yeni Puppet'ta tüm dosyalar modüllere yerleştirilmiştir.

Manifest dosyaları şu uzantıya sahiptir: .pp.

Birkaç savaş örneği

Düğümün ve üzerindeki kaynağın açıklaması

Düğümde server1.testdomain bir dosya oluşturulmalıdır /etc/issue içerikli Debian GNU/Linux n l. Dosyanın sahibi bir kullanıcı ve gruba ait olmalıdır rooterişim hakları olmalıdır 644.

Bir manifesto yazıyoruz:

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

Bir düğümdeki kaynaklar arasındaki ilişkiler

Düğümde server2.testdomain nginx'in önceden hazırlanmış bir konfigürasyonla çalışıyor olması gerekir.

Sorunu ayrıştıralım:

  • Paketin kurulması gerekiyor nginx.
  • Yapılandırma dosyalarının sunucudan kopyalanması gereklidir.
  • Hizmetin çalışıyor olması gerekiyor nginx.
  • Yapılandırma güncellenirse hizmetin yeniden başlatılması gerekir.

Bir manifesto yazıyoruz:

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

Bunun çalışması için kukla sunucusunda yaklaşık olarak aşağıdaki dosya konumuna ihtiyacınız vardır:

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

Kaynak Türleri

Desteklenen kaynak türlerinin tam listesini burada bulabilirsiniz belgelerdeBurada, pratiğimde çoğu sorunu çözmeye yetecek beş temel türü tanımlayacağım.

dosya

Dosyaları, dizinleri, sembolik bağlantıları, içeriklerini ve erişim haklarını yönetir.

Parametreler:

  • kaynak adı — dosyanın yolu (isteğe bağlı)
  • yol — dosyanın yolu (adında belirtilmemişse)
  • sağlamak - dosya tipi:
    • absent - bir dosyayı sil
    • present — herhangi bir türde bir dosya bulunmalıdır (dosya yoksa normal bir dosya oluşturulacaktır)
    • file - normal dosya
    • directory - dizin
    • link - sembolik bağlantı
  • içerik — dosya içerikleri (yalnızca normal dosyalar için uygundur; kaynak veya hedef)
  • kaynak — dosyanın içeriğini kopyalamak istediğiniz yola bir bağlantı (ile birlikte kullanılamaz) içerik veya hedef). Şemalı bir URI olarak belirtilebilir puppet: (daha sonra kukla sunucudaki dosyalar kullanılacaktır) ve şemayla http: (Umarım bu durumda ne olacağı açıktır) ve hatta diyagramla file: veya şemasız mutlak bir yol olarak (daha sonra düğümdeki yerel FS'deki dosya kullanılacaktır)
  • hedef - sembolik bağlantının işaret etmesi gereken yer (ile birlikte kullanılamaz) içerik veya kaynak)
  • sahip — dosyanın sahibi olması gereken kullanıcı
  • Grup — dosyanın ait olması gereken grup
  • kip — dosya izinleri (dize olarak)
  • recurse - özyinelemeli dizin işlemeyi etkinleştirir
  • tasfiye - Puppet'ta açıklanmayan dosyaların silinmesini sağlar
  • anabolik etkileri de mevcuttur - Puppet'ta açıklanmayan dizinlerin silinmesini sağlar

paket

Paketleri yükler ve kaldırır. Bildirimleri işleyebilir - parametre belirtilirse paketi yeniden yükler yeniden yükleme_on_refresh.

Parametreler:

  • kaynak adı — paket adı (isteğe bağlı)
  • isim — paket adı (adda belirtilmemişse)
  • sağlayan — kullanılacak paket yöneticisi
  • sağlamak — paketin istenen durumu:
    • present, installed - yüklü herhangi bir sürüm
    • latest - en son sürüm yüklü
    • absent - silindi (apt-get remove)
    • purged — yapılandırma dosyalarıyla birlikte silindi (apt-get purge)
    • held - paket sürümü kilitli (apt-mark hold)
    • любая другая строка — belirtilen sürüm yüklü
  • yeniden yükleme_on_refresh - Eğer bir true, ardından bildirim alındıktan sonra paket yeniden yüklenecektir. Derleme parametrelerini değiştirirken paketlerin yeniden oluşturulmasının gerekli olabileceği kaynak tabanlı dağıtımlar için kullanışlıdır. Varsayılan false.

hizmet

Hizmetleri yönetir. Bildirimleri işleyebilir - hizmeti yeniden başlatır.

Parametreler:

  • kaynak adı — yönetilecek hizmet (isteğe bağlı)
  • isim — yönetilmesi gereken hizmet (adında belirtilmemişse)
  • sağlamak - hizmetin istenen durumu:
    • running - başlatıldı
    • stopped - durduruldu
  • etkinleştirmek — hizmeti başlatma yeteneğini kontrol eder:
    • true — otomatik çalıştırma etkinleştirildi (systemctl enable)
    • mask - gizlenmiş (systemctl mask)
    • false — otomatik çalıştırma devre dışı bırakıldı (systemctl disable)
  • yeniden - hizmeti yeniden başlatma komutu
  • durum — hizmet durumunu kontrol etme komutu
  • yeniden başlatıldı — hizmet başlangıç ​​betiğinin yeniden başlatmayı destekleyip desteklemediğini belirtin. Eğer false ve parametre belirtildi yeniden — bu parametrenin değeri kullanılır. Eğer false ve parametre yeniden belirtilmemiş - hizmet durduruldu ve yeniden başlatılmaya başlandı (ancak systemd şu komutu kullanıyor: systemctl restart).
  • durumu — hizmet başlangıç ​​betiğinin komutu destekleyip desteklemediğini belirtin status. Eğer false, daha sonra parametre değeri kullanılır durum. Varsayılan true.

exec

Harici komutları çalıştırır. Parametre belirtmezseniz oluşturur, Yalnızca, olmadıkça veya yalnızca yenileme, komut Puppet'in her çalıştırılışında çalıştırılacaktır. Bildirimleri işleyebilir - bir komutu çalıştırır.

Parametreler:

  • kaynak adı - yürütülecek komut (isteğe bağlı)
  • komuta — yürütülecek komut (adında belirtilmemişse)
  • yol — yürütülebilir dosyanın aranacağı yollar
  • Yalnızca — bu parametrede belirtilen komut sıfıra dönüş koduyla tamamlanırsa ana komut yürütülür
  • olmadıkça — bu parametrede belirtilen komut sıfırdan farklı bir dönüş koduyla tamamlanırsa ana komut yürütülür
  • oluşturur — bu parametrede belirtilen dosya mevcut değilse ana komut yürütülür
  • yalnızca yenileme - Eğer bir true, bu durumda komut yalnızca bu yönetici diğer kaynaklardan bildirim aldığında çalıştırılacaktır.
  • cwd — komutun çalıştırılacağı dizin
  • kullanıcı — komutun çalıştırılacağı kullanıcı
  • sağlayan - komutun nasıl çalıştırılacağı:
    • posix — bir alt süreç basitçe oluşturulur, belirttiğinizden emin olun yol
    • kabuk - komut kabukta başlatılır /bin/sh, belirtilmemiş olabilir yol, küreselleştirmeyi, boruları ve diğer kabuk özelliklerini kullanabilirsiniz. Herhangi bir özel karakter varsa genellikle otomatik olarak algılanır (|, ;, &&, || vb).

cron

Cronjobs'ı kontrol eder.

Parametreler:

  • kaynak adı - sadece bir çeşit tanımlayıcı
  • sağlamak — taç işi durumu:
    • present - mevcut değilse oluştur
    • absent - varsa sil
  • komuta - hangi komutun çalıştırılacağı
  • çevre - komutun hangi ortamda çalıştırılacağı (ortam değişkenlerinin listesi ve bunların değerleri =)
  • kullanıcı — komutun hangi kullanıcıdan çalıştırılacağı
  • dakika, saat, iş günü, ay, ay günü — cron'un ne zaman çalıştırılacağı. Bu özelliklerden herhangi biri belirtilmezse crontab'daki değeri şu şekilde olacaktır: *.

Kukla 6.0'da cron sanki kutudan çıkarıldı kukla sunucusunda olduğundan genel sitede hiçbir belge yoktur. Ama o kutunun içinde puppet-agent'ta olduğundan ayrıca yüklemenize gerek yoktur. Bunun için belgeleri görebilirsiniz Puppet'ın beşinci versiyonunun belgelerindeVeya GitHub'da.

Genel olarak kaynaklar hakkında

Kaynak benzersizliği için gereksinimler

Karşılaştığımız en yaygın hata Yinelenen beyan. Bu hata, dizinde aynı türde ve aynı adda iki veya daha fazla kaynak göründüğünde ortaya çıkar.

Bu nedenle tekrar yazacağım: Aynı düğüme ait bildirimler, aynı başlığa sahip, aynı türden kaynaklar içermemelidir!

Bazen aynı adı taşıyan ancak farklı paket yöneticilerine sahip paketleri kurmanız gerekebilir. Bu durumda parametreyi kullanmanız gerekir. namehatayı önlemek için:

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

Diğer kaynak türleri, kopyaların önlenmesine yardımcı olmak için benzer seçeneklere sahiptir - name у hizmet, command у exec, ve benzeri.

Metaparametreler

Her kaynak türünün, niteliğine bakılmaksızın bazı özel parametreleri vardır.

Meta parametrelerin tam listesi Kukla belgelerinde.

Kısa liste:

  • gerektirir — bu parametre, bu kaynağın hangi kaynaklara bağlı olduğunu gösterir.
  • önce - Bu parametre hangi kaynakların bu kaynağa bağlı olduğunu belirtir.
  • abone ol — bu parametre, bu kaynağın hangi kaynaklardan bildirim aldığını belirtir.
  • bildirmek — Bu parametre, hangi kaynakların bu kaynaktan bildirim alacağını belirtir.

Listelenen meta parametrelerin tümü, tek bir kaynak bağlantısını veya köşeli parantez içindeki bir dizi bağlantıyı kabul eder.

Kaynaklara bağlantılar

Kaynak bağlantısı yalnızca kaynağın belirtilmesidir. Esas olarak bağımlılıkları belirtmek için kullanılırlar. Var olmayan bir kaynağa başvurulması derleme hatasına neden olur.

Bağlantının sözdizimi şu şekildedir: büyük harfle kaynak türü (tür adı çift iki nokta üst üste içeriyorsa, adın iki nokta üst üste arasındaki her kısmı büyük harfle yazılır), ardından köşeli parantez içindeki kaynak adı (adın durumu) değişmez!). Boşluk bırakılmamalı, tip adından hemen sonra köşeli parantez yazılmalıdır.

Örnek:

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

Bağımlılıklar ve bildirimler

Belgeler burada.

Daha önce de belirtildiği gibi kaynaklar arasındaki basit bağımlılıklar geçişlidir. Bu arada, bağımlılık eklerken dikkatli olun; döngüsel bağımlılıklar oluşturabilirsiniz, bu da derleme hatasına neden olur.

Bağımlılıklardan farklı olarak bildirimler geçişli değildir. Bildirimler için aşağıdaki kurallar geçerlidir:

  • Kaynak bir bildirim alırsa güncellenir. Güncelleme eylemleri kaynak türüne bağlıdır – exec komutu çalıştırır, hizmet hizmeti yeniden başlatır, paket paketi yeniden yükler. Kaynağın tanımlanmış bir güncelleme eylemi yoksa hiçbir şey olmaz.
  • Puppet'ın bir çalışması sırasında kaynak bir defadan fazla güncellenmez. Bildirimlerin bağımlılıkları içermesi ve bağımlılık grafiğinin döngü içermemesi nedeniyle bu mümkündür.
  • Puppet bir kaynağın durumunu değiştirirse kaynak, kendisine abone olan tüm kaynaklara bildirim gönderir.
  • Bir kaynak güncellendiğinde kendisine abone olan tüm kaynaklara bildirim gönderir.

Belirtilmemiş parametrelerin işlenmesi

Kural olarak, bazı kaynak parametrelerinin varsayılan değeri yoksa ve bu parametre bildirimde belirtilmemişse Puppet, düğümdeki karşılık gelen kaynak için bu özelliği değiştirmez. Örneğin, eğer türde bir kaynak varsa dosya parametre belirtilmedi owner, bu durumda Puppet ilgili dosyanın sahibini değiştirmez.

Sınıflara, değişkenlere ve tanımlara giriş

Diyelim ki konfigürasyonun aynı kısmına sahip birkaç düğümümüz var, ancak farklılıklar da var - aksi takdirde hepsini tek bir blokta tanımlayabilirdik node {}. Tabii ki, konfigürasyonun aynı kısımlarını basitçe kopyalayabilirsiniz, ancak genel olarak bu kötü bir çözümdür - konfigürasyon büyür ve konfigürasyonun genel bölümünü değiştirirseniz, aynı şeyi birçok yerde düzenlemeniz gerekecektir. Aynı zamanda hata yapmak kolaydır ve genel olarak DRY (kendini tekrar etme) ilkesi bir nedenden dolayı icat edilmiştir.

Bu sorunu çözmek için şöyle bir tasarım var: sınıf.

Sınıflar

sınıf adlandırılmış bir poppet kodu bloğudur. Kodu yeniden kullanmak için sınıflara ihtiyaç vardır.

Öncelikle sınıfın tanımlanması gerekiyor. Açıklamanın kendisi hiçbir yere herhangi bir kaynak eklemez. Sınıf manifestlerde açıklanmıştır:

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

Bundan sonra sınıf kullanılabilir:

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

Önceki görevden bir örnek; nginx'in kurulumunu ve yapılandırmasını bir sınıfa taşıyalım:

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
}

Değişkenler

Önceki örnekteki sınıf hiç esnek değil çünkü her zaman aynı nginx yapılandırmasını getiriyor. Yapılandırma değişkenine giden yolu oluşturalım, ardından bu sınıf herhangi bir yapılandırmayla nginx'i yüklemek için kullanılabilir.

Yapılabilir değişkenleri kullanma.

Dikkat: Puppet'taki değişkenler değişmezdir!

Ayrıca bir değişkene ancak bildirildikten sonra erişilebilir, aksi halde değişkenin değeri şu şekilde olacaktır: undef.

Değişkenlerle çalışma örneği:

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

Kukla var ad alanlarıve değişkenler buna göre görünürlük alanı: Aynı isimde bir değişken farklı isim alanlarında tanımlanabilir. Bir değişkenin değeri çözümlenirken, değişken geçerli ad alanında, ardından onu çevreleyen ad alanında vb. aranır.

Ad alanı örnekleri:

  • global - sınıf veya düğüm tanımının dışındaki değişkenler oraya gider;
  • düğüm açıklamasındaki düğüm ad alanı;
  • sınıf açıklamasındaki sınıf ad alanı.

Bir değişkene erişirken belirsizliği önlemek için değişken adında ad alanını belirtebilirsiniz:

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

Nginx yapılandırmasına giden yolun değişkende olduğu konusunda hemfikir olalım $nginx_conf_source. Daha sonra sınıf şöyle görünecek:

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
}

Ancak verilen örnek kötü çünkü sınıfın içinde bir yerde falan isimle bir değişkenin kullanıldığına dair bazı "gizli bilgiler" var. Bu bilgiyi genelleştirmek çok daha doğrudur - sınıfların parametreleri olabilir.

Sınıf parametreleri sınıf ad alanındaki değişkenlerdir, sınıf başlığında belirtilirler ve sınıf gövdesindeki normal değişkenler gibi kullanılabilirler. Manifestte sınıf kullanılırken parametre değerleri belirtilir.

Parametre varsayılan değere ayarlanabilir. Bir parametrenin varsayılan değeri yoksa ve kullanıldığında değer ayarlanmamışsa derleme hatasına neden olur.

Yukarıdaki örnekten sınıfı parametreleştirelim ve iki parametre ekleyelim: ilki, gerekli olan, yapılandırmanın yoludur ve ikincisi, isteğe bağlı, nginx'li paketin adıdır (örneğin, Debian'da paketler vardır). 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'ta değişkenler yazılır. Yemek yemek birçok veri türü. Veri türleri genellikle sınıflara ve tanımlara iletilen parametre değerlerini doğrulamak için kullanılır. Aktarılan parametre belirtilen türle eşleşmiyorsa derleme hatası oluşur.

Tür, parametre adından hemen önce yazılır:

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

Sınıflar: sınıf adı vs sınıf{'sınıf adı':} dahil

Her sınıf bir tür kaynaktır sınıf. Diğer herhangi bir kaynak türünde olduğu gibi, aynı düğümde aynı sınıfın iki örneği bulunamaz.

Aynı düğüme iki kez sınıf eklemeye çalışırsanız class { 'classname':} (fark yok, farklı veya aynı parametrelerde), derleme hatası oluşacaktır. Ancak kaynak stilinde bir sınıf kullanırsanız, onun tüm parametrelerini manifestte hemen açıkça ayarlayabilirsiniz.

Ancak eğer kullanırsanız include, daha sonra sınıf istenildiği kadar eklenebilir. Gerçek şu ki include dizine bir sınıfın eklenip eklenmediğini kontrol eden önemsiz bir işlevdir. Sınıf dizinde değilse ekler, zaten varsa hiçbir şey yapmaz. Ama kullanılması durumunda include Sınıf bildirimi sırasında sınıf parametrelerini ayarlayamazsınız - gerekli tüm parametrelerin harici bir veri kaynağında (Hiera veya ENC) ayarlanması gerekir. Bir sonraki yazımızda bunlardan bahsedeceğiz.

Tanımlar

Önceki blokta da söylendiği gibi aynı sınıf bir düğümde birden fazla bulunamaz. Ancak bazı durumlarda aynı kod bloğunu aynı düğümde farklı parametrelerle kullanabilmeniz gerekir. Yani kendine ait bir kaynak türüne ihtiyaç var.

Örneğin PHP modülünü kurmak için Avito'da aşağıdakileri yapıyoruz:

  1. Paketi bu modülle yükleyin.
  2. Bu modül için bir konfigürasyon dosyası oluşturalım.
  3. Php-fpm için yapılandırmaya bir sembolik bağlantı oluşturuyoruz.
  4. Php cli için yapılandırmaya bir sembolik bağlantı oluşturuyoruz.

Bu gibi durumlarda aşağıdaki gibi bir tasarım tanımlamak (tanımla, tanımlı tür, tanımlı kaynak türü). Define bir sınıfa benzer, ancak farklılıklar vardır: birincisi, her Define bir kaynak değil, bir kaynak türüdür; ikincisi, her tanımın örtülü bir parametresi vardır $title, bildirildiğinde kaynak adının gideceği yer. Tıpkı sınıflarda olduğu gibi, önce bir tanımın tanımlanması gerekir, daha sonra kullanılabilir.

PHP için bir modül içeren basitleştirilmiş bir örnek:

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

Yinelenen bildirim hatasını yakalamanın en kolay yolu Tanımla'dır. Bu, bir tanımın sabit ada sahip bir kaynağı varsa ve bazı düğümlerde bu tanımın iki veya daha fazla örneği varsa meydana gelir.

Kendinizi bundan korumak kolaydır: Tanımın içindeki tüm kaynakların, bağlı olarak bir adı olmalıdır. $title. Bir alternatif, kaynakların önemsiz olarak eklenmesidir; en basit durumda, tanımın tüm örneklerinde ortak olan kaynakları ayrı bir sınıfa taşımak ve bu sınıfı tanım - fonksiyona dahil etmek yeterlidir. include etkisiz.

Kaynak eklerken bağımsızlığa ulaşmanın başka yolları da vardır, yani işlevleri kullanmak defined и ensure_resourcesama bunu bir sonraki bölümde anlatacağım.

Sınıflar ve tanımlar için bağımlılıklar ve bildirimler

Sınıflar ve tanımlar, bağımlılıkların ve bildirimlerin işlenmesine aşağıdaki kuralları ekler:

  • bir sınıfa/tanıma bağımlılık, sınıfın/tanımın tüm kaynaklarına bağımlılıklar ekler;
  • bir sınıf/tanımlama bağımlılığı, tüm sınıf/tanımlama kaynaklarına bağımlılıklar ekler;
  • sınıf/tanımlama bildirimi, sınıfın/tanımlamanın tüm kaynaklarını bilgilendirir;
  • class/define aboneliği, class/define'in tüm kaynaklarına abone olur.

Koşullu ifadeler ve seçiciler

Belgeler burada.

if

Burada her şey basit:

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

olmadıkça

ters bir if olmadığı sürece: ifade yanlışsa kod bloğu yürütülür.

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

dava

Burada da karmaşık bir şey yok. Değer olarak normal değerleri (dizeler, sayılar vb.), düzenli ifadeleri ve veri türlerini kullanabilirsiniz.

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

Seçiciler

Seçici, aşağıdakine benzer bir dil yapısıdır: caseancak bir kod bloğunu yürütmek yerine bir değer döndürür.

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

Модули

Konfigürasyon küçük olduğunda kolaylıkla tek bir bildirimde tutulabilir. Ancak ne kadar çok konfigürasyon tanımlarsak, bildirimde o kadar çok sınıf ve düğüm bulunur, büyür ve birlikte çalışmak elverişsiz hale gelir.

Ek olarak, kodun yeniden kullanımı sorunu da vardır; kodun tamamı tek bir bildirimde olduğunda, bu kodu başkalarıyla paylaşmak zordur. Bu iki sorunu çözmek için Puppet'ın modül adı verilen bir varlığı vardır.

Модули - bunlar ayrı bir dizine yerleştirilen sınıflar, tanımlar ve diğer Puppet varlıkları kümeleridir. Başka bir deyişle, bir modül Puppet mantığının bağımsız bir parçasıdır. Örneğin, nginx ile çalışmak için bir modül olabilir ve yalnızca nginx ile çalışmak için gerekenleri içerecektir veya PHP ile çalışmak için bir modül vb. olabilir.

Modüller sürümlendirilmiştir ve modüllerin birbirine bağımlılığı da desteklenir. Açık bir modül deposu var - Kukla Ocağı.

Kukla sunucusunda modüller, kök dizinin modüller alt dizininde bulunur. Her modülün içinde standart bir dizin şeması vardır - bildirimler, dosyalar, şablonlar, lib vb.

Bir modüldeki dosya yapısı

Modülün kökü, açıklayıcı adlara sahip aşağıdaki dizinleri içerebilir:

  • manifests - manifestolar içeriyor
  • files - dosyalar içeriyor
  • templates - şablonlar içerir
  • lib — Ruby kodunu içerir

Bu, dizinlerin ve dosyaların tam listesi değil, ancak şimdilik bu makale için yeterli.

Kaynak adları ve modüldeki dosyaların adları

Belgeler burada.

Bir modüldeki kaynaklar (sınıflar, tanımlar) istediğiniz gibi adlandırılamaz. Ek olarak, bir kaynağın adı ile Puppet'in o kaynağın açıklamasını arayacağı dosyanın adı arasında doğrudan bir ilişki vardır. Adlandırma kurallarını ihlal ederseniz Puppet kaynak açıklamasını bulamaz ve bir derleme hatası alırsınız.

Kurallar basit:

  • Bir modüldeki tüm kaynakların modül ad alanında olması gerekir. Modül çağrılırsa foo, o zaman içindeki tüm kaynaklar adlandırılmalıdır foo::<anything>ya da sadece foo.
  • Dosyada modül adını taşıyan bir kaynak bulunmalıdır init.pp.
  • Diğer kaynaklar için dosya adlandırma şeması aşağıdaki gibidir:
    • modül adını taşıyan önek atılır
    • varsa tüm çift iki nokta üst üste eğik çizgilerle değiştirilir
    • uzantı eklendi .pp

Bir örnekle göstereceğim. Diyelim ki bir modül yazıyorum nginx. Aşağıdaki kaynakları içerir:

  • sınıf nginx manifestte açıklanan init.pp;
  • sınıf nginx::service manifestte açıklanan service.pp;
  • tanımlamak nginx::server manifestte açıklanan server.pp;
  • tanımlamak nginx::server::location manifestte açıklanan server/location.pp.

Şablonları

Elbette şablonların ne olduğunu kendiniz biliyorsunuz; bunları burada ayrıntılı olarak açıklamayacağım. Ama her ihtimale karşı bırakacağım Wikipedia'ya bağlantı.

Şablonlar nasıl kullanılır: Bir şablonun anlamı bir işlev kullanılarak genişletilebilir template, şablonun yolunu iletir. Türdeki kaynaklar için dosya parametre ile birlikte kullanılır content. Örneğin şöyle:

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

Yolu görüntüle <modulename>/<filename> dosyayı ima eder <rootdir>/modules/<modulename>/templates/<filename>.

Ayrıca bir işlevi var inline_template — giriş olarak dosya adını değil şablon metnini alır.

Şablonların içinde geçerli kapsamdaki tüm Puppet değişkenlerini kullanabilirsiniz.

Puppet, ERB ve EPP formatındaki şablonları destekler:

Kısaca ERB hakkında

Kontrol Yapıları:

  • <%= ВЫРАЖЕНИЕ %> — ifadenin değerini girin
  • <% ВЫРАЖЕНИЕ %> — bir ifadenin değerini hesaplayın (eklemeden). Koşullu ifadeler (if) ve döngüler (her biri) genellikle buraya gelir.
  • <%# КОММЕНТАРИЙ %>

ERB'deki ifadeler Ruby'de yazılmıştır (ERB aslında Gömülü Ruby'dir).

Bildirimden değişkenlere erişmek için şunu eklemeniz gerekir: @ değişken adına. Bir kontrol yapısından sonra görünen satır sonunu kaldırmak için bir kapanış etiketi kullanmanız gerekir. -%>.

Şablonu kullanma örneği

Diyelim ki ZooKeeper'ı kontrol etmek için bir modül yazıyorum. Yapılandırmayı oluşturmaktan sorumlu sınıf şuna benzer:

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

Ve ilgili şablon zoo.cfg.erb - Bu yüzden:

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

Gerçekler ve Yerleşik Değişkenler

Genellikle yapılandırmanın belirli bir kısmı, düğümde o anda olup bitenlere bağlıdır. Örneğin, Debian sürümünün ne olduğuna bağlı olarak paketin bir veya başka bir sürümünü kurmanız gerekir. Tüm bunları manuel olarak izleyebilir, düğümler değişirse bildirimleri yeniden yazabilirsiniz. Ancak bu ciddi bir yaklaşım değil; otomasyon çok daha iyi.

Düğümler hakkında bilgi edinmek için Puppet'ın gerçekler adı verilen bir mekanizması vardır. Gerçekler - bu, genel ad alanındaki sıradan değişkenler biçiminde bildirimlerde bulunan, düğümle ilgili bilgidir. Örneğin, ana bilgisayar adı, işletim sistemi sürümü, işlemci mimarisi, kullanıcı listesi, ağ arayüzleri listesi ve adresleri ve çok daha fazlası. Gerçekler manifestlerde ve şablonlarda normal değişkenler olarak mevcuttur.

Gerçeklerle çalışmaya bir örnek:

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

Resmi olarak konuşursak, bir olgunun bir adı (dizge) ve bir değeri vardır (çeşitli türleri mevcuttur: dizeler, diziler, sözlükler). Yemek yemek yerleşik gerçekler kümesi. Ayrıca kendinizinkini de yazabilirsiniz. Gerçek toplayıcılar anlatılıyor Ruby'deki benzer işlevler, veya nasıl yürütülebilir dosyalar. Gerçekler formda da sunulabilir veri içeren metin dosyaları düğümlerde.

Operasyon sırasında, kukla ajan ilk olarak mevcut tüm bilgi toplayıcıları kağıt sunucusundan düğüme kopyalar, ardından bunları başlatır ve toplanan gerçekleri sunucuya gönderir; Bundan sonra sunucu kataloğu derlemeye başlar.

Yürütülebilir dosyalar biçimindeki gerçekler

Bu tür gerçekler dizindeki modüllere yerleştirilir facts.d. Tabii ki, dosyalar çalıştırılabilir olmalıdır. Çalıştırıldığında, bilgileri standart çıktıya YAML veya anahtar=değer biçiminde çıkarmaları gerekir.

Gerçeklerin, modülünüzün konuşlandırıldığı poppet sunucusu tarafından kontrol edilen tüm düğümler için geçerli olduğunu unutmayın. Bu nedenle, komut dosyasında, sisteminizin çalışması için gerekli tüm programların ve dosyaların bulunduğunu kontrol etmeye dikkat edin.

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

Yakut gerçekleri

Bu tür gerçekler dizindeki modüllere yerleştirilir 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

Metin gerçekleri

Bu tür gerçekler dizindeki düğümlere yerleştirilir /etc/facter/facts.d eski Puppet'ta veya /etc/puppetlabs/facts.d yeni Puppet'ta.

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

Gerçeklere Ulaşmak

Gerçeklere yaklaşmanın iki yolu vardır:

  • sözlük aracılığıyla $facts: $facts['fqdn'];
  • değişken adı olarak olgu adını kullanarak: $fqdn.

Sözlük kullanmak en iyisidir $factsveya daha iyisi global ad alanını belirtin ($::facts).

İşte belgelerin ilgili bölümü.

Yerleşik Değişkenler

Gerçeklerin yanı sıra bir de var bazı değişkenler, global ad alanında mevcuttur.

  • güvenilir gerçekler — müşterinin sertifikasından alınan değişkenler (sertifika genellikle bir poppet sunucusunda verildiğinden, aracı sadece sertifikasını alıp değiştiremez, bu nedenle değişkenler "güvenilir"): sertifikanın adı, sertifikanın adı ana bilgisayar ve etki alanı, sertifikadaki uzantılar.
  • sunucu gerçekleri —sunucu hakkındaki bilgilerle ilgili değişkenler—sürüm, ad, sunucu IP adresi, ortam.
  • ajan gerçekleri — gerçekte değil, doğrudan kukla aracısı tarafından eklenen değişkenler — sertifika adı, aracı sürümü, kukla sürümü.
  • ana değişkenler - Pappetmaster değişkenleri (aynen böyle!). Bu yaklaşık olarak aynı sunucu gerçekleriartı konfigürasyon parametre değerleri mevcuttur.
  • derleyici değişkenleri — her kapsamda farklılık gösteren derleyici değişkenleri: geçerli modülün adı ve geçerli nesneye erişilen modülün adı. Örneğin özel sınıflarınızın doğrudan diğer modüllerden kullanılmadığını kontrol etmek için kullanılabilirler.

Ek 1: Tüm bunlar nasıl çalıştırılır ve hata ayıklanır?

Makale birçok kukla kod örneği içeriyordu, ancak bize bu kodun nasıl çalıştırılacağından hiç bahsetmedi. Neyse kendimi düzeltiyorum.

Puppet'ı çalıştırmak için bir aracı yeterlidir ancak çoğu durumda bir sunucuya da ihtiyacınız olacaktır.

ajan

En azından sürüm 5'ten bu yana, kukla ajan paketleri resmi Puppetlabs deposu tüm bağımlılıkları içerir (ruby ve karşılık gelen mücevherler), böylece kurulum zorlukları olmaz (Debian tabanlı dağıtımlardan bahsediyorum - RPM tabanlı dağıtımları kullanmıyoruz).

En basit durumda, kukla yapılandırmasını kullanmak için aracıyı sunucusuz modda başlatmak yeterlidir: kukla kodunun düğüme kopyalanması koşuluyla, aracıyı başlatın. 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

Tabii ki, sunucuyu kurmak ve aracıları daemon modunda düğümlerde çalıştırmak daha iyidir - daha sonra her yarım saatte bir, sunucudan indirilen yapılandırmayı uygulayacaklar.

İtme işi modelini taklit edebilirsiniz - ilgilendiğiniz düğüme gidin ve başlayın sudo puppet agent -t. Anahtar -t (--test) aslında ayrı ayrı etkinleştirilebilecek çeşitli seçenekler içerir. Bu seçenekler aşağıdakileri içerir:

  • daemon modunda çalıştırmayın (ajan varsayılan olarak daemon modunda başlar);
  • kataloğu uyguladıktan sonra kapatma (varsayılan olarak aracı her yarım saatte bir çalışmaya ve yapılandırmayı uygulamaya devam edecektir);
  • ayrıntılı bir çalışma günlüğü yazın;
  • Dosyalardaki değişiklikleri göster.

Aracının değişiklik olmayan bir çalışma modu vardır - doğru konfigürasyonu yazdığınızdan emin olmadığınızda ve aracının çalışma sırasında tam olarak neyi değiştireceğini kontrol etmek istediğinizde bunu kullanabilirsiniz. Bu mod parametre tarafından etkinleştirilir --noop komut satırında: sudo puppet agent -t --noop.

Ek olarak, işin hata ayıklama günlüğünü de etkinleştirebilirsiniz - burada kukla gerçekleştirdiği tüm eylemler hakkında yazar: şu anda işlediği kaynak hakkında, bu kaynağın parametreleri hakkında, hangi programları başlattığı hakkında. Tabii bu bir parametre --debug.

Sunucu

Bu makalede ppet sunucusunun tam kurulumunu ve ona kod dağıtmayı ele almayacağım; yalnızca az sayıda sunucuyla çalışmak için ek yapılandırma gerektirmeyen, kutudan çıktığı haliyle sunucunun tamamen işlevsel bir sürümünün bulunduğunu söyleyeceğim. düğümler (örneğin yüze kadar). Daha fazla sayıda düğümün ayarlanması gerekecektir - varsayılan olarak kukla sunucusu dörtten fazla çalışanı başlatmaz, daha yüksek performans için sayılarını artırmanız gerekir ve bellek sınırlarını artırmayı unutmayın, aksi takdirde sunucu çoğu zaman çöp toplama işlemi yapar.

Kod dağıtımı - hızlı ve kolay bir şekilde ihtiyacınız varsa (r10k'ye)[https://github.com/puppetlabs/r10k], küçük kurulumlar için oldukça yeterli olmalıdır.

Ek 2: Kodlama Yönergeleri

  1. Tüm mantığı sınıflara ve tanımlara yerleştirin.
  2. Sınıfları ve tanımları, düğümleri açıklayan bildirimlerde değil, modüllerde tutun.
  3. Gerçekleri kullanın.
  4. Ana makine adlarına göre if'ler yapmayın.
  5. Sınıflar ve tanımlar için parametreler eklemekten çekinmeyin; bu, sınıf/tanım gövdesinde gizli olan örtülü mantıktan daha iyidir.

Bunu neden yapmanızı önerdiğimi bir sonraki makalede açıklayacağım.

Sonuç

Girişle bitirelim. Bir sonraki yazımda sizlere Hiera, ENC ve PuppetDB'den bahsedeceğim.

Ankete sadece kayıtlı kullanıcılar katılabilir. Giriş yapLütfen.

Aslında çok daha fazla materyal var - Aşağıdaki konularda makaleler yazabilirim, okumak isteyebileceğiniz konulara oy verebilirim:

  • %59,1Gelişmiş kukla yapıları - bazı sonraki seviye saçmalıklar: döngüler, haritalama ve diğer lambda ifadeleri, kaynak toplayıcılar, dışa aktarılan kaynaklar ve Puppet, etiketler, sağlayıcılar, soyut veri türleri aracılığıyla ana bilgisayarlar arası iletişim.13
  • %31,8“Ben annemin yöneticisiyim” ya da Avito'da farklı versiyonlardaki birkaç poppet sunucusuyla nasıl arkadaşlık kurduğumuzu ve prensip olarak poppet sunucusunu yönetmeyle ilgili kısmı.7
  • %81,8Kukla kodunu nasıl yazıyoruz: enstrümantasyon, dokümantasyon, test etme, CI/CD.18

22 kullanıcı oy kullandı. 9 kişi çekimser kaldı.

Kaynak: habr.com