Ansible Playbook 講解與實戰操作

一、概述

  • playbookad-hoc相比,是一種完全不同的運用ansible的方式,類似與saltstack的state狀態文件。ad-hoc無法持久使用,playbook可以持久使用。
  • playbook是由一個或多個play組成的列表,play的主要功能在于將事先歸并為一組的主機裝扮成事先通過ansible中的task定義好的角色。
  • 從根本上來講,所謂的task無非是調用ansible的一個module。將多個play組織在一個playbook中,即可以讓它們聯合起來按事先編排的機制完成某一任務。

參考文檔:https://ansible-tran.readthedocs.io/en/latest/docs/playbooks.html

Ansible 的基礎介紹和環境部署可以參考我這篇文章:??Ansible 介紹與實戰操作演示??

Ansible Playbook 講解與實戰操作

二、playbook 核心元素

  • Hosts執行的遠程主機列表
  • Tasks任務集
  • Varniables內置變量或自定義變量在playbook中調用
  • Templates模板,即使用模板語法的文件,比如配置文件等
  • Handlers和notity結合使用,由特定條件觸發的操作,滿足條件方才執行,否則不執行
  • Tags標簽,指定某條任務執行,用于選擇運行playbook中的部分代碼。

三、playbook 語法(yaml)

  • playbook使用yaml語法格式,后綴可以是yaml,也可以是yml
  • YAML( /?j?m?l/ )參考了其他多種語言,包括:XML、C語言、Python、Perl以及電子郵件格式RFC2822,Clark Evans在2001年5月在首次發表了這種語言,另外Ingy d?t Net與OrenBen-Kiki也是這語言的共同設計者。
  • YAML格式是類似JSON的文件格式。YAML用于文件的配置編寫,JSON多用于開發設計。

1)YAML 介紹

1、YAML 格式如下

  • 文件的第一行應該以“—”(三個連字符)開始,表明YAML文件的開始。
  • 在同一行中,#之后的內容表示注釋,類似于shell,python和ruby。
  • YAML中的列表元素以“-”開頭并且跟著一個空格。后面為元素內容。
  • 同一個列表之中的元素應該保持相同的縮進,否則會被當做錯誤處理。
  • play中hosts、variables、roles、tasks等對象的表示方法都是以鍵值中間以“:”分隔表示,并且“:”之后要加一個空格。
2、playbooks yaml配置文件解釋
Hosts:運行指定任務的目標主機  remoute_user:在遠程主機上執行任務的用戶;  sudo_user:  tasks:任務列表     tasks的具體格式:     tasks:  - name: TASK_NAME  module: arguments  notify: HANDLER_NAME  handlers:  - name: HANDLER_NAME  module: arguments     ##模塊,模塊參數:  格式如下:  (1)action: module arguments   (2) module: arguments  注意:shell和command模塊后直接加命令,而不是key=value類的參數列表        handlers:任務,在特定條件下觸發;接受到其他任務的通知時被觸發;

3、示例

---  - hosts: web  remote_user: root  tasks:  - name: install nginx##安裝模塊,需要在被控主機里加上nginx的源  yum: name=nginx state=present  - name: copy nginx.conf##復制nginx的配置文件過去,需要在本機的/tmp目錄下編輯nginx.conf  copy: src=/tmp/nginx.conf dest=/etc/nginx/nginx.conf backup=yes  notify: reload#當nginx.conf發生改變時,通知給相應的handlers  tags: reloadnginx#打標簽  - name: start nginx service#服務啟動模塊  service: name=nginx state=started  tags: startnginx#打標簽    handlers:  - name: reload  service: name=nginx state=restarted

2)variables 變量

variables變量有四種定義方法。如下:

1、facts:可以直接調用

ansible中有setup模塊,這個模塊就是通過facts組件來實現的,主要是節點本身的一個系統信息,bios信息,網絡,硬盤等等信息。這里的variables也可以直接調用facts組件的facters我們可以使用setup模塊來獲取,然后直接放入我們的劇本之中調用即可。

ansible web -m setup

Ansible Playbook 講解與實戰操作

常用的幾個參數:

ansible_all_ipv4_addresses # ipv4的所有地址  ansible_all_ipv6_addresses # ipv6的所有地址  ansible_date_time # 獲取到控制節點時間  ansible_default_ipv4 # 默認的ipv4地址  ansible_distribution # 系統  ansible_distribution_major_version # 系統的大版本  ansible_distribution_version # 系統的版本號  ansible_domain #系統所在的域  ansible_env #系統的環境變量  ansible_hostname #系統的主機名  ansible_fqdn #系統的全名  ansible_machine #系統的架構  ansible_memory_mb #系統的內存信息  ansible_os_family # 系統的家族  ansible_pkg_mgr # 系統的包管理工具  ansible_processor_cores #系統的cpu的核數(每顆)  ansible_processor_count #系統cpu的顆數  ansible_processor_vcpus #系統cpu的總個數=cpu的顆數*CPU的核數  ansible_python # 系統上的python

搜索

ansible web -m setup -a 'filter=*processor*'

Ansible Playbook 講解與實戰操作

2、用戶自定義變量

自定義變量有兩種方式

  • 通過命令行傳入
ansible-playbook命令行中的 -e VARS,--extra-vars VARS,這樣就可以直接把自定義的變量傳入

使用playbook定義變量,實例如下:

---  - hosts: web  remote_user: root  tasks:    - name: install {{ rpmname }}  yum: name={{ rpmname }} state=present  - name: copy {{ rpmname }}.conf  copy: src=/tmp/{{ rpmname }}.conf dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yes  notify: reload  tags: reload{{ rpmname }}  - name: start {{ rpmname }} service  service: name={{ rpmname }} state=started  tags: start{{ rpmname }}     handlers:  - name: reload  service: name={{ rpmname }} state=restarted

使用:

ansible-playbook nginx.yml -e rpmname=keepalived  ansible-playbook nginx.yml --extra-vars rpmname=keepalived
  • 在playbook中定義變量
##在playbook中定義變量如下:  vars:  - var1: value1  - var2: value2

使用:

---  - hosts: web  remote_user: root  vars:  - rpmname: keepalived  tasks:  - name: install {{ rpmname }}  yum: name={{ rpmname }} state=present  - name: copy {{ rpmname }}.conf  copy: src=/tmp/{{ rpmname }}.conf dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yes  notify: reload  tags: reload{{ rpmname }}  - name: start {{ rpmname }} service  service: name={{ rpmname }} state=started  tags: start{{ rpmname }}     handlers:  - name: reload  service: name={{ rpmname }} state=restarted

3、通過roles傳遞變量

下面介紹roles會使用roles傳遞變量,小伙伴可以翻到下面看詳解講解。

4、 Host Inventory

可以在主機清單中定義,方法如下:

#向不同的主機傳遞不同的變量  IP/HOSTNAME varaiable=value var2=value2     #向組中的主機傳遞相同的變量  [groupname:vars]  variable=value

3)流程控制

1、用when 來表示的條件判斷

- hosts: web  remote_user: root#代表用root用戶執行,默認是root,可以省略  tasks:  - name: createfile  copy: content="test3" dest=/opt/p1.yml  when: a=='3'  - name: createfile  copy: content="test4" dest=/opt/p1.yml  when: a=='4'

如果a”3″,就將“test3”,寫入到web組下被管控機的/opt/p1.yml中,
如果a”4″,就將“test4”,寫入到web組下被管控機的/opt/p1.yml中。

執行

# 語法校驗  ansible-playbook--syntax-check p1.yml    #執行  ansible-playbook -e 'a="3"' p1.yml

2、標簽(只執行配置文件中的一個任務)

- hosts: web  tasks:  - name: installnginx  yum: name=nginx  - name: copyfile  copy: src=/etc/nginx/nginx.conf dest=/etc/nginx/nginx.conf  tags: copyfile  - name: start  service: name=nginx static=restarted

執行

# 語法校驗  ansible-playbook--syntax-check p2.yml    #執行  ansible-playbook -t copyfile p2.yml 

3、循環 with_items

創建三個用戶

- hosts: web  tasks:  - name: createruser  user: name={{ item }}  with_items:  - shy1  - shy2  - shy3  - name: creategroup  group: name={{ item }}  with_items:  - group1  - group2  - group3 

執行

#語法校驗  ansible-playbook--syntax-check p3.yml    #執行  ansible-playbook p3.yml 

4、循環嵌套(字典)

用戶shy1的屬組是group1,用戶shy2的屬組是group2,用戶shy3的屬組是group3

- hosts: web  tasks:  - name: creategroup  group: name={{item}}  with_items:  - group3  - group4  - group5  - name: createuser  user: name={{item.user}} group={{item.group}}  with_items:  - {'user': shy3,'group': group3}  - {'user': shy4,'group': group4}  - {'user': shy5,'group': group5}

執行

#語法校驗  ansible-playbook--syntax-check p4.yml    #執行  ansible-playbook p4.yml 

4)模板 templates

  • 模板是一個文本文件,嵌套有腳本(使用模板編程語言編寫)
  • Jinja2是python的一種模板語言,以Django的模板語言為原本

該模板支持:

字符串:使用單引號或雙引號;  數字:整數,浮點數;  列表:[item1, item2, ...]  元組:(item1, item2, ...)  字典:{key1:value1, key2:value2, ...}  布爾型:true/false  算術運算:  +, -, *, /, //, %, **  比較操作:  ==, !=, >, >=, 
  • 通常模板都是通過引用變量來運用的

【示例】

1、定義模板

usernginx; #設置nginx服務的系統使用用戶  worker_processes{{ ansible_processor_vcpus }}; #工作進程數    error_log/var/log/nginx/error.log warn; #nginx的錯誤日志  pid/var/run/nginx.pid; #nginx啟動時候的pid    events {  worker_connections1024; #每個進程允許的最大連接數  }    http { #http請求配置,一個http可以包含多個server    #定義 Content-Type  include /etc/nginx/mime.types;  default_typeapplication/octet-stream;    #日志格式 此處main與access_log中的main對應  #$remote_addr:客戶端地址  #$remote_user:http客戶端請求nginx認證的用戶名,默認不開啟認證模塊,不會記錄  #$timelocal:nginx的時間  #$request:請求method + 路由 + http協議版本  #status:http reponse 狀態碼  #body_bytes_sent:response body的大小  #$http_referer:referer頭信息參數,表示上級頁面  #$http_user_agent:user-agent頭信息參數,客戶端信息  #$http_x_forwarded_for:x-forwarded-for頭信息參數  log_formatmain'$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" '  '$status $body_bytes_sent "$http_referer" '  '"$http_user_agent" "$http_x_forwarded_for"';    #訪問日志,后面的main表示使用log_format中的main格式記錄到access.log中  access_log/var/log/nginx/access.logmain;    #nginx的一大優勢,高效率文件傳輸  sendfileon;  #tcp_nopush on;    #客戶端與服務端的超時時間,單位秒  keepalive_timeout65;    #gzipon;  server { #http服務,一個server可以配置多個location  listen {{ nginxport }}; #服務監聽端口  server_namelocalhost; #主機名、域名    #charset koi8-r;  #access_log/var/log/nginx/host.access.logmain;    location / {  root /usr/share/nginx/html; #頁面存放目錄  indexindex.html index.htm; #默認頁面  }    #error_page404/404.html;    # 將500 502 503 504的錯誤頁面重定向到 /50x.html  error_page 500 502 503 504/50x.html;  location = /50x.html { #匹配error_page指定的頁面路徑  root /usr/share/nginx/html; #頁面存放的目錄  }    # proxy the PHP scripts to Apache listening on 127.0.0.1:80  #  #location ~ .php$ {  #proxy_pass http://127.0.0.1;  #}    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000  #  #location ~ .php$ {  #root html;  #fastcgi_pass 127.0.0.1:9000;  #fastcgi_indexindex.php;  #fastcgi_paramSCRIPT_FILENAME/scripts$fastcgi_script_name;  #includefastcgi_params;  #}    # deny access to .htaccess files, if Apache's document root  # concurs with nginx's one  #  #location ~ /.ht {  #denyall;  #}  }  include /etc/nginx/conf.d/*.conf;  }

2、定義yaml編排

---  - hosts: web  remote_user: root  vars:  - rpmname: nginx  - nginxport: 8088  tasks:  - name: install {{ rpmname }}  yum: name={{ rpmname }} state=present  - name: copy {{ rpmname }}.conf  copy: src=/tmp/{{ rpmname }}.conf dest=/etc/{{ rpmname }}/{{ rpmname }}.conf backup=yes  notify: reload  tags: reload{{ rpmname }}  - name: start {{ rpmname }} service  service: name={{ rpmname }} state=started  tags: start{{ rpmname }}     handlers:  - name: reload  service: name={{ rpmname }} state=restarted

使用

##使用reloadnginx標簽,重新加載劇本

copy與template的區別

  • copy模塊不替代參數,template模塊替代參數
  • template的參數幾乎與copy的參數完全相同

5)handlers(觸發事件)

notify:觸發  handlers:觸發的動作

使用上場景:修改配置文件時

【示例】 正常情況時handlers是不會執行的

- hosts: web  tasks:  - name: installredis  yum: name=redis  - name: copyfile  template: src=redis.conf dest=/etc/redis.conf  tags: copyfile  notify: restart  - name: start  service: name=redis state=started  handlers:  - name: restart  service: name=redis

執行

ansible-playbook -t copyfile p6.yml

6)roles

1、roles介紹與優勢

一般情況下將roles寫在/etc/ansible/roles中,也可以寫在其他任意位置(寫在其他位置要自己手動建立一個roles文件夾)

  • 對于以上所有方式有個缺點就是無法實現同時部署web、database、keepalived等不同服務或者不同服務器組合不同的應用就需要寫多個yaml文件,很難實現靈活的調用
  • roles用于層次性,結構化地組織playbook。roles能夠根據層次結果自動裝載變量文件、tasks以及handlers等。
  • 要使用roles只需要在playbook中使用include指令即可。
  • 簡單來講,roles就是通過分別將變量(vars)、文件(files)、任務(tasks)、模塊(modules)以及處理器(handlers)放置于單獨的目錄中,并且可以便捷的include它們地一種機制。
  • 角色一般用于基于主機構建服務的場景中,但是也可以用于構建守護進程等場景中。4

2、目錄結構

創建目錄

mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}

Ansible Playbook 講解與實戰操作

  • roles/
  • mysql/:mysql服務的yml文件
  • httpd/:apached服務的yml文件
  • nginx/:nginx服務的yml文件
  • files/:存儲由copy或者script等模塊調用的文件或者腳本;
  • tasks/:此目錄中至少應該有一個名為main.yml的文件,用于定義各個task;其他文件需要由main.yml進行包含調用;
  • handlers/:此目錄中至少應該有一個名為main.yml的文件,用于定義各個handler;其他文件需要由main.yml進行包含調用;
  • vars/:此目錄至少應該有一個名為main,yml的文件,用于定義各個variable;其他的文件需要由main.yml進行包含調用;
  • templates/:存儲由templates模塊調用的模板文件;
  • meta/:此目錄中至少應該有一個名為main.yml的文件,定義當前角色的特殊設定以及依賴關系,其他文件需要由main.yml進行包含調用;
  • default/:此目錄至少應該有一個名為main.yml的文件,用于設定默認變量;

3、實戰操作

【1】創建目錄

mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}

【2】定義配置文件

先下載nginx rpm部署包

# 下載地址:http://nginx.org/packages/centos/7/x86_64/RPMS/   wget http://nginx.org/packages/centos/7/x86_64/RPMS/nginx-1.18.0-1.el7.ngx.x86_64.rpm -O nginx/files/nginx-1.18.0-1.el7.ngx.x86_64.rpm
  • nginx/tasks/main.yml
- name: cp  copy: src=nginx-1.18.0-1.el7.ngx.x86_64.rpm dest=/tmp/nginx-1.18.0-1.el7.ngx.x86_64.rpm  - name: install  yum: name=/tmp/nginx-1.18.0-1.el7.ngx.x86_64.rpm state=latest  - name: conf  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf  tags: nginxconf  notify: new conf to reload  - name: start service  service: name=nginx state=started enabled=true
  • nginx/templates/nginx.conf.j2
usernginx; #設置nginx服務的系統使用用戶  worker_processes{{ ansible_processor_vcpus }}; #工作進程數    error_log/var/log/nginx/error.log warn; #nginx的錯誤日志  pid/var/run/nginx.pid; #nginx啟動時候的pid    events {  worker_connections1024; #每個進程允許的最大連接數  }    http { #http請求配置,一個http可以包含多個server    #定義 Content-Type  include /etc/nginx/mime.types;  default_typeapplication/octet-stream;    #日志格式 此處main與access_log中的main對應  #$remote_addr:客戶端地址  #$remote_user:http客戶端請求nginx認證的用戶名,默認不開啟認證模塊,不會記錄  #$timelocal:nginx的時間  #$request:請求method + 路由 + http協議版本  #status:http reponse 狀態碼  #body_bytes_sent:response body的大小  #$http_referer:referer頭信息參數,表示上級頁面  #$http_user_agent:user-agent頭信息參數,客戶端信息  #$http_x_forwarded_for:x-forwarded-for頭信息參數  log_formatmain'$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" '  '$status $body_bytes_sent "$http_referer" '  '"$http_user_agent" "$http_x_forwarded_for"';    #訪問日志,后面的main表示使用log_format中的main格式記錄到access.log中  access_log/var/log/nginx/access.logmain;    #nginx的一大優勢,高效率文件傳輸  sendfileon;  #tcp_nopush on;    #客戶端與服務端的超時時間,單位秒  keepalive_timeout65;    #gzipon;  server { #http服務,一個server可以配置多個location  listen {{ nginxport }}; #服務監聽端口  server_namelocalhost; #主機名、域名    #charset koi8-r;  #access_log/var/log/nginx/host.access.logmain;    location / {  root /usr/share/nginx/html; #頁面存放目錄  indexindex.html index.htm; #默認頁面  }    #error_page404/404.html;    # 將500 502 503 504的錯誤頁面重定向到 /50x.html  error_page 500 502 503 504/50x.html;  location = /50x.html { #匹配error_page指定的頁面路徑  root /usr/share/nginx/html; #頁面存放的目錄  }    # proxy the PHP scripts to Apache listening on 127.0.0.1:80  #  #location ~ .php$ {  #proxy_pass http://127.0.0.1;  #}    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000  #  #location ~ .php$ {  #root html;  #fastcgi_pass 127.0.0.1:9000;  #fastcgi_indexindex.php;  #fastcgi_paramSCRIPT_FILENAME/scripts$fastcgi_script_name;  #includefastcgi_params;  #}    # deny access to .htaccess files, if Apache's document root  # concurs with nginx's one  #  #location ~ /.ht {  #denyall;  #}  }  include /etc/nginx/conf.d/*.conf;  }
  • nginx/vars/main.yml
nginxport: 9999
  • nginx/handlers/main.yml
- name: new conf to reload  service: name=nginx state=restarted
  • 定義劇本文件(roles.yml
- hosts: web  remote_user: root  roles:  - nginx

最后的目錄結構如下:

Ansible Playbook 講解與實戰操作

執行

ansible-playbook roles.yml

Ansible Playbook 講解與實戰操作

? 版權聲明
THE END
喜歡就支持一下吧
點贊5 分享