सुरक्षित रूप से एक मशीन के लिए Ansible playbooks सीमित?


227

मैं कंप्यूटर के एक छोटे समूह के साथ कुछ सरल उपयोगकर्ता प्रबंधन कार्यों के लिए Ansible का उपयोग कर रहा हूं। वर्तमान में, मेरे पास मेरी playbooks सेट करने के लिए है hosts: allऔर मेरी होस्ट फ़ाइल सभी सूचीबद्ध मशीनों के साथ एक एकल समूह है:

# file: hosts
[office]
imac-1.local
imac-2.local
imac-3.local

मैंने खुद को एक मशीन को लक्षित करने के लिए अक्सर पाया है। ansible-playbookआदेश कर सकते हैं सीमा इस तरह खेलता है:

ansible-playbook --limit imac-2.local user.yml

लेकिन ऐसा नाजुक लगता है, खासकर एक संभावित विनाशकारी प्लेबुक के लिए। limitझंडे को छोड़ने का मतलब है कि प्लेबुक को हर जगह चलाया जाएगा। चूंकि ये उपकरण केवल कभी-कभी उपयोग किए जाते हैं, इसलिए यह मूर्खतापूर्ण प्लेबैक के लिए कदम उठाने के लायक लगता है इसलिए हम गलती से अब से कुछ महीने पहले नहीं करते हैं।

क्या प्लेबुक को एक मशीन तक चलाने के लिए सबसे अच्छा अभ्यास है? यदि कुछ महत्वपूर्ण विवरण को छोड़ दिया जाए तो आदर्श रूप से प्लेबुक हानिरहित होनी चाहिए।

जवाबों:


209

यह पता चलता है कि एक होस्ट नाम सीधे प्लेबुक में दर्ज करना संभव है, इसलिए प्लेबुक को चलाना hosts: imac-2.localठीक रहेगा। लेकिन यह क्लूनी की तरह है।

एक बेहतर समाधान हो सकता है कि प्लेबुक के मेजबान को एक चर का उपयोग करके परिभाषित किया जाए, फिर एक विशिष्ट मेजबान पते में से गुजर रहा है --extra-vars:

# file: user.yml  (playbook)
---
- hosts: '{{ target }}'
  user: ...

प्लेबुक चलाना:

ansible-playbook user.yml --extra-vars "target=imac-2.local"

अगर {{ target }} परिभाषित नहीं किया गया है, तो playbook कुछ नहीं करता है। यदि आवश्यक हो, तो होस्ट्स फ़ाइल से एक समूह भी पारित किया जा सकता है। कुल मिलाकर, यह एक संभावित विनाशकारी प्लेबुक के निर्माण के लिए बहुत सुरक्षित तरीके की तरह लगता है।

एकल होस्ट को लक्ष्यित करने वाली प्लेबुक:

$ ansible-playbook user.yml --extra-vars "target=imac-2.local" --list-hosts

playbook: user.yml

  play #1 (imac-2.local): host count=1
    imac-2.local

मेजबान के एक समूह के साथ प्लेबुक:

$ ansible-playbook user.yml --extra-vars "target=office" --list-hosts

playbook: user.yml

  play #1 (office): host count=3
    imac-1.local
    imac-2.local
    imac-3.local

मेजबानों को परिभाषित करना सुरक्षित है!

$ ansible-playbook user.yml --list-hosts

playbook: user.yml

  play #1 ({{target}}): host count=0

52
इस के साथ 1.5.3 में व्याख्या करने योग्य है--limit office[0]
एनजी।

4
चर को उद्धृत करने की आवश्यकता है - अर्थात: '{{ target }}'- docs.ansible.com/… के
लिम्बो पेंग

9
यह "विफल सुरक्षित" उत्तर है, कुछ अन्य लोगों के विपरीत - यदि आप कुछ बाहर छोड़ते हैं, तो यह कुछ भी नहीं करेगा। Ansible 1.7 का उपयोग कर 'केवल' एक मेजबान पर चलना run_onceअभी भी विनाशकारी हो सकता है इसलिए यह इतना अच्छा विचार नहीं है।
रिचवेल 16

4
यदि आप एक छोटी कमांड चाहते हैं, -eतो --extra-vars
विलियम टरेल

1
यदि आपके सुगम विन्यास की आवश्यकता होती है कि मेजबानों को खाली या अपरिभाषित नहीं किया जा सकता है, तो एक जिन्न फिल्टर काम के साथ संयुक्त चर का उपयोग करना, जैसे:hosts: "{{ target | default('no_hosts')}}"
Zach Weg

178

एक प्यारा सा ट्रिक भी है जो आपको कमांड लाइन (या कई मेजबानों, मुझे लगता है) पर एक एकल होस्ट निर्दिष्ट करता है, बिना किसी मध्यस्थ सूची के:

ansible-playbook -i "imac1-local," user.yml

अंत में अल्पविराम ( , ) नोट करें ; यह संकेत देता है कि यह एक सूची है, एक फाइल नहीं है।

अब, यह आपकी सुरक्षा नहीं करेगा यदि आप गलती से एक वास्तविक इन्वेंट्री फ़ाइल पास करते हैं, तो यह इस विशिष्ट समस्या का एक अच्छा समाधान नहीं हो सकता है। लेकिन यह जानने के लिए एक आसान चाल है!


2
वह आश्चर्यजनक है। मैं नियमित रूप से -l ध्वज का उपयोग करता हूं, जो आदि / ansible / होस्ट्स (जो EC2 डिस्कवरी API का उपयोग करके पॉपुलेटेड है) के साथ काम करता है, लेकिन कभी-कभी मुझे वास्तव में सिर्फ एक मशीन की आवश्यकता होती है। धन्यवाद!
विक

3
क्या इस ट्रिक से मेजबानों की फाइल का उपयोग किया जाना चाहिए? मैं मेजबानों को हमारी AWS EC2 प्रणाली के लिए एक गतिशील सूची के रूप में उपयोग कर रहा हूं और यह वापस आ गया है skipping: no hosts matched:। शायद यह ट्रिक अब काम नहीं --limitकरती है?
हैमक्स

1
यह चाल मेरे लिए काम नहीं की। लेकिन यह काम किया $ ansible-playbook -kK --limit=myhost1 myplaybook.yml:। देखें मारवान का जवाब
डॉन ली

2
यह उल्लेख किया जाना चाहिए कि इस काम के लिए, मेजबान को allनाटक में सेट किया जाना चाहिए - मुझे यह पता लगाने में
थोड़ा

83

यदि एक से अधिक होस्ट play_hosts चर की जाँच करके प्रदान किया गया है, तो यह दृष्टिकोण से बाहर निकल जाएगा । असफल मॉड्यूल अगर एक मेजबान शर्त पूरी नहीं कर रहा है बाहर निकलने के लिए प्रयोग किया जाता है। नीचे दिए गए उदाहरण दो होस्ट एलिस और बॉब के साथ एक होस्ट फ़ाइल का उपयोग करते हैं।

user.yml (प्लेबुक)

---
- hosts: all
  tasks:
    - name: Check for single host
      fail: msg="Single host check failed."
      when: "{{ play_hosts|length }} != 1"
    - debug: msg='I got executed!'

बिना किसी होस्ट फ़िल्टर के प्लेबुक चलाएं

$ ansible-playbook user.yml
PLAY [all] ****************************************************************
TASK: [Check for single host] *********************************************
failed: [alice] => {"failed": true}
msg: Single host check failed.
failed: [bob] => {"failed": true}
msg: Single host check failed.
FATAL: all hosts have already failed -- aborting

सिंगल होस्ट पर प्लेबुक चलाएं

$ ansible-playbook user.yml --limit=alice

PLAY [all] ****************************************************************

TASK: [Check for single host] *********************************************
skipping: [alice]

TASK: [debug msg='I got executed!'] ***************************************
ok: [alice] => {
    "msg": "I got executed!"
}

1
निश्चित रूप से सबसे अच्छा एक, --limitजाने का रास्ता है
Berto

7
play_hostsअंसिबल 2.2 में पदावनत किया गया है और इसके साथ प्रतिस्थापित किया गया है ansible_play_hosts। आवश्यकता के बिना एक होस्ट पर चलने के लिए --limit, आप उपयोग कर सकते हैं when: inventory_hostname == ansible_play_hosts[0]
ट्रेवर रॉबिन्सन

[WARNING]: conditional statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: {{ play_hosts|length }} == ''२.ible.४ पर।
थॉमस

32

IMHO एक अधिक सुविधाजनक तरीका है। आप वास्तव में मशीन के लिए उपयोगकर्ता को इंटरएक्टिवली प्रॉम्प्ट कर सकते हैं वह धन्यवाद के लिए प्लेबुक को लागू करना चाहता है vars_prompt:

---

- hosts: "{{ setupHosts }}"
  vars_prompt:
    - name: "setupHosts"
      prompt: "Which hosts would you like to setup?"
      private: no
  tasks:
    […]

2
बहुत ही शांत। इसका यह भी लाभ है कि प्लेबुक इन्वेंट्री फ़ाइल के लिए विशिष्ट नहीं है।
इरफान

2
संपादित करें के लिए thx! मैं वास्तव में सोच रहा था कि इनपुट डिफ़ॉल्ट रूप से "पासवर्ड शैली" क्यों था। मुझे याद था कि डॉक्स में :)
बुज़ुत

क्या इस प्लेबुक के साथ प्रॉम्प्ट को खत्म करने के लिए कमांड लाइन से मेजबानों के संस्करण को सेट किया जा सकता है?
andig

1
@andig के साथ --extra-varsऔर आपकी प्लेबुक में एक सामान्य
संस्करण

वास्तव में, मुझे यह काम करने के लिए नहीं मिला - ऐसा लगता {{ hosts }}है कि मूल्य में प्रवेश करने से पहले मूल्यांकन किया जाता है - या कोई विशेष चाल है?
रेमीगियस स्टेलर

18

जोइमैलर के उत्तर पर विस्तार करने के लिए, यदि आप दूरस्थ मशीनों के किसी भी सबसेट (जैसा कि ansibleकमांड करते हैं) से मिलान करने के लिए पैटर्न-मिलान करने की क्षमता चाहते हैं, लेकिन फिर भी सभी मशीनों पर गलती से प्लेबुक चलाना बहुत मुश्किल हो जाता है, यह मैं क्या लेकर आया हूँ:

अन्य उत्तर के रूप में समान प्लेबुक:

# file: user.yml  (playbook)
---
- hosts: '{{ target }}'
  user: ...

निम्नलिखित मेजबान हैं:

imac-10.local
imac-11.local
imac-22.local

अब, सभी उपकरणों पर कमांड चलाने के लिए, आपको "सभी" के लिए लक्ष्य चर सेट करना होगा

ansible-playbook user.yml --extra-vars "target=all"

और इसे एक विशिष्ट पैटर्न तक सीमित करने के लिए, आप सेट कर सकते हैं target=pattern_here

या, वैकल्पिक रूप से, आप तर्क छोड़ सकते हैं target=allऔर --limitतर्क दे सकते हैं, जैसे:

--limit imac-1*

अर्थात। ansible-playbook user.yml --extra-vars "target=all" --limit imac-1* --list-hosts

जिसके परिणामस्वरूप:

playbook: user.yml

  play #1 (office): host count=2
    imac-10.local
    imac-11.local

यह वह परिपाटी है जिसका मैंने अनुगामी- django-postgres-nginx
Ajoy

13

मैं वास्तव में यह नहीं समझता कि सभी उत्तर इतने जटिल कैसे होते हैं, इसे करने का तरीका सरल है:

ansible-playbook user.yml -i hosts/hosts --limit imac-2.local --check

checkमोड किसी भी परिवर्तन करने के बिना, आप सूखी रन मोड में चलाने के लिए अनुमति देता है।


7
संभवतया क्योंकि उत्तरों के बारे में सोचते हुए, आप उस प्रश्न को याद करते हैं, जिसमें गलती से मापदंडों को छोड़ने पर चलने से रोकने का तरीका पूछा गया था। आपने अधिक पैरामीटर जोड़ने का सुझाव दिया है जो आवश्यकता के विरुद्ध जाता है।
टेच्राफ

2
आह, यकीन है, लेकिन अगर लोग मुझे उकसाते हैं, तो ऐसा इसलिए हो सकता है क्योंकि वे Ansible newbies हैं (जैसे कि जब मैंने अपना जवाब लिखा था) जो कि ध्वज के बारे में भी नहीं जानते हैं --check, तो मुझे लगता है कि यह अभी भी उपयोगी दस्तावेज-वार है, जैसा कि यह सवाल बहुत गूंजा
knocte

6

EC2 एक्सटर्नल इन्वेंटरी स्क्रिप्ट का उपयोग करने वाले AWS यूज़र्स केवल आई डी आईडी द्वारा फ़िल्टर कर सकते हैं:

ansible-playbook sample-playbook.yml --limit i-c98d5a71 --list-hosts

यह काम करता है क्योंकि इन्वेंट्री स्क्रिप्ट डिफ़ॉल्ट समूह बनाती है


4
विकल्प - प्रवेश EC2 तक सीमित नहीं है और इसका उपयोग आपकी सूची के नामों / समूहों को होस्ट करने के लिए किया जा सकता है। धन्यवाद।
martinezdelariva 10

5

हमारे पास कुछ सामान्य प्लेबुक हैं जो बड़ी संख्या में टीमों द्वारा उपयोग करने योग्य हैं। हमारे पास पर्यावरण विशिष्ट इन्वेंट्री फाइलें भी हैं, जिसमें कई समूह घोषणाएं हैं।

समूह के विरुद्ध चलने के लिए किसी समूह को निर्दिष्ट करने के लिए किसी प्लेबुक को कॉल करने के लिए मजबूर करने के लिए, हम प्लेबुक के शीर्ष पर एक डमी प्रविष्टि देते हैं:

[ansible-dummy-group]
dummy-server

फिर हम निम्नलिखित चेक को साझा प्लेबुक में पहले चरण के रूप में शामिल करते हैं:

- hosts: all
  gather_facts: False
  run_once: true
  tasks:
  - fail:
      msg: "Please specify a group to run this playbook against"
    when: '"dummy-server" in ansible_play_batch'

यदि डमी-सर्वर मेजबानों की सूची में दिखाई देता है तो यह प्लेबुक (ansible_play_batch) के विरुद्ध चलने वाला है, तो कॉल करने वाले ने एक समूह निर्दिष्ट नहीं किया और प्लेबुक का निष्पादन विफल हो जाएगा।


ansible_play_batchकेवल वर्तमान बैच को सूचीबद्ध करता है, इसलिए बैचिंग का उपयोग करते समय यह अभी भी असुरक्षित है। इसके ansible_play_hostsबजाय उपयोग करना बेहतर है ।
थॉमस

इसके अलावा, यह चाल सबसे सरल और सबसे निकटतम लगती है जो पूछा गया था; मैं इसे अपना रहा हूँ!
थॉमस


4

इससे पता चलता है कि टारगेट सर्वर पर ही प्लेबुक कैसे चलाएं।

यदि आप स्थानीय कनेक्शन का उपयोग करना चाहते हैं तो यह थोड़ा मुश्किल है। लेकिन यह ठीक होना चाहिए यदि आप मेजबान सेटिंग के लिए एक चर का उपयोग करते हैं और होस्ट्स फ़ाइल में स्थानीयहोस्ट के लिए एक विशेष प्रविष्टि बनाते हैं।

में (सभी) प्लेबुक में मेजबान हैं: लाइन सेट टू:

- hosts: "{{ target | default('no_hosts')}}"

इन्वेंट्री होस्ट्स फ़ाइल में स्थानीयहोस्ट के लिए एक प्रविष्टि जोड़ें जो स्थानीय होने के लिए कनेक्शन सेट करता है:

[localhost]
127.0.0.1  ansible_connection=local

फिर कमांड लाइन रन कमांड स्पष्ट रूप से लक्ष्य निर्धारित करने के लिए - उदाहरण के लिए:

$ ansible-playbook --extra-vars "target=localhost" test.yml

यह तब भी काम करेगा जब ansible-pull का उपयोग करें:

$ ansible-pull -U <git-repo-here> -d ~/ansible --extra-vars "target=localhost" test.yml

यदि आप कमांड लाइन पर वेरिएबल सेट करना भूल जाते हैं, तो कमांड सुरक्षित रूप से एरर करेगा (जब तक कि आपने 'no_hosts' नामक एक होस्ट ग्रुप नहीं बनाया है!) की चेतावनी के साथ:

skipping: no hosts matched

और जैसा कि ऊपर उल्लेख किया गया है, आप किसी एकल मशीन को लक्षित कर सकते हैं (जब तक यह आपके होस्ट फ़ाइल में है):

$ ansible-playbook --extra-vars "target=server.domain" test.yml

या कुछ के साथ एक समूह:

$ ansible-playbook --extra-vars "target=web-servers" test.yml

0

मेरे पास एक रैपर स्क्रिप्ट है, जिसे प्रावधान के लिए कहा गया है ताकि आप लक्ष्य चुन सकें, इसलिए मुझे इसे कहीं और संभालने की जरूरत नहीं है।

उन लोगों के लिए जो उत्सुक हैं, मैं उन विकल्पों के लिए ईएनवी वेरिएशन का उपयोग करता हूं, जो मेरी वेज्रान्टाइल उपयोग करता है (क्लाउड सिस्टम के लिए संगत ansible arg को जोड़ना) और शेष ansible args को गुजरने देता है। जहां मैं एक बार में 10 से अधिक सर्वर बना रहा हूं और प्रावधान कर रहा हूं, मैं विफल सर्वर पर एक ऑटो रिट्री को शामिल करता हूं (जब तक प्रगति की जा रही है - मुझे एक बार में 100 या इतने ही सर्वर बनाते समय पाया गया कि कुछ पहले पहली बार विफल हो जाएंगे। )।

echo 'Usage: [VAR=value] bin/provision [options] dev|all|TARGET|vagrant'
echo '  bootstrap - Bootstrap servers ssh port and initial security provisioning'
echo '  dev - Provision localhost for development and control'
echo '  TARGET - specify specific host or group of hosts'
echo '  all - provision all servers'
echo '  vagrant - Provision local vagrant machine (environment vars only)'
echo
echo 'Environment VARS'
echo '  BOOTSTRAP - use cloud providers default user settings if set'
echo '  TAGS - if TAGS env variable is set, then only tasks with these tags are run'
echo '  SKIP_TAGS - only run plays and tasks whose tags do not match these values'
echo '  START_AT_TASK - start the playbook at the task matching this name'
echo
ansible-playbook --help | sed -e '1d
    s#=/etc/ansible/hosts# set by bin/provision argument#
    /-k/s/$/ (use for fresh systems)/
    /--tags/s/$/ (use TAGS var instead)/
    /--skip-tags/s/$/ (use SKIP_TAGS var instead)/
    /--start-at-task/s/$/ (use START_AT_TASK var instead)/
'

0

थोड़ा अलग समाधान विशेष चर का उपयोग करना है ansible_limitजो कि --limitअंसिबल के वर्तमान निष्पादन के लिए सीएलआई विकल्प की सामग्री है ।

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

यहां एक अतिरिक्त चर को परिभाषित करने की आवश्यकता नहीं है, बस --limitध्वज के साथ प्लेबुक चलाएं ।

ansible-playbook --limit imac-2.local user.yml
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.