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 ~]#
能够看到,以前文件末尾增长的那一行没有了。 因此,所谓的回滚就是在操做改动前,先把文件备份一份,若是出现误操做,就将以前备份的文件还原回去,这样就起到了一个回滚的效果。