Giới thiệu về con rối

Puppet là một hệ thống quản lý cấu hình. Nó được sử dụng để đưa máy chủ về trạng thái mong muốn và duy trì trạng thái này.

Tôi đã làm việc với Puppet được hơn năm năm. Văn bản này về cơ bản là một bản tổng hợp được dịch và sắp xếp lại các điểm chính từ tài liệu chính thức, điều này sẽ cho phép người mới bắt đầu nhanh chóng hiểu được bản chất của Puppet.

Giới thiệu về con rối

Thông tin cơ bản

Hệ điều hành của Puppet là máy khách-máy chủ, mặc dù nó cũng hỗ trợ hoạt động không có máy chủ với chức năng hạn chế.

Mô hình hoạt động kéo được sử dụng: theo mặc định, cứ nửa giờ một lần, khách hàng sẽ liên hệ với máy chủ để lấy cấu hình và áp dụng nó. Nếu bạn đã làm việc với Ansible, thì họ sẽ sử dụng một mô hình đẩy khác: quản trị viên bắt đầu quá trình áp dụng cấu hình, bản thân khách hàng sẽ không áp dụng bất cứ điều gì.

Trong quá trình giao tiếp mạng, mã hóa TLS hai chiều được sử dụng: máy chủ và máy khách có khóa riêng và chứng chỉ tương ứng. Thông thường, máy chủ cấp chứng chỉ cho máy khách nhưng về nguyên tắc có thể sử dụng CA bên ngoài.

Giới thiệu về bản tuyên ngôn

Trong thuật ngữ con rối đến máy chủ bù nhìn liên kết điểm giao (điểm giao). Cấu hình cho các nút được viết trong bản tuyên ngôn bằng ngôn ngữ lập trình đặc biệt - Puppet DSL.

Con rối DSL là một ngôn ngữ khai báo. Nó mô tả trạng thái mong muốn của nút dưới dạng khai báo các tài nguyên riêng lẻ, ví dụ:

  • Tệp tồn tại và nó có nội dung cụ thể.
  • Gói đã được cài đặt.
  • Dịch vụ đã bắt đầu.

Các tài nguyên có thể được kết nối với nhau:

  • Có sự phụ thuộc, chúng ảnh hưởng đến thứ tự sử dụng tài nguyên.
    Ví dụ: “trước tiên hãy cài đặt gói, sau đó chỉnh sửa tệp cấu hình, sau đó khởi động dịch vụ”.
  • Có thông báo - nếu một tài nguyên đã thay đổi, nó sẽ gửi thông báo đến các tài nguyên đã đăng ký với nó.
    Ví dụ: nếu tệp cấu hình thay đổi, bạn có thể tự động khởi động lại dịch vụ.

Ngoài ra, Puppet DSL có các hàm và biến, cũng như các câu lệnh và bộ chọn có điều kiện. Nhiều cơ chế tạo khuôn mẫu khác nhau cũng được hỗ trợ - EPP và ERB.

Con rối được viết bằng Ruby nên rất nhiều cấu trúc và thuật ngữ được lấy từ đó. Ruby cho phép bạn mở rộng Puppet - thêm logic phức tạp, các loại tài nguyên, chức năng mới.

Trong khi Puppet đang chạy, các bảng kê khai cho từng nút cụ thể trên máy chủ sẽ được biên dịch vào một thư mục. Thư mục là danh sách các tài nguyên và mối quan hệ của chúng sau khi tính toán giá trị của hàm, biến và khai triển câu lệnh điều kiện.

Cú pháp và kiểu mã

Dưới đây là các phần của tài liệu chính thức sẽ giúp bạn hiểu cú pháp nếu các ví dụ được cung cấp không đủ:

Dưới đây là ví dụ về giao diện của tệp kê khai:

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

Thụt lề và ngắt dòng không phải là phần bắt buộc của bảng kê khai nhưng có một khuyến nghị hướng dẫn mẫu. Bản tóm tắt:

  • Thụt lề hai dấu cách, tab không được sử dụng.
  • Các dấu ngoặc nhọn cách nhau một dấu cách, dấu hai chấm không cách nhau một dấu cách.
  • Dấu phẩy sau mỗi tham số, bao gồm cả tham số cuối cùng. Mỗi tham số nằm trên một dòng riêng biệt. Một ngoại lệ được tạo cho trường hợp không có tham số và một tham số: bạn có thể viết trên một dòng và không có dấu phẩy (tức là resource { 'title': } и resource { 'title': param => value }).
  • Các mũi tên trên các tham số phải ở cùng cấp độ.
  • Mũi tên mối quan hệ tài nguyên được viết ở phía trước của họ.

Vị trí của tập tin trên pappetserver

Để giải thích thêm, tôi sẽ giới thiệu khái niệm “thư mục gốc”. Thư mục gốc là thư mục chứa cấu hình Puppet cho một nút cụ thể.

Thư mục gốc khác nhau tùy thuộc vào phiên bản Puppet và môi trường được sử dụng. Môi trường là các bộ cấu hình độc lập được lưu trữ trong các thư mục riêng biệt. Thường được sử dụng kết hợp với git, trong trường hợp đó môi trường được tạo từ các nhánh git. Theo đó, mỗi nút được đặt trong môi trường này hay môi trường khác. Điều này có thể được cấu hình trên chính nút đó hoặc trong ENC mà tôi sẽ nói đến trong bài viết tiếp theo.

  • Trong phiên bản thứ ba ("Con rối cũ"), thư mục cơ sở là /etc/puppet. Việc sử dụng các môi trường là tùy chọn - ví dụ: chúng tôi không sử dụng chúng với Puppet cũ. Nếu môi trường được sử dụng, chúng thường được lưu trữ trong /etc/puppet/environments, thư mục gốc sẽ là thư mục môi trường. Nếu môi trường không được sử dụng, thư mục gốc sẽ là thư mục cơ sở.
  • Bắt đầu từ phiên bản thứ tư (“Con rối mới”), việc sử dụng môi trường trở thành bắt buộc và thư mục cơ sở được chuyển sang /etc/puppetlabs/code. Theo đó, môi trường được lưu trữ trong /etc/puppetlabs/code/environments, thư mục gốc là thư mục môi trường.

Phải có một thư mục con trong thư mục gốc manifests, chứa một hoặc nhiều bảng kê khai mô tả các nút. Ngoài ra cần có thư mục con modules, chứa các mô-đun. Tôi sẽ cho bạn biết mô-đun nào sau này. Ngoài ra Puppet cũ còn có thể có thư mục con files, chứa nhiều tệp khác nhau mà chúng tôi sao chép vào các nút. Trong Puppet mới, tất cả các tệp được đặt trong các mô-đun.

Tệp kê khai có phần mở rộng .pp.

Một số ví dụ chiến đấu

Mô tả nút và tài nguyên trên đó

Trên nút server1.testdomain một tập tin phải được tạo /etc/issue có nội dung Debian GNU/Linux n l. Tệp phải thuộc sở hữu của người dùng và nhóm root, quyền truy cập phải được 644.

Chúng tôi viết một bản tuyên ngôn:

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

Mối quan hệ giữa các tài nguyên trên một nút

Trên nút server2.testdomain nginx phải đang chạy, hoạt động với cấu hình đã chuẩn bị trước đó.

Hãy phân tích vấn đề:

  • Gói cần được cài đặt nginx.
  • Điều cần thiết là các tập tin cấu hình phải được sao chép từ máy chủ.
  • Dịch vụ cần được chạy nginx.
  • Nếu cấu hình được cập nhật, dịch vụ phải được khởi động lại.

Chúng tôi viết một bản tuyên ngôn:

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

Để tính năng này hoạt động, bạn cần có vị trí tệp gần như sau trên máy chủ con rối:

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

Các loại tài nguyên

Bạn có thể tìm thấy danh sách đầy đủ các loại tài nguyên được hỗ trợ tại đây trong tài liệu, ở đây tôi sẽ mô tả năm loại cơ bản, trong thực tế của tôi là đủ để giải quyết hầu hết các vấn đề.

hồ sơ

Quản lý tập tin, thư mục, liên kết tượng trưng, ​​​​nội dung của chúng và quyền truy cập.

Trả lời:

  • tên tài nguyên - đường dẫn đến tệp (tùy chọn)
  • con đường - đường dẫn đến tệp (nếu nó không được chỉ định trong tên)
  • đảm bảo - loại tệp:
    • absent - xóa một tập tin
    • present — phải có một loại tệp bất kỳ (nếu không có tệp, một tệp thông thường sẽ được tạo)
    • file - tập tin thông thường
    • directory - danh mục
    • link - liên kết tượng trưng
  • nội dung — nội dung tập tin (chỉ phù hợp với các tập tin thông thường, không thể sử dụng cùng với nguồn hoặc mục tiêu)
  • nguồn — một liên kết đến đường dẫn mà bạn muốn sao chép nội dung của tập tin (không thể sử dụng cùng với nội dung hoặc mục tiêu). Có thể được chỉ định làm URI với sơ đồ puppet: (khi đó các tập tin từ máy chủ con rối sẽ được sử dụng) và với sơ đồ http: (Tôi hy vọng rõ ràng điều gì sẽ xảy ra trong trường hợp này) và ngay cả với sơ đồ file: hoặc dưới dạng đường dẫn tuyệt đối không có lược đồ (khi đó tệp từ FS cục bộ trên nút sẽ được sử dụng)
  • mục tiêu — nơi liên kết tượng trưng sẽ trỏ tới (không thể sử dụng cùng với nội dung hoặc nguồn)
  • chủ sở hữu — người dùng nên sở hữu tập tin
  • nhóm — nhóm chứa tập tin đó
  • chế độ - quyền truy cập tệp (dưới dạng chuỗi)
  • tái diễn - cho phép xử lý thư mục đệ quy
  • purge - cho phép xóa các tập tin không được mô tả trong Puppet
  • lực lượng - cho phép xóa các thư mục không được mô tả trong Puppet

gói

Cài đặt và gỡ bỏ các gói. Có thể xử lý thông báo - cài đặt lại gói nếu tham số được chỉ định cài đặt lại_on_refresh.

Trả lời:

  • tên tài nguyên - tên gói (tùy chọn)
  • tên — tên gói (nếu không được chỉ định trong tên)
  • nhà cung cấp dịch vụ - trình quản lý gói để sử dụng
  • đảm bảo - trạng thái mong muốn của gói hàng:
    • present, installed - bất kỳ phiên bản nào được cài đặt
    • latest - đã cài đặt phiên bản mới nhất
    • absent - đã xóa (apt-get remove)
    • purged — đã bị xóa cùng với các tập tin cấu hình (apt-get purge)
    • held - phiên bản gói bị khóa (apt-mark hold)
    • любая другая строка - phiên bản được chỉ định đã được cài đặt
  • cài đặt lại_on_refresh - nếu như true, sau khi nhận được thông báo, gói sẽ được cài đặt lại. Hữu ích cho các bản phân phối dựa trên nguồn, trong đó việc xây dựng lại các gói có thể cần thiết khi thay đổi các tham số bản dựng. Mặc định false.

dịch vụ

Quản lý các dịch vụ. Có thể xử lý thông báo - khởi động lại dịch vụ.

Trả lời:

  • tên tài nguyên - dịch vụ được quản lý (tùy chọn)
  • tên — dịch vụ cần được quản lý (nếu không được chỉ định trong tên)
  • đảm bảo - trạng thái mong muốn của dịch vụ:
    • running - ra mắt
    • stopped - dừng lại
  • cho phép — kiểm soát khả năng khởi động dịch vụ:
    • true — tính năng tự động chạy được bật (systemctl enable)
    • mask - cải trang (systemctl mask)
    • false — tính năng tự động chạy bị vô hiệu hóa (systemctl disable)
  • khởi động lại - lệnh khởi động lại dịch vụ
  • tình trạng - lệnh kiểm tra trạng thái dịch vụ
  • đã khởi động lại - cho biết liệu bản initscript của dịch vụ có hỗ trợ khởi động lại hay không. Nếu như false và tham số được chỉ định khởi động lại - giá trị của tham số này được sử dụng. Nếu như false và tham số khởi động lại không được chỉ định - dịch vụ bị dừng và bắt đầu khởi động lại (nhưng systemd sử dụng lệnh systemctl restart).
  • trạng thái - cho biết liệu initscript dịch vụ có hỗ trợ lệnh hay không status. Nếu false, thì giá trị tham số được sử dụng tình trạng. Mặc định true.

giám đốc điều hành

Chạy các lệnh bên ngoài. Nếu bạn không chỉ định tham số tạo ra, chỉ nếu, trừ khi hoặc sảng khoái, lệnh sẽ được chạy mỗi khi Puppet được chạy. Có thể xử lý thông báo - chạy lệnh.

Trả lời:

  • tên tài nguyên - lệnh được thực thi (tùy chọn)
  • lệnh - lệnh được thực thi (nếu nó không được chỉ định trong tên)
  • con đường — đường dẫn để tìm file thực thi
  • chỉ nếu - nếu lệnh được chỉ định trong tham số này hoàn thành với mã trả về bằng XNUMX, lệnh chính sẽ được thực thi
  • trừ khi - nếu lệnh được chỉ định trong tham số này hoàn thành với mã trả về khác XNUMX, lệnh chính sẽ được thực thi
  • tạo ra - nếu tệp được chỉ định trong tham số này không tồn tại, lệnh chính sẽ được thực thi
  • sảng khoái - nếu như true, thì lệnh sẽ chỉ được chạy khi người thực thi này nhận được thông báo từ các tài nguyên khác
  • cwd - thư mục để chạy lệnh
  • người sử dụng — người dùng sẽ chạy lệnh từ ai
  • nhà cung cấp dịch vụ - cách chạy lệnh:
    • posix — một tiến trình con được tạo đơn giản, hãy nhớ chỉ định con đường
    • shell - lệnh được khởi chạy trong shell /bin/sh, có thể không được chỉ định con đường, bạn có thể sử dụng tính năng toàn cầu, đường ống và các tính năng vỏ khác. Thường được phát hiện tự động nếu có bất kỳ ký tự đặc biệt nào (|, ;, &&, || vân vân).

cron

Kiểm soát cronjob.

Trả lời:

  • tên tài nguyên - chỉ là một số loại nhận dạng
  • đảm bảo - trạng thái vương miện:
    • present - tạo nếu không tồn tại
    • absent - xóa nếu tồn tại
  • lệnh - chạy lệnh gì
  • môi trường — nên chạy lệnh trong môi trường nào (danh sách các biến môi trường và giá trị của chúng thông qua =)
  • người sử dụng - từ người dùng nào sẽ chạy lệnh
  • phút, giờ, ngày trong tuần, tháng, tháng ngày — khi nào nên chạy cron. Nếu bất kỳ thuộc tính nào trong số này không được chỉ định, giá trị của nó trong crontab sẽ là *.

Trong con rối 6.0 cron như nó đã được được lấy ra khỏi hộp trong máy chủ con rối, do đó không có tài liệu nào trên trang web chung. Nhưng anh đang ở trong hộp trong tác nhân bù nhìn nên không cần phải cài đặt riêng. Bạn có thể xem tài liệu về nó trong tài liệu dành cho phiên bản thứ năm của PuppetHoặc trên GitHub.

Về tài nguyên nói chung

Yêu cầu về tính duy nhất của tài nguyên

Lỗi phổ biến nhất chúng ta gặp phải là Khai báo trùng lặp. Lỗi này xảy ra khi hai hoặc nhiều tài nguyên cùng loại có cùng tên xuất hiện trong thư mục.

Vì vậy, tôi sẽ viết lại: các bảng kê khai cho cùng một nút không được chứa các tài nguyên cùng loại có cùng tiêu đề!

Đôi khi có nhu cầu cài đặt các gói có cùng tên nhưng với các trình quản lý gói khác nhau. Trong trường hợp này, bạn cần sử dụng tham số nameđể tránh lỗi:

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

Các loại tài nguyên khác có các tùy chọn tương tự để giúp tránh trùng lặp - name у dịch vụ, command у giám đốc điều hành, và như thế.

Siêu thông số

Mỗi loại tài nguyên có một số tham số đặc biệt, bất kể bản chất của nó.

Danh sách đầy đủ các tham số meta trong tài liệu Con rối.

Danh sách ngắn:

  • yêu cầu — tham số này cho biết tài nguyên này phụ thuộc vào tài nguyên nào.
  • trước - Tham số này chỉ định tài nguyên nào phụ thuộc vào tài nguyên này.
  • đăng ký — tham số này chỉ định tài nguyên nào nhận được thông báo.
  • thông báo — Tham số này chỉ định tài nguyên nào nhận được thông báo từ tài nguyên này.

Tất cả các siêu thông số được liệt kê đều chấp nhận một liên kết tài nguyên hoặc một mảng liên kết trong dấu ngoặc vuông.

Liên kết đến các tài nguyên

Một liên kết tài nguyên chỉ đơn giản là sự đề cập đến tài nguyên đó. Chúng chủ yếu được sử dụng để chỉ ra sự phụ thuộc. Tham chiếu tới một tài nguyên không tồn tại sẽ gây ra lỗi biên dịch.

Cú pháp của liên kết như sau: loại tài nguyên có chữ in hoa (nếu tên loại chứa dấu hai chấm kép thì mỗi phần tên giữa các dấu hai chấm được viết hoa), sau đó tên tài nguyên trong ngoặc vuông (trường hợp tên không thay đổi!). Không được có khoảng trắng; dấu ngoặc vuông được viết ngay sau tên loại.

Ví dụ:

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

Phụ thuộc và thông báo

Tài liệu ở đây.

Như đã nêu trước đó, sự phụ thuộc đơn giản giữa các tài nguyên có tính chất bắc cầu. Nhân tiện, hãy cẩn thận khi thêm các phần phụ thuộc - bạn có thể tạo các phần phụ thuộc theo chu kỳ, điều này sẽ gây ra lỗi biên dịch.

Không giống như phần phụ thuộc, thông báo không mang tính bắc cầu. Các quy tắc sau áp dụng cho thông báo:

  • Nếu tài nguyên nhận được thông báo, nó sẽ được cập nhật. Các hành động cập nhật phụ thuộc vào loại tài nguyên - giám đốc điều hành chạy lệnh, dịch vụ khởi động lại dịch vụ, gói cài đặt lại gói. Nếu tài nguyên không có hành động cập nhật được xác định thì sẽ không có gì xảy ra.
  • Trong một lần chạy Puppet, tài nguyên được cập nhật không quá một lần. Điều này có thể thực hiện được vì thông báo bao gồm các phần phụ thuộc và biểu đồ phụ thuộc không chứa chu trình.
  • Nếu Puppet thay đổi trạng thái của tài nguyên, tài nguyên đó sẽ gửi thông báo đến tất cả các tài nguyên đã đăng ký với nó.
  • Nếu một tài nguyên được cập nhật, nó sẽ gửi thông báo tới tất cả các tài nguyên đã đăng ký với nó.

Xử lý các tham số không xác định

Theo quy định, nếu một số tham số tài nguyên không có giá trị mặc định và tham số này không được chỉ định trong tệp kê khai thì Puppet sẽ không thay đổi thuộc tính này cho tài nguyên tương ứng trên nút. Ví dụ: nếu một tài nguyên thuộc loại hồ sơ tham số không được chỉ định owner, khi đó Puppet sẽ không thay đổi chủ sở hữu của file tương ứng.

Giới thiệu về lớp, biến và định nghĩa

Giả sử chúng ta có một số nút có cùng một phần cấu hình, nhưng cũng có những khác biệt - nếu không, chúng ta có thể mô tả tất cả trong một khối node {}. Tất nhiên, bạn có thể chỉ cần sao chép các phần giống hệt nhau của cấu hình, nhưng nhìn chung đây là một giải pháp tồi - cấu hình sẽ tăng lên và nếu bạn thay đổi phần chung của cấu hình, bạn sẽ phải chỉnh sửa điều tương tự ở nhiều chỗ. Đồng thời, rất dễ mắc sai lầm và nhìn chung nguyên tắc DRY (không lặp lại chính mình) được phát minh ra là có lý do.

Để giải quyết vấn đề này có một thiết kế như lớp.

Các lớp học

lớp là một khối mã poppet được đặt tên. Cần có các lớp để sử dụng lại mã.

Đầu tiên lớp học cần được mô tả. Bản thân mô tả không thêm bất kỳ tài nguyên nào vào bất kỳ đâu. Lớp được mô tả trong bảng kê khai:

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

Sau này lớp có thể được sử dụng:

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

Một ví dụ từ nhiệm vụ trước - hãy chuyển cài đặt và cấu hình nginx vào một lớp:

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
}

Biến

Lớp trong ví dụ trước không linh hoạt chút nào vì nó luôn mang cùng cấu hình nginx. Hãy tạo đường dẫn đến biến cấu hình, sau đó lớp này có thể được sử dụng để cài đặt nginx với bất kỳ cấu hình nào.

Nó có thể được thực hiện sử dụng biến.

Chú ý: các biến trong Puppet là bất biến!

Ngoài ra, một biến chỉ có thể được truy cập sau khi nó đã được khai báo, nếu không giá trị của biến sẽ là undef.

Ví dụ về làm việc với các biến:

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

Con rối có không gian tênvà các biến tương ứng có khu vực tầm nhìn: Một biến có cùng tên có thể được định nghĩa trong các không gian tên khác nhau. Khi phân giải giá trị của một biến, biến đó sẽ được tìm kiếm trong không gian tên hiện tại, sau đó trong không gian tên kèm theo, v.v.

Ví dụ về không gian tên:

  • toàn cầu - các biến bên ngoài mô tả lớp hoặc nút sẽ ở đó;
  • không gian tên nút trong mô tả nút;
  • không gian tên lớp trong mô tả lớp.

Để tránh sự mơ hồ khi truy cập một biến, bạn có thể chỉ định vùng tên trong tên biến:

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

Hãy đồng ý rằng đường dẫn đến cấu hình nginx nằm trong biến $nginx_conf_source. Sau đó, lớp sẽ trông như thế này:

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
}

Tuy nhiên, ví dụ đã cho là tệ vì có một số “kiến thức bí mật” rằng ở đâu đó bên trong lớp, một biến có tên như vậy sẽ được sử dụng. Sẽ đúng hơn nhiều nếu làm cho kiến ​​​​thức này trở nên tổng quát - các lớp có thể có tham số.

Tham số lớp là các biến trong không gian tên lớp, chúng được chỉ định trong tiêu đề lớp và có thể được sử dụng như các biến thông thường trong thân lớp. Các giá trị tham số được chỉ định khi sử dụng lớp trong tệp kê khai.

Tham số có thể được đặt thành giá trị mặc định. Nếu một tham số không có giá trị mặc định và giá trị đó không được đặt khi sử dụng, nó sẽ gây ra lỗi biên dịch.

Hãy tham số hóa lớp từ ví dụ trên và thêm hai tham số: tham số đầu tiên, bắt buộc, là đường dẫn đến cấu hình và tham số thứ hai, tùy chọn, là tên của gói có nginx (ví dụ: trong Debian, có các gói 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',   # задаём параметры класса точно так же, как параметры для других ресурсов
  }
}

Trong Puppet, các biến được gõ. Ăn nhiều kiểu dữ liệu. Các kiểu dữ liệu thường được sử dụng để xác thực các giá trị tham số được truyền cho các lớp và định nghĩa. Nếu tham số được truyền không khớp với loại đã chỉ định thì sẽ xảy ra lỗi biên dịch.

Loại được viết ngay trước tên tham số:

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

Các lớp: bao gồm tên lớp và lớp {'classname':}

Mỗi lớp là một loại tài nguyên tốt nghiệp lớp XNUMX. Giống như bất kỳ loại tài nguyên nào khác, không thể có hai phiên bản của cùng một lớp trên cùng một nút.

Nếu bạn cố gắng thêm một lớp vào cùng một nút hai lần bằng cách sử dụng class { 'classname':} (không có sự khác biệt, có tham số khác hoặc giống nhau) sẽ xảy ra lỗi biên dịch. Nhưng nếu bạn sử dụng một lớp theo kiểu tài nguyên, bạn có thể đặt ngay lập tức tất cả các tham số của nó trong tệp kê khai một cách rõ ràng.

Tuy nhiên, nếu bạn sử dụng include, sau đó lớp có thể được thêm bao nhiêu lần tùy thích. Sự thật là include là một hàm bình thường để kiểm tra xem một lớp đã được thêm vào thư mục chưa. Nếu lớp không có trong thư mục, nó sẽ thêm nó và nếu nó đã tồn tại thì nó không làm gì cả. Nhưng trong trường hợp sử dụng include Bạn không thể đặt tham số lớp trong khi khai báo lớp - tất cả tham số bắt buộc phải được đặt trong nguồn dữ liệu ngoài - Hiera hoặc ENC. Chúng ta sẽ nói về chúng trong bài viết tiếp theo.

Định nghĩa

Như đã nói ở khối trước, cùng một lớp không thể xuất hiện trên một nút nhiều lần. Tuy nhiên, trong một số trường hợp, bạn cần có khả năng sử dụng cùng một khối mã với các tham số khác nhau trên cùng một nút. Nói cách khác, cần có một loại tài nguyên riêng.

Ví dụ: để cài đặt mô-đun PHP, chúng tôi thực hiện như sau trong Avito:

  1. Cài đặt gói với mô-đun này.
  2. Hãy tạo một tập tin cấu hình cho mô-đun này.
  3. Chúng tôi tạo một liên kết tượng trưng đến cấu hình cho php-fpm.
  4. Chúng tôi tạo một liên kết tượng trưng đến cấu hình cho php cli.

Trong những trường hợp như vậy, một thiết kế như định nghĩa (xác định, xác định loại, xác định loại tài nguyên). A Xác định tương tự như một lớp, nhưng có những khác biệt: thứ nhất, mỗi Xác định là một loại tài nguyên, không phải là tài nguyên; thứ hai, mỗi định nghĩa có một tham số ngầm định $title, nơi tên tài nguyên xuất hiện khi nó được khai báo. Cũng giống như trường hợp các lớp, định nghĩa trước tiên phải được mô tả, sau đó mới có thể sử dụng nó.

Một ví dụ đơn giản với mô-đun dành cho 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' }
}

Cách dễ nhất để bắt lỗi Khai báo trùng lặp là trong phần Xác định. Điều này xảy ra nếu một định nghĩa có một tài nguyên có tên không đổi và có hai hoặc nhiều phiên bản của định nghĩa này trên một số nút.

Thật dễ dàng để bảo vệ bạn khỏi điều này: tất cả các tài nguyên bên trong định nghĩa phải có tên tùy thuộc vào $title. Một cách khác là bổ sung tài nguyên bình thường; trong trường hợp đơn giản nhất, chỉ cần di chuyển các tài nguyên chung cho tất cả các trường hợp của định nghĩa vào một lớp riêng biệt và đưa lớp này vào định nghĩa - hàm là đủ include bình thường.

Có nhiều cách khác để đạt được tính bình thường khi thêm tài nguyên, cụ thể là sử dụng hàm defined и ensure_resources, nhưng tôi sẽ kể cho bạn nghe về điều đó trong tập tiếp theo.

Sự phụ thuộc và thông báo cho các lớp và định nghĩa

Các lớp và định nghĩa thêm các quy tắc sau để xử lý các phần phụ thuộc và thông báo:

  • sự phụ thuộc vào một lớp/định nghĩa sẽ thêm các phụ thuộc vào tất cả các tài nguyên của lớp/định nghĩa;
  • một phần phụ thuộc lớp/xác định sẽ thêm các phụ thuộc vào tất cả các tài nguyên lớp/xác định;
  • thông báo lớp/định nghĩa thông báo tất cả các tài nguyên của lớp/định nghĩa;
  • đăng ký class/define đăng ký tất cả các tài nguyên của lớp/define.

Câu lệnh có điều kiện và bộ chọn

Tài liệu ở đây.

if

Mọi thứ đều đơn giản ở đây:

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

trừ khi

trừ khi là if ngược lại: khối mã sẽ được thực thi nếu biểu thức sai.

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

trường hợp

Không có gì phức tạp ở đây cả. Bạn có thể sử dụng các giá trị thông thường (chuỗi, số, v.v.), biểu thức thông thường và kiểu dữ liệu làm giá trị.

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

Bộ chọn

Bộ chọn là một cấu trúc ngôn ngữ tương tự như case, nhưng thay vì thực thi một khối mã, nó trả về một giá trị.

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

Mô-đun

Khi cấu hình nhỏ, nó có thể dễ dàng được lưu giữ trong một bảng kê khai. Nhưng chúng ta càng mô tả nhiều cấu hình thì càng có nhiều lớp và nút trong tệp kê khai, nó sẽ phát triển và trở nên bất tiện khi làm việc.

Ngoài ra, còn có vấn đề về việc sử dụng lại mã - khi tất cả mã nằm trong một bảng kê khai, rất khó để chia sẻ mã này với người khác. Để giải quyết hai vấn đề này, Puppet có một thực thể gọi là mô-đun.

Mô-đun - đây là tập hợp các lớp, định nghĩa và các thực thể Puppet khác được đặt trong một thư mục riêng. Nói cách khác, một mô-đun là một phần độc lập của logic Puppet. Ví dụ: có thể có một mô-đun để làm việc với nginx và nó sẽ chứa những gì và chỉ những gì cần thiết để làm việc với nginx hoặc có thể có một mô-đun để làm việc với PHP, v.v.

Các mô-đun được lập phiên bản và sự phụ thuộc của các mô-đun với nhau cũng được hỗ trợ. Có một kho mô-đun mở - Lò rèn con rối.

Trên máy chủ con rối, các mô-đun được đặt trong thư mục con mô-đun của thư mục gốc. Bên trong mỗi mô-đun có một sơ đồ thư mục tiêu chuẩn - bảng kê khai, tệp, mẫu, lib, v.v.

Cấu trúc tệp trong một mô-đun

Thư mục gốc của mô-đun có thể chứa các thư mục sau với tên mô tả:

  • manifests - nó chứa các bản tuyên ngôn
  • files - nó chứa các tập tin
  • templates - nó chứa các mẫu
  • lib - nó chứa mã Ruby

Đây không phải là danh sách đầy đủ các thư mục và tập tin, nhưng hiện tại nó là đủ cho bài viết này.

Tên tài nguyên và tên tệp trong mô-đun

Tài liệu ở đây.

Tài nguyên (lớp, định nghĩa) trong mô-đun không thể được đặt tên theo bất kỳ tên nào bạn muốn. Ngoài ra, có sự tương ứng trực tiếp giữa tên của tài nguyên và tên của tệp mà Puppet sẽ tìm kiếm mô tả về tài nguyên đó. Nếu bạn vi phạm các quy tắc đặt tên, thì Puppet sẽ không tìm thấy mô tả tài nguyên và bạn sẽ gặp lỗi biên dịch.

Các quy tắc rất đơn giản:

  • Tất cả tài nguyên trong một mô-đun phải nằm trong không gian tên mô-đun. Nếu mô-đun được gọi foo, thì tất cả tài nguyên trong đó phải được đặt tên foo::<anything>, hoặc chỉ foo.
  • Tài nguyên có tên mô-đun phải có trong tệp init.pp.
  • Đối với các tài nguyên khác, sơ đồ đặt tên tệp như sau:
    • tiền tố có tên mô-đun bị loại bỏ
    • tất cả dấu hai chấm, nếu có, được thay thế bằng dấu gạch chéo
    • phần mở rộng được thêm vào .pp

Tôi sẽ chứng minh bằng một ví dụ. Giả sử tôi đang viết một mô-đun nginx. Nó chứa các tài nguyên sau:

  • lớp nginx được mô tả trong bảng kê khai init.pp;
  • lớp nginx::service được mô tả trong bảng kê khai service.pp;
  • định nghĩa nginx::server được mô tả trong bảng kê khai server.pp;
  • định nghĩa nginx::server::location được mô tả trong bảng kê khai server/location.pp.

Templates

Chắc chắn bạn cũng biết mẫu là gì, tôi sẽ không mô tả chi tiết ở đây. Nhưng tôi sẽ để nó lại trong trường hợp liên kết tới Wikipedia.

Cách sử dụng mẫu: Ý nghĩa của mẫu có thể được mở rộng bằng cách sử dụng hàm template, được chuyển đường dẫn đến mẫu. Đối với tài nguyên thuộc loại hồ sơ được sử dụng cùng với tham số content. Ví dụ như thế này:

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

Xem đường dẫn <modulename>/<filename> ngụ ý tập tin <rootdir>/modules/<modulename>/templates/<filename>.

Ngoài ra, có một chức năng inline_template — nó nhận văn bản mẫu làm đầu vào chứ không phải tên tệp.

Trong các mẫu, bạn có thể sử dụng tất cả các biến Puppet trong phạm vi hiện tại.

Con rối hỗ trợ các mẫu ở định dạng ERB và EPP:

Sơ lược về ERB

Cấu trúc điều khiển:

  • <%= ВЫРАЖЕНИЕ %> - chèn giá trị của biểu thức
  • <% ВЫРАЖЕНИЕ %> — tính giá trị của một biểu thức (không cần chèn nó). Câu lệnh có điều kiện (if) và vòng lặp (mỗi) thường xuất hiện ở đây.
  • <%# КОММЕНТАРИЙ %>

Các biểu thức trong ERB được viết bằng Ruby (ERB thực ra là Ruby nhúng).

Để truy cập các biến từ bảng kê khai, bạn cần thêm @ vào tên biến. Để xóa dấu ngắt dòng xuất hiện sau cấu trúc điều khiển, bạn cần sử dụng thẻ đóng -%>.

Ví dụ về việc sử dụng mẫu

Giả sử tôi đang viết một mô-đun để điều khiển ZooKeeper. Lớp chịu trách nhiệm tạo cấu hình trông giống như thế này:

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

Và mẫu tương ứng zoo.cfg.erb - Vì thế:

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

Sự kiện và các biến tích hợp

Thông thường phần cụ thể của cấu hình phụ thuộc vào những gì hiện đang xảy ra trên nút. Ví dụ: tùy thuộc vào bản phát hành Debian là gì, bạn cần cài đặt phiên bản này hoặc phiên bản khác của gói. Bạn có thể theo dõi tất cả điều này một cách thủ công, viết lại bảng kê khai nếu các nút thay đổi. Nhưng đây không phải là một cách tiếp cận nghiêm túc; tự động hóa sẽ tốt hơn nhiều.

Để có được thông tin về các nút, Puppet có một cơ chế gọi là sự kiện. Sự thật - đây là thông tin về nút, có sẵn trong các tệp kê khai dưới dạng các biến thông thường trong không gian tên chung. Ví dụ: tên máy chủ, phiên bản hệ điều hành, kiến ​​trúc bộ xử lý, danh sách người dùng, danh sách giao diện mạng và địa chỉ của họ, v.v. Sự kiện có sẵn trong các bảng kê khai và mẫu dưới dạng các biến thông thường.

Một ví dụ về làm việc với sự kiện:

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

Nói một cách chính thức, một thực tế có tên (chuỗi) và giá trị (có nhiều loại khác nhau: chuỗi, mảng, từ điển). Ăn tập hợp các sự kiện tích hợp. Bạn có thể tự viết mà. Người thu thập thông tin được mô tả giống như các hàm trong Ruby, hoặc cả hai Các tập tin thực thi. Sự thật cũng có thể được trình bày dưới dạng tập tin văn bản với dữ liệu trên các nút.

Trong quá trình hoạt động, tác nhân bù nhìn trước tiên sao chép tất cả các bộ thu thập dữ kiện có sẵn từ máy chủ pappet đến nút, sau đó nó khởi chạy chúng và gửi các dữ kiện đã thu thập được đến máy chủ; Sau đó, máy chủ bắt đầu biên soạn danh mục.

Sự kiện ở dạng tập tin thực thi

Những sự kiện như vậy được đặt trong các mô-đun trong thư mục facts.d. Tất nhiên, các tập tin phải có khả năng thực thi được. Khi chạy, chúng phải xuất thông tin ra đầu ra tiêu chuẩn ở định dạng YAML hoặc key=value.

Đừng quên rằng thực tế áp dụng cho tất cả các nút được kiểm soát bởi máy chủ poppet mà mô-đun của bạn được triển khai. Do đó, trong tập lệnh, hãy chú ý kiểm tra xem hệ thống có tất cả các chương trình và tệp cần thiết để thực tế của bạn hoạt động hay không.

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

Sự thật về Ruby

Những sự kiện như vậy được đặt trong các mô-đun trong thư mục 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

sự kiện văn bản

Những thông tin như vậy được đặt trên các nút trong thư mục /etc/facter/facts.d trong Puppet cũ hoặc /etc/puppetlabs/facts.d trong Con rối mới.

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

Đi đến sự thật

Có hai cách để tiếp cận sự thật:

  • qua từ điển $facts: $facts['fqdn'];
  • sử dụng tên thực tế làm tên biến: $fqdn.

Tốt nhất là dùng từ điển $facts, hoặc thậm chí tốt hơn, chỉ ra không gian tên chung ($::facts).

Đây là phần có liên quan của tài liệu.

Biến tích hợp

Bên cạnh sự thật còn có một số biến, có sẵn trong không gian tên chung.

  • sự thật đáng tin cậy — các biến được lấy từ chứng chỉ của máy khách (vì chứng chỉ thường được cấp trên máy chủ poppet, nên tác nhân không thể lấy và thay đổi chứng chỉ của nó, vì vậy các biến là “đáng tin cậy”): tên của chứng chỉ, tên của máy chủ và tên miền, phần mở rộng từ chứng chỉ.
  • sự thật về máy chủ —các biến liên quan đến thông tin về máy chủ—phiên bản, tên, địa chỉ IP máy chủ, môi trường.
  • sự kiện đại lý — các biến được thêm trực tiếp bởi tác nhân bù nhìn chứ không phải theo thực tế — tên chứng chỉ, phiên bản tác nhân, phiên bản rối.
  • biến chủ - Biến Pappetmaster (sic!). Nó gần giống như trong sự thật về máy chủ, cộng với các giá trị tham số cấu hình có sẵn.
  • biến trình biên dịch - các biến trình biên dịch khác nhau trong từng phạm vi: tên của mô-đun hiện tại và tên của mô-đun mà đối tượng hiện tại được truy cập. Ví dụ: chúng có thể được sử dụng để kiểm tra xem các lớp riêng tư của bạn không được sử dụng trực tiếp từ các mô-đun khác hay không.

Bổ sung 1: làm thế nào để chạy và gỡ lỗi tất cả điều này?

Bài viết có nhiều ví dụ về mã rối, nhưng không cho chúng ta biết cách chạy mã này. Ờ, tôi đang tự sửa lại.

Một tác nhân là đủ để chạy Puppet, nhưng trong hầu hết các trường hợp, bạn cũng sẽ cần một máy chủ.

Đại lý

Ít nhất kể từ phiên bản XNUMX, các gói tác nhân bù nhìn từ kho lưu trữ Puppetlabs chính thức chứa tất cả các phần phụ thuộc (ruby và các viên đá quý tương ứng), do đó không gặp khó khăn gì khi cài đặt (Tôi đang nói về các bản phân phối dựa trên Debian - chúng tôi không sử dụng các bản phân phối dựa trên RPM).

Trong trường hợp đơn giản nhất, để sử dụng cấu hình con rối, việc khởi chạy tác nhân ở chế độ không có máy chủ là đủ: với điều kiện mã con rối được sao chép vào nút, hãy khởi chạy 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

Tất nhiên, tốt hơn là bạn nên thiết lập máy chủ và chạy các tác nhân trên các nút ở chế độ daemon - sau đó cứ nửa giờ chúng sẽ áp dụng cấu hình được tải xuống từ máy chủ.

Bạn có thể bắt chước mô hình đẩy của công việc - đi tới nút bạn quan tâm và bắt đầu sudo puppet agent -t. Chìa khóa -t (--test) thực sự bao gồm một số tùy chọn có thể được kích hoạt riêng lẻ. Các tùy chọn này bao gồm:

  • không chạy ở chế độ daemon (theo mặc định, tác nhân khởi động ở chế độ daemon);
  • tắt sau khi áp dụng danh mục (theo mặc định, tác nhân sẽ tiếp tục làm việc và áp dụng cấu hình cứ nửa giờ một lần);
  • viết nhật ký công việc chi tiết;
  • hiển thị những thay đổi trong tập tin.

Tác nhân có chế độ hoạt động không có thay đổi - bạn có thể sử dụng nó khi bạn không chắc chắn rằng mình đã viết đúng cấu hình và muốn kiểm tra chính xác những gì tác nhân sẽ thay đổi trong quá trình hoạt động. Chế độ này được kích hoạt bởi tham số --noop trên dòng lệnh: sudo puppet agent -t --noop.

Ngoài ra, bạn có thể kích hoạt nhật ký gỡ lỗi của công việc - trong đó, con rối viết về tất cả các hành động mà nó thực hiện: về tài nguyên mà nó hiện đang xử lý, về các tham số của tài nguyên này, về những chương trình mà nó khởi chạy. Tất nhiên đây là một tham số --debug.

Máy chủ

Tôi sẽ không xem xét việc thiết lập đầy đủ của pappetserver và triển khai mã cho nó trong bài viết này; tôi sẽ chỉ nói rằng ngay lập tức có một phiên bản máy chủ đầy đủ chức năng không yêu cầu cấu hình bổ sung để hoạt động với một số lượng nhỏ máy chủ. các nút (giả sử lên tới một trăm). Số lượng nút lớn hơn sẽ yêu cầu điều chỉnh - theo mặc định, máy chủ con rối khởi chạy không quá bốn công nhân, để có hiệu suất cao hơn, bạn cần tăng số lượng của chúng và đừng quên tăng giới hạn bộ nhớ, nếu không máy chủ sẽ thu gom rác hầu hết thời gian.

Triển khai mã - nếu bạn cần nhanh chóng và dễ dàng, hãy xem (tại r10k)[https://github.com/puppetlabs/r10k], đối với những cài đặt nhỏ thì nó là khá đủ.

Phụ lục 2: Nguyên tắc mã hóa

  1. Đặt tất cả logic vào các lớp và định nghĩa.
  2. Giữ các lớp và định nghĩa trong các mô-đun, không phải trong các bảng kê khai mô tả các nút.
  3. Sử dụng sự thật.
  4. Đừng tạo if dựa trên tên máy chủ.
  5. Vui lòng thêm tham số cho các lớp và định nghĩa - điều này tốt hơn so với logic ngầm ẩn trong phần thân của lớp/định nghĩa.

Tôi sẽ giải thích lý do tại sao tôi khuyên bạn nên làm điều này trong bài viết tiếp theo.

Kết luận

Hãy kết thúc với phần giới thiệu. Trong bài viết tiếp theo tôi sẽ kể cho bạn nghe về Hiera, ENC và PuppetDB.

Chỉ những người dùng đã đăng ký mới có thể tham gia khảo sát. Đăng nhập, xin vui lòng.

Trên thực tế, còn có nhiều tài liệu hơn - tôi có thể viết bài về các chủ đề sau, bình chọn những gì bạn muốn đọc:

  • 59,1%Cấu trúc con rối nâng cao - một số nội dung cấp độ tiếp theo: vòng lặp, ánh xạ và các biểu thức lambda khác, bộ thu thập tài nguyên, tài nguyên được xuất và giao tiếp giữa các máy chủ thông qua Con rối, thẻ, nhà cung cấp, kiểu dữ liệu trừu tượng.13
  • 31,8%“Tôi là quản trị viên của mẹ tôi” hoặc cách chúng tôi ở Avito kết bạn với một số máy chủ poppet thuộc các phiên bản khác nhau và về nguyên tắc, phần quản trị máy chủ poppet.7
  • 81,8%Cách chúng tôi viết mã rối: thiết bị đo đạc, tài liệu, thử nghiệm, CI/CD.18

22 người dùng bình chọn. 9 người dùng bỏ phiếu trắng.

Nguồn: www.habr.com