常见

#定义任务的名称 #调用模块,具体要做的事情
- name: create new file file: name=/tmp/playtest.txt state=touch
- name: create new dir file: name=/tmp/back state=directory
- name: create new user user: name=test02 system=yes shell=/sbin/nologin
user: name=test001 state=present
- name: Create New Group group: name=test001 state=present
- name: install package yum: name=httpd
- name: start httpd service: name=httpd state=started
- name: copy index.html copy: src=/var/www/html/index.html dest=/var/www/html/index.html
- name: run df -h shell: name=df -h
get ip_addr shell: echo {{ ansible_default_ipv4[ “address” ] }} >> /root/newfile.txt

task定义要执行该任务的远程用户

  1. tasks:
  2. - name: run df -h
  3. remote_user: test
  4. shell: name=df -h

task定义使用sudo授权用户执行该任务

  1. tasks:
  2. - name: run df -h
  3. sudo_user: test
  4. sudo: yes
  5. shell: name=df -h

task任务列表

每一个task必须有一个名称name,这样在运行playbook时,从其输出的任务执行信息中可以很清楚的辨别是属于哪一个task的,如果没有定义 nameaction的值将会用作输出信息中标记特定的task

Handlers与Notify

很多时候当我们某一个配置发生改变,我们需要重启服务,(比如httpd配置文件文件发生改变了)这时候就可以用到handlersnotify了;
(当发生改动时)notify actions会在playbook的每一个task结束时被触发,而且即使有多个不同task通知改动的发生,notify actions知会被触发一次;比如多个resources指出因为一个配置文件被改动,所以apache需要重启,但是重新启动的操作只会被执行一次。

  1. [root@ansible ~]# cat httpd.yml
  2. #用于安装httpd并配置启动
  3. ---
  4. - hosts: 192.168.1.31
  5. remote_user: root
  6. tasks:
  7. - name: install httpd
  8. yum: name=httpd state=installed
  9. - name: config httpd
  10. template: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
  11. notify:
  12. - restart httpd
  13. - name: start httpd
  14. service: name=httpd state=started
  15. handlers:
  16. - name: restart httpd
  17. service: name=httpd state=restarted
  18. #这里只要对httpd.conf配置文件作出了修改,修改后需要重启生效,在tasks中定义了restart httpd这个action,然后在handlers中引用上面tasks中定义的notify。

Playbook中变量的使用

环境说明:这里配置了两个组,一个apache组和一个nginx组

  1. [root@ansible PlayBook]# cat /etc/ansible/hosts
  2. [apache]
  3. 192.168.1.36
  4. 192.168.1.33
  5. [nginx]
  6. 192.168.1.3[1:2]

命令行指定变量

执行playbook时候通过参数-e传入变量,这样传入的变量在整个playbook中都可以被调用,属于全局变量

  1. [root@ansible PlayBook]# cat variables.yml
  2. ---
  3. - hosts: all
  4. remote_user: root
  5. tasks:
  6. - name: install pkg
  7. yum: name={{ pkg }}
  8. #执行playbook 指定pkg
  9. [root@ansible PlayBook]# ansible-playbook -e "pkg=httpd" variables.yml

hosts文件中定义变量

/etc/ansible/hosts文件中定义变量,可以针对每个主机定义不同的变量,也可以定义一个组的变量,然后直接在playbook中直接调用。注意,组中定义的变量没有单个主机中的优先级高。

  1. # 编辑hosts文件定义变量
  2. [root@ansible PlayBook]# vim /etc/ansible/hosts
  3. [apache]
  4. 192.168.1.36 webdir=/opt/test #定义单个主机的变量
  5. 192.168.1.33
  6. [apache:vars] #定义整个组的统一变量
  7. webdir=/web/test
  8. [nginx]
  9. 192.168.1.3[1:2]
  10. [nginx:vars]
  11. webdir=/opt/web
  12. # 编辑playbook文件
  13. [root@ansible PlayBook]# cat variables.yml
  14. ---
  15. - hosts: all
  16. remote_user: root
  17. tasks:
  18. - name: create webdir
  19. file: name={{ webdir }} state=directory #引用变量
  20. # 执行playbook
  21. [root@ansible PlayBook]# ansible-playbook variables.yml

playbook文件中定义变量#

编写playbook时,直接在里面定义变量,然后直接引用,可以定义多个变量;注意:如果在执行playbook时,又通过-e参数指定变量的值,那么会以-e参数指定的为准。

  1. # 编辑playbook
  2. [root@ansible PlayBook]# cat variables.yml
  3. ---
  4. - hosts: all
  5. remote_user: root
  6. vars: #定义变量
  7. pkg: nginx #变量1
  8. dir: /tmp/test1 #变量2
  9. tasks:
  10. - name: install pkg
  11. yum: name={{ pkg }} state=installed #引用变量
  12. - name: create new dir
  13. file: name={{ dir }} state=directory #引用变量
  14. # 执行playbook
  15. [root@ansible PlayBook]# ansible-playbook variables.yml
  16. # 如果执行时候又重新指定了变量的值,那么会已重新指定的为准
  17. [root@ansible PlayBook]# ansible-playbook -e "dir=/tmp/test2" variables.yml

调用setup模块获取变量#

setup模块默认是获取主机信息的,有时候在playbook中需要用到,所以可以直接调用。常用的参数参考

  1. # 编辑playbook文件
  2. [root@ansible PlayBook]# vim variables.yml
  3. - hosts: [dbservers]
  4. remote_user: ansibleuser
  5. become: yes
  6. become_user: root
  7. tasks:
  8. - name: create new file
  9. shell: echo {{ ansible_fqdn }} > /tmp/newfile.txt
  10. # 执行playbook
  11. [root@ansible PlayBook]# ansible-playbook variables.yml
  1. [ansibleuser@node1 ~]$ ansible dbservers -m setup >setup.txt
  2. [ansibleuser@node1 ~]$ head -50 setup.txt
  3. 172.18.15.182 | SUCCESS => {
  4. "ansible_facts": {
  5. "ansible_all_ipv4_addresses": [
  6. "172.18.15.182"
  7. ],
  8. "ansible_all_ipv6_addresses": [
  9. "fe80::a00:27ff:fe2f:c9bc"
  10. ],
  11. ......
  12. 当然,仔细观察setup模块的输出信息不难发现,所有的内建变量都是键值对的形式,有些多个键值对在一个花括号里面,这样的文本组织形式是基于JSON格式。
  13. 在变量ansible_default_ipv4下还有多个子变量,我们可以称之为二级变量或者子键,分别对应着不同的值,这些子键的调用需要上级主键的配合使用才能完成变量调用,其格式为{{ main_var[ "sub_var" ] }}。
  14. task:
  15. - name: get ip_addr
  16. shell: echo {{ ansible_default_ipv4[ "address" ] }} >> /root/newfile.txt
  17. - name: get mac_addr
  18. shell: echo {{ ansible_default_ipv4[ "macaddress" ] }} >> /root/newfile.txt

独立的变量YAML文件中定义#

为了方便管理将所有的变量统一放在一个独立的变量YAML文件中,playbook文件直接引用文件调用变量即可。

  1. # 定义存放变量的文件
  2. [root@ansible PlayBook]# cat var.yml
  3. var1: vsftpd
  4. var2: httpd
  5. # 编写playbook
  6. [root@ansible PlayBook]# cat variables.yml
  7. ---
  8. - hosts: all
  9. remote_user: root
  10. vars_files: #引用变量文件
  11. - ./var.yml #指定变量文件的path(这里可以是绝对路径,也可以是相对路径)
  12. tasks:
  13. - name: install package
  14. yum: name={{ var1 }} #引用变量
  15. - name: create file
  16. file: name=/tmp/{{ var2 }}.log state=touch #引用变量
  17. # 执行playbook
  18. [root@ansible PlayBook]# ansible-playbook variables.yml

Playbook中标签的使用#

一个playbook文件中,执行时如果想执行某一个任务,那么可以给每个任务集进行打标签,这样在执行的时候可以通过-t选择指定标签执行,还可以通过--skip-tags选择除了某个标签外全部执行等。

Playbook中模板的使用#

template模板为我们提供了动态配置服务,使用jinja2语言,里面支持多种条件判断、循环、逻辑运算、比较操作等。其实说白了也就是一个文件,和之前配置文件使用copy一样,只是使用copy,不能根据服务器配置不一样进行不同动态的配置。这样就不利于管理。
说明:
1、多数情况下都将template文件放在和playbook文件同级的templates目录下(手动创建),这样playbook文件中可以直接引用,会自动去找这个文件。如果放在别的地方,也可以通过绝对路径去指定。
2、模板文件后缀名为.j2
示例:通过template安装httpd
1)playbook文件编写

  1. [root@ansible PlayBook]# cat testtmp.yml
  2. #模板示例
  3. ---
  4. - hosts: all
  5. remote_user: root
  6. vars:
  7. - listen_port: 88 #定义变量
  8. tasks:
  9. - name: Install Httpd
  10. yum: name=httpd state=installed
  11. - name: Config Httpd
  12. template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf #使用模板
  13. notify: Restart Httpd
  14. - name: Start Httpd
  15. service: name=httpd state=started
  16. handlers:
  17. - name: Restart Httpd
  18. service: name=httpd state=restarted

2)模板文件准备,httpd配置文件准备,这里配置文件端口使用了变量

  1. [root@ansible PlayBook]# cat templates/httpd.conf.j2 |grep ^Listen
  2. Listen {{ listen_port }}

3)查看目录结构

  1. # 目录结构
  2. [root@ansible PlayBook]# tree .
  3. .
  4. ├── templates
  5. └── httpd.conf.j2
  6. └── testtmp.yml
  7. 1 directory, 2 files

template之when#

条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过when语句执行,在task中使用jinja2的语法格式、
when语句:
task后添加when子句即可使用条件测试;when语句支持jinja2表达式语法。
类似这样:

  1. tasks:
  2. - command: /bin/false
  3. register: result
  4. ignore_errors: True
  5. - command: /bin/something
  6. when: result|failed
  7. - command: /bin/something_else
  8. when: result|success
  9. - command: /bin/still/something_else
  10. when: result|skipped

示例:通过when语句完善上面的httpd配置
1)准备两个配置文件,一个centos6系统httpd配置文件,一个centos7系统httpd配置文件。

  1. [root@ansible PlayBook]# tree templates/
  2. templates/
  3. ├── httpd6.conf.j2 #6系统2.2.15版本httpd配置文件
  4. └── httpd7.conf.j2 #7系统2.4.6版本httpd配置文件
  5. 0 directories, 2 files

2)修改playbook文件,通过setup模块获取系统版本去判断。setup常用模块

  1. [root@ansible PlayBook]# cat testtmp.yml
  2. #when示例
  3. ---
  4. - hosts: all
  5. remote_user: root
  6. vars:
  7. - listen_port: 88
  8. tasks:
  9. - name: Install Httpd
  10. yum: name=httpd state=installed
  11. - name: Config System6 Httpd
  12. template: src=httpd6.conf.j2 dest=/etc/httpd/conf/httpd.conf
  13. when: ansible_distribution_major_version == "6" #判断系统版本,为6便执行上面的template配置6的配置文件
  14. notify: Restart Httpd
  15. - name: Config System7 Httpd
  16. template: src=httpd7.conf.j2 dest=/etc/httpd/conf/httpd.conf
  17. when: ansible_distribution_major_version == "7" #判断系统版本,为7便执行上面的template配置7的配置文件
  18. notify: Restart Httpd
  19. - name: Start Httpd
  20. service: name=httpd state=started
  21. handlers:
  22. - name: Restart Httpd
  23. service: name=httpd state=restarted

template之with_items#

with_items迭代,当有需要重复性执行的任务时,可以使用迭代机制。
对迭代项的引用,固定变量名为“item”,要在task中使用with_items给定要迭代的元素列表。
列表格式:
  字符串
  字典
示例1:通过with_items安装多个不同软件
编写playbook

  1. [root@ansible PlayBook]# cat testwith.yml
  2. # 示例with_items
  3. ---
  4. - hosts: all
  5. remote_user: root
  6. tasks:
  7. - name: Install Package
  8. yum: name={{ item }} state=installed #引用item获取值
  9. with_items: #定义with_items
  10. - httpd
  11. - vsftpd
  12. - nginx

上面tasks写法等同于:

  1. ---
  2. - hosts: all
  3. remote_user: root
  4. tasks:
  5. - name: Install Httpd
  6. yum: name=httpd state=installed
  7. - name: Install Vsftpd
  8. yum: name=vsftpd state=installed
  9. - name: Install Nginx
  10. yum: name=nginx state=installed

示例2:通过嵌套子变量创建用户并加入不同的组
1)编写playbook

  1. [root@ansible PlayBook]# cat testwith01.yml
  2. # 示例with_items嵌套子变量
  3. ---
  4. - hosts: all
  5. remote_user: root
  6. tasks:
  7. - name: Create New Group
  8. group: name={{ item }} state=present
  9. with_items:
  10. - group1
  11. - group2
  12. - group3
  13. - name: Create New User
  14. user: name={{ item.name }} group={{ item.group }} state=present
  15. with_items:
  16. - { name: 'user1', group: 'group1' }
  17. - { name: 'user2', group: 'group2' }
  18. - { name: 'user3', group: 'group3' }

template之for if#

通过使用forif可以更加灵活的生成配置文件等需求,还可以在里面根据各种条件进行判断,然后生成不同的配置文件、或者服务器配置相关等。

示例1

1)编写playbook

  1. [root@ansible PlayBook]# cat testfor01.yml
  2. # template for 示例
  3. ---
  4. - hosts: all
  5. remote_user: root
  6. vars:
  7. nginx_vhost_port:
  8. - 81
  9. - 82
  10. - 83
  11. tasks:
  12. - name: Templage Nginx Config
  13. template: src=nginx.conf.j2 dest=/tmp/nginx_test.conf

2)模板文件编写

  1. # 循环playbook文件中定义的变量,依次赋值给port
  2. [root@ansible PlayBook]# cat templates/nginx.conf.j2
  3. {% for port in nginx_vhost_port %}
  4. server{
  5. listen: {{ port }};
  6. server_name: localhost;
  7. }
  8. {% endfor %}

{% for port in nginx_vhost_port %}
server{
listen: {{ port }};
server_name: localhost;
}
{% endfor %}

3)执行playbook并查看生成结果

  1. [root@ansible PlayBook]# ansible-playbook testfor01.yml
  2. # 去到一个节点看下生成的结果发现自动生成了三个虚拟主机
  3. [root@linux ~]# cat /tmp/nginx_test.conf
  4. server{
  5. listen: 81;
  6. server_name: localhost;
  7. }
  8. server{
  9. listen: 82;
  10. server_name: localhost;
  11. }
  12. server{
  13. listen: 83;
  14. server_name: localhost;
  15. }

示例2

1)编写playbook

  1. [root@ansible PlayBook]# cat testfor02.yml
  2. # template for 示例
  3. ---
  4. - hosts: all
  5. remote_user: root
  6. vars:
  7. nginx_vhosts:
  8. - web1:
  9. listen: 8081
  10. server_name: "web1.example.com"
  11. root: "/var/www/nginx/web1"
  12. - web2:
  13. listen: 8082
  14. server_name: "web2.example.com"
  15. root: "/var/www/nginx/web2"
  16. - web3:
  17. listen: 8083
  18. server_name: "web3.example.com"
  19. root: "/var/www/nginx/web3"
  20. tasks:
  21. - name: Templage Nginx Config
  22. template: src=nginx.conf.j2 dest=/tmp/nginx_vhost.conf

2)模板文件编写

  1. [root@ansible PlayBook]# cat templates/nginx.conf.j2
  2. {% for vhost in nginx_vhosts %}
  3. server{
  4. listen: {{ vhost.listen }};
  5. server_name: {{ vhost.server_name }};
  6. root: {{ vhost.root }};
  7. }
  8. {% endfor %}

3)执行playbook并查看生成结果

  1. [root@ansible PlayBook]# ansible-playbook testfor02.yml
  2. # 去到一个节点看下生成的结果发现自动生成了三个虚拟主机
  3. [root@linux ~]# cat /tmp/nginx_vhost.conf
  4. server{
  5. listen: 8081;
  6. server_name: web1.example.com;
  7. root: /var/www/nginx/web1;
  8. }
  9. server{
  10. listen: 8082;
  11. server_name: web2.example.com;
  12. root: /var/www/nginx/web2;
  13. }
  14. server{
  15. listen: 8083;
  16. server_name: web3.example.com;
  17. root: /var/www/nginx/web3;
  18. }

示例3

在for循环中再嵌套if判断,让生成的配置文件更加灵活
1)编写playbook

  1. [root@ansible PlayBook]# cat testfor03.yml
  2. # template for 示例
  3. ---
  4. - hosts: all
  5. remote_user: root
  6. vars:
  7. nginx_vhosts:
  8. - web1:
  9. listen: 8081
  10. root: "/var/www/nginx/web1"
  11. - web2:
  12. server_name: "web2.example.com"
  13. root: "/var/www/nginx/web2"
  14. - web3:
  15. listen: 8083
  16. server_name: "web3.example.com"
  17. root: "/var/www/nginx/web3"
  18. tasks:
  19. - name: Templage Nginx Config
  20. template: src=nginx.conf.j2 dest=/tmp/nginx_vhost.conf

2)模板文件编写

  1. # 说明:这里添加了判断,如果listen没有定义的话,默认端口使用8888,如果server_name有定义,那么生成的配置文件中才有这一项。
  2. [root@ansible PlayBook]# cat templates/nginx.conf.j2
  3. {% for vhost in nginx_vhosts %}
  4. server{
  5. {% if vhost.listen is defined %}
  6. listen: {{ vhost.listen }};
  7. {% else %}
  8. listen: 8888;
  9. {% endif %}
  10. {% if vhost.server_name is defined %}
  11. server_name: {{ vhost.server_name }};
  12. {% endif %}
  13. root: {{ vhost.root }};
  14. }
  15. {% endfor %}

3)执行playbook并查看生成结果

  1. [root@ansible PlayBook]# ansible-playbook testfor03.yml
  2. # 去到一个节点看下生成的结果发现自动生成了三个虚拟主机
  3. [root@linux ~]# cat /tmp/nginx_vhost.conf
  4. server{
  5. listen: 8081;
  6. root: /var/www/nginx/web1;
  7. }
  8. server{
  9. listen: 8888;
  10. server_name: web2.example.com;
  11. root: /var/www/nginx/web2;
  12. }
  13. server{
  14. listen: 8083;
  15. server_name: web3.example.com;
  16. root: /var/www/nginx/web3;
  17. }