Ansible之playbook劇本
Ansible之playbook劇本
1. playbook的組成
playbooks 本身由以下各部分組成
(1)Tasks:任務,即通過 task 呼叫 ansible 的模板將多個操作組織在一個 playbook 中執行
(2)Variables:變數
(3)Templates:模板
(4)Handlers:處理器,當changed狀態條件滿足時,(notify)觸發執行的操作
(5)Roles:角色
2. 劇本示例test1
2.1 劇本製作
[root@ansible ~] vim test1.yml
---
yaml檔案以---開頭,以表明這是一個yaml檔案,可省略
- name: first test
定義一個play的名稱,可省略
gather_facts: false
設定不進行facts資訊收集,這可以加快執行速度,可省略
hosts: webservers
指定要執行任務的被管理主機組,如多個主機組用冒號分隔
remote_user: root
指定被管理主機上執行任務的使用者
tasks:
定義任務列表,任務列表中的各任務按次序逐個在hosts中指定的主機上執行
- name: test connection
自定義任務名稱
ping:
使用 module: [options] 格式來定義一個任務
- name: disable selinux
command: '/sbin/setenforce 0'
command模組和shell模組無需使用key=value格式
ignore_errors: True
如執行命令的返回值不為0,就會報錯,tasks停止,可使用ignore_errors忽略失敗的任務
- name: disable firewalld
service: name=firewalld state=stopped
使用 module: options 格式來定義任務,option使用key=value格式
- name: install httpd
yum: name=httpd state=latest
- name: install configuration file for httpd
copy: src=/etc/ansible/httpd.conf dest=/etc/httpd/conf/httpd.conf
這裡需要一個事先準備好的/opt/httpd.conf檔案
notify: "restart httpd"
如以上操作後為changed的狀態時,會通過notify指定的名稱觸發對應名稱的handlers操作
- name: start httpd service
service: enabled=true name=httpd state=started
handlers:
handlers中定義的就是任務,此處handlers中的任務使用的是service模組
- name: restart httpd
notify和handlers中任務的名稱必須一致
service: name=httpd state=restarted
Ansible在執行完某個任務之後並不會立即去執行對應的handler,而是在當前play中所有普通任務都執行完後再去執行handler,這樣的好處是可以多次觸發notify,但最後只執行一次對應的handler,從而避免多次重啟。
2.2 準備http.conf
[root@ansible ansible] vim /etc/ansible/httpd.conf
42行,指定埠
Listen 8080
95行,指定域名
ServerName node1:8080
2.3 執行劇本
ansible-playbook test1.yml
2.4 檢視web伺服器
ansible web -m shell -a 'netstat -natp | grep httpd'
2.5 補充引數
-k(–ask-pass):用來互動輸入ssh密碼
-K(-ask-become-pass):用來互動輸入sudo密碼
-u:指定使用者
ansible-playbook test1.yml --syntax-check
檢查yml檔案的語法是否正確
ansible-playbook test1.yml --list-task
檢查tasks任務
ansible-playbook test1.yml --list-hosts
檢查生效的主機
ansible-playbook test1.yml --start-at-task='install httpd'
指定從某個task開始執行
3. 劇本示例test2--定義、引用變數
3.1 劇本製作
---
- name: second test
hosts: db
remote_user: root
vars:
定義變數
- groupname: mysql
格式為 key: value
- username: nginx
tasks:
- name: create group
group: name={{groupname}} system=yes gid=306
使用 {{key}} 引用變數的值
- name: create user
user: name={{username}} uid=306 group={{groupname}}
- name: copy file
copy: content="{{ansible_default_ipv4}}" dest=/opt/vars.txt
在setup模組中可以獲取facts變數資訊
3.3 檢視db伺服器
ansible db -a 'grep "mysql" /etc/group'
ansible db -a 'grep "nginx" /etc/passwd'
ansible db -a 'cat /opt/vars.txt'
3.4 修改劇本中的變數設定
刪除dbservers中的mysql組和nginx使用者以及/opt/var.txt
ansible db -a 'userdel -r nginx'
ansible db -a 'groupdel mysql'
ansible db -a 'rm -rf /opt/vars.txt'
確認使用者、組以及檔案已刪除
ansible db -a 'grep "mysql" /etc/group'
ansible db -a 'grep "nginx" /etc/passwd'
ansible db -a 'cat /opt/vars.txt'
刪除/註釋"- username: nginx"變數
3.5 在命令列定義變數執行劇本
ansible-playbook test2.yml -e "username=nginx"
3.6 檢視dbservers伺服器
ansible db -a 'grep "mysql" /etc/group'
ansible db -a 'grep "nginx" /etc/passwd'
ansible db -a 'cat /opt/vars.txt'
4. 劇本示例test3--指定遠端主機sudo切換使用者
vim test3.yml
---
- hosts: db
remote_user: wang
become: yes
2.6版本以後的引數,之前是sudo,意思為切換使用者執行
become_user: root
……
指定sudo使用者為root
測試機需要有wang,修改/etc/sudoers檔案
執行playbook時:ansible-playbook test3.yml -K <密碼>
ansible-playbook test3.yml -K
a
驗證
5. 劇本示例test4--when條件判斷
在Ansible中,提供的唯一一個通用的條件判斷是when指令,當when指令的值為true時,則該任務執行,否則不執行該任務。
when一個比較常見的應用場景是實現跳過某個主機不執行任務或者只有滿足條件的主機執行任務
vim test4.yaml
---
- hosts: all
remote_user: root
tasks:
- name: shutdown host
command: /sbin/shutdown -r now
when: ansible_default_ipv4.address == "192.168.10.3"
when指令中的變數名不需要手動加上{{}}
或者使用
when: inventory_hostname == "<主機名>"
ansible-playbook test4.yml
執行後,僅有指定主機重啟,執行ping模組檢視
ansible all -m ping
重啟完畢後,可以ping通
6. 劇本示例test5--迭代
Ansible提供了很多種迴圈結構,一般都命名為with_items,作用等同於loop迴圈。
vim test5.yaml
---
- name: test5
hosts: all
gather_facts: false
tasks:
- name: create directories
file:
path: "{{item}}"
state: directory
with_items:
等同於 loop:
- /test/test1
- /test/test2
- name: add groups
group: name={{item.name}} state=present
with_items:
- name: test1
- name: test2
- name: add users
user: name={{item.name}} state=present groups={{item.groups}}
with_items:
- name: test1
groups: test
- name: test2
groups: root
或使用以下格式
with_items:
- {name:'test1', groups:'test'}
- {name:'test2', groups:'root'}
ansible-playbook test5.yml
檢視驗證
ansible node3 -a "ls -l /test/"
ansible node3 -m shell -a "id test1"
ansible node3 -m shell -a "id test2"
7. Template模組
Jinja是基於Python的模組引擎。Template類是Jinja的一個重要元件,可以看做是一個編譯過的模板檔案,用來產生目標文字,傳遞Python的變數給模板去替換模板中的標記。
7.1 準備template模板檔案
先準備一個以.j2為字尾的template模板檔案,設定引用的變數
模板檔案使用test1曾用的httpd.conf配置檔案
cd /etc/ansible
cp httpd.conf httpd.conf.j2
vim httpd.conf.j2
42行,修改
Listen {{http_port}}
95行,修改
ServerName {{server_name}}
119行,修改
DocumentRoot "{{root_dir}}"
124行,修改
<Directory "{{root_dir}}">
7.2 修改主機清單檔案
修改主機清單檔案,使用主機變數定義一個變數名相同,而值不同的變數
7.3 編寫playbook
vim test6.yml
---
- hosts: all
remote_user: root
vars:
- package: httpd
- service: httpd
tasks:
- name: install httpd package
yum: name={{package}} state=latest
- name: install configure file
template: src=/etc/ansible/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
使用template模板
notify:
- restart httpd
- name: create root dir
file: path=/etc/httpd/htdocs state=directory
- name: start httpd server
service: name={{service}} enabled=true state=started
handlers:
- name: restart httpd
service: name={{service}} state=restarted
7.4 執行playbook
ansible-playbook test6.yml
7.5 製作測試網頁
[root@ansible ~]# ansible node1 -m shell -a "echo 'this is test1 template test' > /etc/httpd/htdocs/index.html"
node1 | CHANGED | rc=0 >>
[root@ansible ~]# ansible node2 -m shell -a "echo 'this is test2 template test' > /etc/httpd/htdocs/index.html"
node2 | CHANGED | rc=0 >>
[root@ansible ~]# ansible node3 -m shell -a "echo 'this is test3 template test' > /etc/httpd/htdocs/index.html"
node3 | CHANGED | rc=0 >>
7.6 訪問測試
curl,訪問前要開放httpd服務的埠
8. tags模組
可以在一個playbook中為某個或某些任務定義"標籤",在執行此playbook時通過ansible-playbook命令使用--tags選項能實現僅執行指定的tasks。
playbook還提供了一個特殊的tags為always。作用就是當使用always當tags的task時,無論執行哪一個tags時,定義有always的tags都會執行。
8.1 編寫指令碼
vim test7.yml
---
- hosts: web
remote_user: root
tasks:
- name: mkdir directory
file: path=/opt/test/ state=directory
tags:
- always
- name: touch file
file: path=/opt/test/testhost state=touch
tags:
- test1
- all
- name: copy hosts file
copy: src=/etc/hosts dest=/opt/test/hosts
tags:
- test2
- all
8.2 執行tags="test1"
ansible-playbook test7.yml --tags="test1"
ansible web -a "ls -l /opt/test/"
8.3 執行tags="test2"
刪除資料夾
ansible web -m file -a "path=/opt/test/ state=absent"
ansible web -a "ls -l /opt/test/"
執行tags="test2"
ansible web -a "ls -l /opt/test/"
8.4 執行tags="all"
刪除資料夾
ansible web -m file -a "path=/opt/test/ state=absent"
ansible web -a "ls -l /opt/test/"
執行tags="all"
ansible-playbook test7.yml --tags="all"
ansible web -a "ls -l /opt/test/"