Ansible是一款为类Unix系统开发的自由开源的配置和自动化工具。它用Python写成,类似于Chef和Puppet,但是有一个不同和优点是我们不需要在节点中安装任何客户端。它使用SSH来和节点进行通信。

    之前也在网上找了一些RHEL6的配置文档,基本都是编译安装有点麻烦,还得注意python版本小于3.x,如果用RHEL7\CENTOS7的话只要先安装好epel7的源,下面都是自动依赖安装的超方便,所以强烈推荐用RHEL7\CENTOS7安装。

如果硬要编译安装可访问主页:https://github.com/ansible/ansible

playbook虽然很实用但目前用的不多,故不做详细记录,参考:http://www.361way.com/ansible-playbook-example/4441.html

root用户无法登陆,普通用户登录后su过去遇到的问题,参考:http://www.361way.com/ansible-su/4882.html 


本篇中我们将在RHEL 7上安装并配置Ansible,并且尝试管理两个节点

服务端:192.168.180.99

客户端:192.168.180.97\98

一、设置EPEL仓库

Ansible仓库默认不在yum仓库中,因此我们需要使用下面的命令启用epel仓库。

rpm -iUvh http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-8.noarch.rpm

二、yum安装ansible

yum install  ansible
ansible --version #没错的话就是最新版的2.2

三、设置ssh鉴权

    其实很简单就是ansible服务端生成rsa的key给到客户端,这样服务端就可以不用输入密码直接登录客户端了,是不是很方便!

#默认不设置加密密码,目录~/.ssh/id_rsa.pub
ssh-keygen -i rsa -P ''    
#该命令会自动给服务端key添加到客户端的~/.ssh/authorized_keys中
ssh-copy-id -id root@192.168.180.97\97

四、ansible节点清单

1、给服务端ansible定义节点清单

vim /etc/ansible/hosts
[test]
#这里用域名、主机名、IP都可以
192.168.180.97
192.168.180.98
[other]
#起个别名
jumper ansible_ssh_port = 5555 ansible_ssh_host = 192.168.1.50
#定了从web1到web50,webservers组共计50台主机
www[01:50].361way.com
#databases组有db-a到db-f共6台主机
db-[a:f].91it.org

2、使用主机变量

以下是Hosts部分中经常用到的变量部分

ansible_ssh_host # 要连接的主机名
ansible_ssh_port # 端口号默认是22
ansible_ssh_user # ssh连接时默认使用的用户名
ansible_ssh_pass # ssh连接时的密码
ansible_sudo_pass # 使用sudo连接用户是的密码
ansible_ssh_private_key_file # 秘钥文件如果不想使用ssh-agent管理时可以使用此选项
ansible_shell_type # shell的类型默认sh
ansible_connection # SSH 连接的类型: local , ssh , paramiko在 ansible 1.2 之前默认是 paramiko ,后来智能选择,优先使用基于 ControlPersist 的 ssh (支持的前提)
ansible_python _ interpreter #用来指定 python 解释器的路径,同样可以指定ruby 、perl 的路径

示例如下:

[test1]
10.212.52.252 ansible_ssh_user=root ansible_ssh_pass='361way.com'
10.212.52.14 ansible_ssh_user=test1 ansible_ssh_pass='91it.org'
10.212.52.16 ansible_ssh_user=test2 ansible_ssh_port=7788 ansible_ssh_pass='123456'

3、组内变量

变量也可以通过组名,应用到组内的所有成员:

[test]
host1
host2
[test:vars]
ntp_server=ntp.aaa.com
proxy=proxy.bbb.com

上面test组中包含两台主机,通过对test组指定vars变更,相应的host1和host2相当于相应的指定了ntp_server和proxy变量参数值 。

4、组的包含与组内变量
[hangzhou]
host1
host2
[jiaxing]
host2
host3
[zhejiang:children]
hangzhou
jiaxing
[zhejiang:vars]
some_server=foo.southeast.example.com
halon_system_timeout=30
self_destruct_countdown=60
escape_pods=2
[china:children]
zhejiang
henan
shandong
hebei

如上面的示例中,我指定了杭州组我有host1、hosts2;嘉兴组我有host3、host4主机;我又指定了一个组浙江组,同时包含杭州和嘉兴;同时为该组内的所有主机指定了四个vars变量。后面我又设定了一个组中国组,包含浙江、河南、山东、河北。

注:由于vars变量在ansible ad-hoc部分中基本用不到,主要用在ansible-playbook中,后面的章节部分也会提到。

五、ansible常用功能

更多更详细的话参考:http://www.361way.com/ansible-modules/4415.html

1、ping模块:看到ping字段为pong即为通,该功能主要用于批量检测连通性

ansible -m ping test

2、执行shell命令的command默认模块,用于远程执行命令,不支持变量,例子:

#查看当前用户
ansible -m command -a 'w' test
#查看日期
ansible -m command -a 'date' test
#给节点增加用户
ansible -m command -a 'useradd mark' test
ansible -m command -a 'grep mark /etc/passwd' test
#重定向输出到文件
ansible -m command -a 'df -Th' test > /root/test.log

3、cron定时任务,例子:

ansible test -m cron -a 'minute="*/1" job="/bin/echo "hell"" name="test job" '
#查看是否成功,另外注意:这里既然生成了,就立即生效,不用重启crond进程
ansible test -m command -a 'crontab -l'

4、user管理,例子:

ansible test -m user -a 'name=mark'
#查看是否成功,现在不明白和command useradd添加有什么区别,但是既然有用户管理还是用它好了
ansible -m command -a 'grep mark /etc/passwd' test

5、远程复制模块copy,例子:

#如果要想远程复制文件成功,必须给所有客户端安装这个。。。不知道为什么,如果不装复制失败报错
ansible -m command -a 'yum install libselinux-python -y' 'test
ansible -m copy -a 'src=/root/VMwareTools-9.4.10-2068191.tar.gz dest=/root owner=root mode=640' 'test'
#往远程主机文件写入内容:使用content代替src
ansible -m copy -a 'content="aaabbb\n" dest=/root/test.log' test

6、设置文件属性模块file,例子:

#当然group\mode\owner不写也行
ansible test -m file -a 'owner=mark group=root mode=644 path=/root/test.log'
#创建文件符号链接
ansible test -m file -a 'path=/root/test.1 src=/root/test.log state=link'

7、service指定服务状态模块管理(须保证远程主机已安装好该服务),例子:

#enableed:是否开机自动启动 true/false
#name:服务名称
#start:状态,取值为started,stoped,restarted
ansible test -m service -a 'enabled=true name=httpd state=started'

8、shell模块: 在远程主机上运行命令,支持管道、变量等在使用复制命令时使用,例子:

#该功能好用,可以批量更改客户端用户密码
ansible test -m shell -a 'echo password |passwd –stdin mark'

9、script将本地脚步复制到远程主机上并运行(注意本地主机脚步路径使用相对路劲),例子:

ansible test -m script -a "test.sh"

10、yum程序安装,例子

#name指定要安装的程序包,可以带上版本号
#state:preset,laster表示安装最新,absent卸载
ansible test -m yum -a 'name=lrzsz'

11、setup收集远程主机的facts,例子:

#查看所有
ansible test -m setup
#查看IP配置
ansible test -m setup -a 'filter=ansible_default_ipv4'
#查看内存信息
ansible test -m setup -a 'filter=ansible_memory_mb'  
#查看主机名
ansible test -m setup -a 'filter=ansible_nodename'

    每个被管理节点在接受并运行管理命令之前,会将自己主机相关信息,操作系统版本、ip地址等会报告给ansible主机用于将状态报告给ansible主机直接调用其变量。

12、其他

#查看模块帮助命令
ansible-doc -l 
#查看支持模块
ansible-doc -s Modules

六、Patterns(主机与组正则匹配部分)

    把Patterns 直接理解为正则实际是不完全准确的,正常的理解为patterns意味着在ansible中管理哪些主机,也可以理解为,要与哪台主机进行通信。在探讨这个问题之前我们先看下ansible的用法:

ansible <pattern_goes_here> -m <module_name> -a <arguments>

直接上一个示例:

ansible webservers -m service -a "name=httpd state=restarted"

这里是对webservers 组或主机重启httpd服务 ,其中webservers 就是Pattern部分。而之所以上面我说Pattern(模式)可以理解为正则,主要针对下面经常用到的用法而言的

1、表示所有的主机可以使用all * 
2、通配符与逻辑或

利用通配符还可以指定一组具有规则特征的主机或主机名,冒号表示or---逻辑或

one.361way.com
one.361way:two.361way.com
192.168.1.50
192.168.1.*

当然,这里的*通配符也可以用在前面,如:

*.361way.com
*.com

上面的用法,在多个组之间同样适用 ,如:

webservers
webservers:dbservers  #表示两个组中所有的主机
3、逻辑非与逻辑and

当然你可以做出非的表达式,例如,目标主机必须在组webservers但不在phoenix组中

webserver:!phoenix

你还可以做出交集的表达式,例如,目标主机必须即在组webservers中又在组staging中

webservers:&staging

一个更复杂的示例:

webserver:dbservers:&staging:!phoenix

上面这个复杂的表达式最后表示的目标主机必须满足:在webservers或者dbservers组中,必须还存在于staging组中,但是不在phoenix组中。这些可以看作是SaltStack中Compound matchers 。

4、混合高级用法
*.361way.com:*.org

还可以在开头的地方使用”~”,用来表示这是一个正则表达式:

~(web|db).*\.91it\.org

到这里估计你应该用能明白为什么前面我会提到Patterns 可以理解为正则的原因了。最后部分给两个ansible-playbook中具体可能用的用法:


a、在ansible-palybook命令中,你也可以使用变量来组成这样的表达式,但是你必须使用“-e”的选项来指定这个表达式(通常我们不这样用):

ansible-palybook -e webservers:!`excluded`:&`required`

b、在ansible和ansible-playbook中,还可以通过一个参数”–limit”来明确指定排除某些主机或组:

ansible-playbook site.yml --limit datacenter2