1. 程式人生 > >3.3 ansible之playbook

3.3 ansible之playbook

類型 並不會 apple notify nta 註釋 ict ins 設計者

playbook

1 playbook是由一個或多個“play”組成的列表
2 play的主要功能在於將事先歸並為一組的主機裝扮成事先通過ansible中的task定義好的角色。從根本上來講,所謂task無非是調用ansible的一個module。將多個play組織在一個playbook中,即可以讓它們聯同起來按事先編排的機制同唱一臺大戲
3 Playbook采用YAML語言編寫

技術分享圖片

YAML語法簡介

List:列表,其所有元素均使用“-”打頭
示例

A list of tasty fruits

  • Apple
  • Orange
  • Strawberry
  • Mango

    YAML介紹

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

    2 YAML Ain’t Markup Language,即YAML不是XML。不過,在開發的這種語言時,YAML的意思其實是:”Yet Another Markup Language”(仍是一種標記語言)

特性

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

YAML語法簡介

1 在單一檔案中,可用連續三個連字號(—)區分多個檔案。另外,還有選擇性的連續三個點號( … )用來表示檔案結尾
2 次行開始正常寫Playbook的內容,一般建議寫明該Playbook的功能

3 使用#號註釋代碼
4 縮進必須是統一的,不能空格和tab混用
5 縮進的級別也必須是一致的,同樣的縮進代表同樣的級別,程序判別配置的級別是通過縮進結合換行來實現的
6 YAML文件內容和Linux系統大小寫判斷方式保持一致,是區別大小寫的,k/v的值均需大小寫敏感
7 k/v的值可同行寫也可換行寫。同行使用:分隔
8 v可是個字符串,也可是另一個列表
9 一個完整的代碼塊功能需最少元素需包括 name: task
10 一個name只能包括一個task
11 YAML文件擴展名通常為yml或yaml
12 Dictionary:字典,通常由多個key與value構成

範例:
An employee record
{name: Example Developer, job: Developer, skill: Elite}

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

Playbook核心元素

1 Hosts 執行的遠程主機列表
2 Tasks 任務集
3 Varniables 內置變量或自定義變量在playbook中調用
4 Templates 模板,可替換模板文件中的變量並實現一些簡單邏輯的文件
5 Handlers 和notity結合使用,由特定條件觸發的操作,滿足條件方才執行,否則不執行
6 tags 標簽 指定某條任務執行,用於選擇運行playbook中的部分代碼。ansible具有冪等性,因此會自動跳過沒有變化的部分,即便如此,有些代碼為測試其確實沒有發生變化的時間依然會非常地長。此時,如果確信其沒有變化,就可以通過tags跳過此些代碼片斷

ansible-playbook –t tagsname useradd.yml

範例
技術分享圖片

[root@ansible ansible]# vim test.yml

  • hosts: cen7 要執行的主機
    remote_user: root 用哪個用戶執行

    tasks: 任務集

    • name: install package 一條任務要有一個名字
      yum: name=httpd 調用的模塊,和參數
    • name: start service
      service: name=httpd state=started enabled=yes

查看playbook中被執行的主機列表

[root@ansible ansible]# ansible-playbook test.yml --list-host

playbook: test.yml

play #1 (cen7): cen7 TAGS: []
pattern: [u‘cen7‘]
hosts (2):
192.168.27.101
192.168.27.102

查看playbook中有哪些任務

ERROR! You must specify a playbook file to run
[root@ansible ansible]# ansible-playbook test.yml --list-tasks

playbook: test.yml

play #1 (cen7): cen7 TAGS: []
tasks:
install package TAGS: []
start service TAGS: []
技術分享圖片

一個playbook推薦只寫一個play,當然可以寫多個play

技術分享圖片

實驗

1 安裝http服務並把它設置為開機啟動,並將端口改為8080端口,開啟服務,寫一個playbook
2 首先在自己的電腦上裝一個http服務,並且修改好配置文件,然後在將配置文件復制到遠程主機上,啟動服務,這裏的所有主機都是centos7的,不同系統版本的http配置文件不一樣,所以要同一版本

  • hosts: cen7
    remote_user: root

    tasks:

    • name: isntall httpd
      yum: name=httpd
    • name: copy config httpd
      copy: src=/app/httpd.conf dest=/etc/httpd/conf/ backup=yes
    • name: start httpd
      service: name=httpd state=started enabled=yes

當我們在想把配置文件改為80端口,如果在重新執行上面的playbook並不會改過了,因為上面只是定義了啟動服務,所以我們要用handlers條件出發


  • hosts: cen7
    remote_user: root

    tasks:

    • name: isntall httpd
      yum: name=httpd
    • name: copy config httpd
      copy: src=/app/httpd.conf dest=/etc/httpd/conf/ backup=yes
      notify: restart httpd 當copy發生改變時會執行notify所指定的名字任務
    • name: start httpd
      service: name=httpd state=started enabled=yes

    handlers: handlers是一個特殊的tasks也可以寫多個任務

    • name: restart httpd
      service: name=httpd state=restarted

當第一次執行這個playbook會順序執行,不會觸發handlers,因為第一次包都沒有裝,但是當第二次執行時開始執行handlers,當copy命令執行結果改變時,會執行對應的handlers的任務

技術分享圖片

playbook基礎組件

Hosts
playbook中的每一個play的目的都是為了讓某個或某些主機以某個指定的用戶身份執行任務。hosts用於指定要執行指定任務的主機,須事先定義在主機清單中
可以是如下形式

bash
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*

Websrvs:dbsrvs 兩個組的並集
Websrvs:&dbsrvs 兩個組的交集
webservers:!phoenix 在websrvs組,但不在dbsrvs組
示例: - hosts: websrvs:dbsrvs

remote_user: 可用於Host和task中。也可以通過指定其通過sudo的方式在遠程主機上執行任務,其可用於play全局或某任務;此外,甚至可以在sudo時使用sudo_user指定sudo時切換的用戶

  • hosts: websrvs
    remote_user: root
    tasks:
    • name: test connection
      ping:
      remote_user: magedu
      sudo: yes 默認sudo為root
      sudo_user:wang sudo為wang

task列表和action

1 play的主體部分是task list。task list中的各任務按次序逐個在hosts中指定的所有主機上執行,即在所有主機上完成第一個任務後再開始第二個。在運行自下而下某playbook時,如果中途發生錯誤,所有已執行任務都將回滾,因此,在更正playbook後重新執行一次即可
2 task的目的是使用指定的參數執行模塊,而在模塊參數中可以使用變量。模塊執行是冪等的,這意味著多次執行是安全的,因為其結果均一致
每個task都應該有其name,用於playbook的執行結果輸出,建議其內容盡可能清晰地描述任務執行步驟。如果未提供name,則action的結果將用於輸出

tasks:任務列表

格式:
(1) action: module arguments
(2) module: arguments 建議使用

示例
tasks:

  • name: disable selinux
    command: /sbin/setenforce 0

如果命令或腳本的退出碼不為零,可以使用如下方式替代

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

或者使用ignore_errors來忽略錯誤信息

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

運行playbook

運行playbook的方式

ansible-playbook <filename.yml> ... [options]

常見選項
–check 只檢測可能會發生的改變,但不真正執行操作
–list-hosts 列出運行任務的主機
–limit 主機列表 只針對主機列表中的主機執行
-v 顯示過程 -vv -vvv 更詳細

  • 範例
    ansible-playbook file.yml --check 只檢測
    ansible-playbook file.yml
    ansible-playbook file.yml --limit websrvs

範例1,限定特定的主機執行,並不是所以的主機執行
[root@ansible app]# ansible-playbook httpd.yml --limit 192.168.27.101
只針對101主機執行並不是所有主機

技術分享圖片

Playbook VS ShellScripts

SHELL腳本

#!/bin/bash

安裝Apache

yum install --quiet -y httpd

復制配置文件

cp /path/to/config/httpd.conf
/etc/httpd/conf/httpd.conf
cp/path/to/httpd-vhosts.conf
/etc/httpd/conf/httpd-vhosts.conf

啟動Apache,並設置開機啟動

service httpd start
chkconfig httpd on

Playbook定義


  • hosts: all
    tasks:
  • name: "安裝Apache"
    command: yum install -q -y httpd
  • name: "復制配置文件"
    command: cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
    command: cp /tmp/httpd-vhosts.conf /etc/httpd/conf/httpd-vhosts.conf
  • name: "啟動Apache,並設置開機啟動"
    service: name=httpd state=started enabled=yes

    範例
    示例:system.yml

    -hosts: all
    remote_user: root
    tasks:

    • name: create mysql user
      user: name=mysql system=yes uid=36
    • name: create a group
      group: name=httpd system=yes

    示例:httpd.yml

    • hosts: websrvs
      remote_user: root
      tasks:
    • name: Install httpd
      yum: name=httpd state=present
    • name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      • name: start service
        service: name=httpd state=started enabled=yes

        handlers和notify結合使用觸發條件

Handlers
是task列表,這些task與前述的task並沒有本質上的不同,用於當關註的資源發生變化時,才會采取一定的操作.
notify這個action可用於在每個play的最後被觸發,這樣可以避免多次有改變發生時每次都執行指定的操作,僅在所有的變化發生完成後一次性地執行指定操作。在notify中列出的操作稱為handler,也即notify中調用handler中定義的操作

Playbook中handlers使用

  • hosts: websrvs
    remote_user: root
    tasks:
    • name: Install httpd
      yum: name=httpd state=present
    • name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      notify: restart httpd
    • name: ensure apache is running
      service: name=httpd state=started enabled=yes
      handlers:
    • name: restart httpd
      service: name=httpd status=restarted

示例

  • hosts: websrvs
    remote_user: root
    tasks:
    • name: add group nginx
      tags: user
      user: name=nginx state=present
    • name: add user nginx
      user: name=nginx state=present group=nginx
    • name: Install Nginx
      yum: name=nginx state=present
    • name: config
      copy: src=/root/config.txt dest=/etc/nginx/nginx.conf
      notify:
      • Restart Nginx
      • Check Nginx Process
        handlers:
    • name: Restart Nginx
      service: name=nginx state=restarted enabled=yes
    • name: Check Nginx process
      shell: killall -0 nginx > /tmp/nginx.log

Playbook中tags使用,從劇本中挑出tags代表的任務,只執行這個,其它的不執行

tage的名字可以相同
示例:httpd.yml

  • hosts: websrvs
    remote_user: root
    tasks:
    • name: Install httpd
      yum: name=httpd state=present
    • name: Install configure file
      copy: src=files/httpd.conf dest=/etc/httpd/conf/
      tags: conf
    • name: start httpd service
      tags: service
      service: name=httpd state=started enabled=yes

[root@ansible app]# ansible-playbook -t conf,service httpd.yml

可以一次啟動多個tags標簽。加-t或者–tags

Playbook中變量使用

變量名:僅能由字母、數字和下劃線組成,且只能以字母開頭
變量來源:
1 ansible setup facts 遠程主機的所有變量都可直接調用
2 在/etc/ansible/hosts中定義
普通變量:主機組中主機單獨定義,優先級高於公共變量
公共(組)變量:針對主機組中所有主機定義統一變量
3 通過命令行指定變量,優先級最高
ansible-playbook –e varname=value
4 在playbook中定義
bash
vars:</li>
<li>var1: value1</li>
<li>var2: value2

5 在role中定義
用setup模塊可以查看機器的所有的內置變量

ansible cen7 -m setup

也可以用filter參數搜索變量,支持通配符

[root@ansible app]# ansible cen7 -m setup -a ‘filter=hostname
192.168.27.102 | SUCCESS => {
"ansible_facts": {
"ansible_hostname": "g102"
},
"changed": false
}
192.168.27.101 | SUCCESS => {
"ansible_facts": {
"ansible_hostname": "g101"
},
"changed": false
}
[root@ansible app]# ansible cen7 -m setup -a ‘filter=nodename
192.168.27.101 | SUCCESS => {
"ansible_facts": {
"ansible_nodename": "g101.com"
},
"changed": false
}
192.168.27.102 | SUCCESS => {
"ansible_facts": {
"ansible_nodename": "g102.com"
},
"changed": false
}
[root@ansible app]# ansible cen7 -m setup -a ‘filter=fqdn
192.168.27.102 | SUCCESS => {
"ansible_facts": {
"ansible_fqdn": "g102.com"
},
"changed": false
}
192.168.27.101 | SUCCESS => {
"ansible_facts": {
"ansible_fqdn": "g101.com"
},
"changed": false
}
最好寫全名稱
可以查ip地址
ct, raw, meta
[root@ansible app]# ansible cen7 -m setup -a ‘filter=addr
192.168.27.102 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.27.102"
],
"ansible_all_ipv6_addresses": [
"fe80::20c:29ff:fe8b:f0dd"
]
},
"changed": false
}
192.168.27.101 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.27.101"
],
"ansible_all_ipv6_addresses": [
"fe80::20c:29ff:fec3:887f"
]
},
"changed": false
}

Playbook中變量使用

變量命名
變量名僅能由字母、數字和下劃線組成,且只能以字母開頭
變量定義:key=value
示例:http_port=80
變量調用方式:
通過{{ variable_name }} 調用變量,且變量名前後必須有空格,有時用“{{ variable_name }}”才生效

ansible-playbook –e 選項指定

ansible-playbook test.yml -e "hosts=www user=mageedu"

範例1:var.yml

  • hosts: websrvs
    remote_user: root
    tasks
    • name: install package
      yum: name={{ pkname }} state=present

ansible-playbook -e pkname=httpd var.yml

範例在playbook中賦值並調用

[root@ansible ansible]# vim var2.yml

  • hosts: cen7
    remote_user: root
    vars: //如果要在play中第一變量要用vars

    • username: user123 //變量名:賦值
    • groupname: group123

    tasks:

    • name: create group
      group: name={{ groupname }} //調用變量
    • name: create uesr
      user: name={{ username }} group={{ groupname }} home=/app/{{ username }}dir //可以寫變量加其它字段
      [root@ansible ansible]# ansible-playbook var2.yml
      [root@ansible ansible]# ansible cen7 -a ‘getent passwd user123‘
      192.168.27.101 | SUCCESS | rc=0 >>
      user123:x:1001:1001::/app/user123dir:/bin/bash

      範例2:變量

      vim var2.yml
      -hosts: websrvs
      remote_user: root
      vars:

      • username: user1
    • groupname: group1

    tasks:

    • name: create group
    • group: name={{ groupname }} state=present
    • name: create user
      user: name={{ username }} state=present

ansible-playbook var2.yml ansible-playbook -e "username=user2 groupname=group2” var2.yml

用yum模塊可以一次安裝或卸載多個包

ansible cen7 -m yum -a ‘name=dstat,httpd state=absent‘

3.3 ansible之playbook