一、基础介绍
1、简介
ansible是新出现的自动化运维工具,基于python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括。
(1)、连接插件connection plugins:负责和被监控端实现通信;
(2)、host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;
(3)、各种模块:核心模块、command模块、自定义模块;
(4)、借助于插件完成记录日志邮件等功能;
(5)、playbook:剧本执行多个任务时,非必须可以让节点一次性运行多个任务。
2、总体架构
3、特性
(1)、no agents:不需要在被管控主机上安装任何客户端;
(2)、no server:无服务器端,使用时直接运行命令即可;
(3)、modules in any languages:基于模块工作,可使用任意语言开发模块;
(4)、yaml,not code:使用yaml语言定制剧本playbook;
(5)、ssh by default:基于SSH工作;
(6)、strong multi-tier solution:可实现多级指挥;
4、优点
(1)、轻量级,无需在客户端安装agent,更新时,只需要在操作机上进行一次更新即可;
(2)、批量任务执行可以写成脚本,而且不用分发到远程就可以执行;
(3)、使用python编写,维护更简单,ruby语法过于复杂;
(4)、支持sudo.
5、任务执行流程
说明:
(1)、以上内容大多是基于他人分享的基础上总结而来,学习借鉴之用;
(2)、本次安装基于 CentOS 6.7 系统环境。
二、Ansible基础安装与配置
1、Ansible基础安装(编译或者rpm)
源码安装 1)、python2.7安装 # wget https://www.python.org/ftp/python/2.7.8/Python-2.7.8.tgz # tar xvzf Python-2.7.8.tgz # cd Python-2.7.8 # ./configure --prefix=/usr/local # make --jobs=`grep processor /proc/cpuinfo | wc -l` # make install ## 将python头文件拷贝到标准目录,以避免编译ansible时,找不到所需的头文件 # cd /usr/local/include/python2.7 # cp -a ./* /usr/local/include/ ## 备份旧版本的python,并符号链接新版本的python # cd /usr/bin # mv python python2.6 # ln -s /usr/local/bin/python ## 修改yum脚本,使其指向旧版本的python,已避免其无法运行 # vim /usr/bin/yum #!/usr/bin/python --> #!/usr/bin/python2.6 2)、setuptools模块安装 https://pypi.python.org/packages/source/s/setuptools/setuptools-7.0.tar.gz # tar xvzf setuptools-7.0.tar.gz # cd setuptools-7.0 # python setup.py install 3)、pycrypto模块安装 https://pypi.python.org/packages/source/p/pycrypto/pycrypto-2.6.1.tar.gz # tar xvzf pycrypto-2.6.1.tar.gz # cd pycrypto-2.6.1 # python setup.py install 4)、PyYAML模块安装 http://pyyaml.org/download/libyaml/yaml-0.1.5.tar.gz # tar xvzf yaml-0.1.5.tar.gz # cd yaml-0.1.5 # ./configure --prefix=/usr/local # make --jobs=`grep processor/proc/cpuinfo | wc -l` # make install https://pypi.python.org/packages/source/P/PyYAML/PyYAML-3.11.tar.gz # tar xvzf PyYAML-3.11.tar.gz # cd PyYAML-3.11 # python setup.py install 5)、Jinja2模块安装 https://pypi.python.org/packages/source/M/MarkupSafe/MarkupSafe-0.9.3.tar.gz # tar xvzf MarkupSafe-0.9.3.tar.gz # cd MarkupSafe-0.9.3 # python setup.py install https://pypi.python.org/packages/source/J/Jinja2/Jinja2-2.7.3.tar.gz # tar xvzf Jinja2-2.7.3.tar.gz # cd Jinja2-2.7.3 # python setup.py install 6)、paramiko模块安装 https://pypi.python.org/packages/source/e/ecdsa/ecdsa-0.11.tar.gz # tar xvzf ecdsa-0.11.tar.gz # cd ecdsa-0.11 # python setup.py install https://pypi.python.org/packages/source/p/paramiko/paramiko-1.15.1.tar.gz # tar xvzf paramiko-1.15.1.tar.gz # cd paramiko-1.15.1 # python setup.py install 7)、simplejson模块安装 https://pypi.python.org/packages/source/s/simplejson/simplejson-3.6.5.tar.gz # tar xvzf simplejson-3.6.5.tar.gz # cd simplejson-3.6.5 # python setup.py install 8)、ansible安装 https://github.com/ansible/ansible/archive/v1.7.2.tar.gz # tar xvzf ansible-1.7.2.tar.gz # cd ansible-1.7.2 # python setup.py install yum安装(依赖epel源) # wget http://mirrors.aliyun.com/epel/6/x86_64/epel-release-6-8.noarch.rpm # yum -y install ansible
2、Ansible配置
1)、SSH免密钥登录设置
服务器环境:
192.168.9.9:作为ansible管理节点
192.168.9.11:node1节点
192.168.9.12:node2节点
##修改/etc/hosts文件 # vim /etc/hosts 192.168.9.9 mail.bjwf125.com mail 192.168.9.11 node1.bjwf125.com node1 192.168.9.12 node2.bjwf125.com node2 ##生成公钥私钥 # ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Created directory ‘/root/.ssh‘. #创建目录 Enter passphrase (empty for no passphrase): #输入密码 Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: 00:3a:43:ef:40:da:b1:41:09:56:ea:91:28:6f:31:61 [email protected] The key‘s randomart image is: +--[ RSA 2048]----+ |.+Eo. | |o*+B . | |++X . . | |o..B . | | .o . S | | . | | | | | | | +-----------------+ [[email protected] ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub node1 The authenticity of host ‘node1 (192.168.9.11)‘ can‘t be established. RSA key fingerprint is 76:31:63:16:97:7a:6e:d8:73:5d:a0:fd:b6:c3:34:bd. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added ‘node1,192.168.9.11‘ (RSA) to the list of known hosts. [email protected]‘s password: Now try logging into the machine, with "ssh ‘node1‘", and check in: .ssh/authorized_keys to make sure we haven‘t added extra keys that you weren‘t expecting. [[email protected] ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub node2 The authenticity of host ‘node2 (192.168.9.12)‘ can‘t be established. RSA key fingerprint is 76:31:63:16:97:7a:6e:d8:73:5d:a0:fd:b6:c3:34:bd. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added ‘node2,192.168.9.12‘ (RSA) to the list of known hosts. [email protected]‘s password: Now try logging into the machine, with "ssh ‘node2‘", and check in: .ssh/authorized_keys to make sure we haven‘t added extra keys that you weren‘t expecting.
2)、ansible配置
[[email protected] ~]# cd /etc/ansible [[email protected] ansible]# ls ansible.cfg hosts roles [[email protected] ansible]# vim hosts [[email protected] ansible]# cp hosts{,.bak} [[email protected] ansible]# ls ansible.cfg hosts hosts.bak roles [[email protected] ansible]# vim hosts ##定义主机组 [webservers] ##主机组名,可以任意命令 node1 ##管理节点,可以是IP,也可以是主机名,我这定义的是主机名 node2
3)、简单测试
[[email protected] ansible]# ansible webservers -m command -a "date" node1 | success | rc=0 >> Thu Jan 14 09:50:38 HKT 2016 node2 | success | rc=0 >> Thu Jan 14 09:50:38 HKT 2016 ##运行成功 ansible命令应用基础: 语法:ansible <host-pattern> [-f forks] [-m module_name] [-a args] -f forks:启动的并发线程数; -m module_name:要使用的模块; -a args:模块特有的参数;
4)、ansible常用的模块
(1)、command模块:默认模块,用于在各被管理节点运行指定的命令; 相关选项如下: creates:一个文件名,当该文件存在,则该命令不执行 free_form:要执行的linux指令 chdir:在执行指令之前,先切换到该目录 removes:一个文件名,当该文件不存在,则该选项不执行 executable:切换shell来执行指令,该执行路径必须是一个绝对路径 [[email protected] ansible]# ansible webservers -m command -a ‘ifconfig eth0‘ node2 | success | rc=0 >> eth0 Link encap:Ethernet HWaddr 00:0C:29:A3:A6:AA inet addr:192.168.9.12 Bcast:192.168.11.255 Mask:255.255.252.0 inet6 addr: fe80::20c:29ff:fea3:a6aa/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:122795 errors:0 dropped:0 overruns:0 frame:0 TX packets:280 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:10895221 (10.3 MiB) TX bytes:27024 (26.3 KiB) node1 | success | rc=0 >> eth0 Link encap:Ethernet HWaddr 00:0C:29:20:16:2E inet addr:192.168.9.11 Bcast:192.168.11.255 Mask:255.255.252.0 inet6 addr: fe80::20c:29ff:fe20:162e/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:122812 errors:0 dropped:0 overruns:0 frame:0 TX packets:270 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:10897214 (10.3 MiB) TX bytes:26930 (26.2 KiB) (2)、user模块:用户模块,用于在各被管理节点管理用户所使用; [[email protected] ansible]# ansible webservers -m user -a ‘name=bjwf125‘ node2 | success >> { "changed": true, "comment": "", "createhome": true, "group": 500, "home": "/home/bjwf125", "name": "bjwf125", "shell": "/bin/bash", "state": "present", "system": false, "uid": 500 } node1 | success >> { "changed": true, "comment": "", "createhome": true, "group": 500, "home": "/home/bjwf125", "name": "bjwf125", "shell": "/bin/bash", "state": "present", "system": false, "uid": 500 } [[email protected] ~]# tail -1 /etc/passwd bjwf125:x:500:500::/home/bjwf125:/bin/bash (3)、group模块:用户组模块,用于在被各管理节点管理用户组所使用; [[email protected] ansible]# ansible webservers -m group -a ‘name=mysql gid=306‘ node2 | success >> { "changed": true, "gid": 306, "name": "mysql", "state": "present", "system": false } node1 | success >> { "changed": true, "gid": 306, "name": "mysql", "state": "present", "system": false } [[email protected] ~]# grep mysql /etc/group mysql:x:306: [[email protected] ~]# tail -1 /etc/gshadow mysql:!:: [[email protected] ~]# tail -1 /etc/group #多种方法查看结果(个人为了增强记忆) (4)、cron模块:计划任务模块,用户在各被管理节点管理计划任务; [[email protected] ansible]# ansible webservers -m cron -a "name=time minute=‘*/2‘ job=‘/usr/sbin/ntpdate 10.0.1.200‘" node1 | success >> { "changed": true, "jobs": [ "time" ] } node2 | success >> { "changed": true, "jobs": [ "time" ] } [[email protected] ~]# crontab -l #在被管理节点查看cron任务 */5 * * * * /sbin/hwclock -s #Ansible: time */2 * * * * /usr/sbin/ntpdate 10.0.1.200 移除cron [[email protected] ~]# ansible webservers -m cron -a "name=time minute=‘*/2‘ job=‘/usr/sbin/ntpdate 10.0.1.200‘ state=absent" node1 | success >> { "changed": false, "jobs": [] } node2 | success >> { "changed": false, "jobs": [] } [[email protected] ~]# crontab -l #在被管理节点查看cron任务 */5 * * * * /sbin/hwclock -s (5)、copy模块:复制模块,复制文件至各管理节点: ###这里需要注意的事,必须把各节点的selinux给关闭了,不然会失败的。 相关选项如下: backup:在覆盖之前,将源文件备份,备份文件包含时间信息。有两个选项:yes|no content:用于替代“src”,可以直接设定指定文件的值 dest:必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径 也必须是个目录 directory_mode:递归设定目录的权限,默认为系统默认权限 force:如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只 有当目标主机的目标位置不存在该文件时,才复制。默认为yes others:所有的file模块里的选项都可以在这里使用 src:被复制到远程主机的本地文件,可以是绝对路径,也可以是相对路径。如果路径是一个目录 ,它将递归复制。在这种情况下,如果路径使用“/”来结尾,则只复制目录里的内容,如果没有 使用“/”来结尾,则包含目录在内的整个内容全部复制,类似于rsync。 [[email protected] ~]# ansible all -m copy -a ‘src=/etc/fstab dest=/tmp/fstab.ansible mode=654‘ node2 | success >> { "changed": true, "checksum": "677ecf6a60822701d7d32e8722d22222be85c6ce", "dest": "/tmp/fstab.ansible", "gid": 0, "group": "root", "md5sum": "e784c8bb3dde9df0e8248941def7ac7f", "mode": "0654", "owner": "root", "size": 805, "src": "/root/.ansible/tmp/ansible-tmp-1452739223.25-249168597668683/source", "state": "file", "uid": 0 } node1 | success >> { "changed": true, "checksum": "677ecf6a60822701d7d32e8722d22222be85c6ce", "dest": "/tmp/fstab.ansible", "gid": 0, "group": "root", "md5sum": "e784c8bb3dde9df0e8248941def7ac7f", "mode": "0654", "owner": "root", "size": 805, "src": "/root/.ansible/tmp/ansible-tmp-1452739223.24-124628130207594/source", "state": "file", "uid": 0 } [[email protected] tmp]# ll -rw-r-xr-- 1 root root 805 Jan 14 10:40 fstab.ansible (6)、file模块:文件模块,修改各节点指定的文件属性; file模块的相关选项: force:需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况 下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个 选项:yes|no group:定义文件/目录的属组 mode:定义文件/目录的权限 owner:定义文件/目录的属主 path:必选项,定义文件/目录的路径 recurse:递归设置文件的属性,只对目录有效 src:被链接的源文件路径,只应用于state=link的情况 dest:被链接到的路径,只应用于state=link的情况 state: directory:如果目录不存在,就创建目录 file:即使文件不存在,也不会被创建 link:创建软链接 hard:创建硬链接 touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新 其最后修改时间 absent:删除目录、文件或者取消链接文件 [[email protected] ~]# ansible all -m file -a ‘path=/tmp/fstab.ansible mode=600 owner=bjwf125‘ node2 | success >> { "changed": true, "gid": 0, "group": "root", "mode": "0600", "owner": "bjwf125", "path": "/tmp/fstab.ansible", "size": 805, "state": "file", "uid": 500 } node1 | success >> { "changed": true, "gid": 0, "group": "root", "mode": "0600", "owner": "bjwf125", "path": "/tmp/fstab.ansible", "size": 805, "state": "file", "uid": 500 } #注:path:指定节点文件路径 mode:指定权限 owner:指定属主 [[email protected] tmp]# ll -rw------- 1 bjwf125 root 805 Jan 14 10:40 fstab.ansible (7)、ping模块:测试模块,测试各个被管理节点是否在线; [[email protected] ~]# ansible all -m ping node2 | success >> { "changed": false, "ping": "pong" } node1 | success >> { "changed": false, "ping": "pong" } (8)、service模块:管理各个节点的服务 [[email protected] ~]# ansible all -m service -a ‘name=ntpd enabled=true‘ node1 | success >> { "changed": true, "enabled": true, "name": "ntpd" } node2 | success >> { "changed": true, "enabled": true, "name": "ntpd" } (9)、shell模块:与command模块功能相同,但比command的模块功能更加强大 [[email protected] ~]# ansible all -m shell -a ‘cat /etc/group | grep mysql‘ node1 | success | rc=0 >> mysql:x:306: node2 | success | rc=0 >> mysql:x:306: (10)、script模块:自动复制脚本至各节点,并运行之 [[email protected] ~]# cat ansible.sh #!/bin/bash # echo "welcome to mylinux." > /tmp/mylinux [[email protected] ~]# ansible all -m script -a ‘/root/ansible.sh‘ node2 | success >> { "changed": true, "rc": 0, "stderr": "", "stdout": "" } node1 | success >> { "changed": true, "rc": 0, "stderr": "", "stdout": "" } [[email protected] tmp]# cat mylinux welcome to mylinux. (11)、setup模块:收集ansible的facters [[email protected] ~]# ansible all -m setup node1 | success >> { #用来查看远程主机的一些基本信息(很强大,感觉超出“基本”了) "ansible_facts": { "ansible_all_ipv4_addresses": [ "192.168.9.11" ], "ansible_all_ipv6_addresses": [ "fe80::20c:29ff:fe20:162e" ], "ansible_architecture": "x86_64", "ansible_bios_date": "07/02/2015", "ansible_bios_version": "6.00", "ansible_cmdline": { "KEYBOARDTYPE": "pc", "KEYTABLE": "us", "LANG": "en_US.UTF-8", "SYSFONT": "latarcyrheb-sun16", "quiet": true, "rd_NO_DM": true, "rd_NO_LUKS": true, "rd_NO_LVM": true, "rd_NO_MD": true, "rhgb": true, "ro": true, "root": "UUID=a4588fdb-b266-4f99-b5d5-013149014d55" }, "ansible_date_time": { "date": "2016-01-14", "day": "14", "epoch": "1452741270", "hour": "11", "iso8601": "2016-01-14T03:14:30Z", "iso8601_micro": "2016-01-14T03:14:30.591778Z", "minute": "14", "month": "01", "second": "30", "time": "11:14:30", "tz": "HKT", "tz_offset": "+0800", "weekday": "Thursday", "year": "2016" }, (12)、yum模块:用于在各个管理节点安装软件所使用 [[email protected] ~]# ansible all -m yum -a ‘name=httpd state=present‘ node1 | success >> { "changed": false, "msg": "", "rc": 0, "results": [ "httpd-2.2.15-47.el6.centos.1.x86_64 providing httpd is already installed" ] } node2 | success >> { "changed": false, "msg": "", "rc": 0, "results": [ "httpd-2.2.15-47.el6.centos.1.x86_64 providing httpd is already installed" ] } [[email protected] tmp]# rpm -q httpd httpd-2.2.15-47.el6.centos.1.x86_64 (13)、更多模块 其他常用模块,比如synchronize、acl就不再一一列举了,可以结合自身所需要的系统环境来进行测试。 ##更多模块可以参考: [[email protected] ~]# ansible-doc -l Homepage: http://www.greenwoodsoftware.com/less a10_server Manage A10 Networks AX/SoftAX/Thunder/vThunder devices a10_service_group Manage A10 Networks AX/SoftAX/Thunder/vThunder devices a10_virtual_server Manage A10 Networks AX/SoftAX/Thunder/vThunder devices acl Sets and retrieves file ACL information. add_host add a host (and alternatively a group) to the ansible-playbook in... airbrake_deployment Notify airbrake about app deployments alternatives Manages alternative programs for common commands apache2_module enables/disables a module of the Apache2 webserver apt Manages apt-packages apt_key Add or remove an apt key apt_repository Add and remove APT repositories apt_rpm apt_rpm package manager assemble Assembles a configuration file from fragments assert Fail with custom message at Schedule the execution of a command or script file via the at com... authorized_key Adds or removes an SSH authorized key azure create or terminate a virtual machine in azure bigip_facts Collect facts from F5 BIG-IP devices bigip_monitor_http Manages F5 BIG-IP LTM http monitors bigip_monitor_tcp Manages F5 BIG-IP LTM tcp monitors bigip_node Manages F5 BIG-IP LTM nodes bigip_pool Manages F5 BIG-IP LTM pools bigip_pool_member Manages F5 BIG-IP LTM pool members bigpanda Notify BigPanda about deployments ##或者一些网址: http://docs.ansible.com/modules_by_category.html
三、一些概念补充
playbook的组成:playbook是由一个或多个“play”组成的列表,可以让它们联同起来按事先编排的机制执行;所谓task无非是调用ansible的一个module,而在模块参数中可以使用变量;模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致;
执行模型:task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。在顺序运行某playbook时,如果中途发生错误,所有已执行任务都将回滚,因此,在修改playbook后重新执行一次即可;
task组成:每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出;
notify指定handler的执行机制:“notify”这个action可用于在每个play的最后被触发,在notify中列出的操作称为handler,仅在所有的变化发生完成后一次性地执行指定操作。
四、ansible使用帮助
ansible-doc -l ##列出ansible的所有模块 ansible-doc -s module name ##查看模块的属性信息 [[email protected] ~]# ansible-doc -s yum ##查看yum模块的属性信息 less 436 Copyright (C) 1984-2009 Mark Nudelman less comes with NO WARRANTY, to the extent permitted by law. For information about the terms of redistribution, see the file named README in the less distribution. Homepage: http://www.greenwoodsoftware.com/less - name: M a n a g e s p a c k a g e s w i t h t h e I ( y u m ) p a c k a g e m a n a g e r action: yum conf_file # The remote yum configuration file to use for the transaction. disable_gpg_check # Whether to disable the GPG checking of signatures of packages being installed. Has an effect only if state is `present‘ or `latest‘. disablerepo # `Repoid‘ of repositories to disable for the install/update operation. These repos will not persist beyond the transaction. When specifying mu enablerepo # `Repoid‘ of repositories to enable for the install/update operation. These repos will not persist beyond the transaction. When specifying mul list # Various (non-idempotent) commands for usage with `/usr/bin/ansible‘ and `not‘ playbooks. See examples. name= # Package name, or package specifier with version, like `name-1.0‘. When using state=latest, this can be ‘*‘ which means run: yum -y update. Yo state # Whether to install (`present‘, `latest‘), or remove (`absent‘) a package. update_cache # Force updating the cache. Has an effect only if state is `present‘ or `latest‘.