
Ich beginne mitansibleund werde es unter anderem verwenden, um Pakete auf verschiedenen Linux-Distributionen zu installieren.
Ich sehe in den Dokumenten, dass die Befehle yum
und apt
getrennt sind. Was wäre der einfachste Weg, sie zu vereinheitlichen und etwa Folgendes zu verwenden:
- name: install the latest version of Apache
unified_install: name=httpd state=latest
anstatt
- 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"
Ich verstehe, dass die beiden Paketmanager unterschiedlich sind, aber sie haben dennoch eine Reihe gemeinsamer grundlegender Verwendungszwecke. Andere Orchestratoren (Salz zum Beispiel) haben einen einzigen Installationsbefehl.
Antwort1
Update: Ab Ansible 2.0 gibt es nun eine generische und abstrahiertepackage
Modul
Anwendungsbeispiele:
Wenn der Paketname in verschiedenen Betriebssystemfamilien derselbe ist, ist es so einfach wie:
---
- name: Install foo
package: name=foo state=latest
Wenn sich der Paketname zwischen den Betriebssystemfamilien unterscheidet, können Sie dies mit distributions- oder betriebssystemfamilienspezifischen Vars-Dateien behandeln:
---
# 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
Erstellen Sie dann für jedes Betriebssystem, das Sie anders handhaben müssen, eine Vars-Datei:
---
# 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
BEARBEITEN: Seit Michael DeHaan (Erfinder von Ansible)hat sich entschieden, die Paketmanagermodule nicht zu abstrahierenwieKochtut,
Wenn Sie noch eine ältere Version von Ansible verwenden (Ansible < 2.0), leider müssen Sie dies inalleIhrer Spielbücher und Rollen. meiner bescheidenen Meinung nachdies schiebt eine Menge unnötiger, sich wiederholender Arbeit auf Playbook- und Rollenautoren … aber so ist es derzeit. Beachten Sie, dass ich nicht sage, dass wir versuchen sollten, Paketmanager wegzuabstrahieren, während wir weiterhin versuchen, alle ihre spezifischen Optionen und Befehle zu unterstützen, sondern nur eine einfache Möglichkeit zu haben, ein Paket zu installieren, das paketmanagerunabhängig ist. Ich sage auch nicht, dass wir alle auf den Zug aufspringen sollten.Intelligenter PaketmanagerZug aufspringen, aber eine Art Abstraktionsschicht für die Paketinstallation in Ihrem Konfigurationsmanagement-Tool ist sehr nützlich, um plattformübergreifende Playbooks/Cookbooks zu vereinfachen. Das Smart-Projekt sieht interessant aus, aber es ist ziemlich ehrgeizig, das Paketmanagement über Distributionen und Plattformen hinweg zu vereinheitlichen, ohne dass es bisher viel Akzeptanz gibt ... es wird interessant sein zu sehen, ob es erfolgreich ist. Das eigentliche Problem ist nur, dass Paketnamen manchmal zwischen den Distributionen unterschiedlich sind, sodass wir immer noch Case-Anweisungen oder when:
Anweisungen verwenden müssen, um die Unterschiede zu behandeln.
Ich gehe damit so um, dass ich tasks
in einem Playbook oder einer Rolle dieser Verzeichnisstruktur folge:
roles/foo
└── tasks
├── apt_package.yml
├── foo.yml
├── homebrew_package.yml
├── main.yml
└── yum_package.yml
Und dann habe ich dies in meinem main.yml
:
---
# foo: entry point for tasks
# Generally only include other file(s) and add tags here.
- include: foo.yml tags=foo
Dies in foo.yml
(für Paket „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'
Dann für die verschiedenen Paketmanager:
Geeignet:
---
# 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
Lecker:
---
# 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
Eigenbrauen:
---
- name: Tap homebrew foobar/foo
homebrew_tap: >
name=foobar/foo
state=present
- homebrew: >
name=foo
state=latest
Beachten Sie, dass dies furchtbar repetitiv ist und nichtTROCKENund obwohl einige Dingekönnteauf den verschiedenen Plattformen unterschiedlich sein und müssen behandelt werden. Generell halte ich dies im Vergleich zu dem von Chef für wortreich und unhandlich:
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
Und ja, es gibt das Argument, dassmanchePaketnamen sind in den verschiedenen Distributionen unterschiedlich. Und obwohl es derzeit eineMangel an leicht zugänglichen Daten, würde ich vermuten, dassam meistenBeliebte Paketnamen sind in allen Distributionen üblich und könnten über ein abstrahiertes Paketmanagermodul installiert werden. Sonderfälle müssten ohnehin behandelt werden und würden bereits zusätzliche Arbeit erfordern, was die Dinge weniger DRY macht. Wenn Sie Zweifel haben, überprüfen Siepkgs.org.
Antwort2
Sie können Paketmanager über Fakten abstrahieren
- name: Install packages
with_items: package_list
action: "{{ ansible_pkg_mgr }} state=installed name={{ item }}"
Alles was Sie brauchen, ist eine Logik, die ansible_pkg_mgr
auf apt
oder yum
usw. einstellt.
Ansiblearbeiten auch daran, das zu tun, was Sie in einem zukünftigen Modul wollen.
Antwort3
Ab Ansible 2.0 gibt es das neue Package
-Modul.
http://docs.ansible.com/ansible/package_module.html
Sie können es dann wie Ihren Vorschlag verwenden:
- name: install the latest version of Apache
package: name=httpd state=latest
Namensunterschiede müssen Sie dennoch berücksichtigen.
Antwort4
Das sollten Sie nicht tun, da sich bestimmte Paketnamen zwischen den Distributionen unterscheiden. Beispielsweise heißt das beliebte Webserverpaket bei RHEL-bezogenen Distributionen httpd
, während es bei Debian-bezogenen Distributionen heißt apache2
. Ähnlich verhält es sich mit einer riesigen Liste anderer System- und Unterstützungsbibliotheken.
Es gibt möglicherweise einen Satz gemeinsamer Basisparameter, aber auch eine Reihe erweiterter Parameter, die sich je nach Paketmanager unterscheiden. Und Sie möchten nicht in eine mehrdeutige Situation geraten, in der Sie für einige Befehle eine Syntax und für andere Befehle eine andere Syntax verwenden.