Як уніфікувати завдання встановлення пакета в ansible?


68

Я починаю з ansible і буду використовувати його, серед інших, для встановлення пакетів у декількох дистрибутивах Linux.

Я бачу в документах, що команди yumі aptкоманди розділені - що було б найпростішим способом уніфікувати їх і використовувати щось подібне:

- name: install the latest version of Apache
  unified_install: name=httpd state=latest

замість

- name: install the latest version of Apache on CentOS
  yum: name=httpd state=latest
  when: ansible_os_family == "RedHat"

- name: install the latest version of Apache on Debian
  apt: pkg=httpd state=latest 
  when: ansible_os_family == "Debian"

Я розумію, що два менеджери пакунків різні, але вони все ще мають набір загальних базових звичок. Інші оркестранти (наприклад, сіль ) мають одну команду встановлення.


У вас може бути три рецепти: один, який повторюється над загальним списком, а потім один для списків, характерних для ОС. Я зараз намагаюся з’ясувати, як сповістити обробника з іменем служби, що відповідає ОС, після встановлення загального елемента конфігурації. Щасти!
dannyman

Відповіді:


66

Оновлення: Станом на Ansible 2.0, тепер існує загальний модуль та абстрагуванняpackage

Приклади використання:

Тепер, коли назва пакету однакова в різних сімействах ОС, це так само просто, як:

---
- name: Install foo
  package: name=foo state=latest

Коли назва пакета відрізняється у сімействах ОС, ви можете обробити його за допомогою файлів vars для розповсюдження або специфічних для сім'ї ОС:

---
# roles/apache/apache.yml: Tasks entry point for 'apache' role. Called by main.yml
# Load a variable file based on the OS type, or a default if not found.
- include_vars: "{{ item }}"
  with_first_found:
    - "../vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version | int}}.yml"
    - "../vars/{{ ansible_distribution }}.yml"
    - "../vars/{{ ansible_os_family }}.yml"
    - "../vars/default.yml"
  when: apache_package_name is not defined or apache_service_name is not defined

- name: Install Apache
  package: >
    name={{ apache_package_name }}
    state=latest

- name: Enable apache service
  service: >
    name={{ apache_service_name }}
    state=started
    enabled=yes
  tags: packages

Потім для кожної ОС, з якою ви маєте працювати по-різному ... створіть файл vars:

---
# roles/apache/vars/default.yml
apache_package_name: apache2
apache_service_name: apache2

---
# roles/apache/vars/RedHat.yml
apache_package_name: httpd
apache_service_name: httpd

---
# roles/apache/vars/SLES.yml
apache_package_name: apache2
apache_service_name: apache2

---
# roles/apache/vars/Debian.yml
apache_package_name: apache2
apache_service_name: apache2

---
# roles/apache/vars/Archlinux.yml
apache_package_name: apache
apache_service_name: httpd



EDIT: Оскільки Майкл ДеХаан (творець Ansible) вирішив не абстрагувати модулі менеджера пакунків, як Chef ,

Якщо ви все ще використовуєте старішу версію Ansible (Ansible <2.0) , на жаль, вам потрібно буде впоратися з цим у всіх своїх іграх і ролях. IMHO це підштовхує багато непотрібних робіт, що повторюються, на авторів ігор та ролей ... але це так, як це є зараз. Зауважте, що я не кажу, що ми повинні намагатися абстрагувати менеджерів пакунків подалі, намагаючись підтримувати всі їх конкретні параметри та команди, а просто мати простий спосіб встановити пакет, який є агностиком менеджера пакунків. Я також не кажу, що всі ми повинні стрибати на Smart Package Managerпростір, але якийсь шар абстракції від встановлення пакету у вашому інструменті управління конфігурацією дуже корисний для спрощення міжплатформних ігор / кулінарних книг. Проект Smart виглядає цікаво, але досить амбітним є уніфікація управління пакунками у різних дистрибутивах та платформах без особливого прийняття… Буде цікаво побачити, чи успішний він. Справжня проблема полягає лише в тому, що назви пакетів іноді мають різницю у різних дистрибутивах, тому нам доводиться робити заяви справи або when:заяви, щоб вирішити відмінності.

Те, як я маю справу з цим, - це слідувати цій tasksструктурі каталогів у книзі чи ролі:

roles/foo
└── tasks
    ├── apt_package.yml
    ├── foo.yml
    ├── homebrew_package.yml
    ├── main.yml
    └── yum_package.yml

І тоді майте це в моєму main.yml:

---
# foo: entry point for tasks
#                 Generally only include other file(s) and add tags here.

- include: foo.yml tags=foo

Це в foo.yml(для пакета 'foo'):

---
# foo: Tasks entry point. Called by main.yml
- include: apt_package.yml
  when: ansible_pkg_mgr == 'apt'
- include: yum_package.yml
  when: ansible_pkg_mgr == 'yum'
- include: homebrew_package.yml
  when: ansible_os_family == 'Darwin'

- name: Enable foo service
  service: >
    name=foo
    state=started
    enabled=yes
  tags: packages
  when: ansible_os_family != 'Darwin'

Тоді для різних менеджерів пакетів:

Apt:

---
# tasks file for installing foo on apt based distros

- name: Install foo package via apt
  apt: >
    name=foo{% if foo_version is defined %}={{ foo_version }}{% endif %}
    state={% if foo_install_latest is defined and foo_version is not defined %}latest{% else %}present{% endif %}
  tags: packages

Yum:

---
# tasks file for installing foo on yum based distros
- name: Install EPEL 6.8 repos (...because it's RedHat and foo is in EPEL for example purposes...)
  yum: >
    name={{ docker_yum_repo_url }}
    state=present
  tags: packages
  when: ansible_os_family == "RedHat" and ansible_distribution_major_version|int == 6

- name: Install foo package via yum
  yum: >
    name=foo{% if foo_version is defined %}-{{ foo_version }}{% endif %}
    state={% if foo_install_latest is defined and foo_version is not defined %}latest{% else %}present{% endif %}
  tags: packages

- name: Install RedHat/yum-based distro specific stuff...
  yum: >
    name=some-other-custom-dependency-on-redhat
    state=latest
  when: ansible_os_family == "RedHat"
  tags: packages

Домашня мова:

---
- name: Tap homebrew foobar/foo
  homebrew_tap: >
    name=foobar/foo
    state=present

- homebrew: >
    name=foo
    state=latest

Зауважте, що це жахливо повторюється, і це НЕ СУХО , і хоча деякі речі можуть бути різними на різних платформах, і їх потрібно буде вирішити, як правило, я вважаю, що це багатослівно і громіздко порівняно з шеф-кухарями:

package 'foo' do
  version node['foo']['version']
end

case node["platform"]
when "debian", "ubuntu"
  # do debian/ubuntu things
when "redhat", "centos", "fedora"
  # do redhat/centos/fedora things
end

І так, є аргумент, що назви деяких пакетів різняться по дистрибутивам. І хоча в даний час є відсутність легкодоступних даних , я б ризикнув припустити , що найбільш популярні імена пакетів є загальними для всіх дистрибутивів і можуть бути встановлені з допомогою відведеного модуля менеджера пакетів. У будь-якому випадку потрібно вирішувати особливі випадки, і це вже потребує додаткової роботи, що робить речі менше ДУХИми, якщо сумніваєтесь, перевірте pkgs.org .


За допомогою Ansible 2 ви можете використовувати модуль пакету, щоб абстрагувати все це docs.ansible.com/ansible/package_module.html
Guido

@ GuidoGarcía: Дуже приємно! Додавання примітки про це для Ansible 2.0
TrinitronX

Можливо, варто також згадати, що ви можете вказати список, розділений комами, або просто список пакетів.
Уес Тернер

13

Ви можете абстрагувати менеджерів пакунків за допомогою фактів

- name: Install packages
  with_items: package_list
  action: "{{ ansible_pkg_mgr }} state=installed name={{ item }}"

Все, що вам потрібно, це певна логіка, яка встановлюється ansible_pkg_mgrна aptі yumт.д.

Відповідальні також працюють над тим, що ви хочете, у майбутньому модулі .


1
Відповідь встановлює ansible_pkg_mgrсебе для будь-якого пакувальника, про якого він знає. Вам нічого не потрібно робити. Я використовую цю конструкцію скрізь.
Майкл Хемптон

Синтаксис все ще досить корисний для тих, хто хоче оптимізувати виконання своїх ігрових книжок. Модуль загального пакету ще не забезпечує оптимізацію for_items, тому він набагато повільніше, коли він використовується для установки декількох пакетів одночасно.
Данила Вершинін

@DanielV. Зауважте, що проблема github дійсно вирішує цю проблему.
Майкл Хемптон

6

З Ansible 2.0 з'явився новий Package-модуль.

http://docs.ansible.com/ansible/package_module.html

Потім ви можете використовувати його як вашу пропозицію:

- name: install the latest version of Apache
  package: name=httpd state=latest

Ви все ще повинні врахувати відмінності імен.


3

Перегляньте документацію Ansible про умовний імпорт .

Одне завдання - забезпечити роботу apache, навіть якщо назви служб різні для кожної ОС.

---
- hosts: all
  remote_user: root
  vars_files:
    - "vars/common.yml"
    - [ "vars/{{ ansible_os_family }}.yml", "vars/os_defaults.yml" ]
  tasks:
  - name: make sure apache is running
    service: name={{ apache }} state=running

2

Ви не хочете цього робити, оскільки певні назви пакунків відрізняються між дистрибутивами. Наприклад, у дистрибутивах, пов'язаних з RHEL, називається популярний пакет веб-серверів httpd, де, як і в дистрибутивах, пов'язаних з Debian, він названий apache2. Аналогічно з величезним списком інших системних та підтримуючих бібліотек.

Можливо, існує набір загальних основних параметрів, але тоді також існує ряд більш досконалих параметрів, які відрізняються між менеджерами пакетів. І ви не хочете опинятися в неоднозначній ситуації, коли для деяких команд ви використовуєте один синтаксис, а для інших команд - інший синтаксис.


Це більш-менш те, чого я очікував (на жаль :)), тому мені цікаво, як saltвдається об’єднати обох менеджерів пакетів. Так чи інакше, я вдадуся до подвійної конфігурації.
WoJ

Або не керуйте зоопарком дистрибуції ;-) переходите до інфраструктури з одним дистрибутивом і живете щасливішим життям.
Mxx

На щастя, у великій кількості лише дві тварини, але це найнижча кількість, на яку я можу зайти :)
WoJ

1
@Mxx - це нормальна логіка для sysadmin, але як щодо постачальника програмного забезпечення або консультанта, який підтримує кілька платформ?
Девід Х. Беннетт

@David, тоді це потрібно вирішити у постачальників дистрибутивів, щоб вони мали уніфіковані назви пакетів та встановлювали інструменти. Реально немає можливості, що Ansible може мати уніфіковане відображення ВСІХ пакетів з усіх підтримуваних дистрибутивів усіх версій.
Mxx
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.