ansible安装及使用

ansible安装及使用

Administrator 878 2018-09-24

主要介绍ansible的安装,以及如何使用ansible远程执行命令、拷贝文件或目录、如何远程执行脚本、管理计划任务。


ansible介绍与安装

ansible介绍

  • ansible不需要安装客户端,通过sshd进行通信,基于模块工作,模块可以由任何语言进行开发;
  • ansible不仅支持命令行使用模块,也支持编写yaml格式的playbook,一句编写和阅读;
  • 安装ansible非常简单,centos上可以直接使用yum安装,并且提供有web界面,名为tower,需要付费使用,命令行模式为免费使用;
  • redhat已经收购了ansible,所以在redhat系上直接使用yum安装的就是ansible的最新版本;
  • 关于按ansible,可以参考ansible first book电子书。

安装ansible

  • 首先准备两台机器,如vm1和vm2;

  • 然后在vm1上使用yum安装ansible:

    yum install -y ansible 
    
  • 接着配置两台机器的密钥认证,将vm1的公钥写到vm2的authorized_keys文件内;

  • 然后编辑/etc/ansible/hosts文件,该文件用来定义主机组,如web组、db组等等,在该文件内写入主机组的名字,然后将主机的ip或者hostname(需要在/etc/hosts文件内进行配置)写在下面即可,如下:

    [testhost]	#组名自定义
    127.0.0.1
    192.168.199.142
    

ansible的使用

远程执行命令

  • ansible远程执行命令是针对在/etc/ansible/hosts内定义的主机组来执行的,使用ansible [groupname] -m command -a ‘[cmd]’,这里-m是执行使用的模块,远程执行命令使用command模块,然后-a指定要执行的命令:

    [root@vm1 ~]# ansible testhost -m command -a 'hostname'
    192.168.199.142 | SUCCESS | rc=0 >>
    vm2
    
    127.0.0.1 | SUCCESS | rc=0 >>
    vm1
    
    
  • 除了指定主机组,也可以针对一台机器执行命令,将上面的命令中的主机组替换为指定主机的ip或hostname(需在/etc/ansible/hosts中使用的是hostname)即可:

    [root@vm1 ~]# ansible 192.168.199.142 -m command -a 'hostname'
    192.168.199.142 | SUCCESS | rc=0 >>
    vm2
    
    
  • 如果远程主机开启了selinux,执行远程命令会报错如下信息,只需要安装libselinux-python软件包即可:

    “msg":"Aborting,target uses selinux but python bindings (libselinux-python) aren't installed!"
    
  • 另外absible还有一个shell模块也可以用来执行远程命令,命令为ansible [group] -m shell -a ‘cmd’,实际上shell模块是用来远程执行脚本的,但是用来执行单条命令也没有问题:

    [root@vm1 ~]# ansible testhost -m shell -a 'hostname'
    127.0.0.1 | SUCCESS | rc=0 >>
    vm1
    
    192.168.199.142 | SUCCESS | rc=0 >>
    vm2
    
    

拷贝文件或目录

  • ansible拷贝目录和文件使用copy模块,命令格式为ansible [group] -m copy -a "src=[/path/dir] dest=[/path/dir] owner=[username] group=[groupname] mode=[0755]",这里的src指定源目录,dest指定目标目录,owner指定属主,group指定属组,mode指定权限;

  • ansible拷贝文件和目录,会将源目录放到指定的目标目录下面去,如果目标目录不存在,将会自动创建新目录,如果拷贝的是文件,dest中指定的文件名和源文件名不同,则会重命名,而如果目标路径下存在与文件同名的目录,ansible则会将文件放到同名的目录下面:

    [root@vm1 ~]# ansible vm2 -m copy -a "src=/etc/ansible dest=/tmp/ansible_test owner=root group=root mode=0755"
    vm2 | SUCCESS => {
        "changed": true, 
        "dest": "/tmp/ansible_test/", 
        "src": "/etc/ansible"
    }
    
    
    • 查看vm2上拷贝来的目录:
    [root@vm2 tmp]# ll ansible_test/
    总用量 0
    drwxr-xr-x. 3 root root 51 9月  24 23:58 ansible
    
    
    • 在指定源目录时,最后的目录路径不能带/,否则相当于将源目录下的文件进行拷贝
    [root@vm1 ~]# ansible vm2 -m copy -a "src=/root/.ssh/ dest=/tmp/vm1_copy/ owner=root group=root mode=0755"
    vm2 | SUCCESS => {
        "changed": true, 
        "dest": "/tmp/vm1_copy/", 
        "src": "/root/.ssh/"
    }
    
    [root@vm2 tmp]# ll vm1_copy/
    总用量 16
    -rwxr-xr-x. 1 root root  771 9月  24 23:54 authorized_keys
    -rwxr-xr-x. 1 root root 1675 9月  24 23:54 id_rsa
    -rwxr-xr-x. 1 root root  390 9月  24 23:54 id_rsa.pub
    -rwxr-xr-x. 1 root root  868 9月  24 23:54 known_hosts
    
    
  • 拷贝文件如下:

    [root@vm1 ~]# ansible vm2 -m copy -a "src=/etc/passwd dest=/tmp owner=root group=root mode=0755"
    vm2 | SUCCESS => {
        "changed": true, 
        "checksum": "d2212e95862f22511ab1610cd53326e11482fef9", 
        "dest": "/tmp/passwd", 
        "gid": 0, 
        "group": "root", 
        "md5sum": "dbc0139917c74a337bc390171007ac4a", 
        "mode": "0755", 
        "owner": "root", 
        "secontext": "unconfined_u:object_r:admin_home_t:s0", 
        "size": 1300, 
        "src": "/root/.ansible/tmp/ansible-tmp-1537804974.59-42062188467412/source", 
        "state": "file", 
        "uid": 0
    }
    
    [root@vm2 tmp]# ll passwd 
    -rwxr-xr-x. 1 root root 1300 9月  25 00:02 passwd
    
    
  • 拷贝文件并重命名:

    [root@vm1 ~]# ansible vm2 -m copy -a "src=/etc/passwd dest=/tmp/vm1_passwd owner=root group=root mode=0755"
    vm2 | SUCCESS => {
        "changed": true, 
        "checksum": "d2212e95862f22511ab1610cd53326e11482fef9", 
        "dest": "/tmp/vm1_passwd", 
        "gid": 0, 
        "group": "root", 
        "md5sum": "dbc0139917c74a337bc390171007ac4a", 
        "mode": "0755", 
        "owner": "root", 
        "secontext": "unconfined_u:object_r:admin_home_t:s0", 
        "size": 1300, 
        "src": "/root/.ansible/tmp/ansible-tmp-1537805059.1-234962579446258/source", 
        "state": "file", 
        "uid": 0
    }
    
    [root@vm2 tmp]# ll vm1_passwd 
    -rwxr-xr-x. 1 root root 1300 9月  25 00:04 vm1_passwd
    
    

远程执行脚本

  • 首先创建一个shell脚本,内容如下:

    #!/bin/bash
    echo `date` > /tmp/ansible_test.txt
    
    
  • ansible不能够像saltstack一样直接远程执行脚本,其必须先将脚本分发到对应的主机上,然后才能执行,使用ansible拷贝文件的命令将脚本拷贝到对应的主机上:

    [root@vm1 ~]# ansible vm2 -m copy -a "src=/root/test_shell.sh dest=/tmp/test_shell.sh mode=0755"
    vm2 | SUCCESS => {
        "changed": true, 
        "checksum": "1a6e4af02dba1bda6fc8e23031d4447efeba0ade", 
        "dest": "/tmp/test_shell.sh", 
        "gid": 0, 
        "group": "root", 
        "md5sum": "edfaa4371316af8c5ba354e708fe8a97", 
        "mode": "0755", 
        "owner": "root", 
        "secontext": "unconfined_u:object_r:admin_home_t:s0", 
        "size": 48, 
        "src": "/root/.ansible/tmp/ansible-tmp-1537805501.67-208729732802698/source", 
        "state": "file", 
        "uid": 0
    }
    
    
  • 然后使用shell模块远程执行脚本:

    [root@vm1 ~]# ansible vm2 -m shell -a "/tmp/test_shell.sh"
    vm2 | SUCCESS | rc=0 >>
    
    
    
    • 到vm2上查看执行结果:
    [root@vm2 tmp]# cat ansible_test.txt 
    2018年 09月 25日 星期二 00:12:33 CST
    
    
  • 远程执行命令的时候,我们使用的command模块,这个模块在执行命令的时候不能够在命令中使用管道符,而shell模块支持管道符:

    [root@vm1 ~]# ansible vm2 -m command -a "cat /etc/passwd|wc -l"
    vm2 | FAILED | rc=1 >>
    cat:无效选项 -- l
    Try 'cat --help' for more information.non-zero return code
    
    [root@vm1 ~]# ansible vm2 -m shell -a "cat /etc/passwd|wc -l"
    vm2 | SUCCESS | rc=0 >>
    22
    
    

管理计划任务

  • ansible同样能够管理主机的计划任务,使用cron模块,命令格式为ansible [group] -m cron -a "name='[cron name]' job='[cmd]' (minute|hour|day|month|weekday|)=x",这里name指定crontab任务的名字,job则指定执行的命令事什么,后面则是使用ansible的关键字来执行任务执行的时间,不指定的时间则会默认为*

    [root@vm1 ~]# ansible vm2 -m cron -a "name='test cron' job='/bin/touch /tmp/123.txt' minute=0 hour=0 weekday=6"
    vm2 | SUCCESS => {
        "changed": true, 
        "envs": [], 
        "jobs": [
            "test cron"
        ]
    }
    
    
  • 在vm2上查看计划任务:

    [root@vm2 tmp]# crontab -l
    #Ansible: test cron
    0 0 * * 6 /bin/touch /tmp/123.txt
    
    
    • 可以看到指定的任务名以注释的形式被写入crontab任务,这里与saltstack一样,不能自行改动ansible写入的计划任务;
  • 删除一个计划任务,使用ansible [group] -m cron -a "name='cron name' state=absent"

    [root@vm1 ~]# ansible vm2 -m cron -a "name='test cron' state=absent"
    vm2 | SUCCESS => {
        "changed": true, 
        "envs": [], 
        "jobs": []
    }
    
    [root@vm2 tmp]# crontab -l
    [root@vm2 tmp]#