Ansible--playbook

簡介

在ansible中playbook是由多個play組成的列表
paly的主要功能在於將事先歸併爲一組的主機裝扮成事先經過ansible中的task定義好的角色,從根本上講,所謂的task無非是調用ansible的module講多個play組織在一個playbook中,便可以讓它們連同起來按事先編排好的機制運行
palybook採用的是YAML語言編寫的

palybook核心元素
hosts               # 執行的遠程主機列表
tasks               # 任務集
varniables          # 內置變量或者自定義變量在playbook中調用
templates           # 模板,可替換模板文件中的變量並實現一些簡單的邏輯文件
handlers和notify    # 兩個集合使用,由特色條件觸發的操做,知足條件方纔執行,不然不執行
tags                # 標籤,指定某條件任務執行,用於選擇運行playbook中的部分代碼
                    # ansible具備冪等性,所以會自動跳過沒有變化的代碼,即使如此,有些代碼爲測試其確實沒有發生變化的時間依然會很是的長,此時,若是確信其沒有變化,就能夠經過tags跳過這些代碼php

經常使用元素示例

hosts元素

hosts元素
指定被控端的遠程主機列表
[root@ansible ~]# vim /root/ansible/hosts.yml
---
- hosts: web
  remote_user: root
  
在hosts後面的主機列表形式能夠是單個主機的主機名、IP地址、組名,或者兩個組的並集、交集、差集,好比:
brian.com       # 單個主機名
192.168.192.129 # 單個IP
web             # 一個組名
web:db          # 兩個組的並集
web:!db         # 兩個組的差集
web:&db         # 兩個組的交集

remote_user表示的是執行遠程的用戶,通常爲root

tasks元素

tasks元素
指定要執行的任務集
[root@ansible ~]# vim /root/ansible/tasks.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: create new file
      file: name=/root/ansible/newfile state=touch
    - name: create new user
      user: name=zhujingzhi state=present system=yes shell=/sbin/onlogin

這裏tasks元素裏面寫的就是要執行的任務
name 表示一個描述信息
file和user表示使用的模塊名,後面跟着的就是使用模塊操做的具體的使用方法(這裏使用file模塊在/root/ansible/建立了一個新的文件,使用user模塊建立了一個zhujingzhi的用戶)

handlers和notify元素

handlers和notify元素
notify元素,在tasks中的某段代碼中定義,做爲handlers的觸發器(當tasks中的代碼中觸發到notify的元素,則會執行notify指定的handlers中的代碼)
handlers元素屬於和tasks同級的列表,其主要做用是定義一個任務(和tasks中的任務是同樣的)等待tasks中任務觸發notify後執行
[root@ansible ~]# vim /root/ansible/nginx.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx 
    - name: copy nginx config file
      copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
      notify: 
        - restart nginx
        - check service
    - name: start nginx
      service: name=nginx state=started enabled=yes

  handlers:
    - name: restart nginx
      service: name=nginx state=restarted
    - name: check service
      shell: killall -0 nginx > /tmp/nginx.log


這裏在運行的時候出現了在被管理機器上沒有killall的命令的錯誤,解決方法(yum -y install psmisc)
killall -0 nginx 的意思就是檢查nginx的進程有沒有啓動返回0啓動,返回非0服務有問題

tags元素

tags元素
tags元素爲tasks裏面的任務打上一個標籤,方便在執行的時候單獨執行tasks裏面的單獨的任務和被其餘調用
[root@ansible ~]# vim /root/ansible/nginx.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx 
      tags: installnginx
    - name: copy nginx config file
      copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
      notify: 
        - restart nginx
        - check service
    - name: start nginx
      service: name=nginx state=started enabled=yes
      tags: startnginx

  handlers:
    - name: restart nginx
      service: name=nginx state=restarted
    - name: check service
      shell: killall -0 nginx > /tmp/nginx.log

可單獨執行tasks裏面的startnginx任務
[root@ansible ~]# ansible-playbook -t startnginx /root/ansible/nginx.yml 
也能夠指定兩個標籤執行
[root@ansible ~]# ansible-playbook -t installnginx,startnginx /root/ansible/nginx.yml 

舒適提示:
這裏多個任務也是可使用一個標籤的名字的
好比:
[root@ansible ~]# vim /root/ansible/nginx.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx 
      tags: nginx
    - name: copy nginx config file
      copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
      notify: 
        - restart nginx
        - check service
    - name: start nginx
      service: name=nginx state=started enabled=yes
      tags: nginx

  handlers:
    - name: restart nginx
      service: name=nginx state=restarted
    - name: check service
      shell: killall -0 nginx > /tmp/nginx.log
      
使用ansible執行(加-t參數)
[root@ansible ~]# ansible-playbook -t nginx /root/ansible/nginx.yml 

vars元素

vars元素
vars元素指的是定義變量
變量名:僅能由字母、數字和下劃線組成,且只能以字母開頭
能夠在什麼地方定義變量呢?以下:
1.ansible setup facts 遠程主機的全部變量都是能夠被直接調用的
2.在/etc/ansible/hosts中定義
普通變量:主機組中主機單獨定義,優先級高於公共變量
公共(組)變量:針對主機組中全部主機定義統一的變量
3.經過命令行指定變量,優先級最高
ansible-playbook -e varname=value
4.在playbook中定義
vars:
  - var1: value1
  - var2: value2
5.在role中定義(role是模塊化的設置模式,在role中var能夠定義在一個單獨的文件中)

示例:
1.ansible setup查看變量
# 查看全部的遠程主機上的可用變量
[root@ansible ~]# ansible all -m setup
# grep過濾查看主機名的變量
[root@ansible ~]# ansible all -m setup | grep ansible_fqdn
# setup模塊的filter方法過濾查看主機名
[root@ansible ~]# ansible all -m setup -a "filter=ansible_hostname"

2.在/etc/ansible/hosts中定義
[root@ansible ~]# vim /etc/ansible/hosts
[testserver]
192.168.192.129         http_port=8080

在playbook中使用
---
- hosts: web
  remote_user: root

  tasks:
    - name: set hostname
      hostname: name=brian{{ http_port }}.python.com

詳細的設置請查看:https://www.cnblogs.com/brianzhu/p/10188676.html

3.經過命令行指定變量,優先級最高
playbook的定義以下(使用{{}}雙大括號定義中間是變量名):
---
- hosts: web
  remote_user: root

  tasks:
    - name: install nginx
      yum: name={{ pkname1 }} 
    - name: install nginx
      yum: name={{ pkname1 }} 
    - name: copy nginx config file
      copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
    - name: start nginx
      service: name={{ pkname }} state=started enabled=yes

在命令行執行指定(使用 -e 參數指定變量變量賦值的定義格式是k=v格式)
[root@ansible ~]# ansible-playbook -e 'pkname1=nginx pkname2=vsftpd' /root/ansible/nginx.yml

4.在playbook中定義
直接是用vars元素定義變量列表
---
- hosts: web
  remote_user: root
  vars:
    - pkname1: nginx
    - pkname2: vsftpd
  tasks:
    - name: install nginx
      yum: name=nginx 
    - name: copy nginx config file
      copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
    - name: start nginx
      service: name=nginx state=started enabled=yes

5.將使用的變量存放到一個文件中,在playbook裏面調用
編輯變量文件
[root@ansible ~]# cat /root/ansible/vars.yml
var1: nginx
var2: nsftpd

在playbook中調用
---
- hosts: web
  remote_user: root
  vars_files:
    - vars.yml
  tasks:
    - name: install nginx
      yum: name={{ var1 }} 
    - name: install vsftpd
      yum: name={{ var2 }} 

templates元素

templates元素
主要是對配置文件進行遠程主機的copy(可以實現根據不一樣的主機的配置修改不一樣的配置文件)
templates 文件也是一個文本文件,嵌套有腳本(使用模板編程語言編寫)
模板文件的編程語言使用的是jinja2語言,支持下面的類型:
字符串: 使用單引號或者雙引號
數字: 整數,浮點數
列表: [item1,item2,..]
元組: (item1,item2,..)
字典: {key1:value1,key2:value2,..}
布爾值: true/false

算數運算符: +,-,*,/,//,%,**
比較運算符: ==,!=,>,>=,<,<=
邏輯運算符: and,or,not
流表達式: for if when

示例:
使用nginx的打開的進程數爲示例
建立模板目錄
[root@ansible ~]# mkdir -p /root/ansible/templates

編輯模板文件
在ansible管理機上安裝nginx,並copy nginx.conf到/root/ansible/templates中並更名爲nginx.conf.j2(更名是必須的這個是模塊的規定)
[root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx.conf.j2

這裏編輯nginx的模板文件將進程數**2
修改/root/ansible/templates/nginx.conf.j2
[root@ansible ~]# vim /root/ansible/templates/nginx.conf.j2

將 worker_processes auto;改爲 worker_processes {{ ansible_processor_vcpus**2 }};
這裏ansible_processor_vcpus是使用ansible setup獲得的遠程主機的cpu的個數


編寫playbook
[root@ansible ~]# vim /root/ansible/nginxtemp.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx
    - name: copy templates file
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
      notify: restart nginx
    - name: start nginx
      service: name=nginx state=started enabled=yes

  handlers:
    - name: restart nginx
      service: name=nginx state=restarted

執行playbook
[root@ansible ~]# ansible-playbook /root/ansible/nginxtemp.yml

查看結果
這裏個人機器是2個CPU的,剛剛在nginx模板文件中設置了worker_processes {{ ansible_processor_vcpus**2 }};全部最後開啓的進程是4個
[root@ansible ~]# ansible all -m shell -a "ps aux |grep nginx"
192.168.192.129 | CHANGED | rc=0 >>
root       6127  0.0  0.1 125092  2256 ?        Ss   17:09   0:00 nginx: master process /usr/sbin/nginx
nginx      6128  0.0  0.3 129348  7080 ?        S    17:09   0:00 nginx: worker process
nginx      6129  0.0  0.3 129348  7080 ?        S    17:09   0:00 nginx: worker process
nginx      6130  0.0  0.3 129348  7080 ?        S    17:09   0:00 nginx: worker process
nginx      6131  0.0  0.3 129348  7080 ?        S    17:09   0:00 nginx: worker process


模板文件使用變量(改變nginx端口)
這裏把變量定義在了/etc/ansible/hosts中爲每臺主機定義的(也可使用上面提到的其餘方式定義變量)

設置變量
[root@ansible ~]# vim /etc/ansible/hosts 
[web]
192.168.192.129  http_port=8080

設置模板文件
[root@ansible ~]# vim /root/ansible/templates/nginx.conf.j2
修改:
listen       {{ http_port }} default_server;
listen       [::]:{{ http_port }} default_server;

執行playbook
[root@ansible ~]# ansible-playbook /root/ansible/nginxtemp.yml

查看結果
[root@ansible ~]# ansible all -m shell -a "ss -ntl | grep 8080"
192.168.192.129 | CHANGED | rc=0 >>
LISTEN     0      128          *:8080                     *:*                  
LISTEN     0      128         :::8080                    :::*            

跳過錯誤繼續執行

做用主要是爲了解決在playbook中的tasks元素中某段代碼執行出現問題是否繼續往下執行的一個解決的方法(其默認是出錯及中止的) 
playbook文件

---
- hosts: web
  remote_user: root

  tasks: run this command and ignore the resullt
    - name: shell start nginx
      shell: /usr/bin/somecommand || /bin/true

或者

---
- hosts: web 
  remote_user: root

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

流程控制語句

when語句

when語句
when語句表示條件的測試,若是須要根據變量、facts或者此前任務的執行結果來作爲某task執行與否的前提時要用到條件測試,經過when語句就能夠實現
示例:
在生產環境中系統有6的和7的共存的狀況,那麼配置有些配置文件在不一樣的操做系統上是不同的,這時候咱們就要建立兩個模板文件根據不一樣的操做系統執行不一樣的配置文件copy
# 定義兩個配置文件
[root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx6.conf.j2
[root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx7.conf.j2

編寫playbook
[root@ansible ~]# vim /root/ansible/nginxtemp.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx
    - name: copy templates file for centos7
      template: src=nginx7.conf.j2 dest=/etc/nginx/nginx.conf
      when: ansible_distribution_major_version == '7'
      notify: restart nginx
    - name: copy templates file for centos6
      template: src=nginx6.conf.j2 dest=/etc/nginx/nginx.conf
      when: ansible_distribution_major_version == '6'
      notify: restart nginx
    - name: start nginx
      service: name=nginx state=started enabled=yes

  handlers:
    - name: restart nginx
      service: name=nginx state=restarted

with_items語句

with_items語法
with_items表示迭代,當須要執行重複性的任務的時候,就可使用迭代機制來實現
對於迭代的引用,固定的變量名爲"item"
要在tasks中使用with_items給定要迭代的元素列表
支持的列表格式:字符串、字典

示例:
同時執行建立多個文件的任務
編寫playbook
[root@ansible ~]# vim /root/ansible/items.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: create file
      file: name=/root/ansible/{{ item }} state=touch
      with_items:
        - file1
        - file2
        - file3

    - name: install packages
      yum: name={{ item }}
      with_items:
        - htop
        - sl
        - hping3

迭代嵌套子變量

迭代嵌套子變量
建立多個組和用戶將多個用戶加入到不一樣的組中
編寫playbook
[root@ansible ~]# vim /root/ansible/guser.yml
---
- hosts: web
  remote_user: root

  tasks:
    - name: add groups
      group: name={{ item }} state=present
      with_items:
        - g1
        - g2
        - g3

    - name: add user for goups
      user: name={{ item.name }} group={{ item.group }} state=present
      with_items:
        - { name: 'user1', group: 'g1'}
        - { name: 'user2', group: 'g2'}
        - { name: 'user3', group: 'g3'}

for語句

for語句
最後須要使用for語句生成的例子
server {
  listen: 81
}
server {
  listen: 82
}
server {
  listen: 83
}

這裏須要使用模板文件和變量來配合使用生成
palybook編寫
[root@ansible ~]# vim /root/ansible/testfor.yml
---
- hosts: web
  remote_user: root
  vars:
    ports:
      - 81
      - 82
      - 83

  tasks:
    - name: create for config
      template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf

模板文件編寫
[root@ansible ~]# vim /root/ansible/testfor.conf.j2
{% for p in ports %}
server {
  listen {{ p }}
}
{% enfor %}

執行playbook
[root@ansible ~]# ansible-playbook /root/ansible/testfor.yml

查看結果
[root@ansible ~]# ansible all -m shell -a "cat /root/ansible/testfor.conf"
192.168.171.129 | CHANGED | rc=0 >>
server {
  listen: 81
}
server {
  listen: 82
}
server {
  listen: 83
}

經過模板文件來獲取playbook文件中的設置好的變量並經過for語句進行屢次循環(playbook中使用的變量是列表的形式),這樣的方式使用起來實際上是很靈活的,也能夠是上面的列表的形式,也能夠是使用字典的形式或者列表嵌套字典的形式
好比:
playbook文件
---
- hosts: web
  remote_user: root
  vars:
    weblist:
      - web:
        port: 81
        name: python.brian.com
        rootdir: /nginx/python
      - web2:
        port: 82
        name: php.brian.com
        rootdir: /nginx/php

  tasks:
    - name: create for config
      template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf

模板文件
{% for w in weblist %}
server {
  listen {{ w.port }}
  servername {{ w.name }}
  documentroot {{ w.rootdir }}
}
{% endfor %}

if語句

if語句
在for語句中使用,判斷playbook中有沒有設置變量,設置了生成,沒有則不生成,這裏只是舉例子,還有其餘使用的方式,好比一個變量等於大於小於多少執行什麼任務等等

[root@ansible ~]# vim /root/ansible/testfor.yml
playbook文件
---
- hosts: web
  remote_user: root
  vars:
    weblist:
      - web:
        port: 81
        rootdir: /nginx/python
      - web2:
        port: 82
        name: php.brian.com
        rootdir: /nginx/php

  tasks:
    - name: create for config
      template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf

模板文件
[root@ansible ~]# vim /root/ansible/testfor.conf.j2
{% for w in weblist %}
server {
  listen {{ w.port }}
{% if w.name is defined %}
  servername {{ w.name }}
{% endif %}
  documentroot {{ w.rootdir }}
}
{% endfor %}

執行playbook
[root@ansible ~]# ansible-playbook  /root/ansible/testfor.yml 

查看結果
[root@ansible ~]# ansible all -m shell -a "cat /root/ansible/testfor.conf"
192.168.171.129 | CHANGED | rc=0 >>
server {
  listen 81
  documentroot /nginx/python
}
server {
  listen 82
  servername php.brian.com
  documentroot /nginx/php
}

上面的示例只是少部分的流程控制語句html

舒適提示:python

上面是我在生產中經常使用的元素,語句,這裏主要是把每一個元素分開來寫的,其實真正的playbook是要把上面的元素語句等結合一塊兒使用的nginx

本站公眾號
   歡迎關注本站公眾號,獲取更多信息