ansible에서 패키지 설치 작업을 통합하는 방법은 무엇입니까?


68

나는 asible로 시작하여 여러 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"

두 패키지 관리자가 다르지만 여전히 공통적 인 기본 사용법이 있습니다. 다른 오케 스트레이터 ( : salt )에는 단일 설치 명령이 있습니다.


세 가지 레시피를 가질 수 있습니다. 하나는 공통 목록을 반복하고 다른 하나는 OS 별 목록을 위해 반복합니다. 내가 지금 알아 내려고하는 것은 공통 구성 항목이 설정된 후 OS 특정 서비스 이름으로 처리기에 알리는 방법입니다. 행운을 빕니다!
dannyman

답변:


66

업데이트 : 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)을 사용하는 경우 불행히도 모든 플레이 북 및 역할에서이 작업을 처리해야합니다. IMHO는 이것으로 많은 불필요한 반복 작업을 플레이 북 및 역할 저자에게 밀어 붙이고 있습니다. 그러나 그것은 현재의 방식입니다. 특정 옵션과 명령을 모두 지원하면서 패키지 관리자를 추상화하려고 시도하지는 않지만 패키지 관리자와 무관 한 패키지를 쉽게 설치할 수 있습니다. 또한 우리는 모두 Smart Package Manager 에 뛰어 들어야한다고 말하지 않습니다.구성 관리 도구의 일종의 패키지 설치 추상화 계층은 플랫폼 간 플레이 북 / 요리 책을 단순화하는 데 매우 유용합니다. Smart 프로젝트는 흥미로워 보이지만 아직 많은 채택없이 배포판과 플랫폼에서 패키지 관리를 통합하는 것은 매우 야심적입니다 ... 성공 여부는 흥미로울 것입니다. 실제 문제는 패키지 이름이 때로는 배포판마다 다른 경향이 있기 때문에 차이점 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

m :

---
# 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 , 그리고 몇 가지가 있지만 수있는 다른 플랫폼에서 다를 수 및 처리되어야 할 것이다, 일반적으로 내가 요리사의 비교했을 때이 장황하고 다루기 생각 :

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

그렇습니다. 일부 패키지 이름은 배포판마다 다릅니다. 현재이 있지만 그리고 쉽게 액세스 할 수있는 데이터의 부족 , 나는 추측 벤처 것입니다 가장 인기있는 패키지 이름이 배포판에서 공통되고 추상화 된 패키지 관리자 모듈을 통해 설치 될 수 있습니다. 어쨌든 특수한 경우를 처리해야하며 추가 작업이 덜 필요할 것입니다 DRY 덜 의심 스러운 경우 pkgs.org를 확인 하십시오 .


Ansible 2에서는 패키지 모듈을 사용 하여이
Guido

@ GuidoGarcía : 아주 좋아요! Ansible 2.0이에 대한 메모를 추가
TrinitronX

쉼표로 구분 된 목록 또는 패키지 목록 만 지정할 수 있다고 언급 할 수도 있습니다.
웨스 터너

13

사실을 통해 패키지 관리자를 추출 할 수 있습니다

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

당신이 필요로하는 설정 일부 로직 ansible_pkg_mgrapt또는 yum

Ansible 은 또한 향후 모듈에서 원하는 작업을 수행하고 있습니다 .


1
Ansible은 ansible_pkg_mgr알고있는 모든 패키저에 대해 자체 설정 합니다. 당신은 아무것도 할 필요가 없습니다. 나는이 특정 구조를 모든 곳에서 사용합니다.
Michael Hampton

이 구문은 플레이 북 실행을 최적화하려는 사람들에게 여전히 유용합니다. 일반 패키지 모듈 은 with_items에 대한 최적화를 아직 제공하지 않으므로 여러 패키지를 한 번에 설치하는 데 사용하면 속도가 훨씬 느려집니다.
Danila Vershinin

@DanielV. github 문제는 이에 대한 해결 방법을 제공합니다.
Michael Hampton


3

조건부 가져 오기 에 대한 Ansible의 문서를 확인하십시오 .

서비스 이름이 OS마다 다르더라도 아파치가 실행되고 있는지 확인하는 한 가지 작업입니다.

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

배포판마다 특정 패키지 이름이 다르기 때문에 그렇게하고 싶지 않습니다. 예를 들어 RHEL 관련 배포판에서 널리 사용되는 웹 서버 패키지의 이름은이며 httpd, 데비안 관련 배포판에서는 이름이 apache2입니다. 다른 시스템 및 지원 라이브러리 목록도 비슷합니다.

공통 기본 매개 변수 세트가있을 수 있지만 패키지 관리자마다 다른 고급 매개 변수도 있습니다. 그리고 어떤 명령에는 하나의 구문을 사용하고 다른 명령에는 다른 구문을 사용하는 모호한 상황에 처하기를 원하지 않습니다.


이것은 내가 기대했던 것 (불행히도 :)입니다. 따라서 salt두 패키지 관리자를 통합 하는 방법이 궁금합니다 . 어쨌든 이중 구성에 의지합니다.
WoJ

또는 배포 동물원을 관리하지 마십시오. ;-) 단일 디스트로 인프라로 마이그레이션하고 더 행복한 삶을 살고 있습니다.
Mxx

동물원은 다행스럽게도 두 마리의 동물 만 있지만 이것은 내가 갈 수있는 가장 작은 숫자입니다.)
WoJ

1
@Mxx 시스템 관리자에게는 훌륭한 논리이지만 여러 플랫폼을 지원하는 소프트웨어 공급 업체 나 컨설턴트는 어떻습니까?
David H. Bennett

@David는 배포 업체와 통합하여 패키지 이름과 설치 도구를 통합해야합니다. Ansible이 모든 버전의 지원되는 모든 배포판에서 모든 패키지의 통합 매핑을 가질 수있는 방법은 현실적으로 없습니다.
Mxx
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.