
我從安西布爾並將使用它在多個 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"
我知道這兩個套件管理器是不同的,但它們仍然有一組共同的基本用法。其他編曲家(例如鹽)有一個安裝指令。
答案1
更新:從 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
編輯: 自 Michael DeHaan(Ansible 的創建者)以來選擇不抽像出套件管理器模組喜歡廚師做,
如果您仍在使用舊版的 Ansible(Ansible < 2.0),不幸的是你需要處理這樣做全部你的劇本和角色。 恕我直言這將大量不必要的重複工作推給了劇本和角色作者……但目前就是這樣。請注意,我並不是說我們應該嘗試將套件管理器抽象化出來,同時仍然嘗試支援它們的所有特定選項和命令,而只是有一種簡單的方法來安裝與套件管理器無關的套件。我也不是說我們都該跳上智慧包管理器流行,但組態管理工具中的某種套件安裝抽象層對於簡化跨平台劇本/說明書非常有用。 Smart 專案看起來很有趣,但它雄心勃勃地想要統一跨發行版和平台的套件管理,但尚未得到太多採用……看看它是否成功將會很有趣。真正的問題是,不同發行版的套件名稱有時會有所不同,因此我們仍然需要使用 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
請注意,這是非常重複的,而不是乾燥,雖然有些事情可能在不同的平台上會有所不同,必須進行處理,一般來說,我認為與 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
是的,有這樣的論點:一些不同發行版的套件名稱不同。而且雖然目前有一個缺乏易於取得的數據,我鬥膽猜測一下最多流行的軟體包名稱在發行版中很常見,可以透過抽象的軟體包管理器模組安裝。無論如何,特殊情況都需要處理,並且已經需要額外的工作來使事情變得不那麼乾燥。pkgs.org。
答案2
您可以透過事實抽像出套件管理器
- name: Install packages
with_items: package_list
action: "{{ ansible_pkg_mgr }} state=installed name={{ item }}"
ansible_pkg_mgr
您所需要的只是一些設定為apt
或yum
等的邏輯。
安西布爾也在努力在未來的模組中做你想做的事情。
答案3
從 Ansible 2.0 開始,出現了新的Package
-modul。
http://docs.ansible.com/ansible/package_module.html
然後您可以像您的提案一樣使用它:
- name: install the latest version of Apache
package: name=httpd state=latest
您仍然需要考慮名稱差異。
答案4
您不想這樣做,因為某些軟體包名稱在發行版之間有所不同。例如,在 RHEL 相關發行版上,流行的 Web 伺服器套件被命名為httpd
,而在 Debian 相關發行版上,它被命名為apache2
。同樣,還有大量其他系統和支援庫。
可能有一組常見的基本參數,但也有許多更高級的參數在套件管理器之間有所不同。並且您不希望處於一種不明確的情況,即對於某些命令您使用一種語法,而對於其他命令您使用另一種語法。