首页 > 技术文章 > ansible lamp部署

fangxinxin 2021-01-07 12:01 原文

主机 ip 属性
node0 192.168.94.142 控制机
node1 192.168.94.141 受控机httpd
node2 192.168.94.143 受控机mysql
node3 192.168.94.144 受控机php

1.映射ip

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

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.94.141 node1
192.168.94.143 node2
192.168.94.144 node3

2.增加清单

设置为test组
[root@node0 ~]# vim /etc/ansible/inventory 

[test]
node1
node2
node3

3.复制公钥至各受控机

 [root@node0 ~] ssh-copy-id root@node2
 [root@node0 ~] ssh-copy-id root@node2
 [root@node0 ~] ssh-copy-id root@node3

4.测试

[root@node0 ~]# ansible test -m ping
node2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
node3 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
node1 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}

5.批量配置yum源

[root@node0 ~]# ansible test -m get_url -a 'url=https://mirrors.aliyun.com/repo/Centos-8.repo dest=/etc/yum.repos.d/'
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "checksum_dest": null,
    "checksum_src": "4966466ad015ef3d2a3cc0b8252d43efbdcf2c94",
    "dest": "/etc/yum.repos.d/Centos-8.repo",
    "elapsed": 0,
    "gid": 0,
    "group": "root",
    "md5sum": "d06fb7d5709727828bcaba7457ea673e",
    "mode": "0644",
    "msg": "OK (2595 bytes)",
    "owner": "root",
    "size": 2595,
    "src": "/root/.ansible/tmp/ansible-tmp-1609930157.028933-4802-48489920245132/tmpm0o67n8u",
    "state": "file",
    "status_code": 200,
    "uid": 0,
    "url": "https://mirrors.aliyun.com/repo/Centos-8.repo"
}
node3 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "checksum_dest": null,
    "checksum_src": "4966466ad015ef3d2a3cc0b8252d43efbdcf2c94",
    "dest": "/etc/yum.repos.d/Centos-8.repo",
    "elapsed": 0,
    "gid": 0,
    "group": "root",
    "md5sum": "d06fb7d5709727828bcaba7457ea673e",
    "mode": "0644",
    "msg": "OK (2595 bytes)",
    "owner": "root",
    "secontext": "system_u:object_r:system_conf_t:s0",
    "size": 2595,
    "src": "/root/.ansible/tmp/ansible-tmp-1609930157.1517816-4806-186470275888078/tmpr722onkj",
    "state": "file",
    "status_code": 200,
    "uid": 0,
    "url": "https://mirrors.aliyun.com/repo/Centos-8.repo"
}
node2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "checksum_dest": null,
    "checksum_src": "4966466ad015ef3d2a3cc0b8252d43efbdcf2c94",
    "dest": "/etc/yum.repos.d/Centos-8.repo",
    "elapsed": 0,
    "gid": 0,
    "group": "root",
    "md5sum": "d06fb7d5709727828bcaba7457ea673e",
    "mode": "0644",
    "msg": "OK (2595 bytes)",
    "owner": "root",
    "secontext": "system_u:object_r:system_conf_t:s0",
    "size": 2595,
    "src": "/root/.ansible/tmp/ansible-tmp-1609930157.1607556-4804-85478380770909/tmpk85eft72",
    "state": "file",
    "status_code": 200,
    "uid": 0,
    "url": "https://mirrors.aliyun.com/repo/Centos-8.repo"
}

//验证
[root@node2 ~]# ll /etc/yum.repos.d/
total 8
-rw-r--r--. 1 root root 2595 Jan  6 18:49 Centos-8.repo
-rw-r--r--. 1 root root  358 Jan  6 18:15 redhat.repo
[root@node1 ~]# ll /etc/yum.repos.d/
total 36
-rw-r--r--  1 root root  2595 Jan  6 18:49 Centos-8.repo
-rw-r--r--. 1 root root  2595 Jan  4 00:42 CentOS-Base.repo
[root@node3 ~]# ll /etc/yum.repos.d/
total 36
-rw-r--r--  1 root root  2595 Jan  6 18:49 Centos-8.repo
-rw-r--r--. 1 root root  2595 Jan  4 00:42 CentOS-Base.repo

6.配置epel源

[root@node0 ~]# wget https://mirrors.aliyun.com/epel/epel-release-latest-8.noarch.rpm 
[root@node0 ~]# yum -y install /root/epel-release-latest-8.noarch.rpm 

7.批量配置repo,epel源

[root@node0 ~]# ansible all -m copy -a 'src=/etc/yum.repos.d/  dest=/etc/yum.repos.d/'
node3 | CHANGED => {
    "changed": true,
    "dest": "/etc/yum.repos.d/",
    "src": "/etc/yum.repos.d/"
}
node2 | CHANGED => {
    "changed": true,
    "dest": "/etc/yum.repos.d/",
    "src": "/etc/yum.repos.d/"
}
node1 | CHANGED => {
    "changed": true,
    "dest": "/etc/yum.repos.d/",
    "src": "/etc/yum.repos.d/"
}

8.清除,生成缓存

[root@node0 ~]# ansible test -a 'yum clean all'
[root@node0 ~]# ansible test -a 'yum makecache'

httpd

node1

9.安装开发工具

[root@node0 ~]# ansible node1 -m yum -a 'name="@Development tools" state=present'
node1 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [
       ...
        "Removed: glibc-langpack-en-2.28-101.el8.x86_64"
    ]
}

10.创建apache用户

//系统用户无家目录不允许登录
[root@node0 ~]# ansible node1 -m user -a 'name=apache system=true shell=/sbin/nologin create_home=false state=present'
//查看用户
[root@node0 ~]# ansible node1 -a 'tail /etc/passwd'
node1 | CHANGED | rc=0 >>
...
apache:x:992:989::/home/apache:/sbin/nologin

11.下载并解压httpd相关安装包

//下载
[root@node0 ~]# wget https://mirrors.tuna.tsinghua.edu.cn/apache/httpd/httpd-2.4.46.tar.bz2
[root@node0 ~]# wget https://mirrors.tuna.tsinghua.edu.cn/apache//apr/apr-1.7.0.tar.gz
[root@node0 ~]# wget https://mirrors.tuna.tsinghua.edu.cn/apache//apr/apr-util-1.6.1.tar.gz

//整合到httpd文件夹里
[root@node0 ~]# mv apr-1.7.0.tar.gz httpd-2.4.46.tar.bz2 apr-util-1.6.1.tar.gz  /httpd

//运用ansible命令远程复制至node1的root用户目录
[root@node0 httpd]# ansible node1 -m copy -a 'src=/root/httpd dest=/root'
node1 | SUCCESS => {
    "changed": false,
    "dest": "/root/",
    "src": "/root/httpd"
}

//解压(如报错需安装bzip2)
[root@node0 ~]# ansible node1 -m shell -a 'tar xf /root/httpd/apr-1.7.0.tar.gz'
[WARNING]: Consider using the unarchive module rather than running 'tar'.  If you need to use command because
unarchive 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.
node1 | CHANGED | rc=0 >>

[root@node0 ~]# ansible node1 -m shell -a 'tar xf /root/httpd/apr-util-1.6.1.tar.gz'
[WARNING]: Consider using the unarchive module rather than running 'tar'.  If you need to use command because
unarchive 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.
node1 | CHANGED | rc=0 >>

[root@node0 ~]# ansible node1 -m shell -a 'tar xf /root/httpd/httpd-2.4.46.tar.bz2'
[WARNING]: Consider using the unarchive module rather than running 'tar'.  If you need to use command because
unarchive 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.
node1 | CHANGED | rc=0 >>

12.安装

//安装apr
[root@node0 ~]# ansible node1 -m shell -a 'cd  /root/apr-1.7.0  && ./configure --prefix=/usr/local/apr'
[root@node0 ~]# ansible node1 -m shell -a 'cd  /root/apr-1.7.0  && make && make install'
node1 | CHANGED | rc=0 >>

//安装apr-util
[root@node0 ~]# ansible node1 -m shell -a 'cd  /root/apr-util-1.6.1  && ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr'
node1 | CHANGED | rc=0 >>
[root@node0 ~]# ansible node1 -m shell -a 'cd  /root/apr-util-1.6.1  && make && make install'
node1 | CHANGED | rc=0 >>

//安装httpd
[root@node0 ~]# ansible node1 -m shell -a 'cd /root/httpd-2.4.46 && ./configure --prefix=/usr/local/apache  --sysconfdir=/etc/httpd24 \
--enable-so \
--enable-ssl \
--enable-cgi \
--enable-rewrite \
--with-zlib \
--with-pcre \
--with-apr=/usr/local/apr \
--with-apr-util=/usr/local/apr-util/ \
--enable-modules=most \
--enable-mpms-shared=all \
--with-mpm=prefork \
--with-crypto'

[root@node0 ~]# ansible node1 -m shell -a 'cd  /root/httpd-2.4.46  && make && make install'

13.配置

//添加环境变量
[root@node0 ~]# ansible node1 -m shell -a 'echo "export PATH=/usr/local/apache/bin:$PATH" > /etc/profile.d/httpd.sh'
node1 | CHANGED | rc=0 >>

[root@node0 ~]# ansible node1 -m shell -a 'source /etc/profile.d/httpd.sh'
node1 | CHANGED | rc=0 >>

[root@node0 ~]# ansible node1 -m shell -a 'echo $PATH'
node1 | CHANGED | rc=0 >>
/usr/local/apache/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin

//创建软连接
[root@node0 ~]# ansible node1 -m shell -a 'ln -s /usr/local/apache/include /usr/local/include/httpd'
[WARNING]: Consider using the file module with state=link rather than running 'ln'.  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.
node1 | CHANGED | rc=0 >>
//取消服务器名注释
[root@node0 ~]# ansible node1 -m shell -a 'sed -i '/#ServerName/s/#//g' /etc/httpd24/httpd.conf'
[WARNING]: Consider using the replace, lineinfile or template module rather than running 'sed'.  If you need to use
command because replace, lineinfile or template 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.
node1 | CHANGED | rc=0 >>

14.启动服务

//启用服务
[root@node0 ~]# ansible node1 -m shell -a '/usr/local/apache/bin/apachectl start'
node1 | CHANGED | rc=0 >>
//查看端口
[root@node0 ~]# ansible node1 -m shell -a 'ss -antl'
node1 | CHANGED | rc=0 >>
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    
LISTEN    0         128                0.0.0.0:22               0.0.0.0:*       
LISTEN    0         128                   [::]:22                  [::]:*       
LISTEN    0         128                      *:80                     *:*       

mysql

node2

15.安装依赖包

[root@node0 ~]# ansible node2 -m yum -a 'name=ncurses-devel,openssl-devel,openssl,cmake,mariadb-devel,ncurses-compat-libs state=present'

16.创建mysql用户

[root@node0 ~]# ansible node2 -m user -a 'name=mysql system=true create_home=false shell=/sbin/nologin state=present' 
node2 | CHANGED => {
  ...
[root@node0 ~]# ansible node2 -m shell -a 'id mysql'
node2 | CHANGED | rc=0 >>
uid=993(mysql) gid=990(mysql) groups=990(mysql)

17.下载mysql包

//下载
[root@node0 ~]# wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.31-linux-glibc2.12-x86_64.tar.gz

//远程传输至node2
[root@node0 ~]# scp /root/mysql-5.7.31-linux-glibc2.12-x86_64.tar.gz  'root'@'node2':/root
mysql-5.7.31-linux-glibc2.12-x86_64.tar.gz                                         100%  359MB 185.8MB/s   00:01  

//查看
[root@node0 ~]# ansible node2 -a 'ls '
node2 | CHANGED | rc=0 >>
anaconda-ks.cfg
epel-release-latest-8.noarch.rpm
mysql-5.7.31-linux-glibc2.12-x86_64.tar.gz

18.解压

//解压至usr/local
[root@node0 ~]# ansible node2 -m shell -a 'tar xf mysql-5.7.31-linux-glibc2.12-x86_64.tar.gz -C /usr/local/'
[WARNING]: Consider using the unarchive module rather than running 'tar'.  If you need to use command because
unarchive 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.
node2 | CHANGED | rc=0 >>

//查看
[root@node0 ~]# ansible node2 -m shell -a 'ls /usr/local/|grep mysql'
node2 | CHANGED | rc=0 >>
mysql-5.7.31-linux-glibc2.12-x86_64

//创建软连接
//文件名简化
[root@node0 ~]# ansible node2 -m shell -a 'ln -s /usr/local/mysql-5.7.31-linux-glibc2.12-x86_64 /usr/local/mysql'
[WARNING]: Consider using the file module with state=link rather than running 'ln'.  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.
node2 | CHANGED | rc=0 >>
//include
[root@node0 ~]# ansible node2 -m shell -a 'ln -s  /usr/local/mysql/include /usr/local/include/mysql'
[WARNING]: Consider using the file module with state=link rather than running 'ln'.  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.
node2 | CHANGED | rc=0 >>

//创建数据存放目录data
[root@node0 ~]# ansible node2 -m shell -a 'mkdir /opt/data'

19.更改属主,组

[root@node0 ~]# ansible node2 -m shell -a 'chown -R mysql.mysql /usr/local/mysql*'
[WARNING]: Consider using the file module with owner rather than running 'chown'.  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.
node2 | CHANGED | rc=0 >>

[root@node0 ~]# ansible node2 -m shell -a 'chown -R mysql.mysql /opt/data'
[WARNING]: Consider using the file module with owner rather than running 'chown'.  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.
node2 | CHANGED | rc=0 >>

20.更改环境变量

[root@node0 ~]# ansible node2 -m shell -a  'echo "export PATH=/usr/local/mysql/bin:$PATH" > /etc/profile.d/mysql.sh'
node2 | CHANGED | rc=0 >>

[root@node0 ~]# ansible node2 -m shell -a  'source /etc/profile.d/mysql.sh'
node2 | CHANGED | rc=0 >>

[root@node0 ~]# ansible node2 -m shell -a  'which mysql'
node2 | CHANGED | rc=0 >>
/usr/local/mysql/bin/mysql

21.初始化数据库

[root@node0 ~]# ansible node2 -m shell -a  '/usr/local/mysql/bin/mysqld --initialize --user=mysql --datadir=/opt/data 
> '
node2 | CHANGED | rc=0 >>
... [Note] A temporary password is generated for root@localhost: qk:gv;ou6a<Z
//暂存临时密码
[root@node0 ~]# ansible node2 -m shell -a  'echo "qk:gv;ou6a<Z">/root/pass'
node2 | CHANGED | rc=0 >>

22.生成配置文件

//node0端编写
[root@node0 ~]# vim my.cnf

[mysqld]
basedir = /usr/local/mysql
datadir = /opt/data
socket = /tmp/mysql.sock
port = 3306
pid-file = /opt/data/mysql.pid
user = mysql
skip-name-resolve

//复制到node2端
[root@node0 ~]# ansible node2 -m copy -a 'src=/root/my.cnf dest=/etc/ '

//配置服务启动脚本
[root@node0 ~]# ansible node2 -m shell -a 'cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld'

//lineinfile生成两行目标
[root@node0 ~]# ansible node2 -m lineinfile -a 'path=/etc/init.d/mysqld line="basedir=/usr/local/mysql" create=yes'
node2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "backup": "",
    "changed": true,
    "msg": "line added"
}
[root@node0 ~]# ansible node2 -m lineinfile -a 'path=/etc/init.d/mysqld line="datadir=/opt/data" create=yes'
node2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "backup": "",
    "changed": true,
    "msg": "line added"
}

23.启动服务

[root@node0 ~]# ansible node2 -m shell -a 'service mysqld start'
[WARNING]: Consider using the service module rather than running 'service'.  If you need to use command because
service 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.
node2 | CHANGED | rc=0 >>
Starting MySQL. SUCCESS! Logging to '/opt/data/node2.err'.
//查看端口是否启用
[root@node0 ~]# ansible node2 -m shell -a 'ss -antl'
node2 | CHANGED | rc=0 >>
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    
LISTEN    0         128                0.0.0.0:22               0.0.0.0:*       
LISTEN    0         80                       *:3306                   *:*       
LISTEN    0         128                   [::]:22                  [::]:*   

24.修改密码

[root@node0 ~]# ansible node2 -m shell -a '/usr/local/mysql/bin/mysql  --connect-expired-password -uroot -p"qk:gv;ou6a<Z" -e "set password=password(\"123456\");"'
node2 | CHANGED | rc=0 >>
mysql: [Warning] Using a password on the command line interface can be insecure.

25.配置依赖库路径

[root@node0 ~]# ansible node2 -m shell -a 'echo "/usr/local/mysql/lib" > /etc/ld.so.conf.d/mysql.conf && ldconfig'
node2 | CHANGED | rc=0 >>

php

node3

26.导入gpg密钥

//根据红帽版本
[root@node3 rpm-gpg]# wget https://archive.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8
--2021-01-07 01:24:35--  https://archive.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-8
Resolving archive.fedoraproject.org (archive.fedoraproject.org)... 38.145.60.22, 38.145.60.24, 38.145.60.23
Connecting to archive.fedoraproject.org (archive.fedoraproject.org)|38.145.60.22|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1627 (1.6K)
Saving to: ‘RPM-GPG-KEY-EPEL-8’

RPM-GPG-KEY-EPEL-8                100%[===========================================================>]   1.59K  --.-KB/s    in 0s      

2021-01-07 01:24:37 (54.4 MB/s) - ‘RPM-GPG-KEY-EPEL-8’ saved [1627/1627]

27.安装依赖包

[root@node0 ~]# ansible node3 -m yum -a 'name=libxml2,libxml2-devel,openssl,openssl-devel,bzip2,bzip2-devel,libcurl,libcurl-devel,libicu-devel,libjpeg,libjpeg-devel,libpng,libpng-devel,openldap-devel,pcre-devel,freetype,freetype-devel,gmp,gmp-devel,libmcrypt,libmcrypt-devel,readline,readline-devel,libxslt,libxslt-devel,mhash,mhash-devel,php-mysqlnd state=present'
node3 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [

28.安装php

[root@node0 ~]# ansible node3 -m yum -a 'name=php-* state=present'
node3 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": true,
    "msg": "",
    "rc": 0,
    "results": [

//查看版本
[root@node0 ~]# ansible node3 -m shell -a 'which php'
node3 | CHANGED | rc=0 >>
/usr/bin/php
[root@node0 ~]# ansible node3 -m shell -a 'php -v'
node3 | CHANGED | rc=0 >>
PHP 7.2.24 (cli) (built: Oct 22 2019 08:28:36) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.24, Copyright (c) 1999-2018, by Zend Technologies

29.启动php

[root@node0 ~]# ansible node3 -m shell -a 'systemctl start php-fpm'
node3 | CHANGED | rc=0 >>

30.配置

  • apache端
//取消注释启用代理
[root@node0 ~]# ansible node1 -m shell -a 'sed -i "s/#LoadModule proxy_module modules\/mod_proxy.so/LoadModule proxy_module modules\/mod_proxy.so/g" /etc/httpd24/httpd.conf'
[WARNING]: Consider using the replace, lineinfile or template module rather than running 'sed'.  If you need to use
command because replace, lineinfile or template 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.
node1 | CHANGED | rc=0 >>

[root@node0 ~]# ansible node1 -m shell -a 'sed -i "s/#LoadModule proxy_fcgi_module modules\/mod_proxy_fcgi.so/LoadModule proxy_fcgi_module modules\/mod_proxy_fcgi.so/g" /etc/httpd24/httpd.conf'
[WARNING]: Consider using the replace, lineinfile or template module rather than running 'sed'.  If you need to use
command because replace, lineinfile or template 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.
node1 | CHANGED | rc=0 >>

  • php端
//添加端口
[root@node0 ~]# ansible node3 -m lineinfile -a 'path=/etc/php-fpm.d/www.conf line="listen = 127.0.0.1:9000" create=yes '
node3 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "backup": "",
    "changed": true,
    "msg": "line added"
}
//重启服务查看端口
[root@node0 ~]# ansible node3 -m shell -a 'systemctl restart php-fpm'
node3 | CHANGED | rc=0 >>

[root@node0 ~]# ansible node3 -m shell -a 'ss -antl'
node3 | CHANGED | rc=0 >>
State     Recv-Q    Send-Q       Local Address:Port        Peer Address:Port    
LISTEN    0         128                0.0.0.0:22               0.0.0.0:*       
LISTEN    0         128              127.0.0.1:9000             0.0.0.0:*       
LISTEN    0         128                   [::]:22                  [::]:* 
[root@node0 ~]# vim index.php
<?php
    phpinfo();
?>
//传输到node1
[root@node0 ~]# ansible node1 -m copy -a 'src=/root/index.php dest=/usr/local/apache/htdocs/test'

//更改htdocs目录下的属主组
[root@node0 ~]# ansible node1 -m shell -a 'chown -R apache.apache /usr/local/apache/htdocs/'

//关闭防火墙
[root@node0 ~]# ansible node1 -m shell -a 'systemctl stop firewalld && setenforce 0'

报错,待研究

推荐阅读