我从ansible开始,将使用它在其他Linux发行版中安装软件包。

我在文档中看到yumapt命令是分开的-这是最简单的方法统一它们并使用类似这样的东西:

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


我知道这两个软件包管理者是不同的,但是他们仍然有一组通用的基本用法。其他协调器(例如盐)只有一个安装命令。

评论

您可能有三种配方:一种遍历一个公用列表,另一种针对特定于操作系统的列表。我现在要弄清楚的是,在设置了公共配置项后,如何使用操作系统特定的服务名称通知处理程序。祝你好运!

基于事实的参数化ansible命令的可能重复项,该怎么办?

#1 楼

更新:从Ansible 2.0开始,现在有一个通用且抽象的package模块


用法示例:

现在,当软件包名称在不同的OS上相同时系列,它很简单:

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


当软件包名称在OS系列中不同时,您可以使用发行版或OS系列特定的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


然后,对于每个必须以不同方式处理的OS ...创建一个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的创建者)已选择不像Chef那样提取软件包管理器模块,因此

如果您仍在使用旧版本的Ansible(Ansible <2.0),那么不幸的是,需要在您所有的剧本和角色中都做到这一点。恕我直言,这将许多不必要的重复性工作推到了剧本和角色作者上……但这是目前的方式。请注意,我并不是说我们应该尝试抽象化软件包管理器,同时仍然尝试支持其所有特定的选项和命令,而只是提供了一种简单的方法来安装与软件包管理器无关的软件包。我并不是说我们都应该跳上Smart Package Manager的浪潮,但是您的配置管理工具中的某种软件包安装抽象层对于简化跨平台的剧本/烹饪书非常有用。 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


请注意,这是非常重复的,而不是DRY,尽管在不同的平台上某些内容可能有所不同并且必须进行处理,但与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。

评论


使用Ansible 2,您可以使用package模块来抽象所有docs.ansible.com/ansible/package_module.html

–圭多
15年12月29日19:00

@GuidoGarcía:非常好!为此添加注释Ansible 2.0

– TrinitronX
15年12月31日在19:56

也许还值得一提的是,您可以指定以逗号分隔的列表或仅列出软件包的列表。

–韦斯·特纳
18/12/12在3:54

#2 楼

您可以通过事实提取软件包管理器

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


您需要的是一些将ansible_pkg_mgr设置为aptyum等的逻辑。

还致力于在将来的模块中做您想做的事情。

评论


Ansible为其知道的任何打包程序自行设置ansible_pkg_mgr。您没有必要做任何事情。我到处都使用这种特殊的构造。

–迈克尔·汉普顿
2015年11月15日22:00



对于想要优化其剧本运行的人来说,语法仍然非常有用。通用软件包模块尚未提供with_items的优化功能,因此,当用于一次安装多个软件包时,它的速度要慢得多。

–达尼拉(Danila Vershinin)
17年5月13日在23:39

@DanielV。请注意,github问题确实提供了解决方法。

–迈克尔·汉普顿
17年12月14日在1:36

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

请查看有关条件导入的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


#5 楼

您不希望这样做,因为某些发行版之间的软件包名称不同。例如,在与RHEL相关的发行版中,流行的Web服务器软件包名为httpd,而在与Debian相关的发行版中,其名为apache2。类似地,还有大量其他系统和支持库。

可能有一组通用的基本参数,但是包管理器之间还有许多不同的高级参数。而且您也不想处于模棱两可的情况,对于某些命令,您使用一种语法,而对于其他命令,您使用另一种语法。

评论


这或多或少是我所期望的(不幸的是:)),所以我想知道salt是如何设法统一两个程序包管理器的。无论如何,我将采用双重配置。

– WoJ
2014年4月10日在12:17

或不管理发行动物园;-)迁移到单一发行的基础架构,过上更幸福的生活。

– Mxx
2014年4月10日在17:12

幸运的是,动物园只有两只动物,但这是我能去的最少的动物:)

– WoJ
2014年4月11日在7:23

@Mxx对系统管理员来说是很好的逻辑,但是支持多个平台的软件供应商或顾问又如何呢?

– David H. Bennett
2014年11月27日15:12



@David,然后这需要由发行版供应商来处理,以使它们具有统一的程序包名称和安装工具。实际上,Ansible不可能对所有版本的所有受支持发行版中的所有软件包进行统一映射。

– Mxx
2014年11月27日17:53

#6 楼

最重要的答案似乎是链接到破碎的页面。看起来像正确的URL:https://docs.ansible.com/ansible/latest/collections/ansible/builtin/package_module.html