前言:你还在手动管理上百台服务器吗?
还记得我刚入行做运维的时候,公司业务刚起步,整个团队只有 5 台服务器,那时候觉得手动管理也没什么,装个 Nginx、改个配置,SSH 上去输两行命令就搞定了。
结果不到半年,业务爆发式增长,服务器一下子从 5 台涨到了 120 台,那时候刚好赶上 Nginx 出了一个高危漏洞,要紧急更新所有服务器的 Nginx 版本。我从早上 9 点开始,一台台 SSH 登录,输命令,装包,重启服务,搞到下午 6 点,才更了 80 多台,累的腰都直不起来,结果晚上线上还出了问题 ------ 我漏了两台边缘服务器没更,被黑客扫到了漏洞,差点搞出大事故。
那时候我就想,难道就没有什么办法,能让我一键搞定所有服务器的操作吗?不用再一台台重复劳动,不用再怕漏了哪台,不用再熬夜加班?
后来我接触到了 Ansible,用了之后才发现,原来原来一天的活,现在 10 分钟就能搞定!原来要手动做的初始化、装软件、改配置,现在写个脚本,点一下执行,所有服务器自动就完成了,效率直接提升了 10 倍都不止。
这篇文章,我就把我这几年用 Ansible 的经验,从 0 到 1,全部教给你,不管你是刚入行的运维新手,还是已经做了几年的老运维,都能跟着这篇文章,直接把自动化用起来,全程无坑,我踩过的所有坑,都会在文章里告诉你,让你少走弯路。
一、Ansible 是什么?为什么选它?
可能还有朋友不太了解 Ansible,我先简单给大家介绍一下:
Ansible 是 RedHat 旗下的一款开源自动化运维工具,它的核心特点就是简单、无代理、上手快。
和其他的自动化工具比如 SaltStack、Puppet 比起来,Ansible 真的太友好了:
-
不用装客户端:你不需要在每台被管理的服务器上装任何 Agent,只要你的服务器开了 SSH 服务,能正常连接,Ansible 就能管理它,不管是 Linux、Windows 还是 Mac,都能管。
-
上手极快:Ansible 用的是 YAML 语法,写的配置文件普通人看一眼就能懂,不用学什么复杂的 DSL,新手几个小时就能上手写自己的脚本。
-
功能强大:从简单的批量执行命令,到复杂的服务部署、集群配置,Ansible 都能搞定,而且有海量的现成模块,不用你自己写脚本。
-
生态完善:官方有上千个现成的模块,还有 Ansible Galaxy,上面有无数开发者分享的现成角色,你要装什么服务,直接下载就能用,不用自己从零写。
现在不管是中小团队,还是像腾讯、阿里这样的大厂,都在大量用 Ansible 做自动化运维,它真的是能让你从重复的手动劳动里解放出来的神器。
二、环境准备:从 0 搭建 Ansible 管理环境
好了,废话不多说,我们直接开始动手,先把 Ansible 的环境搭起来。
2.1 控制节点安装 Ansible
首先,Ansible 的架构是控制节点 + 被管理节点,控制节点就是你自己的工作机,你在这台机器上装 Ansible,然后用它来管理其他所有的服务器。
控制节点的安装很简单,不同的系统有不同的安装方式,我都给你列出来了,你照着自己的系统来就行:
CentOS/RHEL 系统
# 先安装EPEL源
yum install -y epel-release
# 然后安装Ansible
yum install -y ansible
Ubuntu/Debian 系统
# 添加Ansible的官方源
apt-add-repository --yes --update ppa:ansible/ansible
# 安装Ansible
apt install -y ansible
Mac 系统
如果你用 Mac 做控制节点,用 Homebrew 安装就行:
brew install ansible
Windows 系统
Windows 的话,建议你用 WSL2,装个 Ubuntu 子系统,然后按照上面 Ubuntu 的方法安装就行,当然你也可以用 pip 安装:
pip install ansible
安装完之后,你可以执行ansible --version来检查有没有安装成功,如果能输出版本号,就说明装好了:
$ ansible --version
ansible [core 2.16.6]
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.9/site-packages/ansible
ansible collection location = /root/.ansible/collections
executable location = /usr/bin/ansible
python version = 3.9.18 (main, Mar 12 2024, 13:13:32) [GCC 11.2.0]
jinja version = 3.1.4
libyaml = True
2.2 被管理节点的要求
说完控制节点,再说说被管理的节点,也就是你要管理的那些服务器,它们的要求真的非常低:
-
开启 SSH 服务,能让控制节点 SSH 连接上去就行
-
安装了 Python 2.6 或者更高的版本,现在的 CentOS7、Ubuntu20.04 这些默认都带了,不用你额外装
就这两个要求,没有别的了,不用装任何客户端,不用开任何额外的端口,是不是超级简单?
2.3 配置 SSH 免密登录,告别输密码
接下来,我们要配置 SSH 免密登录,不然你每次执行 Ansible 命令,都要给每台服务器输一遍密码,100 台服务器你就要输 100 次,那也太麻烦了。
配置免密登录的步骤很简单:
-
首先在控制节点上生成 SSH 密钥,执行这个命令,一路回车就行:
ssh-keygen -
然后把你的公钥拷贝到每台被管理的服务器上,用
ssh-copy-id命令:
cpp
ssh-copy-id root@192.168.1.101
ssh-copy-id root@192.168.1.102
# ... 所有的服务器都执行一遍
这里给大家提个我踩过的坑:如果你的服务器很多,一个个输太麻烦,你可以写个小循环批量执行:
cppfor ip in 192.168.1.{101..200}; do ssh-copy-id root@$ip done这样 100 台服务器的密钥,一下就传完了。
如果你的服务器没有ssh-copy-id命令,也可以手动拷贝: 把控制节点~/.ssh/id_rsa.pub的内容,加到被管理节点的~/.ssh/authorized_keys文件里就行。
还有一个很常见的坑:很多人配置完免密,还是要输密码,那大概率是权限不对!SSH 对权限的要求很严格,.ssh目录的权限必须是 700,authorized_keys的权限必须是 600,不然 SSH 会认为这个文件不安全,拒绝免密登录。你在被管理节点执行这两个命令就行:
cpp
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
配置完之后,你测试一下,执行ssh root@你的服务器IP,如果不用输密码就能直接登录,就说明免密配置成功了。
2.4 主机清单 Inventory:把你的服务器分组管理
接下来,我们要配置主机清单,也就是告诉 Ansible,你有哪些服务器要管理,这些服务器怎么分组。
主机清单的配置文件,默认是/etc/ansible/hosts,你也可以自己写一个,比如在你的工作目录下建一个inventory.ini文件,这样更方便管理。
编辑这个文件,内容大概是这样的:
cpp
# Ansible 主机清单 Inventory
# Web服务器组,所有的Web服务器都放在这里
[webservers]
192.168.1.101
192.168.1.102
192.168.1.103
192.168.1.104
...
# 这里可以把你所有的Web服务器IP都列出来,100台也没问题
# 数据库服务器组,所有的数据库服务器放在这里
[dbservers]
192.168.1.201
192.168.1.202
192.168.1.203
...
是不是很简单?你可以把你的服务器按照业务分组,比如 Web 组、DB 组、缓存组、监控组,这样以后你就可以针对某个组执行操作,比如只给 Web 组装 Nginx,只给 DB 组装 MySQL,不用每次都操作所有服务器。

2.5 测试连通性:确认所有服务器都能连上
配置完主机清单,我们来测试一下,Ansible 能不能连上所有的服务器,执行这个命令:
cpp
ansible all -m ping -i inventory.ini
这个命令的意思是,对所有的服务器,执行 ping 模块,测试连通性。
如果一切正常的话,你会看到下面这样的输出:

看到了吗?100 台服务器,全部都返回了 pong,说明所有的服务器都能正常连接,没有问题!到这里,我们的 Ansible 环境就已经搭好了,是不是比你想象的简单多了?
三、Ansible 基础:Ad-Hoc 命令,批量操作随手来
环境搭好了,我们先从最简单的 Ad-Hoc 命令开始学,这个是日常运维用的最多的,很多临时的操作,不用写脚本,输一行命令就搞定了。
3.1 什么是 Ad-Hoc 命令?
Ad-Hoc 命令说白了,就是临时执行的命令,你不需要写任何脚本,直接在命令行输 Ansible 命令,就能批量在所有服务器上执行操作,非常适合临时的、一次性的任务。
比如你突然要查一下所有服务器的磁盘够不够,或者要重启一下所有服务器的 Nginx,这时候用 Ad-Hoc 命令,一行就搞定了,比你写 Playbook 还快。
3.2 常用 Ad-Hoc 命令实战,日常运维够用了
我给大家整理了几个日常运维最常用的 Ad-Hoc 命令,你学会这些,日常的临时操作就都够用了:
1. 批量查看所有服务器的磁盘使用率
cpp
ansible all -m shell -a "df -h" -i inventory.ini
这个命令会在所有服务器上执行df -h,然后把结果返回给你,不用你一台台登上去看了。
2. 批量重启所有 Web 服务器的 Nginx
cpp
ansible webservers -m service -a "name=nginx state=restarted" -i inventory.ini
针对 webservers 组,重启 Nginx 服务,一行命令,所有 Web 服务器的 Nginx 就都重启好了。
3. 批量把本地文件拷贝到所有服务器
cpp
ansible all -m copy -a "src=/local/your/file.txt dest=/tmp/file.txt mode=0644" -i inventory.ini
把你本地的文件,批量拷贝到所有服务器的 /tmp 目录,还能顺便设置权限,太方便了。
4. 批量检查所有服务器的 8080 端口有没有打开
cpp
ansible all -m shell -a "netstat -tlnp | grep 8080" -i inventory.ini
批量检查端口,看看你的服务有没有正常启动。
5. 批量更新所有服务器的系统包
cpp
ansible all -m yum -a "name=* state=latest" -i inventory.ini
批量更新所有服务器的系统,一键搞定,不用你一台台更。
6. 批量重启所有服务器
cpp
ansible all -m shell -a "reboot" -i inventory.ini
如果要重启所有服务器,也是一行命令的事。
这些命令是不是都很简单?日常运维的大部分临时操作,用这些命令都能搞定,原来要半小时的活,现在 10 秒钟就搞定了。
3.3 最常用的 5 个 Ansible 模块,学会就能解决 80% 的问题
Ansible 的模块有上千个,但是你不用都学,我告诉你,只要学会这 5 个最常用的模块,你就能解决 80% 的运维问题:
-
shell 模块:执行 Shell 命令,这个是最常用的,你要执行什么自定义的命令,都用这个模块。
-
copy 模块:拷贝文件,把本地的文件拷贝到远程服务器,还能设置权限。
-
file 模块:管理文件和目录,比如创建目录、删除文件、修改权限。
-
service 模块:管理服务,启动、停止、重启服务,设置开机自启。
-
yum/apt 模块:安装软件包,yum 用来管理 CentOS 的包,apt 用来管理 Ubuntu 的包。
就这 5 个模块,真的够你用了,剩下的模块,你用到的时候再查就行,不用提前记。
四、核心实战:Playbook 编写,一键部署不是梦
Ad-Hoc 命令适合临时操作,但是如果是复杂的、重复的任务,比如部署服务、初始化服务器,那就要用 Playbook 了,这个是 Ansible 的核心,也是实现一键部署的关键。
4.1 Playbook 是什么?YAML 语法快速入门
Playbook 说白了,就是把你要执行的任务,写成一个 YAML 格式的文件,Ansible 会按照你写的顺序,在所有服务器上依次执行这些任务,你写完之后,只要执行一次,所有的任务就自动完成了。
YAML 语法非常简单,你只要记住这几点就行:
-
缩进用空格,不能用 Tab,一般用 2 个或者 4 个空格
-
键值对用
key: value的格式,冒号后面要加空格 -
列表用
-开头,比如- name: 安装Nginx
就这么简单,新手看一眼就能学会,根本不用花时间学语法。
4.2 第一个 Playbook:批量安装 Nginx,一步到位
我们先来写第一个 Playbook,批量给所有 Web 服务器安装 Nginx,这个是最常用的,我们一步一步来。
首先,创建一个install_nginx.yml文件,内容如下:
XML
---
- name: 批量安装并配置Nginx
hosts: webservers # 针对webservers组的服务器
become: yes # 提权,用root用户执行,因为装软件需要root权限
tasks: # 任务列表,Ansible会按顺序执行这些任务
# 任务1:安装Nginx软件包
- name: 安装Nginx软件包
ansible.builtin.yum:
name: nginx
state: present
# 任务2:复制Nginx配置文件
- name: 复制Nginx配置文件
ansible.builtin.copy:
src: ./nginx.conf # 你本地的Nginx配置文件
dest: /etc/nginx/nginx.conf # 远程服务器的目标路径
mode: '0644' # 文件权限
notify: 重启Nginx服务 # 如果配置文件变了,就触发重启Nginx的触发器
# 任务3:启动Nginx服务,设置开机自启
- name: 启动Nginx服务,并设置开机自启
ansible.builtin.service:
name: nginx
state: started
enabled: yes
# 触发器,只有配置文件变化的时候才会执行
handlers:
- name: 重启Nginx服务
ansible.builtin.service:
name: nginx
state: restarted
写完之后,你的文件大概是这个样子的,在 VS Code 里还有语法高亮,非常清晰:

这个 Playbook 是什么意思呢?我给你解释一下:
-
首先,我们针对 webservers 组的服务器,用 root 权限执行
-
第一个任务,用 yum 安装 Nginx 软件包
-
第二个任务,把你本地的 Nginx 配置文件,拷贝到所有服务器上,如果配置文件有变化,就触发重启 Nginx 的触发器
-
第三个任务,启动 Nginx 服务,并且设置开机自启
-
handlers 里的触发器,只有当配置文件真的变了的时候,才会重启 Nginx,如果配置文件没变化,就不会重启,不会影响线上的服务,是不是很智能?
然后,你只要执行这个命令,就能一键安装所有 Web 服务器的 Nginx 了:
XML
ansible-playbook install_nginx.yml -i inventory.ini
然后你就等着就行,Ansible 会自动在所有 100 台 Web 服务器上执行这些任务,原来你要一天才能干完的活,现在 10 分钟就搞定了,而且不会出错,不会漏服务器。
4.3 进阶:用 Template 模板,动态生成配置文件
刚才我们用 copy 模块拷贝配置文件,是所有服务器用同一个配置,但是如果你的服务器配置不一样,比如有的 Web 服务器端口是 80,有的是 8080,那怎么办?
这时候就要用 Template 模板了,你可以写一个模板文件,里面用变量,Ansible 会根据不同的服务器,自动替换变量,生成不同的配置文件,超级灵活。
比如,我们写一个 Nginx 的模板文件,叫nginx.conf.j2,里面的内容是这样的:
java
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen {{ nginx_port }}; # 这里用变量,不同的服务器可以不一样
server_name {{ nginx_domain }};
root {{ nginx_root }};
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
}
看到了吗?里面的{``{ nginx_port }}、{``{ nginx_domain }}这些都是变量,然后你在 Playbook 里定义这些变量,不同的服务器用不同的变量值,Ansible 就会自动生成不同的配置文件了。
比如你的 Playbook 里可以这么写:
java
vars: nginx_port: 80 nginx_domain: www.test.com nginx_root: /var/www/html
然后用 template 模块代替 copy 模块:
java
- name: 部署Nginx配置文件
ansible.builtin.template:
src: ./nginx.conf.j2
dest: /etc/nginx/nginx.conf
mode: '0644'
notify: 重启Nginx服务
这样,Ansible 就会自动把变量替换进去,生成对应的配置文件,是不是超级灵活?不管你的服务器有多少种不同的配置,都能搞定。
4.4 实战 2:批量安装 JDK,配置 Java 环境
装完 Nginx,我们再来装 JDK,很多 Java 项目都需要 Java 环境,我们写个 Playbook,批量给所有服务器装 JDK8:
java
---
- name: 批量安装JDK8
hosts: all
become: yes
vars:
jdk_version: "1.8.0_401"
jdk_install_dir: /usr/local/jdk
tasks:
# 1. 创建JDK安装目录
- name: 创建JDK安装目录
ansible.builtin.file:
path: "{{ jdk_install_dir }}"
state: directory
mode: '0755'
# 2. 解压JDK安装包
- name: 解压JDK安装包到目标目录
ansible.builtin.unarchive:
src: ./jdk-8u401-linux-x64.tar.gz # 你本地的JDK安装包
dest: "{{ jdk_install_dir }}"
remote_src: no
creates: "{{ jdk_install_dir }}/jdk1.8.0_401" # 如果已经存在就跳过,不用重复解压
# 3. 配置Java环境变量
- name: 配置Java环境变量
ansible.builtin.lineinfile:
path: /etc/profile
line: |
export JAVA_HOME={{ jdk_install_dir }}/jdk1.8.0_401
export PATH=$PATH:$JAVA_HOME/bin
state: present
# 4. 刷新环境变量
- name: 刷新环境变量
ansible.builtin.shell: source /etc/profile
args:
executable: /bin/bash
这个 Playbook,会自动创建目录,解压 JDK,配置环境变量,所有服务器的 Java 环境一键就装好了,原来你手动装,一台要 5 分钟,100 台要 500 分钟,现在 5 分钟就搞定了。
4.5 实战 3:批量安装 MySQL,初始化数据库
接下来,我们来装 MySQL,这个稍微复杂一点,但是用 Playbook,也能一键搞定:
java
---
- name: 批量安装MySQL8.0
hosts: dbservers
become: yes
vars:
mysql_root_password: "YourStrongRootPassword123!" # 你的root密码,改成自己的
tasks:
# 1. 安装MySQL的Yum源
- name: 安装MySQL Yum源
ansible.builtin.yum:
name: https://dev.mysql.com/get/mysql80-community-release-el7-7.noarch.rpm
state: present
# 2. 安装MySQL服务器
- name: 安装MySQL社区版服务器
ansible.builtin.yum:
name: mysql-community-server
state: present
# 3. 启动MySQL服务,设置开机自启
- name: 启动MySQL服务,并设置开机自启
ansible.builtin.service:
name: mysqld
state: started
enabled: yes
# 4. 等待MySQL初始化完成
- name: 等待MySQL初始化完成
ansible.builtin.wait_for:
path: /var/log/mysqld.log
search_regex: 'root@localhost'
timeout: 300
# 5. 获取MySQL的临时密码
- name: 获取MySQL临时密码
ansible.builtin.shell: grep 'temporary password' /var/log/mysqld.log | awk '{print $NF}'
register: mysql_temp_password
# 6. 修改root用户的密码,授权远程访问
- name: 修改root用户密码
ansible.builtin.mysql_user:
name: root
host: '%'
password: "{{ mysql_root_password }}"
login_password: "{{ mysql_temp_password.stdout }}"
login_user: root
check_implicit_admin: yes
priv: '*.*:ALL,GRANT'
这个 Playbook,从安装源,到装服务,到初始化,到改密码,一步到位,所有的数据库服务器,一键就装好了,不用你手动去记那些复杂的初始化步骤,Ansible 都帮你做了。
五、进阶玩法:Roles 角色,让你的代码复用 100%
你可能会说,我写了 Nginx 的 Playbook,写了 MySQL 的,写了 JDK 的,以后我新搭环境,要把这些代码都复制粘贴吗?那也太麻烦了。
当然不用,这时候我们就要用 Roles 了,Roles 就是把你的 Playbook 拆成独立的、可复用的角色,你写一次,以后随便用。
5.1 为什么要用 Roles?
Roles 的好处就是复用性,你把 Nginx 封装成一个角色,把 MySQL 封装成一个,把 JDK 封装成一个,以后你要部署新的服务器,只要调用这些角色就行,不用再重写一遍代码,一次编写,到处用,不管你是 1 台服务器还是 100 台,都一样。
而且用 Roles,你的目录结构会非常清晰,方便维护,别人看你的代码,一眼就知道哪个角色是干嘛的。
5.2 搭建 Roles 目录结构
首先,我们先创建 Roles 的目录结构,大概是这样的:
java
project/
├── inventory.ini # 主机清单
├── site.yml # 主Playbook
└── roles/ # 角色目录
├── nginx/ # Nginx角色
│ ├── tasks/
│ │ └── main.yml
│ ├── handlers/
│ │ └── main.yml
│ ├── templates/
│ │ └── nginx.conf.j2
│ ├── vars/
│ │ └── main.yml
│ └── defaults/
│ └── main.yml
├── mysql/ # MySQL角色
└── jdk/ # JDK角色
每个角色下面,都有自己的 tasks、handlers、templates、vars,和我们之前写的 Playbook 是一样的,只是拆成了独立的目录。
5.3 把 Nginx 封装成 Role,一次编写到处用
比如,我们把之前写的 Nginx 的 Playbook,拆成 Nginx 角色:
首先,roles/nginx/tasks/main.yml,就是我们之前的任务:
java
# tasks file for nginx
- name: 安装Nginx软件包
ansible.builtin.yum:
name: nginx
state: present
- name: 部署Nginx配置文件
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
mode: '0644'
notify: 重启Nginx服务
- name: 启动Nginx服务,并设置开机自启
ansible.builtin.service:
name: nginx
state: started
enabled: yes
然后roles/nginx/handlers/main.yml,就是触发器:
java
# handlers file for nginx
- name: 重启Nginx服务
ansible.builtin.service:
name: nginx
state: restarted
然后把模板文件放到roles/nginx/templates/nginx.conf.j2,变量放到roles/nginx/vars/main.yml。
这样,Nginx 的角色就写好了,以后你要用的时候,只要在你的主 Playbooksite.yml里调用它就行:
java
---
- name: 部署Web服务器
hosts: webservers
become: yes
roles:
- jdk
- nginx
看到了吗?只要两行,就自动把 JDK 和 Nginx 都装好了,超级简单!如果你要部署数据库服务器,就调用 mysql 角色:
java
---
- name: 部署数据库服务器
hosts: dbservers
become: yes
roles:
- mysql
是不是太方便了?一次写好角色,以后不管什么时候用,直接调用就行,不用再重写代码,复用率 100%。
而且,你不用自己写所有的角色,Ansible Galaxy 上有无数现成的角色,比如你要装 Redis,要装 Elasticsearch,直接去 Galaxy 上下载别人写好的角色,直接用就行,不用自己从零写。
六、企业级实战案例:百台服务器一键初始化
讲了这么多基础的,我们来个企业级的实战案例,就是我之前做的,新买了 100 台服务器,要做初始化,原来手动做要一周,用 Ansible,一天就搞定了。
6.1 案例背景:新买的服务器要做哪些初始化?
新买的服务器,默认的配置都是不能直接用的,要做很多初始化的操作:
-
关闭防火墙,关闭 SELinux
-
修改时区为上海时区
-
安装常用的工具,比如 wget、curl、vim、net-tools
-
添加运维用户,配置 sudo 权限
-
配置 SSH,禁止 root 远程登录,修改 SSH 端口
-
更新系统补丁
-
配置时间同步
这些操作,每台都要做,100 台的话,手动做要好久,但是用 Ansible,一键就搞定了。
6.2 编写初始化 Playbook,一键完成所有配置
我们来写这个初始化的 Playbook:
java
---
- name: 服务器初始化配置
hosts: all
become: yes
tasks:
# 1. 关闭防火墙
- name: 关闭防火墙
ansible.builtin.service:
name: firewalld
state: stopped
enabled: no
# 2. 关闭SELinux
- name: 关闭SELinux
ansible.builtin.selinux:
state: disabled
# 3. 修改时区为上海
- name: 修改时区为亚洲/上海
ansible.builtin.timezone:
name: Asia/Shanghai
# 4. 安装常用工具
- name: 安装常用运维工具
ansible.builtin.yum:
name:
- wget
- curl
- vim
- net-tools
- lsof
- iotop
- htop
- iftop
state: present
# 5. 添加运维用户
- name: 添加运维普通用户
ansible.builtin.user:
name: ops
state: present
shell: /bin/bash
# 6. 给ops用户配置sudo免密权限
- name: 给ops用户配置sudo权限
ansible.builtin.lineinfile:
path: /etc/sudoers
line: 'ops ALL=(ALL) NOPASSWD: ALL'
validate: 'visudo -cf %s'
# 7. 配置SSH,禁止root登录
- name: 禁止root远程登录SSH
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#PermitRootLogin'
line: 'PermitRootLogin no'
notify: 重启SSH服务
# 8. 配置时间同步
- name: 安装chrony时间同步服务
ansible.builtin.yum:
name: chrony
state: present
- name: 启动chrony服务,设置开机自启
ansible.builtin.service:
name: chronyd
state: started
enabled: yes
handlers:
- name: 重启SSH服务
ansible.builtin.service:
name: sshd
state: restarted
就这个 Playbook,执行一下,所有 100 台服务器的初始化,一键就完成了,原来要一周的活,现在 10 分钟就搞定了,而且所有服务器的配置都是统一的,不会出现这台和那台配置不一样的情况,太爽了。
6.3 批量巡检:每天 1 分钟,掌握所有服务器状态
除了部署,日常的巡检也是运维的大活,每天要查所有服务器的 CPU、内存、磁盘,有没有异常,原来要一台台看,现在用 Ansible,批量巡检,1 分钟就搞定。
我们写一个巡检的 Playbook,批量收集所有服务器的状态:
java
---
- name: 批量服务器巡检
hosts: all
become: yes
gather_facts: yes
tasks:
# 收集CPU使用率
- name: 获取CPU使用率
ansible.builtin.shell: top -bn1 | grep Cpu | awk '{print $2}' | cut -d'%' -f1
register: cpu_usage
# 收集内存使用率
- name: 获取内存使用率
ansible.builtin.shell: free | grep Mem | awk '{print $3/$2 * 100.0}'
register: mem_usage
# 收集磁盘使用率
- name: 获取磁盘使用率
ansible.builtin.shell: df -h | grep /dev/vda1 | awk '{print $5}' | cut -d'%' -f1
register: disk_usage
# 输出结果
- name: 输出巡检结果
ansible.builtin.debug:
msg: "服务器 {{ inventory_hostname }} CPU: {{ cpu_usage.stdout }}% 内存: {{ mem_usage.stdout | float | round(2) }}% 磁盘: {{ disk_usage.stdout }}%"
执行完这个 Playbook,你就会得到所有服务器的巡检结果,汇总起来就是这样的:

所有服务器的状态一目了然,哪台服务器磁盘满了,哪台 CPU 过高,一眼就能看到,原来要半小时的巡检,现在 1 分钟就搞定了,每天花 1 分钟,就能掌握所有服务器的状态,太省心了。
七、我踩过的坑:常见问题排错指南
用 Ansible 这几年,我踩了不少坑,这里给大家整理了最常见的几个问题,大家遇到的时候,直接就能解决:
-
免密登录失败,还是要输密码 这个 90% 是权限的问题,.ssh 目录的权限必须是 700,authorized_keys 的权限必须是 600,SSH 对权限要求很严格,权限不对就会拒绝免密,执行这两个命令就行:
javachmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys -
Ansible 执行太慢,100 台要跑好久 默认情况下,Ansible 的并行数是 5,也就是一次只处理 5 台服务器,你可以改大一点,编辑
/etc/ansible/ansible.cfg,把forks = 5改成forks = 50,这样一次就能处理 50 台,速度直接快 10 倍,还有,如果你不需要收集 facts 的话,可以加gather_facts: no,也能快很多。 -
Playbook 执行报错,不知道哪里错了 写完 Playbook,先执行
ansible-playbook --check your_playbook.yml,这个是预执行,不会真的改服务器,就能帮你检查语法和错误,还有,加-v参数,能看到详细的执行日志,比如ansible-playbook your_playbook.yml -v,出错了就能看到详细的错误信息。 -
CentOS 和 Ubuntu 的兼容问题 如果你同时管理 CentOS 和 Ubuntu 的服务器,安装命令不一样,yum 和 apt,这时候你可以用
ansible_os_family来判断系统,然后执行不同的任务:java- name: 安装Nginx on CentOS ansible.builtin.yum: name: nginx state: present when: ansible_os_family == 'RedHat' - name: 安装Nginx on Ubuntu ansible.builtin.apt: name: nginx state: present when: ansible_os_family == 'Debian'这样就自动兼容不同的系统了。
-
普通用户执行,权限不够 很多时候,你用普通用户连接服务器,装软件需要 root 权限,这时候只要在 Playbook 里加
become: yes就行,Ansible 会自动用 sudo 提权,前提是你的用户有 sudo 权限。
八、总结:自动化运维,解放你的双手
到这里,这篇文章就差不多了,我们从 0 开始,搭了 Ansible 的环境,学了 Ad-Hoc 命令,学了 Playbook,学了 Roles,还做了企业级的实战案例,相信你跟着做下来,已经能把 Ansible 用起来了。
其实 Ansible 真的没有那么难,它就是一个帮你把重复的手动劳动自动化的工具,原来你要一天干的活,现在 10 分钟就搞定,原来你要熬夜加班,现在写完脚本,点一下执行,就能去喝茶了。
我现在管理 200 多台服务器,日常的部署、更新、巡检,都用 Ansible,原来要几个人干的活,我一个人就搞定了,再也不用怕漏了服务器,再也不用怕输错命令,再也不用熬夜加班了。
希望这篇文章能帮到你,也希望你能早点用上自动化运维,把自己从重复的劳动里解放出来,去做更有价值的事。
最后,给大家放几个有用的链接,大家可以去看看:
-
Ansible 官方文档:https://docs.ansible.com/
-
Ansible Github:https://github.com/ansible/ansible
-
Ansible Galaxy(现成角色库):https://galaxy.ansible.com/
如果这篇文章对你有帮助,欢迎点赞、收藏、关注,我后面还会分享更多运维自动化的干货~
标签: #运维 #Ansible #Linux #自动化运维 #批量部署 #Nginx #MySQL #Java #服务器