Paket kurulum görevlerini birebir nasıl birleştirebilirim?


68

Ansible ile başlıyorum ve diğerlerinin yanı sıra birkaç Linux dağıtımında paket kurmak için kullanacağım.

Dokümanlarda yumve aptkomutların ayrıldığını görüyorum - bunları birleştirmenin ve bunun gibi bir şeyi kullanmanın en kolay yolu ne olurdu:

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

onun yerine

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

İki paket yöneticisinin farklı olduğunu anlıyorum, ancak yine de bir takım temel kullanım alanları var. Diğer düzenleyicilerin ( örneğin tuz ) tek bir kurulum komutu vardır.


Üç tarifiniz olabilir: biri ortak bir listeyi yineleyen, ardından her biri işletim sistemine özgü listeler için. Şu an anlamaya çalıştığım şey, ortak bir config öğesi ayarlandıktan sonra işletim sistemine özel bir servis adı olan bir işleyiciye nasıl bildirimde bulunulması gerektiğidir. iyi şanslar!
dannyman

Yanıtlar:


66

Güncelleme: Ansible 2.0'dan itibaren artık genel ve soyutlanmış bir packagemodül var.

Kullanım Örnekleri:

Şimdi, paket adı farklı işletim sistemi aileleri arasında aynı olduğunda, bu kadar basit:

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

Paket adı işletim sistemi aileleri arasında farklılık gösterdiğinde, dağıtım veya işletim sistemi ailesine özgü değişken dosyalarıyla kullanabilirsiniz:

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

Ardından, farklı işlem yapmanız gereken her işletim sistemi için bir vars dosyası oluşturun:

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



DÜZENLEME: Michael DeHaan (yanıtlayıcı 'yaratıcısı) yana paket yöneticisi modüllerinin dışarı değil soyut seçmiştir gibi şef yapar

Hala daha eski bir Ansible sürümü kullanıyorsanız (Ansible <2.0) , ne yazık ki bunu tüm oyun defterleriniz ve rollerinizlehalletmeniz gerekecek. IMHO bu, oyun kitabını ve rol yazarlarını çok fazla gereksiz tekrarlayan çalışmaya itiyor ... ama şu anda olduğu gibi. Tüm özel seçeneklerini ve komutlarını desteklemeye devam ederken paket yöneticilerini uzağa soyutlamaya çalışmamız gerektiğini söylemiyorum, ancak paket yöneticisine agnostik olan bir paketi kurmak için kolay bir yol var. Ayrıca Akıllı Paket Yöneticisine atlamamız gerektiğini söylemiyorum.Ancak bu seçenek, yapılandırma yönetim aracınızdaki bir çeşit paket yükleme soyutlama katmanının platformlar arası oyun kitaplarını / yemek kitaplarını basitleştirmek için çok yararlı olduğunu gösteriyor. Akıllı proje ilginç görünüyor, ancak paket yönetimini dağıtım ve platformlar arasında çok fazla kabul edilmeden birleştirmek oldukça iddialı. Başarılı olup olmadığını görmek ilginç olacak. Asıl mesele, sadece paket isimlerinin dağıtımlar arasında farklı olma eğiliminde olmasıdır, bu yüzden when:farklılıkları ele almak için yine de durum ifadeleri veya ifadeler yapmalıyız .

Bununla ilgilendiğim yöntem, bu tasksdizin yapısını bir oyun kitabında veya rolünde takip etmektir :

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

Ve sonra benim de bu var main.yml:

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

- include: foo.yml tags=foo

Bu içinde foo.yml('foo' paketi için):

---
# 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'

Ardından farklı paket yöneticileri için:

Uygun:

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

homebrew:

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

- homebrew: >
    name=foo
    state=latest

Bunun son derece tekrarlayıcı olduğunu ve DRY olmadığını ve farklı platformlarda bazı şeylerin farklı olabileceği ve ele alınması gerekebileceğini unutmayın, genel olarak bunun Chef'inkine kıyasla ayrıntılı ve hantal olduğunu düşünüyorum:

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

Ve evet, bazı paket adlarının dağıtımlar arasında farklı olduğu iddiası var . Şu anda kolay erişilebilir veri eksikliği olmasına rağmen , en popüler paket adlarının dağıtımlar arasında yaygın olduğunu ve soyut bir paket yöneticisi modülü aracılığıyla kurulabileceğini tahmin etmeye teşebbüs ediyorum . Özel davaların yine de ele alınması gerekecekti ve zaten işleri daha az yapmak için fazladan çalışmaya ihtiyaç duyuyordu .



@ GuidoGarcía: Çok hoş! Ansible 2.0 için bununla ilgili bir not ekleme
TrinitronX

Belki de virgülle ayrılmış bir liste veya sadece bir paket listesi belirtebileceğinizi belirtmekte fayda var.
Wes Turner

13

Paket yöneticilerini gerçekler aracılığıyla soyutlayabilirsiniz

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

Tek ihtiyacınız setleri bazı mantık ansible_pkg_mgriçin aptya yumvs.

Ansible ayrıca gelecekteki bir modülde ne istiyorsan onu yapmaya çalışıyor .


1
Ansible ansible_pkg_mgr, bildiği herhangi bir paketleyici için kendisini ayarlar . Hiçbir şey yapman gerekli değil. Bu belirli yapıyı her yerde kullanıyorum.
Michael Hampton

Sözdizimi, oyun kitaplarının çalışmasını optimize etmek isteyenler için hala oldukça faydalıdır. Genel paket modülü henüz with_items için optimizasyon sağlamıyor, bu yüzden bir kerede birden fazla paket yüklemek için kullanıldığında çok daha yavaş oluyor.
Danila Vershinin

@DanielV. Github sorununun bunun için bir geçici çözüm sağladığını unutmayın.
Michael Hampton


3

Ansible'ın Koşullu İthalatlar hakkındaki belgelerine bakın .

Hizmet adları her işletim sistemi arasında farklı olsa bile, apache'nin çalışmasını sağlayan görevlerden biri.

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

Bunu yapmak istemezsiniz çünkü belirli paket isimleri dağıtımlar arasında farklılık gösterir. Örneğin, RHEL ile ilgili dağıtımlarda, popüler web sunucusu paketinin adı httpd, Debian ile ilgili dağıtımlarda olduğu gibi apache2. Benzer şekilde, başka bir sistemin ve destekleyici kütüphanelerin büyük bir listesi.

Bir dizi ortak temel parametre olabilir, ancak daha sonra paket yöneticileri arasında farklı olan daha gelişmiş parametreler de vardır. Ve bazı komutlar için bir sözdizimi ve diğer komutlar için başka bir sözdizimi kullandığınız belirsiz bir durumda olmak istemezsiniz.


Bu ne beklediğimden daha az ya da çok (ne yazık ki :)) bu yüzden salther iki paket yöneticisini nasıl birleştirmeyi başardığını merak ediyorum . Her neyse, o zaman çifte konfigürasyona başvuracağım.
WoJ

Veya bir dağınık hayvanat bahçesini yönetmeyin ;-) tek bir dağınık altyapıya taşınır ve daha mutlu bir yaşam sürdürür.
Mxx

Hayvanat Bahçesi neyse ki sadece iki hayvan büyük ama bu gidebileceğim en düşük sayı :)
WoJ

1
Bir sysadmin için iyi mantık @Mxx ama peki ya çoklu platformları destekleyen bir yazılım satıcısı ya da danışmanı?
David H. Bennett

@David, bu durumda birleşik paket adlarına sahip olmaları ve araçlarını takmaları için dağıtımcı satıcılarla alınması gerekiyor. Gerçekçi olarak, Ansible'ın tüm sürümlerin desteklenen tüm dağıtımlarından TÜM paketlerin birleşik bir eşlemesine sahip olması mümkün değildir.
Mxx
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.