ansible自动化
一,工具与环境介绍
1.1 ansible简介
批量管理服务器的工具
无需部署agent,通过ssh进行管理
流行的自动化运维工具:https://github.com/ansible/ansible
1.2 jenkins简介
可视化运维(主要用在可视化部署)
持续构建,可以和git,svn结合
可结合ssh实现可视化运维
可结合ansible实现可视化运维
1.3 环境说明
Centos7.3(yum -y install net-tools vim)
关闭防火墙(systemctl stop firewalld,systemctl disable firewalld)
关闭selinux
二,Python3与ansible的安装
2.1 使用源码安装Python3.5
#安装支持包[root@ansible ~]# yum -y install lrzsz vim net-tools gcc gcc-c++ ncurses ncurses-devel unzip zlib-devel zlib openssl-devel openssl#源码编译Python3.5[root@ansible Python-3.5.2]# tar xf Python-3.5.2.tgz -C /usr/src/[root@ansible Python-3.5.2]# cd /usr/src/Python-3.5.2/[root@ansible Python-3.5.2]# ./configure --prefix=/usr/local/python/[root@ansible Python-3.5.2]# make && make install[root@ansible Python-3.5.2]# ln -s /usr/local/python/bin/python3 /usr/bin/python3[root@ansible Python-3.5.2]# which python3/usr/bin/python3[root@ansible Python-3.5.2]# python3 -VPython 3.5.2
2.2 使用pip3安装ansible
#安装ansible最新版本[root@ansible Python-3.5.2]# /usr/local/python/bin/pip3 install ansible#静心等待ansible安装完毕后[root@ansible python]# ln -s /usr/local/python/bin/ansible /usr/local/bin/[root@ansible python]# which ansible/usr/local/bin/ansible[root@ansible python]# ansible --versionansible 2.5.4config file = Noneconfigured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']ansible python module location = /usr/local/python/lib/python3.5/site-packages/ansibleexecutable location = /usr/local/bin/ansiblepython version = 3.5.2 (default, Jun 13 2018, 09:13:32) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
2.3 ansible查看帮助
[root@ansible ~]# /usr/local/python/bin/ansible-doc -l 查看总帮助 [root@ansible ~]# /usr/local/python/bin/ansible-doc -s shell 查看shell模块的帮助 [root@ansible ~]# /usr/local/python/bin/ansible-doc -s raw
三,使用公私钥实现ssh无密码登陆
ansible是无agent的,无agent是怎么批量管理服务器的?主要是借用ssh来批量管理服务器。
ssh默认登陆是需要密码的,所以管理起来比较麻烦,这节课主要是介绍ssh的无密码登陆。
ssh无密码登陆实现以后,使用ansible批量管理服务器就变得简单了。
| Host | IP |
|---|---|
| ansible | 192.168.200.137 |
| webA | 192.168.200.132 |
| webB | 192.168.200.138 |
#生成密钥对[root@ansible python]# ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ""#分发密钥[root@ansible python]# ssh-copy-id -i ~/.ssh/id_rsa.pub "-o StrictHostKeyChecking=no" 192.168.200.132#进行免密码登陆测试[root@ansible python]# ssh 192.168.200.132Last login: Wed Jun 13 11:01:10 2018 from 192.168.200.137[root@webA ~]# hostname -I192.168.200.132[root@webA ~]# exitlogoutConnection to 192.168.200.132 closed.[root@ansible python]# hostname -I192.168.200.137
四,ansible的简单配置和ping模块
4.1 ansible的配置文件
通过pip安装的ansible是没有配置文件的。我们需要创建一个
[root@ansible python]# mkdir -p /etc/ansible[root@ansible python]# vim /etc/ansible/hosts[root@ansible python]# cat /etc/ansible/hosts #ansible主机管理配置文件[nginx] #被管理的主机组名称webA ansible_ssh_host=192.168.200.132 ansible_ssh_port=22 ansible_ssh_user=root #第一台主机webB ansible_ssh_host=192.168.200.138 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=666666 #第二台主机特别提示:WebA ===> 主机名ansible_ssh_host ===>主机IPansible_ssh_port ===>ssh的默认端口ansible_ssh_user ===>ssh的用户名ansible_ssh_pass ===>ssh的用户的连接密码
如果我们已经设置了ssh免密钥了。那么就不需要写密码了。例如:webA
我们要是没有设置免密钥,那么就需要安装sshpass工具,并在/etc/ansible/hosts文件里写上主机的连接密码。例如webB
#下载epel源安装sshpass[root@ansible python]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo[root@ansible python]# yum -y install sshpass[root@ansible python]# which sshpass/usr/bin/sshpass
4.2 进行ansible远程执行命令测试
语法:
ansible chensiqi -m command -a 'uptime'
ansible 主机组 -m ansible内置功能模块名 -a 命令
进行命令测试:
#进行ping模块的连接测试[root@ansible python]# ansible nginx -m pingwebB | FAILED! => { #我们发现webB还是没链接成功,这是因为本机的known_hosts文件还没有记录对方主机的信息。"msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host's fingerprint to your known_hosts file to manage this host."}webA | SUCCESS => { #webA成功"changed": false,"ping": "pong"}
想要解决known_hosts的问题,只需要修改ssh的配置文件/etc/ssh/ssh_config即可
#修改ssh配置文件[root@ansible .ssh]# sed -n '35p' /etc/ssh/ssh_config# StrictHostKeyChecking ask[root@ansible .ssh]# vim /etc/ssh/ssh_config[root@ansible .ssh]# sed -n '35p' /etc/ssh/ssh_configStrictHostKeyChecking no #去掉注释,修改成这样#重启ssh服务[root@ansible .ssh]# systemctl reload sshd.service#再次进行ansible连接测试[root@ansible .ssh]# ansible nginx -m pingwebA | SUCCESS => {"changed": false,"ping": "pong"}webB | SUCCESS => {"changed": false,"ping": "pong"}
4.3 ansible的简单使用方式
ansible -i /etc/ansible/hosts 主机或主机组 -m 指定模块 -a 命令
不用-i指定配置文件默认为/etc/ansible/hosts
4.4 使用ping模块用来查看服务器是否连接正常,ping模块不需要-a指定参数
ansible all -m ping
主机组,主机,all代表所有
主机和主机组注意事项:
| 主机组范围 | 解释 |
|---|---|
| all | 代表所有主机 |
| webA:webB | 可以指定多台主机 |
| all:\!webA | 指定all但不包含webB,注意!前需要加转意符号\ |
#操作测试[root@ansible .ssh]# ansible webA -m pingwebA | SUCCESS => {"changed": false,"ping": "pong"}[root@ansible .ssh]# ansible all -m pingwebA | SUCCESS => {"changed": false,"ping": "pong"}webB | SUCCESS => {"changed": false,"ping": "pong"}[root@ansible .ssh]# ansible webA:webB -m pingwebA | SUCCESS => {"changed": false,"ping": "pong"}webB | SUCCESS => {"changed": false,"ping": "pong"}[root@ansible .ssh]# ansible all:\!webA -m pingwebB | SUCCESS => {"changed": false,"ping": "pong"}[root@ansible .ssh]# ansible webA:webB -m command -a 'uptime'webA | SUCCESS | rc=0 >>12:29:05 up 2:43, 3 users, load average: 0.00, 0.01, 0.05webB | SUCCESS | rc=0 >>12:29:05 up 1:03, 2 users, load average: 0.01, 0.02, 0.02
五,ansible的三个命令模块
5.1 ansible模块command(不支持管道,不建议使用)
#command支持直接回显命令的执行结果[root@ansible ~]# ansible all -m command -a "pwd"webA | SUCCESS | rc=0 >>/rootwebB | SUCCESS | rc=0 >>/root#command模块不支持管道符操作[root@ansible ~]# ansible all -m command -a "echo test | grep t"webA | SUCCESS | rc=0 >>test | grep twebB | SUCCESS | rc=0 >>test | grep t#command模块不支持重定向操作[root@ansible ~]# ansible all -m command -a "echo bb >> /tmp/testansible"webA | SUCCESS | rc=0 >>bb >> /tmp/testansiblewebB | SUCCESS | rc=0 >>bb >> /tmp/testansible
5.2 ansible模块shell(支持管道,支持重定向)
#shell模块支持管道符[root@ansible ~]# ansible all -m shell -a "echo testansible | grep a"webA | SUCCESS | rc=0 >>testansiblewebB | SUCCESS | rc=0 >>testansible#shell支持重定向[root@ansible ~]# ansible all -m shell -a "echo bb >> /tmp/testansible"webA | SUCCESS | rc=0 >>webB | SUCCESS | rc=0 >>#如果遇到特殊符号需要加入\转义,这样子ansible才能正常运行[root@ansible ~]# ansible all -m shell -a "cat /etc/passwd | awk -F":" '{print \$1}'"webB | SUCCESS | rc=0 >>rootbindaemonadmlpsyncshutdownhaltmailoperatorgamesftpnobodysystemd-bus-proxysystemd-networkdbuspolkitdtsspostfixsshdchronywebA | SUCCESS | rc=0 >>rootbindaemonadmlpsyncshutdownhaltmailoperatorgamesftpnobodysystemd-bus-proxysystemd-networkdbuspolkitdtsspostfixsshdchrony
5.3 ansible模块raw,最原始的方式运行命令(不依赖python,仅通过ssh实现)
#清除yum缓存[root@ansible ~]# ansible all -m raw -a "yum -y clean all"webB | SUCCESS | rc=0 >>Loaded plugins: fastestmirrorCleaning repos: c7-mediaCleaning up everythingShared connection to 192.168.200.138 closed.webA | SUCCESS | rc=0 >>Loaded plugins: fastestmirrorCleaning repos: c7-media epelCleaning up everythingCleaning up list of fastest mirrorsShared connection to 192.168.200.132 closed.#建立yum缓存[root@ansible ~]# ansible all -m raw -a "yum makecache"webA | SUCCESS | rc=0 >>Loaded plugins: fastestmirrorc7-media | 3.6 kB 00:00Loading mirror speeds from cached hostfile* c7-media:Metadata Cache CreatedShared connection to 192.168.200.132 closed.webB | SUCCESS | rc=0 >>Loaded plugins: fastestmirrorc7-media | 3.6 kB 00:00Loading mirror speeds from cached hostfile* c7-media:Metadata Cache CreatedShared connection to 192.168.200.138 closed.#yum装nmap包ansible all -m raw -a "yum -y install nmap"
六,ansible的copy模块批量下发文件或文件夹
6.1 copy模块概述
copy模块的参数,ansible 主机组 -m 模块 -a 命令
- src:指定源文件或目录
- dest:指定目标服务器的文件或目录
- backup:是否要备份
- owner:拷贝到目标服务器后,文件或目录的所属用户
- group:拷贝到目标服务器后,文件或目录的所属群组
- mode:文件或目录的权限
准备工作
- [root@ansible ~]# mkdir -p /service/scripts
- [root@ansible ~]# echo "aaa" > /service/scripts/test.txt
- [root@ansible ~]# echo "bbb" > /service/scripts/test2.txt
所有被管理端节点必须安装libselinux-python包
- yum -y install libselinux-python
6.2 copy模块拷贝文件
特别提示:如果目标路径不存在会自动创建
src===>源文件路径 dest=目标路径位置
[root@ansible ~]# ansible all -m copy -a "src=/service/scripts/test.txt dest=/service/scripts/"webB | FAILED! => { #节点未安装libselinux-python"changed": false,"checksum": "972a1a11f19934401291cc99117ec614933374ce","msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"}webA | SUCCESS => {"changed": true,"checksum": "972a1a11f19934401291cc99117ec614933374ce","dest": "/service/scripts/test.txt","gid": 0,"group": "root","md5sum": "5c9597f3c8245907ea71a89d9d39d08e","mode": "0644","owner": "root","secontext": "system_u:object_r:svc_svc_t:s0","size": 4,"src": "/root/.ansible/tmp/ansible-tmp-1529035954.8010113-22928023490467/source","state": "file","uid": 0}#节点安装libselinux-python后在进行发送测试[root@ansible ~]# ansible webB -m copy -a "src=/service/scripts/test.txt dest=/service/scripts/"webB | SUCCESS => { #发送成功"changed": true,"checksum": "972a1a11f19934401291cc99117ec614933374ce","dest": "/service/scripts/test.txt","gid": 0,"group": "root","md5sum": "5c9597f3c8245907ea71a89d9d39d08e","mode": "0644","owner": "root","secontext": "system_u:object_r:svc_svc_t:s0","size": 4,"src": "/root/.ansible/tmp/ansible-tmp-1529036146.1609693-94270890826089/source","state": "file","uid": 0}
6.3 copy模块拷贝文件夹
特别提示:
如果目标路径里有与我拷贝的文件同名文件的话,会直接覆盖目标路径下的文件
#拷贝/service/scripts/ 目录下所有内容到dest的路径下(注意两条命令的对比)[root@ansible ~]# ansible webA -m copy -a "src=/service/scripts/ dest=/service/scripts/"webA | SUCCESS => {"changed": true,"dest": "/service/scripts/","src": "/service/scripts/"}#拷贝/service/scripts目录本身及其内部的所有内容到dest的路径下(注意两条命令的对比)[root@ansible ~]# ansible webA -m copy -a "src=/service/scripts dest=/service/scripts/"webA | SUCCESS => {"changed": true,"dest": "/service/scripts/","src": "/service/scripts"}
6.4 copy模块自动备份
特别提示:
参数:backup=yes ===>意思是,如果目标路径下,有与我同名但不同内容的文件时,在覆盖前,对目标文件先进行备份。
[root@ansible ~]# ansible webB -m copy -a "src=/service/scripts/ dest=/service/scripts/ backup=yes"webB | SUCCESS => {"changed": true,"dest": "/service/scripts/","src": "/service/scripts/"}
6.5 copy模块指定用户和属主
[root@ansible ~]# ansible webA -m copy -a "src=/service/scripts/ dest=/service/scripts/ owner=nobody group=nobody mode=0600"webA | SUCCESS => {"changed": true,"dest": "/service/scripts/","src": "/service/scripts/"}
七,ansible的script模块批量运行脚本
ansible的script模块能够实现远程服务器批量运行本地的shell脚本。
#操作示例-->远程批量分发并自动部署nginx#所有被管理端需要挂载光盘,并创建本地yum配置文件[root@ansible scripts]# pwd/service/scripts[root@ansible scripts]# ls | xargs -n1auto_nginx.sh #自动安装nginx脚本fenfa.sh #批量分发脚本nginx-1.10.2.tar.gz #nginx源码包[root@ansible scripts]# cat auto_nginx.sh #nginx安装脚本#!/bin/sh#nginx install shell scriptstest -d /media/cdrom || mkdir -p /media/cdrommount /dev/sr0 /media/cdrom &>/dev/nullyum -y install gcc gcc-c++ make pcre pcre-devel zlib zlib-devel openssl openssl-devel &>/dev/nulltest -d /service/scripts || exit 3cd /service/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/nullmake &>/dev/nullmake install &>/dev/nullexit 0[root@ansible scripts]# cat fenfa.sh #源码包和安装脚本的批量分发脚本#!/bin/sh#批量分发脚本Group=$1ansible $Group -m copy -a "src=/service/scripts/ dest=/service/scripts/"ansible $Group -m script -a "/service/scripts/auto_nginx.sh"[root@ansible scripts]# sh fenfa.sh all #激活脚本
此脚本只是个演示示例,工作中需要写的尽量严谨一些。
八,ansible-playbook的初步使用
playbook的使用,playbook可以把ansible的模块进行组合
ln -s /usr/local/python/bin/ansible-playbook /usr/local/bin/
8.1 playbook的简单shell模块的使用
[root@ansible scripts]# cat test_shell.yaml #playbook的执行模板--- #开头三个小-开头- hosts: webBtasks:- name: testshell: echo "welcome to yunjisaun" >> /tmp/username- name: test2shell: 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:后边还是要有个空格,需要注意。
执行playbook配置文件
[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
8.2 playbook的简单copy模块的使用
[root@ansible scripts]# echo "welcom to yunjisuan" >> /tmp/test_copy[root@ansible scripts]# cat test_copy.yaml---- hosts: alltasks:- name: test copycopy: src=/tmp/copy_test dest=/tmp/[root@ansible scripts]# ansible-playbook /service/scripts/test_copy.yamlPLAY [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=0webB : ok=2 changed=1 unreachable=0 failed=0
8.3 playbook使用register输出命令运行结果
我们在用playbook进行ansible模块操作的时候,并没有命令的执行结果输出,默认被隐藏了。
我们可以通过register模块最加输出命令的执行结果
[root@ansible scripts]# cat test_register.yaml---- hosts: alltasks:- name: test registershell: echo "welcome to yunjisuan"register: print_result #将之前命令的输出结果保存在变量print_result里- debug: var=print_result #将变量的值作为debug输出出来。[root@ansible scripts]# ansible-playbook test_register.yamlPLAY [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=0webB : ok=3 changed=1 unreachable=0 failed=0
8.4 nginx配置下发并检测
[root@ansible scripts]# cat test_nginx_conf.yaml---- hosts: alltasks:- name: copy nginx.confcopy: src=/tmp/nginx.conf dest=/usr/local/nginx/conf/ backup=yes- name:shell: /usr/local/nginx/sbin/nginx -tregister: nginx_result- debug: var=nginx_result
九,playbook的自定义变量和内置变量
9.1 在Playbook中使用自定义变量
[root@localhost scripts]# cat test_vars.yaml---- hosts: allvars: #定义变量- 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=0webB : ok=3 changed=1 unreachable=0 failed=0#我们修改一下name这个变量再发送,就不会出警告了[root@localhost scripts]# cat test_vars.yaml---- hosts: allvars:- names: "yunjisuan"age: "3"tasks:- name: "{{ names }}"shell: echo "myname {{ names }},myage {{ age }}"register: var_result- debug: var=var_result
在使用自定义变量时,我们要特别注意不要和系统的内置保留变量同名,容易引发问题。
9.2 在playbook中使用ansible内置变量
我们可以使用ansible all -m setup | less查看ansible内置变量
[root@localhost scripts]# cat test_setupvars.yaml---- hosts: allgather_facts: True #使用ansible内置变量tasks:- name: setup varshell: 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.yamlPLAY [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=0webB : ok=3 changed=1 unreachable=0 failed=0
简单演示一下ansible内置变量的取用方法ansible all -m setup | less
[root@localhost scripts]# cat test_setupvars.yaml---- hosts: allgather_facts: Truetasks:- name: setup varshell: echo "ip {{ ansible_all_ipv4_addresses[0] }} cpu {{ ansible_processor_count }}" >> /tmp/test- name: setup var2shell: echo "time {{ ansible_date_time["date"] }}" >> /tmp/testregister: var_result- debug: var=var_result
十,Playbook下发可变配置文件
配置文件如果使用copy模块去下发的话,那配置都是一样的;
如果下发的配置文件里有可变的配置,需要用到template模块。
10.1 利用template模块下发可变的配置文件
[root@localhost scripts]# cat /tmp/testmy name is {{ myname }} #自定义变量my name is {{ ansible_all_ipv4_addresses[0] }} #系统变量[root@localhost scripts]# cat test_filevars.yaml---- hosts: allgather_facts: True #开启系统变量vars:- myname: "yunjisuan" #自定义变量tasks:- name: template testtemplate: src=/tmp/test dest=/root/test #使用template下发可变配置文件[root@localhost scripts]# ansible-playbook test_filevars.yaml
10.2 下发配置文件里面使用判断语法
[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: allgather_facts: True #开启系统内置变量vars:- PORT: 90 #自定义变量tasks:- name: jinja2 if testtemplate: src=/tmp/if.j2 dest=/root/test[root@localhost scripts]# ansible-playbook test_ifvars.yaml
如果我们将变量PORT值为空的话,就会是另外的结果
[root@localhost scripts]# cat test_ifvars.yaml---- hosts: allgather_facts: Truevars:- PORT: #置空tasks:- name: jinja2 if testtemplate: src=/tmp/if.j2 dest=/root/test[root@localhost scripts]# ansible-playbook test_ifvars.yaml
十一,Playbook的notify通知和下发nginx配置
#实战下发可执行动作的可变的nginx配置文件[root@localhost scripts]# head -1 /tmp/nginx.j2worker_processes {{ ansible_processor_count }}; #可变的参数[root@localhost scripts]# cat test_nginxvars.yaml---- hosts: allgather_facts: True #开启系统内置变量tasks:- name: nginx conftemplate: src=/tmp/nginx.j2 dest=/usr/local/nginx/conf/nginx.confnotify:- 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标准化Playbook
roles功能可以用来规范playbook的编写
12.1 创建所需要的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原型模组
12.2 roles中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└── vars7 directories, 2 files
12.3 执行简单的roles任务模型
#执行nginx入口配置文件[root@ansible myroles]# ansible-playbook nginx.yamlPLAY [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=0webB : 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: allgather_facts: Truetasks: #其实roles的本质就是将tasks任务单独写了。- name: check alived #并在入口文件里追加了roles去查找tasks配置文件路径ping:- name:shell: ls /register: ls_result- debug: var=ls_result
12.4 roles中vars自定义变量模组的使用
#创建自定义变量vars模组的配置文件[root@ansible myroles]# cat roles/nginx/vars/main.yaml---my_name: yunjisuanphone: 1800000000[root@ansible myroles]# cat roles/nginx/tasks/main.yaml---- name: check alivedping:- 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 #执行入口配置文件
12.5 使用copy,script模块的标准化
roles模型里使用copy,script模块,默认从roles/nginx/files这里面找
[root@ansible myroles]# cat roles/nginx/files/testwelcome to yunjisuan[root@ansible myroles]# cat roles/nginx/files/test.shecho "aaa" >> /tmp/test[root@ansible myroles]# chmod +x roles/nginx/files/test.sh[root@ansible myroles]# cat roles/nginx/tasks/main.yaml---- name: check alivedping:- 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
12.6 roles中template模块的使用
roles模型里使用template模块,默认从roles/nginx/template里面找
[root@ansible myroles]# cat roles/nginx/templates/test.j2myname 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 alivedping:- 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
12.7 roles中notify模块的使用
roles使用notify模块,默认从roles/nginx/handles里面找
[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 alivedping:- 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/test2notify: 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: webAgather_facts: Truetasks:- name:copy: src=/tmp/test dest=/root/ #这步造成目标改变才能出发notifynotify: start_nginxhandlers:- name: start_nginxshell: /usr/local/nginx/sbin/nginx[root@ansible myroles]# ansible-playbook /tmp/test.yamlPLAY [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.yamlPLAY [webA] ***************************************************************************************************TASK [Gathering Facts] ****************************************************************************************ok: [webA]TASK [copy] ***************************************************************************************************ok: [webA] #没有造成任务改变,未触发notify通知PLAY RECAP ****************************************************************************************************webA : ok=2 changed=0 unreachable=0 failed=0
ansible自动化的更多相关文章
- Ansible自动化运维工具-上
[Ansible特点] 1)Ansible与saltstack均是基于Python语言开发的 2)安装使用简单,基于不同插件和模块实现各种软件,平台,版本的管理以及支持虚拟容器多层级的部署 3)不需要 ...
- CentOS7系统 ansible自动化部署多台服务器部署
CentOS7系统 ansible自动化部署多台服务器部署 Ansible工作机制 从图中可以看出ansible分为以下几个部份: 1> Control Node:控制机器2> In ...
- ansible 自动化运维
Ansible 自动化运维 ansible安装epel #yum list all *ansible*#yum install *ansible*#yum info ansible#rpm -ql a ...
- ansible自动化工具安装和简单使用
ansible自动化工具安装和简单使用 1.安装 ansible依赖于Python 2.6或更高的版本.paramiko.PyYAML及Jinja2. 2.1 编译安装 解决依赖关系 # yum -y ...
- Jenkins +svn +maven +tomcat+ ansible 自动化批量部署
Jenkins +svn +maven +tomcat+ ansible 自动化批量部署 一.部署svn yum install subversion 先创建目录 mkdir /home/svn 创建 ...
- [k8s]kubespray(ansible)自动化安装k8s集群
kubespray(ansible)自动化安装k8s集群 https://github.com/kubernetes-incubator/kubespray https://kubernetes.io ...
- Jenkins+Gitlab+Ansible自动化部署(五)
Freestyle Job实现静态网站部署交付(接Jenkins+Gitlab+Ansible自动化部署(四)https://www.cnblogs.com/zd520pyx1314/p/102445 ...
- Jenkins+Gitlab+Ansible自动化部署(六)
Pipeline Job实现Nginix+MySQL+PHP+Wordpress实现自动化部署交付(Jenkins+Gitlab+Ansible自动化部署(五)https://www.cnblogs. ...
- Jenkins+Gitlab+Ansible自动化部署(三)
接Jenkins+Gitlab+Ansible自动化部署(一)https://www.cnblogs.com/zd520pyx1314/p/10210727.html 和(二)https://www. ...
- Jenkins+Gitlab+Ansible自动化部署(一)
首先准备实验环境 虚拟机 主机名 IP地址 服务 系统版本 内核版本 Vmware Workstation 14 gitlab.example.com 192.168.244.130 gitlab ...
随机推荐
- 一维信号频谱图仿真——matlab
程序1: %在MATLAB中是用连续信号在等时间间隔点的样值来近似地表示连续信号的,当采样时间间隔足够小时,这些离散的采样值就能较好地近似出连续信号,matlab中连续信号的显示实际上还是离散信号的显 ...
- 在已安装64位oracle的服务器安装32位客户端
应用场景:服务器操作系统是win2012 64位,原先安装了64位oracle12,后来系统增加导入excel的功能,网站必须启用32位兼容模式,这时候发现原有的页面打不开,提示: 试图加载格式不正确 ...
- 【java】之算法复杂度o(1), o(n), o(logn), o(nlogn)
在描述算法复杂度时,经常用到o(1), o(n), o(logn), o(nlogn)来表示对应算法的时间复杂度, 这里进行归纳一下它们代表的含义: 这是算法的时空复杂度的表示.不仅仅用于表示时间复杂 ...
- BeanUtils使用
1.BeanUtils.populate 可以把一个map中的属性拷贝到实体javaBean,例子: Student: package com.cy.model; import org.apache. ...
- Validation.Add();Excel
Irange = (Microsoft.Office.Interop.Excel.Range)worksheet.get_Range("I1", "I1").g ...
- Verilog风格
Verilog HDL编写原则: 可移植性强(多用宏定义:少用嵌入代码中的常数,即Magic Number:使用头文件): 必要的注释,代码易读: 模块间耦合尽可能低: 变量名与宏的命名规则: 变量名 ...
- db powerdesign CDM、LDM、PDM、OOM的区别
导读 在本篇文章中,你将会了解到PowerDesigner工具中的三种模型CDM,OOM,PDM的区别和联系. PowerDesigner 简称PD,是一种数据建模工具,适合于开发大型应用系统 ...
- 如何实现 C/C++ 与 Python 的通信?
属于混合编程的问题.较全面的介绍一下,不仅限于题主提出的问题.以下讨论中,Python指它的标准实现,即CPython(虽然不是很严格) 本文分4个部分 1. C/C++ 调用 Python (基础篇 ...
- (Python基础)字符编码与转码
ASCII(American Standard Code for Information Interchange,美国标准信息交换代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧 ...
- 团队项目需求分析——NABCD
N(Need)需求 经发现,很多人在理发时都要经过漫长的排队等待时间,这些时间也就因此白白浪费掉了,而且一些理发店也会因个别顾客不愿等待而损失客源.对此,我们设计出了这款小软件——理了么,一款专门为理 ...