ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。主要包括:
- 连接插件connection plugins:负责和被监控端实现通信;
- host inventory:指定操作的主机,是一个配置文件里面定义要操作的主机;
- 各种模块核心模块、command模块、shell模块、自定义模块;
- 借助于插件完成记录日志邮件等功能;playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。

官网地址:
https://docs.ansible.com/
二进制文件下载地址:
https://releases.ansible.com/ansible/
参考文档:
http://www.ansible.com.cn/docs
环境准备:
主控端:192.168.170.132 centos7系统,要安装Python,否则会失败
被控端:192.168.170.134 centos7系统,要安装Python,否则会失败
被控端:192.168.170.135 centos7系统,要安装Python,否则会失败
安装:
1、首先在主控端安装ansible(被控端不需要安装),可通过yum进行安装,命令如下:
yum -y install ansible 或者 apt install ansible-core
2、在主控端配置到被控端的ssh免密登录,通过ssh-keygen与ssh-copy-id来实现快速证书的生成以及下发
方法一:
首先在主控端执行命令ssh-keygen命令,在.ssh目录下生成一对密钥,然后通过ssh-copy-id 192.168.170.134/135,然后输入密码将公钥下发的被控端,最后通过ssh 192.168.170.134/192.168.170.135测试是否可以登录。
方法二:
通过编写shell脚本来实现自动下发公钥,脚本内容如下:

上图中的ip.txt内容如下:

上图中实现自动交互输入密码主要通过expect命令实现,通过for循环遍历文件ip.txt中的内容。
使用
老版本Ansible:ansible通过定义好的主机与组规则对匹配的目标主机进行远程操作,老版本的ansible配置文件默认路径是/etc/ansible/hosts(/etc/ansible/ansible.cfg中指定的默认路径)
编辑文件,添加配置如下:

上图中的主机可以使用域名、IP、别名进行标识,其中webservers为组名,后面跟着的主机为其成员,组中的成员也可以使用域名、IP、别名进行标识。如果定义一个192.168.170.135:8000表示定义一个SSH服务端口为8000的主机
测试:
在192.168.170.132机器上,执行命令,测试ansible,如图:

上图中webservers表示组,在/etc/ansible/hosts中定义的,-a后面接主要接模块参数,-m后面接模块名
新版 Ansible:Ubuntu/Debian 的 ansible 从 Ansible 2.12+(ansible-core) 开始包遵循“最小侵入”原则:不自动建目录、不写空配置,Debian / Ubuntu 官方包 不再自动生成:
- /etc/ansible
- /etc/ansible/ansible.cfg
- /etc/ansible/hosts
原因只有一个:避免隐式配置,强制用户明确自己的环境,虽然不创建ansible.cfg,也不影响使用,只是没那么方便,官方推荐采用项目级方式来使用ansible,创建项目目录,如下:
mkdir /data/ansible && cd ansible-demo
在项目目录下定义ansible.cfg文件,写入文件内容,如下:
cat > ansible.cfg <<EOF
# ============================================================
# Ansible 主配置文件(项目级)
# 作用范围:当前目录及其子目录下的所有 ansible / ansible-playbook 命令
# 优先级:ANSIBLE_CONFIG > ./ansible.cfg > ~/.ansible.cfg > /etc/ansible/ansible.cfg
# ============================================================
[defaults]
# ------------------------------------------------------------
# 1. Inventory(机器清单)
# ------------------------------------------------------------
# 可以是:
# - 单个文件:./hosts
# - 目录(推荐):./inventory/
# - 多个来源:./hosts,./inventory/production
#
# 生产建议:用目录,按环境拆分
inventory = ./inventory/production
# ------------------------------------------------------------
# 2. 并发与性能(生产必调)
# ------------------------------------------------------------
# 同时连接多少台主机(默认 5,生产建议 20~50)
forks = 20
# SSH / 连接超时时间(秒)
timeout = 10
# 每个任务最多重试几次(默认 3)
# 网络抖动场景可适当提高
retries = 2
# ------------------------------------------------------------
# 3. SSH 行为
# ------------------------------------------------------------
# 是否检查主机指纹(第一次连接时)
# True = 安全,但自动化会卡住
# False = 自动化友好,内网生产常见选择
host_key_checking = False
# SSH 连接复用(大幅提升执行速度)
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o PreferredAuthentications=publickey
# 管道模式(减少 Python 解释器拷贝,提升性能)
pipelining = True
# ------------------------------------------------------------
# 4. 输出与日志
# ------------------------------------------------------------
# 输出格式(推荐 yaml,比默认 JSON 可读性强)
stdout_callback = yaml
# 显示任务执行时间(排查慢任务很有用)
callback_whitelist = timer, yaml
# 是否显示被控端的差异(diff)
# 对文件/模板变更非常有用
always_show_diff = True
# 日志路径(生产强烈建议开启)
log_path = ./logs/ansible.log
# ------------------------------------------------------------
# 5. 行为与兼容性
# ------------------------------------------------------------
# 是否收集 facts(系统信息)
# 如果 playbook 不需要 {{ ansible_facts }},可设为 False 提速
gathering = smart
fact_caching = jsonfile
fact_caching_connection = ./facts_cache
fact_caching_timeout = 86400
# 是否创建失败重试文件(hosts that failed)
retry_files_enabled = False
# 默认远程用户(如果 inventory 里没指定)
remote_user = ansible
# 默认 SSH 端口(如果 inventory 里没指定)
# remote_port = 22
# ------------------------------------------------------------
# 6. 安全与权限(默认提权)
# ------------------------------------------------------------
# 默认不开启 become,由 playbook 自行决定
# 如果你希望全局默认提权,取消下面注释
# become = True
# become_method = sudo
# become_user = root
# ------------------------------------------------------------
# 7. 模块与插件
# ------------------------------------------------------------
# 角色搜索路径(多个用冒号分隔)
# roles_path = ./roles:~/.ansible/roles:/usr/share/ansible/roles
# 模块过滤(生产安全加固可选)
# 禁止危险模块(示例)
# module_blacklist = shell,command,raw
[privilege_escalation]
# ------------------------------------------------------------
# 提权配置(可被 playbook / task 级别覆盖)
# ------------------------------------------------------------
# become = True
# become_method = sudo
# become_user = root
# become_ask_pass = False
[ssh_connection]
# ------------------------------------------------------------
# SSH 连接优化(生产推荐)
# ------------------------------------------------------------
# 使用 scp 而不是 sftp(某些受限环境更稳定)
# scp_if_ssh = True
# 控制持久化连接的空闲超时
control_path = %(directory)s/%%h-%%r-%%p
# pipelining 已在 [defaults] 开启,这里无需重复
[inventory]
# ------------------------------------------------------------
# Inventory 行为
# ------------------------------------------------------------
# 忽略某些后缀文件(避免误读备份文件)
ignore_files = .git,.bak,~,.retry
# 启用 inventory 插件(2.12+ 推荐)
enable_plugins = host_list,script,auto,yaml,ini,toml
[galaxy]
# ------------------------------------------------------------
# Ansible Galaxy
# ------------------------------------------------------------
# 私有 Galaxy 服务器(企业内网)
# server = https://galaxy.example.com
EOF
✅ 优点:
- 不污染系统
- 多项目互不干扰
- 最适合真实运维/CI
检查ansible.cfg文件的语法是否正确,如下:
ansible-config dump --only-changed
ansible all -m setup | head
新版本的Ansible安装后采用项目级的配置的项目目录结构推荐如下:
project/
├── ansible.cfg
├── inventory/
│ ├── production/ #自定义名字
│ │ ├── hosts.yml #可自定义,表示机器清单
│ │ └── group_vars/ #组级别变量,固定语法,不可自定义
| | └── host_vars/ #主机级变量,固定语法,某台机器的特殊配置
│ └── staging/
├── playbooks/
├── roles/
├── logs/
└── facts_cache/
如果主机清单的文件后缀是yml,那么就要遵循yml的语法来写,如下:
all: #固定写法,老版本都是ini格式的
children: #固定写法
web: #自定义名字
hosts: #固定写法
192.168.1.10:
192.168.1.11:
db:
hosts:
192.168.1.20:
proxy:
hosts:
192.168.1.30:
这文件只干一件事:告诉 Ansible 有哪些机器,分了什么组
inventory/production/group_vars/下的文件名必须跟hosts.yml中组名一一对应,否则不生效
group_vars/
├── all.yml # 所有机器都生效
├── web.yml # 只对 web 组生效
├── db.yml # 只对 db 组生效
└── proxy.yml # 只对 proxy 组生效
group_vars/all.yml(所有机器通用)
ansible_user: ubuntu #远程机器的用户名
ansible_ssh_private_key_file: ~/.ssh/id_rsa #本地ansible机器私钥,公钥要先放到远程机器的authorized_keys文件中
ansible_become: true
ansible_become_method: sudo
group_vars/web.yml(只给 web 组)
http_port: 80
nginx_worker_processes: 4
app_env: production
工作流程:
1. 读 hosts.yml → 找到 web 组有 192.168.1.10、192.168.1.11
2. 读 group_vars/all.yml → 用 ubuntu 用户 + 密钥 + sudo
3. 读 group_vars/web.yml → 加载 web 组专属变量
4. 连上机器,执行命令
ansible常用模块
模块用法可在命令行使用ansible-doc -s 模块名 来获取,如图:

1、script模块
模块包括command、script、shell,都可以实现远程shell命令运行,command作为ansible默认模块,可以执行远程权限范围的所有shell命令(也可以执行脚本),script功能是在远程主机上执行主控端存储的shell脚本文件,相当于shell+script组合,shell功能是执行远程主机的shell脚本文件和命令。
例如:在远程主机135、134上执行192.168.170.132上的脚本文件test.sh,通过script模块,如图:

注意:script命令要执行的脚本是要在ansible管理机器上的,不是远程机器上
在132机器上通过ansible命令在远程主机上执行脚本test.sh,通过shell模块,如图:

注意:shell命令要执行的脚本是在远程机器上的,不是在ansible管理机器上,与script不同
2、copy模块
主要功能是从主控端向目标机器拷贝文件,与scp功能类似,常见参数如下:
- dest:指出复制文件的目标目录位置,使用绝对路径。如果源是目录,则目标也要是目录,如果目标文件已存在,会覆盖原有内容
- src:指出源文件的路径,可以使用相对路径和绝对路径,支持直接指定目录。如果源是目录,则目标也要是目录
- mode:指出复制时,目标文件的权限,可选
- owner:指出复制时,目标文件的属主,可选
- group:指出复制时目标文件的属组,可选
- content:指出复制到目标主机上的内容,不能和src一起使用,相当于复制content指明的数据到目标文件中
- force: 当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否强制覆盖,可选值有yes和no
- backup: 当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否对远程主机的文件进行备份,可选值有yes和no
例如:将132机器上的root目录下的copy文件,拷贝到远程组webservers对应主机的/root目录下,并设置属主以及属组以及文件权限,如图:

下面命令是将content指定的内容复制到远程主机的copy.txt文件中,如下:
#注意:远程主机上只能是文件,因为内容不可能复制到目录中,只能复制到文件中
ansible webservers -m copy -a 'content="china guagndong shenzhen" dest=/tmp/copy.txt'
3、stat模块
主要功能为获取远程文件状态信息,包括atime、ctime、mtime、md5、uid、gid信息
例子:获取远程主机的文件test.sh的时间信息,如图:

4、get_url模块
主要功能为在远程主机下载指定URL地址到本地,支持sha256sum文件校验
例如:在主控端将百度的URL下载到被控端的本地路径,如图:

5、yum模块
yum模块基于yum机制,对远程主机管理程序包。常用的参数如下 :
- name:程序包名称,可以带上版本号。若不指明版本,则默认为最新版本;
- state=present|latest|absent:指明对程序包执行的操作(present表明安装程序包,latest表示安装最新版本的程序包,absent表示卸载程序包)
- disablerepo:在用yum安装时,临时禁用某个仓库的ID
- enablerepo:在用yum安装时,临时启用某个仓库的ID
- conf_file:yum运行时的配置文件,而不是使用默认的配置文件
- disable_gpg_check=yes|no:是否启用完整性校验功能
例如:下面命令表示安装最新版本的httpd服务器,如图:

注意:test为组名,-i 命令意思是指定主机文件,默认情况下是读取的/etc/ansible/hosts文件,通过-i可以指定,可参考ansible常见命令行使用方式 – IT运维 (blog.ywdevops.cn)
6、cron模块
主要功能,执行远程主机的crontab配置
例子:通过主控机向被控机添加crontab定时功能,执行命令如下:
ansible webservers -m cron -a “name=’clear disk’ hour=5 job=’bash /root/aaa.sh'”
上述命令中,name表示说明此脚本是做什么的,会在crontab中作为注释存在,hour表示5个小时,job表示执行脚本位置或者执行命令,执行后在被控端查看crontab,如图;

cron模块参数如下:
- minute:表示设置分,不写默认为*,例如minute=5表示5分钟
- hour:表示时间,例如hour=5,表示5点执行
- day:表示日,例如:day=5表示5号执行
- month:表示月份,例如month=5表示5月执行
- weekday:表示周,例如:weekday=5表示周五执行
例如:下面的例子表示1月10号的5点零5分执行脚本,如图:


7,mount模块:
主要功能为远程主机分区挂载,
下面命令将设备/dev/sd0挂载到/mnt/data目录下,如下:
ansible webservers -m mount -a “name=/mnt/data src=/dev/sd0 fstype=ext4”
8,service 模块
主要功能为远程主机系统服务管理,常见参数如下:
- name:被管理的服务名称
- state=started|stopped|restarted:动作包含启动,关闭或重启
- enable=yes|no:表示是否设置该服务开机自启动
- runlevel:如果设定了enabled开机自启动,则要定义在哪些运行目标下自动启动
例如:通过service模块实现停止tomcat服务,执行命令如下:

9,user服务模块
主要功能为远程主机用户管理,常见参数如下:
- name:必选参数,账号名称
- state=present|absent:创建账号或者删除账号,present表示创建,absent表示删除
- system=yes|no:是否为系统账户
- uid:用户UID
- group:用户的基本组
- groups:用户的附加组
- shell:默认使用的shell
- home:用户的家目录
- mve_home=yes|no:如果设置的家目录已经存在,是否将已存在的家目录进行移动
- pssword:用户的密码,建议使用加密后的字符串
- comment:用户的注释信息
- remore=yes|no:当state=absent时,是否要删除用户的家目录
例如:下面命令表示创建一个用户,并用默认的shell(可以登录),如图:

删除用户并删除用户家目录,命令如下:
ansible test -i gong -m user -a “name=test state=absent remove=yes”
10、shell模块
可直接在远程主机执行任何linux命令和远程主机脚本,例如,查看远程主机的磁盘,如图:

shell支持管道符号、重定向的操作,command命令不支持管道和重定向
11、command模块
command模块也可以在远程主机执行Linux相关命令和远程主机脚本,但是不支持管道符号和重定向等操作,常用参数如下:
- chdir:在远程主机上运行命令前要提前进入的目录;
- creates:在命令运行时创建一个文件,如果文件已存在,则不会执行创建任务;
- removes:在命令运行时移除一个文件,如果文件不存在,则不会执行移除任务;
- executeable:指明运行命令的shell程序;
例如:运行命令前,提前进入机器的根目录,如图:

12、 hostname模块
hostname模块用于管理远程主机上的主机名 ,参数如下:
- name:指明主机名
例如:设置远程主机的主机名为:shenzhen,执行命令如下:

13、template模块
如果你需要拷贝一个静态的文件,那么用copy 模块就够用了。但是如果你需要拷贝一个文件,并且根据需要修改部分内容, 那么就需要用到template模块,template模块同样具备设置文件属主(owner)、属组(group)、权限(mode)、备份(backup)、force(覆盖)等功能,用法可参考copy,template可通过定义yml文件方式,以playbook方式执行
例如:定义template.yml文件,copy路径templates下的file.html文件到远程机器的/tmp路径,并引用远程机器的变量,如图:

file.html文件的内容如下:

执行ansible-playbook template.yml,在远程机器192.168.226.130上查看file.html内容如下:

注意:上述中获取的变量都是facts变量,普通变量可以通过vars关键字定义,yml文件最上面的三个横杠可以不写,那么是区分多个资源文件时才需要写
14、file模块
file 模块设置远程主机上的文件、软链接(symlinks)和文件夹的权限,也可以用来创建和删除他们。(file下的所有操作都是在远程主机执行),参数如下:
- path:必须参数,用于指定要操作的文件或目录
- state:后面可跟touch表示创建文件、directory表示创建目录、absent表示删除文件或目录或链接文件、link表示创建链接文件
- src:当state设置为link或者hard时,表示我们想要创建一个软链或者硬链,所以,我们必须指明软链或硬链链接的哪个文件,通过src参数即可指定链接源
- owner:修改文件或目录的属主
- group:修改文件或目录的属组
- mode:用于指定被操作文件的权限,比如,如果想要将文件权限设置为”
rw-r-x---“,则可以使用mode=650进行设置,或者使用mode=0650,效果也是相同的。如果想要设置特殊权限,比如为二进制文件设置suid,则可以使用mode=4700 - recurse参数:当要操作的文件为目录,将recurse设置为yes,可以递归的修改目录中文件的属性
改变文件的权限:通过mode参数可以修改文件的权限(通过数字设置权限必须以0开头),如图:

结果如下:

创建文件的软链接,playbooks内容如下:

注意:这里面的src和dest参数的含义是和copy 模块不一样的,file模块里面所操作的文件都是远程节点上的文件
运行结果如下:

创建一个新文件,playbooks文件内容如下::

运行结果如下:

创建新的文件夹,playbooks文件内容如下:

运行结果如下:

15、systemd模块
如果使用systemctl 管理程序的话,可以使用systemd模块,systemctl 可以 控制程序启/停,reload,开机启动,观察程序状态(status)等 ,常用参数如下:
- name: 必选,表示要管理的服务名字
- deamon_reload:重新载入服务,值为yes或no
- enabled :是否开机启动,值为yes或no
- state : 管理服务状态,值为( reloaded、restarted、started、stopped )
# 刷新服务
ansible webservers -m systemd -a "deamon_reload=yes"
# 启动服务并开机启动
ansible webservers -m systemd -a "name=nginx enabled=yes state=started"
# 停止服务 开机禁止启动
ansible webservers -m systemd -a "name=nginx enabled=no state=stopped"
# 重启服务
ansible webservers -m systemd -a "name=nginx state=restarted"
16、synchronize模块
Ansible的synchronize模块是一个基于rsync的文件同步模块,它允许您在Ansible控制节点和远程主机之间同步文件和目录。这个模块特别适合于执行增量同步,只传输文件变化的部分,从而提高效率,常用参数如下:
- src: 源文件或目录的路径
dest: 目标文件或目录的路径mode: 同步模式,可以是push(推送模式,从控制节点向远程节点同步)或pull(拉模式,从远程节点向控制节点同步rsync_opts: 传递给rsync的额外选项数组compress: 是否在传输过程中启用压缩,默认为yesrecursive: 是否递归同步子目录,默认为yesdelete: 是否删除目标路径中不存在于源路径的文件,默认为nochecksum: 是否使用文件校验和来决定是否同步,默认为no
例如:将/data/test/目录下的目录同步到远程主机的/data/test目录,但是不包含defg目录,如下:
ansible 192.168.51.207 -m synchronize -a "src=/data/test/ dest=/data/test compress=yes rsync_opts=--exclude=defg"
注意:src=/data/test/后面需要加”/”,如果不加会把test目录名一起同步过去


