ansible運維工具(二)

ansible playbook(二)php

運行palybook時 要使用ansible-playbook命令
palybook執行任務的順序是,在第一個主機上完成第一個任務,而後在第二個主機上完成第一個任務
而不是在第一個主機上完成全部任務,而後再在第二個主機上完成全部任務,以任務爲中心,在全部主機上執行
如何構建ansible的playbook
Inventory
Modules
Ad Hoc Commands
PlayBooks
Tasks 任務,及調用某模塊所完成的操做
Variable 變量
Templates 模版
Handlers 處理器,一般指的是在某條件知足時觸發執行的操做
Roles 角色
若是想說清楚的playbooks,還要額外的瞭解一些基礎概念html

Ansible中使用的YAML基礎元素:
    變量
    Inventory
    條件判斷
    迭代
基本結構

    - hosts: websrvs
      remote_user:
      tasks:
        - name: task1
          module_name:
        - name: task2
          module_name:

    - hosts: dbsrvs

簡單示例1:node

- hosts: websrvs
  remote_user: root
  tasks:
    - name: create nginx group
      group: name=nginx system=yes gid=208
    - name: create nginx user
      user: name=nginx uid=208 system=yes group=nginx

- hosts: dbsrvs
  remote_user: root
  tasks:
    - name: copy file to dbsrvs
      copy: src=/etc/inittab dest=/tmp/inittab.ansible

簡單實例2:python

- hosts: websrvs
  remote_user: root
  tasks:
    - name: install httpd packege
      yum: name=httpd state=latest
    - name: install configuration file for httpd
      copy: src=conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
    - name: start httpd service
      service: enabled=true name=httpd  state=started

簡單實例3-handler:
當配置文件發生改變時,應該讓服務重啓。那麼重啓服務就要用handler,當這個服務發生變化時使用notify屬性通知要執行的handler裏定義的任務以下:mysql

- hosts: websrvs
  remote_user: root
  tasks:
    - name: install httpd packege
      yum: name=httpd state=latest
    - name: install configuration file for httpd
      copy: src=conf/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
~

簡單實例4-定義變量:linux

- hosts: websrvs
  remote_user: root
  vars:
    - package: httpd
    - service: httpd
  tasks:
    - name: install httpd packege
      yum: name={{ package }} state=latest
    - name: install configuration file for httpd
      copy: src=conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
      notify:
        - restart httpd
    - name: start httpd service
      service: enabled=true name={{ service }} state=started
  handlers:
    - name: restart httpd
      service: name={{ service }} state=restarted

簡單示例5-使用facts變量:nginx

- hosts: websrvs
  remote_user: root
  tasks:
    - name: copy file
      copy: content= "{{ ansible_all_ipv4_addresses }}" dest=/tmp/vars.ans

一樣在inventory 中爲主機 或者主機組定義的變量也能夠經過 {{ 變量名 }}直接調用。web

簡單示例6-條件判斷語句when:sql

- hosts: all
  remote_user: root
  vars:
    - username: user10
  tasks:
    - name: create {{ username }} user
      user: name= {{username}}
      when: ansible_fqdn  == 'node1.my.com'

簡單示例7-迭代
重複執行同類task時使用
定義循環列表:with_itemsshell

- name: add serveral users
      user: name={{ item }} state=present groups=wheel
      with_items:
        - testuser1
        - testuser2
要安裝多個程序包的時候使用很方便,定義yum
    - apache
    - php
    - mysql-server

注意: with_item中的列表值也能夠是字典

    - name add serveral users
      user: name= {{ itesm.name }} state=present groups= {{ item.groups }}
      with_items:
        - { name: 'testuser1', groups: 'wheel' }
        - { name: 'testuser2', groups: 'root' }

比較是用的是,一個tasks下安裝程序包,定義配置文件就能夠用yum,和copy

with_items:
      - { name: apache, conf: conffiles/httpd.conf }
      - { name: php, conf: conffiles/php.ini }
      - { name: mysql-server, conf: conffiles/my.cnf }

模版template 的使用,經常使用於靜態配置文件中定義變量以及條件語句,通常在ansible中模版文件後綴名爲.j2由於使用的是jinjia2模版語言。同時也要安裝python的jinjia2擴展包,對於咱們來將最經常使用的就是變量。
使用舉例:
inventory中定義以下:
[websrvs]
172.16.100.7 http_port=80 maxClients=100
172.16.100.8 http_port=8080 maxClients=200

假若有一個配置文件中關於端口和maxClients配置項更改以下
Server Name {{ ansible_fqdn }}
Listen {{ http_port }}
maxClients {{ maxClients }}
通常都會建立一個名爲templates/httpd.conf.j2

接着咱們在playbooks就把以前使用copy模塊定義配置文件的地方改用template模塊,以下:

- hosts: websrvs
  remote_user: root
  vars:
    - package: httpd
    - service: httpd
  tasks:
    - name: install httpd packege
      yum: name={{ package }} state=latest
    - name: install configuration file for httpd
      template: src=/root/templates/httpd.conf dest=/etc/httpd/conf/httpd.conf
      notify:
        - restart httpd
    - name: start httpd service
      service: enabled=true name={{ service }} state=started
  handlers:
    - name: restart httpd
      service: name={{ service }} state=restarted

tags的使用
咱們前面定義的playbook中有多個tasks,若是咱們想單獨運行這個playbook中的某一個task就須要經過tabs來實現。

- hosts: websrvs
  remote_user: root
  vars:
    - package: httpd
    - service: httpd
  tasks:
    - name: install httpd packege
      yum: name={{ package }} state=latest
    - name: install configuration file for httpd
      template: src=/root/templates/httpd.conf dest=/etc/httpd/conf/httpd.conf
      tags:
        - conf
      notify:
        - restart httpd
    - name: start httpd service
      service: enabled=true name={{ service }} state=started
  handlers:
    - name: restart httpd
      service: name={{ service }} state=restarted

使用下面命令,只運行tags爲conf的任務

    ansible-playbook apache.yml --tags='conf'

固然能夠--tage='aa,bb,cc'指明多個tag

特殊tags
假若有的任務你想只要運行這個playbook(即便指定--tags)就須要執行這個task,那麼就可使用
tags: always

以上內容就能夠知足咱們對ansible的使用了,接來下了解角色的定義,讓咱們更方便的使用ansible
咱們想讓一批主機完成 一批任務就可使用playbook進行配置執行。那麼咱們想那爲何還要有role角色這個東西的存在。存在的意義是什麼。這裏咱們在playbook已經能夠實現爲一批主機執行一批任務了,爲何還要有role角色這個玩意。 那好咱們來舉個例子,假如一臺服務器上安裝nginx又安裝了php還安裝了mysql。那麼你能夠寫一個playbook的yaml文件,可是咱們如今又有一臺主機想只執行 nginx 和php,那麼你怎麼實現。固然能夠再次更改playbook,爲其添加一個play,但這違背了開發的儘可能不寫重複代碼的宗旨。因此你實現的方式很low。那麼這時候你若是想,事先定義了三個角色,一個nginx,php,mysql 在應用到主機上就完美了,那就是roles。

roles的應用
ansible 自1.2版本引入的新特性,用於層次性、結構化地組織playbook,roles可以根據層次型結構自動裝載變量文件、tasks以及handles等,要使用roles只須要在playbook中使用include指令便可,簡單來說,roles就是經過分別將變量、文件、任務、模塊及處理器放置於單獨的目錄中,並能夠便捷地include他們的一種機制,角色通常用於基於主機的構建服務的場景中,但也能夠適用於構建守護進程等場景中:

一個roles的案例以下所示:
    site.yml
    webservers.yml
    fooservers.yml
    roles/
        common/
          files/
          templates/
          tasks/
          handlers/
          vars/
          meta/
        webservers/
          files/
          templates/
          tasks/
          handlers/
          vars/
          meta/
而在playbook中,也能夠這樣使用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: some_role, when: "ansible_os_family == 'redhat'"}

8.1建立role的步驟
(1) 建立以roles命名的目錄;
(2) 在roles目錄中分別建立以各類角色名稱命名的目錄,如 webservers等;
(3) 在每個角色命名的目錄中分別建立 files,handlers,meta, tasks,templates 和vars目錄:用不到的目錄能夠建立爲空目錄,也能夠不建立;
(4) 在playbook文件中,調用各角色

8.2 role內各目錄彙總可用的文件

tasks目錄: 至少應該包含一個名爲main.yml的文件,其定義來此角色的任務列表;此文件可使用include包含其它的位於此目錄中的task文件;
files目錄: 存放又copy或script等模塊調用的文件;
templates目錄: template模塊會自動在此目錄中尋找jinjia2模版文件;
handlers目錄: 此目錄中應當包含一個mian.yml文件,用於定義此角色用到的handler,在handler中使用include包含的其它的handler文件也應該位於此目錄;
vars目錄:應當包含一個mian.yml文件,用於定義此角色用到的變量;
meta目錄:應當包含一個main.yml文件,用於定義此角色的特殊設定及其依賴關係,ansible 1.3及其之後的版本才支持;
default目錄: 爲當前角色設定變量時使用此目錄,應當包含一個main.yml文件

示例:
1.建立roles目錄
mkdir /root/ansible_playbooks/roles
mkidr -pv /root/ansible_playbooks/roles/{webservers, dbservers}/{tasks,files,templates,handlers,vars,meta}
2. 把要用到的文件放到 files目錄下,把要用到的template文件放到 templates目錄下
3. 在tasks目錄中編輯main.yml
vim /root/ansible_playbooks/roles/webservers/tasks/main.yml
- name: install httpd packeg
yum: name=httpd
- name: install configuration file for httpd
template: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
tags:
- conf
notify:
- restart httpd
- name: start httpd service
service: enabled=true name={{ service }} state=started
這裏指定模版文件的時候,就不用指定目錄來,它會本身去找角色目錄下的template目錄下的文件
4. 這裏咱們用到了notify,也就是說咱們須要定義handlers,接下來

vim /root/ansible_playbooks/roles/webservers/handlers/main.yml
      - name: restart httpd
      service: name={{ service }} state=restarted

5. 若是想定義變量
    vim /root/ansible_playbooks/roles/webservers/vars/main.yml
        - http_port: 80
        - service: httpd
        - maxclients: 200
6. 這樣咱們就定義了webservers 這個角色,未來咱們想要調用這個角色,須要在roles這個目錄的同級目錄下有site.yml文件
vim site.yml
- hosts: websrvs
  remote_user: root
  roles:
    - webservers

至此 咱們ansible-playbook site.yml
爲了體現這個roles的靈活性:
vim site.yml
- hosts: 172.16.100.7
remote_user: root
roles:
- webservers

- hosts: 172.16.100.8
  remote_user: root
  roles:
    - dbservers

- hosts: 172.16.100.9
  remote_user: root
  roles:
    - webservers
    - dbservers





4.1 YAML 簡介
YAML是一個可讀性高的用來表達資料序列的格式。YAML在設計時參考了其餘多種語言,包括:XML、C語言、PYTHON、Perl以及電子郵件格式的RFC2882等,Clark Evans 在2001年首次發表了這種語言,另外Ingy dot Net 與 Ben-Kiki 也是這語言的共同設計者。

YAML Ain't Markup Language, 即YAML不是XML,不過,在開發的這種語言是,YAML的意思實際上是: 「Yet Another Markup  Language"(還是一種標記語言),其特性:

也是用於在不一樣主機之間共享數據時,可以經過某種特定形式描述數據自己結構的一種數據組織形式。不一樣xml的是,yaml經過使用鍵值對+縮進的形式表示的

YAML 的可讀性好
YAML 和腳本語言的交互性好
YAML 使用實現語言的數據類型
YAML 又一個一直的信息模型
YAML 易於實現
YAML 能夠基於流來處理
YAML 表達能力強,擴展性好
更多的內容及規範參見http://www.yaml.org/

4.2 YAML 語法

YAML的語法和其餘高階語言相似,而且能夠簡單表達清單、散列表、標量等數據結構,其結構(Structure) 經過空格來展現, 序列(sequence)裏的項用"-"來表明,Map裏的鍵值對用":"分隔。下面是一個事例
name: John Smith
age: 41
gender: Male
spouse:
    name: Jane Smith
    age:37
    gender: Female
children:
    -   name: Jimmy Smith
        age :17
        gender : Male
    -   name: Jenny Smith
        age: 13
        gender:female
YAML 文件擴展名一般爲.yaml, 如 example.yaml.

4.2.1 list
列表的全部元素均使用"-"大頭,例如:
# A list of tasty fruits
- Apple
- Orange
- strawberry
- mango

4.2.2 dictionay
字典經過key與value進行標示, 例如:
---
# An employee record
name: Examle Developer
job: Developer
skill: Elite

也能夠將key:value 放置於{}中進行表示,例如:
---
# An employee record
{name: Examle Developer, job: Developer, skill: Elite}

5、Ansible基礎元素

5.1 變量

5.1.1 變量命名
變量名僅能由字母、數字和下劃線組成,且只能以字母開頭
5.1.2 facts
facts 是由正在通訊的遠程目標主機發回的信息,這些信息被保存在ansible變量中,要獲取指定的遠程主機所支持的全部facts,可以使用以下命令進行:
# ansible hostname -m setup
5.1.3 register
把任務的輸出定義爲變量,而後用於其餘任務,示例以下:

tasks:
    - shell: /usr/bin/foo
    - register: foo_result
    - ignore_errors:True
5.1.4 經過命令行傳遞變量
在運行playbook的時候也能夠傳遞一些變量供playbook使用:示例以下:
    ansible-playbook test.yml --extra-vars "hosts=www user=mageedu"

5.1.5 經過role傳遞變量
當給一個主機應用角色的時候能夠傳遞變量, 而後在角色內使用這些變量,示例以下:
    - hosts: webservers
      roles:
        - common
        - {role: foo_app_instance, dir:'/web/htdocs/a.com', port:8080}

5.2 Inventory
ansible 的主要做用在於批量主機操做, 爲了便捷地使用其中的部分主機, 能夠在inventory file 中將其分組命名, 默認的inventory file爲/etc/ansible/hosts.

inventory file 能夠有多個,且也能夠經過 Dynamic Inventory來動態生成。

5.2.1 inventory文件格式
inventory 文件遵循INI文件風格, 中括號中的字符爲組名,能夠將同一個主機同時歸到多個不一樣的組中;此外,當如若目標主機使用了非默認的SSH端口,還能夠在主機名稱以後使用冒號來標明。

ntp.mageedu.com

[webserver]
www1.my.com:2222
www2.my.com

[dbserver]
db1.my.com
db2.my.com
db3.my.com

若是主機名遵循類似的命名模式,還可使用列表的方式標識各主機,例如:

[webservers]
www[01:10].my.com
[databases]
db-[a:f].my.com

5.2.2主機變量

能夠在inventory中定義主機時爲其添加主機變量以便與在playbook中使用,例如:
[webservers]
www1.my.com http_port=80 maxRequestsPerChild=808
www1.my.com http_port=8080 maxRequestsPerChild=909

5.2.3組變量

組變量是指賦予給指定組內全部主機上的palybook中可用的變量,例如:

[webservers]
www1.my.com
www2.my.com

[webservers:vars]
ntp_server=ntp.my.com
nfs_server=nfs.my.com

5.2.4 組嵌套
inventory 中,組還能夠包含其餘組,而且也能夠向組中的主機指定變量,不過,這些變量只能在ansible-playbook中使用,而ansible不支持,例如:
[apache]
http1.my.com
http2.my.com

[nginx]
ngx1.my.com
ngx2.my.com

[webservers:children]
apache
nginx

[webservers:vars]
ntp_server=ntp.my.com

5.2.5 inventory參數
ansible基於ssh鏈接inventory中指定的遠程主機時,還能夠經過參數指定其交互方式;這些參數以下所示:
[webservers]
172.16.100.7 ansible_ssh_user=root ansible_ssh_pass=mypasswd ansible_ssh_port=12008


5.3 條件測試
在task後添加when子句便可使用條件測試;when語句支持jinjia2表達式語法,例如:

    tasks:
      - name: "shutdown Debian flavored systems"
      command: /sbin/shutdown -h now
      when: ansible_os_family == 'Debian'
when語句中還可使用jinjia2的大多"filter", 例如要忽略此前某語句的錯誤並基於其結果<failed或者sucess> 運行後面指定的語句,可以使用相似以下形式:

    tasks:
        - command: /bin/false
          register: result
          ignore_errors; True
        - command: /bin/something
          when: result|failed
        - command: /bin/somethin_else
          when: result|skipped
   此外,when 語句中還可使用facts或playbook中定義的變量
5.4 迭代,其實就表示循環

當有須要重複性執行的任務時,可使用迭代機制,其使用格式爲將須要迭代的內容定義爲item變量引用,並經過with_items 語句來指明迭代的元素列表便可
- 例如:

    - name: add serveral users
      user: name={{ item }} state=present groups=wheel
      with_items:
        - testuser1
        - testuser2

上面語句的功能等同於下面的語句:

    - name: add user testuser1
      user: name=testuser1 state=present groups=wheel
    - name: add user testuser2
      user: name=testuser2 state=present groups=wheel

事實上,with_items中可使用元素還能夠爲hashes, 例如:

    - name add serveral users
      user: name= {{ itesm.name }} state=present groups= {{ item.groups }}
      with_items:
        - { name: 'testuser1', groups: 'wheel' }
        - { name: 'testuser2', groups: 'root' }

ansible的循環機制還有更多的高級功能, 具體請參見官方文檔(http://docs.ansible.com/playbooks_loops.html)

七. 如何編寫playbook
ansible playbooks
playbook是由一個或多個'play'組成的列表,play的主要功能在於將事先歸併爲一組的主機裝扮成事先經過ansible中的task定義好的角色。從根本上來說,所謂task無非是調用ansible的一個module.將多個play組織在一個palybook中,便可以讓他們聯同起來按事先編排的機制同唱一臺大戲,下面是一個簡單示例。

- hosts: webnodes
  vars:
    http_port: 80
    max_clients: 256
  remote_user:root
  tasks:
    - name: ensure apache is  at the latest version
      yum : name=httpd state=latest
    - name: ensure apache is running
      service: name=httpd state=started
  handlers:
    - name: retart apache
      service: name=httpd state=restarted

7.1 palybook的基礎組件
7.1.1 Hosts和Users
playbook中的每個play的目的都是爲了讓某個或某些主機以某個指定的用戶身份執行任務。hosts 用於指定要執行任務的主機,其能夠是一個或多個由某好分隔主機組;remote_user 則用於指定遠程主機上的執行任務的用戶,如上圖示例中的

- hosts: webnodes
      remote_user: root

不過,remote_user也可用於各task中,也能夠經過指定其經過sudo的方式在遠程主機上執行任務,其可用於play全局或某任務,此外,甚至能夠在sudo時使用sudo_user指定sudo時切換的用戶。
- hosts: webnodes
remote_user: ted1
tasks:
- name: test connection
ping:
remote_user: ted2
sudo : yes
7.1.2 任務列表和action

play的主體部分石task list.task list中的各任務按次序逐個在hosts中指定的全部主機上執行,即在全部主機上完成第一個任務後在開始第二個。在運行自上而下某playbook時,若是中途發生錯誤,全部已執行任務均可能會回滾,所以,在更正playbook後從新執行一次便可。

task的目的是使用指定的參數執行模塊,而在模塊參數中可使用變量,模塊執行時冪等的,這意味着屢次執行時安全的,由於其結果均一致。

每一個task都應該有其name, 用於playbook的執行結果輸出,建議其內容儘量清晰地描述任務執行步驟,若是未提供name,則action的結果用於輸出。

定義task的可使用"action: module options"或"module:
options"的格式, 推薦使用後者以實現向後兼容。若是action一行的內容過多,也可在行首使用幾個空白字符進行換行。
tasks:
    - name: make sure apache is running
      service: name=httpd state=running
在衆多模塊彙總,只有command和shell模塊僅須要給定一個列表而無需使用"key=value"格式,例如:

    tasks:
        - name: disable selinux
          command: /sbin/setenforce 0
若是命令或者腳本的退出碼不爲零,可使用以下方式替代:

    tasks:
        - name: run this command and ignore the result
          sehll: /usr/bin/somecommand|| /bin/true

或者使用ignore_errors來忽略錯誤信息:(即便運行有錯誤,無論他繼續執行其餘tasks)

    tasks:
        - name: run this command and ignore the result
          shell: /usr/bin/somecommand
          ignore_errors: True

7.1.3 handlers
用於當天關注的資源發生變化時採起必定的操做。
'notify'這個action可用於在每一個play的最後被觸發。 這樣能夠避免屢次由改變發生時每次都執行指定的操做,取而代之,僅在全部的變化發生完成後一次性執行指定操做。在notify中列出的操做成爲handler,也即notify中調用handler中定義的操做。
- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache
handler是task列表,這些task與前述的task並無本質上的不一樣。
handlers:
- name: restart memcached
service: name=mamcached state=restarted
- name: restart apache
service: name=apache state=restarted

示例:
    - hosts: websrvs
      remote_user: root
      tasks:
        - name: install httpd packege
          yum: name=httpd state=latest
        - name: install configuration file for httpd
          copy: src=conf/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
相關文章
相關標籤/搜索