一,工具与环境介绍

 

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

 
  1. #安装支持包
  2. [root@ansible ~]# yum -y install lrzsz vim net-tools gcc gcc-c++ ncurses ncurses-devel unzip zlib-devel zlib openssl-devel openssl
  3. #源码编译Python3.5
  4. [root@ansible Python-3.5.2]# tar xf Python-3.5.2.tgz -C /usr/src/
  5. [root@ansible Python-3.5.2]# cd /usr/src/Python-3.5.2/
  6. [root@ansible Python-3.5.2]# ./configure --prefix=/usr/local/python/
  7. [root@ansible Python-3.5.2]# make && make install
  8. [root@ansible Python-3.5.2]# ln -s /usr/local/python/bin/python3 /usr/bin/python3
  9. [root@ansible Python-3.5.2]# which python3
  10. /usr/bin/python3
  11. [root@ansible Python-3.5.2]# python3 -V
  12. Python 3.5.2
 

2.2 使用pip3安装ansible

 
  1. #安装ansible最新版本
  2. [root@ansible Python-3.5.2]# /usr/local/python/bin/pip3 install ansible
  3. #静心等待ansible安装完毕后
  4. [root@ansible python]# ln -s /usr/local/python/bin/ansible /usr/local/bin/
  5. [root@ansible python]# which ansible
  6. /usr/local/bin/ansible
  7. [root@ansible python]# ansible --version
  8. ansible 2.5.4
  9. config file = None
  10. configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  11. ansible python module location = /usr/local/python/lib/python3.5/site-packages/ansible
  12. executable location = /usr/local/bin/ansible
  13. python 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
 
  1. #生成密钥对
  2. [root@ansible python]# ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ""
  3. #分发密钥
  4. [root@ansible python]# ssh-copy-id -i ~/.ssh/id_rsa.pub "-o StrictHostKeyChecking=no" 192.168.200.132
  5. #进行免密码登陆测试
  6. [root@ansible python]# ssh 192.168.200.132
  7. Last login: Wed Jun 13 11:01:10 2018 from 192.168.200.137
  8. [root@webA ~]# hostname -I
  9. 192.168.200.132
  10. [root@webA ~]# exit
  11. logout
  12. Connection to 192.168.200.132 closed.
  13. [root@ansible python]# hostname -I
  14. 192.168.200.137
 

四,ansible的简单配置和ping模块

 

4.1 ansible的配置文件

通过pip安装的ansible是没有配置文件的。我们需要创建一个

 
  1. [root@ansible python]# mkdir -p /etc/ansible
  2. [root@ansible python]# vim /etc/ansible/hosts
  3. [root@ansible python]# cat /etc/ansible/hosts #ansible主机管理配置文件
  4. [nginx] #被管理的主机组名称
  5. webA ansible_ssh_host=192.168.200.132 ansible_ssh_port=22 ansible_ssh_user=root #第一台主机
  6. webB ansible_ssh_host=192.168.200.138 ansible_ssh_port=22 ansible_ssh_user=root ansible_ssh_pass=666666 #第二台主机
  7. 特别提示:
  8. WebA ===> 主机名
  9. ansible_ssh_host ===>主机IP
  10. ansible_ssh_port ===>ssh的默认端口
  11. ansible_ssh_user ===>ssh的用户名
  12. ansible_ssh_pass ===>ssh的用户的连接密码

如果我们已经设置了ssh免密钥了。那么就不需要写密码了。例如:webA
我们要是没有设置免密钥,那么就需要安装sshpass工具,并在/etc/ansible/hosts文件里写上主机的连接密码。例如webB

 
  1. #下载epel源安装sshpass
  2. [root@ansible python]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
  3. [root@ansible python]# yum -y install sshpass
  4. [root@ansible python]# which sshpass
  5. /usr/bin/sshpass
 

4.2 进行ansible远程执行命令测试

语法:

ansible chensiqi -m command -a 'uptime'
ansible 主机组 -m ansible内置功能模块名 -a 命令

进行命令测试:

 
  1. #进行ping模块的连接测试
  2. [root@ansible python]# ansible nginx -m ping
  3. webB | FAILED! => { #我们发现webB还是没链接成功,这是因为本机的known_hosts文件还没有记录对方主机的信息。
  4. "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."
  5. }
  6. webA | SUCCESS => { #webA成功
  7. "changed": false,
  8. "ping": "pong"
  9. }

想要解决known_hosts的问题,只需要修改ssh的配置文件/etc/ssh/ssh_config即可

 
  1. #修改ssh配置文件
  2. [root@ansible .ssh]# sed -n '35p' /etc/ssh/ssh_config
  3. # StrictHostKeyChecking ask
  4. [root@ansible .ssh]# vim /etc/ssh/ssh_config
  5. [root@ansible .ssh]# sed -n '35p' /etc/ssh/ssh_config
  6. StrictHostKeyChecking no #去掉注释,修改成这样
  7. #重启ssh服务
  8. [root@ansible .ssh]# systemctl reload sshd.service
  9. #再次进行ansible连接测试
  10. [root@ansible .ssh]# ansible nginx -m ping
  11. webA | SUCCESS => {
  12. "changed": false,
  13. "ping": "pong"
  14. }
  15. webB | SUCCESS => {
  16. "changed": false,
  17. "ping": "pong"
  18. }
 

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,注意!前需要加转意符号\
 
  1. #操作测试
  2. [root@ansible .ssh]# ansible webA -m ping
  3. webA | SUCCESS => {
  4. "changed": false,
  5. "ping": "pong"
  6. }
  7. [root@ansible .ssh]# ansible all -m ping
  8. webA | SUCCESS => {
  9. "changed": false,
  10. "ping": "pong"
  11. }
  12. webB | SUCCESS => {
  13. "changed": false,
  14. "ping": "pong"
  15. }
  16. [root@ansible .ssh]# ansible webA:webB -m ping
  17. webA | SUCCESS => {
  18. "changed": false,
  19. "ping": "pong"
  20. }
  21. webB | SUCCESS => {
  22. "changed": false,
  23. "ping": "pong"
  24. }
  25. [root@ansible .ssh]# ansible all:\!webA -m ping
  26. webB | SUCCESS => {
  27. "changed": false,
  28. "ping": "pong"
  29. }
  30. [root@ansible .ssh]# ansible webA:webB -m command -a 'uptime'
  31. webA | SUCCESS | rc=0 >>
  32. 12:29:05 up 2:43, 3 users, load average: 0.00, 0.01, 0.05
  33. webB | SUCCESS | rc=0 >>
  34. 12:29:05 up 1:03, 2 users, load average: 0.01, 0.02, 0.02
 

五,ansible的三个命令模块

 

5.1 ansible模块command(不支持管道,不建议使用)

 
  1. #command支持直接回显命令的执行结果
  2. [root@ansible ~]# ansible all -m command -a "pwd"
  3. webA | SUCCESS | rc=0 >>
  4. /root
  5. webB | SUCCESS | rc=0 >>
  6. /root
  7. #command模块不支持管道符操作
  8. [root@ansible ~]# ansible all -m command -a "echo test | grep t"
  9. webA | SUCCESS | rc=0 >>
  10. test | grep t
  11. webB | SUCCESS | rc=0 >>
  12. test | grep t
  13. #command模块不支持重定向操作
  14. [root@ansible ~]# ansible all -m command -a "echo bb >> /tmp/testansible"
  15. webA | SUCCESS | rc=0 >>
  16. bb >> /tmp/testansible
  17. webB | SUCCESS | rc=0 >>
  18. bb >> /tmp/testansible
 

5.2 ansible模块shell(支持管道,支持重定向)

 
  1. #shell模块支持管道符
  2. [root@ansible ~]# ansible all -m shell -a "echo testansible | grep a"
  3. webA | SUCCESS | rc=0 >>
  4. testansible
  5. webB | SUCCESS | rc=0 >>
  6. testansible
  7. #shell支持重定向
  8. [root@ansible ~]# ansible all -m shell -a "echo bb >> /tmp/testansible"
  9. webA | SUCCESS | rc=0 >>
  10. webB | SUCCESS | rc=0 >>
  11. #如果遇到特殊符号需要加入\转义,这样子ansible才能正常运行
  12. [root@ansible ~]# ansible all -m shell -a "cat /etc/passwd | awk -F":" '{print \$1}'"
  13. webB | SUCCESS | rc=0 >>
  14. root
  15. bin
  16. daemon
  17. adm
  18. lp
  19. sync
  20. shutdown
  21. halt
  22. mail
  23. operator
  24. games
  25. ftp
  26. nobody
  27. systemd-bus-proxy
  28. systemd-network
  29. dbus
  30. polkitd
  31. tss
  32. postfix
  33. sshd
  34. chrony
  35. webA | SUCCESS | rc=0 >>
  36. root
  37. bin
  38. daemon
  39. adm
  40. lp
  41. sync
  42. shutdown
  43. halt
  44. mail
  45. operator
  46. games
  47. ftp
  48. nobody
  49. systemd-bus-proxy
  50. systemd-network
  51. dbus
  52. polkitd
  53. tss
  54. postfix
  55. sshd
  56. chrony
 

5.3 ansible模块raw,最原始的方式运行命令(不依赖python,仅通过ssh实现)

 
  1. #清除yum缓存
  2. [root@ansible ~]# ansible all -m raw -a "yum -y clean all"
  3. webB | SUCCESS | rc=0 >>
  4. Loaded plugins: fastestmirror
  5. Cleaning repos: c7-media
  6. Cleaning up everything
  7. Shared connection to 192.168.200.138 closed.
  8. webA | SUCCESS | rc=0 >>
  9. Loaded plugins: fastestmirror
  10. Cleaning repos: c7-media epel
  11. Cleaning up everything
  12. Cleaning up list of fastest mirrors
  13. Shared connection to 192.168.200.132 closed.
  14. #建立yum缓存
  15. [root@ansible ~]# ansible all -m raw -a "yum makecache"
  16. webA | SUCCESS | rc=0 >>
  17. Loaded plugins: fastestmirror
  18. c7-media | 3.6 kB 00:00
  19. Loading mirror speeds from cached hostfile
  20. * c7-media:
  21. Metadata Cache Created
  22. Shared connection to 192.168.200.132 closed.
  23. webB | SUCCESS | rc=0 >>
  24. Loaded plugins: fastestmirror
  25. c7-media | 3.6 kB 00:00
  26. Loading mirror speeds from cached hostfile
  27. * c7-media:
  28. Metadata Cache Created
  29. Shared connection to 192.168.200.138 closed.
  30. #yum装nmap包
  31. 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=目标路径位置

 
  1. [root@ansible ~]# ansible all -m copy -a "src=/service/scripts/test.txt dest=/service/scripts/"
  2. webB | FAILED! => { #节点未安装libselinux-python
  3. "changed": false,
  4. "checksum": "972a1a11f19934401291cc99117ec614933374ce",
  5. "msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"
  6. }
  7. webA | SUCCESS => {
  8. "changed": true,
  9. "checksum": "972a1a11f19934401291cc99117ec614933374ce",
  10. "dest": "/service/scripts/test.txt",
  11. "gid": 0,
  12. "group": "root",
  13. "md5sum": "5c9597f3c8245907ea71a89d9d39d08e",
  14. "mode": "0644",
  15. "owner": "root",
  16. "secontext": "system_u:object_r:svc_svc_t:s0",
  17. "size": 4,
  18. "src": "/root/.ansible/tmp/ansible-tmp-1529035954.8010113-22928023490467/source",
  19. "state": "file",
  20. "uid": 0
  21. }
  22. #节点安装libselinux-python后在进行发送测试
  23. [root@ansible ~]# ansible webB -m copy -a "src=/service/scripts/test.txt dest=/service/scripts/"
  24. webB | SUCCESS => { #发送成功
  25. "changed": true,
  26. "checksum": "972a1a11f19934401291cc99117ec614933374ce",
  27. "dest": "/service/scripts/test.txt",
  28. "gid": 0,
  29. "group": "root",
  30. "md5sum": "5c9597f3c8245907ea71a89d9d39d08e",
  31. "mode": "0644",
  32. "owner": "root",
  33. "secontext": "system_u:object_r:svc_svc_t:s0",
  34. "size": 4,
  35. "src": "/root/.ansible/tmp/ansible-tmp-1529036146.1609693-94270890826089/source",
  36. "state": "file",
  37. "uid": 0
  38. }
 

6.3 copy模块拷贝文件夹

特别提示:
如果目标路径里有与我拷贝的文件同名文件的话,会直接覆盖目标路径下的文件

 
  1. #拷贝/service/scripts/ 目录下所有内容到dest的路径下(注意两条命令的对比)
  2. [root@ansible ~]# ansible webA -m copy -a "src=/service/scripts/ dest=/service/scripts/"
  3. webA | SUCCESS => {
  4. "changed": true,
  5. "dest": "/service/scripts/",
  6. "src": "/service/scripts/"
  7. }
  8. #拷贝/service/scripts目录本身及其内部的所有内容到dest的路径下(注意两条命令的对比)
  9. [root@ansible ~]# ansible webA -m copy -a "src=/service/scripts dest=/service/scripts/"
  10. webA | SUCCESS => {
  11. "changed": true,
  12. "dest": "/service/scripts/",
  13. "src": "/service/scripts"
  14. }
 

6.4 copy模块自动备份

特别提示:
参数:backup=yes ===>意思是,如果目标路径下,有与我同名但不同内容的文件时,在覆盖前,对目标文件先进行备份。

 
  1. [root@ansible ~]# ansible webB -m copy -a "src=/service/scripts/ dest=/service/scripts/ backup=yes"
  2. webB | SUCCESS => {
  3. "changed": true,
  4. "dest": "/service/scripts/",
  5. "src": "/service/scripts/"
  6. }
 

6.5 copy模块指定用户和属主

 
  1. [root@ansible ~]# ansible webA -m copy -a "src=/service/scripts/ dest=/service/scripts/ owner=nobody group=nobody mode=0600"
  2. webA | SUCCESS => {
  3. "changed": true,
  4. "dest": "/service/scripts/",
  5. "src": "/service/scripts/"
  6. }
 

七,ansible的script模块批量运行脚本

ansible的script模块能够实现远程服务器批量运行本地的shell脚本。

 
  1. #操作示例-->远程批量分发并自动部署nginx
  2. #所有被管理端需要挂载光盘,并创建本地yum配置文件
  3. [root@ansible scripts]# pwd
  4. /service/scripts
  5. [root@ansible scripts]# ls | xargs -n1
  6. auto_nginx.sh #自动安装nginx脚本
  7. fenfa.sh #批量分发脚本
  8. nginx-1.10.2.tar.gz #nginx源码包
  9. [root@ansible scripts]# cat auto_nginx.sh #nginx安装脚本
  10. #!/bin/sh
  11. #nginx install shell scripts
  12. test -d /media/cdrom || mkdir -p /media/cdrom
  13. mount /dev/sr0 /media/cdrom &>/dev/null
  14. yum -y install gcc gcc-c++ make pcre pcre-devel zlib zlib-devel openssl openssl-devel &>/dev/null
  15. test -d /service/scripts || exit 3
  16. cd /service/scripts/
  17. tar xf nginx-1.10.2.tar.gz -C /usr/src/
  18. cd /usr/src/nginx-1.10.2/
  19. ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module &>/dev/null
  20. make &>/dev/null
  21. make install &>/dev/null
  22. exit 0
  23. [root@ansible scripts]# cat fenfa.sh #源码包和安装脚本的批量分发脚本
  24. #!/bin/sh
  25. #批量分发脚本
  26. Group=$1
  27. ansible $Group -m copy -a "src=/service/scripts/ dest=/service/scripts/"
  28. ansible $Group -m script -a "/service/scripts/auto_nginx.sh"
  29. [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模块的使用

 
  1. [root@ansible scripts]# cat test_shell.yaml #playbook的执行模板
  2. --- #开头三个小-开头
  3. - hosts: webB
  4. tasks:
  5. - name: test
  6. shell: echo "welcome to yunjisaun" >> /tmp/username
  7. - name: test2
  8. shell: echo "welcome to yunjisuan" >> /tmp/username
  9. 模板说明:
  10. --- #开头必须有三个小-,顶格写
  11. - hosts: #正文配置代码的第一级,必须有两个空格(-占一个空格位)
  12. - host: webB #webB是host参数的值,值和hosts:之间要有一个空格
  13. tasks: #tasks:表示接下来要执行的具体任务
  14. - name: #相对于tasks再多缩进两个格(-占一个空格位),表示属于tasks的下一级
  15. - name: test #test只是要执行的具体命令的名字可以随便写。name:后还是有一个空格要注意
  16. shell: #表示调用shell模块执行命令相对于tasks仍旧要多缩进两个空格
  17. shell: echo "xxx" >> xxx #shell:后边还是要有个空格,需要注意。

执行playbook配置文件

 
  1. [root@ansible scripts]# ansible-playbook test_shell.yaml #执行playbook配置文件
  2. PLAY [webB] ********************************************************************************************************
  3. TASK [Gathering Facts] *********************************************************************************************
  4. ok: [webB]
  5. TASK [test] ********************************************************************************************************
  6. changed: [webB]
  7. TASK [test2] *******************************************************************************************************
  8. changed: [webB]
  9. PLAY RECAP *********************************************************************************************************
  10. webB : ok=3 changed=2 unreachable=0 failed=0
 

8.2 playbook的简单copy模块的使用

 
  1. [root@ansible scripts]# echo "welcom to yunjisuan" >> /tmp/test_copy
  2. [root@ansible scripts]# cat test_copy.yaml
  3. ---
  4. - hosts: all
  5. tasks:
  6. - name: test copy
  7. copy: src=/tmp/copy_test dest=/tmp/
  8. [root@ansible scripts]# ansible-playbook /service/scripts/test_copy.yaml
  9. PLAY [all] *********************************************************************************************************
  10. TASK [Gathering Facts] *********************************************************************************************
  11. ok: [webA]
  12. ok: [webB]
  13. TASK [test copy] ***************************************************************************************************
  14. changed: [webA]
  15. changed: [webB]
  16. PLAY RECAP *********************************************************************************************************
  17. webA : ok=2 changed=1 unreachable=0 failed=0
  18. webB : ok=2 changed=1 unreachable=0 failed=0
 

8.3 playbook使用register输出命令运行结果

我们在用playbook进行ansible模块操作的时候,并没有命令的执行结果输出,默认被隐藏了。
我们可以通过register模块最加输出命令的执行结果

 
  1. [root@ansible scripts]# cat test_register.yaml
  2. ---
  3. - hosts: all
  4. tasks:
  5. - name: test register
  6. shell: echo "welcome to yunjisuan"
  7. register: print_result #将之前命令的输出结果保存在变量print_result里
  8. - debug: var=print_result #将变量的值作为debug输出出来。
  9. [root@ansible scripts]# ansible-playbook test_register.yaml
  10. PLAY [all] *********************************************************************************************************
  11. TASK [Gathering Facts] *********************************************************************************************
  12. ok: [webA]
  13. ok: [webB]
  14. TASK [test register] ***********************************************************************************************
  15. changed: [webA]
  16. changed: [webB]
  17. TASK [debug] *******************************************************************************************************
  18. ok: [webA] => { #命令的执行结果有输出了
  19. "print_result": {
  20. "changed": true,
  21. "cmd": "echo \"welcome to yunjisuan\"",
  22. "delta": "0:00:00.002269",
  23. "end": "2018-06-15 10:28:14.693883",
  24. "failed": false,
  25. "rc": 0,
  26. "start": "2018-06-15 10:28:14.691614",
  27. "stderr": "",
  28. "stderr_lines": [],
  29. "stdout": "welcome to yunjisuan",
  30. "stdout_lines": [
  31. "welcome to yunjisuan"
  32. ]
  33. }
  34. }
  35. ok: [webB] => {
  36. "print_result": {
  37. "changed": true,
  38. "cmd": "echo \"welcome to yunjisuan\"",
  39. "delta": "0:00:00.002633",
  40. "end": "2018-06-15 10:28:14.710242",
  41. "failed": false,
  42. "rc": 0,
  43. "start": "2018-06-15 10:28:14.707609",
  44. "stderr": "",
  45. "stderr_lines": [],
  46. "stdout": "welcome to yunjisuan",
  47. "stdout_lines": [
  48. "welcome to yunjisuan"
  49. ]
  50. }
  51. }
  52. PLAY RECAP *********************************************************************************************************
  53. webA : ok=3 changed=1 unreachable=0 failed=0
  54. webB : ok=3 changed=1 unreachable=0 failed=0
 

8.4 nginx配置下发并检测

 
  1. [root@ansible scripts]# cat test_nginx_conf.yaml
  2. ---
  3. - hosts: all
  4. tasks:
  5. - name: copy nginx.conf
  6. copy: src=/tmp/nginx.conf dest=/usr/local/nginx/conf/ backup=yes
  7. - name:
  8. shell: /usr/local/nginx/sbin/nginx -t
  9. register: nginx_result
  10. - debug: var=nginx_result
 

九,playbook的自定义变量和内置变量

 

9.1 在Playbook中使用自定义变量

 
  1. [root@localhost scripts]# cat test_vars.yaml
  2. ---
  3. - hosts: all
  4. vars: #定义变量
  5. - name: "yunjisuan" #第一个name变量
  6. age: "3" #第二个age变量
  7. tasks:
  8. - name: "{{ name }}" #{{}}两对大括号引用变量,变量名两头空格
  9. shell: echo "myname {{ name }},myage {{ age }}"
  10. register: var_result
  11. - debug: var=var_result
  12. 特别提示:
  13. 引用变量需要在双引号中引用。
  14. [root@localhost scripts]# ansible-playbook /service/scripts/test_vars.yaml
  15. [WARNING]: Found variable using reserved name: name #这里提示,name是一个保留的内置变量,我们在自定义时不能用
  16. PLAY [all] *********************************************************************************************************
  17. TASK [Gathering Facts] *********************************************************************************************
  18. ok: [webA]
  19. ok: [webB]
  20. TASK [yunjisuan] ***************************************************************************************************
  21. changed: [webA]
  22. changed: [webB]
  23. TASK [debug] *******************************************************************************************************
  24. ok: [webA] => {
  25. "var_result": {
  26. "changed": true,
  27. "cmd": "echo \"myname yunjisuan,myage 3\"",
  28. "delta": "0:00:00.002320",
  29. "end": "2018-06-19 10:45:16.175728",
  30. "failed": false,
  31. "rc": 0,
  32. "start": "2018-06-19 10:45:16.173408",
  33. "stderr": "",
  34. "stderr_lines": [],
  35. "stdout": "myname yunjisuan,myage 3",
  36. "stdout_lines": [
  37. "myname yunjisuan,myage 3"
  38. ]
  39. }
  40. }
  41. ok: [webB] => {
  42. "var_result": {
  43. "changed": true,
  44. "cmd": "echo \"myname yunjisuan,myage 3\"",
  45. "delta": "0:00:00.002518",
  46. "end": "2018-06-19 10:45:10.552331",
  47. "failed": false,
  48. "rc": 0,
  49. "start": "2018-06-19 10:45:10.549813",
  50. "stderr": "",
  51. "stderr_lines": [],
  52. "stdout": "myname yunjisuan,myage 3",
  53. "stdout_lines": [
  54. "myname yunjisuan,myage 3"
  55. ]
  56. }
  57. }
  58. PLAY RECAP *********************************************************************************************************
  59. webA : ok=3 changed=1 unreachable=0 failed=0
  60. webB : ok=3 changed=1 unreachable=0 failed=0
  61. #我们修改一下name这个变量再发送,就不会出警告了
  62. [root@localhost scripts]# cat test_vars.yaml
  63. ---
  64. - hosts: all
  65. vars:
  66. - names: "yunjisuan"
  67. age: "3"
  68. tasks:
  69. - name: "{{ names }}"
  70. shell: echo "myname {{ names }},myage {{ age }}"
  71. register: var_result
  72. - debug: var=var_result

在使用自定义变量时,我们要特别注意不要和系统的内置保留变量同名,容易引发问题。

 

9.2 在playbook中使用ansible内置变量

我们可以使用ansible all -m setup | less查看ansible内置变量

 
  1. [root@localhost scripts]# cat test_setupvars.yaml
  2. ---
  3. - hosts: all
  4. gather_facts: True #使用ansible内置变量
  5. tasks:
  6. - name: setup var
  7. shell: echo "ip {{ ansible_all_ipv4_addresses[0] }} cpu {{ ansible_processor_count }}"
  8. register: var_result
  9. - debug: var=var_result
  10. [root@localhost scripts]#
  11. [root@localhost scripts]# ansible-playbook test_setupvars.yaml
  12. PLAY [all] *********************************************************************************************************
  13. TASK [Gathering Facts] *********************************************************************************************
  14. ok: [webA]
  15. ok: [webB]
  16. TASK [setup var] ***************************************************************************************************
  17. changed: [webA]
  18. changed: [webB]
  19. TASK [debug] *******************************************************************************************************
  20. ok: [webA] => {
  21. "var_result": {
  22. "changed": true,
  23. "cmd": "echo \"ip 192.168.200.132 cpu 1\"",
  24. "delta": "0:00:00.002408",
  25. "end": "2018-06-19 11:32:44.540658",
  26. "failed": false,
  27. "rc": 0,
  28. "start": "2018-06-19 11:32:44.538250",
  29. "stderr": "",
  30. "stderr_lines": [],
  31. "stdout": "ip 192.168.200.132 cpu 1",
  32. "stdout_lines": [
  33. "ip 192.168.200.132 cpu 1"
  34. ]
  35. }
  36. }
  37. ok: [webB] => {
  38. "var_result": {
  39. "changed": true,
  40. "cmd": "echo \"ip 192.168.200.138 cpu 1\"",
  41. "delta": "0:00:00.002102",
  42. "end": "2018-06-19 11:32:44.526875",
  43. "failed": false,
  44. "rc": 0,
  45. "start": "2018-06-19 11:32:44.524773",
  46. "stderr": "",
  47. "stderr_lines": [],
  48. "stdout": "ip 192.168.200.138 cpu 1",
  49. "stdout_lines": [
  50. "ip 192.168.200.138 cpu 1"
  51. ]
  52. }
  53. }
  54. PLAY RECAP *********************************************************************************************************
  55. webA : ok=3 changed=1 unreachable=0 failed=0
  56. webB : ok=3 changed=1 unreachable=0 failed=0

简单演示一下ansible内置变量的取用方法ansible all -m setup | less

 
  1. [root@localhost scripts]# cat test_setupvars.yaml
  2. ---
  3. - hosts: all
  4. gather_facts: True
  5. tasks:
  6. - name: setup var
  7. shell: echo "ip {{ ansible_all_ipv4_addresses[0] }} cpu {{ ansible_processor_count }}" >> /tmp/test
  8. - name: setup var2
  9. shell: echo "time {{ ansible_date_time["date"] }}" >> /tmp/test
  10. register: var_result
  11. - debug: var=var_result
 

十,Playbook下发可变配置文件

配置文件如果使用copy模块去下发的话,那配置都是一样的;
如果下发的配置文件里有可变的配置,需要用到template模块。

 

10.1 利用template模块下发可变的配置文件

 
  1. [root@localhost scripts]# cat /tmp/test
  2. my name is {{ myname }} #自定义变量
  3. my name is {{ ansible_all_ipv4_addresses[0] }} #系统变量
  4. [root@localhost scripts]# cat test_filevars.yaml
  5. ---
  6. - hosts: all
  7. gather_facts: True #开启系统变量
  8. vars:
  9. - myname: "yunjisuan" #自定义变量
  10. tasks:
  11. - name: template test
  12. template: src=/tmp/test dest=/root/test #使用template下发可变配置文件
  13. [root@localhost scripts]# ansible-playbook test_filevars.yaml
 

10.2 下发配置文件里面使用判断语法

 
  1. [root@localhost scripts]# cat /tmp/if.j2
  2. {% if PORT %} #if PORT存在
  3. ip=0.0.0.0:{{ PORT }}
  4. {% else %} #否则的话
  5. ip=0.0.0.0:80
  6. {% endif %} #结尾
  7. [root@localhost scripts]# cat test_ifvars.yaml
  8. ---
  9. - hosts: all
  10. gather_facts: True #开启系统内置变量
  11. vars:
  12. - PORT: 90 #自定义变量
  13. tasks:
  14. - name: jinja2 if test
  15. template: src=/tmp/if.j2 dest=/root/test
  16. [root@localhost scripts]# ansible-playbook test_ifvars.yaml

如果我们将变量PORT值为空的话,就会是另外的结果

 
  1. [root@localhost scripts]# cat test_ifvars.yaml
  2. ---
  3. - hosts: all
  4. gather_facts: True
  5. vars:
  6. - PORT: #置空
  7. tasks:
  8. - name: jinja2 if test
  9. template: src=/tmp/if.j2 dest=/root/test
  10. [root@localhost scripts]# ansible-playbook test_ifvars.yaml
 

十一,Playbook的notify通知和下发nginx配置

 
    1. #实战下发可执行动作的可变的nginx配置文件
    2. [root@localhost scripts]# head -1 /tmp/nginx.j2
    3. worker_processes {{ ansible_processor_count }}; #可变的参数
    4. [root@localhost scripts]# cat test_nginxvars.yaml
    5. ---
    6. - hosts: all
    7. gather_facts: True #开启系统内置变量
    8. tasks:
    9. - name: nginx conf
    10. template: src=/tmp/nginx.j2 dest=/usr/local/nginx/conf/nginx.conf
    11. notify:
    12. - reload nginx #下发通知给handlers模块执行名字叫做reload nginx的动作
    13. handlers: #定义动作
    14. - name: reload nginx #动作的名字
    15. shell: /usr/local/nginx/sbin/nginx -s reload
    16. [root@localhost scripts]# ansible-playbook test_nginxvars.yaml

十二,使用roles标准化Playbook

roles功能可以用来规范playbook的编写

 

12.1 创建所需要的roles原型目录结构

 
  1. #创建roles基本原型的目录结构
  2. [root@ansible myroles]# tree /myroles/
  3. /myroles/
  4. ├── nginx.yaml #入口触发配置文件
  5. └── roles #playbook的原型配置目录
  6. └── nginx #nginx相关模组配置目录
  7. ├── files #copy模块和script模块的参数src默认会从这个文件夹查找
  8. ├── handlers #用来存放notify的
  9. ├── tasks #用来存放ansible模块任务的
  10. ├── templates #用来存放j2的
  11. └── vars #用来存放变量的
  12. 7 directories, 1 file
  13. #入口触发配置文件
  14. [root@ansible myroles]# cat /myroles/nginx.yaml
  15. ---
  16. - hosts: all #执行的主机范围
  17. gather_facts: True #开启系统内置变量
  18. roles: #启用roles原型配置
  19. - nginx #执行nginx原型模组
 

12.2 roles中tasks任务编排模组的使用

 
  1. #在nginx模组添加tasks任务配置文件
  2. [root@ansible myroles]# cat roles/nginx/tasks/main.yaml
  3. ---
  4. - name: check alived #任务1的名字
  5. ping: #执行ping模块
  6. - name: #任务2的名字
  7. shell: ls / #执行shell模块
  8. register: ls_result #将执行结果保存给变量
  9. - debug: var=ls_result #变量的值赋值给debug进行输出
  10. #完成后的目录结构如下所示
  11. [root@ansible myroles]# tree /myroles/
  12. /myroles/
  13. ├── nginx.yaml #nginx模组入口配置文件
  14. └── roles
  15. └── nginx #nginx原型模组目录
  16. ├── files
  17. ├── handlers
  18. ├── tasks
  19. │   └── main.yaml #nginx模组的tasks任务配置文件
  20. ├── templates
  21. └── vars
  22. 7 directories, 2 files
 

12.3 执行简单的roles任务模型

 
  1. #执行nginx入口配置文件
  2. [root@ansible myroles]# ansible-playbook nginx.yaml
  3. PLAY [all] ****************************************************************************************************
  4. TASK [Gathering Facts] ****************************************************************************************
  5. ok: [webA]
  6. ok: [webB]
  7. TASK [nginx : check alived] ***********************************************************************************
  8. ok: [webA]
  9. ok: [webB]
  10. TASK [nginx : shell] ******************************************************************************************
  11. changed: [webA]
  12. changed: [webB]
  13. TASK [nginx : debug] ******************************************************************************************
  14. ok: [webA] => {
  15. "ls_result": {
  16. "changed": true,
  17. "cmd": "ls /",
  18. "delta": "0:00:00.002805",
  19. "end": "2018-06-21 11:52:29.343592",
  20. "failed": false,
  21. "rc": 0,
  22. "start": "2018-06-21 11:52:29.340787",
  23. "stderr": "",
  24. "stderr_lines": [],
  25. "stdout": "bin\nboot\ndev\netc\nhome\nlib\nlib64\nmedia\nmnt\nopt\nproc\nroo\nroot\nrun\nsbin\nservice\nsrv\nsys\ntmp\nusr\nvar",
  26. "stdout_lines": [
  27. "bin",
  28. "boot",
  29. "dev",
  30. "etc",
  31. "home",
  32. "lib",
  33. "lib64",
  34. "media",
  35. "mnt",
  36. "opt",
  37. "proc",
  38. "roo",
  39. "root",
  40. "run",
  41. "sbin",
  42. "service",
  43. "srv",
  44. "sys",
  45. "tmp",
  46. "usr",
  47. "var"
  48. ]
  49. }
  50. }
  51. ok: [webB] => {
  52. "ls_result": {
  53. "changed": true,
  54. "cmd": "ls /",
  55. "delta": "0:00:00.002708",
  56. "end": "2018-06-21 11:52:29.359754",
  57. "failed": false,
  58. "rc": 0,
  59. "start": "2018-06-21 11:52:29.357046",
  60. "stderr": "",
  61. "stderr_lines": [],
  62. "stdout": "bin\nboot\ndev\netc\nhome\nlib\nlib64\nmedia\nmnt\nopt\nproc\nroo\nroot\nrun\nsbin\nservice\nsrv\nsys\ntmp\nusr\nvar",
  63. "stdout_lines": [
  64. "bin",
  65. "boot",
  66. "dev",
  67. "etc",
  68. "home",
  69. "lib",
  70. "lib64",
  71. "media",
  72. "mnt",
  73. "opt",
  74. "proc",
  75. "roo",
  76. "root",
  77. "run",
  78. "sbin",
  79. "service",
  80. "srv",
  81. "sys",
  82. "tmp",
  83. "usr",
  84. "var"
  85. ]
  86. }
  87. }
  88. PLAY RECAP ****************************************************************************************************
  89. webA : ok=4 changed=1 unreachable=0 failed=0
  90. webB : ok=4 changed=1 unreachable=0 failed=0
  • ansible-playbook执行入口配置文件nginx.yaml后,它会自动在roles目录下查找nginx目录并进入后查找tasks任务目录并执行main.yaml的任务配置文件。
  • 其实,这个roles的操作等效于以下配置
 
  1. #本配置和之前的roles配置等效
  2. [root@ansible myroles]# cat /service/scripts/test.yaml
  3. ---
  4. - hosts: all
  5. gather_facts: True
  6. tasks: #其实roles的本质就是将tasks任务单独写了。
  7. - name: check alived #并在入口文件里追加了roles去查找tasks配置文件路径
  8. ping:
  9. - name:
  10. shell: ls /
  11. register: ls_result
  12. - debug: var=ls_result
 

12.4 roles中vars自定义变量模组的使用

 
  1. #创建自定义变量vars模组的配置文件
  2. [root@ansible myroles]# cat roles/nginx/vars/main.yaml
  3. ---
  4. my_name: yunjisuan
  5. phone: 1800000000
  6. [root@ansible myroles]# cat roles/nginx/tasks/main.yaml
  7. ---
  8. - name: check alived
  9. ping:
  10. - name:
  11. shell: ls /
  12. register: ls_result
  13. - debug: var=ls_result
  14. - name: #添加对变量引用的任务编排
  15. shell: echo my phone is {{ phone }}
  16. register: echo_result
  17. - debug: var=echo_result
  18. [root@ansible myroles]# ansible-playbook nginx.yaml #执行入口配置文件
 

12.5 使用copy,script模块的标准化

roles模型里使用copy,script模块,默认从roles/nginx/files这里面找

 
  1. [root@ansible myroles]# cat roles/nginx/files/test
  2. welcome to yunjisuan
  3. [root@ansible myroles]# cat roles/nginx/files/test.sh
  4. echo "aaa" >> /tmp/test
  5. [root@ansible myroles]# chmod +x roles/nginx/files/test.sh
  6. [root@ansible myroles]# cat roles/nginx/tasks/main.yaml
  7. ---
  8. - name: check alived
  9. ping:
  10. - name:
  11. shell: ls /
  12. register: ls_result
  13. - debug: var=ls_result
  14. - name:
  15. shell: echo my phone is {{ phone }}
  16. register: echo_result
  17. - debug: var=echo_result
  18. - name: #添加copy模块
  19. copy: src=test dest=/root/
  20. - name: #添加script模块(自动在目标IP机器上执行脚本)
  21. script: test.sh
  22. [root@ansible myroles]# ansible-playbook nginx.yaml
 

12.6 roles中template模块的使用

roles模型里使用template模块,默认从roles/nginx/template里面找

 
  1. [root@ansible myroles]# cat roles/nginx/templates/test.j2
  2. myname is {{ my_name }},my phone is {{ phone }} #引用自定义变量
  3. my ipaddress is {{ansible_all_ipv4_addresses[0]}} #引用内置变量
  4. [root@ansible myroles]# cat roles/nginx/tasks/main.yaml
  5. ---
  6. - name: check alived
  7. ping:
  8. - name:
  9. shell: ls /
  10. register: ls_result
  11. - debug: var=ls_result
  12. - name:
  13. shell: echo my phone is {{ phone }}
  14. register: echo_result
  15. - debug: var=echo_result
  16. - name:
  17. copy: src=test dest=/root/
  18. - name:
  19. script: test.sh
  20. - name:
  21. template: src=test.j2 dest=/root/test2 #下发可变配置文件
  22. [root@ansible myroles]# ansible-playbook nginx.yaml
 

12.7 roles中notify模块的使用

roles使用notify模块,默认从roles/nginx/handles里面找

 
  1. [root@ansible myroles]# cat roles/nginx/handlers/main.yaml
  2. ---
  3. - name: start_nginx #定义handlers的动作类型
  4. shell: /usr/local/nginx/sbin/nginx
  5. - name: stop_nginx #定义handlers的动作类型
  6. shell: /usr/local/nginx/sbin/nginx -s stop
  7. - name: reload_nginx #定义handlers的动作类型
  8. shell: /usr/local/nginx/sbin/nginx -s reload
  9. [root@ansible myroles]# cat roles/nginx/tasks/main.yaml
  10. ---
  11. - name: check alived
  12. ping:
  13. - name:
  14. shell: ls /
  15. register: ls_result
  16. - debug: var=ls_result
  17. - name:
  18. shell: echo my phone is {{ phone }}
  19. register: echo_result
  20. - debug: var=echo_result
  21. - name:
  22. copy: src=test dest=/root/
  23. - name:
  24. script: test.sh
  25. - name:
  26. template: src=test.j2 dest=/root/test2
  27. notify: start_nginx #执行template任务后下发通知给handlers执行start_nginx
  28. [root@ansible myroles]# ansible-playbook nginx.yaml

特别提示:
notify下发通知只有当之前的任务造成了变化那么才会被执行,如果没有发生任何改变,则notify不会被执行。例如:

 
    1. #tasks任务造成改变,触发notify
    2. [root@ansible myroles]# cat /tmp/test.yaml
    3. ---
    4. - hosts: webA
    5. gather_facts: True
    6. tasks:
    7. - name:
    8. copy: src=/tmp/test dest=/root/ #这步造成目标改变才能出发notify
    9. notify: start_nginx
    10. handlers:
    11. - name: start_nginx
    12. shell: /usr/local/nginx/sbin/nginx
    13. [root@ansible myroles]# ansible-playbook /tmp/test.yaml
    14. PLAY [webA] ***************************************************************************************************
    15. TASK [Gathering Facts] ****************************************************************************************
    16. ok: [webA]
    17. TASK [copy] ***************************************************************************************************
    18. changed: [webA] #发生了改变
    19. RUNNING HANDLER [start_nginx] #触发notify *********************************************************************************
    20. changed: [webA]
    21. PLAY RECAP ****************************************************************************************************
    22. webA : ok=3 changed=2 unreachable=0 failed=0
    23. #我们再次执行/tmp/test.yaml
    24. [root@ansible myroles]# ansible-playbook /tmp/test.yaml
    25. PLAY [webA] ***************************************************************************************************
    26. TASK [Gathering Facts] ****************************************************************************************
    27. ok: [webA]
    28. TASK [copy] ***************************************************************************************************
    29. ok: [webA] #没有造成任务改变,未触发notify通知
    30. PLAY RECAP ****************************************************************************************************
    31. webA : ok=2 changed=0 unreachable=0 failed=0

ansible自动化的更多相关文章

  1. Ansible自动化运维工具-上

    [Ansible特点] 1)Ansible与saltstack均是基于Python语言开发的 2)安装使用简单,基于不同插件和模块实现各种软件,平台,版本的管理以及支持虚拟容器多层级的部署 3)不需要 ...

  2. CentOS7系统 ansible自动化部署多台服务器部署

    CentOS7系统 ansible自动化部署多台服务器部署   Ansible工作机制  从图中可以看出ansible分为以下几个部份: 1> Control Node:控制机器2> In ...

  3. ansible 自动化运维

    Ansible 自动化运维 ansible安装epel #yum list all *ansible*#yum install *ansible*#yum info ansible#rpm -ql a ...

  4. ansible自动化工具安装和简单使用

    ansible自动化工具安装和简单使用 1.安装 ansible依赖于Python 2.6或更高的版本.paramiko.PyYAML及Jinja2. 2.1 编译安装 解决依赖关系 # yum -y ...

  5. Jenkins +svn +maven +tomcat+ ansible 自动化批量部署

    Jenkins +svn +maven +tomcat+ ansible 自动化批量部署 一.部署svn yum install subversion 先创建目录 mkdir /home/svn 创建 ...

  6. [k8s]kubespray(ansible)自动化安装k8s集群

    kubespray(ansible)自动化安装k8s集群 https://github.com/kubernetes-incubator/kubespray https://kubernetes.io ...

  7. Jenkins+Gitlab+Ansible自动化部署(五)

    Freestyle Job实现静态网站部署交付(接Jenkins+Gitlab+Ansible自动化部署(四)https://www.cnblogs.com/zd520pyx1314/p/102445 ...

  8. Jenkins+Gitlab+Ansible自动化部署(六)

    Pipeline Job实现Nginix+MySQL+PHP+Wordpress实现自动化部署交付(Jenkins+Gitlab+Ansible自动化部署(五)https://www.cnblogs. ...

  9. Jenkins+Gitlab+Ansible自动化部署(三)

    接Jenkins+Gitlab+Ansible自动化部署(一)https://www.cnblogs.com/zd520pyx1314/p/10210727.html 和(二)https://www. ...

  10. Jenkins+Gitlab+Ansible自动化部署(一)

    首先准备实验环境 虚拟机 主机名 IP地址 服务 系统版本 内核版本 Vmware Workstation 14 gitlab.example.com 192.168.244.130 gitlab  ...

随机推荐

  1. 搭建一个microblaze的最小系统

    搭建一个microblaze的最小系统 首先例化一个microblaze核 对microblaze核进行配置 勾选: 这个是使能外部存储BRAM作为程序运行缓冲区 第二个是需要勾选 这个是使能AXI数 ...

  2. docker创建image

    =========================================================================在已有image基础上创建一个image======= ...

  3. python读写文件\r\n问题

    newline controls how universal newlines mode works (it only applies to text mode). It can be None, ' ...

  4. C/C++程序中内存被非法改写的一个检测方法

    本文所讨论的“内存”主要指(静态)数据区.堆区和栈区空间(详细的布局和描述参考<Linux虚拟地址空间布局>一文).数据区内存在程序编译时分配,该内存的生存期为程序的整个运行期间,如全局变 ...

  5. guava Lists.transform使用

    作用:将一个List中的实体类转化为另一个List中的实体类. 稍微方便一点.例如:将List<Student>转化为List<StudentVo> Student: pack ...

  6. 报错:Exception in thread "main" java.lang.NoClassDefFoundError: Lorg/apache/hadoop/fs/FileSystem

    报错现象: Exception in thread "main" java.lang.NoClassDefFoundError: Lorg/apache/hadoop/fs/Fil ...

  7. 使用原生JDBC循环读取文件并持久化到数据库

    先上代码: package com.demo.common.service; import java.io.File; import java.io.FileInputStream; import j ...

  8. Logic and Proofs--离散数学

    Propositions: A proposition is a declarative sentence(that is, a sentence that declares a fact ) tha ...

  9. js 解密

    需求:爬取https://www.xuexi.cn/f997e76a890b0e5a053c57b19f468436/018d244441062d8916dd472a4c6a0a0b.html页面中的 ...

  10. efcore migration

    实体------->migration------->db ---------------------------------------------------------------- ...