第三十九課 自動化運維之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;