HJM

导航

自动化运维之ansible

第三十九课 自动化运维之ansible

目录

十五、 ansible介绍
十六、 ansible安装
十七、 ansible远程执行命令
十八、 ansible拷贝文件或目录
十九、 ansible远程执行脚本
二十、 ansible管理任务计划
二十一、 ansible安装包和管理服务
二十二、 使用ansible playbook
二十三、 playbook里的变量
二十四、 playbook里的循环
二十五、 playbook里的条件判断
二十六、 playbook中的handlers
二十七、 playbook安装nginx
二十八、 playbook管理配置文件


十五、 ansible介绍

Ansilbe是一个部署一群远程主机的工具。远程的主机可以是远程虚拟机或物理机, 也可以是本地主机。

Ansilbe通过SSH协议实现远程节点和管理节点之间的通信,不需要安装客户端。

Ansible基于模块工作,模块可以由任何语言开发

Ansible不仅支持命令行使用模块,也支持编写yaml格式的playbook,易于编写和阅读

Ansible的安装十分简单,centos上可直接通过yum安装。

Ansible有提供命令行版本,免费。也有提供UI(浏览器图形化)版本,网址: www.ansible.com/tower,但是收费的。

官方文档: http://docs.ansible.com/ansible/latest/index.html

Ansible已经被redhat公司收购,它在github上是一个非常受欢迎的开源软件,github地址https://github.com/ansible/ansible

一本不错的入门电子书 https://ansible-book.gitbooks.io/ansible-first-book/


十六、 ansible安装

环境:

ansiblemanager 192.168.1.51 CentOS Linux release 7.5.1804 (Core)

ansiblemanaged01 192.168.1.52 CentOS Linux release 7.5.1804 (Core)

ansiblemanaged02 192.168.1.53 CentOS Linux release 7.5.1804 (Core)

为三台主机配置hosts文件

[root@ansiblemanager ~]# vim /etc/hosts
// 添加如下内容
192.168.1.51 ansiblemanager
192.168.1.52 ansiblemanaged01
192.168.1.53 ansiblemanaged02

1.在ansiblemanager上安装ansible

// 查看源里自带的ansible版本
[root@ansiblemanager ~]# yum list | grep ansible
Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast
ansible.noarch                            2.6.2-1.el7                  epel     
ansible-doc.noarch                        2.6.2-1.el7                  epel     
ansible-inventory-grapher.noarch          2.4.4-1.el7                  epel     
ansible-lint.noarch                       3.4.21-1.el7                 epel     
ansible-openstack-modules.noarch          0-20140902git79d751a.el7     epel     
ansible-review.noarch                     0.13.4-1.el7                 epel     
kubernetes-ansible.noarch                 0.6.0-0.1.gitd65ebd5.el7     epel     
python2-ansible-runner.noarch             1.0.1-1.el7                  epel     
python2-ansible-tower-cli.noarch          3.3.0-2.el7                  epel   
// 安装ansible
[root@ansiblemanager ~]# yum -y install ansible  ansible-doc.noarch

2.在ansiblemanager上生成密钥

[root@ansiblemanager ~]# 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:SelwQ1T30hy8SQxvHWlQ/0YmDvm0VNYvAR9qrVdqFb8 root@ansiblemanager
The key's randomart image is:
+---[RSA 2048]----+
|       .o.. +*=+=|
|       . . . X=O*|
|      . =   *.&+X|
|       = o . X+O+|
|        S   . BEo|
|             o . |
|                 |
|                 |
|                 |
+----[SHA256]-----+
[root@ansiblemanager ~]# ssh-copy-id 192.168.1.52
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.1.52 (192.168.1.52)' can't be established.
ECDSA key fingerprint is SHA256:F7bJ5VTokx6I6FGONg5glMgIm7xggOdBnDfnOz1WAm4.
ECDSA key fingerprint is MD5:d3:c0:12:84:40:a4:89:27:3f:bd:1a:2b:e5:2e:cc:27.
Are you sure you want to continue connecting (yes/no)? yes
/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.1.52's password: 

Number of key(s) added: 1

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

[root@ansiblemanager ~]# ssh 192.168.1.52
Last login: Wed Sep  5 17:31:52 2018 from ansiblemanaged01
[root@ansiblemanaged01 ~]# logout
Connection to 192.168.1.52 closed.
[root@ansiblemanager ~]# ssh-copy-id 192.168.1.53
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.1.53 (192.168.1.53)' can't be established.
ECDSA key fingerprint is SHA256:F7bJ5VTokx6I6FGONg5glMgIm7xggOdBnDfnOz1WAm4.
ECDSA key fingerprint is MD5:d3:c0:12:84:40:a4:89:27:3f:bd:1a:2b:e5:2e:cc:27.
Are you sure you want to continue connecting (yes/no)? yes
/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.1.53's password: 

Number of key(s) added: 1

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

[root@ansiblemanager ~]# ssh 192.168.1.53
Last login: Wed Sep  5 17:32:23 2018 from ansiblemanaged01
[root@ansiblemanaged02 ~]# logout
Connection to 192.168.1.53 closed.

3.新建配置被管理主机清单文件/etc/ansible/hosts

[root@ansiblemanager ~]# vim /etc/ansible/hosts
// 添加以下内容
[testhosts]
192.168.1.52
192.168.1.53

十七、 ansible远程执行命令

ansible命令的格式是:

ansible <host-pattern> [options]

演示:

// 批量执行命令,-m后面接调用module的名字, -a后面接调用module的参数
[root@ansiblemanager ~]# ansible  testhosts -m command -a 'w' 
192.168.1.52 | SUCCESS | rc=0 >>
 17:49:21 up 59 min,  3 users,  load average: 0.00, 0.01, 0.03
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     tty1                      16:52   56:01   0.02s  0.02s -bash
root     pts/0    192.168.1.9      16:52    3:13   0.32s  0.32s -bash
root     pts/1    ansiblemanager   17:49    0.00s  0.11s  0.00s w

192.168.1.53 | SUCCESS | rc=0 >>
 17:49:22 up 58 min,  3 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     tty1                      16:53   55:46   0.01s  0.01s -bash
root     pts/0    192.168.1.9      16:53    3:14   0.31s  0.31s -bash
root     pts/1    ansiblemanager   17:49    1.00s  0.08s  0.00s w

// 也可以针对单主机执行命令
[root@ansiblemanager ~]# ansible 192.168.1.52 -m command -a 'uptime'
192.168.1.52 | SUCCESS | rc=0 >>
 10:24:44 up 54 min,  2 users,  load average: 0.00, 0.01, 0.03
 
// shell模块也可以执行命令
[root@ansiblemanager ~]# ansible  testhosts -m shell -a 'w'
192.168.1.52 | SUCCESS | rc=0 >>
 10:26:16 up 55 min,  2 users,  load average: 0.00, 0.01, 0.03
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.1.9      09:31    3:52   0.01s  0.01s -bash
root     pts/1    ansiblemanager   10:26    0.00s  0.05s  0.00s w

192.168.1.53 | SUCCESS | rc=0 >>
 10:26:16 up 55 min,  2 users,  load average: 0.00, 0.01, 0.02
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.1.9      09:31   55:08   0.01s  0.01s -bash
root     pts/1    ansiblemanager   10:26    0.00s  0.08s  0.00s w

错误: "msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"

解决: yum install -y libselinux-python


十八、 ansible拷贝文件或目录

1.拷贝目录

// 源目录会放到目标目录下面去,如果目标指定的目录不存在,它会自动创建。
// 如果拷贝的是文件,dest指定的名字和源如果不同,并且它不是已经存在的目录,
// 相当于拷贝过去后又重命名。但相反,如果desc是目标机器上已经存在的目录,
// 则会直接把文件拷贝到该目录下面。
[root@ansiblemanager ~]# ansible 192.168.1.52 -m copy -a "src=/etc/ansible dest=/tmp owner=root group=root mode=755"
192.168.1.52 | SUCCESS => {
    "changed": true, 
    "dest": "/tmp/", 
    "src": "/etc/ansible"
}
// 在192.168.1.52上查看
[root@ansiblemanaged01 ~]# ls -l /tmp/
total 0
drwxr-xr-x 3 root root 51 Sep  6 10:39 ansible
drwx------ 2 root root  6 Sep  6 09:14 vmware-root
[root@ansiblemanaged01 ~]# 

2.拷贝文件

// 拷贝的行为类似于copy命令
[root@ansiblemanager ~]# ansible 192.168.1.52 -m copy -a "src=/etc/inittab dest=/tmp"                                       
192.168.1.52 | SUCCESS => {
    "changed": true, 
    "checksum": "e285e50c4dd88d8a2f644dd1750f60400ca60f94", 
    "dest": "/tmp/inittab", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "66a88d6c4d693170753ea3382f8bc150", 
    "mode": "0644", 
    "owner": "root", 
    "size": 511, 
    "src": "/root/.ansible/tmp/ansible-tmp-1536201763.72-216741204056791/source", 
    "state": "file", 
    "uid": 0
}
// 在192.168.1.52上查看
[root@ansiblemanaged01 ~]# ls -l /tmp/
total 4
drwxr-xr-x 3 root root  51 Sep  6 10:39 ansible
-rw-r--r-- 1 root root 511 Sep  6 10:42 inittab
drwx------ 2 root root   6 Sep  6 09:14 vmware-root

十九、 ansible远程执行脚本

1.在AnsibkeManager端建立脚本文件

[root@ansiblemanaged01 sh]# vim who.sh
#!/bin/bash

echo $HOSTNAME

2.分发脚本到被管理机器

[root@ansiblemanager ~]# ansible testhosts -m copy -a "src=/root/script/sh/who.sh dest=/tmp mode=755"
192.168.1.52 | SUCCESS => {
    "changed": true, 
    "checksum": "71b7b8522c1f41a69ce8f1e6671b028fdf849752", 
    "dest": "/tmp/who.sh", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "2896d6645133ac0c98022eb61a5737cb", 
    "mode": "0755", 
    "owner": "root", 
    "size": 28, 
    "src": "/root/.ansible/tmp/ansible-tmp-1536202718.33-277007092121833/source", 
    "state": "file", 
    "uid": 0
}
192.168.1.53 | SUCCESS => {
    "changed": true, 
    "checksum": "71b7b8522c1f41a69ce8f1e6671b028fdf849752", 
    "dest": "/tmp/who.sh", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "2896d6645133ac0c98022eb61a5737cb", 
    "mode": "0755", 
    "owner": "root", 
    "size": 28, 
    "src": "/root/.ansible/tmp/ansible-tmp-1536202718.34-129515903004432/source", 
    "state": "file", 
    "uid": 0
}

3.批量执行脚本

[root@ansiblemanager ~]# ansible testhosts -m shell -a '/tmp/who.sh'
192.168.1.52 | SUCCESS | rc=0 >>
ansiblemanaged01

192.168.1.53 | SUCCESS | rc=0 >>
ansiblemanaged02

// shell模块与command模块的区别: shell模块,还支持远程执行命令并且带管道
[root@ansiblemanager ~]# ansible testhosts -m command -a 'who | grep root'     
192.168.1.52 | FAILED | rc=1 >>
who: extra operand ‘root’
Try 'who --help' for more information.non-zero return code

192.168.1.53 | FAILED | rc=1 >>
who: extra operand ‘root’
Try 'who --help' for more information.non-zero return code


[root@ansiblemanager ~]# ansible testhosts -m shell -a 'who | grep root'
192.168.1.52 | SUCCESS | rc=0 >>
root     pts/0        2018-09-06 09:31 (192.168.1.9)
root     pts/1        2018-09-06 11:01 (ansiblemanager)

192.168.1.53 | SUCCESS | rc=0 >>
root     pts/0        2018-09-06 09:31 (192.168.1.9)
root     pts/1        2018-09-06 11:01 (ansiblemanager)

二十、 ansible管理任务计划

1.新建任务计划

// 其他的时间表示:分钟 minute 小时 hour 日期 day 月份 month
[root@ansiblemanager ~]# ansible testhosts -m cron -a "name='test cron' job='/bin/echo $(date +%F)>>/tmp/dd.txt'  weekday=6"
192.168.1.52 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "test cron"
    ]
}
192.168.1.53 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "test cron"
    ]
}
// 在被管理端检查计划任务是否建立
[root@ansiblemanaged01 ~]# crontab -l
#Ansible: test cron
* * * * 6 /bin/echo 2018-09-06>>/tmp/dd.txt
// 由ansible管理的计划任务,请不要手动修改,否则会导致ansible无法再管理相应的计划任务

2.删除计划任务

[root@ansiblemanager ~]# ansible 192.168.1.52 -m cron -a "name='test cron' state=absent"                                      
192.168.1.52 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": []
}
// 验证
[root@ansiblemanager ~]# ansible testhosts -m command -a "crontab -l"                                   
192.168.1.52 | SUCCESS | rc=0 >>


192.168.1.53 | SUCCESS | rc=0 >>
#Ansible: test cron
* * * * 6 /bin/echo 2018-09-06>>/tmp/dd.txt

二十一、 ansible安装包和管理服务

1.通过yum模块安装包

// 在name后面还可以加上state=installed/removed来管理软件包
[root@ansiblemanager ~]# ansible testhosts -m yum -a "name=httpd"          
192.168.1.52 | SUCCESS => {
    "changed": true, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: mirrors.cn99.com\n * epel: mirrors.aliyun.com\n * extras: mirrors.cn99.com\n * updates: mirrors.163.com\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-80.el7.centos.1 will be installed\n--> Processing Dependency: httpd-tools = 2.4.6-80.el7.centos.1 for package: httpd-2.4.6-80.el7.centos.1.x86_64\n--> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-80.el7.centos.1.x86_64\n--> Running transaction check\n---> Package httpd-tools.x86_64 0:2.4.6-80.el7.centos.1 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-80.el7.centos.1       updates       2.7 M\nInstalling for dependencies:\n httpd-tools       x86_64       2.4.6-80.el7.centos.1       updates        90 k\n mailcap           noarch       2.1.41-2.el7                base           31 k\n\nTransaction Summary\n================================================================================\nInstall  1 Package (+2 Dependent packages)\n\nTotal download size: 2.8 M\nInstalled size: 9.6 M\nDownloading packages:\n--------------------------------------------------------------------------------\nTotal                                              3.8 MB/s | 2.8 MB  00:00     \nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : httpd-tools-2.4.6-80.el7.centos.1.x86_64                     1/3 \n  Installing : mailcap-2.1.41-2.el7.noarch                                  2/3 \n  Installing : httpd-2.4.6-80.el7.centos.1.x86_64                           3/3 \n  Verifying  : mailcap-2.1.41-2.el7.noarch                                  1/3 \n  Verifying  : httpd-tools-2.4.6-80.el7.centos.1.x86_64                     2/3 \n  Verifying  : httpd-2.4.6-80.el7.centos.1.x86_64                           3/3 \n\nInstalled:\n  httpd.x86_64 0:2.4.6-80.el7.centos.1                                          \n\nDependency Installed:\n  httpd-tools.x86_64 0:2.4.6-80.el7.centos.1    mailcap.noarch 0:2.1.41-2.el7   \n\nComplete!\n"
    ]
}
192.168.1.53 | SUCCESS => {
    "changed": true, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: mirrors.163.com\n * epel: mirrors.aliyun.com\n * extras: mirrors.163.com\n * updates: mirrors.163.com\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-80.el7.centos.1 will be installed\n--> Processing Dependency: httpd-tools = 2.4.6-80.el7.centos.1 for package: httpd-2.4.6-80.el7.centos.1.x86_64\n--> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-80.el7.centos.1.x86_64\n--> Running transaction check\n---> Package httpd-tools.x86_64 0:2.4.6-80.el7.centos.1 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-80.el7.centos.1       updates       2.7 M\nInstalling for dependencies:\n httpd-tools       x86_64       2.4.6-80.el7.centos.1       updates        90 k\n mailcap           noarch       2.1.41-2.el7                base           31 k\n\nTransaction Summary\n================================================================================\nInstall  1 Package (+2 Dependent packages)\n\nTotal download size: 2.8 M\nInstalled size: 9.6 M\nDownloading packages:\n--------------------------------------------------------------------------------\nTotal                                              3.1 MB/s | 2.8 MB  00:00     \nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : httpd-tools-2.4.6-80.el7.centos.1.x86_64                     1/3 \n  Installing : mailcap-2.1.41-2.el7.noarch                                  2/3 \n  Installing : httpd-2.4.6-80.el7.centos.1.x86_64                           3/3 \n  Verifying  : mailcap-2.1.41-2.el7.noarch                                  1/3 \n  Verifying  : httpd-tools-2.4.6-80.el7.centos.1.x86_64                     2/3 \n  Verifying  : httpd-2.4.6-80.el7.centos.1.x86_64                           3/3 \n\nInstalled:\n  httpd.x86_64 0:2.4.6-80.el7.centos.1                                          \n\nDependency Installed:\n  httpd-tools.x86_64 0:2.4.6-80.el7.centos.1    mailcap.noarch 0:2.1.41-2.el7   \n\nComplete!\n"
    ]
}

2.服务管理

[root@ansiblemanager ~]# ansible testhosts -m service -a "name=httpd state=started enabled=yes" 
192.168.1.52 | SUCCESS => {
    "changed": true, 
    "enabled": true, 
    "name": "httpd", 
    "state": "started", 
    "status": {
        "ActiveEnterTimestampMonotonic": "0", 
        "ActiveExitTimestampMonotonic": "0", 
        "ActiveState": "inactive", 
        "After": "systemd-journald.socket -.mount tmp.mount nss-lookup.target system.slice basic.target network.target remote-fs.target", 
        "AllowIsolate": "no", 
        "AmbientCapabilities": "0", 
        "AssertResult": "no", 
        "AssertTimestampMonotonic": "0", 
        "Before": "shutdown.target", 
        "BlockIOAccounting": "no", 
        "BlockIOWeight": "18446744073709551615", 
        "CPUAccounting": "no", 
        "CPUQuotaPerSecUSec": "infinity", 
        "CPUSchedulingPolicy": "0", 
        "CPUSchedulingPriority": "0", 
        "CPUSchedulingResetOnFork": "no", 
        "CPUShares": "18446744073709551615", 
        "CanIsolate": "no", 
        "CanReload": "yes", 
        "CanStart": "yes", 
        "CanStop": "yes", 
        "CapabilityBoundingSet": "18446744073709551615", 
        "ConditionResult": "no", 
        "ConditionTimestampMonotonic": "0", 
        "Conflicts": "shutdown.target", 
        "ControlPID": "0", 
        "DefaultDependencies": "yes", 
        "Delegate": "no", 
        "Description": "The Apache HTTP Server", 
        "DevicePolicy": "auto", 
        "Documentation": "man:httpd(8) man:apachectl(8)", 
        "EnvironmentFile": "/etc/sysconfig/httpd (ignore_errors=no)", 
        "ExecMainCode": "0", 
        "ExecMainExitTimestampMonotonic": "0", 
        "ExecMainPID": "0", 
        "ExecMainStartTimestampMonotonic": "0", 
        "ExecMainStatus": "0", 
        "ExecReload": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -k graceful ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "ExecStart": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -DFOREGROUND ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "ExecStop": "{ path=/bin/kill ; argv[]=/bin/kill -WINCH ${MAINPID} ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "FailureAction": "none", 
        "FileDescriptorStoreMax": "0", 
        "FragmentPath": "/usr/lib/systemd/system/httpd.service", 
        "GuessMainPID": "yes", 
        "IOScheduling": "0", 
        "Id": "httpd.service", 
        "IgnoreOnIsolate": "no", 
        "IgnoreOnSnapshot": "no", 
        "IgnoreSIGPIPE": "yes", 
        "InactiveEnterTimestampMonotonic": "0", 
        "InactiveExitTimestampMonotonic": "0", 
        "JobTimeoutAction": "none", 
        "JobTimeoutUSec": "0", 
        "KillMode": "control-group", 
        "KillSignal": "18", 
        "LimitAS": "18446744073709551615", 
        "LimitCORE": "18446744073709551615", 
        "LimitCPU": "18446744073709551615", 
        "LimitDATA": "18446744073709551615", 
        "LimitFSIZE": "18446744073709551615", 
        "LimitLOCKS": "18446744073709551615", 
        "LimitMEMLOCK": "65536", 
        "LimitMSGQUEUE": "819200", 
        "LimitNICE": "0", 
        "LimitNOFILE": "4096", 
        "LimitNPROC": "1796", 
        "LimitRSS": "18446744073709551615", 
        "LimitRTPRIO": "0", 
        "LimitRTTIME": "18446744073709551615", 
        "LimitSIGPENDING": "1796", 
        "LimitSTACK": "18446744073709551615", 
        "LoadState": "loaded", 
        "MainPID": "0", 
        "MemoryAccounting": "no", 
        "MemoryCurrent": "18446744073709551615", 
        "MemoryLimit": "18446744073709551615", 
        "MountFlags": "0", 
        "Names": "httpd.service", 
        "NeedDaemonReload": "no", 
        "Nice": "0", 
        "NoNewPrivileges": "no", 
        "NonBlocking": "no", 
        "NotifyAccess": "main", 
        "OOMScoreAdjust": "0", 
        "OnFailureJobMode": "replace", 
        "PermissionsStartOnly": "no", 
        "PrivateDevices": "no", 
        "PrivateNetwork": "no", 
        "PrivateTmp": "yes", 
        "ProtectHome": "no", 
        "ProtectSystem": "no", 
        "RefuseManualStart": "no", 
        "RefuseManualStop": "no", 
        "RemainAfterExit": "no", 
        "Requires": "basic.target -.mount", 
        "RequiresMountsFor": "/var/tmp", 
        "Restart": "no", 
        "RestartUSec": "100ms", 
        "Result": "success", 
        "RootDirectoryStartOnly": "no", 
        "RuntimeDirectoryMode": "0755", 
        "SameProcessGroup": "no", 
        "SecureBits": "0", 
        "SendSIGHUP": "no", 
        "SendSIGKILL": "yes", 
        "Slice": "system.slice", 
        "StandardError": "inherit", 
        "StandardInput": "null", 
        "StandardOutput": "journal", 
        "StartLimitAction": "none", 
        "StartLimitBurst": "5", 
        "StartLimitInterval": "10000000", 
        "StartupBlockIOWeight": "18446744073709551615", 
        "StartupCPUShares": "18446744073709551615", 
        "StatusErrno": "0", 
        "StopWhenUnneeded": "no", 
        "SubState": "dead", 
        "SyslogLevelPrefix": "yes", 
        "SyslogPriority": "30", 
        "SystemCallErrorNumber": "0", 
        "TTYReset": "no", 
        "TTYVHangup": "no", 
        "TTYVTDisallocate": "no", 
        "TasksAccounting": "no", 
        "TasksCurrent": "18446744073709551615", 
        "TasksMax": "18446744073709551615", 
        "TimeoutStartUSec": "1min 30s", 
        "TimeoutStopUSec": "1min 30s", 
        "TimerSlackNSec": "50000", 
        "Transient": "no", 
        "Type": "notify", 
        "UMask": "0022", 
        "UnitFilePreset": "disabled", 
        "UnitFileState": "disabled", 
        "Wants": "system.slice", 
        "WatchdogTimestampMonotonic": "0", 
        "WatchdogUSec": "0"
    }
}
192.168.1.53 | SUCCESS => {
    "changed": true, 
    "enabled": true, 
    "name": "httpd", 
    "state": "started", 
    "status": {
        "ActiveEnterTimestampMonotonic": "0", 
        "ActiveExitTimestampMonotonic": "0", 
        "ActiveState": "inactive", 
        "After": "remote-fs.target nss-lookup.target tmp.mount network.target systemd-journald.socket system.slice -.mount basic.target", 
        "AllowIsolate": "no", 
        "AmbientCapabilities": "0", 
        "AssertResult": "no", 
        "AssertTimestampMonotonic": "0", 
        "Before": "shutdown.target", 
        "BlockIOAccounting": "no", 
        "BlockIOWeight": "18446744073709551615", 
        "CPUAccounting": "no", 
        "CPUQuotaPerSecUSec": "infinity", 
        "CPUSchedulingPolicy": "0", 
        "CPUSchedulingPriority": "0", 
        "CPUSchedulingResetOnFork": "no", 
        "CPUShares": "18446744073709551615", 
        "CanIsolate": "no", 
        "CanReload": "yes", 
        "CanStart": "yes", 
        "CanStop": "yes", 
        "CapabilityBoundingSet": "18446744073709551615", 
        "ConditionResult": "no", 
        "ConditionTimestampMonotonic": "0", 
        "Conflicts": "shutdown.target", 
        "ControlPID": "0", 
        "DefaultDependencies": "yes", 
        "Delegate": "no", 
        "Description": "The Apache HTTP Server", 
        "DevicePolicy": "auto", 
        "Documentation": "man:httpd(8) man:apachectl(8)", 
        "EnvironmentFile": "/etc/sysconfig/httpd (ignore_errors=no)", 
        "ExecMainCode": "0", 
        "ExecMainExitTimestampMonotonic": "0", 
        "ExecMainPID": "0", 
        "ExecMainStartTimestampMonotonic": "0", 
        "ExecMainStatus": "0", 
        "ExecReload": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -k graceful ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "ExecStart": "{ path=/usr/sbin/httpd ; argv[]=/usr/sbin/httpd $OPTIONS -DFOREGROUND ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "ExecStop": "{ path=/bin/kill ; argv[]=/bin/kill -WINCH ${MAINPID} ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
        "FailureAction": "none", 
        "FileDescriptorStoreMax": "0", 
        "FragmentPath": "/usr/lib/systemd/system/httpd.service", 
        "GuessMainPID": "yes", 
        "IOScheduling": "0", 
        "Id": "httpd.service", 
        "IgnoreOnIsolate": "no", 
        "IgnoreOnSnapshot": "no", 
        "IgnoreSIGPIPE": "yes", 
        "InactiveEnterTimestampMonotonic": "0", 
        "InactiveExitTimestampMonotonic": "0", 
        "JobTimeoutAction": "none", 
        "JobTimeoutUSec": "0", 
        "KillMode": "control-group", 
        "KillSignal": "18", 
        "LimitAS": "18446744073709551615", 
        "LimitCORE": "18446744073709551615", 
        "LimitCPU": "18446744073709551615", 
        "LimitDATA": "18446744073709551615", 
        "LimitFSIZE": "18446744073709551615", 
        "LimitLOCKS": "18446744073709551615", 
        "LimitMEMLOCK": "65536", 
        "LimitMSGQUEUE": "819200", 
        "LimitNICE": "0", 
        "LimitNOFILE": "4096", 
        "LimitNPROC": "1796", 
        "LimitRSS": "18446744073709551615", 
        "LimitRTPRIO": "0", 
        "LimitRTTIME": "18446744073709551615", 
        "LimitSIGPENDING": "1796", 
        "LimitSTACK": "18446744073709551615", 
        "LoadState": "loaded", 
        "MainPID": "0", 
        "MemoryAccounting": "no", 
        "MemoryCurrent": "18446744073709551615", 
        "MemoryLimit": "18446744073709551615", 
        "MountFlags": "0", 
        "Names": "httpd.service", 
        "NeedDaemonReload": "no", 
        "Nice": "0", 
        "NoNewPrivileges": "no", 
        "NonBlocking": "no", 
        "NotifyAccess": "main", 
        "OOMScoreAdjust": "0", 
        "OnFailureJobMode": "replace", 
        "PermissionsStartOnly": "no", 
        "PrivateDevices": "no", 
        "PrivateNetwork": "no", 
        "PrivateTmp": "yes", 
        "ProtectHome": "no", 
        "ProtectSystem": "no", 
        "RefuseManualStart": "no", 
        "RefuseManualStop": "no", 
        "RemainAfterExit": "no", 
        "Requires": "basic.target -.mount", 
        "RequiresMountsFor": "/var/tmp", 
        "Restart": "no", 
        "RestartUSec": "100ms", 
        "Result": "success", 
        "RootDirectoryStartOnly": "no", 
        "RuntimeDirectoryMode": "0755", 
        "SameProcessGroup": "no", 
        "SecureBits": "0", 
        "SendSIGHUP": "no", 
        "SendSIGKILL": "yes", 
        "Slice": "system.slice", 
        "StandardError": "inherit", 
        "StandardInput": "null", 
        "StandardOutput": "journal", 
        "StartLimitAction": "none", 
        "StartLimitBurst": "5", 
        "StartLimitInterval": "10000000", 
        "StartupBlockIOWeight": "18446744073709551615", 
        "StartupCPUShares": "18446744073709551615", 
        "StatusErrno": "0", 
        "StopWhenUnneeded": "no", 
        "SubState": "dead", 
        "SyslogLevelPrefix": "yes", 
        "SyslogPriority": "30", 
        "SystemCallErrorNumber": "0", 
        "TTYReset": "no", 
        "TTYVHangup": "no", 
        "TTYVTDisallocate": "no", 
        "TasksAccounting": "no", 
        "TasksCurrent": "18446744073709551615", 
        "TasksMax": "18446744073709551615", 
        "TimeoutStartUSec": "1min 30s", 
        "TimeoutStopUSec": "1min 30s", 
        "TimerSlackNSec": "50000", 
        "Transient": "no", 
        "Type": "notify", 
        "UMask": "0022", 
        "UnitFilePreset": "disabled", 
        "UnitFileState": "disabled", 
        "Wants": "system.slice", 
        "WatchdogTimestampMonotonic": "0", 
        "WatchdogUSec": "0"
    }
}

// 被管理端检查
[root@ansiblemanager ~]# ansible testhosts -m shell -a "netstat -nltp | grep :80"
192.168.1.52 | SUCCESS | rc=0 >>
tcp6       0      0 :::80                   :::*                    LISTEN      2542/httpd          

192.168.1.53 | SUCCESS | rc=0 >>
tcp6       0      0 :::80                   :::*                    LISTEN      2015/httpd          

3.Ansible文档的使用

// 列出所有的模块

[root@ansiblemanager ~]# ansible-doc -l 
a10_server                                           Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' server objec...
a10_server_axapi3                                    Manage A10 Networks AX/SoftAX/Thunder/vThunder devices              
a10_service_group                                    Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' service grou...
a10_virtual_server                                   Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' virtual serv...
accelerate                                           Enable accelerated mode on remote node                              
aci_aaa_user                                         Manage AAA users (aaa:User)                                         
aci_aaa_user_certificate                             Manage AAA user certificates (aaa:UserCert)                         
aci_access_port_to_interface_policy_leaf_profile     Manage Fabric interface policy leaf profile interface selectors (inf...
aci_aep                                              Manage attachable Access Entity Profile (AEP) objects (infra:AttEnti...
aci_aep_to_domain                                    Bind AEPs to Physical or Virtual Domains (infra:RsDomP)             
aci_ap                                               Manage top level Application Profile (AP) objects (fv:Ap
...下略...

// 查看指定模块的文档
[root@ansiblemanager ~]# ansible-doc a10_server 
> A10_SERVER    (/usr/lib/python2.7/site-packages/ansible/modules/network/a10/a10_server.py)

        Manage SLB (Server Load Balancer) server objects on A10 Networks devices via aXAPIv2.

OPTIONS (= is mandatory):

- client_cert
        PEM formatted certificate chain file to be used for SSL client authentication. This file can
        also include the key as well, and if the key is included, `client_key' is not required.
        [Default: (null)]

- client_key
        PEM formatted file that contains your private key to be used for SSL client authentication.
        If `client_cert' contains both the certificate and key, this option is not required.
        [Default: (null)]

- force
        If `yes' do not get a cached copy.
        (Aliases: thirsty)[Default: False]
        type: bool
...下略...

二十二、 使用ansible playbook

Playbooks 是 Ansible的配置,部署,编排语言.他们可以被描述为一个需要希望远程主机执行命令的方案,或者一组IT程序运行的命令集合.

如果 Ansible 模块你是工作室中的工具,那么 playbooks 就是你设置的方案计划.

Playbooks 的格式是YAML。

第一个playbook

// 编写playbook文件
// 第一行需要有三个杠,hosts参数指定了对哪些主机进行参作,
// 如果是多台机器可以用逗号作为分隔,也可以使用主机组,在/etc/ansible/hosts里定义
// user参数指定了使用什么用户登录远程主机操作
// tasks指定了一个任务,其下面的name参数同样是对任务的描述,在执行过程中会打印出来,shell是ansible模块名字

[root@ansiblemanager ~]#  vim  /etc/ansible/test.yml
---
- hosts: ansiblemanaged01
  remote_user: root
  tasks:
    - name: test_playbook
      shell: echo $HOSTNAME >>/tmp/playbook_Test.txt

// 执行
[root@ansiblemanager ansible]# ansible-playbook test.yml

PLAY [testhosts] *************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************
ok: [192.168.1.53]
ok: [192.168.1.52]

TASK [test playbook] *********************************************************************************************************
changed: [192.168.1.53]
changed: [192.168.1.52]

PLAY RECAP *******************************************************************************************************************
192.168.1.52               : ok=2    changed=1    unreachable=0    failed=0   
192.168.1.53               : ok=2    changed=1    unreachable=0    failed=0   

[root@ansiblemanager ansible]# ansible all -m shell -a "cat /tmp/playboogtest.txt" 
192.168.1.53 | SUCCESS | rc=0 >>
ansiblemanaged02

192.168.1.52 | SUCCESS | rc=0 >>
ansiblemanaged01


二十三、 playbook里的变量

演示

// 创建playbook文件
[root@ansiblemanager ansible]# vim create_user.yml
---
- name: create user
  hosts: testhosts
  user: root
  gather_facts: false
  vars:
   - user: "nico"
  tasks:
   - name: create user
     user: name="{{ user }}"
// 执行
[root@ansiblemanager ansible]# ansible-playbook create_user.yml 

PLAY [create user] ***********************************************************************************************************

TASK [create user] ***********************************************************************************************************
changed: [192.168.1.53]
changed: [192.168.1.52]

PLAY RECAP *******************************************************************************************************************
192.168.1.52               : ok=1    changed=1    unreachable=0    failed=0   
192.168.1.53               : ok=1    changed=1    unreachable=0    failed=0   
// 验证
[root@ansiblemanager ansible]# ansible all -m shell -a "grep nico /etc/passwd" 
192.168.1.52 | SUCCESS | rc=0 >>
nico:x:5001:5001::/home/nico:/bin/bash

192.168.1.53 | SUCCESS | rc=0 >>
nico:x:5001:5001::/home/nico:/bin/bash

// name参数对该playbook实现的功能做一个概述,后面执行过程中,会打印name变量的值,
// 可以省略;gather_facts参数指定了在以下任务部分执行前,是否先执行setup模块获取主机相关
// 信息,如果后面的task会使用到setup获取的信息时会用到;vars参数,指定了变量,
// 这里指字一个user变量,其值为nico,需要注意的是,变量值一定要用引号引住;
// user指定了调用user模块,name是user模块里的一个参数,而增加的用户名字调用了上面user变量的值。

二十四、 playbook里的循环

演示

// 创建playbook文件
// with_items为循环的对象
[root@ansiblemanager ansible]# vim loop.yml              
---
- hosts: 192.168.1.52
  user: root
  tasks:
   - name: change mode for files
     file: path=/tmp/{{ item }} state=touch mode=600
     with_items:
      - 1.txt
      - 2.txt
      - 3.txt
// 执行
[root@ansiblemanager ansible]# ansible-playbook loop.yml 

PLAY [192.168.1.52] **********************************************************************************************************

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

TASK [change mode for files] *************************************************************************************************
changed: [192.168.1.52] => (item=1.txt)
changed: [192.168.1.52] => (item=2.txt)
changed: [192.168.1.52] => (item=3.txt)

PLAY RECAP *******************************************************************************************************************
192.168.1.52               : ok=2    changed=1    unreachable=0    failed=0   

二十五、 playbook里的条件判断

演示:

// 新建playbook文件
[root@ansiblemanager ansible]# vim when.yml              
---
- hosts: testhosts
  user: root
  gather_facts: True
  tasks:
   - name: use when
     shell: echo $HOSTNAME >>/tmp/tt.txt
     when: ansible_ens32.ipv4.address=="192.168.1.52"
// 执行
[root@ansiblemanager ansible]# ansible-playbook when.yml 

PLAY [testhosts] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.1.52]
ok: [192.168.1.53]

TASK [use when] ****************************************************************
skipping: [192.168.1.53]
changed: [192.168.1.52]

PLAY RECAP *********************************************************************
192.168.1.52               : ok=2    changed=1    unreachable=0    failed=0   
192.168.1.53               : ok=1    changed=0    unreachable=0    failed=0   
// 验证
[root@ansiblemanager ansible]# ansible all -m command -a 'cat /tmp/tt.txt'    
192.168.1.53 | FAILED | rc=1 >>
cat: /tmp/tt.txt: No such file or directorynon-zero return code

192.168.1.52 | SUCCESS | rc=0 >>
ansiblemanaged01

// 当注释when这一句,则会对192.168.1.53

[root@ansiblemanager ansible]# vim when.yml                               
---
- hosts: testhosts
  user: root
  gather_facts: True
  tasks:
   - name: use when
     shell: echo $HOSTNAME >>/tmp/tt.txt
     #when: ansible_ens32.ipv4.address=="192.168.1.52"
// 执行
[root@ansiblemanager ansible]# ansible-playbook when.yml 

PLAY [testhosts] *************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************
ok: [192.168.1.52]
ok: [192.168.1.53]

TASK [use when] **************************************************************************************************************
changed: [192.168.1.53]
changed: [192.168.1.52]

PLAY RECAP *******************************************************************************************************************
192.168.1.52               : ok=2    changed=1    unreachable=0    failed=0   
192.168.1.53               : ok=2    changed=1    unreachable=0    failed=0   

[root@ansiblemanager ansible]# ansible all -m command -a 'cat /tmp/tt.txt'
192.168.1.52 | SUCCESS | rc=0 >>
ansiblemanaged01
ansiblemanaged01

192.168.1.53 | SUCCESS | rc=0 >>
ansiblemanaged02

//所有的facter信息可以通过 "ansible aming-02 -m setup" 查看

二十六、 playbook中的handlers

Ansible playbook中的handlers可实现类似逻辑与的功能。

演示

// 新建playbook文件
// 只有copy模块真正执行后,才会去调用下面的handlers相关的操作。
// 也就是说如果1.txt和2.txt内容是一样的,并不会去执行handlers里面的shell相关命令。 // 这种比较适合配置文件发生更改后,重启服务的操作。
[root@ansiblemanager ansible]# vim handlers.yml                       
---
- name: handlers test
  hosts: testhosts
  user: root
  tasks:
    - name: copy file
      copy: src=/etc/inittab dest=/tmp/1.txt
      notify: test handlers
  handlers:
    - name: test handlers
      shell: echo "new line" >> /tmp/1.txt
// 执行
[root@ansiblemanager ansible]# ansible-playbook handlers.yml

PLAY [handlers test] *********************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************
ok: [192.168.1.52]
ok: [192.168.1.53]

TASK [copy file] *************************************************************************************************************
changed: [192.168.1.52]
changed: [192.168.1.53]

RUNNING HANDLER [test handlers] **********************************************************************************************
changed: [192.168.1.52]
changed: [192.168.1.53]

PLAY RECAP *******************************************************************************************************************
192.168.1.52               : ok=3    changed=2    unreachable=0    failed=0   
192.168.1.53               : ok=3    changed=2    unreachable=0    failed=0   
// 检查
[root@ansiblemanager ansible]# ansible all -m command -a "tail -n 2 /tmp/1.txt"
192.168.1.52 | SUCCESS | rc=0 >>
#
new line

192.168.1.53 | SUCCESS | rc=0 >>
#
new line

二十七、 playbook安装nginx

思路:先在一台机器上编译安装好nginx、打包,然后再用ansible去下发

1.分发主机进入ansible配置文件目录

[root@ansiblemanager ~]# cd /etc/ansible/

2.为方便管理,创建一个nginx_install的目录

[root@ansiblemanager ansible]# mkdir  nginx_install
[root@ansiblemanager ansible]# ls -ld !$
ls -ld nginx_install
drwxr-xr-x 2 root root 6 Sep 10 15:03 nginx_install
[root@ansiblemanager ansible]# cd !$
cd nginx_install

3.创建playbook目录结构

[root@ansiblemanager nginx_install]# mkdir -p roles/{common,install}/{handlers,files,meta,tasks,templates,vars}
[root@ansiblemanager nginx_install]# tree
.
└── roles
    ├── common
    │   ├── files
    │   ├── handlers
    │   ├── meta
    │   ├── tasks
    │   ├── templates
    │   └── vars
    └── install
        ├── files
        ├── handlers
        ├── meta
        ├── tasks
        ├── templates
        └── vars
// roles目录下有两个角色,common为一些准备操作,install为安装nginx的操作。
// 每个角色下面又有几个目录,handlers下面是当发生改变时要执行的操作,
// 通常用在配置文件发生改变,重启服务。files为安装时用到的一些文件,
// meta为说明信息,说明角色依赖等信息,tasks里面是核心的配置文件,
// templates通常存一些配置文件,启动脚本等模板文件,vars下为定义的变量

4.在模板机安装nginx并打包

[root@lanquark sh]# cd /usr/local/
[root@lanquark local]# tar zcvf nginx.tar.gz nginx/ --exclude nginx.conf 
// 打包好以后同步到分发主机

5.将打包的nginx文件,配置文件,启动脚本拷贝到相应的目录

[root@ansiblemanager nginx_install]# mv /usr/local/src/nginx.tar.gz roles/install/files/
[root@ansiblemanager nginx_install]# mv /usr/local/src/nginx.conf roles/install/templates/
[root@ansiblemanager nginx_install]# mv /usr/local/src/nginx roles/install/templates/

6.定义普通的tasks

[root@ansiblemanager nginx_install]# vim roles/common/tasks/main.yml
- name: Install initializtion require software
  yum: name={{ item }} state=installed
  with_items:
    - zlib-devel
    - pcre-devel

7.定义变量

[root@ansiblemanager nginx_install]# vim roles/install/vars/main.yml
nginx_user: nginx
nginx_port: 80
nginx_basedir: /usr/local/nginx 

8.定义文件拷贝配置

[root@ansiblemanager nginx_install]# vim roles/install/tasks/copy.yml
- name: Copy Nginx Software
  copy: src=nginx.tar.gz dest=/tmp/nginx.tar.gz owner=root group=root
- name: Uncompression Nginx Software
  shell: tar zxf /tmp/nginx.tar.gz -C /usr/local/
- name: Copy Nginx Start Script
  template: src=nginx dest=/etc/init.d/nginx owner=root group=root mode=0755
- name: Copy Nginx Config
  template: src=nginx.conf dest={{ nginx_basedir }}/conf/ owner=root group=root mode=0644

9.建立用户、启动服务。删除安装包

[root@ansiblemanager nginx_install]# vim roles/install/tasks/install.yml

- name: Create Nginx User
  user: name={{ nginx_user }} state=present createhome=no shell=/sbin/nologin
- name: Start Nginx Service
  shell: /etc/init.d/nginx start
- name: Add Boot Start Nginx Service
  shell: chkconfig --level 345 nginx on
- name: Delete Nginx compression files
  shell: rm -rf /tmp/nginx.tar.gz

10.创建main.yml,调用copy和install

[root@ansiblemanager nginx_install]# vim roles/install/tasks/main.yml
- include: copy.yml
- include: install.yml

11.创建入口文件

[root@ansiblemanager nginx_install]# vim install.yml 
---
- hosts: 192.168.1.52
  remote_user: root
  gather_facts: True
  roles:
    - common
    - install

12.执行

[root@ansiblemanager nginx_install]# ansible-playbook install.yml 

PLAY [192.168.1.52] **********************************************************************************************************

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

TASK [common : Install initializtion require software] ***********************************************************************
ok: [192.168.1.52] => (item=[u'zlib-devel', u'pcre-devel'])

TASK [install : Copy Nginx Software] *****************************************************************************************
ok: [192.168.1.52]

TASK [install : Uncompression Nginx Software] ********************************************************************************
 [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.

changed: [192.168.1.52]

TASK [install : Copy Nginx Start Script] *************************************************************************************
ok: [192.168.1.52]

TASK [install : Copy Nginx Config] *******************************************************************************************
changed: [192.168.1.52]

TASK [install : Create Nginx User] *******************************************************************************************
changed: [192.168.1.52]

TASK [install : Start Nginx Service] *****************************************************************************************
changed: [192.168.1.52]

TASK [install : Add Boot Start Nginx Service] ********************************************************************************
changed: [192.168.1.52]

TASK [install : Delete Nginx compression files] ******************************************************************************
 [WARNING]: Consider using the file module with state=absent rather than running rm.  If you need to use command because file
is insufficient you can add warn=False to this command task or set command_warnings=False in ansible.cfg to get rid of this
message.

changed: [192.168.1.52]

PLAY RECAP *******************************************************************************************************************
192.168.1.52               : ok=10   changed=6    unreachable=0    failed=0   

13.客户端检查

[root@ansiblemanaged01 ~]# lsof -i :80
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
nginx   14441  root    6u  IPv4 510103      0t0  TCP *:http (LISTEN)
nginx   14442 nginx    6u  IPv4 510103      0t0  TCP *:http (LISTEN)

二十八、 playbook管理配置文件

生产环境中安装软件包只是在初始化环境的时候用一下,大多时候是需要管理配置文件的,下面我们来写个管理nginx配置文件的playbook

1.创建playbook配置目录结构

[root@ansiblemanager nginx_install]# mkdir  -p /etc/ansible/nginx_config/roles/{new,old}/{files,handlers,vars,tasks}
[root@ansiblemanager nginx_install]# cd ../
[root@ansiblemanager ansible]# tree nginx_config/
nginx_config/
└── roles
    ├── new
    │   ├── files
    │   ├── handlers
    │   ├── tasks
    │   └── vars
    └── old
        ├── files
        ├── handlers
        ├── tasks
        └── vars

11 directories, 0 files
// 其中new为更新时用到的,old为回滚时用到的,files下面为nginx.conf和vhosts
// 目录,handlers为重启nginx服务的task
// 关于回滚,需要在执行playbook之前先备份一下旧的配置,所以对于老配置文件的管
// 理一定要严格,千万不能随便去修改线上机器的配置,并且要保证new/files下面的
// 配置和线上的配置一致

2.把当前线上的文件放到new/files下

11 directories, 0 files
[root@ansiblemanager ansible]# cp /usr/local/src/nginx.conf nginx_config/roles/new/files/
[root@ansiblemanager ansible]# ls -l !$
ls -l nginx_config/roles/new/files/
total 4
-rw-r--r-- 1 root root 2903 Sep 10 16:53 nginx.conf

3.定义变量

[root@ansiblemanager ansible]#  vim /etc/ansible/nginx_config/roles/new/vars/main.yml
nx_basedir: /usr/local/nginx

4.定义重新加载nginx服务

[root@ansiblemanager ansible]# vim /etc/ansible/nginx_config/roles/new/handlers/main.yml  
- name: restart nginx
  shell: /etc/init.d/nginx reload

5.定义主配置文件

[root@ansiblemanager ansible]#  vim /etc/ansible/nginx_config/roles/new/tasks/main.yml 
- name: copy conf file
  copy: src={{ item.src }} dest={{ nginx_basedir }}/{{ item.dest }} backup=yes owner=root group=root mode=0644
  with_items:
    - { src: nginx.conf, dest: conf/nginx.conf }
    - { src: vhosts, dest: conf/ }
  notify: restart nginx
  1. 定义入口文件
---
- hosts: 192.168.1.52
  user: root
  roles:
  - new

7.执行更新

// 修改了默认的配置文件,新建了vhosts文件夹,并在vhosts文件夹里添加了几个配置文件
-rw-r--r-- 1 root root 56 Sep 10 20:22 update.yml
[root@ansiblemanager nginx_config]# ansible-playbook update.yml 

PLAY [192.168.1.52] *****************************************************************************************************************************************************

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

TASK [new : copy conf file] *********************************************************************************************************************************************
ok: [192.168.1.52] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'})
changed: [192.168.1.52] => (item={u'dest': u'conf/', u'src': u'vhosts'})

RUNNING HANDLER [new : restart nginx] ***********************************************************************************************************************************
changed: [192.168.1.52]

PLAY RECAP **************************************************************************************************************************************************************
192.168.1.52               : ok=3    changed=2    unreachable=0    failed=0 

// 在192.168.1.52上检查,已经更新,不再是默认的那个配置文件了
[root@ansiblemanager nginx_config]# ansible 192.168.1.52 -m command -a "tail -n 5 /usr/local/nginx/conf/nginx.conf"  
192.168.1.52 | SUCCESS | rc=0 >>
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }    
    }
}

8.回滚操作

// 更新前一定要备份new下files中的内容,再行更新
// 同步new的内容到old,也相当于备份了一次
[root@ansiblemanager nginx_config]# rsync -av roles/new/ roles/old/
sending incremental file list
files/
files/nginx.conf
files/vhosts/
files/vhosts/bbs.yuankeedu.conf
files/vhosts/www.yuankeedu.conf
handlers/
handlers/main.yml
tasks/
tasks/main.yml
vars/
vars/main.yml

sent 3,910 bytes  received 150 bytes  8,120.00 bytes/sec
total size is 3,270  speedup is 0.81
[root@ansiblemanager nginx_config]# tree
.
├── roles
│   ├── new
│   │   ├── files
│   │   │   ├── nginx.conf
│   │   │   └── vhosts
│   │   │       ├── bbs.yuankeedu.conf
│   │   │       └── www.yuankeedu.conf
│   │   ├── handlers
│   │   │   └── main.yml
│   │   ├── tasks
│   │   │   └── main.yml
│   │   └── vars
│   │       └── main.yml
│   └── old
│       ├── files
│       │   ├── nginx.conf
│       │   └── vhosts
│       │       ├── bbs.yuankeedu.conf
│       │       └── www.yuankeedu.conf
│       ├── handlers
│       │   └── main.yml
│       ├── tasks
│       │   └── main.yml
│       └── vars
│           └── main.yml
├── update.retry
└── update.yml

13 directories, 14 files
// 对配置文件进行变更,注释掉对vhosts引用
#    include vhost/*.conf;
//更新
[root@ansiblemanager nginx_config]# ansible-playbook update.yml 

PLAY [192.168.1.52] *****************************************************************************************************************************************************

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

TASK [new : copy conf file] *********************************************************************************************************************************************
changed: [192.168.1.52] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'})
ok: [192.168.1.52] => (item={u'dest': u'conf/', u'src': u'vhosts'})

RUNNING HANDLER [new : restart nginx] ***********************************************************************************************************************************
changed: [192.168.1.52]

PLAY RECAP **************************************************************************************************************************************************************
192.168.1.52               : ok=3    changed=2    unreachable=0    failed=0   

[root@ansiblemanager nginx_config]# 
// 检查是否更新

[root@ansiblemanager nginx_config]# ansible 192.168.1.52 -m command -a "grep ^# /usr/local/nginx/conf/nginx.conf"
192.168.1.52 | SUCCESS | rc=0 >>
#    include vhost/*.conf;

// 回滚
// 建立回滚入口文件
[root@ansiblemanager nginx_config]# vim rollback.yml 
---
- hosts: 192.168.1.52
  user: root
  roles:
  - old

//执行回滚
"rollback.yml" 5L, 56C written                                                                                                                         
[root@ansiblemanager nginx_config]# ansible-playbook rollback.yml 

PLAY [192.168.1.52] *****************************************************************************************************************************************************

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

TASK [old : copy conf file] *********************************************************************************************************************************************
changed: [192.168.1.52] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'})
ok: [192.168.1.52] => (item={u'dest': u'conf/', u'src': u'vhosts'})

RUNNING HANDLER [old : restart nginx] ***********************************************************************************************************************************
changed: [192.168.1.52]

PLAY RECAP **************************************************************************************************************************************************************
192.168.1.52               : ok=3    changed=2    unreachable=0    failed=0   

// 检查, 回滚成功

[root@ansiblemanager nginx_config]# ansible 192.168.1.52 -m command -a "grep vhost /usr/local/nginx/conf/nginx.conf"
192.168.1.52 | SUCCESS | rc=0 >>
    include vhost/*.conf;

posted on 2018-09-10 21:33  kennminn  阅读(574)  评论(0编辑  收藏  举报