1、 选择具有主机模式的主机

1.1 主机清单

[student@workstation mmx]$ cat inventory
web.example.com
data.example.com

[lab]
labhost1.example.com
labhost2.example.com

[test]
test1.example.com
test2.example.com

[datacenter1]
labhost1.example.com
test1.example.com

[datacenter2]
labhost2.example.com
test2.example.com

[datacenter:children]
datacenter1
datacenter2

# 不建议在inventory清单中指定地址给
[new]
192.168.1.1
192.168.1.2

1.2 间接指向ip

不建议在inventory中写ip地址,不清晰,可以通过如下方式

[student@workstation mmx]$ mkdir host_vars
[student@workstation mmx]$ mkdir group_vars
[student@workstation mmx]$ cd host_vars/
[student@workstation host_vars]$ ls
[student@workstation host_vars]$ touch mmx1
[student@workstation host_vars]$ touch mmx2
# 通过在主机组内定义变量,指定ip地址
[student@workstation host_vars]$ echo ansible_host: 192.168.1.1 > mmx1
[student@workstation host_vars]$ echo ansible_host: 192.168.1.2 > mmx2
[student@workstation mmx]$ cat inventory
...
[new]
# 192.168.1.1
# 192.168.1.2
mmx1
mmx2
# 亲测可用
[student@workstation mmx]$ ansible mmx1 -m ping
mmx1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}

1.3 指定hosts的几种方式

web.example.com
data.example.com

[lab]
labhost1.example.com
labhost2.example.com

[test]
test1.example.com
test2.example.com

[datacenter1]
labhost1.example.com
test1.example.com

[datacenter2]
labhost2.example.com
test2.example.com

[datacenter:children]
datacenter1
datacenter2

[new]
192.168.1.1
192.168.1.2
host取值 说明
lab 指定单一主机组(lab)
all 指定所有主机组
ungrouped 指定不属于任何组主机(web.example.com,data.example.com)
* 相当于all
!lab 除了lab组之外所有主机
192.168.1.* 网段192.168.1.开头
datacenter* 以datacenter开头
lab,test 包含lab和test
lab,data* 包含lab和data*

1.4 与和或

符号 含义
& 与,两个都存在
, 或,存在一个以上
# lab和datacenter1的交集
---
- hosts: lab,&datacenter1
...(labhost1.example.com)

# 不包括test2.example.com这个主机
---
- hosts: datacenter,!test2.example.com
...(labhost1.example.com,test1.example.com,labhost2.example.com)

1.5 选择主机or主机组练习

1.5.1 题目要求

  1. 查看inventory1

  2. 查看inventroy2

  3. 使用ad hoc 执行练习:

    1. 使用ad hoc命令加参数--list-hosts查看db1中的主机
    2. 使用ad hoc命令加参数--list-hosts查看172.25.252.44中的主机
    3. 使用ad hoc命令加参数--list-hosts查看inventory中的所有主机
    4. 使用ad hoc命令加参数--list-hosts查看“*.example.com”中的所有主机
    5. 使用ad hoc命令加参数--list-hosts查看inventory且没有“*.lab.example.com"中的主机
    6. 使用ad hoc命令加参数--list-hosts查看三个主机lb1.lab.example.com,s1.lab.example.com,db1.example.com中的主机
    7. 使用ad hoc命令加参数--list-hosts查看”172.25.*‘的主机
    8. 使用ad hoc命令加参数--list-hosts查看“s*"中的所有主机
    9. 使用ad hoc命令加参数--list-hosts查看prod,172*,中的所有主机
    10. 使用ad hoc命令加参数--list-hosts查看在db和lodon两者都存在的主机
    11. 在playbook下填写london,使用-i参数inventory2执行playbook
    12. 在playbook下填写europe,使用-i参数inventory2执行playbook
    13. 在playbook下填写ungrouped,使用-i参数inventory2执行playbook

1.5.2 练习

[student@workstation projects-host]$ cat inventory2
srv1.example.com
srv2.example.com
s1.lab.example.com
s2.lab.example.com

[web]
jupiter.lab.example.com
saturn.example.com

[db]
db1.example.com
db2.example.com
db3.example.com

[lb]
lb1.lab.example.com
lb2.lab.example.com

[boston]
db1.example.com
jupiter.lab.example.com
lb2.lab.example.com

[london]
db2.example.com
db3.example.com
file1.lab.example.com
lb1.lab.example.com

[dev]
web1.lab.example.com
db3.example.com

[stage]
file2.example.com
db2.example.com

[prod]
lb2.lab.example.com
db1.example.com
jupiter.lab.example.com

[function:children]
web
db
lb
city

[city:children]
boston
london
environments

[environments:children]
dev
stage
prod
new

[new]
172.25.252.23
172.25.252.44
172.25.252.32

[student@workstation projects-host]$ cat inventory2
workstation.lab.example.com

[london]
servera.lab.example.com

[berlin]
serverb.lab.example.com

[tokyo]
serverc.lab.example.com

[atlanta]
serverd.lab.example.com

[europe:children]
london
berlin
# 使用ad hoc命令加参数--list-hosts查看db1中的主机
[student@workstation projects-host]$ ansible db1.example.com -i inventory1 --list-hosts
  hosts (1):
    db1.example.com
# 使用ad hoc命令加参数--list-hosts查看172.25.252.44中的主机
[student@workstation projects-host]$ ansible 172.25.252.44 -i inventory1 --list-hosts
  hosts (1):
    172.25.252.44
# 使用ad hoc命令加参数--list-hosts查看inventory中的所有主机
[student@workstation projects-host]$ ansible all -i inventory1  --list-hosts
  hosts (17):
    srv1.example.com
    srv2.example.com
    s1.lab.example.com
    s2.lab.example.com
    jupiter.lab.example.com
    saturn.example.com
    db1.example.com
    db2.example.com
    db3.example.com
    lb1.lab.example.com
    lb2.lab.example.com
    file1.lab.example.com
    web1.lab.example.com
    file2.example.com
    172.25.252.23
    172.25.252.44
    172.25.252.32
#使用ad hoc命令加参数--list-hosts查看“*.example.com”中的所有主机
[student@workstation projects-host]$ ansible '*.example.com' -i inventory1 --list-hosts
  hosts (14):
    srv1.example.com
    srv2.example.com
    s1.lab.example.com
    s2.lab.example.com
    jupiter.lab.example.com
    saturn.example.com
    db1.example.com
    db2.example.com
    db3.example.com
    lb1.lab.example.com
    lb2.lab.example.com
    file1.lab.example.com
    web1.lab.example.com
    file2.example.com
# 使用ad hoc命令加参数--list-hosts查看inventory且没有“*.lab.example.com"中的主机
[student@workstation projects-host]$ ansible '*.example.com, !*.lab.example.com' -i inventory1 --list-hosts
  hosts (7):
    srv1.example.com
    srv2.example.com
    saturn.example.com
    db1.example.com
    db2.example.com
    db3.example.com
    file2.example.com
# 使用ad hoc命令加参数--list-hosts查看三个主机lb1.lab.example.com,s1.lab.example.com,db1.example.com中的主机
[student@workstation projects-host]$ ansible lb1.lab.example.com,s1.lab.example.com,db1.example.com -i inventory1 --list-hosts
  hosts (3):
    lb1.lab.example.com
    s1.lab.example.com
    db1.example.com

# 使用ad hoc命令加参数--list-hosts查看”172.25.*‘的主机
[student@workstation projects-host]$ ansible '172.25.*' -i inventory1 --list-hosts
  hosts (3):
    172.25.252.23
    172.25.252.44
    172.25.252.32
# 使用ad hoc命令加参数--list-hosts查看“s*"中的所有主机
[student@workstation projects-host]$ ansible 's*' -i inventory1 --list-hosts
  hosts (7):
    file2.example.com
    db2.example.com
    srv1.example.com
    srv2.example.com
    s1.lab.example.com
    s2.lab.example.com
    saturn.example.com
# 使用ad hoc命令加参数--list-hosts查看prod,172*,中的所有主机
[student@workstation projects-host]$ ansible 'prod,172.*,*lab*' -i inventory1 --list-hosts
  hosts (11):
    lb2.lab.example.com
    db1.example.com
    jupiter.lab.example.com
    172.25.252.23
    172.25.252.44
    172.25.252.32
    s1.lab.example.com
    s2.lab.example.com
    lb1.lab.example.com
    file1.lab.example.com
    web1.lab.example.com
# 使用ad hoc命令加参数--list-hosts查看在db和lodon两者都存在的主机
[student@workstation projects-host]$ ansible 'db,&london' -i inventory1 --list-hosts
  hosts (2):
    db2.example.com
    db3.example.com
# 在playbook下填写london,使用-i参数inventory2执行playbook
[student@workstation projects-host]$ vim playbook.yml
[student@workstation projects-host]$ cat playbook.yml
---
- name: Resolve host patterns
  hosts: london
  tasks:
    - name: Display managed host name
      debug:
        msg: "{{inventory_hostname}}"
[student@workstation projects-host]$ ansible-playbook -i inventory2 playbook.yml
# 在playbook下填写europe,使用-i参数inventory2执行playbook
[student@workstation projects-host]$ cat playbook.yml
---
- name: Resolve host patterns
  hosts: europe
  tasks:
    - name: Display managed host name
      debug:
        msg: "{{inventory_hostname}}"
[student@workstation projects-host]$ ansible-playbook playbook.yml -i inventory2
# 在playbook下填写ungrouped,使用-i参数inventory2执行playbook
[student@workstation projects-host]$ cat playbook.yml
---
- name: Resolve host patterns
  hosts: ungrouped
  tasks:
    - name: Display managed host name
      debug:
        msg: "{{inventory_hostname}}"
[student@workstation projects-host]$ ansible-playbook playbook.yml -i inventory2

2、 管理动态inventory文件

静态清单文件在一个笔记大型的项目中,无法准确的判断管理节点那些是在线的,那些不存在,使用动态清单文件管理host,可以很方便的解决这一问题

2.1 一些提供动态inventory接口的平台

  1. OpenStack平台
  2. 亚马逊AWS
  3. 虚拟化平台(oVirt,VMware等)
  4. OpenShift
  5. 红帽卫星
  6. 主机提供者

2.2 动态的Inventroy文件

一个静态inventroy文件在底层调用的时候会转化为JSON格式,如果要编写动态inventory文件,必须是JSON格式的

[student@workstation control-flow]$ cat inventory
[database_dev]
servera.lab.example.com

[database_prod]
serverb.lab.example.com
[student@workstation control-flow]$ ansible-inventory -i inventory --list
{
    "_meta": {
        "hostvars": {
            "servera.lab.example.com": {},
            "serverb.lab.example.com": {}
        }
    },
    "all": {
        "children": [
            "database_dev",
            "database_prod",
            "ungrouped"
        ]
    },
    "database_dev": {
        "hosts": [
            "servera.lab.example.com"
        ]
    },
    "database_prod": {
        "hosts": [
            "serverb.lab.example.com"
        ]
    }
}

可以通过执行脚本,返回JSON数据,执行时必须能使用--list参数,可选项: 主机变量

动态inventory中最好不要主机组名和主机名重名,如果重名了,需要在清单文件开头加入一个空的主机组名,以示区分

2.3 动态inventory文件练习

2.3.1 题目要求

  1. 开启实验环境
  2. 进入目录查看,创建inventory目录,下载动态inventroy文件
    1. 下载http://materials.example.com/labs/projects-inventory/inventorya.py
    2. 下载http://materials.example.com/labs/projects-inventory/inventoryw.py
  3. 通过执行XX.py list方式查看主机或主机组
  4. 加入一条静态inventory清单,文件名hosts
    1. 定义一个webservers组,确保执行的时候不会报错
    2. 定义一个servers组,他的子组是webservers

2.3.2 练习

[student@workstation ~]$ lab projects-inventory start

Setting up workstation for lab exercise work:

 · Verifying Ansible installation..............................  SUCCESS
 · Creating working directory..................................  SUCCESS
 · Deploying ansible.cfg.......................................  SUCCESS

[student@workstation ~]$ cd projects-inventory/
[student@workstation projects-inventory]$ ls
ansible.cfg
[student@workstation projects-inventory]$ cat ansible.cfg
[defaults]
inventory = inventory
[student@workstation projects-inventory]$ mkdir inventory
[student@workstation projects-inventory]$ cd inventory/
[student@workstation inventory]$ wget http://materials.example.com/labs/projects-inventory/inventorya.py
[student@workstation inventory]$ wget http://materials.example.com/labs/projects-inventory/inventoryw.py
[student@workstation inventory]$ ls
inventorya.py  inventoryw.py
# 动态inventory写法,python方式
[student@workstation inventory]$ cat inventorya.py
#!/usr/bin/python3

from subprocess import Popen,PIPE
import sys
import json

result = {}
# 主机组
result['webservers'] = {}
# 主机
result['webservers']['hosts'] = []
# 变量
result['webservers']['vars'] = {}

# Popen函数主要用来执行linux命令,调用/etc/hosts
'''
[root@workstation ~]# cat  /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

172.25.254.254  classroom.example.com classroom
172.25.254.254  content.example.com content
172.25.254.254  materials.example.com materials
### rht-vm-hosts file listing the entries to be appended to /etc/hosts
#
172.25.250.9    workstation.lab.example.com      workstation
172.25.250.10   servera.lab.example.com servera
172.25.250.11   serverb.lab.example.com serverb
172.25.250.12   serverc.lab.example.com serverc
172.25.250.13   serverd.lab.example.com serverd
172.25.250.254  bastion.lab.example.com bastion
'''
pipe = Popen(['getent', 'hosts'], stdout=PIPE, universal_newlines=True)

for line in pipe.stdout.readlines():
   # 切割字符串
   s = line.split()
   '''
   如果是以servera开头,则是:
   		servera.lab.example.com
   如果是以server开头,则是:
       servera.lab.example.com
		serverb.lab.example.com
		serverc.lab.example.com
		serverd.lab.example.com
   ''' 
   if s[1].startswith('servera'):
      # 在 result['webservers']['hosts']加入一个主机
      result['webservers']['hosts'].append(s[1])

# 执行脚本输出--list参数,则会执行json.dumps(result)
if len(sys.argv) == 2 and sys.argv[1] == '--list':
    print(json.dumps(result))
# 执行脚本输出--list参数,则会执行json.dumps(result)
elif len(sys.argv) == 3 and sys.argv[1] == '--host':
    print(json.dumps({}))
else:
    # 否则输入如下信息
    print("Requires an argument, please use --list or --host <host>")
[student@workstation inventory]$ cat inventoryw.py
#!/usr/bin/python3

from subprocess import Popen,PIPE
import sys
import json

result = {}
result['all'] = {}

pipe = Popen(['getent', 'hosts'], stdout=PIPE, universal_newlines=True)

result['all']['hosts'] = []
for line in pipe.stdout.readlines():
   s = line.split()
   if s[1].startswith('workstation'):
      result['all']['hosts'].append(s[1])

result['all']['vars'] = {}

if len(sys.argv) == 2 and sys.argv[1] == '--list':
    print(json.dumps(result))
elif len(sys.argv) == 3 and sys.argv[1] == '--host':
    print(json.dumps({}))
else:
    print("Requires an argument, please use --list or --host <host>")
# 赋予可执行权限
[student@workstation inventory]$ chmod +x inventory*
# 通过执行python,可以得出定义了webservers组servera和不属于组的workstation
[student@workstation inventory]$ ./inventorya.py --list
{"webservers": {"hosts": ["servera.lab.example.com"], "vars": {}}}
[student@workstation inventory]$ ./inventoryw.py --list
{"all": {"hosts": ["workstation.lab.example.com"], "vars": {}}}
[student@workstation projects-inventory]$ ansible webservers --list-hosts
  hosts (1):
    servera.lab.example.com
[student@workstation projects-inventory]$ ansible ungrouped --list-hosts
  hosts (1):
    workstation.lab.example.com
[student@workstation projects-inventory]$ cat hosts
# 动态清单中有webservers组,在文件上方定义一个这样的组,不会报错
[webservers]

[servers:children]
webservers

3、 多线程优化

3.1 指定任务使用cpu数

forks:一次处理被管理主机数量,默认forks为5

1、 可以使用 ansible-config list | grep -i forks,查看forks使用方式

[student@workstation projects-inventory]$ ansible-config list | grep -i forks
DEFAULT_FORKS:
  description: Maximum number of forks Ansible will use to execute tasks on target
  - {name: ANSIBLE_FORKS}
  - {key: forks, section: defaults}
  name: Number of task forks

2、 指定forks=1,查看运行效果

# 使用forks,使用n个cpu来执行,forks取决于本机cpu数量
[student@workstation projects-inventory]$ cat ansible.cfg
[defaults]
inventory = inventory
forks = 1
[student@workstation projects-inventory]$ cat install.yml
---
- name: install software
  hosts: all
  vars:
          packages:
                  - httpd
                  - ftp
  remote_user: root
  tasks:
          - name: install software
            yum:
                    name: "{{ item }}"
                    state: present
            loop: "{{ packages }}"
# 此时发现一次运行一个任务,然后运行下一个任务……
[student@workstation projects-inventory]$ ansible-playbook install.yml

PLAY [install software] *********************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************
ok: [workstation.lab.example.com]
ok: [servera.lab.example.com]
ok: [serverb.lab.example.com]
ok: [serverc.lab.example.com]
ok: [serverd.lab.example.com]

TASK [install software] *********************************************************************************************************************************************************************************************************************************
changed: [workstation.lab.example.com] => (item=httpd)
changed: [workstation.lab.example.com] => (item=ftp)
changed: [servera.lab.example.com] => (item=httpd)
changed: [servera.lab.example.com] => (item=ftp)
changed: [serverb.lab.example.com] => (item=httpd)
changed: [serverb.lab.example.com] => (item=ftp)
changed: [serverc.lab.example.com] => (item=httpd)
changed: [serverc.lab.example.com] => (item=ftp)
changed: [serverd.lab.example.com] => (item=httpd)
changed: [serverd.lab.example.com] => (item=ftp)

PLAY RECAP **********************************************************************************************************************************************************************************************************************************************
servera.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverb.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverc.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverd.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
workstation.lab.example.com : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

3.2 指定一次执行任务数

serial:指定一次执行多少个任务,写在playbook里面

# 指定forks为4
[student@workstation projects-inventory]$ cat ansible.cfg
[defaults]
inventory = inventory
forks = 4

# 指定一次执行2个task
[student@workstation projects-inventory]$ cat install.yml
---
- name: install software
  hosts: all
  vars:
          packages:
                  - httpd
                  - ftp
  remote_user: root
  serial: 2
  tasks:
          - name: install software
            yum:
                    name: "{{ item }}"
                    state: present
            loop: "{{ packages }}"
# 发现运行的时候,每次运行两个任务
[student@workstation projects-inventory]$ ansible-playbook install.yml

PLAY [install software] *********************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************
ok: [servera.lab.example.com]
ok: [workstation.lab.example.com]

TASK [install software] *********************************************************************************************************************************************************************************************************************************
changed: [servera.lab.example.com] => (item=httpd)
changed: [workstation.lab.example.com] => (item=httpd)
changed: [servera.lab.example.com] => (item=ftp)
changed: [workstation.lab.example.com] => (item=ftp)

PLAY [install software] *********************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com]
ok: [serverc.lab.example.com]

TASK [install software] *********************************************************************************************************************************************************************************************************************************
changed: [serverb.lab.example.com] => (item=httpd)
changed: [serverc.lab.example.com] => (item=httpd)
changed: [serverb.lab.example.com] => (item=ftp)
changed: [serverc.lab.example.com] => (item=ftp)

PLAY [install software] *********************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************
ok: [serverd.lab.example.com]

TASK [install software] *********************************************************************************************************************************************************************************************************************************
changed: [serverd.lab.example.com] => (item=httpd)
changed: [serverd.lab.example.com] => (item=ftp)

PLAY RECAP **********************************************************************************************************************************************************************************************************************************************
servera.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverb.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverc.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverd.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
workstation.lab.example.com : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

3.3 多线程优化练习

3.3.1 题目要求

  1. 开启实验环境
  2. 环境中有playbook.yml和remove_apache.yml用于测试
    1. playbook.yml安装软件包,remove_apache.yml卸载软件包
    2. ansible.cfg文件中有参数:forks=4,决定每次使用cpu数量
    3. 在plyabook中加入serial:X,决定一次执行任务数
    4. 使用time测试运行时间

3.3.2 练习

[student@workstation ~]$ lab projects-parallelism start

Setting up workstation for lab exercise work:

 · Verifying Ansible installation..............................  SUCCESS
 · Creating working directory..................................  SUCCESS
 · Deploying ansible.cfg.......................................  SUCCESS
 · Deploying Ansible inventory.................................  SUCCESS
 · Deploying playbook.yml playbook.............................  SUCCESS
 · Deploying remove_apache.yml playbook........................  SUCCESS
 · Remove apache...............................................  SUCCESS
 
[student@workstation ~]$ cd projects-parallelism/
[student@workstation projects-parallelism]$ ls
ansible.cfg  inventory  playbook.yml  remove_apache.yml
[student@workstation projects-parallelism]$ cat ansible.cfg
[defaults]
inventory=inventory
remote_user=devops
forks=4

[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False

[student@workstation projects-parallelism]$ cat playbook.yml
---
- name: Update web server
  hosts: webservers
  tasks:
    - name: Latest version of apache installed
      yum:
        name: httpd
        state: latest
      notify:
        - Restart apache

  handlers:
    - name: Restart apache
      service:
        name: httpd
        enabled: yes
        state: restarted
        
[student@workstation projects-parallelism]$ cat remove_apache.yml
---
- hosts: webservers
  tasks:
    - service:
        name: httpd
        enabled: no
        state: stopped
    - yum:
        name: httpd
        state: absent
# 使用force=4,查看playbook运行时间
[student@workstation projects-parallelism]$ time ansible-playbook playbook.yml
...
real    0m4.426s
user    0m1.689s
sys     0m0.503s
...

# 将force改为1,查看playbook运行时间
...
real    0m12.090s
user    0m1.870s
sys     0m0.570s
...
# 将force设置为4,serial设置为3,查看playbook运行时间
[student@workstation projects-parallelism]$ time ansible-playbook playbook.yml
...
real    0m7.193s
user    0m1.650s
sys     0m0.567s
...
# 将force设置为2,serial设置为2,查看playbook运行时间
[student@workstation projects-parallelism]$ time ansible-playbook playbook.yml
...
real    0m7.130s
user    0m1.687s
sys     0m0.538s
...

4、 包含和导入

对于一个比较大型的项目,不可避免会出现playbook会写的很长,可以通过include或者import的方式减少playbook文件的大小

4.1 使用import_playbook参数

将其他位置的playbook直接导入到这个playbook中来

特别不灵活,不建议使用

[student@workstation control-flow]$ cat web.yml
---
- name: install httpd
  hosts: all
  tasks:
          - name: install httpd
            yum:
                    name: httpd
                    state: latest
[student@workstation control-flow]$ cat new.yml
---
- name: install httpd
  import_playbook: web.yml
[student@workstation control-flow]$ ansible-playbook new.yml

PLAY [install httpd] ************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com]
ok: [servera.lab.example.com]

TASK [install httpd] ************************************************************************************************************************************************************************************************************************************
changed: [servera.lab.example.com]
changed: [serverb.lab.example.com]

PLAY RECAP **********************************************************************************************************************************************************************************************************************************************
servera.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverb.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

4.2 使用import_tasks参数(静态导入)

通过写好task任务,调用tasks的方式来执行playbook

  1. 不能使用when
  2. 不能使用loop
  3. 可以使用变量
[student@workstation control-flow]$ cat tasks.yml
- name: install httpd
  yum:
          name: httpd
          state: latest
- name: Start service httpd, if not started
  service:
          name: httpd
          state: started
          enabled: 1
[student@workstation control-flow]$ cat new.yml
---
- name: install httpd
  hosts: all
  tasks:
          - name: import tasks
            import_tasks: tasks.yml
[student@workstation control-flow]$ ansible-playbook new.yml

PLAY [install httpd] ************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************
ok: [servera.lab.example.com]
ok: [serverb.lab.example.com]

TASK [install httpd] ************************************************************************************************************************************************************************************************************************************
ok: [servera.lab.example.com]
ok: [serverb.lab.example.com]

TASK [Start service httpd, if not started] **************************************************************************************************************************************************************************************************************
changed: [servera.lab.example.com]
changed: [serverb.lab.example.com]

PLAY RECAP **********************************************************************************************************************************************************************************************************************************************
servera.lab.example.com    : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverb.lab.example.com    : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

4.3 使用inclue_tasks参数(动态导入)

作用和import_tasks差不多

  1. 可以使用when做判断
  2. 可以使用ansible-playbook --list-tasks列出tasks
  3. 可以使用--start-at-tast进行单步调试
  4. 不能使用notify指定标记运行handlers
[student@workstation control-flow]$ cat tasks.yml
- name: install httpd
  yum:
          name: httpd
          state: latest
- name: Start service httpd, if not started
  service:
          name: httpd
          state: started
          enabled: 1
[student@workstation control-flow]$ cat new.yml
---
- name: install httpd
  hosts: all
  tasks:
          - name: include tasks

4.4 import和include区别

  1. 使用import相当于导入
[student@workstation control-flow]$ ansible-playbook new.yml --list-tasks

playbook: new.yml

  play #1 (all): install httpd  TAGS: []
    tasks:
      install httpd     TAGS: []
      Start service httpd, if not started       TAGS: []
  1. include相当于包括
[student@workstation control-flow]$ ansible-playbook new.yml --list-tasks

playbook: new.yml

  play #1 (all): install httpd  TAGS: []
    tasks:
      include tasks     TAGS: []

4.5 将task参数改为变量形式

[student@workstation control-flow]$ cat vars.yml
---
package: httpd
package_state: latest
service: httpd
state: started
[student@workstation control-flow]$ cat tasks.yml
- name: install {{ package }}
  yum:
          name: "{{ package }}"
          state: "{{ package_state }}"
- name: Start {{ service }}
  service:
          name: "{{ service }}"
          state: "{{ state }}"
          enabled: 1
[student@workstation control-flow]$ cat new.yml
---
- name: install software
  hosts: all
  vars_files:
          - vars.yml
  tasks:
          - name: include tasks
            include_tasks: tasks.yml
[student@workstation control-flow]$ ansible-playbook new.yml

PLAY [install software] ********************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com]
ok: [servera.lab.example.com]

TASK [include tasks] ***********************************************************************************************************************************************************************************************************
included: /home/student/control-flow/tasks.yml for servera.lab.example.com, serverb.lab.example.com

TASK [install httpd] ***********************************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com]
ok: [servera.lab.example.com]

TASK [Start httpd] *************************************************************************************************************************************************************************************************************
ok: [servera.lab.example.com]
ok: [serverb.lab.example.com]

PLAY RECAP *********************************************************************************************************************************************************************************************************************
servera.lab.example.com    : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverb.lab.example.com    : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

4.6 include和import练习

4.6.1 题目要求

  1. 开启实验环境
  2. 查看tasks和plays目录下文件
    1. tasks目录下文件主要用于开启web服务,放行防火墙
    2. plays目录下文件主要用于测试
  3. 创建playbook文件,根据tasks中提示变量,完成实验
  4. 结束实验

4.6.2 实验

[student@workstation ~]$ lab projects-file start

Setting up workstation for lab exercise work:

 · Verifying Ansible installation..............................  SUCCESS
 · Creating working directory..................................  SUCCESS
 · Deploying ansible.cfg.......................................  SUCCESS
 · Deploying Ansible inventory.................................  SUCCESS
 · Creating task directory.....................................  SUCCESS
 · Deploying environment task files............................  SUCCESS
 · Deploying firewall task files...............................  SUCCESS
 · Deploying placeholder task files............................  SUCCESS
 · Creating play directory.....................................  SUCCESS
 · Deploying play files........................................  SUCCESS

[student@workstation ~]$ tree projects-file/
projects-file/
├── ansible.cfg
├── inventory
├── plays
│   └── test.yml
└── tasks
    ├── environment.yml
    ├── firewall.yml
    └── placeholder.yml


[student@workstation ~]$ cd projects-file/
[student@workstation projects-file]$ ls
ansible.cfg  inventory  plays  tasks

[student@workstation projects-file]$ cat ansible.cfg
[defaults]
inventory=inventory
remote_user=devops

[privilege_escalation]
become=True
become_method=sudo
beome_user=root
become_ask_pass=False
[student@workstation projects-file]$ cat inventory
servera.lab.example.com
[student@workstation projects-file]$ cat tasks/
environment.yml  firewall.yml     placeholder.yml
[student@workstation projects-file]$ ls plays/
test.yml

# 查看tasks中定制好的task
[student@workstation projects-file]$ cat tasks/environment.yml
---
  - name: Install the {{ package }} package
    yum:
      name: "{{ package }}"
      state: latest
  - name: Start the {{ service }} service
    service:
      name: "{{ service }}"
      enabled: true
      state: started
[student@workstation projects-file]$ cat tasks/firewall.yml
---
  - name: Install the firewall
    yum:
      name: "{{ firewall_pkg }}"
      state: latest

  - name: Start the firewall
    service:
      state: started
      name: "{{ firewall_svc }}"
      enabled: true

  - name: Open the port for {{ rule }}
    firewalld:
      service: "{{ item }}"
      immediate: true
      permanent: true
      state: enabled
    loop: "{{ rule }}"
[student@workstation projects-file]$ cat tasks/placeholder.yml
---
  - name: Create placeholder file
    copy:
      content: "{{ ansible_facts['fqdn'] }} has been customized using Ansible.\n"
      dest: "{{ file }}"
[student@workstation projects-file]$ cat plays/test.yml
---
- name: Test web service
  hosts: localhost
  become: no
  tasks:
    - name: connect to internet web server
      uri:
        url: "{{ url }}"
        status_code: 200
# 根据上方预留变量,补足变量完成play
[student@workstation projects-file]$ cat playbook.yml
---
- name: configure web server
  hosts: servera.lab.example.com
  tasks:
          - name: 使用include environment
            include_tasks: tasks/environment.yml
            vars:
                    package: httpd
                    service: httpd
            when: ansible_facts['os_family'] == 'RedHat'
          - name: 配置防火墙
            import_tasks: tasks/firewall.yml
            vars:
                    firewall_pkg: firewalld
                    firewall_svc: firewalld
                    rule:
                            - http
                            - https
          - name: 创建主页
            import_tasks: tasks/placeholder.yml
            vars:
                    file: "/var/www/html/index.html"

- name: import_play file
  import_playbook: plays/test.yml
  vars:
          url: http://servera.lab.example.com
[student@workstation projects-file]$ ansible-playbook playbook.yml

PLAY [configure web server] ****************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************************************************
ok: [servera.lab.example.com]

TASK [使用include environment] ***************************************************************************************************************************************************************************************************
included: /home/student/projects-file/tasks/environment.yml for servera.lab.example.com

TASK [Install the httpd package] ***********************************************************************************************************************************************************************************************
ok: [servera.lab.example.com]

TASK [Start the httpd service] *************************************************************************************************************************************************************************************************
ok: [servera.lab.example.com]

TASK [Install the firewall] ****************************************************************************************************************************************************************************************************
ok: [servera.lab.example.com]

TASK [Start the firewall] ******************************************************************************************************************************************************************************************************
ok: [servera.lab.example.com]

TASK [Open the port for ['http', 'https']] *************************************************************************************************************************************************************************************
changed: [servera.lab.example.com] => (item=http)
changed: [servera.lab.example.com] => (item=https)

TASK [Create placeholder file] *************************************************************************************************************************************************************************************************
changed: [servera.lab.example.com]

PLAY [Test web service] ********************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [connect to internet web server] ******************************************************************************************************************************************************************************************
ok: [localhost]

PLAY RECAP *********************************************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
servera.lab.example.com    : ok=8    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

# 测试
[student@workstation projects-file]$ curl http://servera.lab.example.com
servera.lab.example.com has been customized using Ansible.

# 结束实验
[student@workstation projects-file]$ lab projects-file finish

Cleaning up the lab on servera:

 · Remove firewall configuration...............................  SUCCESS
 · Remove web content..........................................  SUCCESS
 · Remove httpd package........................................  SUCCESS

5、 综合实验

管理大项目

5.1 题目要求

  1. 开启实验环境
  2. 将playbook进行拆分
    1. 第1~3个tasks放入tasks/web_tasks.yml中,使用import_tasks方式导入
    2. 第4~6个tasks放入tasks/firewall_tasks.yml中,使用import_tasks方式导入
    3. 从tasks/web_tasks.yml和tasks/firewall_tasks.yml中抽取出install packages和enable services 放到新的tasks/install_and_enable.yml中,通过变量的方式,使用import_tasks方式导入
  3. 如果files/tune.conf发生变化,则会执行handlers任务,实现滚动更新功能,一次执行主机数为2(serial:2)
  4. 检查plyabook,执行playbook

5.2 练习

[student@workstation ~]$ lab projects-review start

Setting up workstation for lab exercise work:

 · Verifying Ansible installation..............................  SUCCESS
 · Creating working directory..................................  SUCCESS
 · Deploying ansible.cfg.......................................  SUCCESS
 · Creating inventory directory................................  SUCCESS
 · Deploying inventory script..................................  SUCCESS
 · Creating files directory....................................  SUCCESS
 · Deploying play files........................................  SUCCESS
 · Deploying playbook..........................................  SUCCESS
 
[student@workstation ~]$ cd projects-review/
[student@workstation projects-review]$ ls
ansible.cfg  files  inventory  playbook.yml

# 查看inventory动态清单文件
[student@workstation projects-review]$ cat inventory/inventory.py
#!/usr/bin/python3

from subprocess import Popen,PIPE
import sys
import json

result = {}
result['all'] = {}

pipe = Popen(['getent', 'hosts'], stdout=PIPE, universal_newlines=True)

result['all']['hosts'] = []
for line in pipe.stdout.readlines():
   s = line.split()
   if s[1].startswith(('w','s')):
      result['all']['hosts'].append(s[1])

result['all']['vars'] = {}

if len(sys.argv) == 2 and sys.argv[1] == '--list':
    print(json.dumps(result))
elif len(sys.argv) == 3 and sys.argv[1] == '--host':
    print(json.dumps({}))
else:
    print("Requires an argument, please use --list or --host <host>")
# 添加可执行权限,否则无法执行
[student@workstation projects-review]$ chmod +x inventory/inventory.py

[student@workstation projects-review]$ ansible-inventory --list
{
    "_meta": {
        "hostvars": {
            "servera.lab.example.com": {},
            "serverb.lab.example.com": {},
            "serverc.lab.example.com": {},
            "serverd.lab.example.com": {},
            "workstation.lab.example.com": {}
        }
    },
    "all": {
        "children": [
            "ungrouped"
        ]
    },
    "ungrouped": {
        "hosts": [
            "servera.lab.example.com",
            "serverb.lab.example.com",
            "serverc.lab.example.com",
            "serverd.lab.example.com",
            "workstation.lab.example.com"
        ]
    }
}
# 编写yum脚本
[student@workstation projects-review]$ cat playbook.yml
---
- name: Install and configure web service
  # 使用通配符
  hosts:
    - server*.lab.example.com
  serial: 2
  tasks:
  		  	# 使用import_tasks
          - name: start web service
            import_tasks: tasks/web_tasks.yml
			# 使用import_tasks
          - name: start firewalld service
            import_tasks: tasks/firewall_tasks.yml

  handlers:
    - name: restart httpd
      service:
        name: httpd
        state: restarted
[student@workstation projects-review]$ cat tasks/web_tasks.yml
- name: Install httpd
  # 使用import_tasks
  import_tasks: install_and_enable.yml
  vars:
          packages: httpd
          services: httpd

- name: Tuning configuration installed
  copy:
          src: files/tune.conf
          dest: /etc/httpd/conf.d/tune.conf
          owner: root
          group: root
          mode: 0644
  notify:
          - restart httpd

# 使用import_tasks
[student@workstation projects-review]$ cat tasks/firewall_tasks.yml
- name: Install firewalld
  import_tasks: install_and_enable.yml
  vars:
          packages: firewalld
          services: firewalld

- name: Open the port for http
  firewalld:
          service: http
          immediate: true
          permanent: true
          state: enabled

# 使用变量方式
[student@workstation projects-review]$ cat tasks/install_and_enable.yml
- name: Install {{ packages }}
  yum:
          name: "{{ packages }}"
          state: latest
- name: Enable and start the {{ services }}
  service:
          name: "{{ services }}"
          enabled: true
          state: started
[student@workstation projects-review]$ ansible-playbook playbook.yml

PLAY [Install and configure web service] *************************************************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com]
ok: [servera.lab.example.com]

TASK [Install httpd] *********************************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com]
ok: [servera.lab.example.com]

TASK [Enable and start the httpd] ********************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com]
ok: [servera.lab.example.com]

TASK [Tuning configuration installed] ****************************************************************************************************************************************************************************************
ok: [serverb.lab.example.com]
ok: [servera.lab.example.com]

TASK [Install firewalld] *****************************************************************************************************************************************************************************************************
ok: [servera.lab.example.com]
ok: [serverb.lab.example.com]

TASK [Enable and start the firewalld] ****************************************************************************************************************************************************************************************
ok: [servera.lab.example.com]
ok: [serverb.lab.example.com]

TASK [Open the port for http] ************************************************************************************************************************************************************************************************
changed: [servera.lab.example.com]
changed: [serverb.lab.example.com]

PLAY [Install and configure web service] *************************************************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************************************
ok: [serverd.lab.example.com]
ok: [serverc.lab.example.com]

TASK [Install httpd] *********************************************************************************************************************************************************************************************************
changed: [serverc.lab.example.com]
changed: [serverd.lab.example.com]

TASK [Enable and start the httpd] ********************************************************************************************************************************************************************************************
changed: [serverc.lab.example.com]
changed: [serverd.lab.example.com]

TASK [Tuning configuration installed] ****************************************************************************************************************************************************************************************
changed: [serverd.lab.example.com]
changed: [serverc.lab.example.com]

TASK [Install firewalld] *****************************************************************************************************************************************************************************************************
ok: [serverd.lab.example.com]
ok: [serverc.lab.example.com]

TASK [Enable and start the firewalld] ****************************************************************************************************************************************************************************************
ok: [serverc.lab.example.com]
ok: [serverd.lab.example.com]

TASK [Open the port for http] ************************************************************************************************************************************************************************************************
changed: [serverd.lab.example.com]
changed: [serverc.lab.example.com]

RUNNING HANDLER [restart httpd] **********************************************************************************************************************************************************************************************
changed: [serverd.lab.example.com]
changed: [serverc.lab.example.com]

PLAY RECAP *******************************************************************************************************************************************************************************************************************
servera.lab.example.com    : ok=7    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverb.lab.example.com    : ok=7    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverc.lab.example.com    : ok=8    changed=5    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
serverd.lab.example.com    : ok=8    changed=5    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

# 判断成绩
[student@workstation projects-review]$ lab projects-review grade

Grading the student's work on workstation:

 · Ensuring Ansible playbook is present........................  PASS
 · Ensuring web task file is present...........................  PASS
 · Ensuring firewall task file is present......................  PASS
 · Ensuring install_and_enable task file is present............  PASS
 · Ensuring dynamic inventory script is executable.............  PASS
 · Checking playbook has configured 'serial' directive.........  PASS

Grading the student's work on servera:

 · Checking packages
   · Checking firewalld........................................  PASS
   · Checking httpd............................................  PASS
 · Ensuring services are started
   · Checking httpd............................................  PASS
   · Checking firewalld........................................  PASS
   · Checking for Apache tune.conf.............................  PASS

 · Ensuring the web server is reachable........................  PASS

Grading the student's work on serverb:

 · Checking packages
   · Checking firewalld........................................  PASS
   · Checking httpd............................................  PASS
 · Ensuring services are started
   · Checking httpd............................................  PASS
   · Checking firewalld........................................  PASS
   · Checking for Apache tune.conf.............................  PASS

 · Ensuring the web server is reachable........................  PASS

Grading the student's work on serverc:

 · Checking packages
   · Checking firewalld........................................  PASS
   · Checking httpd............................................  PASS
 · Ensuring services are started
   · Checking httpd............................................  PASS
   · Checking firewalld........................................  PASS
   · Checking for Apache tune.conf.............................  PASS

 · Ensuring the web server is reachable........................  PASS

Grading the student's work on serverd:

 · Checking packages
   · Checking firewalld........................................  PASS
   · Checking httpd............................................  PASS
 · Ensuring services are started
   · Checking httpd............................................  PASS
   · Checking firewalld........................................  PASS
   · Checking for Apache tune.conf.............................  PASS

 · Ensuring the web server is reachable........................  PASS


Overall lab grade..............................................  PASS