、Ansible整体介绍

Ansible是一个当时最为流行的集群部署与配置工具,在服务器配置和运维管理的过程中有重要的作用和优势。本文主要为结合个人的学习心得,向对ansible有兴趣的朋友尽可能深入简出、详尽的介绍这个工具的原理和用法。

Ansible是由Ansible Inc.和Red Hat共同开发的一款开源集群配置软件,编写语言为python,使用时的配置文件语言为yaml。核心组件使用了paramiko和PyYaml。其中paramiko是python的ssh支持库,而PyYaml则用于支持yaml配置文件的使用和playbook的应用。

Ansible有着非常突出的优点,从而使其在saltstack等集群配置工具中脱颖而出。优势如下:

  • 仅需管理主机安装并配置即可,所有的配置工作都通过ssh连接下发至被管理主机。
  • 轻量化
  • Python编写,源代码可读性强。同时playbook使用yml配置,容易上手
  • 对于集群和ECS的支持非常完美。
  • 支持大量API接入,并且对于python的扩展支持良好。
  • 由于架构出色,理论上在管理主机性能到位的情况下可以同时配置近乎无限的主机。

二、安装ansible

1、配置epel源作为yum安装源

自建源:

ansible app -a ‘mkdir /etc/yum.repos.d/repo’

ansible app -a ‘mv /etc/yum.repos.d/*.repo /etc/yum.repos/repo’

ansible app -m copy -a ‘content=”[base]\nname=CentOS\nbaseurl=file:///misc/cd\ngpgcheck=0\n\n[epel]\nname=epel\nbaseurl=https://mirrors.aliyun.com/centos/7/os/x86_64/\ngpgcheck=0“ dest=/etc/yum.repos.d/base.repo’

查看yum源
ansible all -a ‘cat /etc/yum.repos.d/base.repo’

2、安装配置ansible

yum install ansible -y

主配置文件

  1. $ cat /etc/ansible/ansible.cfg
  2. [defaults]:段常用参数说明
  3. inventory = /etc/ansible/hosts # 定义主机清单的文件
  4. library = /usr/share/my_modules/ # 自定义lib库存放目录
  5. remote_tmp = ~/.ansible/tmp # 临时文件远程主机存放目录
  6. local_tmp = ~/.ansible/tmp # 临时文件本地存放目录
  7. forks = 5 # 默认开启的并发数
  8. poll_interval = 15 # 默认轮询时间间隔
  9. sudo_user = root # 默认sudo用户
  10. #ask_sudo_pass = True # 是否需要sudo密码
  11. #ask_pass = True # 是否需要密码
  12. roles_path - /etc/ansible/roles # 默认下载的roles存放的目录
  13. log_path = /var/log/ansible.log # 执行日志存放目录

配置ansible⼯作特性
vim /etc/ansible/ansible.cfg 取消注释
module_set_locale = False
module_name = shell
log_path=/var/log/ansible.log
host_key_checking = False 禁用ssh检查

主机清单
vim /etc/ansible/hosts
[app]
192.168.23.128
192.168.23.108

基于key验证,将公钥分发

连接测试:

[root@centos ~]# ssh 192.168.37.51

Last login: Sat May 25 11:37:28 2019 from 192.168.37.51
[root@localhost ~]# exit
logout
Connection to 192.168.37.51 closed.

3、Ansible命令参数介绍

ansible本身自带非常多的参数选项,可以适配几乎任何集群部署的需求和各种测试需求。 这些参数在ansible-playbook等延伸指令中往往也通用。

  1. $ ansible --help
  2. Usage: ansible <host-pattern> [options]
  3. Define and run a single task 'playbook' against a set of hosts ##单纯的ansible指令用于对一个或者一组受管机执行一个playbook任务
  4. 普通参数:
  5. -a MODULE_ARGS, --args=MODULE_ARGS
  6. #[重要]模块参数
  7. --ask-vault-pass # 要求输入管理密码
  8. -B SECONDS, --background=SECONDS
  9. #异步运行,X秒后失败(默认关闭)
  10. -C, --check #不对受管机执行任何改变,但是假设已执行语句并返回结果(用于测试)
  11. -D, --diff #当改变小体积文件的时候,显示两者的区别,常常和-C参数一起用(用于测试)
  12. -e EXTRA_VARS, --extra-vars=EXTRA_VARS
  13. #将其他变量设置为key = value或YAML / JSON,如果filename前缀为@
  14. -f FORKS, --forks=FORKS
  15. #指定要使用的并行进程数(默认值= 5)
  16. -h, --help #显示此帮助消息并退出
  17. -i INVENTORY, --inventory=INVENTORY, --inventory-file=INVENTORY
  18. #指定库存主机路径或逗号分隔的主机列表。PS: --inventory-file已弃用
  19. -l SUBSET, --limit=SUBSET
  20. #进一步将所选主机限制为其他模式
  21. --list-hosts #输出匹配主机列表;不会执行任何其他操作
  22. -m MODULE_NAME, --module-name=MODULE_NAME
  23. ##[重要]要执行的模块名称(默认为command)
  24. -M MODULE_PATH, --module-path=MODULE_PATH
  25. ##将冒号分隔的路径预先添加到模块库(默认为[u'/root/.ansible/plugins/modules',u'/usr/share/ansible/plugins/modules'])
  26. -o, --one-line ##压缩输出。
  27. --playbook-dir=BASEDIR
  28. ##由于此工具不使用playbooks,因此将其用作替代playbook目录。这将设置许多功能的相对路径,包括roles/group_vars/etc. 也就是变相实现部分playbook功能。
  29. -P POLL_INTERVAL, --poll=POLL_INTERVAL
  30. ##如果使用-B(默认值= 15),则设置轮询间隔。
  31. --syntax-check ##对playbook执行语法检查,但不执行它.
  32. -t TREE, --tree=TREE ##将输出记录到此目录
  33. --vault-id=VAULT_IDS ##显示要使用的保管库标识
  34. --vault-password-file=VAULT_PASSWORD_FILES
  35. ##保管库密码文件
  36. -v, --verbose ##详细模式(-vvv表示更多,-vvvv表示启用连接调试)
  37. --version ##显示ansible版本并退出
  38. 连接相关参数:
  39. 主要关于控制哪些受管机以及如何连接到主机。
  40. -k, --ask-pass ##要求输入受管机密码
  41. --private-key=PRIVATE_KEY_FILE, --key-file=PRIVATE_KEY_FILE
  42. ##使用特点文件来认证链接
  43. -u REMOTE_USER, --user=REMOTE_USER
  44. ##以特定user来进行连接。
  45. -c CONNECTION, --connection=CONNECTION
  46. ##要使用的连接类型(默认=智能)
  47. -T TIMEOUT, --timeout=TIMEOUT
  48. ##以秒为单位覆盖连接超时(默认值= 10)
  49. --ssh-common-args=SSH_COMMON_ARGS
  50. ##指定传递给sftp / scp / ssh的公共参数(例如ProxyCommand)
  51. --sftp-extra-args=SFTP_EXTRA_ARGS
  52. ##指定仅传递给sftp的额外参数(例如-f,-l)
  53. --scp-extra-args=SCP_EXTRA_ARGS
  54. ##指定仅传递给scp的额外参数(例如-l)
  55. --ssh-extra-args=SSH_EXTRA_ARGS
  56. ##指定仅传递给ssh的额外参数(例如-R)
  57. 特权升级参数:
  58. 控制你在目标主机上如果成为或者成为哪个用户
  59. -s, --sudo ##用sudo(nopasswd)运行操作(不推荐,推荐使用--become-method)
  60. -U SUDO_USER, --sudo-user=SUDO_USER
  61. ##所需的sudo用户(默认= root)(不建议使用,推荐使用--become-method)
  62. -S, --su ##用su运行操作 (不建议使用,推荐使用--become-method)
  63. -R SU_USER, --su-user=SU_USER
  64. ##以su作为此用户运行操作(默认=无)(不建议使用,推荐使用--become-method)
  65. -b, --become ##用run运行操作(不显示密码提示)
  66. --become-method=BECOME_METHOD
  67. ##要使用的权限升级方法(默认= sudo),可选项有: [ sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas | pmrun | enable | machinectl ]
  68. --become-user=BECOME_USER
  69. ##以此用户身份运行操作(默认= root)
  70. --ask-sudo-pass ##请求sudo密码(不推荐使用,推荐使用--become-method)
  71. --ask-su-pass ##请求su密码 (不推荐使用,推荐使用--become-method)
  72. -K, --ask-become-pass
  73. ##要求提供权限提升密码

三、Ansible模块介绍与使用

Ansible内置了海量的原生模块和大量的用于连接第三方API的支持模块,熟练掌握基础模块,并且活用各种扩展模块,是熟练掌握Ansible的必经之路。这一章里面我们会对Ansible的模块进行基础的介绍和使用案例分析。至于详细的模块介绍可以查看我写的Ansible支持模块详表

在ansible中查看所有的模块只需要一个命令:

[root@centos ~]#ansible-doc -l

如果需要查看某一个特定的模块的详细解释则可以直接查询,以shell模块为例:

[root@centos7 ~]#ansible-doc shell

<SHELL (/usr/lib/python2.7/site-packages/ansible/modules/commands/shell.py)

  1. The `shell' module takes the command name followed by a list
  2. of space-delimited arguments. It is almost exactly like the
  3. [command] module but runs the command through a shell
  4. (`/bin/sh') on the remote node. For Windows targets, use the
  5. [win_shell] module instead... 省略

模块的重要性除了本身的强大功能外,熟练地掌握模块也是之后playbook部分的基础。一个优秀的playbook使用者必然对常用模块的参数了如指掌。

1. Command模块

Command模块自如其名,就是一个很纯粹的命令执行模块,用于在受管机上进行命令的执行,其本身也可以配合很多二级参数和指令进行功能的扩展。不支持管道功能。例如最简单的查看hostname功能:

  1. [root@centos7 ~]# ansible fangwei -m command -a 'hostname'
  2. EMRtest | CHANGED | rc=0 >>
  3. EMR-master
  4. Snipeit | CHANGED | rc=0 >>
  5. localhost.localdomain
  6. 复制代码

需要注意的是,在没有特地指定ansible的-m参数的时候,默认调用的Module就是command。 下面是command常用的几个二级参数:

  • creates:判断,当该文件存在时,则该命令不执行
  • free_form:需要执行的Linux指令
  • chdir:在执行命令之前,先切换到该指定的目录
  • removes:判断,当该文件不存在时,则该选项不执行
  • executable:切换shell来执行命令,该执行路径必须是一个绝对路径 下面为chdir的用法举例,其他的指令也是类似的用法,可以自行尝试。具体的格式为: ansible $目标host -a '$二级参数=$目标文件或路径 $待执行指令'
  1. [root@Printer ~]# ansible fangwei -a 'chdir=/etc/ansible ls -l'
  2. EMRtest | CHANGED | rc=0 >>
  3. 总用量 28
  4. -rw-r--r-- 1 root root 20277 12 14 13:57 ansible.cfg
  5. -rw-r--r-- 1 root root 1070 12 26 11:26 hosts
  6. drwxr-xr-x 2 root root 4096 12 14 13:57 roles
  7. 复制代码

2. Shell模块(或者Raw模块)

这个模块的主要特点就是囊括了所有的command的功能和二级参数支持,并且支持管道。

  1. [root@centos7 ~]# ansible fangwei -m shell -a 'ps -ef | grep crond | grep -v grep'
  2. EMRtest | CHANGED | rc=0 >>
  3. root 6030 1 0 2018 ? 00:00:13 /usr/sbin/crond -n
  4. Snipeit | CHANGED | rc=0 >>
  5. root 1042 1 0 212 ? 00:00:04 /usr/sbin/crond -n
  6. 复制代码

3. File模块

File模块主要是对于文件的一些简单操作,主要是创建或者权限设定,已经文件的存在判断等。

  • force:在两种情况下强制创建软链接。1、源文件不存在但之后会建立的情况;2、目标软件已存在,需要先取消之前的软链接,然后创建新的软链接。选项:yes|no
  • group:定义文件/目录的属组
  • mode:定义文件/目录的权限
  • path:必选项,定义文件/目录的路径
  • recurse:递归的设置文件的属性,只对目录有效
  • src:要被链接到的路径,只应用于state=link的情况
  • dest:被链接到的路径,只应用于state=link的情况
  • state: directory:如果目录不存在,创建目录 file:即使文件不存在,也不会被创建 link:创建软链接;hard:创建硬链接 touch:如果文件不存在,则会创建一个新的文件,如果已存在,则更新其最后修改时间 absent:删除目录/文件或者取消链接文件
  1. [root@centos7 ~]# ansible fangwei -m file -a 'path=/root/ninngenn.cfg state=touch'
  2. Snipeit | CHANGED => {
  3. "changed": true,
  4. "dest": "/root/ninngenn.cfg",
  5. "gid": 0,
  6. "group": "root",
  7. "mode": "0644",
  8. "owner": "root",
  9. "size": 0,
  10. "state": "file",
  11. "uid": 0
  12. }
  13. EMRtest | CHANGED => {
  14. "changed": true,
  15. "dest": "/root/ninngenn.cfg",
  16. "gid": 0,
  17. "group": "root",
  18. "mode": "0644",
  19. "owner": "root",
  20. "size": 0,
  21. "state": "file",
  22. "uid": 0
  23. }
  24. 复制代码

4. Copy模块

Copy模块主要用于复制文件到远程主机。具体参数如下:

  • backup:在覆盖之前将源文件备份,备份文件包含时间信息,选项:yes|no
  • content:用于替代”src”,可以直接设定文件的值
  • directory_node:递归的设定目录权限,默认为系统默认权限
  • force:如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖;如果设置为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes
  • others:所有file模块里的选项都可以在这里使用
  • src:要复制到远程主机的文件在本地的地址,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用“/”来结尾,则只复制目录里的内容,如果没有使用“/”来结尾,则包含目录在内的整个内容全部复制,类似于rsync
  1. [root@centos7 ~]# ansible fangwei -m copy -a 'src=/root/ninngenn.cfg dest=/root/ninngenn.cfg force=yes'
  2. EMRtest | CHANGED => {
  3. "changed": true,
  4. "checksum": "458bd6a39e16bc1e00255b66c67b5cb92180166b",
  5. "dest": "/root/ninngenn.cfg",
  6. "gid": 0,
  7. "group": "root",
  8. "md5sum": "cf35206b8cca3e51082bb32ce278ed8d",
  9. "mode": "0644",
  10. "owner": "root",
  11. "size": 56,
  12. "src": "/root/.ansible/tmp/ansible-tmp-1551949966.41-24885251361529/source",
  13. "state": "file",
  14. "uid": 0
  15. }
  16. Snipeit | CHANGED => {
  17. "changed": true,
  18. "checksum": "458bd6a39e16bc1e00255b66c67b5cb92180166b",
  19. "dest": "/root/ninngenn.cfg",
  20. "gid": 0,
  21. "group": "root",
  22. "md5sum": "cf35206b8cca3e51082bb32ce278ed8d",
  23. "mode": "0644",
  24. "owner": "root",
  25. "size": 56,
  26. "src": "/root/.ansible/tmp/ansible-tmp-1551949966.4-190980703709511/source",
  27. "state": "file",
  28. "uid": 0
  29. }

5. Service模块

用于受管机服务的配置与管理,类似于systemd,常用选项:

  • arguments:为命令提供一些附加参数
  • enabled:是否开机启动,选项 yes|no
  • name:必选项,服务名称
  • pattern:定义一个模式,如果通过status指令来查看服务状态时,没有响应,它会通过ps命令在进程中根据该模式进行查找,如果匹配到,则认为该服务依然运行
  • runlevel:运行级别
  • sleep:如果执行了restarted,则在stop和start之间等待几秒钟
  • state:对当前服务执行启动/停止/重启/重新加载等操作(started/stopped/restarted/reloaded)
  1. [root@centos7 ~]# ansible fangwei -m service -a 'name=sshd state=restarted enabled=yes'
  2. Snipeit | CHANGED => {
  3. "changed": true,
  4. "enabled": true,
  5. "name": "sshd",
  6. "state": "started"
  7. }
  8. EMRtest | CHANGED => {
  9. "changed": true,
  10. "enabled": true,
  11. "name": "sshd",
  12. "state": "started"
  13. }
  14. 复制代码

6. Cron模块

类似于Linux的Crontab功能,用来控制服务或者进程的定时执行功能。常用参数:

  • backup:对远程主机上的原计划任务内容修改之前做备份
  • cron_file:如果指定该选项,则用该文件替换远程主机上cron.d目录下的用户的任务计划
  • day:日(1-31,,/2,…)
  • hour:小时(0-23,,/2,…)
  • minute:分钟(0-59,,/2,…)
  • month:月(0-12,*,…)
  • weekday:周(0-7,*,…)
  • job:要执行的任务,依赖于state=present
  • name:该任务的描述
  • special_time:指定什么时候执行,参数:reboot,yearly,annually,monthly,weekly,daily,hourly
  • state:确认该任务计划是创建还是删除
  • user:以哪个用户身份执行
  1. [root@centos7 ~]# ansible fangwei -m cron -a 'name="check home directory" minute=*/10 job="ls -lht /home"'
  2. Snipeit | CHANGED => {
  3. "changed": true,
  4. "envs": [],
  5. "jobs": [
  6. "check home directory"
  7. ]
  8. }
  9. EMRtest | CHANGED => {
  10. "changed": true,
  11. "envs": [],
  12. "jobs": [
  13. "check home directory"
  14. ]
  15. }
  16. 复制代码

7. FileSystem

FileSystem模块用于配置受管机的文件系统。改模块涉及高位操作,请务必小心,常用参数为:

  • dev:目标块设备
  • force:在一个已有文件系统的设备上强制创建
  • fstype:文件系统的类型
  • opts:传递给mkfs命令的选项
  1. [root@centos7 ~]# ansible test_hosts -m filesystem -a 'dev=/dev/sdb fstype=ext4'
  2. 172.26.0.84 | SUCCESS => {
  3. "changed": true
  4. }
  5. 复制代码

8. Mount模块

Mount模块用于配置受管机的磁盘挂载,高危模块,请慎重使用,下面为常用参数:

  • dump:存储(见fstab文件第5列)。注意,如果设置为null并且状态设置为present,它将停止工作,并且将在后续运行中进行重复条目。对Solaris系统没有影响。
  • fstype:必选项,文件系统类型,要求状态是present或mounted
  • name:必选项,挂载点
  • opts:传递给mount命令的参数
  • src:必选项,要挂载的设备路径。要求状态是present或mounted
  • state:必选项。选项如下: present:只处理fstab中的配置 absent:删除挂载点 mounted:自动创建挂载点并挂载 unmounted:卸载
  1. [root@centos7 ~]# ansible test_hosts -m mount -a 'name=/mnt src=/dev/sdb1 fstype=ext4 state=mounted opts=rw'
  2. 172.26.0.84 | SUCCESS => {
  3. "changed": true,
  4. "dump": "0",
  5. "fstab": "/etc/fstab",
  6. "fstype": "ext4",
  7. "name": "/mnt",
  8. "opts": "rw",
  9. "passno": "0",
  10. "src": "/dev/sdb1"
  11. 复制代码

9. Yum模块

如果熟悉CentOS的朋友应该就会知道,这是使用yum包管理器来管理软件包的模块,参数如下:

  • conf_file:yum的配置文件
  • disable_gpg_check:关闭gpg_check
  • disablerepo:不启用某个源
  • enablerepo:启用某个源
  • list:查看yum列表
  • name:要进行操作的软件包名字,也可以传递一个url或者一个本地的rpm包的路径
  • state:状态(present/installed/absent/removed/latest)
  1. [root@centos7 ~]# ansible fangwei -m yum -a 'name=sl state=latest'
  2. Snipeit | CHANGED => {
  3. "ansible_facts": {
  4. "pkg_mgr": "yum"
  5. },
  6. "changed": true,
  7. "msg": "",
  8. "obsoletes": {
  9. "grub2": {
  10. "dist": "x86_64",
  11. "repo": "@anaconda",
  12. "version": "1:2.02-0.65.el7.centos.2"
  13. },
  14. "grub2-tools": {
  15. "dist": "x86_64",
  16. "repo": "@anaconda",
  17. "version": "1:2.02-0.65.el7.centos.2"
  18. }
  19. },
  20. "rc": 0,
  21. "results": [
  22. "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\n * ius: dfw.mirror.rackspace.com\n * webtatic: uk.repo.webtatic.com\nResolving Dependencies\n--> Running transaction check\n---> Package sl.x86_64 0:5.02-1.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n sl x86_64 5.02-1.el7 epel 14 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package\n\nTotal download size: 14 k\nInstalled size: 17 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : sl-5.02-1.el7.x86_64 1/1 \n Verifying : sl-5.02-1.el7.x86_64 1/1 \n\nInstalled:\n sl.x86_64 0:5.02-1.el7 \n\nComplete!\n"
  23. ]
  24. }
  25. EMRtest | CHANGED => {
  26. "ansible_facts": {
  27. "pkg_mgr": "yum"
  28. },
  29. "changed": true,
  30. "msg": "",
  31. "rc": 0,
  32. "results": [
  33. "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package sl.x86_64 0:5.02-1.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package Arch Version Repository Size\n================================================================================\nInstalling:\n sl x86_64 5.02-1.el7 epel 14 k\n\nTransaction Summary\n================================================================================\nInstall 1 Package\n\nTotal download size: 14 k\nInstalled size: 17 k\nDownloading packages:\nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n Installing : sl-5.02-1.el7.x86_64 1/1 \n Verifying : sl-5.02-1.el7.x86_64 1/1 \n\nInstalled:\n sl.x86_64 0:5.02-1.el7 \n\nComplete!\n"
  34. ]
  35. }
  36. 复制代码

10. User模块

User模块顾名思义就是用于用户参数设置的模块。常用参数:

  • home:指定用户家目录
  • group:设置用户主组
  • groups:设置用户的附属组
  • uid:设置用户的UID
  • password:设置用户的密码,密码必须为加密后的值
  • name:创建用户的用户名
  • createhhome:选项yes|no,值为yes时才创建用户家目录
  • system:选项yes|no,默认为no,值为yes时创建的用户为系统用户
  • remove:当state=absent时,remove=yes则表示连同家目录一起删除,等价于userdel -r
  • state:选项present|absent,创建用户或删除用户
  • shell:设置用户的shell环境
  1. [root@centos7 ~]# ansible test_hosts -m user -a 'name=user1 uid=1001 group=yfshare createhome=yes home=/home/user1 password="P@ssw0rd" shell=/bin/bash state=present'
  2. 172.26.0.84 | SUCCESS => {
  3. "changed": true,
  4. "comment": "",
  5. "createhome": true,
  6. "group": 1000,
  7. "home": "/home/user1",
  8. "name": "user1",
  9. "password": "NOT_LOGGING_PASSWORD",
  10. "shell": "/bin/bash",
  11. "state": "present",
  12. "system": false,
  13. "uid": 1001
  14. }
  15. 复制代码

11. Group模块

顾名思义用于配置Group信息的模块,参数如下:

  • gid:设置组的GID
  • name:组名
  • state:选项为present|absent,创建组或删除组
  • system:选项为yes|no,值为yes,则创建系统组 用法与User模块雷同,不再举例。

12. get_url模块

主要用于从http、ftp、https服务器上下载文件(类似于wget),主要参数如下:

  • checksum:文件下载完成后进行校验
  • timeout:请求超时时间,默认为10s
  • url:文件下载地址
  • url_username:用户名,基于HTTP的基本认证
  • url_password:密码
  • -use_proxy:选项yes|no,默认为yes,即使用代理
  • dest:下载文件存储的绝对路径
  1. [root@centos7 ~]# ansible fangwei -m get_url -a 'dest=/root url=http://172.26.0.84/file/drivers/Canon/mac-10-14-canon.dmg'
  2. EMRtest | CHANGED => {
  3. "changed": true,
  4. "checksum_dest": null,
  5. "checksum_src": "eff3bd83c5966373f04d8c4576cbbe610ba0d638",
  6. "dest": "/root/mac-10-14-canon.dmg",
  7. "gid": 0,
  8. "group": "root",
  9. "md5sum": "59b6a0a3dcb9dd3e6e46d1e8374d9c43",
  10. "mode": "0644",
  11. "msg": "OK (23166785 bytes)",
  12. "owner": "root",
  13. "size": 23166785,
  14. "src": "/root/.ansible/tmp/ansible-tmp-1551951882.53-86480089864174/tmp_7guIp",
  15. "state": "file",
  16. "status_code": 200,
  17. "uid": 0,
  18. "url": "http://172.26.0.84/file/drivers/Canon/mac-10-14-canon.dmg"
  19. }
  20. Snipeit | CHANGED => {
  21. "changed": true,
  22. "checksum_dest": null,
  23. "checksum_src": "eff3bd83c5966373f04d8c4576cbbe610ba0d638",
  24. "dest": "/root/mac-10-14-canon.dmg",
  25. "gid": 0,
  26. "group": "root",
  27. "md5sum": "59b6a0a3dcb9dd3e6e46d1e8374d9c43",
  28. "mode": "0644",
  29. "msg": "OK (23166785 bytes)",
  30. "owner": "root",
  31. "size": 23166785,
  32. "src": "/root/.ansible/tmp/ansible-tmp-1551951882.52-38856232211770/tmpPLN4Wf",
  33. "state": "file",
  34. "status_code": 200,
  35. "uid": 0,
  36. "url": "http://172.26.0.84/file/drivers/Canon/mac-10-14-canon.dmg"
  37. 复制代码

13. Setup模块

playbooks自动收集远程主机上可用变量,这些变量用于playbooks配置。

  1. [root@centos7 ~]# ansible test_hosts -m setup
  2. 172.26.0.84 | SUCCESS => {
  3. "ansible_facts": {
  4. "ansible_all_ipv4_addresses": [
  5. "172.26.0.84"
  6. ],
  7. "ansible_all_ipv6_addresses": [
  8. "fe80:****:****:fe5c:dc6d"
  9. ],
  10. "ansible_architecture": "x86_64",
  11. 复制代码

14. Script模块

这个模块用于在受管机上执行sh脚本。

  1. [root@centos7 ~]# ansible test_hosts -m script -a '/tmp/script.sh'
  2. Enter passphrase for key '/root/.ssh/id_rsa':
  3. 172.26.0.84 | SUCCESS => {
  4. "changed": true,
  5. "rc": 0,
  6. "stderr": "Shared connection to 172.26.0.84 closed.\r\n",
  7. "stdout": "",
  8. "stdout_lines": []

四、ansible-Playbook 的用法

1、Yaml语言

Yaml语言是一种配置语言,主要用于配置文件的设定和数据块的储存,作为一种xml语言的进化形态出现。起主要的优势在于:

  • YAML的可读性好。
  • YAML和脚本语言的交互性好。
  • YAML使用实现语言的数据类型。
  • YAML有一个一致的信息模型。
  • YAML易于实现。

上面5条也就是XML不足的地方。同时,YAML也有XML的下列优点:

  • YAML可以基于流来处理;
  • YAML表达能力强,扩展性好。 总之,YAML试图用一种比XML更敏捷的方式,来完成XML所完成的任务。

更多的内容及规范参见yaml官网。 语法结构通过空格来展示。Sequence里的项用”-“来代表,Map里的键值对用”:”分隔。 这几乎就是所有的语法了。以下为一个标准的ansible-playbook的yaml配置文件:

  1. ---
  2. - hosts: rotest2
  3. roles:
  4. - sshd
  5. - snmp
  6. - hostname
  7. - vim
  8. - parted
  9. - authorized_keys
  10. 复制代码

2、playbook模块

roles:角色(主模块,和主yaml文件、ansible配置文件、host文件同在playbook根目录,同时在roles文件夹下则是各种自定义的role。在role文件夹下才包括了后续的其他次级模块)

  1. root@centos7 ~/ansible-test $ ls
  2. ansible.cfg hosts roles main.yml
  3. root@centos7 ~/ansible-test/roles $ ls
  4. audit authorized_keys hostname megacli nrpe parted snmp sshd telegraf vim
  5. 复制代码

在role文件夹下,会调用下面的各个子模块,但是除了task以外都不是必须,而是可选项。例如这个telegraf的部署role,下面只包含了files、handlers、tasks三个子模块。在子模块中我们可以调用任何ansible支持的模块功能,尤其是上一章我们介绍的那些重要功能模块

  1. root@centos7 ~/ansible-test/roles/telegraf $ ls
  2. files handlers tasks
  3. 复制代码
  • tasks:任务
  • variables:变量
  • templates:模板
  • handlers:处理器
  • files:需要的文件

3、如何使用playbook

ansible-playbook的使用基本和ansible类似,哪怕调用--help指令查看,也是一样的参数结果。一般来说由于playbook调用的模块较多,配置的内容较丰富,后续的部署影响较大,所以在使用的时候请务必先调用-D -C两个参数进行结果测试,排查报错,确认一切无误后再进行推送和部署。例如:

  1. [root@centos7 ~]# ansible-playbook -i hosts ro.yml -t authorized_keys -DC
  2. ~$ ansible-playbook -i hosts ro.yml -t authorized_keys
  3. 复制代码

4、使用案例

这里我们就用一个案例来对ansible-playbook进行详细的解释。这个案例比较完整,有助于我们方便理解。 这个案例的文件架构为:

  1. [root@centos7 ~]#/ansible-test $ ls
  2. ansible.cfg hosts roles main.yml
  3. 复制代码

具体的main.yml文件为:

  1. [root@centos7 ~]#/ansible-test $ cat main.yml
  2. ---
  3. - hosts: test
  4. roles:
  5. - sshd
  6. - snmp
  7. - hostname
  8. - vim
  9. - parted
  10. - authorized_keys
  11. - telegraf
  12. - audit
  13. 复制代码

我们进入roles文件夹,查看具体的role内容。

  1. [root@centos7 ~]#/ansible-test/roles $ ls
  2. audit authorized_keys hostname megacli nrpe parted snmp sshd telegraf vim
  3. 复制代码

如果我们需要在受管机上安装某个软件,以telegraf这个role为例:

  1. [root@centos7 ~]#/ansible-test/roles/telegraf $ tree
  2. .
  3. ├── files
  4. ├── telegraf-1.8.0-1.x86_64.rpm #安装包rpm文件
  5. ├── telegraf.conf #自定义的配置文件
  6. └── telegraf.conf.bak #原始默认配置文件(非必须)
  7. ├── handlers
  8. └── main.yml #处理器配置
  9. └── tasks
  10. └── main.yml #role的任务主配置
  11. 3 directories, 5 files
  12. -------------------------------------
  13. [root@centos7 ~]#/ansible-test/roles/telegraf $ cat ./tasks/main.yml
  14. ---
  15. - name: install telegraf #配置npm的下载地址
  16. yum: name=https://dl.influxdata.com/telegraf/releases/telegraf-1.8.0-1.x86_64.rpm state=present
  17. tags: telegraf
  18. - name: copy telegraf config #配置文件的复制
  19. copy: src=telegraf.conf dest=/etc/telegraf/
  20. notify: reload telegraf
  21. tags: telegraf
  22. - name: ensure service telegraf is started and enabled
  23. service: name=telegraf state=started enabled=yes
  24. tags: telegraf #确保在受管机上开机启动telegraf服务
  25. -------------------------------------
  26. [root@centos7 ~]#/ansible-test/roles/telegraf $ cat ./handlers/main.yml
  27. ---
  28. - name: reload telegraf #异常状况重新加载
  29. service: name=telegraf state=reloaded
  30. 复制代码

而对于部分复杂的配置需求,我们甚至可以使用shell脚本来对受管机进行相关的处理,例如磁盘挂载或者分配等系统级别的任务。

  1. [root@centos7 ~]#/ansible-test/roles/parted $ ls
  2. files tasks
  3. -------------------------------------
  4. [root@centos7 ~]#/ansible-test/roles/parted $ tree
  5. .
  6. ├── files
  7. ├── parted.sh #shell脚本文件
  8. └── parted.sh.bak
  9. └── tasks
  10. └── main.yml #主task配置
  11. 2 directories, 3 files
  12. -------------------------------------
  13. [root@centos7 ~]#/ansible-test/roles/parted $ cat files/parted.sh
  14. #!/bin/bash
  15. OPTS="noatime,nobarrier,errors=remount-ro,nofail"
  16. x=b
  17. #for x in {b}
  18. #do
  19. echo "mkpart /dev/vd${x}"
  20. parted /dev/vd${x} -s mklabel gpt
  21. parted /dev/vd${x} -s mkpart primary 1 100%
  22. echo ">>> mkfs.ext4 /dev/vd${x}1"
  23. mkfs.ext4 -q /dev/vd${x}1
  24. if [ $? -eq 0 ]; then
  25. UUID=$(blkid /dev/vd${x}1 | sed -e 's/.*\(UUID=.*\) TYPE.*/\1/')
  26. echo -e "${UUID}\t\t/data\t\text4\t\t${OPTS}\t\t0 0" >> /etc/fstab
  27. fi
  28. seq=$(($seq+1))
  29. #done #通过shell脚本进行磁盘的分区与挂载
  30. -------------------------------------
  31. [root@centos7 ~]#/ansible-test/roles/parted $ cat tasks/main.yml
  32. ---
  33. #parted
  34. - name: copy parted config
  35. copy: src={{ item }} dest=~ owner=root group=root mode="0777"
  36. with_items: #复制脚本到受管机并配置chown权限
  37. - parted.sh #执行shell脚本
  38. tags: parted

五、variables 变量

1、变量的定义

1、通过setup模块结果直接调用其内部变量

2、ansible-playbook命令行中的自定义变量

  1. -e VARS, --extra-vars=VARS
  2. # 示例
  3. [root@centos7 ~]#/working # cat forth.yml
  4. - hosts: webservers
  5. remote_user: root
  6. tasks:
  7. - name: install pkg
  8. yum: name={{ pkname}} state=present # name定义变量引用
  9. # 命令行传递一个变量 pkname=memcached
  10. [root@centos7 ~]#/working # ansible-playbook -e pkname=memcached forth.yml

3、通过 roles 传递变量

4、Host Inventory 中定义变量

  1. (1) 向不同的主机传递不同的变量
  2. IP/HOSTNAME variables=value var2=value2
  3. 示例:
  4. [webservers]
  5. 192.168.1.142 http_port=80
  6. (2) 向组中的主机传递相同的变量
  7. [groupname:vars]
  8. variable=value
  9. 示例:
  10. [webservers]
  11. 192.168.1.142
  12. [webservers:vars] # 向webservers组内传递变量
  13. http_port=80

注意:inventory 参数:

  1. 用于定义ansible远程连接目标主机时使用的参数,而非传递给playbook的变量;
  2. ansible_ssh_host
  3. ansible_ssh_port
  4. ansible_ssh_user
  5. ansible_ssh_pass
  6. ansible_sudo_pass

5、在playbook文件中定义变量

定义方式:

  1. vars:
  2. - var1: value1
  3. - var2: value2

示例:

  1. - hosts: webservers
  2. remote_user: root
  3. vars: # 声明变量定义
  4. - http_port: 80 # http_port的值为80
  5. tasks:
  6. - name: install httpd package
  7. yum: name=httpd state=present
  8. - name: install config file
  9. template: src=files/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
  10. tags: instconf
  11. notify: restart httpd
  12. - name: start httpd service
  13. service: name=httpd state=started
  14. handlers:
  15. - name: restart httpd
  16. service: name=httpd state=restarted

2、调用变量

调用方式:在模版文件中使用{{ 变量名 }}来调用指定变量;

  1. {{ variable }}
  2. # 例如,nginx 进程数设置为远程主机的CPU核心数
  3. user nginx;
  4. worker_processes {{ ansible_processor_count }};
  5. # 变量中还可进行算数运算等操作例如,CPU 的核心数加1
  6. worker_processes {{ ansible_processor_count + 1 }};

注意:被调用的模版文件后缀必须以.j2结尾

示例:httpd.conf 配置文件中 Listen 调用变量 http_port

  1. # 修改httpd.conf文件
  2. Listen {{ http_port }}
  3. # playbook文件
  4. - hosts: webservers
  5. remote_user: root
  6. vars: # 声明变量定义
  7. - http_port: 80 # http_port的值为80
  8. tasks:
  9. - name: install httpd package
  10. yum: name=httpd state=present
  11. - name: install config file
  12. template: src=files/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
  13. tags: instconf
  14. notify: restart httpd
  15. - name: start httpd service
  16. service: name=httpd state=started
  17. handlers:
  18. - name: restart httpd
  19. service: name=httpd state=restarted

六、条件测试

when语句:在 task 中使用,jinja2 的语法格式;

示例:

  1. task:
  2. - name: install conf file to centos7
  3. template: stc=files/nginx.conf.c7.j2
  4. when: ansible_distribution_major_version == "7" # 当远程主机版本为centos7提供centos7的nginx配置文件
  5. - name: install conf file to centos6
  6. template: stc=files/nginx.conf.c6.j2
  7. when: ansible_distribution_major_version == "6" # 当远程主机版本为centos6提供centos6的nginx配置文件

when 语句中也可以使用 jinja2 中的语法,例如 and、not 等

  1. - hosts: webservers
  2. remote_user: root
  3. tasks:
  4. - name: install nginx
  5. yum: name=nginx state=latest
  6. - name: inst nginx config centos7
  7. template: src=files/nginx.conf.c7.j2 dest=/etc/nginx/nginx.conf
  8. # 两个条件必须同时满足
  9. when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7"
  10. tags: instconf
  11. notify: restart nginx
  12. - name: inst nginx config centos6
  13. template: src=files/nginx.conf.c6.j2 dest=/etc/nginx/nginx.conf
  14. when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6"
  15. tags: instconf
  16. - name: start nginx
  17. systemd: name=nginx state=started enabled=yes
  18. handlers:
  19. - name: restart nginx
  20. systemd: name=nginx state=reloade

七、循环

功用:迭代需要重复的任务;

格式:

  1. # 对迭代项引用,固定变量名为"item";而后要在task中使用 `loop` 给定要迭代的元素列表;在低版本的 ansible 中使用 with_items;
  2. 列表方法:
  3. 字符串
  4. 字典

示例:

  1. - name: install some packages
  2. yum: name= {{ item }} state=present
  3. loop: # 一次迭代一个元素,第一次item为nginx,第二次item为memcached,第三次item为php-fpm
  4. - nginx
  5. - memcached
  6. - php-fpm
  7. - name: add some groups # 循环创建三个组
  8. group: name={{ item }} state=present
  9. loop:
  10. - group11
  11. - group12
  12. - group13
  13. - name: add some users # 循环创建三个用户,并且同时给组引用变量;
  14. user: name={{ item.name }} group={{ item.group }} state=present
  15. loop:
  16. - { name: 'user1',group: 'group11' }
  17. - { name: 'user2',group: 'group12' }
  18. - { name: 'user3',group: 'group13' }

完整示例:

  1. [root@centos7 ~]# cat users.yml
  2. - hosts: webservers
  3. remote_user: root
  4. tasks:
  5. - name: add some groups
  6. group: name={{ item }} state=present
  7. loop:
  8. - group11
  9. - group12
  10. - group13
  11. - name: add some users
  12. user: name={{ item.name }} group={{ item.group }} state=present
  13. loop:
  14. - { name: 'user1',group: 'group11' }
  15. - { name: 'user2',group: 'group12' }
  16. - { name: 'user3',group: 'group13' }

八、角色(roles)

使用 roles 可以让我们按照功能角色为基准来划分。

默认 ansible 角色(roles)的存放位置在 /etc/ansible/roles 目录内,可以通过修改 ansible 配置文件进行修改:

  1. # additional paths to search for roles in, colon separated
  2. #roles_path = /etc/ansible/roles

以下是一个参考示例,我们就是按照功能进行划分,每个应用在roles下面都是一个独立的子目录;

  1. roles/
  2. mysql/
  3. nginx/
  4. httpd/
  5. tomcat/
  6. memcached/

每个角色,以特定的层级目录结构进行组织;例如:

  1. mysql/
  2. files/:存放由copyscript模块等调用的文件;
  3. templates/:template模块查找所需的模版文件目录;
  4. tasks/:至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含;
  5. handlers/:至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含;
  6. vars/:至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含;
  7. meta/:至少应该包含一个名为main.yml的文件;定义当前角色的特殊设定及其依赖关系;其它的文件需要在此文件中通过include进行包含;
  8. default/:设定默认变量时使用此目录中的main.yml文件;

上面这些目录并不是必须创建,用到哪个就创建哪个就可以。

1、角色调用方法

在 playbook中调用角色的方法1:

  1. - hosts: webservers
  2. remote_user: root
  3. roles:
  4. - mysql
  5. - memcached
  6. - nginx

在playbook中调用角色的方法2:传递变量给角色

  1. - hosts: webservers
  2. remote_user: root
  3. roles:
  4. - { role: nginx,username: nginx }
  5. role用于指定角色名称;后续的username: nginx用于传递变量给角色;
  6. 还可以基于条件测试实现角色调用:
  7. roles:
  8. - { role: nginx, when: ansible_distribution_major_version == '7' }
  9. 当系统版本为centos7时才执行nginx这个角色

九、Ansible template 模块遇到特殊字符处理问题

注意:如果推送的配置文件里含有特殊字符,如:”;” “#”等,是不能用Template模块直接推送的,因为这些不能被解析会报错,如下:

Ansible - 图1ansible template模块报错

使用jinja2的Escaping,把这些特殊字符转义,语法:“ … ”,参考:http://jinja.pocoo.org/docs/2.9/templates/#escaping

  1. sed -i '/^;/s/^;/{% raw %};/g' www.conf.j2
  2. sed -i '/^{% raw %}/s/$/{% endraw %}\n/g' www.conf.j2

Jinja2转义符:

  1. #被raw包含起来的部分被转义,不会被解析
  2. {% raw %}
  3. ;aaa
  4. #bbb
  5. {% endraw %}