ansible是一個部署一羣遠程主機的自動化運維工具,基於Python開發,集合了衆多運維工具(puppet、cfengine、chef、func、fabric)的優勢,它不須要安裝客戶端,經過SSH協議實現遠程節點和管理節點之間的通訊,實現了批量系統配置、批量程序部署、批量運行命令等功能。
ansible是基於模塊工做的,模塊能夠由任何語言開發,它不只支持命令行使用模塊,也支持編寫yaml格式的playbook。html
兩臺主機,jin-10,jin-11,咱們只須要在jin-10上安裝ansible便可。python
[root@jin-10 ~]# yum install -y ansible
而後把jin-10上的公鑰文件id_rsa.pub複製到jin-11上的/root/.ssh/authorized_keys裏,同時,對本機也進行密鑰認證(把/root/.ssh/id_rsa.pub文件的內容複製到authorized_keys裏)。linux
[root@jin-10 ~]# ssh jin-10 Last login: Tue Sep 3 12:27:50 2019 from jin-11
[root@jin-10 ~]# ssh jin-11 Last login: Tue Sep 3 12:24:22 2019 from jin-10
能夠看到,jin-10用ssh的方式鏈接本機和jin-11都不用密碼和密鑰認證。nginx
而後咱們設置一個主機組,用來告訴Ansible須要管理哪些主機。編輯文件vim /etc/ansible/hosts,內容以下:docker
[testhost] 127.0.0.1 jin-11
其中,testhost爲自定義的主機組名字,而後是兩個主機的IP(或主機名)。shell
ansible模塊Module
bash不管在命令行上執行,仍是bash腳本中,都須要調用cd、ls、copy、yum等命令;module就是ansible的「命令」,module是ansible命令行和腳本中都須要調用的。經常使用的ansible module有yum、copy、template等。
在bash,調用命令時能夠跟不一樣的參數,每一個命令的參數都是該命令自定義的;一樣,ansible中調用module也能夠跟不一樣的參數,每一個module的參數也都是由module自定義的。
在命令行中,-m後面接調用module的名字,-a後面接調用module的參數:apache
[root@jin-10 ~]# ansible all -m copy -a "src=/etc/hosts dest=/tmp/hosts" jin-11 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "checksum": "843eede91ec66c16e38ddb67dee1bb173ea7fe9c", "dest": "/tmp/hosts", "gid": 0, "group": "root", "mode": "0644", "owner": "root", "path": "/tmp/hosts", "secontext": "unconfined_u:object_r:admin_home_t:s0", "size": 182, "state": "file", "uid": 0 } 127.0.0.1 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "checksum": "843eede91ec66c16e38ddb67dee1bb173ea7fe9c", "dest": "/tmp/hosts", "gid": 0, "group": "root", "mode": "0644", "owner": "root", "path": "/tmp/hosts", "secontext": "unconfined_u:object_r:admin_home_t:s0", "size": 182, "state": "file", "uid": 0 }
在playbook腳本中,tasks中的每個action都是對module的一次調用。在每一個action中:冒號前面是module的名字,冒號後面是調用module的參數:編程
--- tasks: - name: ensure apache is at the latest version yum: pkg=httpd state=latest - name: write the apache config file template: src=templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf - name: ensure apache is running service: name=httpd state=started
調試和測試類的module:json
文件類的module:vim
linux上經常使用的操做:
執行Shell命令:
例:ansible testhost -m command -a 'w'
此處的testhost爲主機組名(也能夠直接寫一個ip,針對某一臺機器來執行命令),-m後邊是模塊名字,-a後面是命令
[root@jin-10 ~]# ansible testhost -m command -a 'w' jin-11 | CHANGED | rc=0 >> 09:07:34 up 21:59, 2 users, load average: 0.00, 0.01, 0.05 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.154.1 二11 20:39m 0.33s 0.33s -bash root pts/1 jin-10 09:07 1.00s 0.28s 0.02s w 127.0.0.1 | CHANGED | rc=0 >> 09:07:34 up 23:03, 3 users, load average: 0.27, 0.14, 0.19 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.154.1 二10 6.00s 6.63s 5.48s ssh jin-10 root pts/1 fe80::d601:fb6f: 二12 6.00s 7.09s 0.00s ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/21f0e6a9ae -tt 127.0.0.1 /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1567559253.0-170559931011383/AnsiballZ_command.py && sleep 0' root pts/4 localhost 09:07 1.00s 0.51s 0.01s w
針對某一臺機器來執行命令:
[root@jin-10 ~]# ansible jin-11 -m command -a 'hostname' jin-11 | CHANGED | rc=0 >> jin-11
模塊shell也能夠一樣實現:
[root@jin-10 ~]# ansible testhost -m shell -a 'hostname' jin-11 | CHANGED | rc=0 >> jin-11 127.0.0.1 | CHANGED | rc=0 >> jin-10
ansible拷貝目錄時,若是目標指定的目錄不存在,它會自動建立:
[root@jin-10 ~]# ansible jin-11 -m copy -a "src=/etc/ansible dest=/tmp/ansible_test owner=root group=root mode=0755" jin-11 | CHANGED => { "changed": true, "dest": "/tmp/ansible_test/", "src": "/etc/ansible" }
[root@jin-11 ~]# ll /tmp/ansible_test 總用量 0 drwxr-xr-x. 3 root root 51 9月 4 09:24 ansible
能夠看到目標目錄被建立且源目錄在目標目錄下面。
操做時,要注意src和dest是文件仍是目錄,拷貝文件時,若是目標目錄已經存在同名目錄,那麼會把該文件放到同名目錄裏面:
[root@jin-11 /tmp]# ll -t 總用量 4 drwxr-xr-x. 2 root root 6 9月 4 09:32 m_test
[root@jin-10 ~]# ansible jin-11 -m copy -a "src=/etc/passwd dest=/tmp/m_test" jin-11 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "checksum": "1db31b171f911344344ceb7cf8621d31be83ec07", "dest": "/tmp/m_test/passwd", "gid": 0, "group": "root", "md5sum": "e1a0ce587167dc3587ee5f1b357dc3c4", "mode": "0644", "owner": "root", "secontext": "unconfined_u:object_r:admin_home_t:s0", "size": 1299, "src": "/root/.ansible/tmp/ansible-tmp-1567560870.7-110358489604181/source", "state": "file", "uid": 0 }
[root@jin-11 /tmp]# ls m_test/ passwd
在jin-10上編寫一個test_ansible.sh的腳本,內容以下:
#!/bin/bash echo `date` >/tmp/test_ansible.txt
而後分發到主機組testhost:
[root@jin-10 ~]# ansible testhost -m copy -a "src=/tmp/test_ansible.sh dest=/tmp/test.sh mode=0755" jin-11 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "checksum": "0dc6471ba363889d83d3bf98c4354d874c86bd19", "dest": "/tmp/test.sh", "gid": 0, "group": "root", "md5sum": "bfee9509a7066ca2e822dbe48b21fbe7", "mode": "0755", "owner": "root", "secontext": "unconfined_u:object_r:admin_home_t:s0", "size": 48, "src": "/root/.ansible/tmp/ansible-tmp-1567561704.9-93797175448931/source", "state": "file", "uid": 0 } 127.0.0.1 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "checksum": "0dc6471ba363889d83d3bf98c4354d874c86bd19", "dest": "/tmp/test.sh", "gid": 0, "group": "root", "md5sum": "bfee9509a7066ca2e822dbe48b21fbe7", "mode": "0755", "owner": "root", "secontext": "unconfined_u:object_r:admin_home_t:s0", "size": 48, "src": "/root/.ansible/tmp/ansible-tmp-1567561704.82-59120276764010/source", "state": "file", "uid": 0 }
而後批量執行該腳本:
[root@jin-10 ~]# ansible testhost -m shell -a "/tmp/test.sh" jin-11 | CHANGED | rc=0 >> 127.0.0.1 | CHANGED | rc=0 >>
[root@jin-10 ~]# ls /tmp/test_ansible.txt /tmp/test_ansible.txt [root@jin-10 ~]# cat !$ cat /tmp/test_ansible.txt 2019年 09月 04日 星期三 09:50:23 CST
[root@jin-11 /tmp]# ls /tmp/test_ansible.txt /tmp/test_ansible.txt [root@jin-11 /tmp]# cat !$ cat /tmp/test_ansible.txt 2019年 09月 04日 星期三 09:50:23 CST
使用cron模塊能夠建立計劃任務:
[root@jin-10 ~]# ansible jin-11 -m cron -a "name='test cron' job='/bin/touch /tmp/test_cron' weekday=6" jin-11 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "envs": [], "jobs": [ "test cron" ] }
[root@jin-11 /tmp]# crontab -l #Ansible: test cron * * * * 6 /bin/touch /tmp/test_cron
使用cron模塊刪除計劃任務:
[root@jin-10 ~]# ansible jin-11 -m cron -a "name='test cron' state=absent" jin-11 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "envs": [], "jobs": [] }
[root@jin-11 /tmp]# crontab -l
能夠看到,以前建立的計劃任務已經被刪除了。
ansible的yum模塊能夠安裝包和管理服務(能夠進行安裝包的安裝、卸載和遠程啓動等)。 咱們在jin-11上安裝httpd爲例:
[root@jin-11 ~]# rpm -qa httpd [root@jin-11 ~]#
能夠看到,jin-11是沒有安裝httpd的。
在jin-10上執行以下命令:
[root@jin-10 ~]# ansible jin-11 -m yum -a "name=httpd state=installed" jin-11 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "changes": { "installed": [ "httpd" ] }, "msg": "", "rc": 0, "results": [ "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * base: mirrors.tuna.tsinghua.edu.cn\n * epel: hkg.mirror.rackspace.com\n * extras: mirrors.aliyun.com\n * updates: mirrors.tuna.tsinghua.edu.cn\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-89.el7.centos.1 will be installed\n--> Processing Dependency: httpd-tools = 2.4.6-89.el7.centos.1 for package: httpd-2.4.6-89.el7.centos.1.x86_64\n--> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-89.el7.centos.1.x86_64\n--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.4.6-89.el7.centos.1.x86_64\n--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.4.6-89.el7.centos.1.x86_64\n--> Running transaction check\n---> Package apr.x86_64 0:1.4.8-3.el7_4.1 will be installed\n---> Package apr-util.x86_64 0:1.5.2-6.el7 will be installed\n---> Package httpd-tools.x86_64 0:2.4.6-89.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-89.el7.centos.1 updates 2.7 M\nInstalling for dependencies:\n apr x86_64 1.4.8-3.el7_4.1 base 103 k\n apr-util x86_64 1.5.2-6.el7 base 92 k\n httpd-tools x86_64 2.4.6-89.el7.centos.1 updates 91 k\n mailcap noarch 2.1.41-2.el7 base 31 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package (+4 Dependent packages)\n\nTotal download size: 3.0 M\nInstalled size: 10 M\nDownloading packages:\n--------------------------------------------------------------------------------\nTotal 260 kB/s | 3.0 MB 00:11 \nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : apr-1.4.8-3.el7_4.1.x86_64 1/5 \n Installing : apr-util-1.5.2-6.el7.x86_64 2/5 \n Installing : httpd-tools-2.4.6-89.el7.centos.1.x86_64 3/5 \n Installing : mailcap-2.1.41-2.el7.noarch 4/5 \n Installing : httpd-2.4.6-89.el7.centos.1.x86_64 5/5 \n Verifying : httpd-2.4.6-89.el7.centos.1.x86_64 1/5 \n Verifying : mailcap-2.1.41-2.el7.noarch 2/5 \n Verifying : httpd-tools-2.4.6-89.el7.centos.1.x86_64 3/5 \n Verifying : apr-util-1.5.2-6.el7.x86_64 4/5 \n Verifying : apr-1.4.8-3.el7_4.1.x86_64 5/5 \n\nInstalled:\n httpd.x86_64 0:2.4.6-89.el7.centos.1 \n\nDependency Installed:\n apr.x86_64 0:1.4.8-3.el7_4.1 apr-util.x86_64 0:1.5.2-6.el7 \n httpd-tools.x86_64 0:2.4.6-89.el7.centos.1 mailcap.noarch 0:2.1.41-2.el7 \n\nComplete!\n" ] }
再在jin-11上查看,已經安裝了httpd包,而且沒有啓動:
[root@jin-11 ~]# rpm -qa httpd httpd-2.4.6-89.el7.centos.1.x86_64 [root@jin-11 ~]# ps aux |grep httpd root 4256 0.0 0.1 112724 996 pts/0 S+ 11:29 0:00 grep --color=auto httpd
咱們再遠程啓動httpd:
[root@jin-10 ~]# ansible jin-11 -m service -a "name=httpd state=started enabled=no"
再查看jin-11是否成功啓動httpd服務:
[root@jin-11 ~]# ps aux |grep httpd root 4355 19.0 0.5 230408 5184 ? Ss 11:31 0:00 /usr/sbin/httpd -DFOREGROUND apache 4356 0.0 0.3 230408 3004 ? S 11:31 0:00 /usr/sbin/httpd -DFOREGROUND apache 4357 0.0 0.3 230408 3004 ? S 11:31 0:00 /usr/sbin/httpd -DFOREGROUND apache 4358 0.0 0.3 230408 3004 ? S 11:31 0:00 /usr/sbin/httpd -DFOREGROUND apache 4360 0.0 0.3 230408 3004 ? S 11:31 0:00 /usr/sbin/httpd -DFOREGROUND apache 4361 0.0 0.3 230408 3004 ? S 11:31 0:00 /usr/sbin/httpd -DFOREGROUND root 4370 0.0 0.1 112724 996 pts/0 R+ 11:31 0:00 grep --color=auto httpd
能夠看到,httpd服務已經成功啓動。
playbook是指一個可被ansible執行的yml文件,最基本的playbook腳本分爲三個部分:
一、在什麼機器上以什麼身份執行:
二、執行的任務有哪些:
三、善後的任務有哪些:
下面咱們來編寫一個簡單的playbook,vim /etc/ansible/test.yml:
--- - hosts: jin-11 remote_user: root tasks: - name: test_playbook shell: touch /tmp/test_playbook.txt
而後執行:
[root@jin-10 /etc/ansible]# ansible-playbook /etc/ansible/test.yml PLAY [jin-11] ************************************************************************ TASK [Gathering Facts] *************************************************************** ok: [jin-11] TASK [test_playbook] ***************************************************************** [WARNING]: Consider using the file module with state=touch rather than running 'touch'. 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: [jin-11] PLAY RECAP *************************************************************************** jin-11 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@jin-11 ~]# ll -t /tmp/ 總用量 16 -rw-r--r--. 1 root root 0 9月 4 14:49 test_playbook.txt
能夠看到,在jin-11的/tmp/下生成了文件test_playbook.txt。
在playbook中,經過vars關鍵字自定義變量,使用時用{{ }}引用以來便可。
咱們以建立用戶爲例,編輯vim /etc/ansible/create_user.yml,內容以下:
--- - name: create_user hosts: jin-11 user: root gather_facts: false vars: - user: "test" tasks: - name: create user user: name="{{ user }}"
而後執行:
[root@jin-10 /etc/ansible]# ansible-playbook /etc/ansible/create_user.yml PLAY [create_user] ******************************************************************* TASK [create user] ******************************************************************* changed: [jin-11] PLAY RECAP *************************************************************************** jin-11 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
在jin-11上查看:
[root@jin-11 ~]# id test uid=1002(test) gid=1002(test) 組=1002(test)
ansible會經過module setup來收集主機的系統信息,這些收集到的系統信息叫作facts,這些facts信息能夠直接以變量的形式使用。
[root@jin-10 ~]# ansible all -m setup -u root jin-11 | SUCCESS => { "ansible_facts": { "ansible_all_ipv4_addresses": [ "192.168.154.11" ], "ansible_all_ipv6_addresses": [ "fe80::c9a8:961e:9b39:d180" ], "ansible_apparmor": { "status": "disabled" }, "ansible_architecture": "x86_64", ...
在playbook中定義的變量,能夠直接在template中使用,facts變量也能夠直接在template中使用,包含在inventory裏面定義的host和group變量。只要是在playbook中能夠訪問的變量,均可以在template文件中使用。
把task的執行結果也能夠做爲一個變量值。這個時候就須要用到「註冊變量」,將執行結果註冊到一個變量中,待後面的action使用,註冊變量常常和debug module一塊兒使用,這樣能夠獲得更多action的輸出信息,幫助用戶調試。
--- - hosts: all tasks: - shell: ls register: result ignore_errors: True - shell: echo "{{ result.stdout }}" when: result.rc == 5 - debug: msg="{{ result.stdout }}"
爲了使Playbook更靈活、通用性更強,容許用戶在執行的時候傳入變量的值,這個時候就須要用到「額外變量」。
在playbook中定義的變量,須要從命令行傳遞變量值。
下面是在命令行裏面傳值得的方法:
[root@jin-10 ~]# ansible-playbook for_var_test.yml --extra-vars "hosts=jin-11 user=root"
能夠用json格式傳遞參數:
[root@jin-10 ~]# ansible-playbook for_var_test.yml --extra-vars "{ 'hosts': 'jin-11', 'user': 'root' }"
還能夠把參數放在文件裏面:
[root@jin-10 ~]# ansible-playbook for_var_test.yml --extra-vars "@vars.json"
when: 相似於編程語言中的if語句
編輯文件vim /etc/ansible/when.yml,內容以下:
--- - hosts: testhost user: root gather_facts: True tasks: - name: use when shell: touch /tmp/when.txt when: ansible_ens32.ipv4.address == "192.168.154.11"
執行:
[root@jin-10 ~]# ansible-playbook /etc/ansible/when.yml PLAY [testhost] ********************************************************************** TASK [Gathering Facts] *************************************************************** ok: [jin-11] ok: [127.0.0.1] TASK [use when] ********************************************************************** skipping: [127.0.0.1] [WARNING]: Consider using the file module with state=touch rather than running 'touch'. 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: [jin-11] PLAY RECAP *************************************************************************** 127.0.0.1 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0 jin-11 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
查看結果:
[root@jin-10 ~]# ll -t /tmp/ 總用量 12 -rw-r--r--. 1 root root 43 9月 4 09:50 test_ansible.txt -rwxr-xr-x. 1 root root 48 9月 4 09:48 test.sh
[root@jin-11 ~]# ll -t /tmp/ 總用量 16 -rw-r--r--. 1 root root 0 9月 5 09:33 when.txt -rw-r--r--. 1 root root 0 9月 4 14:49 test_playbook.txt
能夠看到jin-10沒有生成when.txt文件,而jin-11則生成了。
loop: 相似於編程語言中的while語句,在playbook腳本中通常寫做with_...
編輯文件vim /etc/ansible/while.yml,內容以下:
--- - hosts: testhost user: root tasks: - name: change mode for files file: path=/tmp/{{ item }} state=touch mode=600 with_items: - while1.txt - while2.txt - while3.txt
執行:
[root@jin-10 ~]# ansible-playbook /etc/ansible/while.yml PLAY [testhost] ********************************************************************** TASK [Gathering Facts] *************************************************************** ok: [jin-11] ok: [127.0.0.1] TASK [change mode for files] ********************************************************* changed: [jin-11] => (item=while1.txt) changed: [127.0.0.1] => (item=while1.txt) changed: [jin-11] => (item=while2.txt) changed: [jin-11] => (item=while3.txt) changed: [127.0.0.1] => (item=while2.txt) changed: [127.0.0.1] => (item=while3.txt) PLAY RECAP *************************************************************************** 127.0.0.1 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 jin-11 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
查看結果:
[root@jin-10 ~]# ll -t /tmp/ 總用量 12 -rw-------. 1 root root 0 9月 5 09:45 while3.txt -rw-------. 1 root root 0 9月 5 09:45 while2.txt -rw-------. 1 root root 0 9月 5 09:45 while1.txt -rw-r--r--. 1 root root 43 9月 4 09:50 test_ansible.txt [root@jin-11 ~]# ll -t /tmp/ 總用量 16 -rw-------. 1 root root 0 9月 5 09:45 while3.txt -rw-------. 1 root root 0 9月 5 09:45 while2.txt -rw-------. 1 root root 0 9月 5 09:45 while1.txt -rw-r--r--. 1 root root 0 9月 5 09:33 when.txt
思路:先在一臺機器上編譯安裝好nginx、打包,而後再用ansible去下發。
- 建立相關的目錄
進入ansible配置文件目錄, 建立一個nginx_install的目錄,方便管理,最終目錄以下:
[root@jin-10 /var/lib/docker]# cd /etc/ansible/ [root@jin-10 /etc/ansible]# mkdir nginx_install [root@jin-10 /etc/ansible]# cd !$ cd nginx_install [root@jin-10 /etc/ansible/nginx_install]# mkdir -p roles/{common,install}/{handlers,files,meta,tasks,templates,vars} [root@jin-10 /etc/ansible/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下爲定義的變量。
[root@jin-10 /etc/ansible/nginx_install]# ls /usr/local/nginx/ client_body_temp fastcgi_temp logs sbin uwsgi_temp conf html proxy_temp scgi_temp
[root@jin-10 /etc/ansible/nginx_install]# ls /etc/init.d/nginx /etc/init.d/nginx
[root@jin-10 /etc/ansible/nginx_install]# ls /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf
把nginx的目錄打包,並複製文件到以前建立的目錄中:
[root@jin-10 /usr/local]# tar czf nginx.tar.gz --exclude "nginx.conf" --exclude "vhost" nginx/ [root@jin-10 /usr/local]# mv nginx.tar.gz /etc/ansible/nginx_install/roles/install/files/ [root@jin-10 /usr/local]# cp nginx/conf/nginx.conf /etc/ansible/nginx_install/roles/install/templates/ [root@jin-10 /usr/local]# cp /etc/init.d/nginx /etc/ansible/nginx_install/roles/install/templates/
定義common的tasks,安裝nginx須要的一些依賴包:
進入/etc/ansible/nginx_install/roles/目錄,並編寫/etc/ansible/nginx_install/roles/common/tasks/main.yml文件,內容以下:
[root@jin-10 /etc/ansible/nginx_install/roles]# vim /etc/ansible/nginx_install/roles/common/tasks/main.yml - name: Install initializtion require software yum: name={{ item }} state=installed with_items: - zlib-devel - pcre-devel
再編寫一個定義變量的文件vim /etc/ansible/nginx_install/roles/install/vars/main.yml,內容以下:
nginx_user: www nginx_port: 80 nginx_basedir: /usr/local/nginx
而後再建立一個配置文件vim /etc/ansible/nginx_install/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=06 44
再建立一個文件vim /etc/ansible/nginx_install/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
再建立一個調用copy和install的文件 /etc/ansible/nginx_install/roles/install/tasks/main.yml,內容以下:
- include: copy.yml - include: install.yml
最後,咱們再定義一個入口配置文件/etc/ansible/nginx_install/install.yml,內容以下:
--- - hosts: jin-11 remote_user: root gather_facts: True roles: - common - install
最終目錄文件以下:
[root@jin-10 /etc/ansible/nginx_install]# tree . ├── install.yml └── roles ├── common │ ├── files │ ├── handlers │ ├── meta │ ├── tasks │ │ └── main.yml │ ├── templates │ └── vars └── install ├── files │ └── nginx.tar.gz ├── handlers ├── meta ├── tasks │ ├── copy.yml │ ├── install.yml │ └── main.yml ├── templates │ ├── nginx │ └── nginx.conf └── vars └── main.yml
[root@jin-11 ~]# yum remove nginx 已加載插件:fastestmirror 參數 nginx 沒有匹配 不刪除任何軟件包
若是目標機器上已安裝了nginx,先用命令yum remove nginx刪除已安裝的nginx。
而後執行playbook腳本:
[root@jin-10 /etc/ansible/nginx_install]# ansible-playbook /etc/ansible/nginx_install/install.yml PLAY [jin-11] ************************************************************************ TASK [Gathering Facts] *************************************************************** ok: [jin-11] TASK [common : Install initializtion require software] ******************************* [DEPRECATION WARNING]: Invoking "yum" only once while using a loop via squash_actions is deprecated. Instead of using a loop to supply multiple items and specifying `name: "{{ item }}"`, please use `name: ['zlib-devel', 'pcre-devel']` and remove the loop. This feature will be removed in version 2.11. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg. ok: [jin-11] => (item=[u'zlib-devel', u'pcre-devel']) TASK [install : Copy nginx software] ************************************************* changed: [jin-11] 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: [jin-11] TASK [install : Copy nginx start script] ********************************************* ok: [jin-11] TASK [install : Copy nginx config] *************************************************** ok: [jin-11] TASK [install : Create nginx user] *************************************************** changed: [jin-11] TASK [install : Start nginx service] ************************************************* changed: [jin-11] TASK [install : Add boot start nginx service] **************************************** changed: [jin-11] 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: [jin-11] PLAY RECAP *************************************************************************** jin-11 : ok=10 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
在jin-11主機上查看是否有nginx的進程:
[root@jin-11 ~]# ps aux|grep nginx root 4040 0.0 0.0 20540 628 ? Ss 08:32 0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf nobody 4042 0.0 0.3 22984 3192 ? S 08:32 0:00 nginx: worker process nobody 4043 0.0 0.3 22984 3192 ? S 08:32 0:00 nginx: worker process root 4192 0.0 0.1 112724 996 pts/0 S+ 09:45 0:00 grep --color=auto nginx
安裝軟件通常是在初始化環境的時候,而在生產環境中,咱們大多數是要管理配置文件。
下面咱們來寫一個管理nginx配置文件的playbook。
首先先建立所須要的目錄:
[root@jin-10 ~]# mkdir -p /etc/ansible/nginx_config/roles/{new,old}/{files,handlers,vars,tasks}
最終目錄以下:
[root@jin-10 ~]# tree /etc/ansible/nginx_config/ /etc/ansible/nginx_config/ └── roles ├── new │ ├── files │ ├── handlers │ ├── tasks │ └── vars └── old ├── files ├── handlers ├── tasks └── vars
其中,new目錄更新時用到,old回滾時用到,files下面爲nginx.conf,handlers爲重啓nginx服務的命令。
關於回滾,須要在執行playbook以前先備份舊的配置,因此對於舊的配置文件的管理必定要謹慎,千萬不要隨便去修改線上機器的配置,並且要保證new/files下面的配置和線上的配置保持一致。
拷貝nginx.conf文件到/etc/ansible/nginx_config/roles/new/files/目錄下:
[root@jin-10 /usr/local/nginx/conf]# cp -r nginx.conf /etc/ansible/nginx_config/roles/new/files/
編輯一個定義變量的文件vim /etc/ansible/nginx_config/roles/new/vars/main.yml,內容以下:
nginx_basedir: /usr/local/nginx
再編寫一個從新加載nginx服務的文件vim /etc/ansible/nginx_config/roles/new/handlers/main.yml,內容以下:
- name: restart nginx shell: /etc/init.d/nginx reload
再編寫一個核心任務的文件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=r oot group=root mode=0644 with_items: - { src: nginx.conf, dest: conf/nginx.conf } notify: restart nginx
最後,咱們定義一個總入口配置文件vim /etc/ansible/nginx_config/update.yml,內容以下:
--- - hosts: testhost user: root roles: - new
執行update.yml
[root@jin-10 ~]# ansible-playbook /etc/ansible/nginx_config/update.yml PLAY [testhost] ********************************************************************** TASK [Gathering Facts] *************************************************************** ok: [jin-11] ok: [127.0.0.1] TASK [new : copy conf file] ********************************************************** ok: [jin-11] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'}) ok: [127.0.0.1] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'}) PLAY RECAP *************************************************************************** 127.0.0.1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 jin-11 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
能夠看到,nginx服務已經從新加載了:
[root@jin-11 ~]# ps aux|grep nginx root 4040 0.0 0.0 20540 628 ? Ss 08:32 0:00 nginx: master process /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf nobody 4042 0.0 0.3 22984 3192 ? S 08:32 0:00 nginx: worker process nobody 4043 0.0 0.3 22984 3192 ? S 08:32 0:00 nginx: worker process root 4570 0.0 0.1 112724 996 pts/0 S+ 10:43 0:00 grep --color=auto nginx [root@jin-11 ~]# date 2019年 09月 09日 星期一 10:44:12 CST
咱們編輯nginx.conf,加上一行註釋內容:# test for the rollback,而後再執行update.yml腳本:
[root@jin-10 ~]# cat /etc/ansible/nginx_config/roles/new/files/nginx.conf|grep test # test for the rollback [root@jin-10 ~]# ansible-playbook /etc/ansible/nginx_config/update.yml PLAY [testhost] ********************************************************************** TASK [Gathering Facts] *************************************************************** ok: [jin-11] ok: [127.0.0.1] TASK [new : copy conf file] ********************************************************** ok: [jin-11] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'}) ok: [127.0.0.1] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'}) PLAY RECAP *************************************************************************** 127.0.0.1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 jin-11 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
在jin-11上查看nginx.conf是否備份成功:
[root@jin-11 ~]# cat /usr/local/nginx/conf/nginx.conf|grep test # test for the rollback
以上的操做是針對於更新、修改配置文件的,下面來介紹一下回滾操做:
回滾操做就是把舊的配置覆蓋,而後從新加載nginx服務, 每次改動nginx配置文件以前先備份到old裏,對應目錄爲/etc/ansible/nginx_config/roles/old/files。
拷貝new目錄裏的文件到old目錄裏,至關於把當前nginx配置文件備份到old裏,如需回滾就將備份還原。
[root@jin-10 ~]# rsync -av /etc/ansible/nginx_config/roles/new/ /etc/ansible/nginx_config/roles/old/ sending incremental file list files/ files/nginx.conf handlers/ handlers/main.yml tasks/ tasks/main.yml vars/ vars/main.yml sent 2,535 bytes received 108 bytes 5,286.00 bytes/sec total size is 2,080 speedup is 0.79
編寫一個一個總入口配置文件vim /etc/ansible/nginx_config/rollback.yml,內容以下:
--- - hosts: jin-11 user: root roles: - old
下面咱們來進行一個簡單的回滾操做:
一、先將配置文件同步到old目錄下:
[root@jin-10 ~]# rsync -av /etc/ansible/nginx_config/roles/new/files/nginx.conf /etc/ansible/nginx_config/roles/old/files/nginx.conf sending incremental file list sent 49 bytes received 12 bytes 122.00 bytes/sec total size is 1,772 speedup is 29.05
二、修改配置文件/etc/ansible/nginx_config/roles/new/files/nginx.conf,文件末尾增長一行註釋內容:
#test the ansible playbook rollback
三、執行update.yml文件向客戶端更新文件:
[root@jin-10 ~]# ansible-playbook /etc/ansible/nginx_config/update.yml PLAY [testhost] ********************************************************************** TASK [Gathering Facts] *************************************************************** ok: [jin-11] ok: [127.0.0.1] TASK [new : copy conf file] ********************************************************** changed: [jin-11] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'}) changed: [127.0.0.1] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'}) RUNNING HANDLER [new : restart nginx] ************************************************ changed: [jin-11] changed: [127.0.0.1] PLAY RECAP *************************************************************************** 127.0.0.1 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 jin-11 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
四、在jin-11上查看,文件是否同步:
[root@jin-11 ~]# tail -n1 /usr/local/nginx/conf/nginx.conf #test the ansible playbook rollback
五、能夠看到,同步成功,而後咱們執行rollback.yml文件進行回滾操做:
[root@jin-10 ~]# ansible-playbook /etc/ansible/nginx_config/rollback.yml PLAY [jin-11] ************************************************************************ TASK [Gathering Facts] *************************************************************** ok: [jin-11] TASK [old : copy conf file] ********************************************************** changed: [jin-11] => (item={u'dest': u'conf/nginx.conf', u'src': u'nginx.conf'}) RUNNING HANDLER [old : restart nginx] ************************************************ changed: [jin-11] PLAY RECAP *************************************************************************** jin-11 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
六、在jin-11上查看是否已恢復:
[root@jin-11 ~]# tail -n1 /usr/local/nginx/conf/nginx.conf } [root@jin-11 ~]#
能夠看到,以前文件末尾增長的那一行沒有了。 因此,所謂的回滾就是在操做改動前,先把文件備份一份,若是出現誤操做,就將以前備份的文件還原回去,這樣就起到了一個回滾的效果。