Ghi đè biến máy chủ của Ansible playbook từ dòng lệnh


110

Đây là một đoạn của sách vở mà tôi đang sử dụng ( server.yml):

- name: Determine Remote User
  hosts: web
  gather_facts: false
  roles:
    - { role: remote-user, tags: [remote-user, always] }

Tệp máy chủ của tôi có các nhóm máy chủ khác nhau, ví dụ:

[web]
x.x.x.x

[droplets]
x.x.x.x

Bây giờ tôi muốn thực thi ansible-playbook -i hosts/<env> server.ymlvà ghi đè hosts: webtừ server.ymlđể chạy playbook này [droplets].

Tôi có thể chỉ ghi đè một lần duy nhất mà không cần chỉnh sửa server.ymltrực tiếp không?

Cảm ơn.

Câu trả lời:


128

Tôi không nghĩ Ansible cung cấp tính năng này. Đây là điều bạn có thể làm:

hosts: "{{ variable_host | default('web') }}"

và bạn có thể chuyển variable_hosttừ dòng lệnh hoặc từ tệp vars, ví dụ:

ansible-playbook server.yml --extra-vars "variable_host=newtarget(s)"

3
Cần một chỉnh sửa nhỏ. Nó phải làhosts: "{{ variable_host | default('web')}}"
SPM

16
Dưới đây là một lưu ý mà tôi cảm thấy sẽ hoàn thành câu trả lời cho người mới ansible tìm kiếm giải pháp này: Ví dụ:ansible-playbook server.yml --extra-vars "variable_host=newtarget(s)"
Frobbit

1
KHI (tức là theo thứ tự gì) làm ansible biến phân tích biến trong group_vars/allxuất hiện để được phân tích sau khi các hosts:dòng của playbook. Tuy nhiên, biến trong vars:và biến trong vars_files:được phân tích cú pháp trước hosts:dòng? LƯU Ý Tôi không hỏi về mức độ ưu tiên.
Felipe Alvarez,

2
Bạn cũng có thể sử dụng -ethay vì --extra-vars.
noun

Nhìn vào câu trả lời khác để biết thêm chi tiết
Anand Varkey Philips

63

Đối với bất kỳ ai có thể tìm kiếm giải pháp.
Sách chơi

- hosts: '{{ host }}'
  tasks:
  - debug: msg="Host is {{ ansible_fqdn }}"

Hàng tồn kho

[web]
x.x.x.x

[droplets]
x.x.x.x

Lệnh: ansible-playbook deplyment.yml -i hosts --extra-vars "host=droplets" Vì vậy, bạn có thể chỉ định tên nhóm trong các cánh bổ sung


2
Lưu ý, hãy cẩn thận với cách đặt tên var. Tôi đã thử nghiệm điều này bằng cách sử dụng play_hostsvà không nhận được kết quả như mong đợi vì tôi quên rằng đó play_hostslà var Ansible nội bộ cho tất cả các máy chủ trong trò chơi hiện tại.
Ryan Fisher

Tôi cho rằng mặc định nên được đặt như trong câu trả lời ở trên.
kakaz

19

Điều này hơi muộn, nhưng tôi nghĩ bạn có thể sử dụng --limit or -llệnh để giới hạn mẫu cho các máy chủ cụ thể hơn. (phiên bản 2.3.2.0)

Bạn có thể có - hosts: all (or group) tasks: - some_task

rồi ansible-playbook playbook.yml -l some_more_strict_host_or_pattern sử dụng --list-hostscờ để xem cấu hình này sẽ được áp dụng trên máy chủ nào.


3
Tôi rất mới với ansible nhưng tôi coi đây là một giải pháp rất hiệu quả, nhỏ gọn hơn nhiều so với những giải pháp khác. Tại sao nó bị từ chối?
Alessandro Dentella

16
Điều này nguy hiểm. Trong trường hợp quên limitdanh sách các máy chủ bị ảnh hưởng, playbook có thể gây ra nhiều thiệt hại.
Alexander Shcheblikin

3
Tôi thấy rằng việc sử dụng --extra-vars "variable_host=newtarget(s)"giống như giải pháp được chấp nhận cũng nguy hiểm và là một giải pháp phức tạp hơn. Nó sử dụng một máy chủ mặc định webcó thể được áp dụng ở đây thay vì all. Bạn có thể sử dụng nhóm máy chủ nghiêm ngặt làm mặc định để tránh mắc lỗi và sử dụng --list-hostscờ để hiểu rõ ràng về máy chủ nào bạn đang ảnh hưởng.
Jonathan Hamel

3
Giải pháp với extra-vars cho phép chỉ định nhóm trống (hoặc không tồn tại) làm giá trị mặc định. Vì vậy, nếu bạn quên cung cấp biến thông qua dòng lệnh, không có gì xấu xảy ra. Giải pháp với tùy chọn "--limit" nguy hiểm hơn vì playbook không thể sử dụng nhóm trống làm giá trị mặc định cho máy chủ. Tùy chọn "--llmit" được áp dụng cho giá trị máy chủ do đó nó sẽ được áp dụng cho các nhóm trống và sẽ cung cấp kết quả trống. Vì vậy, bạn PHẢI sử dụng "tất cả" hoặc một số máy chủ lưu trữ không trống khác làm giá trị mặc định. Và một ngày nào đó bạn sẽ quên cung cấp đối số "--limit" và playbook sẽ được áp dụng cho tất cả các máy chủ.
Gregory Petukhov

4
Điều này nên được kết hợp với @ câu trả lời TmTron để nắm bắt những trường hợp người gọi thất bại trong việc cung cấp --limit(nếu không nó sẽ ảnh hưởng đến tất cả các host có thể, trong đó có thể không phải là hành vi mà bạn muốn)
ncoghlan

14

Chúng tôi sử dụng một nhiệm vụ thất bại đơn giản để buộc người dùng chỉ định tùy chọn giới hạn Ansible , để chúng tôi không thực thi trên tất cả các máy chủ theo mặc định / tai nạn.

Cách dễ nhất mà tôi tìm thấy là:

---
- name: Force limit
  # 'all' is okay here, because the fail task will force the user to specify a limit on the command line, using -l or --limit
  hosts: 'all'

  tasks:
  - name: checking limit arg
    fail:
      msg: "you must use -l or --limit - when you really want to use all hosts, use -l 'all'"
    when: ansible_limit is not defined
    run_once: true

Bây giờ chúng ta phải sử dụng -l(= --limitoption) khi chạy playbook, ví dụ:

ansible-playbook playbook.yml -l www.example.com

Giới hạn tài liệu tùy chọn :

Giới hạn đối với một hoặc nhiều máy chủ Điều này là bắt buộc khi một người muốn chạy playbook với một nhóm máy chủ, nhưng chỉ với một hoặc nhiều thành viên của nhóm đó.

Giới hạn cho một máy chủ

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit "host1"

Giới hạn cho nhiều máy chủ

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit "host1,host2"

Mức giới hạn.
LƯU Ý: PHẢI sử dụng các dấu nháy đơn để ngăn nội suy bash.

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit 'all:!host1'

Giới hạn cho nhóm máy chủ

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit 'group1'


7

Tôi đang sử dụng một cách tiếp cận khác không cần bất kỳ khoảng không quảng cáo nào và hoạt động với lệnh đơn giản này:

ansible-playbook site.yml -e working_host=myhost

Để thực hiện điều đó, bạn cần một cuốn sách có hai vở:

  • lần chơi đầu tiên chạy trên localhost và thêm máy chủ (từ biến đã cho) trong một nhóm đã biết trong kho lưu trữ inmemory
  • lượt chơi thứ hai chạy trên nhóm đã biết này

Một ví dụ làm việc (sao chép nó và chạy nó bằng lệnh trước đó):

- hosts: localhost
  connection: local
  tasks:
  - add_host:
      name: "{{ working_host }}"
      groups: working_group
    changed_when: false

- hosts: working_group
  gather_facts: false
  tasks:
  - debug:
      msg: "I'm on {{ ansible_host }}"

Tôi đang sử dụng ansible 2.4.3 và 2.3.3


7

Tôi đã thay đổi của tôi thành mặc định thành không có máy chủ lưu trữ và có một kiểm tra để bắt nó. Bằng cách đó, người dùng hoặc cron buộc phải cung cấp một máy chủ hoặc nhóm duy nhất, v.v. Tôi thích logic từ nhận xét từ @wallydrag. Không empty_groupchứa máy chủ nào trong khoảng không quảng cáo.

- máy chủ: "{{variable_host | default ('rỗng_group')}}"

Sau đó thêm các tác vụ đăng ký:

   nhiệm vụ:
   - name: Tập lệnh không thành công nếu thiếu tham số variable_host bắt buộc
     Thất bại:
       msgstr: "Bạn phải thêm --extra-vars = 'variable_host ='"
     khi: (variable_host không được xác định) hoặc (variable_host == "")

5

Chỉ cần xem qua googling này để tìm giải pháp. Trên thực tế, có một trong Ansible 2.5. Bạn có thể chỉ định tệp khoảng không quảng cáo của mình với --inventory, như sau:ansible --inventory configs/hosts --list-hosts all


Tôi tin rằng đây là câu trả lời đúng nhất trong năm của Chúa chúng ta năm 2019. Từ Ansible 2.8.4 của -h:-i INVENTORY, --inventory=INVENTORY, --inventory-file=INVENTORY specify inventory host path or comma separated host list. --inventory-file is deprecated
pyansharp

3

Nếu bạn muốn chạy một tác vụ được liên kết với máy chủ, nhưng trên máy chủ khác, bạn nên thử ủy quyền_to .

Trong trường hợp của bạn, bạn nên ủy quyền cho localhost của mình (ansible master) và ansible-playbooklệnh gọi


2

Tôi đang sử dụng ansible 2.5 (chính xác là 2.5.3) và có vẻ như tệp vars được tải trước khi param máy chủ được thực thi. Vì vậy, bạn có thể đặt máy chủ lưu trữ trong tệp vars.yml và chỉ cần ghi hosts: {{ host_var }}vào sổ chơi của bạn

Ví dụ: trong playbook.yml của tôi:

---
- hosts: "{{ host_name }}"
  become: yes
  vars_files:
    - vars/project.yml
  tasks:
    ... 

Và bên trong vars / project.yml:

---

# general
host_name: your-fancy-host-name

0

Đây là một giải pháp thú vị mà tôi đã đưa ra để chỉ định máy chủ một cách an toàn thông qua --limittùy chọn. Trong ví dụ này, vở kịch sẽ kết thúc nếu vở kịch được thực thi mà không có bất kỳ máy chủ nào được chỉ định thông qua --limittùy chọn.

Điều này đã được thử nghiệm trên Ansible phiên bản 2.7.10

---
- name: Playbook will fail if hosts not specified via --limit option.
  # Hosts must be set via limit. 
  hosts: "{{ play_hosts }}"
  connection: local
  gather_facts: false
  tasks:
  - set_fact:
      inventory_hosts: []
  - set_fact:
      inventory_hosts: "{{inventory_hosts + [item]}}"
    with_items: "{{hostvars.keys()|list}}"

  - meta: end_play
    when: "(play_hosts|length) == (inventory_hosts|length)"

  - debug:
      msg: "About to execute tasks/roles for {{inventory_hostname}}"

0

Một giải pháp khác là sử dụng biến đặc biệt ansible_limitlà nội dung của --limittùy chọn CLI để thực thi Ansible hiện tại.

- hosts: "{{ ansible_limit | default(omit) }}"

Nếu --limittùy chọn bị bỏ qua, thì Ansible đưa ra cảnh báo, nhưng không có tác dụng gì vì không có máy chủ nào phù hợp.

[WARNING]: Could not match supplied host pattern, ignoring: None

PLAY ****************************************************************
skipping: no hosts matched
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.