什么是Ansible

ansible是新出现的运维工具是基于Python研发的糅合了众多老牌运维工具的优点实现了批量操作系统配置、批量程序的部署、批量运行命令等功能。

Ansible特性

基于Python语言实现,由Paramiko, PyYAML和Jinjia2三个关键模块;

ansible是工作在agentless模式下具有幂等性。ansible在控制端只需要告诉监控端的期望状态就可以实现批量部署。

默认使用SSH协议;

    (1) 基于密钥认证;

    (2) 在inventory文件中指定账号和密码;

基于“模块”完成各种“任务”

支持自定义模块:支持各种编程语言

可以使用YAML语言定制playbook

Ansible架构图

Ansible核心组件说明:

Ansible:Ansible的核心程序

Host Lnventory:记录了每一个由Ansible管理的主机信息,信息包括ssh端口,root帐号密码,ip地址等等。

Playbooks:YAML格式文件,多个任务定义在一个文件中,使用时可以统一调用

Core Modules:Ansible执行任何管理任务都不是由Ansible自己完成,而是由核心模块完成;Ansible管理主机之前,先调用core Modules中的模块,然后指明管理Host Lnventory中的主机,就可以完成管理主机。

Custom Modules:自定义模块,完成Ansible核心模块无法完成的功能

Connection Plugins:连接插件,Ansible和Host通信使用

环境拓扑图

安装Ansible

Ansible在epel的yum中有提供,所以配置好epel源,直接使用yum命令安装即可

[root@node1 ~]# yum -y install ansible

查看生成的主要文件

[root@node1 ~]# rpm -ql ansible/etc/ansible/ansible.cfg   #主配置文件/etc/ansible/hosts           #invertory文件

说明:Ansible不是服务,所以不需要服务脚本

配置和被管理的主机直接建立基于ssh的密钥认证

ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ''ssh-copy-id -i .ssh/id_rsa.pub 172.16.4.101ssh-copy-id -i .ssh/id_rsa.pub 172.16.4.102ssh-copy-id -i .ssh/id_rsa.pub 172.16.4.103

定义主机,将所有被管理的主机加入到/etc/ansible/hosts中,否则无法管理

[root@node1 ~]# vim /etc/ansible/hosts[webserver]       #定义一个组172.16.4.101172.16.4.102[dbserver]172.16.4.103

补充:如果没有设置基于ssh的密钥认证,可以在hosts文件中直接指定帐号和密码,方法如下所示:

[webserver]172.16.4.101 ansible_ssh_user=root ansible_ssh_pass=password172.16.4.102 ansible_ssh_user=root ansible_ssh_pass=password[dbserver]172.16.4.103 ansible_ssh_user=root ansible_ssh_pass=password

模块使用:

如何查看模块帮助:

   ansible-doc -l          #查看所有模块

    ansible-doc -s MODULE_NAME       #查看指定模块的详细帮助

ansible命令应用基础:

语法: ansible <host-pattern> [-f forks] [-m module_name] [-a args]

     -f forks:启动的并发线程数;

      -m module_name: 要使用的模块;

      -a args: 模块特有的参数;

常见模块说明:

Command

功能:命令模块,默认模块,用于在远程主机执行命令,缺点:运行的命令中无法使用变量,管道。

[root@node1 ~]# ansible-doc -s command- name: 在远程节点执行命令action: commandchdir           # 在执行命令之前,先切换到该目录creates         # 一个文件名,当这个文件存在,则该命令不执行executable      # 切换shell来执行命令,需要使用命令的绝对路径free_form=      #要执行的Linux指令,一般使用Ansible的-a参数代替。removes         #一个文件名,这个文件不存在,则该命令不执行

示例:查看被管理节点的时间,使用-m使用command模块,-a使用date命令即可

Cron

[root@node1 ~]# ansible-doc -s cron- name: 设置管理节点生成定时任务action: cronbackup             # 如果设置,创建一个crontab备份cron_file          #如果指定, 使用这个文件cron.d,而不是单个用户crontabday                # 日应该运行的工作( 1-31, *, */2, etc )hour               # 小时 ( 0-23, *, */2, etc )job                #指明运行的命令是什么minute             #分钟( 0-59, *, */2, etc )month              # 月( 1-12, *, */2, etc )name               #定时任务描述reboot             # 任务在重启时运行,不建议使用,建议使用special_timespecial_time       # 特殊的时间范围,参数:reboot(重启时),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小时)state              #指定状态,prsent表示添加定时任务,也是默认设置,absent表示删除定时任务user               # 以哪个用户的身份执行weekday            # 周 ( 0-6 for Sunday-Saturday, *, etc )

示例:设置webServer组的主机没10分钟运行一次hello world

删除定时任务的方法如下所示:只需要设置state为absent即可

User

[root@node1 ~]# ansible-doc -s user- name: 管理用户帐号action: usercomment          # 用户的描述信息createhome       # 是否创建家目录force            # 在使用`state=absent'是, 行为与`userdel --force'一致.group            # 指定基本组groups           # 指定附加组,如果指定为('groups=')表示删除所有组home             # 指定用户家目录login_class      #可以设置用户的登录类 FreeBSD, OpenBSD and NetBSD系统.move_home        # 如果设置为`home='时, 试图将用户主目录移动到指定的目录name=            # 指定用户名non_unique       # 该选项允许改变非唯一的用户ID值password         # 指定用户密码remove           # 在使用 `state=absent'时, 行为是与 `userdel --remove'一致.shell            # 指定默认shellstate            #设置帐号状态,不指定为创建,指定值为absent表示删除system           # 当创建一个用户,设置这个用户是系统用户。这个设置不能更改现有用户。uid              #指定用户的uidupdate_password  # 更新用户密码

示例:创建一个用户

删除用户

Group

[root@node1 ~]# ansible-doc -s group- name: 添加或删除组action: groupgid       # 设置组的GID号name=     # 管理组的名称state     # 指定组状态,默认为创建,设置值为absent为删除system    # 设置值为yes,表示为创建系统组

示例:创建一个mysql组,并添加mysql用户加入到组中

Copy

[root@node1 ~]# ansible-doc -s copy- name: 将文件复制到被管理主机action: copybackup          # 创建一个备份文件包括时间戳信息,如果以某种方式重创错了,还可以拿回原始文件content         # 取代src=,表示直接用此处指定的信息生成为目标文件内容;dest=           # 远程节点存放文件的路径,必须是绝对路径directory_mode  # 递归复制设置目录权限,默认为系统默认权限force           # 如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果设置为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yesgroup           # 复制到远程主机后,指定文件或目录的属mode            # 复制到远程主机后,指定文件或目录权限,类似与 `chmod'指明如 0644owner           # 复制到远程主机后,指定文件或目录属主src             # 指定复制的源文件,可以是相对路径或者绝对路径,如果给出的源是目录,那么会把目录下的所有文件都复制过去

示例:将本地的/etc/fatab文件复制到目标主机的/tmp/fatab.ansbile,属主为root权限为640

验证:webserver组中的主机/tmp/目录下已经出现fstab.ansbile文件,属主和权限都正确

[root@node2 ~]# ll /tmp/fstab.ansbile-rw-r----- 1 root root 921 Jun 28 14:16 /tmp/fstab.ansbile

示例:在webserver组主机创建文件,自己手动指定文件内容。

验证:查看文件内容

[root@node2 ~]# cat /tmp/test.ansibleHello AnsibleHello world[root@node2 ~]#

File

[root@node1 ~]# ansible-doc -s file- name: 设置文件属性action: fileforce          # 需要在两种情况下强制创建软连接,一种是源文件不存在但之后会建立的情况下;另一种是目标连接已存在,需要先取消之前的软连接,有两个选项:yes|nogroup          # 设置文件或目录的属组mode           # 设置文件或目录的权限owner          # 设置文件或目录的属主path=          # 必选项,定义文件或目录的路径recurse        # 递归设置文件的属性,只对目录有效src            # 要被链接到的路径,只应用与state=link的情况state          # directory:如果目录不存在,创建目录;file:即使文件不存在,也不会被创建;link:创建软连接;hard:创建硬连接;touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间;absent:删除目录、文件或者取消链接文件

示例:设置/tmp/fstab.ansbile属主和属组都为mysql,权限为644

示例:在webserver组创建/test/fstab.ansible的连接文件

Ping

功能:测试指定主机是否能连接,如果成功返回pong。

Service

[root@node1 ~]# ansible-doc -s service- name: 管理服务action: servicearguments     # 向服务传递的命令行参数enabled       # 设置服务开机自动启动,参数为yes|noname=         # 控制服务的名称pattern       # 定义一个模式,如果通过status指令来查看服务的状态时,没有响应,就会通过ps指令在进程中根据该模式进行查找,如果匹配到,则认为该服务依然在运行runlevel      # 设置服务自启动级别sleep         # 如果执行了restarted,则在stop和start之间沉睡几秒钟state         # 启动`started' 关闭`stopped' 重新启动 `restarted' 重载 `reloaded'

查看httpd服务器信息:开机为不启动,当前状态为关闭

示例:启动httpd服务,并设置开机自动启动

Shell

功能:执行的命令中有管道或者变量,就需要使用shell

[root@node1 ~]# ansible-doc -s shell- name: Execute commands in nodes.action: shellchdir       # 执行之前,先cd到指定目录在执行命令creates     # 一个文件名,当这个文件存在,则该命令不执行executable  # 切换shell来执行命令,需要使用命令的绝对路径free_form=  # 执行的命令removes     # 一个文件名,这个文件不存在,则该命令不执行

示例:为user1用户设置密码

Script

[root@node1 ~]# ansible-doc -s script- name: 将本地脚本复制到远程主机并运行之action: scriptcreates      # 一个文件名,当这个文件存在,则该命令不执行free_form=   # 本地脚本路径removes      # 一个文件名,这个文件不存在,则该命令不执行

示例:将本机的test.sh脚本在被管理主机运行

验证:

[root@node2 ~]# ll /tmp/script.ansible-rw-r--r-- 1 root root 26 Jun 28 15:21 /tmp/script.ansible[root@node2 ~]# cat /tmp/script.ansiblehello ansible from script

yum

[root@node1 ~]# ansible-doc -s yum- name: Manages packages with the `yum' package manageraction: yumconf_file          # yum的配置文件disable_gpg_check  # 关闭gpg_checkdisablerepo        # 不启用某个源enablerepo         # 启用某个源name=              # 指定要安装的包,如果有多个版本需要指定版本,否则安装最新的包state              # 安装(`present'),安装最新版(`latest'),卸载程序包(`absent')

示例:安装zsh程序包

setup:

收集远程主机的facts

每个被管理节点在接收并运行管理命令之前,会将自己主机相关信息,如操作系统版本、IP地址等报告给远程的ansbile主机;

示例:查看172.16.4.101主机状态信息,输出内容很多,但是通俗易懂,这里不做过多说明

[root@node1 ~]# ansible 172.16.4.101 -m setup172.16.4.101 | success >> {"ansible_facts": {"ansible_all_ipv4_addresses": ["172.16.4.101"],"ansible_all_ipv6_addresses": ["fe80::20c:29ff:fef1:ddb2"],"ansible_architecture": "x86_64","ansible_bios_date": "05/20/2014","ansible_bios_version": "6.00","ansible_cmdline": {"KEYBOARDTYPE": "pc","KEYTABLE": "us","LANG": "en_US.UTF-8","SYSFONT": "latarcyrheb-sun16","crashkernel": "auto","quiet": true,"rd_LVM_LV": "vg0/root","rd_NO_DM": true,"rd_NO_LUKS": true,"rd_NO_MD": true,"rhgb": true,"ro": true,"root": "/dev/mapper/vg0-root"},"ansible_date_time": {"date": "2015-06-28","day": "28","epoch": "1435476945","hour": "15","iso8601": "2015-06-28T07:35:45Z","iso8601_micro": "2015-06-28T07:35:45.390263Z","minute": "35","month": "06","second": "45","time": "15:35:45","tz": "CST","tz_offset": "+0800","weekday": "Sunday","year": "2015"},"ansible_default_ipv4": {"address": "172.16.4.101","alias": "eth0","gateway": "172.16.0.1","interface": "eth0","macaddress": "00:0c:29:f1:dd:b2","mtu": 1500,"netmask": "255.255.0.0","network": "172.16.0.0","type": "ether"},"ansible_default_ipv6": {},"ansible_devices": {"sda": {"holders": [],"host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)","model": "VMware Virtual S","partitions": {"sda1": {"sectors": "409600","sectorsize": 512,"size": "200.00 MB","start": "2048"},"sda2": {"sectors": "125829120","sectorsize": 512,"size": "60.00 GB","start": "411648"}},"removable": "0","rotational": "1","scheduler_mode": "cfq","sectors": "377487360","sectorsize": "512","size": "180.00 GB","support_discard": "0","vendor": "VMware,"},"sr0": {"holders": [],"host": "IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)","model": "VMware IDE CDR10","partitions": {},"removable": "1","rotational": "1","scheduler_mode": "cfq","sectors": "2097151","sectorsize": "512","size": "1024.00 MB","support_discard": "0","vendor": "NECVMWar"}},"ansible_distribution": "CentOS","ansible_distribution_major_version": "6","ansible_distribution_release": "Final","ansible_distribution_version": "6.6","ansible_domain": "","ansible_env": {"CVS_RSH": "ssh","G_BROKEN_FILENAMES": "1","HOME": "/root","LANG": "C","LC_CTYPE": "C","LESSOPEN": "||/usr/bin/lesspipe.sh %s","LOGNAME": "root","MAIL": "/var/mail/root","PATH": "/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin","PWD": "/root","QTDIR": "/usr/lib64/qt-3.3","QTINC": "/usr/lib64/qt-3.3/include","QTLIB": "/usr/lib64/qt-3.3/lib","SHELL": "/bin/bash","SHLVL": "2","SSH_ASKPASS": "/usr/libexec/openssh/gnome-ssh-askpass","SSH_CLIENT": "172.16.4.100 60862 22","SSH_CONNECTION": "172.16.4.100 60862 172.16.4.101 22","SSH_TTY": "/dev/pts/0","TERM": "linux","USER": "root","_": "/usr/bin/python"},"ansible_eth0": {"active": true,"device": "eth0","ipv4": {"address": "172.16.4.101","netmask": "255.255.0.0","network": "172.16.0.0"},"ipv6": [{"address": "fe80::20c:29ff:fef1:ddb2","prefix": "64","scope": "link"}],"macaddress": "00:0c:29:f1:dd:b2","module": "e1000","mtu": 1500,"promisc": false,"type": "ether"},"ansible_form_factor": "Other","ansible_fqdn": "node2","ansible_hostname": "node2","ansible_interfaces": ["lo","eth0"],"ansible_kernel": "2.6.32-504.el6.x86_64","ansible_lo": {"active": true,"device": "lo","ipv4": {"address": "127.0.0.1","netmask": "255.0.0.0","network": "127.0.0.0"},"ipv6": [{"address": "::1","prefix": "128","scope": "host"}],"mtu": 65536,"promisc": false,"type": "loopback"},"ansible_lsb": {"codename": "Final","description": "CentOS release 6.6 (Final)","id": "CentOS","major_release": "6","release": "6.6"},"ansible_machine": "x86_64","ansible_memfree_mb": 68,"ansible_memtotal_mb": 474,"ansible_mounts": [{"device": "/dev/mapper/vg0-root","fstype": "ext4","mount": "/","options": "rw","size_available": 19614814208,"size_total": 21003628544},{"device": "/dev/sda1","fstype": "ext4","mount": "/boot","options": "rw","size_available": 159812608,"size_total": 198902784},{"device": "/dev/mapper/vg0-usr","fstype": "ext4","mount": "/usr","options": "rw","size_available": 7437721600,"size_total": 10434699264},{"device": "/dev/mapper/vg0-var","fstype": "ext4","mount": "/var","options": "rw","size_available": 19657154560,"size_total": 21003628544}],"ansible_nodename": "node2","ansible_os_family": "RedHat","ansible_pkg_mgr": "yum","ansible_processor": ["Intel(R) Core(TM) i5-4200M CPU @ 2.50GHz"],"ansible_processor_cores": 1,"ansible_processor_count": 1,"ansible_processor_threads_per_core": 1,"ansible_processor_vcpus": 1,"ansible_product_name": "VMware Virtual Platform","ansible_product_serial": "VMware-56 4d cf 50 b9 67 e1 67-fd ba 73 89 3c f1 dd b2","ansible_product_uuid": "564DCF50-B967-E167-FDBA-73893CF1DDB2","ansible_product_version": "None","ansible_python_version": "2.6.6","ansible_selinux": {"status": "disabled"},"ansible_ssh_host_key_dsa_public": "AAAAB3NzaC1kc3MAAACBAJX6mCvtR/7SlWAQtqoJ7fGcOnCQUif9z8BNlTf8Zh0WadsNAOOm6bq48O8FKAuuUl+PDQdvfJteGSb0maqdzBL1A5BaOCIBFLAdcubrSPm9BjBu37M9Dd0/rGzeLmNRpKuEf0VpmJ0QJvp36iDnDsUCtekjrYlhhwcauJUSVqvxAAAAFQDVMMCA/SHSLd8bskYGRZztoVDHewAAAIB16IbxqPLWALteNs8HmFkk2+m43LQ8xJhzAoUB/rBYclWs0W8HHKF98p91rYfwVfitLIZ+S2gFEYxrMrMyRlJNpeChDDeEVZoMyhBeo8Y9PXd4eQCl+FJ2ZQJ31lC0EEB6T+zwdKuP5dQfCaJ7wVNr87UQuQf7t8My3GHkN7ErSAAAAIEAhPngSDosZGPofwHzNJG+dDITWQEJ7cI0tpYJUum0xREDnkYuWUhjI5soR4jotfToUeTwLRxRZMJXA7dCE6NtHJicEbhxiSXHYQUNhQvvrE0/MEvH/BChJK0Nqqt/RxpFNMF2yN5lJPYdufSKd92rgYEMIzELuh21GL6c4iGJWyM=","ansible_ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAABIwAAAQEA57ZIETHEsImga9O6N6pHClC6vXfhK01/odan1OdlZnCGTSx3J/fhvNxRidj6YwTb91lahWRRZHOx6EuQ35O4Ba/YVdOF/eF47i/tFNHuo5eEXj2n6fV1mHS97rBc2P+o+2TwL0Ezo9ifXjQPyUHRcCir0abh/if7m/DNfxofY0trW0MKKlA9Ig3CuKrg1k5DUD2HYTS2bbWXDppDG2hpXa6DgxiFO6iLWysR9rw6kY5Aj8WusUpLd2aDkolfIV4zHn2TF6tLP0c1pF2z3u7F5IjOg7aqbEfubmI7mU2d6VPVbxsAakvBNGXoClwt8Skxki1U4u4KXSZ8s/Vq75nRIQ==","ansible_swapfree_mb": 2047,"ansible_swaptotal_mb": 2047,"ansible_system": "Linux","ansible_system_vendor": "VMware, Inc.","ansible_user_id": "root","ansible_userspace_architecture": "x86_64","ansible_userspace_bits": "64","ansible_virtualization_role": "guest","ansible_virtualization_type": "VMware","module_setup": true},"changed": false}

补充:

Ansible的跟多功能,如playbook,roles详见下文:

http://ximenfeibing.blog.51cto.com/8809812/1669188