自动化运维工具:ansible

1、运维自动化发展历程及技术应用
  本地部署:On-Premises
  基础设施即服务:IaaS(Infrastructure as a Service)
  平台即服务:PaaS(Platform as a Service)
  软件即服务:SaaS(Software as a Service)

2、自动化运维应用场景
  1>文件传输
  2>命令执行
    应用部署
    配置管理
    任务流编排
  3>程序发布
    预发布:新版本的代码先发布到服务器(跟线上环境完全相同,只是未接入调度器)
    程序发布:不能导致系统故障或造成系统完全不可用;不能影响用户体验
    灰度发布:先发布1/10的服务器,面向少量精准用户,在逐渐增多
    发布路径:
      /nginx1.1
      nginx(软链接)
      /nginx1.2
      在调度机上将一台real-server置为down,停止旧版本的服务,删除旧的软链接,启动新的服务,创建新的软链接,在调度器启用这一批服务器
    自动化灰度发布:脚本、发布平台

3、ansible特性
  1>模块化,有Paramiko,PyYAML,jinja2(模块语言)三个关键模块,支持自定义模块
  2>基于Python语言实现,部署简单,基于python和ssh(默认安装),安全、agentless(无代理,不需要配置代理,主控端直接控制被控端)
  3>支持playbook编排任务
  4>幂等性:一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况
  5>无需代理不依赖PKI(无需ssl)
  6>可使用任何编程语言写模块
  7>YAML格式,编排任务,支持丰富的数据结构
  8>较强大的多层解决方案(角色)

4、ansible架构及工作原理

 

 

 

 

 

5、ansible主要组成部分
  ansible playbook:任务剧本(任务集),编排定义Ansible任务集的配置文件,由Ansible顺序依次执行,通常是JSON格式的YML文件
  inventory:Ansible管理主机的清单/etc/anaible/hosts
  modules:Ansible执行命令的功能模块,多数为内置核心模块,也可自定义
  plugins:模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用
  API:供第三方程序调用的应用程序编程接口
  ANSIBLE:组合INVENTORY、API、 MODULES、PLUGINS的绿框,可以理解为是ansible命令工具,其为核心执行工具

6、Ansible命令执行来源:
  USER,普通用户,即SYSTEM ADMINISTRATOR
  CMDB (配置管理数据库) API 调用
  PUBLIC/PRIVATE CLOUD API调用
  USER → Ansible Playbook → Ansibile

7、利用ansible实现管理的方式:
  Ad-Hoc即ansible命令,主要用于临时命令使用场景
  Ansible-playbook主要用于长期规划好的,大型项目的场景,需要有前提的规划
  Ansible-playbook (剧本) 执行过程:
    将已有编排好的任务集写入Ansible-Playbook
    通过ansible-playbook命令分拆任务集至逐条ansible命令,按预定规则逐条执行
  Ansible主要操作对象:
    HOSTS主机
    NETWORKING网络设备
  注意事项:
  ➢执行ansible的主机一般称为主控端,中控,master或堡垒机
  ➢主控端Python版本需要2.6或以上
  ➢被控端Python版本小于2.4需要安装python-simplejson
  ➢被控端如开启SELinux需要安装libselinux-python
  ➢windows不能做为主控端

8、安装(本机采用rpm安装,实验)
  1>rpm包安装:EPEL源

yum install ansible -y

  2>编译安装:

yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
tar xf ansible-1.5.4.tar.gz
cd ansible-1.5.4
python setup.py build
python setup.py install
mkdir /etc/ansible
cp -r examples/* /etc/ansible

  3>Git方式:

git clone git://github.com/ansible/ansible.git --recursive
cd ./ansible
source ./hacking/env-setup

  4>pip安装:pip是安装Python包的管理器,类似yum

yum install python-pip python-devel
yum install gcc glibc-devel zibl-devel rpm-bulid openssl-devel
pip install --upgrade pip
pip install ansible --upgrade

  5>确认安装: ansible --version

9、相关文件
  1>配置文件
    /etc/ansible/ansible.cfg    主配置文件,配置ansible工作特性
    /etc/ansible/hosts             主机清单
    /etc/ansible/roles/             存放角色的目录
  2>程序
    /usr/bin/ansible                 主程序,临时命令执行工具
    /usr/bin/ansible-doc           查看配置文档,模块功能查看工具
    /usr/bin/ansible-galaxy      下载/上传优秀代码或Roles模块的官网平台
    /usr/bin/ansible-playbook  定制自动化任务,编排剧本工具/usr/bin/ansible-pull远程执行命令的工具
    /usr/bin/ansible-vault         文件加密工具
    /usr/bin/ansible-console    基于Console界面与用户交互的执行工具
  3>主机清单inventory
    Inventory主机清单
    ansible的主要功用在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory file中将其分组命名
    默认的inventory file为/etc/ansible/hosts
    inventory file可以有多个,且也可以通过Dynamic Inventory来动态生成

  4>/etc/ansible/hosts文件格式
  inventory文件遵循INI文件风格,中括号中的字符为组名。可以将同一个主机同时归并到多个不同的组中;此外,当如若目标主机使用了非默认的SSH端口,还可以在主机名称之后使用冒号加端口号来标明

[root@ansible ~]#vim /etc/ansible/hosts

 

 

   也可以配置域名解析,使用域名代替ip,如果ssh默认端口号有改动不是22端口,则 ip/域名:端口

  Ansible配置文件
  Ansible配置文件/etc/ansible/ansible.cfg (一般保持默认)

[defaults]
#inventory = /etc/ansible/hosts     #主机列表配置文件
#library = /usr/share/my_modules/   #库文件存放目录
#remote_tmp = $HOME/.ansible/tmp    #临时py命令文件存放在远程主机目录
#local_tmp = $HOME/.ansible/tmp     #本机的临时命令执行目录
#forks = 5                          #默认并发数
#sudo_user = root                   #默认sudo用户
#ask_sudo_pass = True               #每次执行ansible命令是否询问ssh密码
#ask_pass = True
#remote_port = 22
#host_key_checking = False          #检查对应服务器的host_key,建议取消注释,要不然得先建立连接(/root/.ssh/known_hosts)Ansible才能连接成功
#log_path=/var/log/ansible.log      #日志文件

  Ansible配置文件保持默认,建议开启:host_key_checking = False,log_path=/var/log/ansible.log

10、Ansible系列命令
  ansible ansible-doc ansible-playbook ansible-vault ansible-console ansible-galaxy ansible-pull
  ansible-doc 显示模块帮助
  ansible-doc [options] [module...]
    -a 显示所有模块的文档
    -l,--list 列出可用模块
    -s,--snippet显示指定模块的playbook片段
  示例:

ansible-doc -l      列出所有模块
ansible-doc ping    查看指定模块帮助用法
ansible-doc -s ping 查看指定模块帮助用法(短帮助)

 

  ansible通过ssh实现配置管理、应用部署、任务执行等功能,建议配置ansible端能基于密钥认证的方式联系各被管理节点
  ansible <host-pattern> [-m module_name] [-a args]
    --version显示版本
    -m module指定模块,默认为command
    -v详细过程-vv -vvv更详细
    --list-hosts显示主机列表,可简写-list
    -k, --ask-pass提示输入ssh连接密码,默认Key验证
    -K, --ask-become-pass提示输入sudo时的口令
    -C, --check检查,并不执行
    -T, --timeout=TIMEOUT执行命令的超时时间,默认10s
    -u, --user=REMOTE_USER执行远程执行的用户
    -b, --become代替旧版的sudo切换

[root@ansible ~]#ansible 192.168.100.10 -m ping -k    #-m:指定模块,-k:指定k口令验证
SSH password: 
192.168.100.10 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

[root@ansible ~]#ansible all --list    #列出主机列表
  hosts (2):
    192.168.100.10
    192.168.100.20
[root@ansible ~]#ansible all -m ping -u yang -k    #以yang用户身份执行ping
SSH password: 
192.168.100.20 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.100.10 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[root@ansible ~]#ansible all -k -u yang -b -K -m command -a 'ls /root'    #以yang用户身份执行ls /root,-b即sudo切换身份,-K输入sudo时的口令
SSH password: 
BECOME password[defaults to SSH password]: 
192.168.100.20 | CHANGED | rc=0 >>
anaconda-ks.cfg
jdk-8u221-linux-x64.tar.gz
192.168.100.10 | CHANGED | rc=0 >>
anaconda-ks.cfg


设置基于key验证:
[root@ansible ~]#ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):     #设置空,为了安全建议进行进一步设置
Enter passphrase (empty for no passphrase):                  #设置空
Enter same passphrase again:                                 #设置空
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:nHRFKqBQ/jceNpkOFfoVLKbE+hVchYw25FKG8m3eFeM root@ansible.localdomain
The key's randomart image is:
+---[RSA 2048]----+
|  .....+==o++    |
|   o..+*O.++o    |
|    o=o==++. o   |
|    ..o*+B  E    |
|     .o+S. .     |
|      .*.+.      |
|        o        |
|                 |
|                 |
+----[SHA256]-----+
[root@ansible ~]#ssh-copy-id 192.168.100.10    #拷贝至192.168.100.10
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.100.10's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh '192.168.100.10'"
and check to make sure that only the key(s) you wanted were added.

[root@ansible ~]#ssh-copy-id 192.168.100.20    #拷贝至192.168.100.20
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.100.20's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh '192.168.100.20'"
and check to make sure that only the key(s) you wanted were added.
[root@ansible
~]#ansible all -m ping #基于key验证不需要在输入key口令 192.168.100.20 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" } 192.168.100.10 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" }

 


  ansible的Host-pattern
  匹配主机的列表
  All:表示所有Inventory中的所有主机

[root@ansible ~]#ansible all --list
  hosts (2):
    192.168.100.10
    192.168.100.20

   *:通配符
  ansible "*" -m ping
  ansible 192.168.100.* -m ping
  ansible "*server" -m ping

 

[root@ansible ~]#ansible *server -m ping
192.168.100.20 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.100.10 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

 

  或关系
  ansible "webserver:dbserver" -m ping
  ansible "192.168.100.10:192.168.100.20" -m ping

 

[root@ansible ~]#ansible "webserver:dbserver" -m ping
192.168.100.20 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.100.10 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

 

  逻辑与
  ansible "webserver:&dbserver" -m ping
  在webserver组并且在dbserver组中的主机
  逻辑非
  ansible 'webserver:!dbserver' -m ping
  在webserver组,但不在dbserver组中的主机
  注意:此处为单引号
  综合逻辑
  ansible 'webserver:dbserver:&appserver:!ftpserver' -m ping
  正则表达式
  ansible "webserver:&dbserver" -m ping
  ansible“ ~(web|db).*\.yang\.com”-m ping

11、Ansible命令执行过程
  1.加载自己的配置文件默认/etc/ansible/ansible.cfg
  2.加载自己对应的模块文件,如command
  3.通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
  4.给文件+x执行
  5.执行并返回结果
  6.删除临时py文件,sleep 0退出
  执行状态:
    绿色:执行成功并且不需要做改变的操作
    黄色:执行成功并且对目标主机做变更
    红色:执行失败

12、Ansible常见模块

  各种模块的使用,可以ansible-doc -s service先查看帮助,再进行使用
  1>command模块:在远程主机执行命令,默认模块,可忽略-m选项

[root@ansible ~]#ansible all -m command -a 'hostname'
192.168.100.20 | CHANGED | rc=0 >>
node-2
192.168.100.10 | CHANGED | rc=0 >>
node-1
[root@ansible ~]#ansible all -m command -a 'echo yang | passwd --stdin yang'
192.168.100.20 | CHANGED | rc=0 >>
yang | passwd --stdin yang    #没有成功,当字符串打印出来了
192.168.100.10 | CHANGED | rc=0 >>
yang | passwd --stdin yang    #没有成功,当字符串打印出来了

  此命令不支持$VARNAME < > | ; & 等,需要使用shelI模块实现

  2>shell模块:和command相似,用shell执行命令

[root@ansible ~]#ansible all -m shell -a 'echo yang | passwd --stdin yang'
192.168.100.20 | CHANGED | rc=0 >>
更改用户 yang 的密码 。
passwd:所有的身份验证令牌已经成功更新。
192.168.100.10 | CHANGED | rc=0 >>
更改用户 yang 的密码 。
passwd:所有的身份验证令牌已经成功更新。

  调用bash执行命令类似cat /tmp/stanley.md | awk -F'|' '{print $1,$2}' &>/tmp/example.txt 这些复杂命令,即使使用shell也可能会失败,解决办法:写到脚本,copy到远程,执行,再把需要的结果拉回执行命令的机器

  3>script模块:运行脚本
  -a "/PATH/TO/SCRIPT_FILE"

[root@ansible ~]#./hello.sh     #当前Ansible机器上的脚本:实现打印hello,输出主机名
hello
my hostname is ansible.localdomain
[root@ansible ~]#ansible all -m script -a '/root/hello.sh'
192.168.100.20 | CHANGED => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 192.168.100.20 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 192.168.100.20 closed."
    ], 
    "stdout": "hello\r\nmy hostname is node2.localdomain\r\n", 
    "stdout_lines": [
        "hello", 
        "my hostname is node2.localdomain"
    ]
}
192.168.100.10 | CHANGED => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 192.168.100.10 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 192.168.100.10 closed."
    ], 
    "stdout": "hello\r\nmy hostname is node1.localdomain\r\n", 
    "stdout_lines": [
        "hello", 
        "my hostname is node1.localdomain"
    ]
}

  4>copy模块:从服务器复制文件到客户端

[root@ansible ~]#ansible all -m copy -a 'src=/root/hello.sh dest=/root/'    #src:指定源文件  dest:指定目标文件存放目录
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "63ff849c6cde8cd1eef04e0472e832d8407eca00", 
    "dest": "/root/hello.sh", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "c426adca4193658a2183f59d726cc2dc", 
    "mode": "0644", 
    "owner": "root", 
    "size": 58, 
    "src": "/root/.ansible/tmp/ansible-tmp-1584450232.18-80008690840068/source", 
    "state": "file", 
    "uid": 0
}
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "63ff849c6cde8cd1eef04e0472e832d8407eca00", 
    "dest": "/root/hello.sh", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "c426adca4193658a2183f59d726cc2dc", 
    "mode": "0644", 
    "owner": "root", 
    "size": 58, 
    "src": "/root/.ansible/tmp/ansible-tmp-1584450232.14-44687748938829/source", 
    "state": "file", 
    "uid": 0
}

node1节点查看:
[root@node1 ~]# ll
total 8
-rw-------. 1 root root 1557 Sep 28 22:49 anaconda-ks.cfg
-rw-r--r--  1 root root   58 Mar 17 21:03 hello.sh

删除node节点的hello.sh文件,重新创建个同名文件,再使用ansible复制,如目标存在,默认覆盖,此处backup=yes指定先备份(ansible有幂等性特点)
[root@ansible ~]#ansible all -m copy -a 'src=/root/hello.sh dest=/root/ backup=yes mode=+x' #src:指定源文件 dest:指定目标文件存放目录 backup=yes:如果目标文件存在则进行备份
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "63ff849c6cde8cd1eef04e0472e832d8407eca00",
    "dest": "/root/hello.sh",
    "gid": 0,
    "group": "root",
    "mode": "0755",
    "owner": "root",
    "path": "/root/hello.sh",
    "size": 58,
    "state": "file",
    "uid": 0
}
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "checksum": "63ff849c6cde8cd1eef04e0472e832d8407eca00",
    "dest": "/root/hello.sh",
    "gid": 0,
    "group": "root",
    "mode": "0755",
    "owner": "root",
    "path": "/root/hello.sh",
    "size": 58,
    "state": "file",
    "uid": 0
}


[root@ansible ~]#ansible all -a 'ls /root/'
192.168.100.20 | CHANGED | rc=0 >>
anaconda-ks.cfg
hello.sh
hello.sh.4160.2020-03-17@21:14:23~ #原文件存在,被备份
jdk-8u221-linux-x64.tar.gz
192.168.100.10 | CHANGED | rc=0 >>
anaconda-ks.cfg
hello.sh
hello.sh.4604.2020-03-17@21:14:22~ #原文件存在,被备份

  5>Fetch模块:从客户端取文件至服务器端,copy相反,目录可先tar

[root@ansible ~]#mkdir /data    #先创建一个/data目录,存放抓取过来的文件
[root@ansible ~]#ansible all -m fetch -a 'src=/root/anaconda-ks.cfg dest=/data'
192.168.100.10 | CHANGED => {
    "changed": true, 
    "checksum": "c324508ffa651d64f4fa6286fb74ec438e283b3b", 
    "dest": "/data/192.168.100.10/root/anaconda-ks.cfg", 
    "md5sum": "b1c0bd6a556fac4e120fddcc7d1124df", 
    "remote_checksum": "c324508ffa651d64f4fa6286fb74ec438e283b3b", 
    "remote_md5sum": null
}
192.168.100.20 | CHANGED => {
    "changed": true, 
    "checksum": "4a2e5b1e34c5496d9dcebbb9a1b7ece8b6b03950", 
    "dest": "/data/192.168.100.20/root/anaconda-ks.cfg", 
    "md5sum": "32435d070271e8018672e21ae7c2acbb", 
    "remote_checksum": "4a2e5b1e34c5496d9dcebbb9a1b7ece8b6b03950", 
    "remote_md5sum": null
}
[root@ansible ~]#tree /data/
/data/
├── 192.168.100.10
│   └── root
│       └── anaconda-ks.cfg
└── 192.168.100.20
    └── root
        └── anaconda-ks.cfg

4 directories, 2 files

  6>File模块:设置文件属性

[root@ansible ~]#ansible all -a 'ls /data'
192.168.100.20 | FAILED | rc=2 >>
ls: 无法访问/data: 没有那个文件或目录non-zero return code
192.168.100.10 | FAILED | rc=2 >>
ls: 无法访问/data: 没有那个文件或目录non-zero return code
[root@ansible ~]#ansible all -m shell -a 'mkdir /data'    #可以看到我们使用shell,创建目录,建议我们使用file模块创建目录
[WARNING]: Consider using the file module with state=directory rather than running
'mkdir'.  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.
192.168.100.10 | CHANGED | rc=0 >>

192.168.100.20 | CHANGED | rc=0 >>

[root@ansible ~]#ansible all -a 'ls /data'
192.168.100.20 | CHANGED | rc=0 >>

192.168.100.10 | CHANGED | rc=0 >>

[root@ansible ~]#ansible all -m file -a 'name=/data/f1 state=touch'    #在创建的/data目录下,使用file模块创建文件,state=touch:状态=touch 创建
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/data/f1", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/data/f1", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}
[root@ansible ~]#ansible all -a 'ls /data'
192.168.100.20 | CHANGED | rc=0 >>
f1
192.168.100.10 | CHANGED | rc=0 >>
f1
[root@ansible ~]#ansible all -m file -a 'name=/data/f1 state=absent'    #absent删除文件
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/data/f1", 
    "state": "absent"
}
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/data/f1", 
    "state": "absent"
}
[root@ansible ~]#ansible all -a 'ls /data'
192.168.100.20 | CHANGED | rc=0 >>

192.168.100.10 | CHANGED | rc=0 >>

[root@ansible ~]#ansible all -m file -a 'name=/data/dir1 state=directory'    #directory创建目录
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/data/dir1", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/data/dir1", 
    "size": 6, 
    "state": "directory", 
    "uid": 0
}
[root@ansible ~]#ansible all -a 'ls -l /data'
192.168.100.20 | CHANGED | rc=0 >>
总用量 0
drwxr-xr-x 2 root root 6 3月  17 22:29 dir1
192.168.100.10 | CHANGED | rc=0 >>
总用量 0
drwxr-xr-x 2 root root 6 3月  17 22:29 dir1
[root@ansible ~]#ansible all -m file -a 'name=/data/dir1 state=absent'    #删除目录
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/data/dir1", 
    "state": "absent"
}
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/data/dir1", 
    "state": "absent"
}
[root@ansible ~]#ansible all -a 'ls /data'
192.168.100.20 | CHANGED | rc=0 >>

192.168.100.10 | CHANGED | rc=0 >>

[root@ansible ~]#ansible all -m file -a 'src=/etc/fstab dest=/data/fstab.link state=link'    #src,dest指定源文件,目标文件,link:创建软链接
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/data/fstab.link", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "size": 10, 
    "src": "/etc/fstab", 
    "state": "link", 
    "uid": 0
}
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "dest": "/data/fstab.link", 
    "gid": 0, 
    "group": "root", 
    "mode": "0777", 
    "owner": "root", 
    "size": 10, 
    "src": "/etc/fstab", 
    "state": "link", 
    "uid": 0
}
[root@ansible ~]#ansible all -a 'ls -l /data'
192.168.100.20 | CHANGED | rc=0 >>
总用量 0
lrwxrwxrwx 1 root root 10 3月  17 22:31 fstab.link -> /etc/fstab
192.168.100.10 | CHANGED | rc=0 >>
总用量 0
lrwxrwxrwx 1 root root 10 3月  17 22:31 fstab.link -> /etc/fstab
[root@ansible ~]#ansible all -m file -a 'dest=/data/fstab.link state=absent'    #删除软链接
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/data/fstab.link", 
    "state": "absent"
}
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "path": "/data/fstab.link", 
    "state": "absent"
}
[root@ansible ~]#ansible all -a 'ls -l /data'
192.168.100.20 | CHANGED | rc=0 >>
总用量 0
192.168.100.10 | CHANGED | rc=0 >>
总用量 0

  7>Hostname模块:管理主机名

node-1节点先查看主机名:
[root@node-1 ~]# hostname
node-1

[root@ansible ~]#ansible 192.168.100.10 -m hostname -a 'name=node1'
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "ansible_domain": "", 
        "ansible_fqdn": "node1", 
        "ansible_hostname": "node1", 
        "ansible_nodename": "node1", 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "node1"
}

node-1节点再查看主机名:exit退出生效
[root@node-1 ~]# hostname
node1

  8>Cron模块:计划任务
支持时间:minute , hour , day , month , weekday:分钟,小时,日,月,周

[root@ansible ~]#ansible all -m cron -a 'minute=* weekday=1,2,3 job="/usr/bin/wall FBI warning" name=warning'    #创建任务
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "warning"
    ]
}
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "envs": [], 
    "jobs": [
        "warning"
    ]
}

node-1节点查看:node-2节点类似
[root@node-1 ~]#
Broadcast message from root@node-1 (Tue Mar 17 22:48:01 2020):

FBI warning

Broadcast message from root@node-1 (Tue Mar 17 22:49:01 2020):

FBI warning

[root@ansible ~]#ansible all -m cron -a 'disabled=true job="/usr/bin/wall FBI warning" name=warning' #disabled=true关闭任务
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "envs": [],
    "jobs": [
        "warning"
    ]
}
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "envs": [],
    "jobs": [
        "warning"
    ]
}

[root@ansible ~]#ansible all -m cron -a 'job="/usr/bin/wall FBI warning" name=warning state=absent' #absent删除任务
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "envs": [],
    "jobs": []
}
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "envs": [],
    "jobs": []
}

  9>Yum:管理包
  ansible server -m yum -a 'name=httpd state=latest'安装
  ansible server -m yum -a 'name=httpd state=absent'删除

[root@ansible ~]#ansible all -m yum -a 'name=httpd state=latest'    #latest:安装
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "installed": [
            "httpd"
        ], 
        "updated": []
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-67.el7.centos will be installed\n--> Processing Dependency: httpd-tools = 2.4.6-67.el7.centos for package: httpd-2.4.6-67.el7.centos.x86_64\n--> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-67.el7.centos.x86_64\n--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.4.6-67.el7.centos.x86_64\n--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.4.6-67.el7.centos.x86_64\n--> Running transaction check\n---> Package apr.x86_64 0:1.4.8-3.el7 will be installed\n---> Package apr-util.x86_64 0:1.5.2-6.el7 will be installed\n---> Package httpd-tools.x86_64 0:2.4.6-67.el7.centos will be installed\n---> Package mailcap.noarch 0:2.1.41-2.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package            Arch          Version                     Repository   Size\n================================================================================\nInstalling:\n httpd              x86_64        2.4.6-67.el7.centos         base        2.7 M\nInstalling for dependencies:\n apr                x86_64        1.4.8-3.el7                 base        103 k\n apr-util           x86_64        1.5.2-6.el7                 base         92 k\n httpd-tools        x86_64        2.4.6-67.el7.centos         base         87 k\n mailcap            noarch        2.1.41-2.el7                base         31 k\n\nTransaction Summary\n================================================================================\nInstall  1 Package (+4 Dependent packages)\n\nTotal download size: 3.0 M\nInstalled size: 10 M\nDownloading packages:\n--------------------------------------------------------------------------------\nTotal                                              8.4 MB/s | 3.0 MB  00:00     \nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : apr-1.4.8-3.el7.x86_64                                       1/5 \n  Installing : apr-util-1.5.2-6.el7.x86_64                                  2/5 \n  Installing : httpd-tools-2.4.6-67.el7.centos.x86_64                       3/5 \n  Installing : mailcap-2.1.41-2.el7.noarch                                  4/5 \n  Installing : httpd-2.4.6-67.el7.centos.x86_64                             5/5 \n  Verifying  : httpd-2.4.6-67.el7.centos.x86_64                             1/5 \n  Verifying  : mailcap-2.1.41-2.el7.noarch                                  2/5 \n  Verifying  : apr-1.4.8-3.el7.x86_64                                       3/5 \n  Verifying  : httpd-tools-2.4.6-67.el7.centos.x86_64                       4/5 \n  Verifying  : apr-util-1.5.2-6.el7.x86_64                                  5/5 \n\nInstalled:\n  httpd.x86_64 0:2.4.6-67.el7.centos                                            \n\nDependency Installed:\n  apr.x86_64 0:1.4.8-3.el7                     apr-util.x86_64 0:1.5.2-6.el7    \n  httpd-tools.x86_64 0:2.4.6-67.el7.centos     mailcap.noarch 0:2.1.41-2.el7    \n\nComplete!\n"
    ]
}
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "installed": [
            "httpd"
        ], 
        "updated": []
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-67.el7.centos will be installed\n--> Processing Dependency: httpd-tools = 2.4.6-67.el7.centos for package: httpd-2.4.6-67.el7.centos.x86_64\n--> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-67.el7.centos.x86_64\n--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.4.6-67.el7.centos.x86_64\n--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.4.6-67.el7.centos.x86_64\n--> Running transaction check\n---> Package apr.x86_64 0:1.4.8-3.el7 will be installed\n---> Package apr-util.x86_64 0:1.5.2-6.el7 will be installed\n---> Package httpd-tools.x86_64 0:2.4.6-67.el7.centos will be installed\n---> Package mailcap.noarch 0:2.1.41-2.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package            Arch          Version                     Repository   Size\n================================================================================\nInstalling:\n httpd              x86_64        2.4.6-67.el7.centos         base        2.7 M\nInstalling for dependencies:\n apr                x86_64        1.4.8-3.el7                 base        103 k\n apr-util           x86_64        1.5.2-6.el7                 base         92 k\n httpd-tools        x86_64        2.4.6-67.el7.centos         base         87 k\n mailcap            noarch        2.1.41-2.el7                base         31 k\n\nTransaction Summary\n================================================================================\nInstall  1 Package (+4 Dependent packages)\n\nTotal download size: 3.0 M\nInstalled size: 10 M\nDownloading packages:\n--------------------------------------------------------------------------------\nTotal                                              8.3 MB/s | 3.0 MB  00:00     \nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : apr-1.4.8-3.el7.x86_64                                       1/5 \n  Installing : apr-util-1.5.2-6.el7.x86_64                                  2/5 \n  Installing : httpd-tools-2.4.6-67.el7.centos.x86_64                       3/5 \n  Installing : mailcap-2.1.41-2.el7.noarch                                  4/5 \n  Installing : httpd-2.4.6-67.el7.centos.x86_64                             5/5 \n  Verifying  : httpd-2.4.6-67.el7.centos.x86_64                             1/5 \n  Verifying  : mailcap-2.1.41-2.el7.noarch                                  2/5 \n  Verifying  : apr-1.4.8-3.el7.x86_64                                       3/5 \n  Verifying  : httpd-tools-2.4.6-67.el7.centos.x86_64                       4/5 \n  Verifying  : apr-util-1.5.2-6.el7.x86_64                                  5/5 \n\nInstalled:\n  httpd.x86_64 0:2.4.6-67.el7.centos                                            \n\nDependency Installed:\n  apr.x86_64 0:1.4.8-3.el7                     apr-util.x86_64 0:1.5.2-6.el7    \n  httpd-tools.x86_64 0:2.4.6-67.el7.centos     mailcap.noarch 0:2.1.41-2.el7    \n\nComplete!\n"
    ]
}
[root@ansible ~]#ansible all -m shell -a 'rpm -q httpd'    #查看是否安装
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.
If you need to use command because yum, dnf or zypper 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.
192.168.100.20 | CHANGED | rc=0 >>
httpd-2.4.6-67.el7.centos.x86_64
192.168.100.10 | CHANGED | rc=0 >>
httpd-2.4.6-67.el7.centos.x86_64
[root@ansible ~]#ansible all -m yum -a 'name=httpd state=absent'    #absent:卸载
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "removed": [
            "httpd"
        ]
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "已加载插件:fastestmirror\n正在解决依赖关系\n--> 正在检查事务\n---> 软件包 httpd.x86_64.0.2.4.6-67.el7.centos 将被 删除\n--> 解决依赖关系完成\n\n依赖关系解决\n\n================================================================================\n Package       架构           版本                          源             大小\n================================================================================\n正在删除:\n httpd         x86_64         2.4.6-67.el7.centos           @base         9.4 M\n\n事务概要\n================================================================================\n移除  1 软件包\n\n安装大小:9.4 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  正在删除    : httpd-2.4.6-67.el7.centos.x86_64                            1/1 \n  验证中      : httpd-2.4.6-67.el7.centos.x86_64                            1/1 \n\n删除:\n  httpd.x86_64 0:2.4.6-67.el7.centos                                            \n\n完毕!\n"
    ]
}
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "changes": {
        "removed": [
            "httpd"
        ]
    }, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "已加载插件:fastestmirror\n正在解决依赖关系\n--> 正在检查事务\n---> 软件包 httpd.x86_64.0.2.4.6-67.el7.centos 将被 删除\n--> 解决依赖关系完成\n\n依赖关系解决\n\n================================================================================\n Package       架构           版本                          源             大小\n================================================================================\n正在删除:\n httpd         x86_64         2.4.6-67.el7.centos           @base         9.4 M\n\n事务概要\n================================================================================\n移除  1 软件包\n\n安装大小:9.4 M\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  正在删除    : httpd-2.4.6-67.el7.centos.x86_64                            1/1 \n  验证中      : httpd-2.4.6-67.el7.centos.x86_64                            1/1 \n\n删除:\n  httpd.x86_64 0:2.4.6-67.el7.centos                                            \n\n完毕!\n"
    ]
}
[root@ansible ~]#ansible all -m shell -a 'rpm -q httpd'    #卸载后查看
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.
If you need to use command because yum, dnf or zypper 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.
192.168.100.20 | FAILED | rc=1 >>
未安装软件包 httpd non-zero return code
192.168.100.10 | FAILED | rc=1 >>
未安装软件包 httpd non-zero return code

  10>Service模块:管理服务
  ansible server -m service -a 'name=httpd state=stopped'
  ansible server -m service -a 'name=httpd state=started'
  ansible server -m service -a 'name=httpd state=reloaded'
  ansible server -m service -a 'name=httpd state=restarted'

[root@ansible ~]#ansible all -m yum -a 'name=httpd state=latest'    #安装httpd
[root@ansible ~]#ansible all -m shell -a 'ss -ntl'
192.168.100.20 | CHANGED | rc=0 >>
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128          *:22                       *:*                  
LISTEN     0      100    127.0.0.1:25                       *:*                  
LISTEN     0      128         :::22                      :::*                  
LISTEN     0      100        ::1:25                      :::*                  
192.168.100.10 | CHANGED | rc=0 >>
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128          *:22                       *:*                  
LISTEN     0      100    127.0.0.1:25                       *:*                  
LISTEN     0      128         :::22                      :::*                  
LISTEN     0      100        ::1:25                      :::*                  
[root@ansible ~]#ansible all -m service -a 'name=httpd state=started enabled=yes'    #启动httpd,并设为开机自启动
[root@ansible ~]#ansible all -m shell -a 'ss -ntl'
192.168.100.20 | CHANGED | rc=0 >>
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128          *:22                       *:*                  
LISTEN     0      100    127.0.0.1:25                       *:*                  
LISTEN     0      128         :::80                      :::*                  
LISTEN     0      128         :::22                      :::*                  
LISTEN     0      100        ::1:25                      :::*                  
192.168.100.10 | CHANGED | rc=0 >>
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port              
LISTEN     0      128          *:22                       *:*                  
LISTEN     0      100    127.0.0.1:25                       *:*                  
LISTEN     0      128         :::80                      :::*                  
LISTEN     0      128         :::22                      :::*                  
LISTEN     0      100        ::1:25                      :::*[root@ansible ~]#ansible all -m service -a 'name=httpd state=stopped'    #关闭httpd

  11>User模块:管理用户

[root@ansible ~]#ansible all -m user -a 'name=nginx shell=/sbin/nologin system=yes home=/var/nginx groups=root,bin uid=77 comment="nginx service"'    #创建用户指定shell类型,系统账号,家目录,附加组,uid,描述信息
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "nginx service", 
    "create_home": true, 
    "group": 77, 
    "groups": "root,bin", 
    "home": "/var/nginx", 
    "name": "nginx", 
    "shell": "/sbin/nologin", 
    "state": "present", 
    "system": true, 
    "uid": 77
}
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "comment": "nginx service", 
    "create_home": true, 
    "group": 77, 
    "groups": "root,bin", 
    "home": "/var/nginx", 
    "name": "nginx", 
    "shell": "/sbin/nologin", 
    "state": "present", 
    "system": true, 
    "uid": 77
}
[root@ansible ~]#ansible all -a 'getent passwd nginx'
192.168.100.20 | CHANGED | rc=0 >>
nginx:x:77:77:nginx service:/var/nginx:/sbin/nologin
192.168.100.10 | CHANGED | rc=0 >>
nginx:x:77:77:nginx service:/var/nginx:/sbin/nologin
[root@ansible ~]#ansible all -m user -a 'name=nginx state=absent remove=yes'    #删除用户及其家目录信息
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "force": false, 
    "name": "nginx", 
    "remove": true, 
    "state": "absent", 
    "stderr": "userdel: nginx 邮件池 (/var/spool/mail/nginx) 未找到\n", 
    "stderr_lines": [
        "userdel: nginx 邮件池 (/var/spool/mail/nginx) 未找到"
    ]
}
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "force": false, 
    "name": "nginx", 
    "remove": true, 
    "state": "absent", 
    "stderr": "userdel: nginx 邮件池 (/var/spool/mail/nginx) 未找到\n", 
    "stderr_lines": [
        "userdel: nginx 邮件池 (/var/spool/mail/nginx) 未找到"
    ]
}
[root@ansible ~]#ansible all -a 'getent passwd nginx'
192.168.100.20 | FAILED | rc=2 >>
non-zero return code
192.168.100.10 | FAILED | rc=2 >>
non-zero return code

  12>Group:管理组

[root@ansible ~]#ansible all -m group -a 'name=nginx system=yes gid=88'
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 88, 
    "name": "nginx", 
    "state": "present", 
    "system": true
}
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "gid": 88, 
    "name": "nginx", 
    "state": "present", 
    "system": true
}
[root@ansible ~]#ansible all -a 'getent group nginx'
192.168.100.20 | CHANGED | rc=0 >>
nginx:x:88:
192.168.100.10 | CHANGED | rc=0 >>
nginx:x:88:
[root@ansible ~]#ansible all -m group -a 'name=nginx state=absent'
192.168.100.20 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "nginx", 
    "state": "absent"
}
192.168.100.10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "name": "nginx", 
    "state": "absent"
}
[root@ansible ~]#ansible all -a 'getent group nginx'
192.168.100.20 | FAILED | rc=2 >>
non-zero return code
192.168.100.10 | FAILED | rc=2 >>
non-zero return code

  模块用法不清楚可以查看帮助:

[root@ansible ~]#ansible-doc -s cron    #例:查看cron模块

 

13、ansible系列命令

  1>ansible-galaxy
  连接https://galaxy.ansible.com下载相应的roles(角色)
  列出所有已安装的galaxy
    ansible-galaxy list
  安装galaxy
    ansible-galaxy install geerlingguy.redis
  删除galaxy
    ansible-galaxy remove geerlingguy.redis

  2>ansible-pull
  推送命令至远程,效率无限提升,对运维要求较高

  3>Ansible-playbook

  (1)playbook是由一个或多个 "play" 组成的列表,采用YAML语言编写。
    play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联同起来按事先编排的机制同唱一台大戏。

  (2)YAML是一一个可读性高的用来表达资料序列的格式。YAML参考了其他多种语言,包括:XML、C语言、Python、 Perl以及电子邮件格式RFC2822等。
    YAML Ain't Markup Language,即YAML不是XML。不过,在开发的这种语言时,YAML的意思其实是:"Yet Another Markup Language" (仍是一种标记语言)
    特性:
      YAML的可读性好
      YAML和脚本语言的交互性好
      YAML使用实现语言的数据类型
      YAML有一个一致的信息模型
      YAML易于实现
      YAML可以基于流来处理
      YAML表达能力强,扩展性好
      更多的内容及规范参见http://www.yaml.org

  (3)在单一档案中,可用连续三个连字号(一)区分多个档案。另外,还有选择性的连续三个点号(...)用来表示档案结尾
次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
    使用#号注释代码
    缩进必须是统一的,不能空格和tab混用
    缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
    YAML文件内容和Linux系统大小写判断方式保持一致,是区别大小写的,k/v的值均需大小写敏感
    k/v的值可同行写也可换行写。同行使用:分隔
    v可是个字符串,也可是另一个列表
    一个完整的代码块功能需最少元素需包括name: task
    一个name只能包括一个task
    YAML文件扩展名通常为yml或yaml

  (4)List:列表,其所有元素均使用"-"打头

示例:
[root@ansible ansible]#cat file.yml 
---
- hosts: webserver    #一个hosts列表,定义针对的列表主机
  remote_user: root

  tasks:              #任务
    - name: create new file    #任务列表1
      file: name=/root/newfile state=touch
    - name: create new user    #任务列表2
      user: name=test system=yes shell=/sbin/nologin

  (5)Dictionary:字典,通常由多个key与value构成

示例:
# An employee record
name: Example Developer
job: Developer
skill: Elite

    也可以将key:value放置于{}中进行表示,用","分隔多个key:value

# An employee record
{name: Example Developer, job: Developer, skill: Elite}

  (6)Hosts:执行的远程主机列表
    playbook中的每一个play的目的都是为了让某个或某些主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,须事先定义在主机清单中。
    可以是如下形式:
    one.example.com
    one.example.com:two.example.com
    192.168.100.10
    192.168.100.*
    webserver:dbserver 两个组的并集
    webserver:&dbserver 两个组的交集
    webservers:!dbserver 在webserver组,但不在dbserver组
              all /etc/ansible/hosts主机清单中的所有主机

---
- hosts: all    #主机清单中的所有主机
  remote_user: root

  tasks:              #任务
  ......

  (7)task列表和action
    ➢play的主体部分是task list,task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在运行自下而下某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此,在更正playbook后重新执行一次即可。
    ➢task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。
    ➢每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤,如果未提供name,则action的结果将用于输出。
    tasks:任务列表
    格式:
      action: module arguments
      module: arguments    #建议使用
    ➢注意:shell和command模块后面跟命令,而非key=value
    某任务的状态在运行后为changed时,可通过"notify"通知给相应的 handlers

    handlers(触发器)和notify(通知)结合使用触发条件
Handlers是task列表,这些task与前述的task并没有本质上的不同,用于当关注的资源发生变化时,才会采取一定的操作
Notify此action可用于在每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。

#编辑httpd.yml,实现httpd的安装,配置文件更改,服务启动
#问题:第一次启动后,更改httpd的配置文件,第二次再执行,会因为之前启动了,而无法重启服务
#解决:通过设置"notify",当某任务的状态在运行后为changed时,通知给相应的 handlers ,触发相应的命令
[root@ansible ansible]#vim httpd.yml
---
- hosts: all
  remote_user: root

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

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

  ➢任务可以通过"tags"打标签,而后可在ansible-playbook命令上使用-t指定进行调用

[root@ansible ansible]#ansible all -m yum -a 'name=httpd state=absent'
[root@ansible ansible]#ansible all -m shell -a 'rpm -q httpd'
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.
If you need to use command because yum, dnf or zypper 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.
192.168.100.20 | FAILED | rc=1 >>
未安装软件包 httpd non-zero return code
192.168.100.10 | FAILED | rc=1 >>
未安装软件包 httpd non-zero return code

 

   通过ansible卸载httpd,在通过tags标签指定只下载httpd

[root@ansible ansible]#ansible-playbook -t install -C httpd.yml

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.20]
ok: [192.168.100.10]

TASK [install httpd package] *******************************************************
changed: [192.168.100.20]
changed: [192.168.100.10]

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

[root@ansible ansible]#ansible-playbook -t install httpd.yml

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.20]
ok: [192.168.100.10]

TASK [install httpd package] *******************************************************
changed: [192.168.100.10]
changed: [192.168.100.20]

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

[root@ansible ansible]#ansible all -m shell -a 'rpm -q httpd'
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'.
If you need to use command because yum, dnf or zypper 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.
192.168.100.20 | CHANGED | rc=0 >>
httpd-2.4.6-67.el7.centos.x86_64
192.168.100.10 | CHANGED | rc=0 >>
httpd-2.4.6-67.el7.centos.x86_64
[root@ansible ansible]#ansible all -m shell -a 'ss -ntl | grep 80'
192.168.100.20 | FAILED | rc=1 >>
non-zero return code
192.168.100.10 | FAILED | rc=1 >>
non-zero return code

 

   (8)运行playbook

    如果命令或脚本的退出码不为零,可以使用如下方式替代

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

    或者使用ignore_errors来忽略错误信息:

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

    运行playbook的方式
    ansible-playbook <filename.yml> ... [options]
    常见选项:
      --check只检测可能会发生的改变,但不真正执行操作
      --list-hosts 列出运行任务的主机
      --limit主机列表只针对主机列表中的主机执行
      -v显示过程-vv -vvv 更详细

示例:
ansible-playbook file.yml --check #只检测
ansible-playbook file.yml #执行
ansible-playbook file.yml --limit webserver

  (9)ansible-playbook支持变量:

    变量名:仅能由字母、数字和下划线组成,且只能以字母开头
    变量来源:
      1 ansible setup facts远程主机的所有变量都可直接调用
      2 在/etc/ansible/hosts中定义
        普通变量:主机组中主机单独定义,优先级高于公共变量
        公共(组)变量:针对主机组中所有主机定义统一变量

 

      3 通过命令行指定变量,优先级最高
      ansible-playbook -e varname=value
      4 在playbook中定义

[root@ansible ansible]#vim apps.yml 
---
- hosts: all
  remote_user: root

  tasks:
    - name: install package
      yum: name={{ pkname }}    #定义变量
    - name: start service
      service: name={{ pkname }} state=started enabled=yes
[root@ansible ansible]#ansible-playbook -e 'pkname=vsftpd' -C apps.yml

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.20]
ok: [192.168.100.10]

TASK [install package] *************************************************************
changed: [192.168.100.20]
changed: [192.168.100.10]

TASK [start service] ***************************************************************
changed: [192.168.100.10]
changed: [192.168.100.20]

PLAY RECAP *************************************************************************
192.168.100.10             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.100.20             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible ansible]#ansible-playbook -e 'pkname=vsftpd' apps.yml

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.10]
ok: [192.168.100.20]

TASK [install package] *************************************************************
changed: [192.168.100.20]
changed: [192.168.100.10]

TASK [start service] ***************************************************************
changed: [192.168.100.10]
changed: [192.168.100.20]

PLAY RECAP *************************************************************************
192.168.100.10             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
192.168.100.20             : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@ansible ansible]#ansible all -m shell -a 'ss -ntl|grep 21'
192.168.100.20 | CHANGED | rc=0 >>
LISTEN     0      32          :::21                      :::*                  
192.168.100.10 | CHANGED | rc=0 >>
LISTEN     0      32          :::21                      :::*      

  也可以在playbook中,定义vars

 

  也可以使用变量文件:

[root@ansible ansible]#vim vars.yml 
var1: httpd
var2: vsftpd
[root@ansible ansible]#vim testvar.yml 
---
- hosts: all
  remote_user: root
  vars_files:
    - vars.yml

  tasks:
    - name: install package
      yum: name={{ var1 }}
    - name: create file
      file: name=/root/{{ var2 }}.log state=touch
[root@ansible ansible]#ansible-playbook -C testvar.yml 
......
[root@ansible ansible]#ansible-playbook testvar.yml
......
[root@ansible ansible]#ansible all -a 'ls /root' 192.168.100.20 | CHANGED | rc=0 >> ...... vsftpd.log 192.168.100.10 | CHANGED | rc=0 >> ...... vsftpd.log [root@ansible ansible]#ansible all -m shell -a 'rpm -q httpd' [WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'. If you need to use command because yum, dnf or zypper 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. 192.168.100.20 | CHANGED | rc=0 >> httpd-2.4.6-67.el7.centos.x86_64 192.168.100.10 | CHANGED | rc=0 >> httpd-2.4.6-67.el7.centos.x86_64

      5 在role中定义
    变量定义:key=value
    示例:http_port=80
    变量调用方式:
      通过{{ variable_name }}调用变量,且变量名前后必须有空格,有时用"{{ variable_ name}}" 才生效
      ansible playbook -e选项指定

 

  4>Ansible-vault
  功能:管理加密解密yml文件

ansible-vault [create |decrypt| edit encrypt|rekey |view]
ansible-vault encrypt hello.yml    加密
ansible-vault decrypt hello.yml    解密
ansible-vault view hello.yml       查看
ansible-vault edit hello.yml       编辑加密文件
ansible-vault rekey hello.yml      修改口令
ansible-vault create new.yml       创建新文件

 

  5>Ansible-console:2.0+新增,可交互执行命令,支持tab
  root@test (2)[f:10] $
  执行用户@当前操作的主机组(当前组的主机数量)[f:并发数]$
    ➢设置并发数:forksn 例如:forks 10
    ➢切换组:cd主机组 例如:cd web
    ➢列出当前组主机列表:list
    ➢列出所有的内置命令:?或help
    ➢示例:

[root@ansible ~]#ansible-console
Welcome to the ansible console.
Type help or ? to list commands.

root@all (2)[f:5]$ cd webserver
root@webserver (1)[f:5]$ forks 10
root@webserver (1)[f:10]$ command hostname
192.168.100.10 | CHANGED | rc=0 >>
node1
root@webserver (1)[f:10]$ shell ls /root
192.168.100.10 | CHANGED | rc=0 >>
anaconda-ks.cfg
hello.sh
hello.sh.4604.2020-03-17@21:14:22~

 

14、模板templates
  文本文件,嵌套有脚本(使用模板编程语言编写)
  Jinja2语言,使用字面量,有下面形式
    字符串:使用单引号或双引号
    数字:整数,浮点数
    列表: [item1, item2, ...]
    元组: (item1, item2, ...)
    字典: {key1:value1, key2:value2, ...}
    布尔型: true/false
    算术运算: +,-, *,/.// %,**
    比较操作: ==,!=,>,>=, <, <=
    逻辑运算: and, or, not
    流表达式: For If When

  templates功能:根据模块文件动态生成对应的配置文件
  templates文件必须存放于templates目录下,且命名为.j2结尾
  yamI/yml文件需和templates目录平级,目录结构如下:

  .
  ├── ansible
      └── templates

#实例:配置nginxtemplates模板文件,使不同主机的worker进程数量=CPU*2
[root@ansible ~]#mkdir ansiable/templates
[root@ansible ~]#tree -d
.
├── ansible
│   └── templates
└── bin
[root@ansible ansible]#ansible webserver -m setup | grep "processor"    #查看CPU变量名
        "ansible_processor": [
        "ansible_processor_cores": 1, 
        "ansible_processor_count": 1, 
        "ansible_processor_threads_per_core": 1, 
        "ansible_processor_vcpus": 1, 
[root@ansible ansible]#cp /etc/nginx/nginx.conf ./templates/nginx.conf.j2
[root@ansible ansible]#vim templates/nginx.conf.j2

 

 

[root@ansible ansible]#vim testtempl.yml 
---
- hosts: webserver
  remote_user: root

  tasks:
    - name: install paskage
      yum: name=nginx
    - name: copy template
      tempate: src=/root/ansible/templates/nginx.conf.j2 dest=/etc/nginx/nginx.conf
    - name: start service
      service: name=nginx state=started enabled=yes
[root@ansible ansible]#ansible-playbook testtempl.yml

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

  对不同centos版本针对配置

[root@ansible ansible]#ansible all -m setup -a 'filter="*distribution*"'
192.168.100.20 | SUCCESS => {
    "ansible_facts": {
        "ansible_distribution": "CentOS", 
        "ansible_distribution_file_parsed": true, 
        "ansible_distribution_file_path": "/etc/redhat-release", 
        "ansible_distribution_file_variety": "RedHat", 
        "ansible_distribution_major_version": "7", 
        "ansible_distribution_release": "Core", 
        "ansible_distribution_version": "7.4", 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}
192.168.100.10 | SUCCESS => {
    "ansible_facts": {
        "ansible_distribution": "CentOS", 
        "ansible_distribution_file_parsed": true, 
        "ansible_distribution_file_path": "/etc/redhat-release", 
        "ansible_distribution_file_variety": "RedHat", 
        "ansible_distribution_major_version": "7", 
        "ansible_distribution_release": "Core", 
        "ansible_distribution_version": "7.4", 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}

 

   迭代:当有需要重复性执行的任务时,可以使用迭代机制
    对迭代项的引用,固定变量名为"item"
    要在task中使用with_items给定要迭代的元素列表
    列表格式:
      字符串
      字典

 

   迭代嵌套子变量

[root@ansible ansible]#cat testitem.yml 
---
- hosts: all
  remote_user: root

  tasks:
    - name: create some groups
      group: name={{ item }}
      with_items:
        - g1
        - g2
        - g3
    - name: create some users
      user: name={{ item.name }} group={{ item.group }}
      with_items:
        - { name: 'user1', group: 'g1' }
        - { name: 'user2', group: 'g2' }
        - { name: 'user3', group: 'g3' }

 

 

  playbook中的template for if:

[root@ansible ansible]#cat templates/for1.conf.j2 
{% for port in ports %}
server{
    listen {{ port }}
}
{% endfor %}
[root@ansible ansible]#cat testfor.yml 
---
- hosts: all
  remote_user: root
  vars:
    ports:
      - 81
      - 82
      - 83
  tasks:
    - name: copy conf
      template: src=/root/ansible/templates/for1.conf.j2 dest=/root/for1.conf
[root@ansible ansible]#ansible-playbook -C testfor.yml 

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.20]
ok: [192.168.100.10]

TASK [copy conf] *******************************************************************
changed: [192.168.100.10]
changed: [192.168.100.20]

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

[root@ansible ansible]#ansible-playbook testfor.yml 

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.20]
ok: [192.168.100.10]

TASK [copy conf] *******************************************************************
changed: [192.168.100.10]
changed: [192.168.100.20]

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


node1节点查看:
[root@node1 ~]# cat for1.conf
server{
    listen 81
}
server{
    listen 82
}
server{
    listen 83
}
[root@ansible ansible]#cat testfor2.yml 
---
- hosts: all
  remote_user: root
  vars:
    ports:
        - listen_port: 80
        - listen_port: 82
        - listen_port: 83
  tasks:
    - name: copy conf
      template: src=/root/ansible/templates/for2.conf.j2 dest=/root/for2.conf
[root@ansible ansible]#cat templates/for2.conf.j2 
{% for port in ports %}
server{
    listen {{ port.listen_port }}
}
{% endfor %}
[root@ansible ansible]#ansible-playbook testfor2.yml 

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.20]
ok: [192.168.100.10]

TASK [copy conf] *******************************************************************
changed: [192.168.100.10]
changed: [192.168.100.20]

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

node1节点查看:
[root@node1 ~]# cat for2.conf 
server{
    listen 80
}
server{
    listen 82
}
server{
    listen 83
}


[root@ansible ansible]#
cat testfor3.yml --- - hosts: all remote_user: root vars: ports: - web1: port: 81 name: web1.yang.com rootdir: /root/website1 - web1: port: 82 name: web2.yang.com rootdir: /root/website2 - web1: port: 83 name: web3.yang.com rootdir: /root/website3 tasks: - name: copy conf template: src=/root/ansible/templates/for3.conf.j2 dest=/root/for3.conf [root@ansible ansible]#cat templates/for3.conf.j2 {% for p in ports %} server{ listen {{ p.port }} servername {{ p.name }} documentroot {{ p.rootdir }} } {% endfor %} [root@ansible ansible]#ansible-playbook testfor3.yml PLAY [all] ************************************************************************* TASK [Gathering Facts] ************************************************************* ok: [192.168.100.20] ok: [192.168.100.10] TASK [copy conf] ******************************************************************* changed: [192.168.100.20] changed: [192.168.100.10] PLAY RECAP ************************************************************************* 192.168.100.10 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 192.168.100.20 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 node1节点查看: [root@node1 ~]# cat for3.conf server{ listen 81 servername web1.yang.com documentroot /root/website1 } server{ listen 82 servername web2.yang.com documentroot /root/website2 } server{ listen 83 servername web3.yang.com documentroot /root/website3 }
[root@ansible ansible]#cat testfor4.yml 
---
- hosts: all
  remote_user: root
  vars:
    ports:
      - web1:
        port: 81
        #name: web1.yang.com
        rootdir: /root/website1
      - web1:
        port: 82
        name: web2.yang.com
        rootdir: /root/website2
      - web1:
        port: 83
        #name: web3.yang.com
        rootdir: /root/website3
  tasks:
    - name: copy conf
      template: src=/root/ansible/templates/for4.conf.j2 dest=/root/for4.conf
[root@ansible ansible]#cat templates/for4.conf.j2 
{% for p in ports %}
server{
    listen {{ p.port }}
{% if p.name is defined %}    #如果被定义了则生成,没有定义则不生成
    servername {{ p.name }}
{% endif %}
    documentroot {{ p.rootdir }}
}
{% endfor %}
[root@ansible ansible]#ansible-playbook testfor4.yml 

PLAY [all] *************************************************************************

TASK [Gathering Facts] *************************************************************
ok: [192.168.100.10]
ok: [192.168.100.20]

TASK [copy conf] *******************************************************************
changed: [192.168.100.20]
changed: [192.168.100.10]

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


node1节点查看:
[root@node1 ~]# cat for4.conf 
server{
    listen 81
    documentroot /root/website1
}
server{
    listen 82
    servername web2.yang.com
    documentroot /root/website2
}
server{
    listen 83
    documentroot /root/website3
}

 

15、roles
  1>定义:ansilbe自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。
  复杂场景:建议使用roles,代码复用度高
    变更指定主机或主机组
    如命名不规范维护和传承成本大
    某些功能需多个Playbook,通过Includes即可实现

  2>roles目录结构
  每个角色,以特定的层级目录结构进行组织

playbook.yml
roles/
    project/
        tasks/
        files/
        vars/         不常用
        default/      不常用
        templates/
        handlers/
        meta/         不常用

  /roles/project/:项目名称,有以下子目录
  files/ : 存放由copy或script模块等调用的文件
  templates/ : template模块查找所需要模板文件的目录
  tasks/ : 定义task,role的基本元素,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
  handlers/ : 至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
  vars/ : 定义变量,至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含
  meta/ : 定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.ymI的文件,其它文件需在此文件中通过include进行包含
  default/ : 设定默认变量时使用此目录中的main.yml文件

  3>使用:
  角色(roles):角色集合
  roles/(官方建议目录/etc/ansible/roles,不过也可以自定义)
    mysql/
    httpd/
    nginx/
    memcached/

[root@ansible ansible]#tree    #构建目录结构,如果没有可以mkdir创建目录
.
└── roles
    ├── httpd
    ├── memcache
    ├── mysql
    └── nginx

5 directories, 0 files
[root@ansible ansible]#cd roles/nginx/
[root@ansible nginx]#pwd
/root/ansible/roles/nginx
[root@ansible nginx]#mkdir tasks templates    #在roles/nginx创建一个任务目录和模板目录
[root@ansible nginx]#ls
tasks  templates
[root@ansible nginx]#cd tasks/                #进入任务tasks目录
[root@ansible tasks]#vim group.yml            #先创建组文件
[root@ansible tasks]#cat group.yml
- name: create group
  group: name=nginx gid=80
[root@ansible tasks]#vim user.yml             #再创建用户文件
[root@ansible tasks]#cat user.yml
- name: create user
  user: name=nginx uid=80 group=nginx system=yes shell=/sbin/nologin
[root@ansible tasks]#vim yum.yml              #再创建安装文件
[root@ansible tasks]#cat yum.yml
- name: install package
  yum: name=nginx
[root@ansible tasks]#vim start.yml            #进而创建启动文件
[root@ansible tasks]#cat start.yml
- name: start service
  service: name=nginx state=started enabled=yes
[root@ansible tasks]#cp start.yml restart.yml
[root@ansible tasks]#vim restart.yml          #重启服务文件
[root@ansible tasks]#cat restart.yml
- name: restart service
  service: name=nginx state=restarted
[root@ansible templates]#cd ../templates/     #进入模板templates目录
[root@ansible templates]#cp /etc/nginx/nginx.conf nginx.conf.j2    #拷贝本机的nginx文件成为模板文件
[root@ansible templates]#vim nginx.conf.j2

 


[root@ansible templates]#cd ../tasks/
[root@ansible tasks]#ls
group.yml  restart.yml  start.yml  user.yml  yum.yml
[root@ansible tasks]#vim templ.yml
[root@ansible tasks]#cat templ.yml            #回到任务tasks目录,创建templ.yml文件
- name: copy conf
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
[root@ansible tasks]#ls
group.yml  restart.yml  start.yml  templ.yml  user.yml  yum.yml
[root@ansible tasks]#vim main.yml             #创建全局文件,定义调用各个板块文件的顺序
[root@ansible tasks]#cat main.yml
- include: group.yml
- include: user.yml
- include: yum.yml
- include: templ.yml
- include: start.yml
[root@ansible tasks]#cd ../../
[root@ansible roles]#ls
httpd  memcache  mysql  nginx
[root@ansible roles]#cd ../
[root@ansible ansible]#ls
roles
[root@ansible ansible]#vim nginx_role.yml     #创建nginx role文件,注意必须和roles同级
[root@ansible ansible]#cat nginx_role.yml
- hosts: all
  remote_user: root
  roles:
    - role: nginx
[root@ansible ansible]#ansible-playbook -C nginx_role.yml    #检查语法
[root@ansible ansible]#ansible-playbook nginx_role.yml       #执行


总结:构建目录树结构如下 [root@ansible ansible]#tree . ├── nginx_role.yml └── roles ├── httpd ├── memcache ├── mysql └── nginx ├── tasks │ ├── group.yml │ ├── main.yml │ ├── restart.yml │ ├── start.yml │ ├── templ.yml │ ├── user.yml │ └──
yum.yml └── templates └── nginx.conf.j2 7 directories, 9 files

 



posted @ 2020-05-05 16:43  我听过  阅读(754)  评论(0编辑  收藏  举报