Я начинаю с анзибль и будет использовать его, среди прочего, для установки пакетов в нескольких дистрибутивах 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"
Я понимаю, что два менеджера пакетов разные, но у них все еще есть набор общих базовых применений. Другие оркестровщики (соль например) есть одна команда установки.
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
РЕДАКТИРОВАТЬ: Начиная с Майкла ДеХаана (создателя Ansible) решил не абстрагироваться от модулей диспетчера пакетов лайк Повар делает,
Если вы все еще используете старую версию Ansible (Ansible <2.0), к сожалению, вам придется сделать это в все ваших пьес и ролей. по моему мнению это заставляет авторов сценария и ролей выполнять множество ненужных и повторяющихся задач ... но так оно и есть сейчас. Обратите внимание: я не говорю, что мы должны пытаться абстрагироваться от менеджеров пакетов, при этом пытаясь поддерживать все их конкретные параметры и команды, а просто иметь простой способ установить пакет, который не зависит от менеджера пакетов. Я также не говорю, что мы все должны прыгать на Умный менеджер пакетов победитель, но этот своего рода уровень абстракции установки пакетов в вашем инструменте управления конфигурацией очень полезен для упрощения кроссплатформенных playbooks / cookbooks. Смарт-проект выглядит интересным, но он довольно амбициозен - унифицировать управление пакетами между дистрибутивами и платформами без особого принятия ... будет интересно посмотреть, будет ли он успешным. Реальная проблема заключается в том, что имена пакетов иногда имеют тенденцию отличаться в разных дистрибутивах, поэтому нам все равно нужно делать операторы case или 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'
Затем для разных менеджеров пакетов:
Квартира:
---
# 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
Ням:
---
# 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
Обратите внимание, что это ужасно повторяется, а не D.R.Y., и хотя некоторые вещи мощь будет отличаться на разных платформах, и с ним придется работать, в целом я думаю, что это многословно и громоздко по сравнению с Chef:
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
И да, есть аргумент, что некоторые имена пакетов в разных дистрибутивах разные. И хотя в настоящее время существует отсутствие легкодоступных данных, Рискну предположить, что большинство популярные имена пакетов являются общими для разных дистрибутивов и могут быть установлены с помощью абстрактного модуля диспетчера пакетов. В любом случае нужно будет разобраться со специальными случаями, которые уже потребуют дополнительной работы, чтобы уменьшить D.R.Y. Если сомневаетесь, проверьте pkgs.org.
Вы можете абстрагироваться от менеджеров пакетов с помощью фактов
- name: Install packages
with_items: package_list
action: "{{ ansible_pkg_mgr }} state=installed name={{ item }}"
Все, что вам нужно, это логика, которая устанавливает ansible_pkg_mgr
к apt
или yum
и т.п.
Ansible также работают над тем, что вы хотите, в будущем модуле.
В Ansible 2.0 появился новый Package
-модуль.
http://docs.ansible.com/ansible/package_module.html
Затем вы можете использовать его как свое предложение:
- name: install the latest version of Apache
package: name=httpd state=latest
Вы все равно должны учитывать различия в названиях.
Ознакомьтесь с документацией 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
Вы не хотите этого делать, потому что имена некоторых пакетов в разных дистрибутивах различаются. Например, в дистрибутивах, связанных с RHEL, популярный пакет веб-сервера называется httpd
, где, как и в дистрибутивах, связанных с Debian, он называется apache2
. Точно так же с огромным списком других системных и поддерживающих библиотек.
Может быть набор общих основных параметров, но есть также ряд более сложных параметров, которые различаются между менеджерами пакетов. И вы не хотите оказаться в двусмысленной ситуации, когда для некоторых команд вы используете один синтаксис, а для других команд вы используете другой синтаксис.