ansible的管理与剧本
首先我们安装一个ansible。
在7版本,直接用yum安装就可以
yum -y install ansible
然后清空ansible的配置文件,在里面写入自己需要管理的服务器的ip和相应的登陆密码
[root@localhost ~]# cat /etc/ansi [root@localhost ~]# cat /etc/ansible/hosts [test] web1 ansible_ssh_host=192.168.200.131 ansible_ssh_pass=mima web2 ansible_ssh_host=192.168.200.133 ansible_ssh_pass=mima [root@localhost ~]#
ansible的批量运行的脚本
[root@localhost scripts]# pwd
/server/scripts
[root@localhost scripts]# vim auto_nginx.sh
#!/bin/bash dir=/media/cdrom anzhuang=/server/scripts [ -d $dir ] || mkdir -p $dir umount /dev/sr0 mount /dev/sr0 $dir &>/dev/null yum -y install gcc gcc-c++ make pcre pcre-devel zlib zlib-devel openssl openssl-devel &>/dev/null [ -d $anzhuang ] || mkdir -p $anzhuang cd /server/scripts/ tar xf nginx-1.10.2.tar.gz -C /usr/src/ cd /usr/src/nginx-1.10.2/ ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module &>/dev/null make &>/dev/null make install &>/dev/null
exit 0
写分发脚本
[root@localhost scripts]# vim fenfa.sh
#!/bin/bash
Group=$1
dir=/server/scripts/
ansible $Group -m shell -a "mkdir -p $dir"
ansible $Group -m copy -a "src=$dir dest=$dir"
ansible $Group -m script -a "/server/scripts/auto_nginx.sh"
然后激活脚本
[root@localhost scripts]# sh fenfa.sh all
如果copy报错一下的语句
"msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"
需要在备分发的服务器上安装支持包
[root@www ~]# mount /dev/sr0 /media/cdrom/ mount: block device /dev/sr0 is write-protected, mounting read-only [root@www ~]# yum -y install libselinux-python
ansible的剧本playbook
[root@ansible scripts]# cat test_shell.yaml #playbook的执行模板 --- #开头三个小-开头 - hosts: webB tasks: - name: test shell: echo "welcome to yunjisaun" >> /tmp/username - name: test2 shell: echo "welcome to yunjisuan" >> /tmp/username 模板说明: --- #开头必须有三个小-,顶格写 - hosts: #正文配置代码的第一级,必须有两个空格(-占一个空格位) - host: webB #webB是host参数的值,值和hosts:之间要有一个空格 tasks: #tasks:表示接下来要执行的具体任务 - name: #相对于tasks再多缩进两个格(-占一个空格位),表示属于tasks的下一级 - name: test #test只是要执行的具体命令的名字可以随便写。name:后还是有一个空格要注意 shell: #表示调用shell模块执行命令相对于tasks仍旧要多缩进两个空格 shell: echo "xxx" >> xxx #shell:后边还是要有个空格,需要注意。
执行剧本
[root@ansible scripts]# ansible-playbook test_shell.yaml #执行playbook配置文件 PLAY [webB] ******************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************* ok: [webB] TASK [test] ******************************************************************************************************** changed: [webB] TASK [test2] ******************************************************************************************************* changed: [webB] PLAY RECAP ********************************************************************************************************* webB : ok=3 changed=2 unreachable=0 failed=0
简单的copy剧本
[root@ansible scripts]# echo "welcom to yunjisuan" >> /tmp/test_copy [root@ansible scripts]# cat test_copy.yaml --- - hosts: all tasks: - name: test copy copy: src=/tmp/copy_test dest=/tmp/ [root@ansible scripts]# ansible-playbook /service/scripts/test_copy.yaml PLAY [all] ********************************************************************************************************* TASK [Gathering Facts] ********************************************************************************************* ok: [webA] ok: [webB] TASK [test copy] *************************************************************************************************** changed: [webA] changed: [webB] PLAY RECAP ********************************************************************************************************* webA : ok=2 changed=1 unreachable=0 failed=0 webB : ok=2 changed=1 unreachable=0 failed=0
剧本的查看输出的过程
我们在用playbook进行ansible模块操作的时候,并没有命令的执行结果输出,默认被隐藏了。
我们可以通过register模块最加输出命令的执行结果
[root@ansible scripts]# cat test_register.yaml --- - hosts: all tasks: - name: test register shell: echo "welcome to yunjisuan" register: print_result #将之前命令的输出结果保存在变量print_result里 - debug: var=print_result #将变量的值作为debug输出出来。 [root@ansible scripts]# ansible-playbook test_register.yaml PLAY [all] ********************************************************************************************************* TASK [Gathering Facts] ********************************************************************************************* ok: [webA] ok: [webB] TASK [test register] *********************************************************************************************** changed: [webA] changed: [webB] TASK [debug] ******************************************************************************************************* ok: [webA] => { #命令的执行结果有输出了 "print_result": { "changed": true, "cmd": "echo \"welcome to yunjisuan\"", "delta": "0:00:00.002269", "end": "2018-06-15 10:28:14.693883", "failed": false, "rc": 0, "start": "2018-06-15 10:28:14.691614", "stderr": "", "stderr_lines": [], "stdout": "welcome to yunjisuan", "stdout_lines": [ "welcome to yunjisuan" ] } } ok: [webB] => { "print_result": { "changed": true, "cmd": "echo \"welcome to yunjisuan\"", "delta": "0:00:00.002633", "end": "2018-06-15 10:28:14.710242", "failed": false, "rc": 0, "start": "2018-06-15 10:28:14.707609", "stderr": "", "stderr_lines": [], "stdout": "welcome to yunjisuan", "stdout_lines": [ "welcome to yunjisuan" ] } } PLAY RECAP ********************************************************************************************************* webA : ok=3 changed=1 unreachable=0 failed=0 webB : ok=3 changed=1 unreachable=0 failed=0
配置文件下发的简单剧本
[root@ansible scripts]# cat test_nginx_conf.yaml --- - hosts: all tasks: - name: copy nginx.conf copy: src=/tmp/nginx.conf dest=/usr/local/nginx/conf/ backup=yes - name: shell: /usr/local/nginx/sbin/nginx -t register: nginx_result - debug: var=nginx_result
在剧本中使用自定义变量
[root@localhost scripts]# cat test_vars.yaml --- - hosts: all vars: #定义变量 - name: "yunjisuan" #第一个name变量 age: "3" #第二个age变量 tasks: - name: "{{ name }}" #{{}}两对大括号引用变量,变量名两头空格 shell: echo "myname {{ name }},myage {{ age }}" register: var_result - debug: var=var_result 特别提示: 引用变量需要在双引号中引用。 [root@localhost scripts]# ansible-playbook /service/scripts/test_vars.yaml [WARNING]: Found variable using reserved name: name #这里提示,name是一个保留的内置变量,我们在自定义时不能用 PLAY [all] ********************************************************************************************************* TASK [Gathering Facts] ********************************************************************************************* ok: [webA] ok: [webB] TASK [yunjisuan] *************************************************************************************************** changed: [webA] changed: [webB] TASK [debug] ******************************************************************************************************* ok: [webA] => { "var_result": { "changed": true, "cmd": "echo \"myname yunjisuan,myage 3\"", "delta": "0:00:00.002320", "end": "2018-06-19 10:45:16.175728", "failed": false, "rc": 0, "start": "2018-06-19 10:45:16.173408", "stderr": "", "stderr_lines": [], "stdout": "myname yunjisuan,myage 3", "stdout_lines": [ "myname yunjisuan,myage 3" ] } } ok: [webB] => { "var_result": { "changed": true, "cmd": "echo \"myname yunjisuan,myage 3\"", "delta": "0:00:00.002518", "end": "2018-06-19 10:45:10.552331", "failed": false, "rc": 0, "start": "2018-06-19 10:45:10.549813", "stderr": "", "stderr_lines": [], "stdout": "myname yunjisuan,myage 3", "stdout_lines": [ "myname yunjisuan,myage 3" ] } } PLAY RECAP ********************************************************************************************************* webA : ok=3 changed=1 unreachable=0 failed=0 webB : ok=3 changed=1 unreachable=0 failed=0 #我们修改一下name这个变量再发送,就不会出警告了 [root@localhost scripts]# cat test_vars.yaml --- - hosts: all vars: - names: "yunjisuan" age: "3" tasks: - name: "{{ names }}" shell: echo "myname {{ names }},myage {{ age }}" register: var_result - debug: var=var_result
在使用自定义变量时,要特别注意不要和系统的内置保留变量同名,容易引发问题。
使用内置的变量
我们可以使用ansible all -m setup | less查看ansible内置变量
[root@localhost scripts]# cat test_setupvars.yaml --- - hosts: all gather_facts: True #使用ansible内置变量 tasks: - name: setup var shell: echo "ip {{ ansible_all_ipv4_addresses[0] }} cpu {{ ansible_processor_count }}" register: var_result - debug: var=var_result [root@localhost scripts]# [root@localhost scripts]# ansible-playbook test_setupvars.yaml PLAY [all] ********************************************************************************************************* TASK [Gathering Facts] ********************************************************************************************* ok: [webA] ok: [webB] TASK [setup var] *************************************************************************************************** changed: [webA] changed: [webB] TASK [debug] ******************************************************************************************************* ok: [webA] => { "var_result": { "changed": true, "cmd": "echo \"ip 192.168.200.132 cpu 1\"", "delta": "0:00:00.002408", "end": "2018-06-19 11:32:44.540658", "failed": false, "rc": 0, "start": "2018-06-19 11:32:44.538250", "stderr": "", "stderr_lines": [], "stdout": "ip 192.168.200.132 cpu 1", "stdout_lines": [ "ip 192.168.200.132 cpu 1" ] } } ok: [webB] => { "var_result": { "changed": true, "cmd": "echo \"ip 192.168.200.138 cpu 1\"", "delta": "0:00:00.002102", "end": "2018-06-19 11:32:44.526875", "failed": false, "rc": 0, "start": "2018-06-19 11:32:44.524773", "stderr": "", "stderr_lines": [], "stdout": "ip 192.168.200.138 cpu 1", "stdout_lines": [ "ip 192.168.200.138 cpu 1" ] } } PLAY RECAP ********************************************************************************************************* webA : ok=3 changed=1 unreachable=0 failed=0 webB : ok=3 changed=1 unreachable=0 failed=0
去内置变量的操作
[root@localhost scripts]# cat test_setupvars.yaml --- - hosts: all gather_facts: True tasks: - name: setup var shell: echo "ip {{ ansible_all_ipv4_addresses[0] }} cpu {{ ansible_processor_count }}" >> /tmp/test - name: setup var2 shell: echo "time {{ ansible_date_time["date"] }}" >> /tmp/test register: var_result - debug: var=var_result
利用template模块下发可变的变量配置
[root@localhost scripts]# cat /tmp/test my name is {{ myname }} #自定义变量 my name is {{ ansible_all_ipv4_addresses[0] }} #系统变量 [root@localhost scripts]# cat test_filevars.yaml --- - hosts: all gather_facts: True #开启系统变量 vars: - myname: "yunjisuan" #自定义变量 tasks: - name: template test template: src=/tmp/test dest=/root/test #使用template下发可变配置文件 [root@localhost scripts]# ansible-playbook test_filevars.yaml
下发的变量的判断的语法
[root@localhost scripts]# cat /tmp/if.j2 {% if PORT %} #if PORT存在 ip=0.0.0.0:{{ PORT }} {% else %} #否则的话 ip=0.0.0.0:80 {% endif %} #结尾 [root@localhost scripts]# cat test_ifvars.yaml --- - hosts: all gather_facts: True #开启系统内置变量 vars: - PORT: 90 #自定义变量 tasks: - name: jinja2 if test template: src=/tmp/if.j2 dest=/root/test [root@localhost scripts]# ansible-playbook test_ifvars.yaml
如果我们把PROT的值置空就会是假
[root@localhost scripts]# cat test_ifvars.yaml --- - hosts: all gather_facts: True vars: - PORT: #置空 tasks: - name: jinja2 if test template: src=/tmp/if.j2 dest=/root/test [root@localhost scripts]# ansible-playbook test_ifvars.yaml
剧本的通知和下发机制
#下发可执行动作的可变的nginx配置文件 [root@localhost scripts]# head -1 /tmp/nginx.j2 worker_processes {{ ansible_processor_count }}; #可变的参数 [root@localhost scripts]# cat test_nginxvars.yaml --- - hosts: all gather_facts: True #开启系统内置变量 tasks: - name: nginx conf template: src=/tmp/nginx.j2 dest=/usr/local/nginx/conf/nginx.conf notify: - reload nginx #下发通知给handlers模块执行名字叫做reload nginx的动作 handlers: #定义动作 - name: reload nginx #动作的名字 shell: /usr/local/nginx/sbin/nginx -s reload [root@localhost scripts]# ansible-playbook test_nginxvars.yaml
用roles来模板换剧本,可以自己组合模板
#创建roles基本原型的目录结构 [root@ansible myroles]# tree /myroles/ /myroles/ ├── nginx.yaml #入口触发配置文件 └── roles #playbook的原型配置目录 └── nginx #nginx相关模组配置目录 ├── files #copy模块和script模块的参数src默认会从这个文件夹查找 ├── handlers #用来存放notify的 ├── tasks #用来存放ansible模块任务的 ├── templates #用来存放j2的 └── vars #用来存放变量的 7 directories, 1 file #入口触发配置文件 [root@ansible myroles]# cat /myroles/nginx.yaml --- - hosts: all #执行的主机范围 gather_facts: True #开启系统内置变量 roles: #启用roles原型配置 - nginx #执行nginx原型模组
tasks的任务编排模块
#在nginx模组添加tasks任务配置文件 [root@ansible myroles]# cat roles/nginx/tasks/main.yaml --- - name: check alived #任务1的名字 ping: #执行ping模块 - name: #任务2的名字 shell: ls / #执行shell模块 register: ls_result #将执行结果保存给变量 - debug: var=ls_result #变量的值赋值给debug进行输出 #完成后的目录结构如下所示 [root@ansible myroles]# tree /myroles/ /myroles/ ├── nginx.yaml #nginx模组入口配置文件 └── roles └── nginx #nginx原型模组目录 ├── files ├── handlers ├── tasks │ └── main.yaml #nginx模组的tasks任务配置文件 ├── templates └── vars 7 directories, 2 files
执行监督的模块
[root@ansible myroles]# ansible-playbook nginx.yaml PLAY [all] **************************************************************************************************** TASK [Gathering Facts] **************************************************************************************** ok: [webA] ok: [webB] TASK [nginx : check alived] *********************************************************************************** ok: [webA] ok: [webB] TASK [nginx : shell] ****************************************************************************************** changed: [webA] changed: [webB] TASK [nginx : debug] ****************************************************************************************** ok: [webA] => { "ls_result": { "changed": true, "cmd": "ls /", "delta": "0:00:00.002805", "end": "2018-06-21 11:52:29.343592", "failed": false, "rc": 0, "start": "2018-06-21 11:52:29.340787", "stderr": "", "stderr_lines": [], "stdout": "bin\nboot\ndev\netc\nhome\nlib\nlib64\nmedia\nmnt\nopt\nproc\nroo\nroot\nrun\nsbin\nservice\nsrv\nsys\ntmp\nusr\nvar", "stdout_lines": [ "bin", "boot", "dev", "etc", "home", "lib", "lib64", "media", "mnt", "opt", "proc", "roo", "root", "run", "sbin", "service", "srv", "sys", "tmp", "usr", "var" ] } } ok: [webB] => { "ls_result": { "changed": true, "cmd": "ls /", "delta": "0:00:00.002708", "end": "2018-06-21 11:52:29.359754", "failed": false, "rc": 0, "start": "2018-06-21 11:52:29.357046", "stderr": "", "stderr_lines": [], "stdout": "bin\nboot\ndev\netc\nhome\nlib\nlib64\nmedia\nmnt\nopt\nproc\nroo\nroot\nrun\nsbin\nservice\nsrv\nsys\ntmp\nusr\nvar", "stdout_lines": [ "bin", "boot", "dev", "etc", "home", "lib", "lib64", "media", "mnt", "opt", "proc", "roo", "root", "run", "sbin", "service", "srv", "sys", "tmp", "usr", "var" ] } } PLAY RECAP **************************************************************************************************** webA : ok=4 changed=1 unreachable=0 failed=0 webB : ok=4 changed=1 unreachable=0 failed=0
ansible-playbook执行入口配置文件nginx.yaml后,它会自动在roles目录下查找nginx目录并进入后查找tasks任务目录并执行main.yaml的任务配置文件。 其实,这个roles的操作等效于以下配置
#本配置和之前的roles配置等效 [root@ansible myroles]# cat /service/scripts/test.yaml --- - hosts: all gather_facts: True tasks: #其实roles的本质就是将tasks任务单独写了。 - name: check alived #并在入口文件里追加了roles去查找tasks配置文件路径 ping: - name: shell: ls / register: ls_result - debug: var=ls_result
roles下的自定义变量模块
#创建自定义变量vars模组的配置文件 [root@ansible myroles]# cat roles/nginx/vars/main.yaml --- my_name: yunjisuan phone: 1800000000 [root@ansible myroles]# cat roles/nginx/tasks/main.yaml --- - name: check alived ping: - name: shell: ls / register: ls_result - debug: var=ls_result - name: #添加对变量引用的任务编排 shell: echo my phone is {{ phone }} register: echo_result - debug: var=echo_result [root@ansible myroles]# ansible-playbook nginx.yaml #执行入口配置文件
roles使用copy,和scripts模块
[root@ansible myroles]# cat roles/nginx/files/test welcome to yunjisuan [root@ansible myroles]# cat roles/nginx/files/test.sh echo "aaa" >> /tmp/test [root@ansible myroles]# chmod +x roles/nginx/files/test.sh [root@ansible myroles]# cat roles/nginx/tasks/main.yaml --- - name: check alived ping: - name: shell: ls / register: ls_result - debug: var=ls_result - name: shell: echo my phone is {{ phone }} register: echo_result - debug: var=echo_result - name: #添加copy模块 copy: src=test dest=/root/ - name: #添加script模块(自动在目标IP机器上执行脚本) script: test.sh [root@ansible myroles]# ansible-playbook nginx.yaml
roles中的template模块
[root@ansible myroles]# cat roles/nginx/templates/test.j2 myname is {{ my_name }},my phone is {{ phone }} #引用自定义变量 my ipaddress is {{ansible_all_ipv4_addresses[0]}} #引用内置变量 [root@ansible myroles]# cat roles/nginx/tasks/main.yaml --- - name: check alived ping: - name: shell: ls / register: ls_result - debug: var=ls_result - name: shell: echo my phone is {{ phone }} register: echo_result - debug: var=echo_result - name: copy: src=test dest=/root/ - name: script: test.sh - name: template: src=test.j2 dest=/root/test2 #下发可变配置文件 [root@ansible myroles]# ansible-playbook nginx.yaml
roles的notify变动通知执行模块
[root@ansible myroles]# cat roles/nginx/handlers/main.yaml --- - name: start_nginx #定义handlers的动作类型 shell: /usr/local/nginx/sbin/nginx - name: stop_nginx #定义handlers的动作类型 shell: /usr/local/nginx/sbin/nginx -s stop - name: reload_nginx #定义handlers的动作类型 shell: /usr/local/nginx/sbin/nginx -s reload [root@ansible myroles]# cat roles/nginx/tasks/main.yaml --- - name: check alived ping: - name: shell: ls / register: ls_result - debug: var=ls_result - name: shell: echo my phone is {{ phone }} register: echo_result - debug: var=echo_result - name: copy: src=test dest=/root/ - name: script: test.sh - name: template: src=test.j2 dest=/root/test2 notify: start_nginx #执行template任务后下发通知给handlers执行start_nginx [root@ansible myroles]# ansible-playbook nginx.yaml
特别提示:
notify下发通知只有当之前的任务造成了变化那么才会被执行,如果没有发生任何改变,则notify不会被执行。例如:
#tasks任务造成改变,触发notify [root@ansible myroles]# cat /tmp/test.yaml --- - hosts: webA gather_facts: True tasks: - name: copy: src=/tmp/test dest=/root/ #这步造成目标改变才能出发notify notify: start_nginx handlers: - name: start_nginx shell: /usr/local/nginx/sbin/nginx [root@ansible myroles]# ansible-playbook /tmp/test.yaml PLAY [webA] *************************************************************************************************** TASK [Gathering Facts] **************************************************************************************** ok: [webA] TASK [copy] *************************************************************************************************** changed: [webA] #发生了改变 RUNNING HANDLER [start_nginx] #触发notify ********************************************************************************* changed: [webA] PLAY RECAP **************************************************************************************************** webA : ok=3 changed=2 unreachable=0 failed=0 #我们再次执行/tmp/test.yaml [root@ansible myroles]# ansible-playbook /tmp/test.yaml PLAY [webA] *************************************************************************************************** TASK [Gathering Facts] **************************************************************************************** ok: [webA] TASK [copy] *************************************************************************************************** ok: [webA] #没有造成任务改变,未触发notify通知 PLAY RECAP **************************************************************************************************** webA : ok=2 changed=0 unreachable=0 failed=0