Ansible服务

一、概述

Ansible服务官方网站

1. 概念

Ansible是基于Python开发的自动化运维软件工具,基于SSH远程管理服务实现以并行的方式对主机进行批量管理;

2. 功能组成

Ansible服务官方文档

  • ansible主机清单(Inventory)
  • ansible功能模块(Module)
  • ansible剧本编写(Playbook)

3. 主要功能

  • 实现批量系统操作配置
  • 实现批量软件服务部署
  • 实现批量分发数据文件
  • 实现批量采集系统信息

4. 特点

  • 管理端不需要启动服务程序(no server)
  • 管理端不需要编写配置文件(/etc/ansible/ansible.cfg)
  • 受控端不需要安装软件程序(libselinux-python)
  • 受控端不需要启动服务程序(no agent)
  • 服务程序管理操作模块众多(module)
  • 利用剧本编写可实现自动化(playbook)

5. 意义

  • 提高工作效率
  • 提高工作准确度
  • 减少维护成本
  • 减少重复性工作

二、ansible安装与配置

1. 安装ansible

step 01 管理端分发公钥至被管理端

分发公钥操作详见SSH服务章节

[root@ansible-manager ~]# yum install -y sshpass.x86_64 
Loaded plugins: fastestmirror
......
Complete!
[root@ansible-manager ~]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
......
[root@ansible-manager ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub -o StrictHostKeyChecking=no -p 22 root@10.0.0.15 
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
......
[root@ansible-manager ~]# ssh root@10.0.0.15
Last login: Tue Nov  9 13:29:52 2021 from 10.0.0.2
[root@web01 ~]# logout
Connection to 10.0.0.15 closed.
[root@ansible-manager ~]# for i in {16,17}; do sshpass -p 123456 ssh-copy-id -i ~/.ssh/id_rsa.pub -o StrictHostKeyChecking=no -p 22 root@10.0.0.$i &>/dev/null; done
[root@ansible-manager ~]# ssh root@10.0.0.16
Last login: Tue Nov  9 13:29:52 2021 from 10.0.0.2
[root@web02 ~]# logout
Connection to 10.0.0.16 closed.
[root@ansible-manager ~]# ssh root@10.0.0.17
Last login: Tue Nov  9 13:29:51 2021 from 10.0.0.2
[root@web03 ~]# logout
Connection to 10.0.0.17 closed.

step 02 管理端安装ansible服务

ansible依赖EPEL源

[root@ansible-manager ~]# yum install -y ansible
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
......
Complete!
[root@ansible-manager ~]# rpm -qa ansible
ansible-2.9.25-1.el7.noarch

2. ansible核心文件

[root@ansible-manager ~]# rpm -ql ansible | grep /etc/ansible/
/etc/ansible/ansible.cfg
/etc/ansible/hosts
/etc/ansible/roles
  • /etc/ansible/ansibel.cfg 默认配置文件
  • /etc/ansible/hosts 主机清单(Inventory)
  • /etc/ansible/roles 角色目录

3. ansible核心命令

/usr/bin/anisble

ansible 主机信息1,主机信息2,... 批量管理主机执行同一任务

-m 模块名称 指定调用的功能模块
-a "指令" 指定完成的指令信息
-i /目录/文件名称 指定临时调用主机清单文件
--version 查看ansible版本

注意:
1. ansible命令后面指定的主机信息,必须添加到主机清单中;否则无法管理成功;
2. 主机信息可以使用all用以管理所有主机;
# 未添加主机清单
[root@ansible-manager ~]# ansible 10.0.0.15 -m command -a hostname
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit
localhost does not match 'all'
[WARNING]: Could not match supplied host pattern, ignoring: 10.0.0.15

# 管理特定一台主机
[root@ansible-manager ~]# ansible 10.0.0.15 -m command -a hostname
10.0.0.15 | CHANGED | rc=0 >>
web01
/usr/bin/anisble-playbook

ansible-playbook 剧本名称 执行ansible剧本

--syntax-check 检查剧本语法
-C 模拟执行剧本(不会对远程主机造成更改)
-e 变量名=值 指定变量执行剧本
-t 标记点 仅执行指定标记的模块(项目)
--skip-tags=标记点 运行剧本并跳过标记点的模块

ansible-doc #查看ansible本机帮助文档
ansible-doc 模块名称 #查看ansible指定模块的具体用法

-l 查看ansible所有模块信息
-s 模块名称 查看指定模块详细说明

[root@ansible-manager ~]# ansible-doc -l | wc -l
3387
[root@ansible-manager ~]# ansible-doc -l
fortios_router_community_list                                 Configure community lists in Fortin...
azure_rm_devtestlab_info                                      Get Azure DevTest Lab facts        
ecs_taskdefinition                                            register a task definition in ecs  
avi_alertscriptconfig                                         Module for setup of AlertScriptConf...
......

4. 配置主机清单文件

方式一:简单配置

/etc/ansible/hosts
主机IP地址
[root@ansible-manager ~]# grep -Ev '^$|#' /etc/ansible/hosts 
10.0.0.15
10.0.0.16
10.0.0.17
[root@ansible-manager ~]# ansible all -m command -a "hostname"
10.0.0.15 | CHANGED | rc=0 >>
web01
10.0.0.17 | CHANGED | rc=0 >>
web03
10.0.0.16 | CHANGED | rc=0 >>
web02
[root@ansible-manager ~]# ansible 10.0.0.15,10.0.0.16 -m command -a "hostname"
10.0.0.15 | CHANGED | rc=0 >>
web01
10.0.0.16 | CHANGED | rc=0 >>
web02

方式二:分组配置

/etc/ansible/hosts
[组名1]
主机IP地址1
主机IP地址2
[组名2]
主机IP地址1
......
[root@ansible-manager ~]# grep -Ev '^$|#' /etc/ansible/hosts 
[web]
10.0.0.15
10.0.0.16
[db]
10.0.0.17
[root@ansible-manager ~]# ansible web -m command -a "hostname"
10.0.0.16 | CHANGED | rc=0 >>
web02
10.0.0.15 | CHANGED | rc=0 >>
web01
[root@ansible-manager ~]# ansible db -m command -a "hostname"
10.0.0.17 | CHANGED | rc=0 >>
web03

方式三:符号匹配信息配置

/etc/ansible/hosts
主机地址[起始:结束]
主机名称[起始:结束]
[root@ansible-manager ~]# grep -Ev '^$|#' /etc/ansible/hosts 
[web]
10.0.0.[15:18]
[root@ansible-manager ~]# ansible web -m command -a "hostname"
10.0.0.16 | CHANGED | rc=0 >>
web02
10.0.0.15 | CHANGED | rc=0 >>
web01
10.0.0.17 | CHANGED | rc=0 >>
web03

#因为不存在10.0.0.18主机,所以执行报错;
10.0.0.18 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: ssh: connect to host 10.0.0.18 port 22: No route to host", 
    "unreachable": true
}

方式四:特殊变量信息配置

/etc/ansible/hosts
主机地址 参数名1=参数值 参数名2=参数值 ...
参数必须是ansible自身支持的参数,不支持自定义参数;
ansible内置参数
[root@ansible-manager ~]# grep -Ev '^$|#' /etc/ansible/hosts 
[web]
10.0.0.15
[data]
10.0.0.16
[db]
10.0.0.17 ansible_user=root ansible_password=123456 ansible_port=22 
[root@ansible-manager ~]# ssh root@10.0.0.17 'rm -rf /root/.ssh/authorized_keys'
[root@ansible-manager ~]# ssh root@10.0.0.16 'rm -rf /root/.ssh/authorized_keys'
[root@ansible-manager ~]# ssh root@10.0.0.16
root@10.0.0.16's password: 

[root@ansible-manager ~]# ssh root@10.0.0.17
root@10.0.0.17's password: 

[root@ansible-manager ~]# ansible data -m command -a "hostname"
10.0.0.16 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: Permission denied (publickey,password).", 
    "unreachable": true
}
[root@ansible-manager ~]# ansible db -m command -a "hostname"
web03 | CHANGED | rc=0 >>
web03

利用变量参数,实现ansible用户身份切换
/etc/ansible/hosts
ansible_user=用户名 #指定登录用户名
ansible_password=用户名密码 #指定登录用户名密码
ansible_port=端口号 #指定SSH连接端口

ansible_become=yes #开启用户身份切换
ansible_become_method=su #指定转换方法为su(也可以是sudo)
ansible_become_user=root #指定切换用户名
ansible_become_pass=123456 #指定切换用户密码
[root@ansible-manager ~]# grep -Ev '^$|#' /etc/ansible/hosts 
[nfs:children]
nfs_server
nfs_client
[nfs_server]
10.0.0.15
[nfs_server:vars]
ansible_user=Young
ansible_password=123456
[nfs_client]
10.0.0.16
10.0.0.17
[root@ansible-manager /etc/ansible]# ansible nfs_server -m copy -a "content='testing txt' dest=/home/Young/test2.txt "
10.0.0.15 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "d77d1759eb57e64717a0d2e71a5df62e3ea2631c", 
    "dest": "/home/Young/test2.txt", 
    "gid": 1001, 
    "group": "Aspen", 
    "md5sum": "f5a2007be791b68e4d2fabadd41436fe", 
    "mode": "0644", 
    "owner": "Young", 
    "size": 11, 
    "src": "/home/Young/.ansible/tmp/ansible-tmp-1638318982.17-7865-240639660263401/source", 
    "state": "file", 
    "uid": 1001
[root@ansible-manager ~]# grep -Ev '^$|#' /etc/ansible/hosts 
[nfs:children]
nfs_server
nfs_client
[nfs_server]
10.0.0.15
[nfs_server:vars]
ansible_user=Young
ansible_password=123456
ansible_become=yes
ansible_become_method=su
ansible_become_user=root
ansible_become_pass=123456
[nfs_client]
10.0.0.16
10.0.0.17
[root@ansible-manager /etc/ansible]# ansible nfs_server -m copy -a "content='testing txt' dest=/home/Young/test.txt "
10.0.0.15 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "d77d1759eb57e64717a0d2e71a5df62e3ea2631c", 
    "dest": "/home/Young/test.txt", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "f5a2007be791b68e4d2fabadd41436fe", 
    "mode": "0644", 
    "owner": "root", 
    "size": 11, 
    "src": "/home/Young/.ansible/tmp/ansible-tmp-1638318875.0-7814-240027464307441/source", 
    "state": "file", 
    "uid": 0
}
[root@ansible-manager ~]# ansible nfs_server -a "ls -l"
10.0.0.15 | CHANGED | rc=0 >>
total 8
-rw-r--r-- 1 Young Aspen 11 Dec  1 08:36 test2.txt
-rw-r--r-- 1 root  root  11 Dec  1 08:34 test.txt

方式五:嵌入式配置

  • 嵌入子组
/etc/ansible/hosts
[父组名称:children]
组名1
组名2
......
[组名1]
主机IP地址1
主机IP地址2
[组名2]
主机IP地址1
......
[root@ansible-manager ~]# grep -Ev '^$|#' /etc/ansible/hosts 
[nfs:children]
nfs_server
nfs_client
[nfs_server]
10.0.0.15
[nfs_client]
10.0.0.16
10.0.0.17
[root@ansible-manager ~]# ansible nfs_server -m command -a "hostname"
10.0.0.15 | CHANGED | rc=0 >>
web01
[root@ansible-manager ~]# ansible nfs_client -m command -a "hostname"
10.0.0.17 | CHANGED | rc=0 >>
web03
10.0.0.16 | CHANGED | rc=0 >>
web02
[root@ansible-manager ~]# ansible nfs -m command -a "hostname"
10.0.0.16 | CHANGED | rc=0 >>
web02
10.0.0.15 | CHANGED | rc=0 >>
web01
10.0.0.17 | CHANGED | rc=0 >>
web03
  • 嵌入变量
嵌入式变量配置主机清单的方式,常与ansible的playbook配合使用;
/etc/ansible/hosts
[组名]
主机地址
[组名:vars]
变量名1=值
变量名2=值
......
[root@ansible-manager ~]# grep -Ev '^$|#' /etc/ansible/hosts 
[nfs:children]
nfs_server
nfs_client
[nfs_server]
10.0.0.15
[nfs_client]
10.0.0.16
10.0.0.17
[nfs_client:vars]
ansible_user=root
ansible_password=123456
ansible_port=22
[root@ansible-manager ~]# ssh root@10.0.0.16 "rm -rf /root/.ssh/authorized_keys"
[root@ansible-manager ~]# ssh root@10.0.0.17 "rm -rf /root/.ssh/authorized_keys"
[root@ansible-manager ~]# ssh root@10.0.0.17 
root@10.0.0.17's password: 

[root@ansible-manager ~]# ssh root@10.0.0.16
root@10.0.0.16's password: 

[root@ansible-manager ~]# ansible nfs_client -m command -a "hostname"
10.0.0.17 | CHANGED | rc=0 >>
web03
10.0.0.16 | CHANGED | rc=0 >>
web02
[root@ansible-manager ~]# grep -Ev '^$|#' /etc/ansible/hosts 
[nfs:children]
nfs_server
nfs_client
[nfs_server]
10.0.0.15
[nfs_client]
10.0.0.16
10.0.0.17
[root@ansible-manager ~]# ansible nfs_client -m command -a "hostname"
10.0.0.16 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: Permission denied (publickey,password).", 
    "unreachable": true
}
10.0.0.17 | UNREACHABLE! => {
    "changed": false, 
    "msg": "Failed to connect to the host via ssh: Permission denied (publickey,password).", 
    "unreachable": true
}

5. ansible执行返回结果字体颜色含义

  • 绿色:命令执行成功,并对远程主机进行任何修改;
  • 黄色:命令执行成功,并对远程主机进行修改(大部分情况);
  • 红色:命令执行失败;
  • 粉色:警告信息;一般是给出官方建议的操作方法;
  • 蓝色:显示命令或剧本的执行的过程;

三、功能模块

ansible功能模块介绍

ansible常用模块
command(默认模块), shell(万能模块), copy, fetch, file, script, yum, rpm, apt-get, pip, service, cron, user, mount, ping, setup, debug, mysql(相关), archive, unarchive

1. command模块

作用: 批量管理主机执行命令;

command模块局限性:该模块不能以Shell方式进行指令处理,因此变量参数不能识别
变量:如$HOME;
参数:如:"<", ">", "|", ";", "&" ...

语法:

ansible 主机地址 -m command -a "参数 命令"

核心参数:

  • chdir

    chdir=目录名称 #执行指令操作前进行目录切换;
    [root@ansible-manager ~]# ansible 10.0.0.15 -m command -a "chdir=/tmp pwd"
    10.0.0.15 | CHANGED | rc=0 >>
    /tmp
    [root@ansible-manager ~]# ansible 10.0.0.15 -m command -a "pwd"
    10.0.0.15 | CHANGED | rc=0 >>
    /root
  • creates

    creates=/目录/文件名称 #若creates文件存在,则跳过后续命令执行(文件存在即不执行)
    [root@ansible-manager ~]# ansible 10.0.0.15 -m command -a "creates=/root/anaconda-ks.cfg touch /root/testing.txt"
    10.0.0.15 | SUCCESS | rc=0 >>
    skipped, since /root/anaconda-ks.cfg exists
    [root@ansible-manager ~]# ansible 10.0.0.15 -m command -a "ls"
    10.0.0.15 | CHANGED | rc=0 >>
    anaconda-ks.cfg
    [root@ansible-manager ~]# ansible 10.0.0.15 -m command -a "creates=/root/testing.txt touch /root/testing.txt"
    [WARNING]: Consider using the file module with state=touch rather than running 'touch'.  If you need
    to use command because file is insufficient you can add 'warn: false' to this command task or set
    'command_warnings=False' in ansible.cfg to get rid of this message.
    10.0.0.15 | CHANGED | rc=0 >>
    
    [root@ansible-manager ~]# ansible 10.0.0.15 -m command -a "ls"
    10.0.0.15 | CHANGED | rc=0 >>
    anaconda-ks.cfg
    testing.txt
  • removes

    removes=/目录/文件名称 #若removes文件不存在,则跳过后续命令执行(文件存在即执行)
    [root@ansible-manager ~]# ansible 10.0.0.15 -m command -a "removes=/root/testing.txt rm -f anaconda-ks.cfg"
    [WARNING]: Consider using the file module with state=absent rather than running 'rm'.  If you need to
    use command because file is insufficient you can add 'warn: false' to this command task or set
    'command_warnings=False' in ansible.cfg to get rid of this message.
    10.0.0.15 | CHANGED | rc=0 >>
    
    [root@ansible-manager ~]# ansible 10.0.0.15 -m command -a "ls"
    10.0.0.15 | CHANGED | rc=0 >>
    testing.txt
    [root@ansible-manager ~]# ansible 10.0.0.15 -m command -a "removes=anaconda-ks.cfg.txt rm -f testing.txt"
    10.0.0.15 | SUCCESS | rc=0 >>
    skipped, since anaconda-ks.cfg.txt does not exist
    [root@ansible-manager ~]# ansible 10.0.0.15 -m command -a "ls"
    10.0.0.15 | CHANGED | rc=0 >>
    testing.txt

2. shell模块

作用: 批量管理主机执行命令;

shell模块:与command模块功能类似,但是可以识别变量和一些特殊字符;
shell模块:又被称为万能模块;

语法:

ansible 主机地址 -m shell -a "参数 命令"

核心参数:

  • chdir

    chdir=目录名称 #执行指令操作前进行目录切换;
    [root@ansible-manager ~]# ansible 10.0.0.15 -m shell -a "chdir=/etc/sysconfig/network-scripts/ pwd"
    10.0.0.15 | CHANGED | rc=0 >>
    /etc/sysconfig/network-scripts
    [root@ansible-manager ~]# ansible 10.0.0.15 -m shell -a "pwd"
    10.0.0.15 | CHANGED | rc=0 >>
    /root
  • creates

    creates=/目录/文件名称 #若creates文件存在,则跳过后续命令执行(文件存在即不执行)
    [root@ansible-manager ~]# ansible 10.0.0.15 -m shell -a "creates=/etc/sysconfig/network-scripts/ifcfg-eth0 touch /root/Young.txt"
    10.0.0.15 | SUCCESS | rc=0 >>
    skipped, since /etc/sysconfig/network-scripts/ifcfg-eth0 exists
    [root@ansible-manager ~]# ansible 10.0.0.15 -m shell -a "ls"
    10.0.0.15 | CHANGED | rc=0 >>
    testing.txt
    [root@ansible-manager ~]# ansible 10.0.0.15 -m shell -a "creates=/etc/sysconfig/network-scripts/ifcfg-eth5 touch /root/Young.txt"
    [WARNING]: Consider using the file module with state=touch rather than running 'touch'.  If you need
    to use command because file is insufficient you can add 'warn: false' to this command task or set
    'command_warnings=False' in ansible.cfg to get rid of this message.
    10.0.0.15 | CHANGED | rc=0 >>
    
    [root@ansible-manager ~]# ansible 10.0.0.15 -m shell -a "ls"
    10.0.0.15 | CHANGED | rc=0 >>
    testing.txt
    Young.txt
  • removes

    removes=/目录/文件名称 #若removes文件不存在,则跳过后续命令执行(文件存在即执行)
    [root@ansible-manager ~]# ansible 10.0.0.15 -m shell -a "removes=/etc/sysconfig/network-scripts/ifcfg-eth5 rm -rf  /root/Young.txt"
    10.0.0.15 | SUCCESS | rc=0 >>
    skipped, since /etc/sysconfig/network-scripts/ifcfg-eth5 does not exist
    [root@ansible-manager ~]# ansible 10.0.0.15 -m shell -a "ls"
    10.0.0.15 | CHANGED | rc=0 >>
    testing.txt
    Young.txt
    [root@ansible-manager ~]# ansible 10.0.0.15 -m shell -a "removes=/etc/sysconfig/network-scripts/ifcfg-eth0 rm -rf  /root/Young.txt"
    [WARNING]: Consider using the file module with state=absent rather than running 'rm'.  If you need to
    use command because file is insufficient you can add 'warn: false' to this command task or set
    'command_warnings=False' in ansible.cfg to get rid of this message.
    10.0.0.15 | CHANGED | rc=0 >>
    
    [root@ansible-manager ~]# ansible 10.0.0.15 -m shell -a "ls"
    10.0.0.15 | CHANGED | rc=0 >>
    testing.txtshell模块

3. script模块

作用: 批量管理主机执行脚本信息;

script模块可以让受控主机直接执行保存在控制端的脚本,节省了分发脚本和授权的步骤;

语法:

ansible 主机地址 -m script -a "/目录/脚本"
[root@ansible-manager ~]# cat test.sh 
#!/bin/bash
stat . | awk -F "[ /(]" 'NR==4 {print $3}'
stat /tmp | awk -F "[ /(]" 'NR==4 {print $3}'
[root@ansible-manager ~]# ansible nfs_server -m script -a "./test.sh"
10.0.0.15 | CHANGED => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to 10.0.0.15 closed.\r\n",
    "stderr_lines": [
        "Shared connection to 10.0.0.15 closed."
    ], 
    "stdout": "0550\r\n1777\r\n",
    "stdout_lines": [
        "0550",
        "1777"
    ]
}
[root@ansible-manager ~]# ansible nfs_server -m shell -a "./test.sh"
10.0.0.15 | FAILED | rc=127 >>
/bin/sh: ./test.sh: No such file or directorynon-zero return code

4. yum模块

作用: 批量管理主机部署软件;

语法:

ansible 主机地址 -m yum -a "参数"

核心参数:

  • name

    name=软件名称 #指定目标软件名称;
  • state

    state=操作方式 #选择安装目标软件或卸载目标软件;
    安装参数installed, latest, present;
    卸载参数absent, removed
    [root@ansible-manager ~]# ansible nfs_server -m yum -a "name=nginx state=installed"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "changes": {
          "installed": [
              "nginx"
          ]
      }, 
      "msg": "", 
      "rc": 0, 
      "results": [......
      ]
    }

5. service模块

作用: 批量管理主机部署软件;

语法:

ansible 主机地址 -m service -a "参数"

核心参数:

  • name

    name=服务名称 #指定目标服务名称;
  • state

    state=操作方式 #选择目标服务的工作方式;
    started #启动指定服务
    restarted #重启指定服务
    reloaded #平滑重启指定服务
    stopped #停止指定服务
  • enabled

    enabled=操作方式 #选择目标服务的开启启动状态;
    yes #指定服务开机自启动
    no #停止服务开启自启动
    [root@ansible-manager ~]# ansible nfs_server -m shell -a "systemctl status sshd" | head -4
    10.0.0.15 | CHANGED | rc=0 >>
    ● sshd.service - OpenSSH server daemon
     Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2021-11-10 08:44:41 CST; 5h 18min ago
    [root@ansible-manager ~]# ansible nfs_server -m service -a "name=sshd state=stopped enabled=no"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
    ......
    [root@ansible-manager ~]# ansible nfs_server -m shell -a "systemctl status sshd" | head -4
    10.0.0.15 | FAILED | rc=3 >>
    ● sshd.service - OpenSSH server daemon
     Loaded: loaded (/usr/lib/systemd/system/sshd.service; disabled; vendor preset: enabled)
     Active: inactive (dead)
    [root@ansible-manager ~]# ansible nfs_server -m service -a "name=sshd state=started enabled=yes"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "enabled": true, 
      "name": "sshd", 
      "state": "started", 
    ......
    [root@ansible-manager ~]# ansible nfs_server -m shell -a "systemctl status sshd" | head -4
    10.0.0.15 | CHANGED | rc=0 >>
    ● sshd.service - OpenSSH server daemon
     Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2021-11-10 14:39:45 CST; 27s ago

6. copy模块

作用:

  • 分发文件;将管理端主机的数据文件分发至受控端主机中;
  • 移动文件;将受控端某一目录中的数据移动至本机的其他目录中;

语法:

ansible 主机地址 -m copy -a "参数"

核心参数:

  • src

    src=/目录/文件名称 #指定管理端源文件;
  • dest

    dest=/目录 #指定受控端文件存放位置;
  • owner

    owner=受控端用户名 #文件完成后,修改文件属主为参数指定用户;
  • group

    group=受控端用户组名 #文件完成后,修改文件属组为参数指定用户组;
  • mode

    mode=权限位 #指定文件权限;(可直接修改目标文件的12位权限位)
    [root@ansible-manager ~]# ansible nfs_server -m copy -a "src=/etc/sysconfig/network-scripts/ifcfg-eth0 dest=/opt owner=Young group=Aspen mode=1666"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "checksum": "4b012dda109a9bf006925c5ebc6536122293f643", 
      "dest": "/opt/ifcfg-eth0", 
      "gid": 1001, 
      "group": "Aspen", 
      "md5sum": "844f6f76b88a3f434e7b4a100a33e5f6", 
      "mode": "01666", 
      "owner": "Young", 
      "size": 124, 
      "src": "/root/.ansible/tmp/ansible-tmp-1636528273.42-9514-35710178891211/source", 
      "state": "file", 
      "uid": 1001
    }
    [root@ansible-manager ~]# ansible nfs_server -m shell -a "ls -l /opt"
    10.0.0.15 | CHANGED | rc=0 >>
    total 4
    -rw-rw-rwT 1 Young Aspen 124 Nov 10 15:11 ifcfg-eth0
  • backup

    使用backup备份时,备份文件名称具有随机性,不利于文件恢复;不建议使用;备份文件建议使用remote_src参数

    backup=状态 #分发文件之前,将受控端源文件按照时间信息备份;(backup参数仅对文件内容发生更改的文件生效备份)
    yes #开启备份功能
    no #关闭备份功能(默认参数)
    [root@ansible-manager ~]# ansible nfs_client -m copy -a "src=/etc/hosts dest=/opt owner=Young group=Aspen mode=0555" 
    10.0.0.17 | CHANGED => {
    ......
    [root@ansible-manager ~]# >/etc/hosts
    [root@ansible-manager ~]# ansible nfs_client -m copy -a "src=/etc/hosts dest=/opt owner=Young group=Aspen mode=0555 backup=yes" 
    10.0.0.16 | CHANGED => {
    [root@ansible-manager ~]# ansible nfs_client -m shell -a "ls -l /opt" 
    10.0.0.16 | CHANGED | rc=0 >>
    total 4
    -r-xr-xr-x 1 Young Aspen   0 Nov 10 15:24 hosts
    -r-xr-xr-x 1 Young Aspen 349 Nov 10 15:23 hosts.8686.2021-11-10@15:24:46~
    10.0.0.17 | CHANGED | rc=0 >>
    total 4
    -r-xr-xr-x 1 Young Aspen   0 Nov 10 15:24 hosts
    -r-xr-xr-x 1 Young Aspen 349 Nov 10 15:23 hosts.8650.2021-11-10@15:24:46~
  • remote_src

    remote_src=状态 #指定分发文件源地址;
    yes #指定源文件在受控端
    no #指定源文件在管理端(默认参数)
    [root@ansible-manager ~]# ansible nfs_server -m copy -a "src=/etc/sysconfig/network-scripts/ifcfg-eth0 dest=/opt owner=Young group=Aspen mode=1777 remote_src=yes"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
    .......
    }
    [root@ansible-manager ~]# ansible nfs_server -m copy -a "src=/etc/sysconfig/network-scripts/ifcfg-eth0 dest=/opt/ifcfg-eth0.txt owner=Young group=Aspen mode=1777"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
    ......
    }
    [root@ansible-manager ~]# ansible nfs_server -m shell -a "cat /opt/ifcfg-*"
    10.0.0.15 | CHANGED | rc=0 >>
    TYPE=Ethernet
    BOOTPROTO=none
    NAME=eth0
    DEVICE=eth0
    ONBOOT=yes
    IPADDR=10.0.0.15
    PREFIX=24
    GATEWAY=10.0.0.254
    DNS1=10.0.0.254
    -------------------------------------------#手动分割线#-----------------------------------------------
    TYPE=Ethernet
    BOOTPROTO=none
    NAME=eth0
    DEVICE=eth0
    ONBOOT=yes
    IPADDR=10.0.0.12
    PREFIX=24
    GATEWAY=10.0.0.254
    DNS1=10.0.0.254
  • content

    content=内容 #指定内容作为文件分发;(仅能指定简单内容)
    [root@ansible-manager ~]# ansible nfs_server -m copy -a "content=aspenhan.com dest=/opt/young.txt mode=600"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "checksum": "a19091186a872f390ed7b22b2a2112e2c4c0c475", 
      "dest": "/opt/young.txt", 
      "gid": 0, 
      "group": "root", 
      "md5sum": "78d6eafa109f8aa6643efa3ce4222efc", 
      "mode": "0600", 
      "owner": "root", 
      "size": 12, 
      "src": "/root/.ansible/tmp/ansible-tmp-1636532016.71-10097-212988197816126/source", 
      "state": "file", 
      "uid": 0
    }
    [root@ansible-manager ~]# ansible nfs_server -m shell  -a "cat /opt/young.txt"
    10.0.0.15 | CHANGED | rc=0 >>
    aspenhan.com

7. fetch模块

作用: 拉取远程受控端主机数据至本地;

fetch模块不仅拉取目标文件,为了区分多台主机同时拉取,会连同对应文件的目录结构一起拉取至本地指定目录下的IP地址目录中

语法:

ansible 主机地址 -m fetch -a "参数"

核心参数:

  • src

    src=/目录/文件名称 #指定被控端被拉取文件;
  • dest

    dest=/目录 #指定管理端文件存放位置;
    [root@ansible-manager ~]# ansible nfs_client -m fetch -a "src=/etc/sysconfig/network-scripts/ifcfg-eth0 dest=/opt"
    10.0.0.16 | CHANGED => {
      "changed": true, 
      "checksum": "4a166ce4f2ceae28e4a6ad5400f969b3442cf2ca", 
      "dest": "/opt/10.0.0.16/etc/sysconfig/network-scripts/ifcfg-eth0", 
      "md5sum": "ffc518fe7818892473a062abf9143a02", 
      "remote_checksum": "4a166ce4f2ceae28e4a6ad5400f969b3442cf2ca", 
      "remote_md5sum": null
    }
    10.0.0.17 | CHANGED => {
      "changed": true, 
      "checksum": "dfdb59c07cd37c844c90d884680376b214fe6b10", 
      "dest": "/opt/10.0.0.17/etc/sysconfig/network-scripts/ifcfg-eth0", 
      "md5sum": "b4c7dbf25c5edbffafa736c969e57027", 
      "remote_checksum": "dfdb59c07cd37c844c90d884680376b214fe6b10", 
      "remote_md5sum": null
    }
    [root@ansible-manager ~]# tree /opt/
    /opt/
    ├── 10.0.0.16
    │   └── etc
    │       └── sysconfig
    │           └── network-scripts
    │               └── ifcfg-eth0
    └── 10.0.0.17
      └── etc
          └── sysconfig
              └── network-scripts
                  └── ifcfg-eth0
    
    8 directories, 2 files

8. file模块

作用:

  • 修改文件属性信息
  • 创建数据信息,如创建目录,创建文件,创建链接文件;
  • 删除数据信息

语法:

ansible 主机地址 -m file -a "参数"

核心参数:

  • path

    path=/目录/文件 #指定处理数据路径信息
  • owner

    owner=受控端用户名 #文件完成后,修改文件属主为参数指定用户;
  • group

    group=受控端用户组名 #文件完成后,修改文件属组为参数指定用户组;
  • mode

    mode=权限位 #指定文件权限;(可直接修改目标文件的12位权限位)
  • state

    state=状态 #指定文件执行的操作
    touch #创建文件
    directory #创建目录(默认支持递归创建多级目录)
    hard #创建硬链接
    link #创建软连接
    absent #删除数据信息(默认支持递归删除)
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "warn=false rm -rf /opt/* "
    10.0.0.15 | CHANGED | rc=0 >>
    # 创建目录
    [root@ansible-manager ~]# ansible 10.0.0.15 -m file -a "path=/opt/young state=directory owner=Young group=Aspen mode=1777"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "gid": 1001, 
      "group": "Aspen", 
      "mode": "01777", 
      "owner": "Young", 
      "path": "/opt/young", 
      "size": 6, 
      "state": "directory", 
      "uid": 1001
    }
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "ls -l /opt"
    10.0.0.15 | CHANGED | rc=0 >>
    total 0
    drwxrwxrwt 2 Young Aspen 6 Nov 11 10:40 young
    # 创建文件
    [root@ansible-manager ~]# ansible 10.0.0.15 -m file -a "path=/opt/young/aspen.txt state=touch"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "dest": "/opt/young/aspen.txt", 
      "gid": 0, 
      "group": "root", 
      "mode": "0644", 
      "owner": "root", 
      "size": 0, 
      "state": "file", 
      "uid": 0
    }
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "ls -l /opt/young"
    10.0.0.15 | CHANGED | rc=0 >>
    total 0
    -rw-r--r-- 1 root root 0 Nov 11 10:41 aspen.txt
    # 创建软连接与硬链接
    [root@ansible-manager ~]# ansible 10.0.0.15 -m file -a "src=/opt/young/aspen.txt path=/opt/young/aspen_hardlink.txt state=hard"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "dest": "/opt/young/aspen_hardlink.txt", 
      "gid": 0, 
      "group": "root", 
      "mode": "0644", 
      "owner": "root", 
      "size": 0, 
      "src": "/opt/young/aspen.txt", 
      "state": "hard", 
      "uid": 0
    }
    [root@ansible-manager ~]# ansible 10.0.0.15 -m file -a "src=/opt/young/aspen.txt path=/opt/young/aspen_softlink.txt state=link"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "dest": "/opt/young/aspen_softlink.txt", 
      "gid": 0, 
      "group": "root", 
      "mode": "0777", 
      "owner": "root", 
      "size": 20, 
      "src": "/opt/young/aspen.txt", 
      "state": "link", 
      "uid": 0
    }
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "ls -li /opt/young"
    10.0.0.15 | CHANGED | rc=0 >>
    total 0
    3098 -rw-r--r-- 2 root root  0 Nov 11 10:41 aspen_hardlink.txt
    17748 lrwxrwxrwx 1 root root 20 Nov 11 11:13 aspen_softlink.txt -> /opt/young/aspen.txt
    3098 -rw-r--r-- 2 root root  0 Nov 11 10:41 aspen.txt
    # 删除文件
    [root@ansible-manager ~]# ansible 10.0.0.15 -m file -a "path=/opt/young/aspen_softlink.txt state=absent"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "path": "/opt/young/aspen_softlink.txt", 
      "state": "absent"
    }
    [root@ansible-manager ~]# ansible 10.0.0.15 -m file -a "path=/opt/young/aspen_hardlink.txt state=absent"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "path": "/opt/young/aspen_hardlink.txt", 
      "state": "absent"
    }
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "ls -li /opt/young"
    10.0.0.15 | CHANGED | rc=0 >>
    total 0
    3098 -rw-r--r-- 1 root root 0 Nov 11 10:41 aspen.txt

9. mount模块

作用: 批量管理主机完成挂载操作;

语法:

ansible 主机地址 -m mount -a "参数"

核心参数:

  • src

    src=设备目录 #指定被挂载的设备目录
  • path

    path=挂载点 #指定挂载点目录
  • fstype

    fstype=文件系统类型 #指定挂载的文件系统类型
  • state

    state=操作方式 #选择安装目标软件或卸载目标软件;
    挂载参数mounted(永久挂载、立即挂载), present(永久挂载);
    卸载参数unmounted(临时卸载), absent(永久卸载、立即卸载);
    # 准备环境
    [root@web01 ~]# dd if=/dev/zero of=/tmp/testing_block bs=1M count=1024
    1024+0 records in
    1024+0 records out
    1073741824 bytes (1.1 GB) copied, 29.9253 s, 35.9 MB/s
    [root@web01 ~]# mkfs.xfs /tmp/testing_block 
    meta-data=/tmp/testing_block     isize=512    agcount=4, agsize=65536 blks
           =                       sectsz=512   attr=2, projid32bit=1
           =                       crc=1        finobt=0, sparse=0
    data     =                       bsize=4096   blocks=262144, imaxpct=25
           =                       sunit=0      swidth=0 blks
    naming   =version 2              bsize=4096   ascii-ci=0 ftype=1
    log      =internal log           bsize=4096   blocks=2560, version=2
           =                       sectsz=512   sunit=0 blks, lazy-count=1
    realtime =none                   extsz=4096   blocks=0, rtextents=0
    # mount挂载
    [root@ansible-manager ~]# ansible 10.0.0.15 -m mount -a "src=/tmp/testing_block path=/mnt state=mounted fstype=xfs"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "dump": "0", 
      "fstab": "/etc/fstab", 
      "fstype": "xfs", 
      "name": "/mnt", 
      "opts": "defaults", 
      "passno": "0", 
      "src": "/tmp/testing_block"
    }
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "df -Th" |tail -1  
    /dev/loop0     xfs      1014M   33M  982M   4% /mnt
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "cat /etc/fstab" | tail -1  
    /tmp/testing_block /mnt xfs defaults 0 0
    
    # absent卸载
    [root@ansible-manager ~]# ansible 10.0.0.15 -m mount -a "src=/tmp/testing_block path=/mnt state=absent"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "dump": "0", 
      "fstab": "/etc/fstab", 
      "name": "/mnt", 
      "opts": "defaults", 
      "passno": "0", 
      "src": "/tmp/testing_block"
    }
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "cat /etc/fstab" | tail -1  
    UUID=42eaa7c4-975b-4c3a-8301-1e4543eb730e swap                    swap    defaults        0 0
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "df -Th" | tail -1 
    tmpfs          tmpfs     199M     0  199M   0% /run/user/0
    
    # present挂载
    [root@ansible-manager ~]# ansible 10.0.0.15 -m mount -a "src=/tmp/testing_block path=/mnt state=present fstype=xfs"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "dump": "0", 
      "fstab": "/etc/fstab", 
      "fstype": "xfs", 
      "name": "/mnt", 
      "opts": "defaults", 
      "passno": "0", 
      "src": "/tmp/testing_block"
    }
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "df -Th" | tail -1 
    tmpfs          tmpfs     199M     0  199M   0% /run/user/0
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "cat /etc/fstab" | tail -1  
    /tmp/testing_block /mnt xfs defaults 0 0
    
    # 准备环境
    [root@ansible-manager ~]# ansible 10.0.0.15 -m mount -a "src=/tmp/testing_block path=/mnt state=absent fstype=xfs"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "dump": "0", 
      "fstab": "/etc/fstab", 
      "fstype": "xfs", 
      "name": "/mnt", 
      "opts": "defaults", 
      "passno": "0", 
      "src": "/tmp/testing_block"
    
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "cat /etc/fstab" | tail -1  
    UUID=42eaa7c4-975b-4c3a-8301-1e4543eb730e swap                    swap    defaults        0 0
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "df -Th" | tail -1 
    tmpfs          tmpfs     199M     0  199M   0% /run/user/0
    [root@ansible-manager ~]# ansible 10.0.0.15 -m mount -a "src=/tmp/testing_block path=/mnt state=mounted fstype=xfs"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "dump": "0", 
      "fstab": "/etc/fstab", 
      "fstype": "xfs", 
      "name": "/mnt", 
      "opts": "defaults", 
      "passno": "0", 
      "src": "/tmp/testing_block"
    
    # unmounted卸载
    [root@ansible-manager ~]# ansible 10.0.0.15 -m mount -a "src=/tmp/testing_block path=/mnt state=unmounted"
    10.0.0.15 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "dump": "0", 
      "fstab": "/etc/fstab", 
      "name": "/mnt", 
      "opts": "defaults", 
      "passno": "0", 
      "src": "/tmp/testing_block"
    }
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "df -Th" | tail -1 
    tmpfs          tmpfs     199M     0  199M   0% /run/user/0
    [root@ansible-manager ~]# ansible 10.0.0.15 -a "cat /etc/fstab" | tail -1  
    /tmp/testing_block /mnt xfs defaults 0 0

10. cron模块

作用: 批量设置管理主机的定时任务;

语法:

ansible 主机地址 -m cron -a "参数"

核心参数:

  • name

    name=注释内容 #定义定时任务注释信息;
  • minute

    minute=数字 #定义定时任务分钟信息
  • hour

    hour=数字 #定义定时任务小时信息
  • day

    day=数字 #定义定时任务日期信息
  • month

    month=数字 #定义定时任务月份信息
  • weekday

    weekday=数字 #定义定时任务星期信息
  • job

    job=任务 #定义定时任务执行的指令信息
  • state

    state=状态 #指定定时任务的状态
    present #创建定时任务(默认参数)
    absent #删除定时任务(仅能删除由ansible创建的定时任务)
  • disabled

    disabled=状态 #指定定时任务的启用
    no #启用定时任务
    yes #注释定时任务
    # 设置定时任务
    [root@ansible-manager ~]# ansible 10.0.0.16 -m cron -a "name='syne time every 10 minutes' minute=*/10 job='ntpdate ntp1.aliyun.com &>/dev/null'"
    10.0.0.16 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "envs": [], 
      "jobs": [
          "syne time every 10 minutes"
      ]
    }
    [root@ansible-manager ~]# ansible 10.0.0.16 -m shell -a "crontab -l"
    10.0.0.16 | CHANGED | rc=0 >>
    #sync time by Aspen 20190511
    */5 * * * * /usr/sbin/ntpdate ntp1.aliyun.com >/dev/null 2>&1
    #Ansible: syne time every 10 minutes
    */10 * * * * ntpdate ntp1.aliyun.com &>/dev/null
    
    # 删除定时任务
    [root@ansible-manager ~]# ansible 10.0.0.16 -m cron -a "name='syne time every 10 minutes' state=absent"
    10.0.0.16 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "envs": [], 
      "jobs": []
    }
    [root@ansible-manager ~]# ansible 10.0.0.16 -m shell -a "crontab -l"
    10.0.0.16 | CHANGED | rc=0 >>
    #sync time by Aspen 20190511
    */5 * * * * /usr/sbin/ntpdate ntp1.aliyun.com >/dev/null 2>&1
    
    # 注释定时任务并启用
    [root@ansible-manager ~]# ansible 10.0.0.16 -m cron -a "name='syne time every 10 minutes' minute=*/10 job='ntpdate ntp1.aliyun.com &>/dev/null' disabled=yes"
    10.0.0.16 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "envs": [], 
      "jobs": [
          "syne time every 10 minutes"
      ]
    }
    [root@ansible-manager ~]# ansible 10.0.0.16 -m shell -a "crontab -l"
    10.0.0.16 | CHANGED | rc=0 >>
    #sync time by Aspen 20190511
    */5 * * * * /usr/sbin/ntpdate ntp1.aliyun.com >/dev/null 2>&1
    #Ansible: syne time every 10 minutes
    #*/10 * * * * ntpdate ntp1.aliyun.com &>/dev/null
    [root@ansible-manager ~]# ansible 10.0.0.16 -m cron -a "name='syne time every 10 minutes' job='ntpdate ntp1.aliyun.com &>/dev/null' disabled=no"
    10.0.0.16 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "envs": [], 
      "jobs": [
          "syne time every 10 minutes"
      ]
    }
    [root@ansible-manager ~]# ansible 10.0.0.16 -m shell -a "crontab -l"
    10.0.0.16 | CHANGED | rc=0 >>
    #sync time by Aspen 20190511
    */5 * * * * /usr/sbin/ntpdate ntp1.aliyun.com >/dev/null 2>&1
    #Ansible: syne time every 10 minutes
    * * * * * ntpdate ntp1.aliyun.com &>/dev/null

11. user模块

作用: 批量管理主机创建用户;

语法:

ansible 主机地址 -m user -a "参数"

核心参数:

  • name

    name=用户名 #指定用户名称
  • uid

    uid=数字 #指定用户UID信息
  • group

    group=用户组名 #指定用户的所属组信息
  • groups

    groups=用户组名 #指定用户的附加组信息
  • password

    password=密码 #指定用户的密码信息(必须是密文的密码信息)
  • shell

    shell=用户名 #指定用户的所使用的命令解释器
  • create_home

    create_home=no #不创建家目录
  • state

    state=状态 #指定用户状态
    present #创建用户(默认参数)
    absent #删除用户
    # 创建虚拟用户
    [root@ansible-manager ~]# ansible 10.0.0.16 -m user -a "name=aspen uid=1010 group=Aspen groups=oldboy shell=/sbin/nologin create_home=no"
    10.0.0.16 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "comment": "", 
      "create_home": false, 
      "group": 1001, 
      "groups": "oldboy", 
      "home": "/home/aspen", 
      "name": "aspen", 
      "shell": "/sbin/nologin", 
      "state": "present", 
      "system": false, 
      "uid": 1010
    }
    [root@ansible-manager ~]# ansible 10.0.0.16 -m shell -a "id aspen"
    10.0.0.16 | CHANGED | rc=0 >>
    uid=1010(aspen) gid=1001(Aspen) groups=1001(Aspen),1000(oldboy)
    [root@ansible-manager ~]# ansible 10.0.0.16 -m shell -a "ls /home"
    10.0.0.16 | CHANGED | rc=0 >>
    oldboy
    Young
    
    # 删除用户
    [root@ansible-manager ~]# ansible 10.0.0.16 -m user -a "name=aspen state=absent"
    10.0.0.16 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      },
      "changed": true,
      "force": false,
      "name": "aspen",
      "remove": false,
      "state": "absent"
    }
    [root@ansible-manager ~]# ansible 10.0.0.16 -m shell -a "id aspen"
    10.0.0.16 | FAILED | rc=1 >>
    id: aspen: no such usernon-zero return code
    
    # 创建用户
    [root@ansible-manager ~]# ansible 10.0.0.16 -m user -a 'name=aspen uid=1010 group=Aspen groups=oldboy password="$6$Young$XtmxodFMen47.aEj8/RWo/2Z/VQSJF9hHWonQI1CebNDNVe2WHw9kzlEC3RiypHgre/LZMuXoHbOf4A5knpdi/"'
    10.0.0.16 | CHANGED => {
      "ansible_facts": {
          "discovered_interpreter_python": "/usr/bin/python"
      }, 
      "changed": true, 
      "comment": "", 
      "create_home": true, 
      "group": 1001, 
      "groups": "oldboy", 
      "home": "/home/aspen", 
      "name": "aspen", 
      "password": "NOT_LOGGING_PASSWORD", 
      "shell": "/bin/bash", 
      "state": "present", 
      "stderr": "Creating mailbox file: File exists\n", 
      "stderr_lines": [
          "Creating mailbox file: File exists"
      ], 
      "system": false, 
      "uid": 1010
    }
    [root@ansible-manager ~]# ssh aspen@10.0.0.16
    aspen@10.0.0.16's password: 
    [aspen@web02 ~]$ pwd
    /home/aspen
    [aspen@web02 ~]$ logout
    Connection to 10.0.0.16 closed.

创建密文密码

  • 方式一:利用ansible的模块功能

    ansible all -i localhost, -m debug -a msg={{ '明文密码' | password_hash('sha512', '辅助密钥') }}" #生成用户密码密码
    [root@ansible-manager ~]# ansible all -i localhost, -m debug -a "msg={{ '123456' | password_hash('sha512', 'Young') }}"
    localhost | SUCCESS => {
      "msg": "$6$Young$XtmxodFMen47.aEj8/RWo/2Z/VQSJF9hHWonQI1CebNDNVe2WHw9kzlEC3RiypHgre/LZMuXoHbOf4A5knpdi/"
    }
  • 方式二:利用python的模块功能

第一步:安装pip命令

yum install -y python-pip
[root@ansible-manager ~]# yum install python-pip -y 
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
......
Installed:
  python2-pip.noarch 0:8.1.2-14.el7                                                                   

Complete!

第二步:安装对应模块

pip install passlib
[root@ansible-manager ~]# pip install passlib
Collecting passlib
  Using cached https://files.pythonhosted.org/packages/3b/a4/ab6b7589382ca3df236e03faa71deac88cae040af60c071a78d254a62172/passlib-1.7.4-py2.py3-none-any.whl
Installing collected packages: passlib
Successfully installed passlib-1.7.4
You are using pip version 8.1.2, however version 21.3.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

第三步:生成密码

python -c "from passlib.hash import sha512_crypt; import getpass; print(sha512_crypt.using(rounds=5000).hash(getpass.getpass()))"
[root@ansible-manager ~]# python -c "from passlib.hash import sha512_crypt; import getpass; print(sha512_crypt.using(rounds=5000).hash(getpass.getpass()))"
Password: 
$6$fIR9.6Jm3xUtwLqT$jOnUQPZjKPPw.A4YLg131TwnouiN60gZeypqtDooq.9c8YRu28rQ6ekep9yPQvWOu8m//EfCKpOUsUPsYkdK8.

12. setup模块

作用: 批量获取主机信息;

语法:

ansible 主机地址 -m setup -a "filter=项目"

常用项目:

项目名称 含义
ansible_all_ipv4_addresses: 仅显示IPv4的信息
ansible_devices: 仅显示磁盘设备信息
ansible_distribution: 显示系统发行类型(CentOS/SUSE/Ubuntu...)
ansible_distribution_major_version: 显示系统主版本
ansible_distribution_version: 仅显示系统版本(32位/64位)
ansible_machine: 显示系统类型
ansible_eth0: 仅显示eth0的信息
ansible_hostname: 仅显示主机名称
ansible_kernal: 仅显示系统内核版本
ansible_lvm: 显示lvm相关信息
ansible_memtotal_mb: 显示系统总内存
ansible_memfree_mb: 显示系统可用内存
ansible_memory_mb: 详细显示内存情况
ansible_swaptotal_mb: 显示swap内存的总内存
ansible_swapfree_mb: 显示swap内存的可用内存
ansible_mounts: 显示系统磁盘挂载情况
ansible_processor: 显示CPU个数(具体显示每个CPU的型号)
ansible_processor_vcpus: 显示CPU个数(只显示总的个数)
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible 10.0.0.15 -m setup
10.0.0.15 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "172.16.1.15", 
            "10.0.0.15"
        ],
......
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible 10.0.0.15 -m setup | wc -l
659
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible 10.0.0.15 -m setup -a "filter=ansible_hostname"
10.0.0.15 | SUCCESS => {
    "ansible_facts": {
        "ansible_hostname": "web01",
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible 10.0.0.15 -m setup -a "filter=ansible_all_ipv4_addresses"
10.0.0.15 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "172.16.1.15",
            "10.0.0.15"
        ], 
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false
}

四、ansible-playbook(剧本)

剧本的作用
1. 将多个模块操作功能进行整合;
2. 实现重复工作简单化(提高工作效率)
3. 实现批量管理特殊需求

1. 剧本组成

- hosts: 主机IP地址 定义角色信息
tasks: 定义任务信息
- 模块名称: 参数1 参数2

2. 剧本编写规范(YAML)

1.缩进 - 2个空格表示1个缩进关系;

2.冒号 - 创建键值对信息;在正文中(非在描述和注释信息中),非以冒号结尾情况下,冒号后面必须有空格;

3.短横线 - 短横线用以标识多个列表;列表表示相同的信息/类别多次出现;在正文中(非在描述和注释信息中),短横线后必须有空格;

3. 编写实践

rsync服务一键自动化部署

- hosts: rsync_server
  tasks:
    - name: Install rsyncd service
      yum: name=rsync state=installed
    - name: Backup source configuration File
      copy: src=/etc/rsyncd.conf dest=/etc/rsyncd.conf.bak remote_src=yes
    - name: Delivery configuration file to target
      copy: src=/etc/ansible/ansible-playbook/rsync/rsyncd.conf dest=/etc/rsyncd.conf
    - name: Create group
      group: name=rsync
    - name: Create User
      user: name=rsync group=rsync shell=/sbin/nologin create_home=no
    - name: Create backup directory
      file: path=/backup owner=rsync group=rsync state=directory
    - name: Delivery password file to target
      copy: content='rsync_backup:123456' mode=600 dest=/etc/rsync_server.password
    - name: Start rsyncd service
      service: name=rsyncd state=started enabled=yes
- hosts: rsync_client
  tasks:
    - name: Delivery Password File
      copy: content='123456' mode=600 dest=/etc/rsync_client.password
[root@ansible-manager ~]# mkdir /etc/ansible/ansible-playbook/rsync -p && cd /etc/ansible/ansible-playbook
[root@ansible-manager /etc/ansible/ansible-playbook]# ls rsync/rsyncd.conf 
rsync/rsyncd.conf
[root@ansible-manager /etc/ansible/ansible-playbook]# grep -Ev '^$|#' ../hosts 
[rsync:children]
rsync_server
rsync_client
[rsync_server]
10.0.0.15
[rsync_client]
10.0.0.16
10.0.0.17
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook --syntax-check rsync_deploy.yaml

playbook: rsync_deploy.yaml
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook -C rsync_deploy.yaml | head -5

PLAY [rsync_server] **********************************************************************************

TASK [Gathering Facts] *******************************************************************************
ok: [10.0.0.15]
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook rsync_deploy.yaml
PLAY [rsync_server] **********************************************************************************
......
[root@web02 ~]# rsync -av /etc/fstab rsync_backup@172.16.1.15::backup --password-file=/etc/rsync_client.password 
sending incremental file list
fstab

sent 596 bytes  received 43 bytes  1,278.00 bytes/sec
[root@web02 ~]# ssh root@172.16.1.15 'ls /backup'
root@172.16.1.15's password: 
fstab
[root@web03 ~]# rsync -av /etc/sysconfig/network-scripts/ifcfg-eth0 rsync_backup@172.16.1.15::backup --password-file=/etc/rsync_client.password 
sending incremental file list
ifcfg-eth0

sent 224 bytes  received 43 bytes  534.00 bytes/sec
total size is 124  speedup is 0.46
[root@web03 ~]# ssh root@172.16.1.15 'ls /backup'
root@172.16.1.15's password: 
fstab
ifcfg-eth0

nfs服务一键自动化部署

[root@ansible-manager /etc/ansible/ansible-playbook]# cat nfs_deploy.yaml 
- hosts: nfs_server
  tasks:
    - name: Install rpcbind and nfs service
      yum: 
        name:
          - rpcbind 
          - nfs-utils
        state: installed
    - name: Create group
      group: name=www gid=2000
    - name: Create user
      user: name=www uid=2000 group=www shell=/sbin/nologin create_home=no
    - name: Create shared directory
      file: path=/backup/www/uploads state=directory owner=www group=www
    - name: Delivery configuration file
      copy: content='/backup/www/uploads 172.16.1.0/24(rw,sync,anonuid=2000,anongid=2000)' dest=/etc/exports
    - name: Start rpcbind service
      service: name=rpcbind state=started enabled=yes
    - name: Start nfs service
      service: name=nfs state=started enabled=yes
- hosts: nfs_client
  tasks:
    - name: Install nfs service
      yum: name=nfs-utils state=installed
    - name: Create group
      group: name=www gid=2000
    - name: Create user
      user: name=www uid=2000 group=www shell=/sbin/nologin create_home=no
    - name: Create mount point
      file: path=/var/www/images state=directory
    - name: Mount NFS service
      mount: src=172.16.1.15:/backup/www/uploads path=/var/www/images fstype=nfs state=mounted
[root@ansible-manager /etc/ansible/ansible-playbook]# grep -Ev '^$|#' ../hosts 
[nfs:children]
nfs_server
nfs_client
[nfs_server]
10.0.0.15
[nfs_client]
10.0.0.16
10.0.0.17
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook --syntax-check nfs_deploy.yaml  

playbook: nfs_deploy.yaml
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook -C nfs_deploy.yaml | head -2

PLAY [nfs_server] ************************************************************************************
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook nfs_deploy.yaml 

PLAY [nfs_server] ************************************************************************************

TASK [Gathering Facts] *******************************************************************************
ok: [10.0.0.15]
......
[root@web02 ~]# cd /var/www/images/
[root@web02 /var/www/images]# df -Th |tail -1 
172.16.1.15:/backup/www/uploads nfs4       99G  2.7G   97G   3% /var/www/images
[root@web02 /var/www/images]# tail -1 /etc/fstab 
172.16.1.15:/backup/www/uploads /var/www/images nfs defaults 0 0
[root@web02 /var/www/images]# cp /etc/hostname . 
[root@web02 /var/www/images]# ls
hostname
[root@web03 ~]# cd /var/www/images/
[root@web03 /var/www/images]# df -Th | tail -1 
172.16.1.15:/backup/www/uploads nfs4       99G  2.7G   97G   3% /var/www/images
[root@web03 /var/www/images]# tail -1 /etc/fstab 
172.16.1.15:/backup/www/uploads /var/www/images nfs defaults 0 0
[root@web03 /var/www/images]# ls
hostname
[root@web03 /var/www/images]# cp /etc/hostname ./hostname_web03
[root@web01 ~]# ls /backup/www/uploads/ -l
total 8
-rw-r--r-- 1 www www 6 Nov 17 13:40 hostname
-rw-r--r-- 1 www www 6 Nov 17 13:41 hostname_web03
[root@web01 ~]# cat /backup/www/uploads/hostname
web02
[root@web01 ~]# cat /backup/www/uploads/hostname_web03 
web03

五、ansible-playbook进阶

1. 设置变量

变量设置方式优先级: 命令行 > 剧本文件 > 主机配置清单

方式一:剧本中设置变量

- hosts: 主机IP地址
vars: #定义变量
变量名1: 变量值
变量名2: 变量值
...
tasks:
- 模块名称: 参数={{ 变量名 }} 参数={{ 变量名 }} ... #引用变量
- hosts: 10.0.0.15
  vars:
     var1: 0
     dir_info: /etc/
     second_dir: sysconfig/network-scripts/
     dest_dir: /tmp/
     dest_file: ifcfg-eth{{ var1 }}
  tasks:
    - name: Delivery file to test vars
      copy: src={{ dir_info  }}{{ second_dir  }}{{ dest_file }} dest={{ dest_dir  }}{{ dest_file }}
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook vars_test.yaml 

PLAY [10.0.0.15] 
......
[root@ansible-manager /etc/ansible/ansible-playbook]# ssh root@10.0.0.15 'cat /tmp/ifcfg-eth0|sed -n 6p'
IPADDR=10.0.0.12
[root@ansible-manager /etc/ansible/ansible-playbook]# ssh root@10.0.0.15 'ls -l /tmp/ifcfg-eth0'
-rw-r--r-- 1 root root 124 Nov 17 15:56 /tmp/ifcfg-eth0

方式二:命令行中设置变量

anisble-playbook -e 变量名1=值 -e 变量名2=值 ... 剧本名
- hosts: 10.0.0.15
  vars:
     dir_info: /etc/
     second_dir: sysconfig/network-scripts/
     dest_dir: /tmp/
     dest_file: ifcfg-eth{{ var1 }}
  tasks:
    - name: Delivery file to test vars
      copy: src={{ dir_info  }}{{ second_dir  }}{{ dest_file }} dest={{ dest_dir  }}{{ dest_file }}
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook vars_test.yaml -e var1=1

PLAY [10.0.0.15] 
......
[root@ansible-manager /etc/ansible/ansible-playbook]# ssh root@10.0.0.15 'ls -l /tmp/ifcfg-eth1'
-rw-r--r-- 1 root root 94 Nov 17 16:26 /tmp/ifcfg-eth1
[root@ansible-manager /etc/ansible/ansible-playbook]# ssh root@10.0.0.15 'sed -n 6p /tmp/ifcfg-eth1'
IPADDR=172.16.1.12

方式三:在主机清单文件中定义变量

/etc/ansible/hosts
[组名]
主机地址
[组名:vars]
变量名1=值
变量名2=值
......
[root@ansible-manager /etc/ansible/ansible-playbook]# grep -Ev '#' vars_test.yaml 
- hosts: 10.0.0.15
  tasks:
    - name: Delivery file to test vars
      copy: src={{ dir_info  }}{{ second_dir  }}{{ dest_file }} dest={{ dest_dir  }}{{ dest_file }}
[root@ansible-manager /etc/ansible/ansible-playbook]# grep -Ev '#|^$' ../hosts 
[nfs:children]
nfs_server
nfs_client
[nfs_server]
10.0.0.15
[nfs_server:vars]
dir_info=/etc/
second_dir=sysconfig/network-scripts/
dest_dir=/tmp/
dest_file=ifcfg-eth{{ var1 }}
[nfs_client]
10.0.0.16
10.0.0.17
[root@ansible-manager /etc/ansible/ansible-playbook]# ssh root@10.0.0.15 'rm -rf /tmp/*'
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook vars_test.yaml -e var1=0

PLAY [10.0.0.15] *************************************************************************************
......
[root@ansible-manager /etc/ansible/ansible-playbook]# ssh root@10.0.0.15 'ls -l /tmp/'
total 4
-rw-r--r-- 1 root root 124 Nov 17 16:46 ifcfg-eth0
[root@ansible-manager /etc/ansible/ansible-playbook]# ssh root@10.0.0.15 'sed -n 6p /tmp/ifcfg-eth0'
IPADDR=10.0.0.12

2. 注册信息

- hosts: 主机IP地址
tasks:
- 模块名称: 参数
register: 变量名 #将指令结果注册至变量
- 模块名称: 参数
debug: msg={{ 变量名.stdout_lines }} #显示变量信息(stdout_lines表示按行标准化输出)
stdout_lines参数在使用时,ansible-playbook -C模拟运行会报错;
- hosts: 10.0.0.15
  vars:
    user_name: www
  tasks:
    - name: Display user info
      command: id {{ user_name }}
      register: user_info
    - name: Display result
      debug:
        msg:
          - "{{ user_info.stdout_lines }}"
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook register.yaml

PLAY [10.0.0.15] *************************************************************************************

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

TASK [Display user info] *****************************************************************************
changed: [10.0.0.15]

TASK [Display result] ********************************************************************************
ok: [10.0.0.15] => {
    "msg": [
        [
            "uid=2000(www) gid=2000(www) groups=2000(www)"
        ]
    ]
}

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

3.循环功能

使用循环功能可以实现一个模块,完成多个操作;

循环方式1

- hosts: 主机IP地址
tasks:
- 模块名称: 参数={{ item }}
with_items:
- 循环值1
- 循环值2
....
- hosts: 10.0.0.15
  tasks:
      - name: Create_User
        user:
          name: "{{ item }}"
          shell: /sbin/nologin
          create_home: no
        with_items:
          - Young01
          - Young02
          - Young03
[root@ansible-manager /etc/ansible/ansible-playbook]# cat cycle_test1.yaml 
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook --syntax-check cycle_test1.yaml 

playbook: cycle_test1.yaml
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook -C cycle_test1.yaml 

PLAY [10.0.0.15] *************************************************************************************

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

TASK [Create_User] ***********************************************************************************
changed: [10.0.0.15] => (item=Young01)
changed: [10.0.0.15] => (item=Young02)
changed: [10.0.0.15] => (item=Young03)

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

循环方式2

- hosts: 主机IP地址
tasks:
- 模块名称: 参数1={{ item.变量名1 }} 参数2={{ item.变量名2 }} 参数3={{ item.变量名3 }}
with_items:
- {变量名1: '变量值', 变量名2: '变量值', 变量名3: '变量值'}
- {变量名1: '变量值', 变量名2: '变量值', 变量名3: '变量值'}
- {变量名1: '变量值', 变量名2: '变量值', 变量名3: '变量值'}
...
- hosts: 10.0.0.15
  tasks:
      - name: Create_User
        user:
          name: "{{ item.name }}"
          shell: "{{ item.shell }}"
          create_home: "{{ item.home }}"
        with_items:
          - {name: 'Young01', shell: '/sbin/nologin', home: 'no'}
          - {name: 'Young02', shell: '/bin/bash', home: 'no'}
          - {name: 'Young03', shell: '/sbin/nologin', home: 'yes'}
          - {name: 'Young04', shell: '/bin/bash', home: 'yes'}
[root@ansible-manager /etc/ansible/ansible-playbook]# cat cycle_test2.yaml
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook --syntax-check cycle_test2.yaml 

playbook: cycle_test2.yaml
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook -C cycle_test2.yaml 

PLAY [10.0.0.15] *************************************************************************************

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

TASK [Create_User] ***********************************************************************************
changed: [10.0.0.15] => (item={u'home': u'no', u'shell': u'/sbin/nologin', u'name': u'Young01'})
changed: [10.0.0.15] => (item={u'home': u'no', u'shell': u'/bin/bash', u'name': u'Young02'})
changed: [10.0.0.15] => (item={u'home': u'yes', u'shell': u'/sbin/nologin', u'name': u'Young03'})
changed: [10.0.0.15] => (item={u'home': u'yes', u'shell': u'/bin/bash', u'name': u'Young04'})

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

4. 判断功能

- hosts: 主机IP地址
tasks:
- 模块名称: 参数
when: (条件 == "值") #条件为真执行
- 模块名称: 参数
when: (条件 != "值") #条件为假执行
- hosts: nfs
  tasks:
    - name: Create File For web01
      copy: 
        content: "Young test ansible_playbook condition function for web01"
        dest: /opt/test.txt
        mode: 755
      when: (ansible_hostname == "web01")
    - name: Create File For Others
      copy: 
        content: "Young test ansible_playbook condition function for Others"
        dest: /opt/test.txt
        mode: 755
      when: (ansible_hostname != "web01")
[root@ansible-manager /etc/ansible/ansible-playbook]# cat condition_test.yaml 
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook condition_test.yaml 

PLAY [nfs] *******************************************************************************************

TASK [Gathering Facts] *******************************************************************************
ok: [10.0.0.15]
ok: [10.0.0.16]
ok: [10.0.0.17]

TASK [Create File For web01] *************************************************************************
skipping: [10.0.0.16]
skipping: [10.0.0.17]
changed: [10.0.0.15]

TASK [Create File For Others] ************************************************************************
skipping: [10.0.0.15]
changed: [10.0.0.16]
changed: [10.0.0.17]

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=2    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
10.0.0.16                  : ok=2    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
10.0.0.17                  : ok=2    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible nfs -a "cat /opt/test.txt"
10.0.0.16 | CHANGED | rc=0 >>
Young test ansible_playbook condition function for Others
10.0.0.15 | CHANGED | rc=0 >>
Young test ansible_playbook condition function for web01
10.0.0.17 | CHANGED | rc=0 >>
Young test ansible_playbook condition function for Others

5. 忽略错误

- hosts: 主机IP地址
tasks:
- 模块名称: 参数
ignore_errors: yes #开启忽略错误功能(仅对当前模块有效)
忽略错误主要作用:
1. ansible-playbook遇到错误时,将会停止执行;使用忽略错误功能,便于整个剧本的调试
2. 当使用shell模块执行操作时,会出现一些合理错误;使用忽略错误功能,便于忽略合理错误
- hosts: 10.0.0.15
  tasks:
    - name: Create user01
      user:
        name: Young01
    - name: Create user02
      shell: useradd Young02
      ignore_errors: yes
    - name: Create user03
      user:
        nam: Young03
      ignore_errors: yes
    - name: Create user04
      shell: useradd Young04
    - name: Create user05
      user:
        name: Young05
[root@ansible-manager /etc/ansible/ansible-playbook]# cat ignoreErr_test.yaml
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook ignoreErr_test.yaml 

PLAY [10.0.0.15] *************************************************************************************

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

TASK [Create user01] *********************************************************************************
ok: [10.0.0.15]

TASK [Create user02] *********************************************************************************
fatal: [10.0.0.15]: FAILED! => {"changed": true, "cmd": "useradd Young02", "delta": "0:00:00.031795", "end": "2021-12-01 09:54:55.574370", "msg": "non-zero return code", "rc": 9, "start": "2021-12-01 09:54:55.542575", "stderr": "useradd: user 'Young02' already exists", "stderr_lines": ["useradd: user 'Young02' already exists"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Create user03] *********************************************************************************
fatal: [10.0.0.15]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (user) module: nam Supported parameters include: append, authorization, comment, create_home, expires, force, generate_ssh_key, group, groups, hidden, home, local, login_class, move_home, name, non_unique, password, password_lock, profile, remove, role, seuser, shell, skeleton, ssh_key_bits, ssh_key_comment, ssh_key_file, ssh_key_passphrase, ssh_key_type, state, system, uid, update_password"}
...ignoring

TASK [Create user04] *********************************************************************************
fatal: [10.0.0.15]: FAILED! => {"changed": true, "cmd": "useradd Young04", "delta": "0:00:00.031879", "end": "2021-12-01 09:54:56.092036", "msg": "non-zero return code", "rc": 9, "start": "2021-12-01 09:54:56.060157", "stderr": "useradd: user 'Young04' already exists", "stderr_lines": ["useradd: user 'Young04' already exists"], "stdout": "", "stdout_lines": []}

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=4    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=2   

6. 标签功能

- hosts: 主机IP地址
tasks:
- 模块名称: 参数
ignore_errors: yes
tags: 标签名 #指定标签名称
标签功能
1. 便于剧本调试时,仅执行指定的模块和操作。使用指令ansible-playbook -t 标记点 剧本名称执行指定模块
2. 常与忽略错误功能一起使用,用于剧本调试。
- hosts: 10.0.0.15
  tasks:
    - name: Create user01
      user:
        name: Young01
      tags: process_01
    - name: Create user02
      shell: useradd Young02
      ignore_errors: yes
      tags: process_02
[root@ansible-manager /etc/ansible/ansible-playbook]# cat tags_test.yaml 
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook -t process_01 tags_test.yaml 

PLAY [10.0.0.15] *************************************************************************************

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

TASK [Create user01] *********************************************************************************
ok: [10.0.0.15]

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook -t process_02 tags_test.yaml 

PLAY [10.0.0.15] *************************************************************************************

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

TASK [Create user02] *********************************************************************************
fatal: [10.0.0.15]: FAILED! => {"changed": true, "cmd": "useradd Young02", "delta": "0:00:00.031879", "end": "2021-12-01 10:13:12.920290", "msg": "non-zero return code", "rc": 9, "start": "2021-12-01 10:13:12.888411", "stderr": "useradd: user 'Young02' already exists", "stderr_lines": ["useradd: user 'Young02' already exists"], "stdout": "", "stdout_lines": []}
...ignoring

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1 

7. 忽略采集功能

该功能不能用于含有判断功能的剧本中;

ansible在执行剧本的时候,默认第一步动作是搜集所有被管理主机信息,随着管理主机的增多,该步骤的耗时将越来越长;为了提了剧本执行效率,可使用忽略采集功能进行提速。
- hosts: 主机IP地址
gather_facts: no #关闭主机信息采集功能
tasks:
- 模块名称: 参数
- hosts: nfs
  gather_facts: no
  tasks:
    - name: Pull file from remote host
      fetch:
        src: /etc/sysconfig/network-scripts/ifcfg-eth0
        dest: /tmp
[root@ansible-manager /etc/ansible/ansible-playbook]# cat disabledGatherFact_test.yaml 
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook disabledGatherFact_test.yaml 

PLAY [nfs] *******************************************************************************************

TASK [Pull file from remote host] ********************************************************************
changed: [10.0.0.15]
changed: [10.0.0.17]
changed: [10.0.0.16]

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
10.0.0.16                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
10.0.0.17                  : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

8. 触发功能

触发器项目处于changed状态时,执行触发器动作
- hosts: 主机IP地址
tasks:
- 模块名称: 参数
notify: 触发器名称 #引用触发器
handlers: #定义触发器
- name: 触发器名称
模块名称: 参数
[root@ansible-manager /etc/ansible/ansible-playbook]# vim trigger_test.yaml 
- hosts: 10.0.0.15
  tasks:
    - name: Delivery config file to host
      copy:
        src: ./rsync/rsyncd.conf
        dest: /etc/rsyncd.conf
      notify: rsyncd_service
    - name: Starting service
      service:
        name: rsyncd
        state: started
  handlers:
    - name: rsyncd_service
      service:
        name: rsyncd
        state: restarted
[root@ansible-manager /etc/ansible/ansible-playbook]# cat trigger_test.yaml 
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook trigger_test.yaml 

PLAY [10.0.0.15] *************************************************************************************

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

TASK [Delivery config file to host] ******************************************************************
ok: [10.0.0.15]

TASK [Starting service] ******************************************************************************
ok: [10.0.0.15]

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible 10.0.0.15 -m shell -a "netstat -lntup|grep [r]sync"
10.0.0.15 | CHANGED | rc=0 >>
tcp        0      0 0.0.0.0:873             0.0.0.0:*               LISTEN      13634/rsync         
tcp6       0      0 :::873                  :::*                    LISTEN      13634/rsync  

[root@ansible-manager /etc/ansible/ansible-playbook]# sed -i s#'port = 873'#'port = 876'#g rsync/rsyncd.conf
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook trigger_test.yaml 

PLAY [10.0.0.15] *************************************************************************************

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

TASK [Delivery config file to host] ******************************************************************
changed: [10.0.0.15]

TASK [Starting service] ******************************************************************************
ok: [10.0.0.15]

RUNNING HANDLER [rsyncd_service] *********************************************************************
changed: [10.0.0.15]

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

[root@ansible-manager /etc/ansible/ansible-playbook]# ansible 10.0.0.15 -m shell -a "netstat -lntup|grep [r]sync"
10.0.0.15 | CHANGED | rc=0 >>
tcp        0      0 0.0.0.0:876             0.0.0.0:*               LISTEN      14490/rsync         
tcp6       0      0 :::876                  :::*                    LISTEN      14490/rsync   

9. 汇总功能

汇总功能是将多个剧本进行整合;

方式一: include_tasks

include_tasks的整合方法用的较少,是因为它所引用的剧本仅能包含tasks下面的任务内容
- hosts: 主机IP地址
tasks:
- include_tasks: 剧本1 #相对于当前剧本的相对路径
- include_tasks: 剧本2
......
# 剧本1
- hosts: 10.0.0.15
s: 10.0.0.15
s:
- name: Create_User
  user:
    name: "{{ item }}"
    shell: /sbin/nologin create_home=no
  with_items:
    - Young01
    - Young02
    - Young03
# 剧本2
[root@ansible-manager /etc/ansible/ansible-playbook]# cat ignoreErr_test.yaml
- name: Create user01
  user:
    name: Young01
- name: Create user02
  shell: useradd Young02
  ignore_errors: yes
- name: Create user03
  user:
    nam: Young03
  ignore_errors: yes
# 合成剧本
- hosts: 10.0.0.15
  tasks:
    - include_tasks: ignoreErr_test.yaml
    - include_tasks: cycle_test1.yaml

- hosts: 
    - 10.0.0.16 
    - 10.0.0.17
  tasks:
    - include_tasks: ignoreErr_test.yaml
[root@ansible-manager /etc/ansible/ansible-playbook]# ansible-playbook include_tasks.yaml 

PLAY [10.0.0.15] *************************************************************************************

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

TASK [include_tasks] *********************************************************************************
included: /etc/ansible/ansible-playbook/ignoreErr_test.yaml for 10.0.0.15

TASK [Create user01] *********************************************************************************
ok: [10.0.0.15]

TASK [Create user02] *********************************************************************************
fatal: [10.0.0.15]: FAILED! => {"changed": true, "cmd": "useradd Young02", "delta": "0:00:00.032157", "end": "2021-12-01 16:54:47.945938", "msg": "non-zero return code", "rc": 9, "start": "2021-12-01 16:54:47.913781", "stderr": "useradd: user 'Young02' already exists", "stderr_lines": ["useradd: user 'Young02' already exists"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Create user03] *********************************************************************************
fatal: [10.0.0.15]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (user) module: nam Supported parameters include: append, authorization, comment, create_home, expires, force, generate_ssh_key, group, groups, hidden, home, local, login_class, move_home, name, non_unique, password, password_lock, profile, remove, role, seuser, shell, skeleton, ssh_key_bits, ssh_key_comment, ssh_key_file, ssh_key_passphrase, ssh_key_type, state, system, uid, update_password"}
...ignoring

TASK [include_tasks] *********************************************************************************
included: /etc/ansible/ansible-playbook/cycle_test1.yaml for 10.0.0.15

TASK [Create_User] ***********************************************************************************
changed: [10.0.0.15] => (item=Young01)
changed: [10.0.0.15] => (item=Young02)
changed: [10.0.0.15] => (item=Young03)

PLAY [10.0.0.16,10.0.0.17] ***************************************************************************

TASK [Gathering Facts] *******************************************************************************
ok: [10.0.0.16]
ok: [10.0.0.17]

TASK [include_tasks] *********************************************************************************
included: /etc/ansible/ansible-playbook/ignoreErr_test.yaml for 10.0.0.16, 10.0.0.17

TASK [Create user01] *********************************************************************************
changed: [10.0.0.17]
changed: [10.0.0.16]

TASK [Create user02] *********************************************************************************
changed: [10.0.0.16]
changed: [10.0.0.17]

TASK [Create user03] *********************************************************************************
fatal: [10.0.0.17]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (user) module: nam Supported parameters include: append, authorization, comment, create_home, expires, force, generate_ssh_key, group, groups, hidden, home, local, login_class, move_home, name, non_unique, password, password_lock, profile, remove, role, seuser, shell, skeleton, ssh_key_bits, ssh_key_comment, ssh_key_file, ssh_key_passphrase, ssh_key_type, state, system, uid, update_password"}
...ignoring
fatal: [10.0.0.16]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (user) module: nam Supported parameters include: append, authorization, comment, create_home, expires, force, generate_ssh_key, group, groups, hidden, home, local, login_class, move_home, name, non_unique, password, password_lock, profile, remove, role, seuser, shell, skeleton, ssh_key_bits, ssh_key_comment, ssh_key_file, ssh_key_passphrase, ssh_key_type, state, system, uid, update_password"}
...ignoring

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=7    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=2   
10.0.0.16                  : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1   
10.0.0.17                  : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1   

方式2: include

- include: 剧本1 #相对于当前剧本的相对路径
- include: 剧本2
......
- hosts: 10.0.0.15
  vars:
    user_name: www
  tasks:
    - name: Display user info 
      command: id {{ user_name }}
      register: user_info
    - name: Display result
      debug: 
        msg: 
          - "{{ user_info.stdout_lines }}"
- hosts: 10.0.0.15
  tasks:
      - name: Create_User
        user:
          name: "{{ item }}"
          shell: /sbin/nologin
          create_home: no
        with_items:
          - Young01
          - Young02
          - Young03
- include: ansible-playbook/cycle_test1.yaml
- include: ansible-playbook/register_test.yaml
[root@ansible-manager /etc/ansible]# ansible-playbook include.yaml 
[DEPRECATION WARNING]: 'include' for playbook includes. You should use 'import_playbook' instead. 
This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting 
deprecation_warnings=False in ansible.cfg.

PLAY [10.0.0.15] *************************************************************************************

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

TASK [Create_User] ***********************************************************************************
changed: [10.0.0.15] => (item=Young01)
changed: [10.0.0.15] => (item=Young02)
changed: [10.0.0.15] => (item=Young03)

PLAY [10.0.0.15] *************************************************************************************

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

TASK [Display user info] *****************************************************************************
changed: [10.0.0.15]

TASK [Display result] ********************************************************************************
ok: [10.0.0.15] => {
    "msg": [
        [
            "uid=2000(www) gid=2000(www) groups=2000(www)"
        ]
    ]
}

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

方式3: import_playbook

- import_playbook: 剧本1 #相对于当前剧本的相对路径
- import_playbook: 剧本2
......
- import_playbook: ansible-playbook/cycle_test1.yaml
- import_playbook: ansible-playbook/register_test.yaml
[root@ansible-manager /etc/ansible]# ansible-playbook import_playbook.yaml 

PLAY [10.0.0.15] *************************************************************************************

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

TASK [Create_User] ***********************************************************************************
ok: [10.0.0.15] => (item=Young01)
ok: [10.0.0.15] => (item=Young02)
ok: [10.0.0.15] => (item=Young03)

PLAY [10.0.0.15] *************************************************************************************

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

TASK [Display user info] *****************************************************************************
changed: [10.0.0.15]

TASK [Display result] ********************************************************************************
ok: [10.0.0.15] => {
    "msg": [
        [
            "uid=2000(www) gid=2000(www) groups=2000(www)"
        ]
    ]
}

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=5    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

六、ansible-playbook角色

ansible-playbook角色功能是由ansible公司提出的剧本规划化配置
  • 名称规范
  • 目录规范

1. 规范化操作流程

本文以rsyncd服务部署为例

/etc/ansible/roles目录下创建,角色目录;目录名称可自定义。

step 01 创建角色目录

mkdir 角色名 #为角色创建子目录
[root@ansible-manager /etc/ansible]# cd 
[root@ansible-manager ~]# cd /etc/ansible/roles/
[root@ansible-manager /etc/ansible/roles]# mkdir rsync

step 02 在角色目录中创建规范化子目录

mkdir {tasks,handlers,vars,files,templates} #为角色创建子目录
tasks #包含觉得需要执行的主要任务列表
handlers #包含处理程序,可以由此角色使用,甚至可以在此角色之外的任何位置使用
defaults #角色的默认变量
vars #角色的其他变量
files #包含可以通过此角色部署的文件
templates #包含可以通过此角色部署的模板
meta #为此角色定义一些元数据
[root@ansible-manager /etc/ansible/roles]# cd rsync/
[root@ansible-manager /etc/ansible/roles/rsync]# mkdir {tasks,vars,files,handlers,templates}
[root@ansible-manager /etc/ansible/roles/rsync]# tree .
.
├── files
├── handlers
├── tasks
├── templates
└── vars

5 directories, 0 files

step 03 进入tasks目录,创建剧本主体任务

vim main.yaml #剧本名称必须为main.yaml
[root@ansible-manager /etc/ansible/roles/rsync]# cd tasks/
[root@ansible-manager /etc/ansible/roles/rsync/tasks]# vim main.yml
# Server
- name: Install rsync service
  yum:
    name: rsync
    state: installed
- name: Delivery File
  copy:
    src: "{{ item.src }}"
    dest: "{{ Dest_path }}"
    mode: "{{ item.mode }}"
  with_items:
    - {src: 'rsyncd.conf',            mode: '644'}
    - {src: 'rsyncd_server.password', mode: '600'}
  notify: rsyncd_restart
  when: (ansible_hostname == "web01")
- name: Create virtual user for rsync
  user:
    name: rsync
    shell: /sbin/nologin
    create_home: no
  when: (ansible_hostname == "web01")
- name: Create directory for backup
  file:
    path: "{{  item.path }}"
    state: directory
    owner: "{{ item.owner }}"
    group: "{{ item.group }}"
  with_items:
    - {path: '/backup', owner: 'rsync', group: 'rsync'}
  when: (ansible_hostname == "web01")
- name: Start service
  service: 
    name: rsyncd
    state: started
    enabled: yes
  when: (ansible_hostname == "web01")
- name: register port info
  shell: netstat -lntup | grep [r]sync
  register: Port_info
  tags: Check_Port
  when: (ansible_hostname == "web01")
- name: Check service port
  debug:
    msg: 
      - "{{ Port_info.stdout_lines }}"
  when: (ansible_hostname == "web01")
  tags: Display_Port

#Client
- name: Delivery password for client
  copy:
    content: "{{ Rsync_password}}"
    dest: "{{ Dest_path }}rsync_client.password"
    mode: 600
  when: (ansible_hostname != "web01")

step 04 进入vars目录,定义相关变量参数

vim main.yaml #剧本名称必须为main.yaml
[root@ansible-manager /etc/ansible/roles/rsync/tasks]# cd ../vars/
[root@ansible-manager /etc/ansible/roles/rsync/vars]# vim main.yaml
Dest_path: /etc/
Rsync_password: '123456'

step 05 进入files目录,整理剧本需分发的文件

[root@ansible-manager /etc/ansible/roles/rsync/vars]# cd ../files/
[root@ansible-manager /etc/ansible/roles/rsync/files]# cp -rp ../../../ansible-playbook/rsync/rsyncd.conf .
[root@ansible-manager /etc/ansible/roles/rsync/files]# echo "rsync_backup:123456" >rsyncd_server.password
[root@ansible-manager /etc/ansible/roles/rsync/files]# ls
rsyncd.conf  rsyncd_server.password

step 06 进入handlers目录,定义触发器操作

vim main.yaml #剧本名称必须为main.yaml
[root@ansible-manager /etc/ansible/roles/rsync/files]# cd ../handlers/
[root@ansible-manager /etc/ansible/roles/rsync/handlers]# vim main.yaml
- name: rsyncd_restart
  service:
    name: rsyncd
    state: restarted

step 07 进入roles目录,创建汇总剧本

- hosts: 主机IP地址
roles:
- 角色名1
- 角色名2
......
- hosts: rsync
  roles:
    - rsync
[root@ansible-manager /etc/ansible/roles]# cat execute_rsync.yml
[root@ansible-manager /etc/ansible/roles]# sed s#'port = 873'#'port = 874'#g rsync/files/rsyncd.conf -i
[root@ansible-manager /etc/ansible/roles]# ansible-playbook  execute_rsync.yml 

PLAY [rsync] *****************************************************************************************

TASK [Gathering Facts] *******************************************************************************
ok: [10.0.0.17]
ok: [10.0.0.15]
ok: [10.0.0.16]

TASK [Install rsync service] *************************************************************************
ok: [10.0.0.16]
ok: [10.0.0.17]
ok: [10.0.0.15]

TASK [rsync : Delivery File] *************************************************************************
skipping: [10.0.0.16] => (item={u'src': u'rsyncd.conf', u'mode': u'644'}) 
skipping: [10.0.0.16] => (item={u'src': u'rsyncd_server.password', u'mode': u'600'}) 
skipping: [10.0.0.17] => (item={u'src': u'rsyncd.conf', u'mode': u'644'}) 
skipping: [10.0.0.17] => (item={u'src': u'rsyncd_server.password', u'mode': u'600'}) 
changed: [10.0.0.15] => (item={u'src': u'rsyncd.conf', u'mode': u'644'})
ok: [10.0.0.15] => (item={u'src': u'rsyncd_server.password', u'mode': u'600'})

TASK [Create virtual user for rsync] *****************************************************************
skipping: [10.0.0.16]
skipping: [10.0.0.17]
ok: [10.0.0.15]

TASK [rsync : Create directory for backup] ***********************************************************
skipping: [10.0.0.16] => (item={u'owner': u'rsync', u'path': u'/backup', u'group': u'rsync'}) 
skipping: [10.0.0.17] => (item={u'owner': u'rsync', u'path': u'/backup', u'group': u'rsync'}) 
ok: [10.0.0.15] => (item={u'owner': u'rsync', u'path': u'/backup', u'group': u'rsync'})

TASK [rsync : Start service] *************************************************************************
skipping: [10.0.0.16]
skipping: [10.0.0.17]
ok: [10.0.0.15]

TASK [rsync : register port info] ********************************************************************
skipping: [10.0.0.16]
skipping: [10.0.0.17]
changed: [10.0.0.15]

TASK [rsync : Check service port] ********************************************************************
ok: [10.0.0.15] => {
    "msg": [
        [
            "tcp        0      0 0.0.0.0:873             0.0.0.0:*               LISTEN      11493/rsync         ", 
            "tcp6       0      0 :::873                  :::*                    LISTEN      11493/rsync         "
        ]
    ]
}
skipping: [10.0.0.16]
skipping: [10.0.0.17]

TASK [rsync : Delivery password for client] **********************************************************
skipping: [10.0.0.15]
ok: [10.0.0.17]
ok: [10.0.0.16]

RUNNING HANDLER [rsyncd_restart] *********************************************************************
changed: [10.0.0.15]

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=9    changed=3    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
10.0.0.16                  : ok=3    changed=0    unreachable=0    failed=0    skipped=6    rescued=0    ignored=0   
10.0.0.17                  : ok=3    changed=0    unreachable=0    failed=0    skipped=6    rescued=0    ignored=0   

[root@ansible-manager /etc/ansible/roles]# ansible-playbook -t Check_Port -t Display_Port execute_rsync.yml 

PLAY [rsync] *****************************************************************************************

TASK [Gathering Facts] *******************************************************************************
ok: [10.0.0.15]
ok: [10.0.0.16]
ok: [10.0.0.17]

TASK [rsync : register port info] ********************************************************************
skipping: [10.0.0.16]
skipping: [10.0.0.17]
changed: [10.0.0.15]

TASK [rsync : Check service port] ********************************************************************
ok: [10.0.0.15] => {
    "msg": [
        [
            "tcp        0      0 0.0.0.0:874             0.0.0.0:*               LISTEN      13091/rsync         ", 
            "tcp6       0      0 :::874                  :::*                    LISTEN      13091/rsync         "
        ]
    ]
}
skipping: [10.0.0.16]
skipping: [10.0.0.17]

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
10.0.0.16                  : ok=1    changed=0    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0   
10.0.0.17                  : ok=1    changed=0    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0 

2. 角色说明

角色的主要用于实现剧本,任务一键化执行,进行批量管理;并且在一键化执行过程中,规划要求整个剧本文件目录的目录结构以及 剧本名称

剧本执行过程

templates目录说明

templates目录用于保存模板配置文件;在templates中保存的配置文件可以引用vars/main.yml中的变量;
注意:分发templates目录中的文件,需要调用变量,需使用template模块替换copy模块;两者参数基本一致

NFS 一键化部署配置规范化案例


# summary
- hosts: nfs
  roles:
    - nfs

# tasks
- name: Install Services
  yum:
    name:
      - rpcbind
      - nfs-utils
    state: installed
- name: Create nfs group
  group:
    name: "{{ Nfs_name }}"
    gid: "{{ Nfs_ID }}"
- name: Create nfs user
  user:
    name: "{{ Nfs_name }}"
    shell: /sbin/nologin
    create_home: no
    group: "{{ Nfs_ID }}"
    uid: "{{ Nfs_ID }}"
- name: Create shared directory
  file:
    path: "{{ item }}"
    state: directory
    owner: "{{ Nfs_name }}"
    group: "{{ Nfs_name }}"
  with_items:
    - /backup/www/test
  when: (ansible_hostname == 'web01')
- name: Delivery config file
  template:
    src: exports
    dest: "{{ Dest_dir  }}"
  notify: restart_nfs
  when: (ansible_hostname == 'web01')
- name: Start service
  service:
    name: "{{ item }}"
    state: started
    enabled: yes
  with_items:
    - rpcbind
    - nfs-server
  when: (ansible_hostname == 'web01')
- name: Create mount point
  file:
    path: "{{ item }}"
    state: directory
  with_items:
    - /var/www/test_dir
  when: (ansible_hostname != 'web01')
- name: Mount NFS file system
  mount:
    src: "{{ NfsS_IP }}:{{ item.srcdir }}"
    path: "{{ item.dstdir }}"
    fstype: nfs
    state: mounted
  with_items:
    - {srcdir: '/backup/www/test', dstdir: '/var/www/test_dir'}
  when: (ansible_hostname != 'web01')
- name: Check info
  shell: "tail -1 /etc/fstab"
  register: mount_info
- name: Display info
  debug:
    msg:
      - "{{ mount_info.stdout_lines }}"

# vars
[root@ansible-manager /etc/ansible/roles]# cat nfs/vars/main.yml 
Nfs_ID: "3000"
Nfs_name: test
Dest_dir: /etc/
NfsS_IP: 172.16.1.15
Shared_dir: /backup/www/test
Shared_ip: 172.16.1.0/24

# handlers
- name: restart_nfs
  service:
    name:  nfs-server
    state: reloaded
[root@ansible-manager /etc/ansible/roles]# cat nfs/templates/exports 
{{Shared_dir}} {{ Shared_ip}}(rw,sync,anonuid={{ Nfs_ID }},anongid={{ Nfs_ID }})

[root@ansible-manager /etc/ansible/roles]# tree nfs
nfs
├── files
├── handlers
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
│   └── exports
└── vars
    └── main.yml

5 directories, 4 files

[root@ansible-manager /etc/ansible/roles]# ansible-playbook --syntax-check execute_nfs.yml 
[WARNING]: Could not match supplied host pattern, ignoring: nfs

playbook: execute_nfs.yml
[root@ansible-manager /etc/ansible/roles]# ansible-playbook -i hosts execute_nfs.yml 

PLAY [nfs] *******************************************************************************************

TASK [Gathering Facts] *******************************************************************************
ok: [10.0.0.17]
ok: [10.0.0.15]
ok: [10.0.0.16]

TASK [nfs : Install Services] ************************************************************************
ok: [10.0.0.15]
ok: [10.0.0.16]
ok: [10.0.0.17]

TASK [Create nfs group] ******************************************************************************
ok: [10.0.0.16]
ok: [10.0.0.17]
ok: [10.0.0.15]

TASK [Create nfs user] *******************************************************************************
ok: [10.0.0.16]
ok: [10.0.0.17]
ok: [10.0.0.15]

TASK [nfs : Create shared directory] *****************************************************************
skipping: [10.0.0.16] => (item=/backup/www/test) 
skipping: [10.0.0.17] => (item=/backup/www/test) 
ok: [10.0.0.15] => (item=/backup/www/test)

TASK [nfs : Delivery config file] ********************************************************************
skipping: [10.0.0.16]
skipping: [10.0.0.17]
changed: [10.0.0.15]

TASK [nfs : Start service] ***************************************************************************
skipping: [10.0.0.16] => (item=rpcbind) 
skipping: [10.0.0.16] => (item=nfs-server) 
skipping: [10.0.0.17] => (item=rpcbind) 
skipping: [10.0.0.17] => (item=nfs-server) 
ok: [10.0.0.15] => (item=rpcbind)
ok: [10.0.0.15] => (item=nfs-server)

TASK [nfs : Create mount point] **********************************************************************
skipping: [10.0.0.15] => (item=/var/www/test_dir) 
ok: [10.0.0.17] => (item=/var/www/test_dir)
ok: [10.0.0.16] => (item=/var/www/test_dir)

TASK [nfs : Mount NFS file system] *******************************************************************
skipping: [10.0.0.15] => (item={u'dstdir': u'/var/www/test_dir', u'srcdir': u'/backup/www/test'}) 
changed: [10.0.0.16] => (item={u'dstdir': u'/var/www/test_dir', u'srcdir': u'/backup/www/test'})
changed: [10.0.0.17] => (item={u'dstdir': u'/var/www/test_dir', u'srcdir': u'/backup/www/test'})

TASK [nfs : Check info] ******************************************************************************
changed: [10.0.0.16]
changed: [10.0.0.17]
changed: [10.0.0.15]

TASK [nfs : Display info] ****************************************************************************
ok: [10.0.0.15] => {
    "msg": [
        [
            "UUID=42eaa7c4-975b-4c3a-8301-1e4543eb730e swap                    swap    defaults        0 0"
        ]
    ]
}
ok: [10.0.0.16] => {
    "msg": [
        [
            "172.16.1.15:/backup/www/test /var/www/test_dir nfs defaults 0 0"
        ]
    ]
}
ok: [10.0.0.17] => {
    "msg": [
        [
            "172.16.1.15:/backup/www/test /var/www/test_dir nfs defaults 0 0"
        ]
    ]
}

RUNNING HANDLER [restart_nfs] ************************************************************************
changed: [10.0.0.15]

PLAY RECAP *******************************************************************************************
10.0.0.15                  : ok=10   changed=3    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0   
10.0.0.16                  : ok=8    changed=2    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0   
10.0.0.17                  : ok=8    changed=2    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0  

[root@ansible-manager /etc/ansible/roles]# ansible 10.0.0.15 -m shell -a "cat /etc/exports"
10.0.0.15 | CHANGED | rc=0 >>
/backup/www/test 172.16.1.0/24(rw,sync,anonuid=3000,anongid=3000)