1)安装2)常用模块3)inventory4)playbook(role\tag\template)5) yaml6) jinja2二、简介及架构1、简介ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:连接插件connection plugins:负责和被监控端实现通信;inventory:指定操作的主机,是一个配置文件里面定义监控的主机;各种模块核心模块、command模块、自定义模块;借助于插件完成记录日志邮件等功能;playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务2、架构图3、特性不需要在被管控主机上安装任何客户端;no server:无服务器端,使用时直接运行命令即可;modules in any languages:基于模块工作,可使用任意语言开发模块;yaml,not code:使用yaml语言定制剧本playbook;ssh by default:基于SSH工作;strong multi-tier solution:可实现多级指挥。4、优点轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;批量任务执行可以写成脚本,而且不用分发到远程就可以执行;使用python编写,维护更简单,ruby语法过于复杂;支持sudo。四、具体介绍(很长,按需要阅读)注:下面大部份内容是网上一些翻译或经验贴内容1、安装注:安装的命令参见附件1,所有命令我都试过,可用Ansible进行管理的服务器俗称“受控节点”。管理节点依赖的东西比较少,列表如下:1 Python 2.6 或更高版本2 Paramiko(Python的SSH模块)3 PyYAML(Python的YAML解析器)4 Jinja2(Python的模板引擎)受控节点如果是Python 2.4 或 Python 2.5 ,则需额外安装 Simplejson 模块。到Python的2.6或以上版本,就则内置了 Simplejson模块,不需要额外安装任何其它依赖。值得欣慰的是,目前主流的服务器上内置的Python版本绝多数都是 Python 2.6 以上版本。通常大家都喜欢用各个系统自带的包管理工具去安装和维护软件包,我分别安装了centos、ubuntu两个操作系统,CentOS用这个方式:$ sudo yum -y install ansible,Ubuntu$ apt-get install ansible。具体步骤参见附件(举UBUNTU的例子)2、常用模块注:官方支持很多模块,具体能见附件2,这节先列以下常用的模块,这个常用的模块基本覆盖我们平时工作的80%(1)、setup## 用来查看远程主机的一些基本信息# ansible storm_cluster -m setup(2)、ping## 用来测试远程主机的运行状态# ansible storm_cluster -m ping(3)、file## 设置文件的属性相关选项如下:force:需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|nogroup:定义文件/目录的属组mode:定义文件/目录的权限owner:定义文件/目录的属主path:必选项,定义文件/目录的路径recurse:递归设置文件的属性,只对目录有效src:被链接的源文件路径,只应用于state=link的情况dest:被链接到的路径,只应用于state=link的情况state:directory:如果目录不存在,就创建目录file:即使文件不存在,也不会被创建link:创建软链接hard:创建硬链接touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间absent:删除目录、文件或者取消链接文件示例:## 远程文件符号链接创建# ansible storm_cluster -m file -a "src=/etc/resolv.conf dest=/tmp/resolv.conf state=link"## 远程文件信息查看# ansible storm_cluster -m command -a "ls –al /tmp/resolv.conf"## 远程文件符号链接删除# ansible storm_cluster -m file -a "path=/tmp/resolv.conf state=absent"## 远程文件信息查看# ansible storm_cluster -m command -a "ls -al /tmp/resolv.conf"说明:如上显示,代表文件或链接已经删除。(4)、copy## 复制文件到远程主机相关选项如下:backup:在覆盖之前,将源文件备份,备份文件包含时间信息。有两个选项:yes|nocontent:用于替代“src”,可以直接设定指定文件的值dest:必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径也必须是个目录directory_mode:递归设定目录的权限,默认为系统默认权限force:如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yesothers:所有的file模块里的选项都可以在这里使用src:被复制到远程主机的本地文件,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用“/”来结尾,则只复制目录里的内容,如果没有使用“/”来结尾,则包含目录在内的整个内容全部复制,类似于rsync。示例:## 将本地文件“/etc/ansible/ansible.cfg”复制到远程服务器# ansible storm_cluster -m copy -a "src=/etc/ansible/ansible.cfg dest=/tmp/ansible.cfg owner=root group=root mode=0644"## 远程文件信息查看# ansible storm_cluster -m command -a "ls -al /tmp/ansible.cfg"(5)、command## 在远程主机上执行命令相关选项如下:creates:一个文件名,当该文件存在,则该命令不执行free_form:要执行的linux指令chdir:在执行指令之前,先切换到该目录removes:一个文件名,当该文件不存在,则该选项不执行executable:切换shell来执行指令,该执行路径必须是一个绝对路径示例:# ansible storm_cluster -m command -a "uptime"(6)、shell## 切换到某个shell执行指定的指令,参数与command相同。与command不同的是,此模块可以支持命令管道,同时还有另一个模块也具备此功能:raw示例:## 先在本地创建一个SHELL脚本# vim /tmp/rocketzhang_test.sh#!/bin/shdate +%F_%H:%M:%S#chmod +x /tmp/rocketzhang_test.sh## 将创建的脚本文件分发到远程# ansible storm_cluster -m copy -a "src=/tmp/rocketzhang_test.sh dest=/tmp/rocketzhang_test.sh owner=root group=root mode=0755"## 远程执行# ansible storm_cluster -m shell -a "/tmp/rocketzhang_test.sh"(7)、更多模块其他常用模块,比如:service、cron、yum、synchronize就不一一例举,可以结合自身的系统环境进行测试。service:系统服务管理cron:计划任务管理yum:yum软件包安装管理synchronize:使用rsync同步文件user:系统用户管理group:系统用户组管理更多模块可以参考:#ansible-doc –l3、inventory注:设计好inventory,将有助于后续自动化工具分组策略的关键,下面的介绍是摘录,介绍得很全面Ansible的Inventory文件,默认情况下这个文件是/etc/ansible/hosts,Hosts and Groups对于/etc/ansible/hosts最简单的定义格式像下面:mail.lightclooud.com[webservers]web1.lightcloud.comweb2.lightcloud.com[cloudservers]cloud1.lightcloud.comcloud2.lightcloud.com• 标准的主机的主机名或者域名• 中括号中的名字代表组名,你可以根据你自己的需求将庞大的主机分成具有标识的如果某些主机的SSH运行在自定义的端口上,ansible使用Paramiko进行ssh连接时,不会使用你SSH配置文件中列出的端口,但是如果修改ansible使用openssh进行ssh连接时将会使用badwolf.lightcloud.com:5309假如你想要为某些静态IP设置一些别名,类似于SaltStack中minion配置文件中id的参数配置。你可以这样做:jumper ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50假如你有很多主机遵循某一种模式,你还可以这样来表示他们:[webservers]web[1:50].lightcloud.com• 表示从web1到web50,共计50台主机当然你还可以通过字母来定义可变的范围,例如:[database]db-[a:f].lightcloud.com对于每台主机的连接类型,连接用户等这些你都可以完全自定义,例如:[targets]localhost ansible_connection=localcloud1.lightcloud.com ansible_connection=ssh ansible_ssh_user=lightcloud2.lightcloud.com ansible_connection=ssh ansible_ssh_user=cloud而对于上面的定义方式,只能算是我们针对每台主机的一个快速定义,随后将会讲述如何在host_vars目录下,以单个文件存储它们。Host Variables如上面提到,我们目前可以轻易的给某台或多台主机赋予变量,提供给后面的playbooks使用:Crayon Syntax Highlighter v2.7.1[lightcloud]web1 http_port=202 maxRequestsPerChild=404web2 http_port=303 maxRequestsPerChild=606Groups Variables变量也可以通过组名,应用到组内的所有成员:[lightcloud]host1host2[lightcloud:vars]ntp_server=ntp.lightcloud.comproxy=proxy.lightcloud.com[Format Time: 0.0009 seconds]Groups of Groups, and Group Variables主机组可以包含主机组,主机的变量可以通过继承关系,继承到最高等级的组的变量。定义主机组之间的继承关系我们使用”:children”来表示:[atlanta]host1host2[raleigh]host2host3[southeas:children]atlantaraleighSplitting Out Host and Group Specific DataAnsible并不建议将主机的变量都存储在Inventory文件中,这些变量也可以存储在单个文件中,而这些变量文件必须遵循YAML语法,假设Inventory文件没有被修改,路径如下:/etc/ansible/hosts如果主机的名字“foosball”,两个组的名字分别是“raleigh”,“raleigh”,以下路径的yaml文件中的变量将会应用到对应的主机上:/etc/ansible/group_vars/raleigh/etc/ansible/group_vars/webservers/etc/ansible/host_vars/foosballTip:在Ansible 1.2或更高版本中,groupvars和hostvars目录可以存在于playbook目录或者Inventory目录,如果两个目录都存在同一主机的相同定义,那么playbook目录将会第二次被加载,也就是说playbook中定义的将会覆盖Inventory中对应的定义List of Behavioral Inventory ParametersAnsible内置了一些关于连接主机的变量,设置以下变量控制ansible与远程主机:Crayon Syntax Highlighter v2.7.1ansible_ssh_host:ansible通过ssh连接的IPansible_ssh_port: SSH连接端口ansible_ssh_user: 默认SSH连接用户ansible_ssh_pass: SSH连接的密码(这是不安全的,ansible极力推荐使用--ask-pass选项或使用SSH keys)ansible_sudo_pass: sudo用户的密码ansible_connection: SSH连接的类型:local,ssh,paramiko,在ansible 1.2之前默认是paramiko,后来智能选择,优先使用基于ControlPersist的ssh(支持的前提)ansible_ssh_private_key_file: SSH连接的公钥文件ansible_shell_type: 指定主机所使用的shell解释器,默认是sh,你可以设置成csh, fish等shell解释器ansible_python_interpreter: 用来指定python解释器的路径ansible\_\*\_interpreter: 用来指定主机上其他语法解释器的路径,例如ruby,perl等例如:Crayon Syntax Highlighter v2.7.1some_host ansible_ssh_port=2222 ansible_ssh_user=manageraws_host ansible_ssh_private_key_file=/home/example/.ssh/aws.pemfreebsd_host ansible_python_interpreter=/usr/local/bin/pythonruby_module_host ansible_ruby_interpreter=/usr/bin/ruby.1.9.3Patternspatterns意味着在ansible中管理哪些主机,也可以理解为,要与哪台主机进行通信在命令行中,通常这样来使用1ansible-m-a[Format Time: 0.0010 seconds]
例如
ansible webservers -m service -a "name=httpd state=restarted”
一个模式通常会用一个组来表示,这样可以在较少的文字中表示较多的主机(例如上面的例子),主机都是“webserver”组中
不管怎样,使用ansible,首先要知道如何告诉ansible,在你的inventory中有哪些主机。通过主机名或者组名都可以。
下面的通配模式用来表示inventory中的所有主机
Crayon Syntax Highlighter v2.7.1
all
*
利用通配符还可以指定一组具有规则特征的主机或主机名
one.lightcloud.com
one.lightcloud.com:two.lightcloud.com
192.168.1.50
192.168.1.*
下面的模式,用来知道一个地址或多个组。组名之间通过冒号隔开,表示“OR”的意思,意思是这两个组中的所有主机。
webservers
webservers:dbservers
当然你可以做出非的表达式,例如,目标主机必须在组webservers但不在phoenix组中
webserver:!phoenix
你还可以做出交集的表达式,例如,目标主机必须即在组webservers中又在组staging中
webservers:&staging
你还还可以把它们全部组合到一块
webserver:dbservers:&staging:!phoenix
上面这个复杂的表达式最后表示的目标主机必须满足:在webservers或者dbservers组中,必须还存在于staging组中,但是不在phoenix组中。
这些可以看作是SaltStack中Compound matchers
注意:在shell中,记得把 & ! 这些特殊符号进行转义。
在ansible-palybook命令中,你也可以使用变量来组成这样的表达式,但是你必须使用“-e”的选项来指定这个表达式。通常我们不这样用:
ansible-palybook -e webservers:!{{excluded}}:&{{required}}
你完全不需要使用这些严格的模式去定义组来管理你的机器。无论通过主机名,IP,组都可以使用通配符去匹配
*.lightcloud.com
*.com
他们也可以通过混合模式组合在一起
*.lightcloud.com:*.com
你还可以在开头的地方使用”~”,用来表示这是一个正则表达式
~(web|db).*\.example\.com
最后,在ansible和ansible-playbook中,还可以通过一个参数”–limit”来明确指定排除某些主机或组
ansible-playbook site.yml --limit datacenter2
4、playbook(role\tag\template)
注:playbook涉及面比较大,附件有专题的role、tag、template
简单的说就是定义一个配置文件,文件中写入你需要安装的服务,配置文件,变量等信息,使他们可以按照事先定义好的机制完成一个任务。Playbook使用YAML语法结构,所以配置阅读起来都比较简单。
Playbooks 的组成部分
Target section
定义将要执行playbook的远程主机组
Variable section
定义playbook运行时需要使用的变量
Task section
定义将要在远程主机上执行的任务列表
Handler section
定义task执行完成以后需要调用的任务
Target section常用参数
hosts:定义远程主机组
user:执行该任务的用户
sudo: 设置为yes的时候,执行任务的时候使用root权限
sudo_user 如果你设置用户为tshare365,那么你执行的时候会使用tshare365用户的权限
connection 通过什么方式连接到远程主机,默认是ssh
gather_facks 是否启用在远程主机执行setup模块,默认是会执行的,可用同setup模块获取远程主机的信息,在定义变量的时候使用
Variabler section常用参数
vars 定义格式 变量名:变量值
vars_files 指定变量文件
vars_prompt 用户交互模式自定义变量
setup 模块去远程主机的值
Task ssection
name:输出到屏幕的信息
action:定义执行的动作调用ansible的模块例如:yum name=http state=installed就是安装apache服务
copy:复制本地文件到远程主机
template:复制本地文件到远程主机但是他可以在本地文件中调用变量
service :定义服务的状态
语法简单介绍
#选择的主机组
- hosts: webservers
#这个是变量
vars:
http_port: 80
max_clients: 200
tasks:
#利用yum模块来操作
- name: ensure apache is at the latest version
yum: pkg=httpd state=latest
- name: write the apache config file
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
#触发重启服务器(只要上面的httpd.conf文件变化了,就触发handlers中的restart apache)
notify:
- restart apache
- name: ensure apache is running
service: name=httpd state=started
#这里的restart apache 和上面的触发是配对的。这就是handlers的作用。相当于tag
handlers:
- name: restart apache
service: name=httpd state=restarted
5、 yaml
YAML的设计目的
1、容易人类阅读
2、适合表示程序语言的数据结构
3、可用于不同程序间交换数据
4、支持泛型工具
5、支持串行处理?
6、丰富的表达能力和可扩展性
7、易于使用
粗看了specification以后感觉最好的是“容易人类阅读”:
# YAML代码块
---
site:
name: sina
url : http://www.sina.com.cn
---
site:
name: google
url : http://www.google.com
YAML利用缩进或者是explicit indicatior(如上面的{})来表示属性的嵌套,更为直观和simple。
附一:安装命令
以下步骤验证过,可以直接执行
1、Ansible基础安装
(1)、python2.7安装
https://www.python.org/ftp/python/2.7.8/Python-2.7.8.tgz
# tar xvzf Python-2.7.8.tgz
# cd Python-2.7.8
# ./configure --prefix=/usr/local
# make --jobs=`grep processor/proc/cpuinfo | wc -l`
# make install
## 将python头文件拷贝到标准目录,以避免编译ansible时,找不到所需的头文件
# cd /usr/local/include/python2.7
# cp -a ./* /usr/local/include/
## 备份旧版本的python,并符号链接新版本的python
# cd /usr/bin
# mv python python2.6
# ln -s /usr/local/bin/python
## 修改yum脚本,使其指向旧版本的python,已避免其无法运行
# vim /usr/bin/yum
#!/usr/bin/python --> #!/usr/bin/python2.6
(2)、setuptools模块安装
https://pypi.python.org/packages/source/s/setuptools/setuptools-7.0.tar.gz
# tar xvzf setuptools-7.0.tar.gz
# cd setuptools-7.0
# python setup.py install
(3)、pycrypto模块安装
https://pypi.python.org/packages/source/p/pycrypto/pycrypto-2.6.1.tar.gz
# tar xvzf pycrypto-2.6.1.tar.gz
# cd pycrypto-2.6.1
# python setup.py install
(4)、PyYAML模块安装
http://pyyaml.org/download/libyaml/yaml-0.1.5.tar.gz
# tar xvzf yaml-0.1.5.tar.gz
# cd yaml-0.1.5
# ./configure --prefix=/usr/local
# make --jobs=`grep processor/proc/cpuinfo | wc -l`
# make install
https://pypi.python.org/packages/source/P/PyYAML/PyYAML-3.11.tar.gz
# tar xvzf PyYAML-3.11.tar.gz
# cd PyYAML-3.11
# python setup.py install
(5)、Jinja2模块安装
https://pypi.python.org/packages/source/M/MarkupSafe/MarkupSafe-0.9.3.tar.gz
# tar xvzf MarkupSafe-0.9.3.tar.gz
# cd MarkupSafe-0.9.3
# python setup.py install
https://pypi.python.org/packages/source/J/Jinja2/Jinja2-2.7.3.tar.gz
# tar xvzf Jinja2-2.7.3.tar.gz
# cd Jinja2-2.7.3
# python setup.py install
(6)、paramiko模块安装
https://pypi.python.org/packages/source/e/ecdsa/ecdsa-0.11.tar.gz
# tar xvzf ecdsa-0.11.tar.gz
# cd ecdsa-0.11
# python setup.py install
https://pypi.python.org/packages/source/p/paramiko/paramiko-1.15.1.tar.gz
# tar xvzf paramiko-1.15.1.tar.gz
# cd paramiko-1.15.1
# python setup.py install
(7)、simplejson模块安装
https://pypi.python.org/packages/source/s/simplejson/simplejson-3.6.5.tar.gz
# tar xvzf simplejson-3.6.5.tar.gz
# cd simplejson-3.6.5
# python setup.py install
(8)、ansible安装
https://github.com/ansible/ansible/archive/v1.7.2.tar.gz
# tar xvzf ansible-1.7.2.tar.gz
# cd ansible-1.7.2
# python setup.py install
2、Ansible配置
(1)、SSH免密钥登录设置
## 生成公钥/私钥
# ssh-keygen -t rsa -P ''
## 写入信任文件(将/root/.ssh/id_rsa_storm1.pub分发到其他服务器,并在所有服务器上执行如下指令):
# cat /root/.ssh/id_rsa_storm1.pub >> /root/.ssh/authorized_keys
# chmod 600 /root/.ssh/authorized_keys
(2)、ansible配置
# mkdir -p /etc/ansible
# vim /etc/ansible/ansible.cfg
……
remote_port = 36000
private_key_file = /root/.ssh/id_rsa_storm1
……
附二:官网目前支持的模块
All Modules
http://docs.ansible.com/ansible/list_of_all_modules.html
附三:playbook:role
一、ansible Role介绍
# ansilbe自1.2版本引入的新特性,用于层次性、结构化地组织playbook。
# roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。
# 要使用roles只需要在playbook中使用include指令即可。
#简单来讲,roles就是通过分别将变量、文件、任务、模块及处理器放置于单独的目录中,
# 并可以便捷地include它们的一种机制。
# 角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。
############## 创建role的步骤
(1) 创建以roles命名的目录;
(2) 在roles目录中分别创建以各角色名称命名的目录,如webservers等。注意:在 roles
必须包括 site.yml文件,可以为空;
(3) 在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;
用不到的目录可以创建为空目录,也可以不创建;
(4) 在playbook文件中,调用各角色;
############### role内各目录中可用的文件
tasks目录:至少应该包含一个名为main.yml的文件,其定义了此角色的任务列表;
此文件可以使用include包含其它的位于此目录中的task文件;
files目录:存放由copy或script等模块调用的文件;
templates目录:template模块会自动在此目录中寻找Jinja2模板文件;
handlers目录:此目录中应当包含一个main.yml文件,用于定义此角色用到的各handler;
在handler中使用include包含的其它的handler文件也应该位于此目录中;
vars目录:应当包含一个main.yml文件,用于定义此角色用到的变量;
meta目录:应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系;
ansible 1.3及其以后的版本才支持;
default目录:为当前角色设定默认变量时使用此目录;应当包含一个main.yml文件。
二、基于Role实现 lamp 平台的批量部署
实验环境:
控制端:
172.16.10.9 server.magedu.com
被控制端:
172.16.10.22 node2.example.com
172.16.10.33 node3.example.com
172.16.0.50 director1.example.com
172.16.0.51 director2.example.com
计划:
172.16.10.22 node2.example.com
172.16.10.33 node3.example.com
# 安装 web php程序,并提供配置文件
172.16.0.50 director1.example.com
172.16.0.51 director2.example.com
# 安装 mysql mysql-server,并提供配置文件
要求:基于主机名通信(被控制端都可以解析到其他的主机名)
配置步骤:
1、配置好 Inventory 文件
# /etc/ansible/hosts
[webhosts]
node2.example.com
node3.example.com
[mysql]
director1.example.com
director2.example.com
2、创建对应的目录树
# 执行 tree /root/lamp/roles 查看目录树
/root/lamp/roles
|-- common
| |-- default
| |-- files
| | `-- hosts
| |-- handlers
| |-- meta
| |-- tasks
| | `-- main.yml
| |-- templates
| `-- vars
|-- db
| |-- default
| |-- files
| | `-- my.cnf
| |-- handlers
| | `-- main.yml
| |-- meta
| |-- tasks
| | `-- main.yml
| |-- templates
| `-- vars
|-- db.yml
|-- php
| |-- default
| |-- files
| | `-- php.ini
| |-- handlers
| |-- meta
| |-- tasks
| | `-- main.yml
| |-- templates
| `-- vars
|-- site.yml
|-- web
| |-- default
| |-- files
| | `-- httpd.conf
| |-- handlers
| | `-- main.yml
| |-- meta
| |-- tasks
| | `-- main.yml
| |-- templates
| `-- vars
`-- web.yml
3、各个文件的内容
# 当前所在目录 /root/lamp/roles
# cat db.yml
- name: mysqld servise
remote_user: root
hosts: mysql
roles:
- common
- db
# cat web.yml
- name: wed servise
remote_user: root
hosts: webhosts
roles:
- common
- php
- web
4、开始批量部署
ansible-playbooks web.yml
ansible-playbooks db.yml
附四:playbook:tag
用ansible写playbook的朋友可能会发现,当配置工作很多时,如果在中间过程出错了,修改后想重新执行,前面的一大堆步骤让人感觉很烦躁。虽然提供了“retry”文件,但是却只是根据host来判断重新执行,仍然不够方便;又或者,中间的某些步骤特别耗时,比如下载一个很大的数据包,每次执行特别浪费时间,想要特别的跳过。怎么办?我猜你就是把不需要的部分给注释掉了。有没有更好的办法呢?
当然,现在流行的ansible有提供一种方法解决这个问题。
ansible的playbool中有一个关键字,叫做tags。tags是什么?就是打标签。tags可以和一个play(就是很多个task)或者一个task进行捆绑。然后,ansible-playbook提供了“--skip-tags”和“--tags” 来指明是跳过特定的tags还是执行特定的tags。
阅
验证远程传输文件是否可以
ansible hadoop3 -C -m copy -a "src=/tmp/checkdatanode__60_check.py dest=/usr/local/easyops/agent/easy_collector/plugins/monitor_custom/ mode=0750 force=no"
远程复制文件
ansible hadoop3 -m copy -a "src=/tmp/checkdatanode__60_check.py dest=/usr/local/easyops/agent/easy_collector/plugins/monitor_custom/ mode=0750 force=no"
查看文件系统空间
ansible hadoop1 -a "df -h"