第三十九课 自动化运维之ansiblephp
目录html
十5、 ansible介绍
十6、 ansible安装
十7、 ansible远程执行命令
十8、 ansible拷贝文件或目录
十9、 ansible远程执行脚本
二10、 ansible管理任务计划
二11、 ansible安装包和管理服务
二12、 使用ansible playbook
二十3、 playbook里的变量
二十4、 playbook里的循环
二十5、 playbook里的条件判断
二十6、 playbook中的handlers
二十7、 playbook安装nginx
二十8、 playbook管理配置文件node
Ansilbe是一个部署一群远程主机的工具。远程的主机能够是远程虚拟机或物理机, 也能够是本地主机。python
Ansilbe经过SSH协议实现远程节点和管理节点之间的通讯,不须要安装客户端。linux
Ansible基于模块工做,模块能够由任何语言开发nginx
Ansible不只支持命令行使用模块,也支持编写yaml格式的playbook,易于编写和阅读git
Ansible的安装十分简单,centos上可直接经过yum安装。github
Ansible有提供命令行版本,免费。也有提供UI(浏览器图形化)版本,网址: www.ansible.com/tower,可是收费的。shell
官方文档: http://docs.ansible.com/ansible/latest/index.htmlapache
Ansible已经被redhat公司收购,它在github上是一个很是受欢迎的开源软件,github地址https://github.com/ansible/ansible
一本不错的入门电子书 https://ansible-book.gitbooks.io/ansible-first-book/
环境:
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 <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
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
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)
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
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 ...下略...
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文件 [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文件 // 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文件 [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" 查看
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
思路:先在一台机器上编译安装好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)
生产环境中安装软件包只是在初始化环境的时候用一下,大多时候是须要管理配置文件的,下面咱们来写个管理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
--- - 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;