1.基本语法

playbook文件格式为yaml语法.示例如下:
1.1 nginx.yaml

---
- hosts: all
  tasks:
      - name: Install Nginx Package
        yum: name=nginx state=present

      - name: Copy Nginx.conf
        template: src=./nginx.conf.j2 dest=/etc/nginx/nginx.conf owner=root group=root mode=0644 validate='nginx -t -c %s'
        notify:
           - Restart Nginx Service
  handlers:
      - name: Restart Nginx Service
        service: name=nginx state=restarted
---第一行表示该文件是yaml文件,非必须,建议写上

hosts:all 定义该playbook针对的目标主机,all表示针对所有主机,这个参数支持Ad-Hoc模式的所有参数
tasks: 定义该playbook所有的tasks集合

name: Install Nginx Package定义一个task的名称,建议根据task实际任务命名
yum: name=nginx state=present 定义一个状态的action,这里使用yum模块,实现nginx软件包的安装

第6行-第9行使用template模板去管理/etc/nginx/nginx.conf文件,owner,group定义该文件的属主及属组,使用validate参数指文件生成后使用nginx -t -c 检测配置文件语法,notify是触发handlers,如果同步后,文件md5值有变化的话会触发handler
第10-12行定一个一个handler状态让Nginx去重启,

1.2 主机清单文件

cat /tmp/hosts

[nginx]
192.168.1.1
192.168.1.2
[nginx:vars]
ansible_python_interpreter=/usr/bin/python2.6

1.3 nginx.conf.j2

user                                    admin  admin;
worker_processes                        8;
worker_cpu_affinity                     {{ ansible_processor_cores }};
error_log                               /export/servers/nginx/logs/nginx_error.log  warn;
pid                                     /export/servers/nginx/run/nginx.pid;
worker_rlimit_nofile                    65535;
events 
{
                                        use epoll;
                                        worker_connections 65535;
}
http 
{
        include                         mime.types;
        default_type                    application/octet-stream;
        server_tokens                   on;
        log_format main                 '$remote_addr - $remote_user [$time_local] "$http_x_forwarded_for" "$http_j_forwarded_for" '
                                                        '"$request" $status $bytes_sent '
                                                        '"$http_referer" "$http_user_agent" '
                                                        '"$gzip_ratio"';
        #charset                        utf-8;
        server_names_hash_bucket_size   128;
        client_header_buffer_size       32k;
        large_client_header_buffers     4 32k;
        client_max_body_size            300m;
        sendfile                        on;
        tcp_nopush                      on;
        keepalive_timeout               0;
        tcp_nodelay                     on;
        client_body_buffer_size         512k;
        fastcgi_intercept_errors        on;
        proxy_connect_timeout           90;
        proxy_read_timeout              180;
        proxy_send_timeout              180;
        proxy_buffer_size               256k;
        proxy_buffers                   4 256k;
        proxy_busy_buffers_size         256k;
        proxy_temp_file_write_size      256k;
        proxy_intercept_errors          on;
        server_name_in_redirect         off;
        proxy_hide_header       X-Powered-By;

        gzip                            on;
        gzip_min_length                 100;
        gzip_buffers                    4 16k;
        gzip_http_version               1.0;
        gzip_comp_level                 9;
        gzip_types                      text/plain application/x-javascript text/css application/xml;
        gzip_vary                       on;
        gzip_proxied                       any;

include domains/*;
###########status#########
#        server
#                {
#                 listen                 80;
#                 server_name            status.360buy.com;
#        location / {
#                 stub_status            on;
#                 access_log             off;
#                 }
#        }
}

1.hosts文件里面定义了一个nginx组,里面有2个IP
2.组变量ansible_python_interpreter是ansible自带的影藏变量,是facts套件提供的;如果目标机器上python版本多,指定一个版本来运行
3.nginx.conf.j2是nginx.conf的模板文件,里面只针对worker_processes参数通过facts套件中的cpu核心数生成,其他配置都是默认的

1.4 检查yaml文件的语法是否正确

$ ansible-playbook -i /tmp/hosts nginx.yaml --syntax-check

1.5 检查yaml文件中的tasks任务

$ ansible-playbook -i /tmp/hosts nginx.yaml --list-task

1.6 检查yaml文件中的生效主机

$ ansible-playbook -i /tmp/hosts nginx.yaml --list-hosts

1.7 运行playbook

$ ansible-playbook -i /tmp/hosts nginx.yaml

1.8 运行playbook里面特定的某个task,从某个task开始运行

$ ansible-playbook -i /tmp/hosts nginx.yaml --start-at-task='Copy Nginx.conf'

2.变量与引用
2.1 通过inventory文件定义主机以及主机组变量
(1)静态主机文件

默认的ansible invetory是/etc/hosts文件,可以通过ANSIBLE_HOSTS环境变量或者通过运行命令的时候加上-i

vim /tmp/hosts
# 定义组
[webservers]
10.187.11.34
10.187.137.191

# 组变量
[webservers:vars]
ansible_ssh_pass = '123456'

多个静态文件,可以写不同的文件里,文件名字hosts不是必须

inventory可以指向一个目录,这样目录里面所有的文件都会被加载进来,可以通过–list-hosts()来验证

[admin@host-10-187-196-225 hosts_file]$ ansible -i /tmp/hosts_file/ webservers --list-hosts
    10.187.109.116
    10.189.92.46

(2)动态主机文件

ansible.cfg配置文件中的inventory配置项指向一个脚本
这个脚本有一定规范和参数要求
1.支持–list或者-l,这个参数运行后会显示所有的主机以及主机组的信息(JSON格式)
2.支持–host或者-H,这个参数后面需要指定一个host,运行结果会返回这台主机的所有信息(包括认证信息,主机变量等),也是json格式

#!/usr/bin/env python
# -*- coding=utf-8 -*-
#########################
import argparse
import sys
import json

def lists():
    r = dict()
    h = ['172.17.42.10' + str(i) for i in range(1,4)]
    hosts = {'hosts':h}
    r['docker'] = hosts
    return json.dumps(r,indent=4)

def hosts(name):
    r = {'ansible_ssh_pass':'123456'}
    cpis = dict(r.items())
    return json.dumps(cpis,indent=4)

if __name__ == "__main__":
    '''添加argparse的参数类实例,添加一些-l和-H的帮助显示提示'''
    parser = argparse.ArgumentParser()
    parser.add_argument('-l','--list',help='hosts list',action='store_true')
    parser.add_argument('-H','--host',help='hosts vars')
    '''vars方法把parser.parse_args()字典转换过去判断用户输入的内容'''
    args = vars(parser.parse_args())
    if args['list']:
        print lists()
    elif args['host']:
        print hosts(args['host'])
    else:
        parser.print_help()

用实际主机来跑一批任务

ansible -i hosts.py docker -m ping -k

(3)主机文件支持的变量

ansible_ssh_host 定义host ssh地址
ansible_ssh_port 定义host ssh端口
ansible_ssh_user 定义hosts ssh认证用户
ansible_ssh_pass 定义hosts ssh 认证密码
ansible_sudo 定义hosts sudo用户
ansible_sudo_pass 定义hosts sudo密码
ansible_sudo_exe 定义hosts sudo 路径
ansible_connection 定义hosts连接方式
ansible_ssh_private_key_file 定义hosts私钥
ansible_shell_type 定义hosts shell类型
ansible_python_interpreter 定义hosts任务执行python路径
ansible_*_interpreter 定义hosts其他语言解析器路径
2.2 通过playbook文件当前目录下新建group_vars和host_vars这2个目录(目录名字固定,不能改)

$ cat group_vars/nginx

---
key: NGINX

在当前目录下运行playbook的时候,会自动去找group_vars和host_vars这2个目录

2.3 通过ansible-playbook命令行参数传入
(1)命令行传递变量

$ ansible-playbook -i /tmp/hosts nginx.yaml -e "key=KEY"

(2)命令行传递变量文件

$ cat var.yaml
---
key: YAML
$ cat var.json
{"key":"JSON"}
$ ansible-playbook -i /tmp/hosts nginx.yaml -e "@var.json"
$ ansible-playbook -i /tmp/hosts nginx.yaml -e "@var.yaml"

2.4 在playbook文件内使用vars(用的很少)

---
- hosts: all
  vars:
        key: Ansible
  tasks:
      - name: xxx
        deubg: msg="The {{ key}}"

2.5 在playbook文件内使用vars_files引用外部变量文件(也可以是json文件,后期开发api模式主要用这种方式)

---
- hosts: all
  vars_files:
    - var.yaml
    - var.json

2.6 使用register内的变量

ansible的task之间还可以互相传递数据,把第一个task执行的结果register注册为变量然后传递给第二个task

---
- hosts: all
  tasks:
      - name: register variable
        shell: hostname
        register: info
      - name: display variable
        debug: msg="The msg is {{ info }}"
        debug: msg="The msg is {{ info['stdout'] }}"

实际跑下看下结果(-l呢是在匹配主机inventory里面再进一步筛选,只跑192.168.1.118主机)

$ ansible-playbook -i /tmp/hosts variable.yaml -l 192.168.1.118

3.循环
3.1 标准loops

分别打印one two这2个值

---
- hosts:all
  tasks:
      - name: debug loops
        debug: msg = "name---> {{ item }}"
        with_items:
            - one
            - two

with_items:值呢是python list数据结构,每个task会循环读取list里面的值,key的名称是item,当然支持列表里面嵌套字典,例子如下

---
- hosts:all
  tasks:
      - name: debug loops
        debug: msg = "name-----> {{ item.key }} value---->{{ item.value }}"
        with_items:
            - {key:"one",value:"value1"}
            - {key:"two",value:"value2"}

3.2 嵌套loops

实现一堆多或者多对多的合并

---
- hosts:all
  tasks:
      - name: debug loops
        debug: msg="name ----->{{ item[0] }}  value----->{{ item[1] }}"
        with_nested:
            - ['A']
            - ['a','b','c']

3.3 字典循环

---
- hosts:all
  tasks:
      - name: debug loops
        debug: msg="name ----->{{ item.key }}  value----->{{ item.value }}"
        with_dict: user

3.4 文件循环

---
- hosts:all
  tasks:
      - name: debug loops
        debug: msg="{{ item }}"
        with_fileglob:
            - /tmp/*.yaml

3.5 随机循环

---
- hosts:all
  tasks:
      - name: debug loops
        debug: msg="{{ item }}"
        with_random_choice:
            - "ansible1"
            - "ansible2"
            - "ansible3"

3.6 条件判断循环

---
- hosts:all
  tasks:
      - name: debug loops
        shell: cat /root/ansible
        register: host
        until: host.stdout.startswith('Master')
        retries:5
        delay:5

5秒执行一次cat /root/ansible,将结果注册给变量host,判断host.stdout的内容是否以Master开头,条件成立,task运行完成,条件不成立,5秒后重试,5次还不成立,task运行失败

4.lookups
从外部拉取信息,定义给一个变量的形式,lookups插件