批量管理工具ansible使用

ansible的安装

yum安装方式

1
2
yum install -y epel-release
yum install -y ansible

pip的安装方式

1
pip install ansible -i https://mirrors.aliyun.com/pypi/simple/

ansible定义管理节点(资产)和变量

一、 简单使用介绍

  1. ansible管理被管理节点,如果不想设置被管理节点的登录信息,可以配置免秘钥登录

    1
    2
    3
    4
    ssh-keygen -t rsa -b 2048 -N '' -f ~/.ssh/id_rsa

    # 将公钥分发到被管理节点
    ssh-copy-id $IPs
  2. 基础使用

    1
    2
    3
    4
    5
    6
    # 单节点列表,注意节点后面的逗号
    ansible all -i 172.16.88.112, -m ping
    ansible all -i 172.16.88.112,172.16.88.113 -m ping

    #定义了节点信息的hosts文件
    ansible all -i ./hosts -m ping

注意:

  • all 节点选择器,通常-i参数给定节点信息,all表示匹配所有的-i指定的节点,也可以是文本内定义的某个分组名
  • -i参数指定节点列表,可以是一个列表,也可以是一个文件名,如果是一个单节点列表,后面需要加上逗号,否则执行会报错,如果没有指定-i参数则使用默认文件/etc/ansible/hosts
  • -m 执行运行的模块
  • -a 指定模块参数

二、 静态资产
静态资产就是一个文本文件,定义资产信息,默认是/etc/ansible/hosts,定义的节点可以是主机名或者主机IP,对不同功能节点服务器可以定义不同的分组,分组名用[]括起,有利于后续操作时方便节点选择

  1. 资产定义和分组

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    vim test_hosts

    # 定义web组的资产
    [web]
    172.16.88.112
    172.16.88.11[5:9] #表示115到119的ip段

    # 定义db组的资产
    [db]
    172.16.88.113

    # 将web组合db组的资产都嵌套到all
    [all_hosts]
    [all_hosts:children] #:children是固定写法
    web
    db

  2. 列出定义的资产

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    # 列出所有资产
    ansible all -i test_hosts --list-hosts

    # 列出单个资产
    ansible 172.16.88.113 -i test_hosts --list-hosts

    # 使用*匹配
    ansible 172.16.88.* -i test_hosts --list-hosts

    # 并集
    ansible 'web:db' -i test_hosts --list-hosts

    # 交集
    ansible 'web:&db' -i test_hosts --list-hosts

    # 排除,哪个分组在前,以哪个分组为基准
    ansible 'web:!db' -i test_hosts --list-hosts

    # 列出db分组所有资产
    ansible db -i test_hosts --list-hosts

    # 列出all_hosts组的资产
    ansible all_hosts -i test_hosts --list-hosts

三、 动态资产
待补充…

全局变量

执行ansible或者ansible-playbook时通过-e参数指定的变量
传递形式

  1. 普通key=value形式传递
    1
    ansible  web -i test_hosts  -m  template -a "src=./test.j2 dest=/tmp/test" -e "var=world"
  2. 以yaml/json格式或者文本传递
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # json格式
    cat a.json
    {"var":"word"}
    ansible web -i test_hosts -m debug -a "msg='this is a hello {{ var }}'" -e @a.json

    ## yaml格式
    cat a.yaml
    var: word

    ansible web -i test_hosts -m debug -a "msg='this is a hello {{ var }}'" -e @a.yaml

剧本变量

这种变量和playbook有关,常见的两种定义方式

  1. 通过playbook的vars属性定义

    1
    2
    3
    4
    5
    6
    7
    # 通过vars定义
    - name: test playbook
    hosts: all
    vars:
    user: haha
    path: /home/data

  2. 通过playbook的vars_files指定一个变量文件,变量文件也是yaml格式文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 定义变量文件vars_file.yaml
    user: haha
    path: /home/data

    # 指定vars_files
    - name: test playbook
    hosts: all
    vars_files:
    - vars_file.yaml

  3. playbook中使用剧本变量
    直接使用双大括号将变量名括起来

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    - name: test playbook
    hosts: all
    vars:
    user: haha
    path: /home/data
    tasks:
    - name: tasks test {{ user }}
    user:
    # 这里需要注意字典引用变量需要加上双引号,否则会报错,区别于上面的字符串引用变量
    name: "{{ user }}"
    paths: "{{ path }}"

    资产变量

前面我们介绍了资产的定义,如果要为某台服务器定义单独的变量,叫做资产变量,直接在资产的后面定义变量即可,多个以空格隔开

  1. 主机变量
    比如我们给前面定义的资产添加资产变量
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    vim test_hosts

    # 定义web组的资产
    [web]
    172.16.88.112 port=22
    ...


    # 资产变量的引用
    ansible web -i test_hosts -m debug -a "msg='port is {{ port }}'"
  2. 主机组变量
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    vim test_hosts

    # 定义web组的资产
    [web]
    172.16.88.112
    172.16.88.11[5:9] #表示115到119的ip段

    # 定义web组的组变量[:vars]是固定写法
    [web:vars]
    port=22
    ...

注意:
当主机定义了主机变量和主机组变量的时候,主机变量优先级大于主机组变量优先级
3. 主机变量的继承

1
2
3
4
5
6
7
8
9
10
11
vim test_hosts
...
[all_hosts]
[all_hosts:children] #:children是固定写法
web
db

#定义主机变量的继承
[all_hosts:vars]
port=33

Inventory内置变量

内置变量都是以ansible_为前缀的
ansible_ssh_host 连接远程主机的主机名或IP
ansible_ssh_port 端口
ansible_ssh_user 用户
ansible_ssh_pass 密码,不安全,官方建议使用密钥或者–ask-pass
ansible_sudo_pass sudo密码,不安全,官方建议–ask-sudo-pass
ansible_ssh_private_key_file ssh使用的私钥文件
ansible_python_interpreter 目标主机的python路径,使用当远程主机有多个python环境需要指定具体环境时使用

Facts变量

ansible内置变量,完全由setup模块去搜集完成,收集远程主机的各种信息
Facts变量的使用

  1. 命令行使用
    1
    2
    3
    4
    5
    # 获取完整变量
    ansible web -i test_hosts -m setup

    #过滤变量,filter模糊匹配
    ansible web -i test_hosts -m setup -a "filter=*default_ipv4*"
  2. playbook使用
    playbook会自动获取Facts变量,直接使用即可
    如需关闭,在playbook中添加参数
    1
    gather_facts: no

变量优先级

优先级从高到低
全局变量(-e指定参数)
playbook剧本变量(vars定义的变量)
资产变量

常用模块

学会使用帮助命令

1
2
3
4
5
6
7
# 列出模块
ansible-doc -l

# 列出某个模板的使用方法
ansible-doc module_name #详细
ansible-doc -s module_name # 简洁

command模块

command模块是ansible的默认模块,不指定-m参数是使用的就是command模块

1
2
ansible db -i test_hosts -a "ip a"
ansible db -i test_hosts -m command -a "ip a"

shell模块

1
ansible -i test_hosts web -m shell -a "ps -ef|grep etcd"

shell模块和command模块的区别
command模块无法执行shell的内置命令和特性,比如管道等,shell模块可以

script模块

使管理节点上的脚本在远程被管理节点上执行

在管理节点新建一个测试脚本然后通过ansible执行

1
2
echo 'ip a' > /tmp/test.sh
ansible web -i test_hosts -m script -a "/tmp/test.sh"

copy模块和fetch模块

copy模块用户管理节点和被管理节点之间的文件拷贝,用于将管理节点文件拷贝到被管理节点
fetch模块与copy模块功能相反,将被管理节点的文件拷贝到管理节点上

copy常用参数解析:
|参数|解释|
| — | — |
| src | 指定拷贝文件的源地址 |
| dest | 指定拷贝文件的目标地址 |
| backup | 拷贝文件时若原始文件发生变化则对目标文件进行备份 |
| woner | 指定新拷贝文件的所有者 |
| group | 指定新拷贝文件的属组 |
| mode | 指定新拷贝文件的权限 |

用法:

1
ansible web -i test_hosts  -m copy -a "src=./test.sh dest=/root/ backup=yes mode=755"

fetch常用参数解析
|参数|解释|
| — | — |
| src | 指定远程主机上需要拷贝文件的地址 |
| dest | 指定拷贝文件到本地的地址 |
| flat | 允许覆盖 |

用法:

1
ansible web -i test_hosts  -m fetch -a "src=/home/testans/.ssh dest=/tmp"

package模块

用于包管理
|参数|解释|
| — | — |
| name | 要安装的软件包名,多个以逗号,隔开 |
| state | 对当前指定的软件的操作,安装(present)/删除(absent) |
| use | 使用哪种包管理,yum/apt等,默认auto |

用法:

1
2
3
4
5
6
# 安装nginx
ansible web -i test_hosts -m package -a "name=nginx state=present"

# 移除nginx
ansible web -i test_hosts -m package -a "name=nginx state=absent"

yum模块

在被管理节点上执行yum命令
|参数|解释|
| — | — |
| name | 要安装的软件包名,多个以逗号,隔开 |
| state | 对当前指定的软件的操作 |

state状态的支持的参数
|参数|解释|
| — | — |
| present | 确保安装,但不升级 |
| installed | 确保已经安装 |
| latest | 确保安装且升级到最新 |
| absent | 确认删除 |
| removed | 确认删除 |

用法:

1
2
3
4
5
6
7
8
9
10
11
12
# 安装nginx
ansible web -i test_hosts -m yum -a "name=nginx state=present"
ansible web -i test_hosts -m yum -a "name=nginx state=installed"
ansible web -i test_hosts -m yum -a "name=nginx state=latest"

# 移除nginx
ansible web -i test_hosts -m yum -a "name=nginx state=absent"
ansible web -i test_hosts -m yum -a "name=nginx state=removed"

# 安装软件包组,软件包组以@开头
ansible web -i test_hosts -m yum -a "name='@Development tools' state=present"

systemd和service模块

centos6管理服务使用的是service模块,centos7以后使用的是systemd模块

  1. service模块的用法

参数|解释|
| — | — |
| name | 服务名称 |
| enabled | 是否开机自启动,yes或者no |
| pattern | 定义一个模式,如果通过status指令来查看服务的状态时,没有响应,就会通过ps指令在进程中根据该模式进行查找,如果匹配到,则认为该服务依然在运行 |
| state | 执行的操作,启动(started)、停止(stopped)、重启(restarted)、重新加载(reloaded) |

用法:

1
2
3
4
5
6
7
8
9
# 启动nginx并设置开机自启
ansible web -i test_hosts -m service -a "name=nginx state=started enabled=yes"

# 关闭nginx
ansible web -i test_hosts -m systemd -a "name=nginx state=stopped"

# 重启nginx
ansible web -i test_hosts -m systemd -a "name=nginx state=restarted"

  1. systemd模块的用法
参数 解释
daemon_reload 重新载入systemd
name 服务名称
enabled 是否开机自启动,yes或者no
state 执行的操作,启动(started)、停止(stopped)、重启(restarted)、重新加载(reloaded)
注意:
state参数的reloaded状态需要服务自身支持reload才能使用,比如nginx就支持

用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 重新加载systemd,等价于systemd daemon_reload
ansible web -i test_hosts -m systemd -a "daemon_reload=yes"

# 启动nginx并设置开机自启
ansible web -i test_hosts -m systemd -a "name=nginx state=started enabled=yes"

# 关闭nginx
ansible web -i test_hosts -m systemd -a "name=nginx state=stopped"

# 重启nginx
ansible web -i test_hosts -m systemd -a "name=nginx state=restarted"

# 重新加载nginx
ansible web -i test_hosts -m systemd -a "name=nginx state=reloaded"

group和user模块

  1. group模块使用
  2. 参数 解释
    system 是否为系统组,yes或no,默认no
    name 组名
    state 创建(present)和删除(absent),默认present

用法:

1
2
# 创建普通用户组group01
ansible web -i test_hosts -m group -a "name=group01"
  1. user模块使用
参数 解释
name 用户名
group 设置用户的主组
groups 将用户加入其它组,多个组以逗号隔开
append 与groups配合使用的参数,设置为yes的时候,不会把用户从其他已经加入的组中删除
password 用户密码,接收加密后的值,默认不设置密码
update_password 设置的密码不同于原始密码,则更新密码
home 指定用户家目录
shell 设置用户shell
commnet 描述信息
create_home 创建用户时是否创建家目录,默认yes
system 设置为yes时将创建为一个系统账号
expires 设置用户过期时间,值为时间戳
generate_ssh_key 设置为yes时为用户创建密钥,不会覆盖原有密钥
ssh_key_type 设置密钥类型,默认rsa
state 添加用户(present)/删除用户(absent)
remove 与state参数一起使用,删除一个用户管理的目录,比如家目录等

用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 创建用户名设置密码
pass=$(echo "123456" |openssl passwd -1 -stdin)
ansible web -i test_hosts -m user -a "name=testuser password=${pass}"

# 创建用户并创建密钥对,密钥对类型为ecdsa
ansible web -i test_hosts -m user -a "name=testuser generate_ssh_key=yes ssh_key_type=ecdsa"

# 创建用户并设置有效期到某一天,并将改用户加入到某个组
ansible web -i test_hosts -m user -a "name=testuser expires=$(date +%s -d 20210827) groups=docker"

# 创建用户并设置有效期到某一天,并将改用户加入到某个组,不改变原有组
ansible web -i test_hosts -m user -a "name=testuser expires=$(date +%s -d 20210827) groups=docker append=yes"

file模块

参数 解释
path 指定文件路径或目录
owner 属主
group 属组
mode 权限
state file/directory/link/hard/touch/absent
recurse 递归设置文件属性,只对目录有效
src 当state=link时可指定该参数,表示被链接的源文件路径
dest 当state=link时可指定该参数,被链接的路径

state参数解析
|参数|解释|
| — | — |
| directory | 目录不存在则创建 |
| file | 文件不存在则不会被创建,存在则返回文件信息 |
| link | 创建软链接 |
| hard | 创建硬链接 |
| touch | 如果文件不存在,则创建一个新文件,如果存在则更新最后修改时间 |
| absent | 删除目录、文件或取消链接 |

用法:

1
2
3
4
5
6
7
8
9
# 创建文件
ansible web -i test_hosts -m file "path=/tmp/test.log state=touch"

# 创建软链接
ansible web -i test_hosts -m file "state=link src=/usr/bin/vi dest=/tmp/vim"

# 取消软链接
ansible web -i test_hosts -m file -a "path=/tmp/vim state=absent"

cron模块

cron模块创建的计划任务是不可以使用crontab -e命令去编辑,否则ansible无法在控制该任务

参数 解释
name 任务名
minute 分钟,格式(0-59,,/2)等,默认*
hour 小时,格式(0-23,,/2)等,默认*
day 天,格式(1-31,,/2)等,默认*
month 月,格式(1-12,,/2)等,默认*
weekday 星期,格式(0-6,Sunday-Saturday,1,)等,默认
job 执行的任务
state 新增(present),删除(absent)

用法:

1
2
3
4
5
# 创建一个每2分钟执行一次的计划任务
ansible web -i test_hosts -m cron -a "name=testcron minute='*/2' job='ls /tmp' "

# 删除计划任务testcron
ansible web -i test_hosts -m cron -a "name=testcron state=absent"

debug模块

debug模块主要用来调试,打印变量结果等

参数 解释
var 打印指定变量的值
msg 打印一段可以格式化的字符串

用法:

1
2
3
4
5
6
# 打印role变量的值,-e指定一个变量role
ansible web -i test_hosts -m debug -a "var=role" -e "role=test"

# 打印一串带变量的字符串,变量使用{{ xx }}括起
ansible web -i test_hosts -m debug -a "msg='this is a {{ role }}'" -e "role=test"

template模块

使用Jinjia2格式作为文件模板,用法和copy模块基本一样,差别是模板文件内存在变量替换

参数 解释
src 指定模板文件路径
dest 指定被管理节点生成文件路径
owner 属主
group 属组
mode 权限
backup 创建一个包含时间戳的备份文件,yes/no

用法:

1
2
3
4
5
6
7
# 创建一个模板文件
vi test.j2
Hello {{ var }}

# 根据模板文件和传入变量生产文件
ansible web -i test_hosts -m template -a "src=./test.j2 dest=/tmp/test" -e "var=world"

parted模块

parted模块用来对磁盘进行分区进行操作
|参数|解释|
| — | — |
| device | 待操作磁盘设备名称 |
| fs_type | 磁盘分区格式,默认null |
| label | |
| number | 分区号 |
| part_start | 分区开始位置 |
| part_end | 分区结束位置|
| part_type | 分区类型 extended, logical, primary,默认primary|
| state | 状态,present,absent |
| resize | 调整分区大小,默认false |
| unit | 分区默认单位,Choices: s, B, KB, KiB, MB, MiB, GB, GiB, TB, TiB, %, cyl, chs,compact.默认Kib |

用法:

1
2
3
4
5
# 给/dev/vdb磁盘分区
ansible -i test_hosts all -m parted -a "device=/dev/vdb number=1 state=present fs_type=ext4"

# 删除/dev/vdb磁盘分区
ansible -i test_hosts all -m parted -a "device=/dev/vdb number=1 state=absent "

lvg模块

lvg模块,卷组管理,创建、删除卷组以及动态改变卷组大小
|参数|解释|
| — | — |
| vg | 要创建的卷组名称 |
| pvs | 要加入到卷组的物理卷列表 |
| pesize | 指定pe大小,默认4M,默认单位M |
| state | 状态,present,absent |

用法:

1
2
3
4
5
# 将物理卷添加到卷组
ansible -i test_hosts all -m lvg -a "vg=centos-01 pvs=/dev/sdb1 state=present"

# 删除卷组
ansible -i test_hosts all -m lvg -a "vg=centos-01 state=absent"

lvol模块

lvol模块,逻辑卷管理,创建删除逻辑卷

filesystem模块

unarchive模块

get_url模块

stat模块

replace模块

lineinfile和blockinfile模块

lineinfile模块用正则匹配的方式对目标文件的一行内容修改删除,每次只修改一行内容
replace模块可以对目标文件匹配到的多行内容修改删除操作
blockinfile模块对文件进行一次性添加、修改、删除多行内容操作

参数 解释
path 目标文件路径
state 替换(present)/删除(absent)
regexp 正则匹配,当state=present时,仅最后一个匹配行有效
line 与state-present同时使用,要插入和修改的内容
create 文件不存在时是否创建yes/no

用法:

1
2
3
4
5
6
# 删除
ansible web -i test_hosts -m lineinfile -a "path=/etc/hosts regexp='^127' state=absent"

# 替换
ansible web -i test_hosts -m lineinfile -a "path=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=disabled' state=present