Ansible第一篇:基础,ansible第一篇基础


一、配置文件 ansible.cfg

/etc/ansible/ansible.cfg 是ansible安装好后的默认配置文件,但是配置文件可以存在于多个地方,ansible读取配置文件的顺序依次是:当前命令执行目录 ---> **用户家目录下的 .ansible.cfg ** ---> /etc/ansible/ansible.cfg,先找到哪个就使用哪个的配置。ansible.cfg中的配置均可在命令行通过参数传递或定义在playbooks中。

以下是[defaults]常用的配置项:

1)inventory 
    该参数表示资源清单inventory文件的位置,资源清单就是一些Ansible需要连接管理的主机列表 
    inventory = /root/ansible/hosts 

2)library 
    Ansible的操作动作,无论是本地或远程,都使用一小段代码来执行,这小段代码称为模块,这个library参数就是指向存放Ansible模块的目录 
    library = /usr/share/ansible 

3)forks 
    设置默认情况下Ansible最多能有多少个进程同时工作,默认设置最多5个进程并行处理。具体需要设置多少个,可以根据控制主机的性能和被管理节点的数量来确定。 
    forks = 5 

4)sudo_user 
    这是设置默认执行命令的用户,也可以在playbook中重新设置这个参数sudo_user = root 
    //注意:新版本已经作了修改,如ansible2.4.1下已经为: default_sudo_user = root 

5)remote_port 
    这是指定连接被关节点的管理端口,默认是22,除非设置了特殊的SSH端口,不然这个参数一般是不需要修改的 
    remote_port = 22 

6)host_key_checking 
    这是设置是否检查SSH主机的密钥。可以设置为True或False 
    host_key_checking = False 

7)timeout 
    这是设置SSH连接的超时间隔,单位是秒。 
    timeout = 20 

8)log_path 
    Ansible系统默认是不记录日志的,如果想把Ansible系统的输出记录到人i治稳健中,需要设置log_path来指定一个存储Ansible日志的文件 
    log_path = /var/log/ansible.log 
    另外需要注意,执行Ansible的用户需要有写入日志的权限,模块将会调用被管节点的syslog来记录,口令是不会出现的日志中的 

9)private_key_file 在使用ssh公钥私钥登录系统时候,使用的密钥路径。 
    private_key_file=/path/to/file.pem
    
作者: Jeson老师 
链接:https://www.imooc.com/article/22513
来源:慕课网

更多配置项请参考官方文档

二、主机清单(Inventory)文件hosts

2.1 hosts文件定义

默认存放在 **/etc/ansible/hosts **,命令行使用时,还可以通过 -i--inventory-file 指定读取某个hosts文件,如:

//读取当前用户家目录下的hosts文件
ansible -i ~/ansible/hosts webs -m ping

如下是hosts文件中的常用常用的定义主机方法:

# 定义单独的主机
192.168.1.189   //可以直接为IP地址
ntp.cgy.com:2222    //也可以主机名:端口,端口默认是22

# 定义主机组
[apache]
httpd1.cgy.com
httpd[10:20].cgy.com    //[10:20]表示10~20之间所有数字(包括10和20)

# 定义主机变量
[nginx]
ngx-a.cgy.com http_port=808     //自定义这台主机的nginx端口为808,可以写多个变量,每个变量用空格间隔即可           
ngx-[b:f].cgy.com   //[b:f]表示b到f之间所有字母

# 定义主机组变量
[nginx:vars]
ntp_server=ntp.cgy.com      //定义nginx组中所有的主机ntp_server值为ntp.cgy.com

# 定义组嵌套及组变量
[webservers:children]
apache
nginx

[webservers:vars]
ntp_server=ntp.cgy.com

2.2 主机匹配

  1. all(全量)匹配,匹配所有主机
// all和 * 号功能相同,但 * 号需要引起来
ansible all -m ping
ansible "*" -m ping

// 匹配192.168.1.0/24网段的主机
ansible 192.168.1.* -m ping

  1. 逻辑或(or)匹配

如果希望同时对多台主机或多个组同时执行,相互之间用:(冒号)分隔即可。

使用方式如下:

ansible "webservers:dbservers" -m ping

  1. 逻辑非(!)匹配

逻辑非用感叹号(!)表示,主要针对多重条件的匹配规则,使用方法如下:

// 所有在nginx组,但不包括ngx-c.cgy.com的主机
ansible "nginx:!ngx-c.cgy.com" -m ping

  1. 逻辑与(&)匹配

与逻辑非一样,只是逻辑上的判断不同。

// apache组和nginx组中同时存在的主机
ansible "apache:&nginx" -m ping

  1. 模糊匹配

* 通配符在ansible表示0个或多个任意字符。

ansible "http*.cgy.com" -m ping

  1. 域切割

hosts文件如下:

[webservers]
cobweb
webbing
weber

通过截取数组下标即可以获取对应主机:

webservers[0]       # == cobweb
webservers[-1]      # == weber
webservers[0:1]     # == cobweb, webbing
webservers[1:]      # == webbing, weber

  1. 正则匹配

ansible同样完整支持正则匹配功能,~ 开始表示正则匹配

ansible "~(beta|web|green)\.example\.(com|org)" -m ping

ansible ~192\.168\.[0-9]\{\2}\.[0-9]\{2,} -m ping

三、Ad-Hoc命令集

Ad-Hoc命令,也就是临时命令的意思,就是通常在命令行下操作的ansible命令,区别于ansible-playbook。

Ad-Hoc 注重于解决一些简单或者平时工作中临时遇到的任务,相当于Linux系统命令行下的Shell命令;

Ansible-playbook 更适合解决复杂或需要固化下来的任务,相当于Linux系统的Shell脚本。

3.1 ansible命令用法

格式:ansible <host-pattern> [options]

可用选项如下:

-v, --verbose:               输出更详细的执行过程信息,**-vvv** 可得到所有执行过程信息。
-i PATH, --inventory=PATH:   指定inventory信息,默认/etc/ansible/hosts。
-f NUM, --forks=NUM:         并发线程数,默认5个线程。
--private-key=PRIVATE_KEY_FILE:  指定密钥文件。
-m NAME, --module-name=NAME:     指定执行使用的模块。
-M DIRECTORY, --module-path=DIRECTORY:  指定模块存放路径,默认/usr/share/ansible,也可以通过ANSIBLE_LIBRARY设定默认路径。
-a 'ARGUMENTS', --args='ARGUMENTS':     模块参数。
-k, --ask-pass SSH:           认证密码。
-K, --ask-sudo-pass sudo:     用户的密码(—sudo时使用)。
-o, --one-line:               标准输出至一行。
-s, --sudo:                   相当于Linux系统下的sudo命令。
-t DIRECTORY, --tree=DIRECTORY:  输出信息至DIRECTORY目录下,结果文件以远程主机名命名。
-T SECONDS, --timeout=SECONDS:   指定连接远程主机的最大超时,单位是:秒。
-B NUM, --background=NUM:     后台执行命令,超NUM秒后kill正在执行的任务。
-P NUM, --poll=NUM:           定期返回后台任务进度。
-u USERNAME, --user=USERNAME: 指定远程主机以USERNAME运行命令。
-U SUDO_USERNAME, --sudo-user=SUDO_USERNAM:  使用sudo,相当于Linux下的sudo命令。
-c CONNECTION, --connection=CONNECTION:      指定连接方式,可用选项paramiko (SSH), ssh, local。Local方式常用于crontab 和 kickstarts。
-l SUBSET, --limit=SUBSET:    指定运行主机。
-l ~REGEX, --limit=~REGEX:    指定运行主机(正则)。
--list-hosts:                 列出符合条件的主机列表,不执行任何其他命令

3.2 ansible命令执行流程图

img_4b2157b5e30f74d4df0f0300d2556ead.png ansible命令执行流程

3.3 常用模块介绍

使用ansible-doc -l可以列出所有ansible支持的模块;
使用ansible-doc 模块名获取模块帮助信息;

/etc/ansible/hosts文件内容如下:

[root@LOCALHOST ~]# cat /etc/ansible/hosts
[load-node]
openstack-load1
openstack-load2

[compute-node]
openstack-compute1
openstack-compute2

[control-node]
openstack-control1
openstack-control2

[openstack:children]
load-node
compute-node
control-node

3.3.1  command模块

如果没有用-m指定一个模块,则ansible默认使用的就是command模块。如下:

查看load-node组的主机名:

[root@LOCALHOST ~]# <strong>ansible load-node -a "hostname"</strong>
openstack-load2 | SUCCESS | rc=0 >>
openstack-load2

openstack-load1 | SUCCESS | rc=0 >>
openstack-load1.example.com 

注意:command 模块不支持 shell 变量,也不支持管道等 shell 相关的东西.如果你想使用 shell相关的这些东西, 请使用’shell’ 模块。

特别注意:执行ansible命令之前需要将主机清单中所有主机关闭selinux状态置于disabled状态,就是将/etc/sysconfig/selinux中的SELINUX=disabled,然后重启生效。


3.3.2  shell模块

示例一(读取变量):

[root@LOCALHOST ~]# **ansible load-node -m shell -a "echo $TERM"**
openstack-load2 | SUCCESS | rc=0 >>
xterm 

openstack-load1 | SUCCESS | rc=0 >>
xterm

示例二(支持管道):

[root@LOCALHOST ~]# ansible load-node -m shell -a "netstat -tunlp | grep sshd"
openstack-load1 | SUCCESS | rc=0 >>
tcp        0      0 0.0.0.0:2002            0.0.0.0:*               LISTEN      845/sshd            
tcp6       0      0 :::2002                 :::*                    LISTEN      845/sshd            

openstack-load2 | SUCCESS | rc=0 >>
tcp        0      0 0.0.0.0:2002            0.0.0.0:*               LISTEN      853/sshd            
tcp6       0      0 :::2002                 :::*                    LISTEN      853/sshd 

3.3.3  copy模块
[root@LOCALHOST ~]# **ansible load-node -m copy -a "src=/root/upgrade.log dest=/root/"**
openstack-load2 | SUCCESS => {
    "changed": true, 
    "checksum": "792f7f450667adc5c89fbaeb06f778488149b87b", 
    "dest": "/root/upgrade.log", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "1c1a33178d6a6aeb42fb4126ab420ba0", 
    "mode": "0644", 
    "owner": "root", 
    "size": 36, 
    "src": "/root/.ansible/tmp/ansible-tmp-1522073638.68-199717195987657/source", 
    "state": "file", 
    "uid": 0
}
...省略部分输出...

注意:copy模块还有一个remote_src参数,不写此参数,默认为:remote_src=no,将控制主机的src复制到目标主机的dest。如果加上参数 remote_src=yes,那么将从远程目标主机的src复制到远程主机的dest


3.3.5  file模块

使用file模块可以做到修改文件的属主和权限:

$ ansible webservers -m file -a "dest=/srv/foo/a.txt mode=600"

$ ansible webservers -m file -a "dest=/srv/foo/b.txt mode=600 owner=mdehaan group=mdehaan"

使用file模块也可以创建目录,与执行mkdir -p 效果类似:

$ ansible webservers -m file -a "dest=/path/to/c mode=755 owner=mdehaan group=mdehaan state=directory"

删除目录(递归的删除)和删除文件:

$ ansible webservers -m file -a "dest=/path/to/c state=absent"

3.3.6  yum模块

安装软件包:

$ ansible control-node -m yum -a "name=httpd state=present"

    // 或者state=installed 安装软件
    // state=latest 安装最新版本 

卸载软件包:

$ ansible control-node -m yum -a "name=httpd state=absent"
    
    // 或者state=removed 卸载软件包

yum模块在playbook中的用法:

# 以下只写出了tasks部分内容:

//安装指定版本的软件
- name: install one specific version of Apache
  yum:
    name: httpd-2.2.29-1.4.amzn1
    state: present


// 升级所有软件包
- name: upgrade all packages
  yum:
    name: '*'
    state: latest

// 升级所有软件包,不包括内核和foo相关的软件包
- name: upgrade all packages, excluding kernel & foo related packages
  yum:
    name: '*'
    state: latest
    exclude: kernel*,foo*

// 从远程仓库安装nginx
- name: install the nginx rpm from a remote repo
  yum:
    name: http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
    state: present


// 安装开发环境包组
- name: install the 'Development tools' package group
  yum:
    name: "@Development tools"
    state: present

// 列出指定软件包信息并注册至变量result
- name: List ansible packages and register result to print with debug later.
  yum:
    list: ansible
  register: result

3.3.7  user模块

使用 user 模块可以方便的创建账户,删除账户,或是管理现有的账户:

// 添加用户foo
$ ansible all -m user -a "name=foo password=123456"

// 删除用户foo
$ ansible all -m user -a "name=foo state=absent"

    // state=absent结合remove=yes使用,相当于shell命令userdel --remove 删除用户家目录及邮件目录

3.3.8  git模块

可以直接使用git模块部署webapp:

$ ansible webservers -m git -a "repo=git://foo.example.org/repo.git dest=/srv/myapp version=HEAD"

3.3.9  service模块

service模块来管理各种服务的启停:

// 开启httpd
$ ansible webservers -m service -a "name=httpd state=started"

// 重启httpd
$ ansible webservers -m service -a "name=httpd state=restarted"

    // state可以选择stopped(停止)、reloaded(重载配置)

需要注意的是,startedstopped是 <font color=green size=4>幂等操作</font>,也就是说,如果某项服务已经开启或关闭,那么就不再继续操作。


3.3.10  pip模块
// 安装Django
$ ansible app -m pip -a "name=django state=present"

3.3.11  mysql_user模块

mysql_user模块,是对mysql用户进行管理的模块。
事实上,Ansible也支持如Openstack、Mongodb、PostgreSQL、RabbitMQ等应用的管理。

新增mysql用户stanley,密码123456,对zabbix.*表有所有权限,命令如下:

$ ansible db -m mysql_user -a "login_host=localhost login_user=root login_password=laksdvcx name=stanley password=123456 priv=zabbix.*:ALL state=present"

注意:上述命令直接将Mysql登录信息完全暴露在命令行,存在很大的安全隐患。如果在远程主机的~/.my.conf文件中定义登录用户及密码,则可以在上述命令中省略登录相关信息。

3.3.12  setup模块

获取远程主机的系统信息,这些系统信息在playbook中可以直接当作变量引用,如 {{ ansible_all_ipv4_addresses }}就可以获取到远程主机的所有IP地址[ "10.0.1.105", "43.240.137.105"],这些变量被称作facts变量。

$ ansible compute-node -m setup
openstack-compute2 | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "10.0.1.105", 
            "43.240.137.105"
        ], 
        "ansible_all_ipv6_addresses": [
            "fe80::5054:ff:fe13:38cc", 
            "fe80::5054:ff:fe2b:60e5"
        ], 
        "ansible_apparmor": {
            "status": "disabled"
        }, 
        "ansible_architecture": "x86_64", 
        "ansible_bios_date": "01/01/2007", 
        "ansible_bios_version": "0.5.1", 
        "ansible_cmdline": {
            "BOOT_IMAGE": "/vmlinuz-3.10.0-327.el7.x86_64", 
            "LANG": "zh_CN.UTF-8", 
            "biosdevname": "0", 
            "crashkernel": "auto", 
            "net.ifnames": "0", 
            "quiet": true, 
            "rd.lvm.lv": "centos/swap", 
            "rhgb": true, 
            "ro": true, 
            "root": "/dev/mapper/centos-root"
        }, 

... 省略 ...
        "ansible_system_capabilities_enforced": "True", 
        "ansible_system_vendor": "Red Hat", 
        "ansible_uptime_seconds": 313578, 
        "ansible_user_dir": "/root", 
        "ansible_user_gecos": "root", 
        "ansible_user_gid": 0, 
        "ansible_user_id": "root", 
        "ansible_user_shell": "/bin/bash", 
        "ansible_user_uid": 0, 
        "ansible_userspace_architecture": "x86_64", 
        "ansible_userspace_bits": "64", 
        "ansible_virtualization_role": "guest", 
        "ansible_virtualization_type": "kvm", 
        "gather_subset": [
            "all"
        ], 
        "module_setup": true
    }, 
    "changed": false

过滤显示:

$ ansible compute-node -m setup -a 'filter=ansible_eth[0-1]'


$ ansible compute-node -m setup -a 'gather_subset=network,virtual'


$ ansible compute-node -m setup -a 'gather_subset=!all,!any,network,virtual'

3.3.13  cron模块

cron模块是用来添加或删除定时任务的;

// 添加一个定时任务,每过2分钟从time.aliyun.com同步一次时间
[root@LOCALHOST ~]# ansible load-node -m cron -a "name='sync time from ntpserver' minute=*/2 job='/sbin/ntpdate time.aliyun.com &> /dev/null'"
openstack-load1 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "sync time from ntpserver"
    ]
}
openstack-load2 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "sync time from ntpserver"
    ]
}

注意:如果 hourdaymonthweekday都没指定,则都表示 *
state没写,默认等于present,就是创建定时任务。

删除一个定时任务:

[root@LOCALHOST ~]# ansible load-node -m cron -a "name='sync time from ntpserver' state=absent"
openstack-load1 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": []
}
openstack-load2 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": []

3.3.14  script模块

script模块是将本地脚本先拷贝一份到目标主机上去执行,执行完成后再将目标主机上的拷贝删除。

// 在目标主机上执行控制机root目录下的test.sh脚本
[root@LOCALHOST ~]# ansible load-node -m script -a "/root/test.sh"
openstack-load2 | SUCCESS => {
    "changed": true, 
    "rc": 0, 
    "stderr": "", 
    "stdout": "", 
    "stdout_lines": []
}
openstack-load1 | SUCCESS => {
    "changed": true, 
    "rc": 0, 
    "stderr": "", 
    "stdout": "", 
    "stdout_lines": []
}


// 验证脚本在目标主机是否执行成功
[root@LOCALHOST ~]# ansible load-node -m shell -a "cat /tmp/ansible.txt"
openstack-load1 | SUCCESS | rc=0 >>
openstack-load1.example.com: Ansible is very good !!!

openstack-load2 | SUCCESS | rc=0 >>
openstack-load2: Ansible is very good !!!


3.3.15  archive和unarchive模块

archiveunarchive模块是打包压缩与解压缩模块;

archive模块默认情况下,它假定目标主机上存在压缩源;

$ ansible load-node -m archive -a "path=/tmp/test exclude_path=/tmp/test/sub2 format=bz2 dest=/tmp/test.tar.bz2"
  • path:指定远程主机上将要压缩的目录或文件;
  • exclude_path:指定要排除的文件或目录;
  • format:指定压缩格式,choices:gz、bz2、zip、tar、xz (ansible 2.5支持),默认是gz格式;
  • dest:压缩后的文件名。

unarchive模块默认情况下,它将在解包之前将源文件从本地系统复制到目标主机。设置remote_src = yes将解包目标主机上已有的压缩包。

$ ansible load-node -m  unarchive -a "src=/tmp/test.tar.bz2 dest=/root list_files=yes remote_src=yes"

常用模块就介绍这么多,更多模块学习请使用ansible-doc 模块名称获取帮助。

相关内容