天天看點

自動化運維工具——YAML詳解YAML介紹YAML文法YAML支援的資料結構:playbook的組成三要素playbook 文法hosts和users介紹指定遠端主機sudo切換使用者小實驗 練練手Handlers介紹條件測試疊代

自動化運維工具——YAML詳解

  • YAML介紹
  • YAML文法
    • 基本文法
  • YAML支援的資料結構:
  • playbook的組成
  • 三要素
  • playbook 文法
  • hosts和users介紹
  • 指定遠端主機sudo切換使用者
  • 小實驗 練練手
    • 實驗要求:
  • Handlers介紹
    • 1、在playbook直接使用變量
    • 2、通過ansible指令傳遞
    • 3、直接在yaml中定義變量
    • 4、直接引用主機變量
  • 條件測試
    • 多條件判斷
    • 組條件判斷
  • 疊代

YAML介紹

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

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

YAML的可讀性好

YAML和腳本語言的互動性好

YAML使用實作語言的資料類型

YAML有一個一緻的資訊模型

YAML易于實作

YAML可以基于流來處理

YAML表達能力強,擴充性好

YAML文法

YAML的文法和其他高階語言類似,并且可以簡單表達清單、散清單、标量等資料結構。其結構(Structure)通過空格來展示,序列(Sequence)裡的項用"-“來代表,Map裡的鍵值對用”:"分隔。下面是一個示例。YAML是用鍵值對和縮進來表示的。

基本文法

1、大小寫敏感

2、使用縮進表示層級關系

3、縮進時不允許使用Tab鍵,隻能使用空格

4、縮進的空格數且不重要,隻要相同層級的元素左側對其即可

YAML支援的資料結構:

1.對象:鍵值對的集合,又稱為映射(mapping)/哈希(hashes)/字典(dictionary)

例如:

name:Example Developer
         鍵值
⒉數組:一組按次序排列的值,又稱為序列(sequence)/清單(list)例如:-Apple
         -Orange
3.純量:單個的、不可再分的值
例如:number: 12.30
             sure: true


yaml示例:
name:zhangsan
age:20
name:lisi
age:22
people:
-name:zhangsan
  age:20
  -name:lisiage:22

           

playbook的組成

Ansible的腳本—playbook劇本

通過task調用ansible的模闆将多個play組織在一個

playbook中運作。playbooks本身由以下各部分組成

(1)Tasks:任務,即調用子產品完成的某操作;

(2) Variables:變量

(3) Templates:模闆

(4)Handlers:處理器,當某條件滿足時,觸發執行的操作;

(5) Roles:角色。

三要素

劇本的三要素

1、演出的場地

2、演員要到位

3、故事情節

playbook的三要素

1、場地—主機組hosts

2、演員—授權執行的使用者 remote user

3、故事情節----執行的任務tasks (調用的是各種ansible子產品)

playbook 文法

執行一個playbook

ansible-playbook [yaml檔案名]
例如:ansible-playbook ping.yml
參數:-k(-ask-pass)用來互動輸入ssh密碼
        -K(-ask-become-pass)用來互動輸入sudo密碼
         -u指定使用者
補充指令:
ansible-playbook nginx.yaml --syntax-check #檢查yaml檔案的文法是否正确
 ansible-playbook nginx.yaml --list-task #檢查tasks任務
ansible-playbook nginx.yaml --list-hosts #檢查生效的主機
ansible-playbook nginx.yaml --start-at-task='Copy Nginx.conf’ #指定從某個task開始運作
           

hosts和users介紹

hosts: webserver #指定主機組,可以是一個或多個組。

remote user: root #指定遠端主機執行的使用者名

[[email protected] ~]# vim ping.yaml  
- hosts: all  #定義主機組
  remote_user: root   #指定root使用者 全局變量
  tasks:
   - name: test connection
     ping:
[[email protected] ~]# ansible-playbook ping.yaml --syntax-check  //檢查文法

playbook: ping.yaml
[[email protected] ~]# ansible-playbook ping.yaml   //執行

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

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.30]
ok: [192.168.188.20]

TASK [test connection] ************************************************************
ok: [192.168.188.20]
ok: [192.168.188.30]

PLAY RECAP ************************************************************************
192.168.188.20             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.188.30             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

           

指定遠端主機sudo切換使用者

[[email protected] ~]# vim sudo.yaml
- hosts: webservers
  remote_user: root
  become: yes  //切換使用者執行
  become_user: lisi  //指定sudo使用者為lisi
  tasks:
   - name: copy text
     copy: src=/etc/fstab dest=/home/lisi/fstab.bak
[[email protected] ~]# ansible-playbook sudo.yaml --syntax-check  //檢視文法

playbook: sudo.yaml
[[email protected] ~]# ansible-playbook sudo.yaml   //執行

PLAY [webservers] *****************************************************************

TASK [Gathering Facts] ************************************************************
[WARNING]: Module remote_tmp /home/lisi/.ansible/tmp did not exist and was created
with a mode of 0700, this may cause issues when running as another user. To avoid
this, create the remote_tmp dir with the correct permissions manually
ok: [192.168.188.20]

TASK [copy text] ******************************************************************
changed: [192.168.188.20]

PLAY RECAP ************************************************************************
192.168.188.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

去node1驗證
[[email protected] ~]# id lisi
uid=1001(lisi) gid=1001(lisi) 組=1001(lisi)
[[email protected] ~]# cd /home/lisi/
[[email protected] lisi]# ls
[[email protected] lisi]# ls
fstab.bak
           

小實驗 練練手

實驗要求:

安裝Apcha

開啟Apcha

關閉防火牆

給Apcha首頁換成this is Apche

[[email protected] ~]# vim Apcha.yaml
- hosts: mysql
  remote_user: root
  tasks:
   - name: yum httpd
     yum: name=httpd
   - name: start httpd
     service: name=httpd state=started
   - name: stop firewalld
     service: name=firewalld state=stopped
   - name: index.html
     copy: content="this is Apcha" dest=/var/www/html/index.html

[[email protected] ~]# ansible-playbook Apcha.yaml --syntax-check

playbook: Apcha.yaml

[[email protected] ~]# ansible-playbook Apcha.yaml 

PLAY [mysql] **********************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.30]

TASK [yum httpd] ******************************************************************
changed: [192.168.188.30]

TASK [start httpd] ****************************************************************
changed: [192.168.188.30]

TASK [stop firewalld] *************************************************************
ok: [192.168.188.30]

TASK [index.html] *****************************************************************
changed: [192.168.188.30]

PLAY RECAP ************************************************************************
192.168.188.30             : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


node2 驗證

[[email protected] ~]# rpm -q httpd
httpd-2.4.6-67.el7.centos.x86_64
[[email protected] ~]# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: active (running) since 四 2021-01-14 10:07:20 CST; 25s ago
     Docs: man:httpd(8)
           man:apachectl(8)
 Main PID: 42301 (httpd)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"

[[email protected] ~]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:firewalld(1)

           
自動化運維工具——YAML詳解YAML介紹YAML文法YAML支援的資料結構:playbook的組成三要素playbook 文法hosts和users介紹指定遠端主機sudo切換使用者小實驗 練練手Handlers介紹條件測試疊代

如果一個hosts執行task失敗,整個task就會復原,請修正playbook錯誤,然後重新執行

[[email protected] ~]# vim Apcha.yaml
- hosts: webservers
  remote_user: root
  tasks:
   - name: yum httpd
     yum: name=httpd
   - name: start httpd
     service: name=httpd state=started
   - name: stop firewalld
     service: name=firewall state=stopped   //firewalld 少d
   - name: index.html
     copy: content="this is Apcha" dest=/var/www/html/index.html

[[email protected] ~]# ansible-playbook Apcha.yaml --syntax-check  //文法正确

playbook: Apcha.yaml

[[email protected] ~]# ansible-playbook Apcha.yaml   //執行  到stop firewalld顯示錯誤  後面不執行

PLAY [webservers] *****************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.20]

TASK [yum httpd] ******************************************************************
changed: [192.168.188.20]

TASK [start httpd] ****************************************************************
changed: [192.168.188.20]

TASK [stop firewalld] *************************************************************
fatal: [192.168.188.20]: FAILED! => {"changed": false, "msg": "Could not find the requested service firewall: host"}

PLAY RECAP ************************************************************************
192.168.188.20             : ok=3    changed=2    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   


node1 驗證
[[email protected] lisi]# id httpd
id: httpd: no such user
[[email protected] lisi]# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: active (running) since 四 2021-01-14 10:48:41 CST; 1min 18s ago
     Docs: man:httpd(8)
           man:apachectl(8)
 Main PID: 42757 (httpd)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"

[[email protected] lisi]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: active (running) since 四 2021-01-14 10:50:29 CST; 16s ago
     Docs: man:firewalld(1)
 Main PID: 42868 (firewalld)
   CGroup: /system.slice/firewalld.service
           └─42868 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid

           

在stop firewalld 下面添加ignore_errors: True(忽略錯誤,強制傳回成功)

[[email protected] ~]# vim Apcha.yaml
- hosts: webservers
  remote_user: root
  tasks:
   - name: yum httpd
     yum: name=httpd
   - name: start httpd
     service: name=httpd state=started
   - name: stop firewalld
     service: name=firewall state=stopped
     ignore_errors: True
   - name: index.html
     copy: content="this is Apcha" dest=/var/www/html/index.html
[[email protected] ~]# ansible-playbook Apcha.yaml --syntax-check

playbook: Apcha.yaml

[[email protected] ~]# ansible-playbook Apcha.yaml 

PLAY [webservers] *****************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.20]

TASK [yum httpd] ******************************************************************
ok: [192.168.188.20]

TASK [start httpd] ****************************************************************
ok: [192.168.188.20]

TASK [stop firewalld] *************************************************************
fatal: [192.168.188.20]: FAILED! => {"changed": false, "msg": "Could not find the requested service firewall: host"}
...ignoring

TASK [index.html] *****************************************************************   
changed: [192.168.188.20]

PLAY RECAP ************************************************************************
192.168.188.20             : ok=5    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1    //有一條被忽略

           

Handlers介紹

Handlers也是一些task的清單,和一般的task并沒有什麼差別。

是由通知者進行的notify,如果沒有被notify,則Handlers不會執行,假如被notify了,則Handlers被執行

不管有多少個通知者進行了notify,等到play中的所有task執行完成之後,handlers也隻會被執行一次

1、在playbook直接使用變量

[[email protected] ~]# vim Apcha.yaml 
- hosts: webservers
  remote_user: root
  vars:
   - abc: httpd   //把httpd變成abc
  tasks:
   - name: yum httpd
     yum: name={{abc}}
   - name: start httpd
     service: name={{abc}} state=started
   - name: stop firewalld
     service: name=firewalld state=stopped
   - name: index.html
     copy: content="this is Apcha" dest=/var/www/html/index.html

[[email protected] ~]# ansible-playbook Apcha.yaml --syntax-check 

playbook: Apcha.yaml
[[email protected] ~]# ansible-playbook Apcha.yaml 

PLAY [webservers] *****************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.20]

TASK [yum httpd] ******************************************************************
changed: [192.168.188.20]

TASK [start httpd] ****************************************************************
changed: [192.168.188.20]

TASK [stop firewalld] *************************************************************
ok: [192.168.188.20]

TASK [index.html] *****************************************************************
ok: [192.168.188.20]

PLAY RECAP ************************************************************************
192.168.188.20             : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


           

2、通過ansible指令傳遞

[[email protected] ~]# vim Apcha.yaml 
- hosts: webservers
  remote_user: root
  vars:
   - abc:    //空的  在外面用指令設定
  tasks:
   - name: yum httpd
     yum: name={{abc}}
   - name: start httpd
     service: name={{abc}} state=started
   - name: stop firewalld
     service: name=firewalld state=stopped
   - name: index.html
     copy: content="this is Apcha" dest=/var/www/html/index.html

[[email protected] ~]# ansible-playbook Apcha.yaml -e 'abc=httpd'  

PLAY [webservers] *****************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.20]

TASK [yum httpd] ******************************************************************
ok: [192.168.188.20]

TASK [start httpd] ****************************************************************
ok: [192.168.188.20]

TASK [stop firewalld] *************************************************************
ok: [192.168.188.20]

TASK [index.html] *****************************************************************
ok: [192.168.188.20]

PLAY RECAP ************************************************************************
192.168.188.20             : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

           

3、直接在yaml中定義變量

[[email protected] ~]# vim test.yaml
- hosts: mysql
  remote_user: root
  tasks:
   - name: copy file
     copy: content="{{ansible_all_ipv4_addresses}}" dest=/opt/addr.txt

[[email protected] ~]# ansible-playbook test.yaml --syntax-check

playbook: test.yaml
[[email protected] ~]# ansible-playbook test.yaml 

PLAY [mysql] **********************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.30]

TASK [copy file] ******************************************************************
changed: [192.168.188.30]

PLAY RECAP ************************************************************************
192.168.188.30             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

到node2 驗證
[[email protected] ~]# cd /opt/
[[email protected] opt]# ls
addr.txt  rh
[[email protected] opt]# cat addr.txt 
["192.168.122.1", "192.168.188.30"][[email protected] opt]# 
           

4、直接引用主機變量

[[email protected] ~]# vim /etc/ansible/hosts 
[webservers]
192.168.188.20
[mysql]
192.168.188.30  num="123456"
           
自動化運維工具——YAML詳解YAML介紹YAML文法YAML支援的資料結構:playbook的組成三要素playbook 文法hosts和users介紹指定遠端主機sudo切換使用者小實驗 練練手Handlers介紹條件測試疊代
[[email protected] ~]# vim test.yaml
- hosts: mysql
  remote_user: root
  tasks:
   - name: copy file
     copy: content="{{ansible_all_ipv4_addresses}},{{num}}" dest=/opt/num.txt

[[email protected] ~]# ansible-playbook test.yaml --syntax-check

playbook: test.yaml
[[email protected] ~]# ansible-playbook test.yaml

PLAY [mysql] **********************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.30]

TASK [copy file] ******************************************************************
changed: [192.168.188.30]

PLAY RECAP ************************************************************************
192.168.188.30             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


去node2驗證
[[email protected] opt]# ls
addr.txt  num.txt  rh
[[email protected] opt]# cat num.txt 
([u'192.168.122.1', u'192.168.188.30'], 123456)[[email protected] opt]# 
           

條件測試

[[email protected] ~]# vim when.yaml

- hosts: mysql
  remote_user: root
  tasks:
   - name: "shutdown CentOS"
     command: /sbin/shutdown -h now
     when: ansible_distribution == "CentOS"   //判斷系統CentOS



[[email protected] ~]# ansible-playbook when.yaml 

PLAY [mysql] **********************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.30]

TASK [shutdown CentOS] ************************************************************
fatal: [192.168.188.30]: FAILED! => {"msg": "Failed to connect to the host via ssh: ssh: connect to host 192.168.188.30 port 22: Connection refused"}

PLAY RECAP ************************************************************************
192.168.188.30             : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

           

多條件判斷

[[email protected] ~]# vim when.yaml
- hosts: mysql
  remote_user: root
  tasks:
   - name: "shut down CentOS 7 systems"
     command: /sbin/shutdown -r now
     when:
      - ansible_distribution == "CentOS"   //判斷CentOS系統
      - ansible_distribution_major_version == "7"   //7版本


[[email protected] ~]# ansible-playbook when.yaml 

PLAY [mysql] **********************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.30]

TASK [shut down CentOS 7 systems] *************************************************
fatal: [192.168.188.30]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Shared connection to 192.168.188.30 closed.", "unreachable": true}

PLAY RECAP ************************************************************************
192.168.188.30             : ok=1    changed=0    unreachable=1    failed=0    skipped=0    rescued=0    ignored=0   

           

組條件判斷

[[email protected] ~]# vim when.yaml 
- hosts: mysql
  remote_user: root
  tasks:
   - name: "shut down CentOS 7 systems"
     command: /sbin/shutdown -r now
     when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6") or (ansible_distribution == "Debian " and ansible_distribution_major_version == "7")  //判斷你的系統是CentOS 版本是6 或者系統是Debian 7

[[email protected] ~]# ansible-playbook when.yaml --syntax-check

playbook: when.yaml
[[email protected]erver1 ~]# ansible-playbook when.yaml 

           

疊代

當有需要重複性執行的任務時,可以使用疊代機制

[[email protected] ~]# vim yum.yaml
- hosts: all
  remote_user: root
  tasks:
   - name: install httpd tomcat
     yum: name={{item}}
     with_items:
      - httpd
      - tomcat
[[email protected] ~]# ansible-playbook yum.yaml --syntax-check

playbook: yum.yaml
[[email protected] ~]# ansible-playbook yum.yaml 
LAY [all] ************************************************************************

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.30]
ok: [192.168.188.20]

TASK [install httpd tomcat] *******************************************************
[DEPRECATION WARNING]: Invoking "yum" only once while using a loop via 
squash_actions is deprecated. Instead of using a loop to supply multiple items and
 specifying `name: "{{item}}"`, please use `name: ['httpd', 'tomcat']` and remove 
the loop. This feature will be removed in version 2.11. Deprecation warnings can 
be disabled by setting deprecation_warnings=False in ansible.cfg.
[DEPRECATION WARNING]: Invoking "yum" only once while using a loop via 
squash_actions is deprecated. Instead of using a loop to supply multiple items and
 specifying `name: "{{item}}"`, please use `name: ['httpd', 'tomcat']` and remove 
the loop. This feature will be removed in version 2.11. Deprecation warnings can 
be disabled by setting deprecation_warnings=False in ansible.cfg.
changed: [192.168.188.20] => (item=[u'httpd', u'tomcat'])
changed: [192.168.188.30] => (item=[u'httpd', u'tomcat'])

PLAY RECAP ************************************************************************
192.168.188.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.188.30             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[[email protected] ~]# rpm -q httpd
httpd-2.4.6-67.el7.centos.x86_64
[[email protected] ~]# rpm -q tomcat
tomcat-7.0.76-2.el7.noarch

[[email protected] ~]# rpm -q httpd
httpd-2.4.6-67.el7.centos.x86_64
[[email protected] ~]# rpm -q tomcat
tomcat-7.0.76-2.el7.noarch


也可以自己定義

[[email protected] ~]# vim user.yaml

- hosts: all
  remote_user: root
  tasks:
  - name: "users"
    user: name={{ item.name }} state=present groups={{ item.groups }}
    with_items:
      - { name: 'song', groups: 'root' }
      - { name: 'shufeng', groups: 'wheel' }
[[email protected] ~]# ansible-playbook user.yaml --syntax-check

playbook: user.yaml
[[email protected] ~]# ansible-playbook user.yaml

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

TASK [Gathering Facts] ************************************************************
ok: [192.168.188.20]
ok: [192.168.188.30]

TASK [users] **********************************************************************
changed: [192.168.188.30] => (item={u'name': u'song', u'groups': u'root'})
changed: [192.168.188.20] => (item={u'name': u'song', u'groups': u'root'})
changed: [192.168.188.30] => (item={u'name': u'shufeng', u'groups': u'wheel'})
changed: [192.168.188.20] => (item={u'name': u'shufeng', u'groups': u'wheel'})

PLAY RECAP ************************************************************************
192.168.188.20             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.188.30             : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   




[[email protected] ~]# id song
uid=1002(song) gid=1002(song) 組=1002(song),0(root)
[[email protected] ~]# id shufeng
uid=1003(shufeng) gid=1003(shufeng) 組=1003(shufeng),10(wheel)



[[email protected] ~]# id song
uid=1003(song) gid=1003(song) 組=1003(song),0(root)
[[email protected] ~]# id shufeng
uid=1004(shufeng) gid=1004(shufeng) 組=1004(shufeng),10(wheel)


           

繼續閱讀