1. 程式人生 > >Ansible--playbook基礎

Ansible--playbook基礎

linux ansible

playbook可以理解成劇本,即一份文件可以存放多個ansible任務。後續的操作全部按照playbook中定義的動作執行

playbook使用YAML格式

YAML有自己的書寫格式,操作時一定要嚴格按照此格式執行,後面會詳細介紹其格式


playbook示例:

首先編輯yaml格式的文件,而此文件中統一定義要執行的操作:
vim  test.yaml     
- hosts: webservers   #指定操作的遠程主機 
  remote_user: root   #以root身份執行以下tasks
  tasks: 
  - name: install nginx               #任務的名稱,即在執行時顯示的標題名稱
    yum: name=nginx state=latest      #調用yum模塊,與單獨使用yum模塊時的用法是一樣的
  - name: start nginx 
    service: name=nginx enabled=true state=started  #service模塊

- hosts: dbservers     #另一組遠程主機
  remote_user: root
  tasks: 
  - name: install redis 
    yum: name=redis state=latest 
  - name: install conf file
    copy: src=/root/redis.conf dest=/app/ owner=redis group=root mode=0644
  - name: start redis 
    service: name=redis state=started
#以上註意hosts與name前要有短橫線打頭,這是yaml的格式要求
#而且tasks和其後面的具體任務要錯開,即不能頂格配置name、service等

ansible-playbook  --list-hosts test.yaml
#主機檢查
ansible-playbook  --list-tasks test.yaml
#任務檢查
ansible-playbook  --syntax-check test.yaml
#語法檢查

存在兩個問題

1)只想執行test.yaml中的某一個任務怎麽做

2)配置文件修改了,服務怎麽重啟,要知道service模塊的配置中state已經配置為started了,不會再添加state為restarted

上述兩個問題都需要執行任務但是只能將所有任務重新執行一遍,效率不高


問題1)的解決方案:給任務加標簽

vim test.yaml
 tasks: 
  - name: install redis 
    yum: name=redis state=latest 
  - name: install conf file
    copy: src=/root/redis.conf dest=/app/ owner=redis group=root mode=0644
    tags: install    #加此標簽,執行時指定此標簽則只執行此任務,未加標簽的任務不執行
  - name: start redis 
    service: name=redis state=started
    tags: start
#而且可以指定多個標簽,多個任務也可以使用同一個標簽,當調一個標簽時可以執行多個任務
ansible-playbook  --list-tags test.yaml 
#查看哪些hosts打了標簽
ansible-playbook  -t install,start test.yaml
#指定標簽執行

問題2)的解決方案:

條件式觸發任務,在配置文件被修改時會觸發handlers機制

vim test.yaml
- hosts: dbservers
  remote_user: root
  tasks: 
  - name: install redis 
    yum: name=redis state=latest 
  - name: install conf file
    copy: src=/root/redis.conf dest=/etc/ owner=redis group=root mode=0644
    tags: install 
    notify: restart redis service   #條件通知,當此任務即要復制的文件被修改了notify就會通知handlers執行觸發任務
  - name: start redis 
    service: name=redis state=started
    tags: start
  handlers:    #條件觸發器,只有滿足特定條件才會執行後續任務
  - name: restart redis service 
    service: name=redis state=restarted
#handlers依然調用service模塊重啟,這樣只有配置文件修改才會觸發handlers,才會執行此處的service。
#正常配置文件未改變的情況下不會觸發此任務
ansible-playbook  -t install  test.yaml  
#將redis.conf的bind端口修改後,測試即可

還有一個問題需要註意,即如何根據實際情況調整參數

如redis.conf配置文件中有maxmemory字段,表示用於redis的內存容量,如果想將此容量調整為當前主機的內存容量的一半該怎麽做。

要知道多個遠程主機的內存容量不一定是一樣的,有的是4G有的是16G如何根據主機自身的內存容量來配置呢?解決方案如下:

這個就用到了變量variables

facts變量:
ansible dbservers -m setup |  less
用戶自定義變量:
    a、在playbook中定義變量,如下: 
    vim tree.yml  
- hosts: webservers
  remote_user: root
  vars:   #定義變量,其格式是 變量名+冒號+值
  - pkgname: tree
  tasks:
  - name: install {{ pkgname }} pkg   #調用變量使用花括號
    yum: name={{ pkgname }} state=latest   #在執行任務時就可以調用變量
然後測試即可
ansible-playbook  -C tree.yml  

     b、在ansible-playbook命令中指定變量,其優先級高於playbook中定義的,如下:
     接著上述步驟a進行操作
     ansible-playbook -e "pkgname=memcached" -C tree.yml 
     #在命令行中使用-e指定變量的鍵值,tree.yml只是本次測試使用
     
    c、通過roles傳遞的變量,後續介紹
    
    d、host inventory主機列表中定義的變量:
    vim /etc/ansible/hosts 
    [webservers]
    192.168.1.106 pkgname=redis
    192.168.1.107 pkgname=redis
    #在定義主機列表時定義
    如果同一組內主機變量全部相同,即向一個組傳遞相同變量,還可以使用下述方法定義:
    [webservers:var]
    pkgname=redis

模板與變量引用:通常需要在模板中調用變量

template模塊:jinja2語法格式,類似於copy模塊

vim redis.yml  
- hosts: webservers
  remote_user: root
  tasks:
  - name: install redis maxmem
    template: src=/root/redis.conf dest=/tmp/ owner=redis mode=666 
#在此任務中我們使用template模塊,其提供模板功能,用法類似於copy
vim redis.conf 
maxmemory {{ ansible_memtotal_mb /2 }}mb
#ansible_memtotal_mb是ansible內置變量,可以參與多種運算
#在控制端,定義ansible內置變量並進行除法運算,即取本本機內存空間的一半
#這樣即使遠程多臺主機的內存大小不一致,此變量仍會取內存大小的一半並將取出的最終結果定義在此配置文件中傳給遠程主機
ansible-playbook  redis.yml   
#template支持嵌套腳本的文本文件這是與copy模塊的主要區別
#此示例可以上述提到的根據具體主機分別設置參數的問題。關鍵就是使用template模塊並使用正確的變量

條件測試:

when語句,只有滿足when條件才會執行任務

cat dfile.yml  
- hosts: webservers
  remote_user: root
  tasks:
  - name: copy file
    copy: src=/root/diff1.txt dest=/app/
    when: ansible_default_ipv4[‘address‘] == ‘172.18.251.244‘  #只有滿足此條件才能夠執行此任務
    #此條件說明當地址為127.18.251.244時執行copy模塊的操作,ansible_default_ipv4是ansible的內置變量,中括號[]表示調用變量的子鍵
    #
  - name: copy file2
    copy: src=/root/diff2.txt dest=/app/
    when: ansible_default_ipv4[‘address‘] == ‘192.168.1.107‘
    #
ansible-playbook  --syntax-check dfile.yml 
#檢查語法
ansible-playbook  dfile.yml

循環:叠代

需要重復執行任務,如在遠程主機上安裝多個程序包

cat tomcat.yml  
- hosts: dbservers
  remote_user: root
  vars:
  - jdk_version: 1.8.0   #定義變量
  tasks:
  - name: install  pkgs
    yum: name={{ item }} state=latest   #變量的調用方法是{{ }},而item是變量,其內容就是with_items中的
    with_items: 
    - nginx
    - java-{{ jdk_version }}-openjdk   #此處使用變量調用上文的內容
    - tomcat 
    - tomcat-webapps
    - tomcat-docs-webapp
    - tomcat-admin-webapps
    #以上是在一個任務中要安裝的軟件包
    擴展:以上是在一個任務中安裝多個軟件包,如果是創建多個用戶、組也是類似的方法
    總結:叠代循環配合變量,叠代的關鍵字段是with_items,變量的調用使用{{ }}
    
ansible-playbook  tomcat.yml   #執行操作

下面思考一個問題:

如果使用循環方式安裝多個軟件包,而每個軟件包的版本號基本是不一樣的,那如何動態的在安裝軟件包時添加版本號,而不是事先寫好在yaml文件中?

解決上述問題需要調用字典

cat tomcat.yml  
- hosts: dbservers
  remote_user: root
  tasks:
  - name: install  pkgs
    yum: name={{ item.name }}-{{ item.version }} state=latest   #item是使用循環的固定變量,此處item變量調用字典內容
    with_items:    #此處即所謂的字典,定義好軟件包名稱和版本號
    - { name: ‘nginx‘, version: 1.10.2 }
    - { name: ‘tomcat‘,version: 7.0.69 } 
#在一個任務中使用字典安裝軟件
ansible-playbook  -C tomcat.yml

再來看下面這個例子:循環加字典的使用
在控制端修改了兩份文件:tomcat-users.xml和 server.xml
現在要是先的是將此二份文件通過copy模塊復制到遠程主機
cat tomcat.yml 
- hosts: dbservers
  remote_user: root
  tasks:
  - name: install config file 
    copy: src={{ item.file }} dest={{ item.conf }}
    with_items:
    - { file: ‘/root/server.xml‘,conf: ‘/etc/tomcat/server.xml‘ }
    - { file: ‘/root/tomcat-users.xml‘,conf: ‘/etc/tomcat/tomcat-users.xml‘ }
#在字典中我們定義file和conf
ansible-playbook  tomcat.yml
#完成上述步驟,就可以到遠程主機上查看指定路徑的文件是否已經修改過

roles 角色:

vim /etc/ansible/ansible.cfg 
roles_path    = /etc/ansible/roles   #roles的路徑

/etc/ansible/roles/nginx/   
#其中nginx就是一個角色,在nginx目錄下應該具有特定的目錄層級結構,如:handlers  tasks  templates  vars
cat /etc/ansible/roles/nginx/tasks/main.yml    #tasks是nginx角色的一個任務模塊,main.yml是固定格式不能改變
- name: install nginx pkg
  yum: name=nginx state=latest
- name: start nginx service 
  service: name=nginx state=started enabled=true
  #此任務模塊完成兩個動作,安裝nginx和啟動nginx
  
然後配置playbook文件
cat websrv.yml 
- hosts: webservers
  remote_user: root
  roles:   #不需要像以前那樣配置tasks之類的,而是直接指定角色
  - nginx 
  #對webservers的主機以root身份調用nginx角色,而nginx橘色定義了兩個task任務

ansible-playbook  -C websrv.yml 
#測試

總結:創建角色nginx,配置playbook文件,而此文件只需調用角色即可,具體操作已經在角色的模塊中定義好了

示例:
基於模板生成nginx配置文件
第一步定義nginx內的變量                    #定義變量,將被templates模板調用
cat /etc/ansible/roles/nginx/vars/main.yml 
nginx_server_port: 8888
nginx_server_name: www.abc.com
nginx_doc_root: /webdata
第二步配置nginx下的模板文件                #定義模板文件,調用vars變量,此模板將用於生成nginx服務的配置文件
cat /etc/ansible/roles/nginx/templates/web-conf.j2 
server {
        listen {{ nginx_server_port }}
        server_name {{ nginx_server_name }}

        location  / {
                root {{ nginx_doc_root }}
        }
}
第三步定義nginx下的任務文件                #定義多項任務,安裝nginx、配置文件、創建文件、開啟服務
cat /etc/ansible/roles/nginx/tasks/main.yml  
- name: install nginx pkg
  yum: name=nginx state=latest
- name: install conf file
  template: src=web-conf.j2 dest=/etc/nginx/conf.d/web.conf
- name: create datadir
  file: path={{ nginx_doc_root }} state=directory    #此目錄即nginx模板文件中將使用的
- name: start nginx service 
  service: name=nginx state=started enabled=true
第四步配置playbook文件                #定義webservers組中主機以root身份調用nginx角色,而nginx角色能做什麽上述三個步驟已定義
cat /root/websrv.yml 
- hosts: webservers
  remote_user: root
  roles:
  - nginx
第五步測試i
ansible-playbook   websrv.yml 
#執行完上述操作,在遠程webservers主機的/etc/nginx/conf.d/web.conf文件中就會有nginx模板下web-conf.j2文件的內容
#





















本文出自 “a_pan” 博客,謝絕轉載!

Ansible--playbook基礎