2.Ansible基本使用
2-Ansible 基本使用
Ansible 清单
Ansible 清单(Inventory)就像是一个 “通讯录”,里面记录了所有需要 Ansible 管理的主机信息。我们可以把主机分到不同的组里,方便批量操作;组还能包含子组,一个主机也能属于多个组。清单里还能设置一些变量,专门用于它所定义的主机或组。
Ansible 软件包中文件
通过 rpm -ql ansible
命令可以查看 Ansible 软件包安装的所有文件及路径,主要包含以下关键目录:
[bq@controller ~]# rpm -ql ansible # 列出ansible安装的所有文件路径
- 配置文件目录:
/etc/ansible
(存放核心配置文件) - 执行文件目录:
/usr/bin
(ansible、ansible-playbook 等可执行命令) - 依赖库目录:
/usr/lib/python2.7/site-packages/ansible
(Ansible 运行依赖的 Python 库) - 插件目录:
/usr/share/ansible/plugins
(各类功能插件,如连接插件、过滤插件等) - 帮助文档目录:
/usr/share/doc/ansible
(官方文档) - 手册目录:
/usr/share/man/man1/
(man 命令可查看的手册)
主机清单
清单的定义方式分为两种:
- 静态主机清单:用文本文件(如 ini、yaml 格式)手动定义主机信息,适合主机数量固定的场景。
- 动态主机清单:通过脚本或程序从外部环境(如 OpenStack、Kubernetes)自动获取主机信息,适合主机频繁变动的场景(本课程暂不深入)。
静态主机清单
静态清单支持多种格式,这里以最常用的 ini 格式 为例讲解。
最简单的静态清单
直接列出受管节点的主机名或 IP 地址,每行一个。
示例:创建一个名为 inventory
的清单文件
[bq@controller ~]$ vim inventory # 编辑清单文件
文件内容(包含 4 个节点和 1 个控制节点):
controller # 控制节点主机名
node1 # 受管节点1主机名
node2 # 受管节点2主机名
node3 # 受管节点3主机名
node4 # 受管节点4主机名
验证清单的常用命令:
# 列出清单中所有主机(all表示所有主机)
[root@controller ~ 13:41:54]# ansible -i ./inventory --list-hosts allhosts (5):controllernode1node2node3node4# 在所有主机上执行id命令(查看当前用户身份)
# -i inventory:指定清单文件路径
# -a id:-a参数指定要执行的命令(这里是id)
[root@controller ~ 13:41:54]# ansible all -i inventory -a id
node2 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) 组=0(root) # 输出结果:node2主机当前用户为root
# 其他节点输出类似...# 只在node1主机上执行id命令
[root@controller ~ 13:42:08]# ansible node1 -i inventory -a id
node1 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) 组=0(root)# 检查清单中是否存在node1主机
[bq@controller ~]$ ansible -i inventory --list-hosts node1hosts (1):node1# 检查清单中是否存在IP为10.1.8.11的主机
[bq@controller ~]$ ansible --list-hosts -i inventory 10.1.8.11 hosts (1):10.1.8.11
命令说明:ansible
命令通过 -i PATHNAME
或 --inventory PATHNAME
选项指定清单文件路径(PATHNAME
是清单文件的路径)。
主机组
为了更高效地管理主机,可以将主机分到不同的组中。组的格式为 [组名]
,下面列出该组包含的主机。
示例:带分组的清单文件
10.1.8.110 # 未分组的主机(IP地址)[controllers] # 控制机组
controller # 属于controllers组的主机[nodes] # 节点组
node1 # 属于nodes组的主机
node2
node3
node4[nj] # 南京节点组
node1
node3[bj] # 北京节点组
node2
node4[webs] # Web服务器组
node1
node2[dbs] # 数据库服务器组
node3
node4
验证分组的命令:
# 列出nj组中的所有主机
[bq@controller webapp 17:12:00]$ ansible -i inventory --list-hosts njhosts (2):node1node3# 列出bj组中的所有主机
[bq@controller webapp 17:16:47]$ ansible -i inventory --list-hosts bjhosts (2):node2node4# 列出未分组(ungrouped)的主机
[bq@controller webapp 17:18:34]$ ansible -i inventory --list-hosts ungroupedhosts (1):10.1.8.111 # 前面清单中未分组的10.1.8.110在这里显示(示例可能有笔误,核心是显示未分组主机)
默认存在的特殊组:
all
:包含清单中所有主机(无论是否分组)。ungrouped
:包含清单中列出但不属于任何组的主机。
# 列出所有主机(all组)
[bq@controller ~]$ ansible -i inventory --list-hosts allhosts (10): # 示例中包含10个主机10.1.8.111controllernode1# 其他主机...# 列出未分组主机(ungrouped组)
[bq@controller ~]$ ansible --list-hosts -i inventory ungroupedhosts (1):app1.example.com # 未属于任何组的主机
主机组嵌套
一个组可以包含其他组(子组),格式为 [父组名:children]
,下面列出子组名。
示例:带嵌套组的清单
[eastdc] # 东DC组
web1.example.com
db1.example.com[westdc] # 西DC组
web2.example.com
db2.example.com[dc:children] # dc组包含的子组
eastdc # 子组1
westdc # 子组2
验证嵌套组:
# 列出dc组中的所有主机(包含子组eastdc和westdc的所有主机)
[bq@controller webapp 17:26:52]$ ansible --list-hosts -i inventory dchosts (4):web1.example.com # 来自eastdcdb1.example.com # 来自eastdcweb2.example.com # 来自westdcdb2.example.com # 来自westdc
注意:子组必须先定义,否则会报错。例如清单中写 [dc:children]
后接未定义的 node1
(不是组),会提示 “包含未定义的组”。
范围简写
当主机名或 IP 有规律时,可以用 [start:end]
简写范围(支持数字或字母)。
示例:
# IP范围:192.168.4.0 到 192.168.7.255(包含4-7网段的所有IP)
[priv]
192.168.[4:7].[0:255]# 主机名范围:host01.example.com 到 host20.example.com(01-20的数字)
[hosts]
host[01:20].example.com# 字母范围:servera.example.com 到 serverc.example.com(a-c的字母)
[servers]
server[a:c].example.com
验证范围:
# 列出hosts组的主机(共20台:host01到host20)
[bq@controller ~]$ ansible --list-hosts -i inventory hostshosts (20):host01.example.comhost02.example.com# ...省略中间主机host19.example.comhost20.example.com# 列出servers组的主机(3台:a、b、c)
[bq@controller ~]$ ansible --list-hosts -i inventory servershosts (3):servera.example.comserverb.example.comserverc.example.com
错误示例:不支持混合数字和字母的范围(如 server[0a:2c].example.com
),正确写法是 server[0:2][a:c].example.com
(表示 0-2 数字 + a-c 字母的组合,共 3×3=9 台主机)。
ansible-inventory 命令
用于以不同格式查看清单结构,常用选项如下:
选项 | 功能 |
---|---|
--graph | 以树形结构显示清单(包含组和主机的层级关系) |
--list | 以 JSON 格式显示所有主机信息 |
-y | 与--list 配合,以 YAML 格式显示 |
-i 清单文件 | 指定要查看的清单文件 |
示例:基于如下清单文件操作
app1.example.com # 未分组主机[webservers] # Web服务器组
web1.example.com
web2.example.com
192.168.3.7[dbservers] # 数据库服务器组
db1.example.com
db2.example.com
192.0.2.42[eastdc] # 东DC组
web1.example.com
db1.example.com[westdc] # 西DC组
web2.example.com
db2.example.com[dc:children] # dc组(包含eastdc和westdc子组)
eastdc
westdc
# 树形结构显示清单(清晰展示组和主机的包含关系)
[bq@controller ~]$ ansible-inventory -i inventory --graph
@all: # 所有主机|--@dbservers: # dbservers组| |--192.0.2.42| |--db1.example.com| |--db2.example.com|--@dc: # dc组(父组)| |--@eastdc: # eastdc子组| | |--db1.example.com| | |--web1.example.com| |--@westdc: # westdc子组| | |--db2.example.com| | |--web2.example.com|--@ungrouped: # 未分组主机| |--app1.example.com|--@webservers: # webservers组| |--192.168.3.7| |--web1.example.com| |--web2.example.com# YAML格式显示所有主机信息(更易读的结构化格式)
[bq@controller ~]$ ansible-inventory -i inventory --list -y
all:children: # 所有子组dbservers:hosts: # dbservers组包含的主机192.0.2.42: {}db1.example.com: {}db2.example.com: {}# 其他组信息...
管理 ANSIBLE 配置文件
Ansible 的配置文件用于设置默认参数(如清单路径、远程用户、并发数等),通过配置文件可以简化命令操作。
配置文件位置和优先级
Ansible 会按以下顺序查找配置文件,优先级从高到低:
- 环境变量
ANSIBLE_CONFIG
(指定的配置文件路径) - 当前目录的
./ansible.cfg
(推荐:项目级配置,方便不同项目隔离) - 用户家目录的
~/.ansible.cfg
(用户级配置) - 系统默认的
/etc/ansible/ansible.cfg
(系统级配置)
验证优先级的命令:
# 创建一个项目目录并进入
[bq@controller ~]$ mkdir webapp && cd webapp# 查看当前使用的配置文件(默认是系统级)
[bq@controller webapp]$ ansible --version | grep 'config file'config file = /etc/ansible/ansible.cfg# 创建用户级配置文件后,优先使用用户级
[bq@controller webapp]$ touch ~/.ansible.cfg
[bq@controller webapp]$ ansible --version | grep 'config file'config file = /home/bq/.ansible.cfg# 创建当前目录配置文件后,优先使用当前目录的
[bq@controller webapp]$ touch ansible.cfg
[bq@controller webapp]$ ansible --version | grep 'config file'config file = /home/bq/webapp/ansible.cfg# 通过环境变量指定后,优先使用环境变量指定的
[bq@controller webapp]$ export ANSIBLE_CONFIG=/opt/ansible.cfg
[bq@controller webapp]$ sudo touch /opt/ansible.cfg
[bq@controller webapp]$ ansible --version | grep 'config file'config file = /opt/ansible.cfg
配置文件解析
默认配置文件 /etc/ansible/ansible.cfg
包含多个部分(以 [section]
划分),常用部分及参数如下:
[defaults] # 核心默认配置
# 清单文件路径(默认是/etc/ansible/hosts)
inventory = /etc/ansible/hosts# 并发执行任务的主机数量(默认5台,可根据服务器性能调整)
forks = 5# 检查任务是否完成的时间间隔(秒)
poll_interval = 15# 连接主机时是否提示输入密码(默认False,通过密钥登录时无需密码)
ask_pass = True# 远程登录使用的用户(默认root)
remote_user = root# 是否校验SSH主机密钥(首次连接时的指纹验证,测试环境可设为False)
host_key_checking = False# 日志文件路径(记录ansible命令执行日志)
log_path = /var/log/ansible.log[inventory] # 清单相关配置
# 启用的清单插件(默认支持多种格式)
# enable_plugins = host_list, virtualbox, yaml, constructed[privilege_escalation] # 权限提升配置(sudo相关)
# 是否需要提权(默认False,需要以root执行命令时设为True)
become=True# 提权方式(默认sudo,也可是su、pbrun等)
become_method=sudo# 提权后的用户(默认root)
become_user=root# 提权时是否提示输入密码(默认False,若sudo需要密码则设为True)
become_ask_pass=False
注释说明:配置文件中以 #
或 ;
开头的行为注释,不生效。
配置文件示例
基础使用场景中,只需配置 [defaults]
(清单路径、远程用户)和 [privilege_escalation]
(提权设置)即可。
示例:ansible.cfg
配置文件
[defaults]
inventory = ./inventory # 清单文件在当前目录
remote_user = bq # 远程登录用户为bq(非root)[privilege_escalation]
become = True # 启用提权
become_user = root # 提权到root用户
become_method = sudo # 使用sudo提权
become_ask_pass = False # 提权无需输入密码(前提:bq用户在远程主机的sudoers中配置免密)
效果验证:无需指定 -i
和提权选项,直接执行命令即可用 root 权限操作
[bq@controller webapp]$ ansible all -a id # 对清单中所有主机执行id命令
node3 | CHANGED | rc=0 >>
uid=0(root) gid=0(root) groups=0(root) # 结果显示当前用户为root(提权成功)
# 其他节点输出类似...
ansible-config 命令
用于查看和管理 Ansible 配置,常用子命令如下:
子命令 | 功能 |
---|---|
list | 列出所有配置参数的说明(默认值、环境变量、配置文件位置等) |
dump | 输出当前生效的所有配置(包含默认值和自定义配置) |
view | 查看当前使用的配置文件内容 |
init | 生成配置文件模板(新版本支持) |
示例:
# 生成配置文件模板(保存为ansible.cfg.example)
[bq@controller webapp]$ ansible-config init > ansible.cfg.example# 查看当前使用的配置文件内容
[bq@controller webapp]$ ansible-config view
[defaults]
remote_user = bq
inventory = ./inventory[privilege_escalation]
become = True
become_user = root
become_method = sudo
become_ask_pass = False# 输出当前生效的所有配置(筛选清单路径配置)
[bq@controller webapp]$ ansible-config dump | grep DEFAULT_HOST_LIST
DEFAULT_HOST_LIST(/home/bq/webapp/ansible.cfg) = ['/home/bq/webapp/inventory']# 查看inventory参数的详细说明(默认值、配置位置等)
[bq@controller webapp]$ ansible-config list | grep -A 10 DEFAULT_HOST_LIST
DEFAULT_HOST_LIST:default: /etc/ansible/hostsdescription: Comma separated list of Ansible inventory sourcesenv:- {name: ANSIBLE_INVENTORY}expand_relative_paths: trueini:- {key: inventory, section: defaults}name: Inventory Sourcetype: pathlistyaml: {key: defaults.inventory}
运行 AD HOC 命令
AD HOC 命令是 Ansible 的 “临时命令”,用于快速执行单个任务(无需编写剧本),适合临时操作(如重启服务、检查状态)。
基本格式
ansible <目标主机/组> -m <模块名> -a "<模块参数>" [其他选项]
<目标主机/组>
:清单中定义的主机名、IP 或组名(如node1
、webs
、all
)。-m <模块名>
:指定要使用的模块(如command
、shell
、copy
),默认使用command
模块。-a "<模块参数>"
:模块的参数(如命令内容、文件路径等)。- 其他选项:如
-i
指定清单、-u
指定远程用户等。
命令结果颜色说明
- 红色:执行出错(如命令不存在、权限不足),通常会中止后续任务。
- 绿色:主机状态已符合预期(无需修改)。
- 黄色:命令执行成功且主机状态被修改(达到预期)。
常用模块及命令示例
command 模块
在受管节点执行命令,但不支持 shell 特性(如管道 |
、重定向 >
、环境变量 $PATH
)。
语法:
ansible <目标> -m command -a "命令内容"
示例:
# 在node1主机上执行hostname命令(查看主机名)
[bq@controller webapp]$ ansible node1 -m command -a 'hostname'
node1 | CHANGED | rc=0 >>
node1.bq.cloud # 输出node1的主机名# 简化输出格式(-o选项:单行显示结果)
[bq@controller webapp]$ ansible node1 -m command -a 'hostname' -o
node1 | CHANGED | rc=0 | (stdout) node1.bq.cloud
注意:若未指定 -m
模块,默认使用 command
模块,如 ansible node1 -a 'hostname'
等效于上面的命令。
shell 模块
在受管节点的 shell 中执行命令,支持 shell 特性(管道、重定向、环境变量等)。
语法:
ansible <目标> -m shell -a "命令内容"
示例:
# 尝试用command模块执行shell内置命令set(失败,因为command不支持shell内置命令)
[bq@controller webapp]$ ansible node1 -m command -a set
node1 | FAILED | rc=2 >>
[Errno 2] No such file or directory: 'set': 'set'# 用shell模块执行set(成功,显示环境变量)
[bq@controller webapp]$ ansible node1 -m shell -a set
node1 | CHANGED | rc=0 >>
BASH=/bin/sh
BASHOPTS=cmdhist:complete_fullquote:... # 输出环境变量列表
raw 模块
直接在远程主机的 shell 中执行命令,无需远程主机安装 Python(适合网络设备等特殊场景)。
语法:
ansible <目标> -m raw -a "命令内容"
示例:
# 在node1上创建/tmp/hello.txt文件(用重定向,raw支持shell特性)
[bq@controller webapp]$ ansible node1 -m raw -a 'echo "hello ansible" > /tmp/hello.txt'
node1 | CHANGED | rc=0 >>
Shared connection to node1 closed. # 额外显示连接关闭信息(与shell模块的区别)# 验证文件内容(用默认的command模块)
[bq@controller webapp]$ ansible node1 -a 'cat /tmp/hello.txt'
node1 | CHANGED | rc=0 >>
hello ansible # 内容正确
其他常用模块
模块 | 功能 | 示例 |
---|---|---|
ping | 测试主机连通性(常用作基础测试) | ansible all -m ping (检查所有主机是否在线) |
copy | 从控制节点复制文件到受管节点 | ansible webs -m copy -a "src=/local/file dest=/remote/file" (复制本地文件到 webs 组主机) |
file | 管理文件 / 目录属性(权限、所有者等) | ansible node1 -m file -a "path=/tmp/test state=directory mode=0755" (创建 /tmp/test 目录,权限 755) |
yum | 管理 RPM 系软件包(如 CentOS) | ansible all -m yum -a "name=httpd state=present" (安装 httpd 服务) |
service | 管理系统服务(启动、停止、重启) | ansible all -m service -a "name=httpd state=started enabled=yes" (启动 httpd 并设为开机自启) |
ansible-doc 命令
用于查看模块的帮助文档(用法、参数、示例)。
常用选项:
-l
:列出所有模块及简要说明。-s <模块名>
:显示模块的用法示例(简洁版)。<模块名>
:显示模块的详细文档(参数、示例、返回值等)。
示例:
# 列出所有模块(简化输出,只显示名称和简介)
[bq@controller ~]$ ansible-doc -l | head -n 3 # 只看前3行
fortios_router_community_list Configure community lists i...
azure_rm_devtestlab_info Get Azure DevTest Lab facts
# ...# 查看user模块的用法示例(-s:snippet片段)
[bq@controller ~]$ ansible-doc -s user
- name: Manage user accountsuser:append: # If `yes', add the user to the groups specified in `groups'. If `no', user will only be added to the groups specified in `groups', removing them from all other groups.comment: # Optional comment for the user.create_home: # Whether to create the user's home directory.# ...(其他参数)# 查看user模块的详细文档(包含参数说明、示例、返回值等)
[bq@controller ~]$ ansible-doc user
> USER (/usr/lib/python3.6/site-packages/ansible/modules/system/user.py)Manage user accounts and user attributes. For Windows targets, use the [win_user] module instead.# ...(详细内容)
Ad Hoc 命令常用选项
命令行选项的优先级高于配置文件,常用选项如下:
选项 | 对应配置文件参数 | 功能 |
---|---|---|
-i <清单文件> | inventory | 指定清单文件路径 |
-u <用户> | remote_user | 指定远程登录用户 |
-k | ask_pass | 提示输入 SSH 登录密码 |
-b | become | 启用权限提升(sudo) |
--become-method <方法> | become_method | 指定提权方法(如 sudo) |
--become-user <用户> | become_user | 提权后的目标用户(默认 root) |
-K | become_ask_pass | 提示输入提权密码(sudo 密码) |
示例:
# 用用户test登录node1,提权到root,执行id命令(需输入test的SSH密码和sudo密码)
ansible node1 -i ./inventory -u test -k -b -K -a 'id'
如涉及版权问题,请联系作者处理!!!!!!!!