一、概述
Ansible 是安装在单个主机(称为控制节点)上的无代理自动化工具。从控制节点,Ansible 可以通过 SSH、Powershell 远程处理和许多其他传输远程管理整个机器和其他设备(称为托管节点),所有这些都来自一个简单的命令行界面,不需要数据库或守护程序。
1.1 控制节(管理端)点安装要求
linux环境
python 3
1.2 受管节点要求
安装SSH,实际使用的是SFTP
二、安装配置
2.1 安装epel源
[root@oral8 ~] # dnf install epel-release
2.2 安装ansible
[root@oral8 ~] # dnf install ansible
查看是否安装成功
[root@oral8 ~]# ansible --version
ansible 2.9.27
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.6/site-packages/ansible
executable location = /usr/bin/ansible
python version = 3.6.8 (default, May 19 2021, 10:00:09) [GCC 8.4.1 20200928 (Red Hat 8.4.1-1.0.1)]
2.3 配置
ansible配置文件将按以下顺序搜索,找到一个可使用的配置后,其它的文件都将被忽略。
- ANSIBLE_CONFIG (如果设置了环境变量)
- ansible.cfg (# 命令执行当前目录中)
- ~/.ansible.cfg (在主目录中)
- /etc/ansible/ansible.cfg # 默认yum安装后生成的配置文件位置
主要配置文件有三个:
- ansible.cfg # ansible的主配置文件,一般使用默认配置。为了避免第一次连接底部,在配置文件中增加一个host_key_checking=False,第一次连接提示输入的Yes/No
- hosts # 主机清单,必要配置文件
- roles # 配置角色的目录,可不做配置
hosts配置内容如下:
[mysql] # 主机组名,下面为mysql组的主机,可以不配置组名,直接在配置文件中添加要管理的主机IP地址
192.168.1.51
192.168.1.52
2.4 测试验证
[root@oral8 ansible_opt]# ansible 192.168.1.51 -a 'hostname'
192.168.1.51 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: root@192.168.1.51: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).",
"unreachable": true
}
出现以上错误是由于默认采用key进行ssh连接主机192.168.1.51。
解决方法有两种:
1、配置免密匙访问
[root@oral8 ansible_opt]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:dUgIGKvcPFKYNiGARlu04H59mkxDcC6N9fV8CjCUgqY root@oral8
The key's randomart image is:
+---[RSA 3072]----+
|*oo+o=o=.o. |
|oo+*Xo..=.o. |
|.oB+o+.. .oo.. |
|.E *+ ...o |
| .+.++ .S . |
| ..o.= |
| + |
+----[SHA256]-----+
# 将控制端生成的密码发给主机192.168.1.51
[root@oral8 ansible_opt]# ssh-copy-id root@192.168.1.51
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.1.51's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'root@192.168.1.51'" and check to make sure that only the key(s) you wanted were added.
2、在连接时指定ssh用户及密码连接。有两种方法
# 1 在执行命令时,指定用户并询问密码. 使用参数-u REMOTE_USER, 指定远程用户(default=None);-k, 连接时询问密码
# 2 在hosts文件中配置以下两行
ansible_ssh_user=root
ansible_ssh_pass=123456
不建议直接配置,明文密码非常危险。建议采用方法一,安全性好。配置好后,再执行
[root@oral8 ansible_opt]# ansible 192.168.1.51 -a ‘hostname’
192.168.1.51 | CHANGED | rc=0 >>
localhost.localdomain
三、ad-hoc命令方式管理
命令格式 : ansible 主机或主机组 模块 命令参数
例: 查看mysql组主机的主机名
命令解释: ansible:命令 mysql:主机名/IP/分组
-m:指定模块(默认是command,可以不写,推荐使用shell模块,) shell:模块名称
-a:模块参数 hostname:参数值,远程执行的命令
执行命令返回的结果颜色代表的含义:
绿色:正常执行,没有被修改
黄色:正常执行,有被管理端发生变更
红色:执行出现错误
紫色:表示警告或建议
常用连接选项:
参数说明-k, --ask-pass要求用户输入请求连接密码–private-key=PRIVATE_KEY_FILE,
--key-file=PRIVATE_KEY_FILE私钥路径,使用这个文件来验证连接-u REMOTE_USER,
–user=REMOTE_USER连接用户-T TIMEOUT, --timeout=TIMEOUT指定默认超时时间,默认是10S
四、常用模块介绍
ansible官方存在大量的模块,我们使用ansible主要使用的也是因为它有大量的模块和插件,虽然模块很多,但是我们常用的模块就那么几种,下面介绍以下常用模块:
模块名 | 说明 |
command(默认) | 不支持管道过滤、grep,等一些特殊符号 |
shell | 支持管道过滤、grep ,推荐使用,执行脚本时,执行必须在被管理端 |
script | 不用把脚本复制到远程主机就可以在远程主机执行脚本 |
yum | 软件包安装卸载 |
yum_repository | 配置yum源 |
copy | 拷贝文件到远程主机 |
file | 在远程主机创建目录或者文件 |
service | 启动或停止服务,redhat6及以上版本使用 |
systemd | 启动或停止服务,redhat7及以上版本使用 |
get_url | 下载文件到远程主机 |
cron | 执行定时任务 |
firewalld | 防火墙设置 |
4.1 command模块
用于执行简单的不带特殊符号的命令,默认使用该模块
例: 查看所有主机的主机名
[root@oral8 ansible_opt]# ansible all -m command -a 'hostname'
192.168.1.52 | CHANGED | rc=0 >>
mysql52
192.168.1.51 | CHANGED | rc=0 >>
localhost.localdomain
192.168.1.61 | CHANGED | rc=0 >>
node1
192.168.1.62 | CHANGED | rc=0 >>
node2
192.168.1.63 | CHANGED | rc=0 >>
node3
192.168.1.70 | CHANGED | rc=0 >>
k8s-master
ansible all -a ‘hostname’ 与ansible all -m command -a ‘hostname’
命令相同,默认command可以省略
4.2 shell模块
shell模块有command模块的所有功能,并且可以执行特殊符号的命令及脚本,对于windows主机需要使用win_shell
查看所有主机的主机名
[root@oral8 ansible_opt]# ansible all -m shell -a 'hostname'
192.168.1.52 | CHANGED | rc=0 >>
mysql52
192.168.1.61 | CHANGED | rc=0 >>
node1
192.168.1.62 | CHANGED | rc=0 >>
node2
192.168.1.63 | CHANGED | rc=0 >>
node3
192.168.1.51 | CHANGED | rc=0 >>
localhost.localdomain
192.168.1.70 | CHANGED | rc=0 >>
k8s-master
查看是否安装mysql
[root@oral8 ansible_opt]# ansible 192.168.1.51 -m shell -a 'rpm -qa|grep mysql'
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'. If you need to use command because yum, dnf or zypper is insufficient you
can add 'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
192.168.1.51 | CHANGED | rc=0 >>
mysql57-community-release-el7-10.noarch
mysql-community-server-5.7.37-1.el7.x86_64
mysql-community-common-5.7.37-1.el7.x86_64
mysql-community-libs-5.7.37-1.el7.x86_64
mysql-community-client-5.7.37-1.el7.x86_64
4.3 copy模块
远程文件传输模块,将本地或远程的文件copy到指定位置,也可以直接向目录主机文件写入内容。windows使用win_copy
参数 | 选项 | 含义 |
src | 源目录或文件,如果源是目录,将copy目录 | |
dest | 目标目录或文件,必要参数 | |
remote_src | True、False | src是远程主机上还是在当前主机上,仅在mode=preserve有效 |
owner | 所属用户 | |
group | 所属组 | |
mode | 0655、u=rw、u+rw | 设置文件权限 |
backup | yes、no | 是否备份目标文件 |
content | 将文件的内容直接目标主机文件中,如果文件存在,则会替换原有的文件内容,如果文件不存在,则创建文件。使用content时,不要同时使用src参数。 |
将当前目录的test文件传输到192.168.1.51的tmp下
[root@oral8 ansible_opt]# ansible 192.168.1.51 -m copy -a 'src=test dest=/tmp '
192.168.1.51 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "62dc7430288794d85d09f2ec872de61e6f2fbf0a",
"dest": "/tmp/test",
"gid": 0,
"group": "root",
"md5sum": "b8d7b9f1635cc45353e1104b57b9bbd0",
"mode": "0644",
"owner": "root",
"secontext": "unconfined_u:object_r:admin_home_t:s0",
"size": 15,
"src": "/root/.ansible/tmp/ansible-tmp-1652669747.0875425-72927-162790753036419/source",
"state": "file",
"uid": 0
}
查看test是否copy到192.168.1.51上
[root@oral8 ansible_opt]# ansible 192.168.1.51 -m shell -a 'ls /tmp'
192.168.1.51 | CHANGED | rc=0 >>
agent.sock
ansible_command_payload_XOLGiR
systemd-private-b1811965a62647e6b28e8b1c5b9960fe-chronyd.service-g6db8J
systemd-private-b1811965a62647e6b28e8b1c5b9960fe-cups.service-zjQN56
systemd-private-b1811965a62647e6b28e8b1c5b9960fe-vgauthd.service-tzxXHN
systemd-private-b1811965a62647e6b28e8b1c5b9960fe-vmtoolsd.service-7XR4rR
test
拷贝test到目标机器,并指定所有者,所有组并给定权限为600
[root@oral8 ansible_opt]# ansible 192.168.1.51 -m copy -a 'src=test dest=/tmp/ backup=yes owner=mysql group=mysql mode=600'
192.168.1.51 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "62dc7430288794d85d09f2ec872de61e6f2fbf0a",
"dest": "/tmp/test",
"gid": 27,
"group": "mysql",
"mode": "0600",
"owner": "mysql",
"path": "/tmp/test",
"secontext": "unconfined_u:object_r:admin_home_t:s0",
"size": 15,
"state": "file",
"uid": 27
}
查看远程主机上文件test文件
[root@oral8 ansible_opt]# ansible 192.168.1.51 -a 'ls -l /tmp/test'
192.168.1.51 | CHANGED | rc=0 >>
-rw-------. 1 mysql mysql 15 5月 16 10:55 /tmp/test
在远程主机创建一个文件并写入内容
[root@oral8 ansible_opt]# ansible 192.168.1.51 -m copy -a 'content=hellworld dest=/tmp/test'
192.168.1.51 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "b1a4b17bfcfc4c8c80f02ad7b48a1f0491d1b874",
"dest": "/tmp/test",
"gid": 27,
"group": "mysql",
"md5sum": "0c2aa4b059c95e3c034f696834f6523f",
"mode": "0600",
"owner": "mysql",
"secontext": "unconfined_u:object_r:admin_home_t:s0",
"size": 9,
"src": "/root/.ansible/tmp/ansible-tmp-1652671205.2719164-73417-10527535059685/source",
"state": "file",
"uid": 27
}
查看目标主机是否写入
[root@oral8 ansible_opt]# ansible 192.168.1.51 -a 'cat /tmp/test'
192.168.1.51 | CHANGED | rc=0 >>
hellworld
4.4 file模块
创建、删除、或修改文件属性或创建链接文件
参数 | 含义 |
path | 路径(文件或目录),必须项 |
src | 源文件,用于创建软链接 |
state | 模式状态: directory 创建目录 file 更新文件,如果文件不存在也不创建 link 创建软链接 touch 创建文件 absent 删除 |
testfile目录
[root@oral8 ansible_opt]# ansible 192.168.1.51 -m file -a ' path=/tmp/testfile state=directory '
192.168.1.51 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/tmp/testfile",
"secontext": "unconfined_u:object_r:user_tmp_t:s0",
"size": 6,
"state": "directory",
"uid": 0
}
创建文件
[root@oral8 ansible_opt]# ansible 192.168.1.51 -m file -a ' path=/tmp/testfile/one state=touch'
192.168.1.51 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/tmp/testfile/one",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"secontext": "unconfined_u:object_r:user_tmp_t:s0",
"size": 0,
"state": "file",
"uid": 0
}
修改目录及子文件权限
使用recurse时,state必须为directory。 recurse=yes 设置递归,默认为no
[root@oral8 ansible_opt]# ansible 192.168.1.51 -m file -a ' path=/tmp/testfile mode=700 state=directory recurse=yes'
192.168.1.51 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0700",
"owner": "root",
"path": "/tmp/testfile",
"secontext": "unconfined_u:object_r:user_tmp_t:s0",
"size": 17,
"state": "directory",
"uid": 0
}
删除文件及目录
当path为目录时,将递归删除目录及子目录文件
[root@oral8 ansible_opt]# ansible 192.168.1.51 -m file -a ' path=/tmp/testfile state=absent'
192.168.1.51 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"path": "/tmp/testfile",
"state": "absent"
}
4.5 systemd模块
适应于systemd管理的系统服务管理,如:redhat7及以上系统。
services 管理的主机使用 service模块 进行管理,如redhat6、centos6及以下的系统,方法及参数与systemd一样。
参数 | 选项 | 含义 |
name | 服务名,必须项 | |
state | reloaded、restarted、started、stopped | 重载配置、重启、启动、停止服务state参数与enabled参数二选一 |
enabled | 开机启动服务。state参数与enabled参数二选一 |
停止mysql服务
[root@oral8 ansible_opt]# ansible 192.168.1.51 -m systemd -a 'name=mysqld state=stopped'
192.168.1.51 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"name": "mysqld",
"state": "stopped",
"status": {
"ActiveEnterTimestamp": "一 2022-04-25 10:46:49 CST",
"ActiveEnterTimestampMonotonic": "18809490427",
"ActiveExitTimestampMonotonic": "0",
"ActiveState": "active",
.... 中间部分太长省略
}
}
4.6 yum模块
参数 | 选项 | 含义 |
name | nginx、git、… | 软件包名称或url |
state | installed、present(默认)、remove、absent、latest | 安装、删除、最新版。installed与present相同,remove与absent相同 |
list | 要查看的软件包名 | |
download_only | Yes、no | 仅下载软件包,不安装 |
安装最新版的nginx
[root@oral8 ansible_opt]# ansible 192.168.1.52 -m yum -a "name=nginx state=latest"
删除nginx软件包
[root@oral8 ansible_opt]# ansible 192.168.1.52 -m yum -a "name=nginx state=absent"
查看是否安装mysql
[root@oral8 ansible_opt]# ansible 192.168.1.52 -m yum -a 'list=mysql'
192.168.1.52 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"results": [
{
"arch": "x86_64",
"envra": "0:mysql-community-client-8.0.25-1.el7.x86_64",
"epoch": "0",
"name": "mysql-community-client",
"release": "1.el7",
"repo": "installed",
"version": "8.0.25",
"yumstate": "installed"
}
]
}
4.7 yum_repository模块
yum_repository用于添加或删除yum源仓库
参数 | 含义 |
name | yum仓库名,必须项 |
description | 仓库描述内容 |
baseurl | yum源中baseurl地址 |
enabled | 是否启动这个源 |
gpgcheck | 是否启动gpgcheck功能 |
file | yum源文件名,默认与模块名(name)一致 |
创建一个test_yum的仓库
[root@oral8 ansible_opt]# ansible 192.168.1.51 -m yum_repository -a 'name=test_yum description="this is test yum response" baseurl="http://123.com" enabled=yes gpgcheck=yes '
192.168.1.51 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"repo": "test_yum",
"state": "present"
}
4.7 get_url模块
get_url从 HTTP、HTTPS 或 FTP 下载文件到远程服务器机指定目录
参数 | 含义 |
url | 指定要下载的地址,必须项 |
dest | 指定下载文件保存目录,必须项 |
下载nginx
[root@oral8 ansible_opt]# ansible 192.168.1.51 -m get_url -a 'url="http://nginx.org/download/nginx-1.20.2.zip" dest=/opt/'
192.168.1.51 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum_dest": null,
"checksum_src": "3670568e32b40fb9cd0166879f3f35b8df6b8522",
"dest": "/opt/nginx-1.20.2.zip",
"elapsed": 9,
"gid": 0,
"group": "root",
"md5sum": "2172359f411c60e133c672ab6904000d",
"mode": "0644",
"msg": "OK (1730766 bytes)",
"owner": "root",
"secontext": "system_u:object_r:usr_t:s0",
"size": 1730766,
"src": "/root/.ansible/tmp/ansible-tmp-1652692625.2139606-76577-253705425909810/tmpi5INCw",
"state": "file",
"status_code": 200,
"uid": 0,
"url": "http://nginx.org/download/nginx-1.20.2.zip"
五、收集远程主机信息模块
收集远程主机信息模块有两个:setup、gather_facts(在ansible2.8版后新增功能),实现两个获取的内容是一样的。
常用参数主要是filter对收集的信息进行过滤。要查询模块下的子模块,中间用点加子模块名即可。
在执行ansible命令时,默认是先收集远程主机信息后再执行相关模块的命令,如果需要提高执行速度,可以在ansilbe.cfg配置文件中添加一行gathering = explicit
#smart 表示默认收集 facts,但 facts 已有的情况下不会收集,即使用缓存 facts
#implicit 表示默认收集 facts,要禁止收集,必须使用 gather_facts: False
#explicit 则表示默认不收集,要显式收集,必须使用 gather_facts: Ture
或者在ansible-play的yaml脚本中增加一行gather_facts no
[root@oral8 ansible_opt]# ansible 192.168.1.51 -m gather_facts
#查看远程主机内存信息
[root@oral8 ansible_opt]# ansible 192.168.1.51 -m gather_facts -a 'filter=ansible_*_mb'
192.168.1.51 | SUCCESS => {
"ansible_facts": {
"ansible_memfree_mb": 2513,
"ansible_memory_mb": {
"nocache": {
"free": 3323,
"used": 468
},
"real": {
"free": 2513,
"total": 3791,
"used": 1278
},
"swap": {
"cached": 8,
"free": 3889,
"total": 3967,
"used": 78
}
},
"ansible_memtotal_mb": 3791,
"ansible_swapfree_mb": 3889,
"ansible_swaptotal_mb": 3967,
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"deprecations": [],
"warnings": []
}
常用模块过滤参数
参数名 | 查询内容 |
ansible_all_ipv4_addresses | 仅显示ipv4的信息 |
ansible_devices | 仅显示磁盘设备信息 |
ansible_distribution | 显示是什么系统,例:centos,suse等 |
ansible_distribution_major_version | 显示是系统主版本 |
ansible_distribution_version | 仅显示系统版本 |
ansible_machine | 显示系统类型,例:32位,还是64位 |
ansible_eth0 | 仅显示eth0的信息 |
ansible_hostname | 仅显示主机名 |
ansible_kernel | 仅显示内核版本 |
ansible_lvm | 显示lvm相关信息 |
ansible_memtotal_mb | 显示系统总内存 |
ansible_memfree_mb | 显示可用系统内存 |
ansible_memory_mb | 详细显示内存情况 |
ansible_swaptotal_mb | 显示总的swap内存 |
ansible_swapfree_mb | 显示swap内存的可用内存 |
ansible_mounts | 显示系统磁盘挂载情况 |
ansible_processor | 显示cpu个数(具体显示每个cpu的型号) |
ansible_processor_vcpus | 显示cpu个数(只显示总的个数) |