แทนที่โฮสต์ตัวแปรของ Ansible playbook จากบรรทัดคำสั่ง


110

นี่คือส่วนหนึ่งของ playbook ที่ฉันใช้ ( server.yml):

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

ไฟล์โฮสต์ของฉันมีกลุ่มเซิร์ฟเวอร์ที่แตกต่างกันเช่น

[web]
x.x.x.x

[droplets]
x.x.x.x

ตอนนี้ผมต้องการที่จะดำเนินการansible-playbook -i hosts/<env> server.ymlและแทนที่hosts: webจากserver.ymlการเรียกใช้ PlayBook [droplets]นี้

ฉันสามารถแทนที่เป็นการปิดครั้งเดียวโดยไม่แก้ไขserver.ymlโดยตรงได้หรือไม่

ขอบคุณ.

คำตอบ:


128

ฉันไม่คิดว่า Ansible จะให้คุณสมบัตินี้อย่างที่ควรจะเป็น นี่คือสิ่งที่คุณสามารถทำได้:

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

และคุณสามารถส่งผ่านvariable_hostจากบรรทัดคำสั่งหรือจากไฟล์ vars เช่น:

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

3
จำเป็นต้องมีการแก้ไขเล็กน้อย ควรจะเป็นhosts: "{{ variable_host | default('web')}}"
SPM

16
นี่คือบันทึกที่ฉันรู้สึกว่าจะตอบโจทย์สำหรับมือใหม่ที่กำลังค้นหาวิธีแก้ปัญหานี้: ตัวอย่าง:ansible-playbook server.yml --extra-vars "variable_host=newtarget(s)"
Frobbit

1
เมื่อ (เช่นในสิ่งที่สั่งซื้อ) ไม่เบิ้ลตัวแปรแยกตัวแปรในgroup_vars/allดูเหมือนจะแยกวิเคราะห์หลังจากhosts:สายของกลยุทธ์ที่นัก อย่างไรก็ตามตัวแปรในvars:และตัวแปรในvars_files:จะถูกแยกวิเคราะห์ก่อนhosts:บรรทัด? หมายเหตุฉันไม่ได้ถามเกี่ยวกับลำดับความสำคัญ
Felipe Alvarez

2
คุณสามารถใช้-eแทน--extra-varsไฟล์.
คำนาม

ดูคำตอบอื่น ๆ สำหรับรายละเอียดเพิ่มเติม
Anand Varkey Philips

63

สำหรับใครที่กำลังมองหาทางออก
เล่นหนังสือ

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

สินค้าคงคลัง

[web]
x.x.x.x

[droplets]
x.x.x.x

คำสั่ง: ansible-playbook deplyment.yml -i hosts --extra-vars "host=droplets" คุณสามารถระบุชื่อกลุ่มในตัวแปรพิเศษได้


2
หมายเหตุโปรดใช้ความระมัดระวังในการตั้งชื่อแบบต่างๆ ฉันกำลังทดสอบสิ่งนี้โดยใช้play_hostsและไม่ได้รับผลลัพธ์ที่คาดหวังเพราะฉันลืมไปว่านั่นplay_hostsคือ Ansible var ภายในสำหรับโฮสต์ทั้งหมดในการเล่นปัจจุบัน
Ryan Fisher

ฉันคิดว่าควรตั้งค่าเริ่มต้นตามคำตอบด้านบน
kakaz

19

มันช้าไปหน่อย แต่ฉันคิดว่าคุณสามารถใช้ไฟล์ --limit or -lคำสั่งเพื่อ จำกัด รูปแบบให้เฉพาะโฮสต์ได้มากขึ้น (รุ่น 2.3.2.0)

คุณสามารถมี - hosts: all (or group) tasks: - some_task

แล้ว ansible-playbook playbook.yml -l some_more_strict_host_or_pattern ใช้--list-hostsแฟล็กเพื่อดูว่าโฮสต์ใดที่จะใช้การกำหนดค่านี้


3
ฉันยังใหม่มากที่จะตอบได้ แต่ฉันคิดว่านี่เป็นวิธีแก้ปัญหาที่มีประสิทธิภาพมากกะทัดรัดกว่าวิธีอื่น ๆ เหตุใดจึงถูกลดคะแนน
Alessandro Dentella

16
สิ่งนี้อันตราย ในกรณีที่ใครลืมlimitรายชื่อโฮสต์ที่ส่งผลกระทบต่อเพลย์บุ๊กอาจทำให้เกิดความเสียหายได้มาก
Alexander Shcheblikin

3
ฉันพบว่าการใช้--extra-vars "variable_host=newtarget(s)"เช่นเดียวกับโซลูชันที่ยอมรับนั้นอันตรายและเป็นวิธีแก้ปัญหาที่ซับซ้อนกว่า ใช้โฮสต์เริ่มต้นwebซึ่งสามารถใช้ที่นี่ได้เช่นกันแทนที่จะallใช้ คุณสามารถใช้กลุ่มโฮสต์ที่เข้มงวดเป็นค่าเริ่มต้นเพื่อหลีกเลี่ยงการทำผิดพลาดและใช้--list-hostsแฟล็กเพื่อทำความเข้าใจอย่างชัดเจนว่าโฮสต์ใดที่คุณส่งผลกระทบ
Jonathan Hamel

3
โซลูชันที่มีตัวแปรพิเศษช่วยให้ระบุกลุ่มว่าง (หรือไม่มีอยู่) เป็นค่าเริ่มต้น ดังนั้นหากคุณลืมระบุตัวแปรผ่านทางบรรทัดคำสั่งจะไม่มีอะไรเกิดขึ้น วิธีแก้ไขด้วยตัวเลือก "--limit" อันตรายกว่าเนื่องจาก playbook ไม่สามารถใช้กลุ่มว่างเป็นค่าเริ่มต้นสำหรับโฮสต์ ตัวเลือก "--llmit" ถูกนำไปใช้กับค่าโฮสต์ดังนั้นจะใช้กับกลุ่มที่ว่างเปล่าและจะให้ผลลัพธ์ที่ว่างเปล่า ดังนั้นคุณต้องใช้ "ทั้งหมด" หรือโฮสต์อื่นที่ไม่ว่างเปล่าเป็นค่าเริ่มต้น และบางวันคุณจะลืมระบุอาร์กิวเมนต์ "--limit" และเพลย์บุ๊กจะใช้กับโฮสต์ทั้งหมด
Gregory Petukhov

4
สิ่งนี้ควรรวมกับคำตอบของ @ TmTron เพื่อจับกรณีที่ผู้โทรไม่สามารถจัดหาได้--limit(มิฉะนั้นจะส่งผลต่อโฮสต์ที่เป็นไปได้ทั้งหมดซึ่งอาจไม่ใช่พฤติกรรมที่คุณต้องการ)
ncoghlan

14

เราใช้งานที่ล้มเหลวง่ายๆเพื่อบังคับให้ผู้ใช้ระบุตัวเลือกขีด จำกัด Ansible เพื่อที่เราจะไม่ดำเนินการกับโฮสต์ทั้งหมดโดยค่าเริ่มต้น / อุบัติเหตุ

วิธีที่ง่ายที่สุดที่ฉันพบคือ:

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

ตอนนี้เราต้องใช้-l(= --limitตัวเลือก) เมื่อเราเรียกใช้ playbook เช่น

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

เอกสารตัวเลือก จำกัด :

จำกัด ไว้ที่โฮสต์อย่างน้อยหนึ่งโฮสต์สิ่งนี้จำเป็นเมื่อต้องการเรียกใช้ playbook กับกลุ่มโฮสต์ แต่เฉพาะกับสมาชิกหนึ่งคนหรือมากกว่าของกลุ่มนั้น

จำกัด ไว้ที่หนึ่งโฮสต์

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

จำกัด เฉพาะหลายโฮสต์

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

ขีด จำกัด เชิงลบ
หมายเหตุ: ต้องใช้เครื่องหมายคำพูดเดี่ยวเพื่อป้องกันการแก้ไข bash

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

จำกัด เฉพาะกลุ่มโฮสต์

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


7

ฉันใช้วิธีอื่นที่ไม่ต้องการสินค้าคงคลังใด ๆ และใช้งานได้กับคำสั่งง่ายๆนี้:

ansible-playbook site.yml -e working_host=myhost

ในการดำเนินการดังกล่าวคุณต้องมี playbook ที่มีสองบท:

  • การเล่นครั้งแรกทำงานบน localhost และเพิ่มโฮสต์ (จากตัวแปรที่กำหนด) ในกลุ่มที่รู้จักในสินค้าคงคลังในหน่วยความจำ
  • การเล่นครั้งที่สองดำเนินไปในกลุ่มที่รู้จักกันนี้

ตัวอย่างการทำงาน (คัดลอกและเรียกใช้ด้วยคำสั่งก่อนหน้า):

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

ฉันใช้ ansible 2.4.3 และ 2.3.3


7

ฉันเปลี่ยนของฉันเป็นค่าเริ่มต้นเป็นไม่มีโฮสต์และมีการตรวจสอบเพื่อจับมัน ด้วยวิธีนี้ผู้ใช้หรือ cron ถูกบังคับให้จัดหาโฮสต์เดียวหรือกลุ่มเป็นต้นฉันชอบตรรกะจากความคิดเห็นจาก @wallydrag empty_groupมีเจ้าภาพในสินค้าคงคลังไม่มี

- โฮสต์: "{{variable_host | default ('empty_group')}}"

จากนั้นเพิ่มงานเช็คอิน:

   งาน:
   - ชื่อ: สคริปต์ล้มเหลวหากไม่มีพารามิเตอร์ variable_host ที่ต้องการ
     ล้มเหลว:
       msg: "คุณต้องเพิ่ม --extra-vars = 'variable_host ='"
     เมื่อ: (ไม่ได้กำหนด variable_host) หรือ (variable_host == "")

5

เพิ่งเจอ googling นี้เพื่อหาวิธีแก้ปัญหา อันที่จริงมีหนึ่งใน Ansible 2.5 คุณสามารถระบุไฟล์สินค้าคงคลังของคุณได้--inventoryดังนี้:ansible --inventory configs/hosts --list-hosts all


ฉันเชื่อว่านี่เป็นคำตอบที่ถูกต้องที่สุดในปีแห่งพระเจ้าของเรา 2019 จาก Ansible 2.8.4's -h:-i INVENTORY, --inventory=INVENTORY, --inventory-file=INVENTORY specify inventory host path or comma separated host list. --inventory-file is deprecated
pyansharp

3

หากคุณต้องการรันงานที่เชื่อมโยงกับโฮสต์ แต่อยู่บนโฮสต์อื่นคุณควรลองใช้delegate_to delegate_to

ในกรณีของคุณคุณควรมอบหมายให้ localhost (ansible master) และเรียกansible-playbookคำสั่ง


2

ฉันใช้ ansible 2.5 (2.5.3 เป๊ะ) และดูเหมือนว่าไฟล์ varsจะถูกโหลดก่อนที่จะเรียกใช้พารามิเตอร์โฮสต์ ดังนั้นคุณสามารถตั้งค่าโฮสต์ในไฟล์vars.ymlและเขียนลงhosts: {{ host_var }}ใน playbook ของคุณ

ตัวอย่างเช่นใน playbook.yml ของฉัน:

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

และภายใน vars / project.yml:

---

# general
host_name: your-fancy-host-name

0

นี่เป็นทางออกที่ยอดเยี่ยมที่ฉันคิดขึ้นเพื่อระบุโฮสต์อย่างปลอดภัยผ่าน--limitตัวเลือก ในตัวอย่างนี้การเล่นจะสิ้นสุดลงหากมีการดำเนินการ playbook โดยไม่มีโฮสต์ใด ๆ ที่ระบุผ่าน--limitตัวเลือก

สิ่งนี้ได้รับการทดสอบบน Ansible เวอร์ชัน 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

วิธีแก้ปัญหาอื่นคือการใช้ตัวแปรพิเศษansible_limitซึ่งเป็นเนื้อหาของ--limitอ็อพชัน CLI สำหรับการดำเนินการปัจจุบันของ Ansible

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

หากไม่ใส่--limitตัวเลือกนี้ Ansible จะออกคำเตือน แต่จะไม่ดำเนินการใด ๆ เนื่องจากไม่มีโฮสต์ที่ตรงกัน

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

PLAY ****************************************************************
skipping: no hosts matched
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.