Wie vereinheitlichen Sie Paketinstallationsaufgaben in Ansible?

Wie vereinheitlichen Sie Paketinstallationsaufgaben in Ansible?

Ich beginne mitansibleund werde es unter anderem verwenden, um Pakete auf verschiedenen Linux-Distributionen zu installieren.

Ich sehe in den Dokumenten, dass die Befehle yumund aptgetrennt 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 abstrahiertepackageModul

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 tasksin 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_mgrauf aptoder yumusw. 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.

verwandte Informationen