ansible playbooks

10.ansible playbooks
10.1簡介
(1)playbook是由一個或多個“play”組成的列表
(2)play的主要功能在於將事先歸併爲一組的主機裝扮成事先通過anaible中task定義好的角色。從根本上來將,所謂task無非是調用ansible的一個module,將多個play組織在一個playbook中,即可以讓它們聯通起來按事先編排的機制同唱一臺大戲。
10.2組成結構
Inventory
Modules
Ad hoc commands
Playbooks
Tasks:任務,即調用模塊完成的某操作
Variables:變量
Templates:模板
Handlers:處理器,由某時間觸發執行的操作
10.3 playbook
基礎組件包括:Tasks、Variables、Templates、Handlers、Roles
10.3.1hosts和users
(1)playbook中每一個play的目的都是爲了讓某個或某些主機以某個指定的用戶身份執行任務。
(2)Hosts用於指定要執行指定任務的主機,其可以是一個或多個由冒號分割主機組:
(3)remote_user則用於指定遠程主機上的執行任務的用戶。如上面實例中的
-hosts:webnodes
remote_user:root
不過,remote_user也可用於各task中,也可以通過指定其通過sudo的方式在遠程主機上執行任務,其可以用於play全局或某任務:此外,甚至可以在sudo時使用sudo_user指定sudo時切換的用戶

  • hosts:webnodes //定義一個主機組
    remote_user:zhang //定義登錄時的用戶身份
    tasks: //定義任務,可以有多個
  • name: test connection //任務名稱
    gather_facts: false 這個參數指定了在以下任務執行前,是否先執行setup模塊獲取主機相關信息,這在後面的task會使用到task獲取的信息,如果不需要,則選項爲false,默認開啓
    ping: //動作
    remote_user:zhang //在這可以使用自己定義的,相當於局部變量
    sudo:yes //是否sudo到root用戶
    10.3.2任務列表和action
    (1)Play的主體部分是task list
    (2)Task list 中的各任務按次序逐個在hosts中指定的所有主機上執行,即在所有主機上完成第一個任務後再開始第二個
    (3)在運行自下而上某playbook時,如果中途發生錯誤,所有已執行任務都可能回滾,因此,在更正playbook後重新執行一次即可
    (4)Task的目的是使用指定的參數執行模塊,而在模塊參數中可以使用變量。模塊執行是冪等的,這意味着多次執行是安全的,因爲其結果一致
    (5)每個task都應該有其name,用於playbook的執行結果輸出,建議其內容儘可能清晰的秒數任務執行步驟,如果未提供name,則action的結果將用於輸出
    (6)定義task的可以使用“action:module options”或“module:option”的格式,推薦使用後者以實現向後兼容,前邊的只是在較新的版本中纔可以使用。如果action一行的內容過多,可以在行首使用幾個空白字符進行替換
    tasks:
    -name:make sure apache is runing
    service :name-httpd state=running //在運行這個模塊時使用後面的參數
    (7)在衆多模塊中,只有command和shell模塊僅需要給定一個列表而無需使用“key-value”格式,例如
    tasks:
    -name:disbles selinux
    command: /sbin/setenforce 0
    (8)如果命令或腳本的退出碼不爲0,可以使用如下方式替代:
    tasks:
    • name: run this command and ignore the result
      shell: /usr/bin/somecommand || /bin/true //強行成功
      (9)使用ignore_errors來忽略錯誤信息
      tasks:
      -name: run this command and ingore the result
      shell: /usr/bin/somecommand
      ignore errors:True //忽略失敗,不影響後續執行
      10.3.3例一
      安裝apache服務,並確保服務正常啓動
  • hosts: webnodes //只對webnodes組裏邊的服務器生效,webnodes在inventory中定義
    vars: //在這組主機上定義了一組變量,vars,是一個鍵值對,值是個字典
    http_port:80
    max_clients:256
    remote_user:root //連接到遠程主機時以哪個用戶登錄
    tasks: //用來定義接下來執行的任務有哪些
    • name:ensure apache is at the lastest version //第一個任務
      yum:name=httpd state=latest //基於yum模塊來安裝程序包
    • name:ensure apache is runing //第二個任務
      service:name=httpd state=started //基於service模塊來啓動服務
      handlers: //處理器
    • name:restart apache
      service:name=httpd state=restarted
      10.3.4例二
      創建nginx組和用戶,複製本地文件到遠端服務器
  • hosts: zhang
    remote_user: root
    tasks:
    • name: create nginx group
      group: name=nginx system=yes gid=208
    • name: create nginx user
      user: name=nginx uid=208 group=nginx system=yes
  • hosts: wang
    remote_user: root
    tasks:
    • name: copy file to wang
      copy: src=/etc/passwd dest=/tmp/wang.txt
      ansible playbooks
      執行後結果如下圖,changed表示已經在遠程主機上已經做了修改,後邊有個PLAY RECAP是報告任務的執行情況
      ansible playbooks

10.3.5例三
安裝httpd服務,使用本地配置文件,啓動服務

  • hosts: zhang
    remote_user: root
    tasks:
    • name: install httpd package
      yum: name=httpd state=latest
    • name: install configuration file for httpd
      copy: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
    • name: start httpd service
      service: enabled=true name=httpd state=started
      ansible playbooks
      ansible playbooks

10.3.6例四
使用兩個花括號來表示引用變量值

  • hosts: zhang
    remote_user: root
    vars:
    • package: httpd
    • service: httpd
      tasks:
    • name: install httpd package
      yum: name={{ package }} state=latest
    • name: install configuration file for httpd
      copy: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
      notify: restart httpd
    • name: start {{ service }} service
      service: enabled=true name=httpd state=started
      handlers:
    • name: restart httpd
      service: name=httpd state=restarted
      ansible playbooks
      10.3.7 handlers
      (1)用於當關注的資源發生變化時採取一定的操作
      (2)舉例說明,比如上面的實例二,當重新修改httpd.conf的時候,需要重啓下服務,但是ansible並沒有這麼做,所以需要使用handlers這個action
      (3)“notify”這個action可用於在每個play的最後被觸發,這樣可以避免多次有改變發生時每次都執行指定的操作,取而代之,僅在所有的變化發生完成後一次性的執行指定操作,(4)在notify中列出的操作稱爲handler,也即notify中調用handler中定義的操作,當有改變的時候notify通知handler執行下邊的操作。
      如果配置文件改變,將重啓apache和memcache
  • name: template configuration file
    template: src=template.j2 dest=/etc/foo.conf
    notify: //指明觸發哪一個操作
    • restart memcached
    • restart apache
      handlers:
    • name: restart memcached
      service: name=memcached state=restarted
    • name: restart apache
      service: name=apache state=restarted
      (5)headles跟tasks是同級,需要定義,一般不會執行,只有當觸發了某一條件的時候纔會執行。比如可以將上述例二修改爲如下,這樣就可以確保,當配置文件發生改變的時候,服務也會重啓,配置文件將重讀一次。
      可以監控另外一個task,只有當這個task改變的時候纔會觸發notify執行
  • hosts: zhang
    remote_user: root
    tasks:
    • name: install httpd package
      yum: name=httpd state=latest
    • name: install configuration file for httpd
      copy: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
      notify: restart httpd
    • name: start httpd service
      service: enabled=true name=httpd state=started
      handlers:
    • name: restart httpd
      service: name=httpd state=restarted
      ansible playbooks
      ansible playbooks

(6)hendlers還可以監聽某一個handers A,當A觸發的時候,會觸發這個handlers,這樣多個handler監聽A的時候,當觸發了A,那麼監聽A的handlers都會被觸發
handlers:

  • name: restart memcached
    service:
    name: memcached
    state: restarted
    listen: "restart web services"
  • name: restart apache
    service:
    name: apache
    state:restarted
    listen: "restart web services"

tasks:

  • name: restart everything
    command: echo "this task will restart the web services"
    notify: "restart web services"
    10.3.8條件測試
    (1)when用於條件判斷,只有滿足條件的主機纔會執行這個任務,這個信息可以在setup收集回來的信息上取值
    (2)例如:
    • hosts: all
      remote_user: root
      vars:
    • username: user10
      tasks:
    • name: create {{ username }} user
      user: name={{ username }}
      when: ansible_fqdn == "glusterfs.tarena.com"
      ansible playbooks
      如下,不滿足條件的就被跳過了
      ansible playbooks
      10.3.9 迭代
      (1)簡介:當有需要重複執行的任務時,可以使用迭代機制,其使用格式爲將需要迭代的內容定義爲item變量引用,並通過with_items語句來指明迭代的元素
      (2)item_items中可以使用元素還可爲hashes
      (3)item是固定的變量名,會循環with_items列表中的每一個值來替代,相當於遍歷式的迭代循環
      (4)with_items中的列表還也可以是字典,但是引用時需要使用item.key
      (5)ansible的循環機制還有更多的高級功能,具體可以參見官方文檔http://docs.ansible.com/playbooks_loops.html
      例1:增加多個用戶
    • name: add serveral users
      user: name={{ item }} state=present groups=wheel
      with_items:
      • testuser1
      • testuser2
        例2:增加多個用戶並且指定組
    • name: add serveral users
      user: name={{ item }} state=present groups={{ item.groups }}
      with_items:
  • { name: 'testuser1',groups: 'wheel'}
  • { name: 'testuser2',groups: 'root'}
    10.3.10算數和比較運算符
    (1)允許使用計算值,很少用到,但是爲了完成性,允許其存在
    (2)支持 + - * / //(取整) % **(冪)
    (3)支持比較運算符 != == > >= < <=
    (4)可以使用變量
    (5)所有運算都必須在{{}}中
    10.3.11 Tags
    (1)Tags用於有選則的運行playbook中的代碼,可以選擇只運行有標籤的代碼,即調用playbook中的某一個任務
    (2)Ansible具有冪等性,因此會自動跳過沒有變化的部分,即使如此,有些代碼爲測試其沒有發生變化的時間依然會非常長。此時,如果確信其沒有變化,就可以使用tags跳過這些代碼片段
    (3)always_tags,這個選項的意思是無論如何被這個標記的任務都會執行
    Tags: t3,always
    (4)可以在play級別寫,也可以在tasks級別寫,寫到play級別下邊的tasks自動繼承play的tags名稱
    (5)一個name可以有多個tag,如下
    Tags: ts,http
    (6)ansible playbooks

例:

  • name: install httpd package
    yum: name={{ package }} state=latest
    tags:
    • conf
      10.3.12 roles
      10.3.12.1簡介
      (1)Ansible自1.2版本引入的新特性,用於層次性、結構化的組織playbook
      (2)roles能夠根據層次型結構自動裝載變量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include命令即可。簡單來講,roles就是通過分別將變量、文件、任務、模塊及處理器放置於單獨的目錄中,並可以便捷的include它們的一種機制。
      (3)角色一般用於基於主機構建服務的場景中,但也可以是用於構建守護進程等場景中
      10.3.12.2案例
      一個roles的案例如下:
      roles/
      common/
      files/ //分別將一些需要的東西放到對應的目錄中
      templates/
      tasks/
      handlers/
      vars/
      meta/
      webservers/
      files/
      templates/
      tasks/
      handlers/
      vars/
      meta/
      而在playbook中,可以這樣使用roles,直接調用roles裏邊的參數
    • hosts: webservers
      roles:
    • common
    • webservers
      也可以向roles傳遞參數,例如
    • hosts: webservers
      roles:
  • common
  • { role: foo_app_instance, dir: '/opt/a', port:5000 }
  • { role: foo_app_instance, dir: '/opt/b', port:5001 }
    甚至也可以條件式的使用roles,例如:
    • hosts: webservers
      roles:
      • { role: som_role, when: "ansible_os_family == 'Redhat'" }
        10.3.12.3創建role的步驟
        (1)構建以role命名的目錄
        (2)在roles目錄中分別創建以各角色名稱命名的目錄,如webservers等
        (3)在每個角色命名的目錄中分別創建files、handlers、meta、tasks、templates和var目錄;用不到的目錄可以創建爲空目錄,也可以不創建
        (4)在playbook文件中,請用各角色
        10.3.12.4role內各目錄中可用的文件
        Tasks目錄:至少應該包含一個名爲main.yml的文件,其定義的此角色的任務列表:此文件可以使用include包含其它的位於此目錄中的task文件
        Files目錄:存放由copy或scripts等模塊調用的文件
        Template目錄:template模塊會自動在此目錄中尋找jinja2模板文件
        Handlers目錄:此目錄中應當包含一個main
        Yml文件:用於定義此角色用到的各handlers;在handlers中使用include包含的其它handler文件也應該位於此目錄中
        Vars目錄:應當包含一個main.yml文件,用於定義此角色用到的變量
        Meta目錄:應當包含一個main.yml文件,用於定義此角色的特殊設定及其依賴關係;ansible1.3及其以後的版本才支持
        Default目錄:爲當前角色設定默認變量時才使用此目錄,應當包含一個main.yml文件
        10.3.13 lookups
        Lookup插件可以用來從外部數據讀取信息,然後賦給一個變量。獲取外部數據信息的種類包括:讀取文件內容、隨機生成password、執行shell命令、讀取redis的鍵值等等。注意,lookup所有的運算都是在ansible中控機上完成的,而不是遠程目標機
        10.3.13.1 第一個參數爲file
        第一個參數爲file,表示獲取外部文件內容
    • name: test
      hosts: self
      vars:
      contents: "{{ lookup('file', '/etc/foo.txt') }}"
      tasks:
    • debug: msg="the value of foo.txt is {{ contents }}"
    • debug: msg="the value of foo.txt is {{ lookup('file','/etc/foo.txt') }}"
      ansible playbooks
      10.3.13.2第一個參數爲password
      第一個參數爲password,表示生成一個隨機明文密碼,並存儲到指定文件中,生成的密碼包括大小寫字母、數字和.,:-_,長度爲20個字符,該長度可以通過傳遞一個額外參數length=<length>修改

除了length外,還可以使用chars=<chars>參數,用於自定義生成密碼的字符集
chars=’ ascii_letters,digits,hexdigits,punctuation,,’ ,號本身用,號

  • hosts: self
    gather_facts: false
    tasks:
  • debug: msg="password - {{ lookup('password', '/tmp/random_pass.txt length=10')}}"
    ansible playbooks
    10.3.13.3其它類型
  • hosts: all
    tasks:

    • debug: msg="{{ lookup('env','HOME') }} is an environment variable"

    • debug: msg="{{ lookup('pipe','date') }} is the raw result of running this command"

    • debug: msg="{{ lookup('redis_kv', 'redis://localhost:6379,somekey') }} is value in Redis for somekey"

    • debug: msg="{{ lookup('dnstxt', 'example.com') }} is a DNS TXT record for example.com"

    • debug: msg="{{ lookup('template', './some_template.j2') }} is a value from evaluation of this template"
      10.3.14循環
      ansible playbooks
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章