Ansible剧本(playbook)

6324 字
32 分钟
Ansible剧本(playbook)

Ansible剧本(playbook)#

[TOC]


初认知#

image-20260330095958869
image-20260330095958869

  • Ad-Hoc: 就像“单次命令”
    • 你想让服务器马上执行一个简单的操作
    • 它是一次性的、临时的
  • Playbook: 就像“剧本”或“清单”
    • 如果你想完成一系列复杂的任务
    • 你可以把这些任务写成一个文件(剧本),然后让 Ansible 按照这个文件一步步去执行
    • 它是可重复使用的,适合复杂的工作
  • Playbook 是 Ansible 的自动化脚本,采用 YAML 格式编写
  • 与临时命令( ad-hoc )相比,Playbook 更强大

组成#

image-20250827090844876
image-20250827090844876

红色框(playbook):整个剧本文件

绿色框(play):剧本里的一个“章节”或“场景”

黄色框(task):具体的一个动作、每个 task 都是实际干活的命令

  • 一个 Playbook(剧本)是由多个“Play”组成的

  • 每个“Play”里又包含多个“Task”(任务)


==运行结果颜色==

颜色意思举例
🟢 绿色成功了,但系统没变。常出现在读取信息或检查状态时,比如 ping 主机、查看文件是否存在、==没有发生改变==ansible all -m ping
🟡 黄色成功了,系统改变了。这是最常见的,因为我们执行 Ansible 通常都是为了改变系统
比如安装软件、创建文件 第一次黄色输出,有变化 第二次==绿色==输出,幂等性
创建一个新文件、安装一个包
🔴 红色出错了,失败了,得看日志命令找不到、权限不足
💜 紫色提了个警告,但还能继续跑配置可能有问题,但不影响当前任务执行

YAML 语法(别写错):

  • 缩进用空格(2个),不能用 Tab
  • 键值对:key: value (⚠️冒号后 ==必须有空格== )
  • 列表:- item1- item2
  • 注释:# 这是注释
  • 文件名推荐用 .yml,比如 my_playbook.yml
    • 几乎所有 Ansible 示例和文档都使用 .yml
    • .yaml 更正式、更完整的扩展名

实战#

Terminal window
[root@m01 ~]# rm -rf ./*
[root@m01 ~]# ll
total 0
[root@m01 ~]# vim a.yml
# 定义一个 Play
- hosts: web01
# 目标主机
gather_facts: no
# 默认是开着的,默认收集信息!
# 不收集目标主机的信息,让任务更快
tasks:
# 任务列表开始
- name: ping_test
# 任务名称
ping:
# 使用 'ping' 模块
[root@m01 ~]# ansible-playbook --syntax-check a.yml
# ✅️检查
playbook: a.yml
'语法没有问题!'
[root@m01 ~]# ansible-playbook a.yml
# 执行!
PLAY [web01] ********************************************************************
TASK [ping_test] ********************************************************************
ok: [web01]
PLAY RECAP ********************************************************************
web01 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

常用模块#

Terminal window
(1)创建文件
[root@m01 ~]# vim a.yml
- hosts: web01
gather_facts: no
tasks:
- name: Create file
file:
path: /home/te_file
state: touch
owner: www
group: www
mode: 0755
# 这里mode是四位数!
[root@m01 ~]# ansible-playbook --syntax-check a.yml
# 检查!
playbook: a.yml
[root@m01 ~]# ansible-playbook a.yml
changed: [web01]...
[root@m01 ~]# ssh web01 "ls -lh /home/te_file"
-rwxr-xr-x 1 www www 0 Mar 30 12:40 /home/te_file
# 文件权限755,属主属组都是www
(2)往里面写点东西
[root@m01 ~]# vim b.yml
- hosts: web01
gather_facts: no
tasks:
- name: write something
blockinfile:
path: /home/te_file
state: present
block: |
abcd
efg
aohou
[root@m01 ~]# ansible-playbook --syntax-check b.yml
playbook: b.yml
[root@m01 ~]# ssh web01 "cat /home/te_file"
# 查看一下,什么东西都没有!
[root@m01 ~]# ansible-playbook b.yml
# 运行后再查看一下!
[root@m01 ~]# ssh web01 "cat /home/te_file"
'默认在文件末尾创建!'
# BEGIN ANSIBLE MANAGED BLOCK
abcd
efg
aohou
# END ANSIBLE MANAGED BLOCK
=======================================
# 替换内容
'前提:文件中有标记!否则又会再一次的添加内容!'
# marker: "" 如果留空则会重复添加!
blockinfile:
path: /home/te_file
block: |
new
# 替换成new!!
[root@m01 ~]# ansible-playbook b.yml
[root@m01 ~]# ssh web01 "cat /home/te_file"
# BEGIN ANSIBLE MANAGED BLOCK
new
# END ANSIBLE MANAGED BLOCK
=======================================
自定义 marker 字符串
✅️需要用双引号包裹起来!
marker: "# {mark} ANSIBLE MANAGED BLOCK"
# 默认
marker: "# {mark} Ansible"
---------------------
'也可以留空,但是不建议'
🛑⚠️如果你设置 marker: ""❌️
Ansible 将不会在文件中写入任何标记行
后果:
1.Ansible 无法识别它之前写入的内容块
2.每次运行 Playbook 时,Ansible 都会认为文件里没有这个块,于是在文件末尾重复追加内容
3.你的配置文件会瞬间爆炸,充满重复的配置
什么时候可以留空?❓️
你只打算运行一次!但通常强烈不建议这样做!!❌️
---------------------
# 可以根据更改注释的样式!
比如xml的配置文件:
marker: "<!-- {mark} Ansible -->"
=======================================
[root@m01 ~]# ssh web01 "cat /home/te_file"
# BEGIN ANSIBLE MANAGED BLOCK
new
# END ANSIBLE MANAGED BLOCK
'替换block && 更换marker标记'
[root@m01 ~]# vim b.yml
blockinfile:
state: present
path: /home/te_file
block: |
New_block
Hello
world
marker: "# {mark} Ansible"
[root@m01 ~]# ansible-playbook b.yml
[root@m01 ~]# ssh web01 "cat /home/te_file"
# BEGIN ANSIBLE MANAGED BLOCK
new
# END ANSIBLE MANAGED BLOCK
# BEGIN Ansible
New_block
Hello
world
# END Ansible
'因为这里标记发生了改变!所以不认识之前的标记了'
# 结果又添加了一遍!!
'我们再替换修改一下!'
blockinfile:
state: present
path: /home/te_file
block: |
Successful
marker: "# {mark} Ansible"
# 依旧是这个marker标记!
[root@m01 ~]# ansible-playbook b.yml
# BEGIN ANSIBLE MANAGED BLOCK
new
# END ANSIBLE MANAGED BLOCK
# BEGIN Ansible
Successful
# END Ansible
'成功替换!!'
(3)替换某一行
# 比如把Successful替换为Failed
[root@m01 ~]# vim c.yml
- hosts: web01
gather_facts: no
tasks:
- name: sed ti huan
lineinfile:
path: /home/te_file
regexp: ^Succ
line: Failed
[root@m01 ~]# !ssh
ssh web01 "cat /home/te_file"
# BEGIN ANSIBLE MANAGED BLOCK
new
# END ANSIBLE MANAGED BLOCK
# BEGIN Ansible
Failed
# END Ansible
'成功替换'
(4)复制文件到web01
"如果有比较复杂的配置"
# 可以考虑现在我们本地进行编辑,然后再copy过去!
[root@m01 ~]# echo "Hello World" > hello.txt
[root@m01 ~]# vim d.yml
- hosts: web01
gather_facts: no
tasks:
- name: copy
copy:
src: ~/hello.txt
dest: /home/
[root@m01 ~]# ansible-playbook --syntax-check d.yml
playbook: d.yml
[root@m01 ~]# ssh web01 "ls -lh /home/hello.txt"
ls: cannot access '/home/hello.txt': No such file or directory
[root@m01 ~]# ansible-playbook d.yml
changed: [web01]
[root@m01 ~]# ssh web01 "ls -lh /home/hello.txt"
-rw-r--r-- 1 root root 12 Mar 30 14:45 /home/hello.txt
[root@m01 ~]# ssh web01 "cat /home/hello.txt"
Hello World
# 有了!
(5)创建虚拟用户
# 先创建组,再创建用户!
[root@m01 ~]# vim e.xml
- hosts: web01
gather_facts: no
tasks:
- name: Create group
group:
name: jiu
gid: 789
- name: Create user
user:
group: 789
uid: 789
name: jiu
shell: /sbin/nologin
create_home: false
[root@m01 ~]# ansible-playbook --syntax-check e.xml
playbook: e.xml
[root@m01 ~]# ssh web01 "id jiu"
id: ‘jiu’: no such user
[root@m01 ~]# ansible-playbook e.xml
[root@m01 ~]# ssh web01 "id jiu"
uid=789(jiu) gid=789(jiu) groups=789(jiu)
# 成功创建!

重构#

❤️帮助信息#

  • ==ansible-doc== 是写 ad-hoc 命令或 playbook 时的内置参考手册
Terminal window
[root@m01 ~]# ansible-doc yum
"进入之后 --> /进入搜索模式!"
# 搜索EXAM回车!
😍 其实就是example 示例
'就可以出现下面的案例了!'
EXAMPLES:
- name: Install the latest version of Apache
ansible.builtin.yum:
name: httpd
state: latest
- name: Install Apache >= 2.4
ansible.builtin.yum:
name: httpd>=2.4
state: present
====================================
ansible-doc -s yum # 查看yum模块的选项
"它是去介绍一个个选项的使用"
name: # A package name or package specifier with version, like `name-1.0'.'
state: # Whether to install (`present' or `installed', `latest'), or remove '

📌 一句话:不知道模块怎么用 → ansible-doc -s <模块名>,要看完整文档 → 去掉 -s

backup#

Terminal window
修改目录属主属组
创建日志文件,属主www
4.启动rsync 加入开机自启
'先拷贝|编辑配置文件📃'
[root@m01 ~]# scp 172.16.1.41:/etc/rsyncd.conf .
rsyncd.conf 100% 410 595.7KB/s
# 拷贝到当前路径下
[root@m01 ~]# cat rsyncd.conf
uid = www
gid = www
port = 873
fake super = yes
use chroot = no
max connections = 200
timeout = 600
ignore errors
read only = false
list = false
auth users = rsync_backup
secrets file = /etc/rsync.passwd
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file =/var/log/rsyncd.log
############################
[backup]
comment = Welcome to oldboyedu backup!
path = /backup
[data]
path = /data
(1)初始化backup服务器!
'恢复快照!'
(2)配置主机清单
[root@m01 ~]# vim /etc/ansible/hosts
lb0[1:2]
db01
backup
nfs0a
[webs]
web0[1:2]
# 前提/etc/hosts有对应的IP映射
(3)配置免密钥
[root@m01 ~]# ssh-copy-id -i ~/.ssh/my_key.pub 172.16.1.41
[root@m01 ~]# ssh backup "hostname -I"
'测试查看!'
Authorized users only. All activities may be monitored and reported.
10.0.0.41 172.16.1.41
# 优化!
[root@m01 ~]# ssh backup "> /etc/issue && > /etc/issue.net"
[root@m01 ~]# ssh backup "hostname -I"
10.0.0.41 172.16.1.41
(4)编写剧本
[root@m01 ~]# ll
total 4
-rw-r--r-- 1 root root 410 Mar 30 15:17 rsyncd.conf
[root@m01 ~]# vim backup.yml
- hosts: backup
gather_facts: no
tasks:
- name: Install rsync server
# 安装rsync
yum:
name: rsync
state: present
- name: Configure rsync file
# 拷贝配置文件
copy:
src: ./rsyncd.conf
dest: /etc/
- name: Create group www
# 创建www组
group:
gid: 888
name: www
- name: Create user www
# 创建虚拟用户
user:
group: 888
uid: 888
name: www
shell: /sbin/nologin
create_home: false
- name: Create passwd file
# 创建认证文件--》权限0600
copy:
content: rsync_backup:123
dest: /etc/rsync.passwd
mode: 0600
- name: Create dir /data
# 创建/data共享目录--》属主www
file:
path: /data
state: directory
owner: www
group: www
mode: 0755
- name: Create dir /backup
# 创建/backup共享目录--》属主www
file:
path: /backup
state: directory
owner: www
group: www
mode: 0755
- name: Create log file
# 创建日志文件--》属主www
file:
path: /var/log/rsyncd.log
state: touch
owner: www
group: www
mode: 0644
- name: Start rsyncd server
# 启动服务并开启自启
systemd:
name: rsyncd
state: started
enabled: yes
[root@m01 ~]# ansible-playbook --syntax-check backup.yml
playbook: backup.yml
[root@m01 ~]# ansible-playbook backup.yml
...
PLAY RECAP **********
backup : ok=9 changed=8 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@m01 ~]# ssh backup "netstat -lntuo | grep 873"
tcp 0 0.0.0.0:873 0.0.0.0:* LISTEN
tcp6 0 :::873 :::* LISTEN
# 成功运行起来了
# 接着就是本地测试,服务端测试
[root@m01 ~]# rsync -avz /etc/passwd rsync_backup@172.16.1.41::backup
Password:
sending incremental file list
passwd
ss
sent 841 bytes received 43 bytes 353.60 bytes/sec
total size is 1,845 speedup is 2.09
[root@m01 ~]# ssh backup "ls /backup/"
passwd
# 成功传送过去!

nfs服务#

Terminal window
(1)拷贝配置文件
[root@nfs ~]# cat /etc/exports
# 先去nfs看一下配置文件
/data/wp 172.16.1.0/24(rw,sync,all_squash,anonuid=888,anongid=888)
[root@m01 ~]# scp 172.16.1.31:/etc/exports .
Authorized users only.
exports 100% 204 317.4KB/s
[root@m01 ~]# ls exports
exports
# 成功拷贝过来
(2)初始化31
'恢复快照'
(3)主机清单
[root@m01 ~]# grep nfs /etc/ansible/hosts
nfs01
[root@m01 ~]# grep nfs /etc/hosts
172.16.1.31 nfs01
(4)免密钥优化
# 得先做了免密钥
[root@m01 ~]# ssh nfs01 "> /etc/issue && > /etc/issue.net"
Authorized users only.
[root@m01 ~]# ssh nfs01 "hostname -I"
10.0.0.31 172.16.1.31
(5)编写playbook剧本
[root@m01 ~]# vim nfs.yml
- hosts: nfs01
gather_facts: no
tasks:
- name: Install NFS server
# 下载安装nfs-utils
yum:
name: nfs-utils
state: present
- name: Configure NFS server
# 拷贝配置文件
copy:
src: ./exports
dest: /etc/exports
- name: Create Group www
# 创建www组
group:
name: www
gid: 888
- name: Create User www
# 创建www虚拟用户
user:
group: 888
uid: 888
name: www
shell: /sbin/nologin
create_home: false
- name: Create dir /data/wp
# 创建挂载目录&&改目录属主
file:
path: /data/wp
state: directory
owner: www
group: www
- name: Start nfs Server
# 启动&&开机自启
systemd:
name: nfs
# Rocky10是nfs-server
state: started
enabled: yes
- hosts: webs
# 这里是webs,一个组!
gather_facts: no
tasks:
# web 下载nfs-utils
# 为了能够挂载nfs文件系统
- name: Webs Install NFS Server
yum:
name: nfs-utils
state: present
(5)测试&&启动
[root@m01 ~]# ansible-playbook --syntax-check nfs.yml
playbook: nfs.yml
[root@m01 ~]# ansible-playbook nfs.yml
PLAY RECAP *************
nfs01
web01
web02

📚mount 模块#

Terminal window
mount模块用于在远程主机上管理文件系统的挂载和卸载操作
# 可以设置为开机自动挂载
src: 指定挂载源(设备)
path: 指定挂载点路径(挂载目录,若不存在会自动创建)
fstype: 指定文件系统类型(必须指定)
state: 挂载状态
'State参数详解'
1. mounted
功能: 进行挂载,并修改/etc/fstab信息
行为:
如果未挂载,则挂载设备
在/etc/fstab中添加条目,实现永久挂载
挂载点不存在时自动创建
2. absent
功能: 永久性卸载,并修改/etc/fstab信息
行为:
卸载当前挂载的设备
从/etc/fstab中删除对应的条目
实现真正的永久卸载
====================================
我们用web01进行挂载测试!
nfs01的/data/wp挂载到--》web01的/mnt目录上!
[root@web01 ~]# df -h | grep mnt
#现在/mnt目录没有挂载任何的设备!
[root@web01 ~]# showmount -e 172.16.1.31
Export list for 172.16.1.31:
/data/wp 172.16.1.0/24
# 成功嗅探到!
[root@m01 ~]# vim mount.yml
'切回m01'
- hosts: web01
gather_facts: no
tasks:
- name: Mount NFS /data/wp
mount:
src: 172.16.1.31:/data/wp
# src:设备
path: /mnt
# path:要挂载的目录
fstype: nfs
state: mounted
[root@m01 ~]# ansible-playbook --syntax-check mount.yml
playbook: mount.yml
[root@m01 ~]# ansible-playbook mount.yml
[root@web01 ~]# df -h | grep /mnt
'切回web01'
172.16.1.31:/data/wp 49G 3.8G 45G 8% /mnt
# 成功挂载上去了!
[root@web01 ~]# grep '/mnt' /etc/fstab
172.16.1.31:/data/wp /mnt nfs defaults 0 0
# 同时也被永久写入到了/etc/fstab
'永久挂载!'
[root@m01 ~]# vim mount.yml
[root@m01 ~]# grep absent mount.yml
state: absent
'尝试卸载 !'
[root@m01 ~]# ansible-playbook --syntax-check mount.yml
playbook: mount.yml
[root@m01 ~]# ansible-playbook mount.yml
# 回到web01进行验证测试!卸载干净了!
[root@web01 ~]# df -h | grep /mnt
[root@web01 ~]# grep '/mnt' /etc/fstab

重构Nginx#

Terminal window
'我们这里以web01为例!'
(1)拷贝配置文件
[root@m01 ~]# scp 10.0.0.7:/etc/nginx/nginx.conf .
nginx.conf 100% 726 536.2KB/s
[root@m01 ~]# ls nginx.conf
nginx.conf
(2)初始化web01
# DNS服务器
(3)免密钥
[root@m01 ~]# ssh-copy-id -i ~/.ssh/my_key.pub 172.16.1.7
[root@m01 ~]# ssh web01 "> /etc/issue && > /etc/issue.net"
[root@m01 ~]# ssh web01 "hostname -I"
10.0.0.7 172.16.1.7

📚yum_repository 模块#

Ansible yum_repository 模块参数生成的 .repo 文件内容实际含义与作用
name: nginx[nginx-stable]仓库 ID 这是仓库的唯一标识符
description: nginx YUM reponame=nginx stable repo仓库描述 这是给人看的描述
baseurl: ...baseurl=...软件包地址 两者完全一致
gpgcheck: nogpgcheck=0no/yes 转换为 0/1
enabled: yesenabled=1启用开关
Terminal window
它的作用就是帮你自动编辑 /etc/yum.repos.d/ 目录下的 .repo 文件
Ansible 默认会把 `name` 的值直接放在 `[]`
========================================
# 我们来看一下web02的Nginx仓库
[root@web02 ~]# cd /etc/yum.repos.d/
[root@web02 yum.repos.d]# cat nginx.repo
[nginx-stable]
name = nginx stable repo
baseurl = https://nginx.org/packages/centos/7/$basearch/
gpgcheck = 0
enabled = 1
'我们也试着编辑yml文件'
[root@m01 ~]# vim yum.yml
- hosts: web01
gather_facts: no
tasks:
- name: Configure Nginx Repo
# 配置Nginx的yum仓库
yum_repository:
name: nginx-stable
# name对应着repo文件的[]
description: nginx stable repo
# description对应着repo文件的name
baseurl: https://nginx.org/packages/centos/7/$basearch/
gpgcheck: no
enabled: yes
[root@m01 ~]# ansible-playbook --syntax-check yum.yml
playbook: yum.yml
[root@m01 ~]# ssh web01 "ls /etc/yum.repos.d/ | grep nginx"
[root@m01 ~]# ansible-playbook yum.yml
[root@m01 ~]# ssh web01 "ls /etc/yum.repos.d/ | grep nginx"
nginx-stable.repo
[root@m01 ~]# ssh web01 "cat /etc/yum.repos.d/nginx-stable.repo"
[nginx-stable]
async = 1
baseurl = https://nginx.org/packages/centos/7/$basearch/
enabled = 1
gpgcheck = 0
name = nginx stable repo
# 这些也都对应上了!!
========================================
现象:async = 1 Ansible yum_repository 模块自动生成的管理标记
影响:无,YUM 会忽略该行,不影响功能
========================================
# 其实我们也可以用copy模块,提前写好再拷贝过去!
'我们这里使用blockinfile模块'
# fatal: [web01]: FAILED! => {"changed": false, "msg": "Path /etc/yum.repos.d/nginx.repo does not exist !", "rc": 257}
'使用block块写入文件的时候,得有这个🧨文件!'
[root@m01 ~]# vim block.yml
- hosts: web01
gather_facts: no
tasks:
- name: Rm The old repo
file:
path: /etc/yum.repos.d/nginx-stable.repo
state: absent
# 先把之前的删除了
- name: Touch repo file
file:
path: /etc/yum.repos.d/nginx.repo
state: touch
# 再新建一个!
- name: Write block to repo
blockinfile:
path: /etc/yum.repos.d/nginx.repo
block: |
[nginx-stable]
name = nginx stable repo
baseurl = https://nginx.org/packages/centos/7/$basearch/
gpgcheck = 0
enabled = 1
state: present
marker: "# {mark} Ansible"
[root@m01 ~]# ansible-playbook --syntax-check block.yml
playbook: block.yml
[root@m01 ~]# ansible-playbook block.yml
[root@m01 ~]# ssh web01 "cat /etc/yum.repos.d/nginx.repo"
# BEGIN Ansible/
[nginx-stable]
name = nginx stable repo
baseurl = https://nginx.org/packages/centos/7/$basearch/
gpgcheck = 0
enabled = 1
# END Ansible
'现在也是一模一样了!'
- hosts: web01
gather_facts: no
tasks:
- name: Configure nginx repo
yum_repository:
name: nginx-stable
description: nginx stable repo
baseurl: https://nginx.org/packages/centos/7/$basearch/
gpgcheck: no
enabled: yes
- name: Install nginx server
yum:
name: nginx
state: present
- name: Configure copy nginx file
copy:
src: ./nginx.conf
dest: /etc/nginx/
- name: Create group www
group:
name: www
gid: 888
- name: Create user www
user:
name: www
uid: 888
group: www
shell: /sbin/nologin
create_home: false
- name: Start nginx server
systemd:
name: nginx
state: started
enabled: yes
Terminal window
[root@m01 ~]# rm -rf block.yml
[root@m01 ~]# vim nginx.yml
'把上面配置文件的放过来'
[root@m01 ~]# ansible-playbook --syntax-check nginx.yml
playbook: nginx.yml
[root@m01 ~]# ansible-playbook nginx.yml
============================================
'测试验证!'
[root@web01 ~]# ps aux | grep nginx
root 5400 ...Ss 10:20 0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
www 5401 S 10:20 0:00 nginx: worker process
[root@web01 ~]# ss -lntup| grep nginx
tcp LISTEN 0.0.0.0:80 (("nginx",pid=5401,fd=9

重构PHP#

Terminal window
1)去web02拿PHP的配置文件
[root@m01 ~]# scp 10.0.0.8:/etc/php-fpm.d/www.conf .
Authorized users only.
www.conf 100% 19KB
[root@m01 ~]# ls www.conf
www.conf
2)编写配置文件
[root@m01 ~]# vim php.yml
- hosts: web01
gather_facts: no
tasks:
- name: Install php server
yum:
name:
- php
- php-bcmath
- php-cli
- php-common
- php-devel
- php-embedded
- php-fpm
- php-gd
- php-intl
- php-mbstring
- php-mysqlnd
- php-opcache
- php-pdo
- php-process
- php-xml
- php-json
state: present
- name: Configure copy php
copy:
src: ./www.conf
dest: /etc/php-fpm.d/
- name: Start php server
systemd:
name: php-fpm
state: started
enabled: yes
[root@m01 ~]# ansible-playbook --syntax-check php.yml
playbook: php.yml
[root@m01 ~]# ansible-playbook php.yml
============================================
'测试验证!'
[root@web01 ~]# ss -lntup | grep php
tcp LISTEN 0 128 127.0.0.1:9000 0.0.0.0:* users:(("php-fpm",pid=6880,fd=13),("php-fpm",pid=6879,fd=13),("php-fpm",pid=6878,fd=13),("php-fpm",pid=6877,fd=13),("php-fpm",pid=6876,fd=13),("php-fpm",pid=6875,fd=11))
# 监听的是9000端口!

静态页#

Terminal window
# 因为我们web有一些重要的配置!
'所以我们先自行拷贝过来'
# 不然恢复快照,很多东西都要重新搞!
[root@web02 conf.d]# ll
'/etc/nginx/conf.d'
total 20
-rw-r--r-- 1 root root 261 Mar 10 18:35 download.conf
-rw-r--r-- 1 root root 650 Mar 10 18:35 php.conf
-rw-r--r-- 1 root root 136 Aug 29 2025 php-fpm.conf
-rw-r--r-- 1 root root 124 Mar 20 16:46 test.conf
-rw-r--r-- 1 root root 382 Mar 21 16:39 wp.conf
[root@web02 conf.d]# cd /code/
[root@web02 code]# ll
total 4
drwxr-xr-x 5 www www 4096 Mar 13 11:07 wordpress
drwxr-xr-x 3 root root 18 Mar 24 15:49 zrlog
============================================
[root@m01 ~]# scp -r 172.16.1.8:/etc/nginx/conf.d .
# 把整个目录拷贝过来!
Authorized users only.
download.conf 100% 261 403.8KB/s
php.conf 100% 650 1.5MB/s
php-fpm.conf 100% 136 304.6KB/s
test.conf 100% 124 247.8KB/s
wp.conf 100% 382 848.4KB/s
[root@m01 ~]# ll -d conf.d/
drwxr-xr-x 2 root root 95 Apr 2 11:38 conf.d/
[root@m01 ~]# scp -r 172.16.1.8:/code .
# /code整个目录拷贝过来!
[root@m01 ~]# ll -d code
drwxr-xr-x 4 root root 36 Apr 2 11:43 code
# 代码目录!
============================================
# web02也要恢复快照!
✅️也同样执行上面安装Nginx和php的步骤!
WEB01--------显示页面 web01....
WEB02------->显示页面 web02....
"没有学变量-需要一个个的书写✍️"
[root@m01 ~]# vim ./conf.d/test.conf
server {
listen 80 default_server;
# 手动默认指定
server_name _;
# _配合default_server使用!
root /code/test;
location / {
index index.html;
}
}
[root@m01 ~]# vim index.yml
- hosts: web01
gather_facts: no
tasks:
- name: Configure test file
copy:
src: ./conf.d/test.conf
dest: /etc/nginx/conf.d/
- name: Create test dir /code/test
file:
path: /code/test
state: directory
owner: www
group: www
- name: Create index_page file
copy:
content: web01...
dest: /code/test/index.html
- name: Restart nginx server
systemd:
name: nginx
state: restarted
"因为没有学习变量,所以在这个的基础上改为web02"
⚠️特别是默认页部分!
[root@m01 ~]# ansible-playbook --syntax-check index.yml
playbook: index.yml
[root@m01 ~]# ansible-playbook index.yml
- hosts: web02
...
copy:
content: web02...
dest: /code/test/index.html
....
# 重新执行index.yml脚本!
[root@m01 ~]# curl 10.0.0.7
web01...
[root@m01 ~]# curl 10.0.0.8
web02...
'成功访问到!'

📚mysql#

Terminal window
"这里用db02来进行安装!"
# 先把db02恢复快照-->从头开始
1)免密登录
[root@m01 ~]# ssh-copy-id -i ~/.ssh/my_key.pub 172.16.1.52
2)主机清单
[root@m01 ~]# grep db02 /etc/ansible/hosts
db02
3)编写配置文件
[root@m01 ~]# vim mysql.yml
- hosts: db02
gather_facts: no
tasks:
- name: Install mariadb server
yum:
name:
- mariadb-server
- python3-PyMySQL
# 有了☝才能进入到mysql里面-->创建用户!
# python3-mysqlclient --> 该驱动已被 Ansible 官方标记为弃用
state: present
- name: Start mariadb server
systemd:
name: mariadb
state: started
enabled: yes
- name: Create wp database
# 创建数据库
# 创建数据库之前需要先登录
mysql_db:
login_unix_socket: /var/lib/mysql/mysql.sock
# 显式指定认证方式 --> 用 socket 认证
login_user: root
# 新建数据库时,没有设置密码 --> socket 认证也不需要密码
name: wp
state: present
============================================
'下面有数据库导入部分!'
state: 设置为 import,明确指示模块执行导入操作
# (将 SQL 文件导入到数据库中)
target: 指定要导入的 SQL 文件的路径
# ⚠️要导入的sql文件得在目标主机上
# 所以我们得先用copy模块拷贝到目标主机上!!
name: 指定要导入sql文件的,目标数据库名称
# ⚠️如果你是导出整个all.sql(所有的数据)
# 那么这里名字依旧是all
============================================
- name: Create db user jiuzhao
mysql_user:
login_unix_socket: /var/lib/mysql/mysql.sock
# 同样改用 socket
login_user: root
name: jiuzhao
password: oldboy123.com
priv: '*.*:ALL'
# 给所有的数据库和所有表授予所有权限
# 这里给wp就够用了 'wp.*:ALL'
host: '172.16.1.%'
# 还要允许172.xxx网段连接
state: present
[root@m01 ~]# ansible-playbook --syntax-check mysql.yml
playbook: mysql.yml
[root@m01 ~]# ansible-playbook mysql.yml
'登录测试&&查看数据'
# 直接在db02中查看!
[root@db02 ~]# mysql -h 172.16.1.52 -ujiuzhao -poldboy123.com -e "show databases;"
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| wp |
+--------------------+

重构wordpress#

Terminal window
"先引出来一个问题!!"
# 后面做实验可能一直跳HTTPS
[root@m01 ~]# cat conf.d/wp.conf
.....
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
.........
fastcgi_param HTTPS on;
# 配置fastcgi支持https的请求功能!
"在wordpress中的配置文件里面!"
得把这条配置删除掉!不然老跳https
# 如果你不小心把这个配置带入到wordpress安装页面
# 也就是安装好了!
'就是把https写入到了数据库中'
# 你得把数据库中对应的wordpress库删除掉!
server {
listen 80;
server_name wp.kpyun.com;
root /code/wordpress;
location / {
index index.php index.html;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}

📚get_url && unarchive#

Terminal window
"下载&&解压"
get_url:负责把文件从网上(或内部服务器)下载到目标机器上
unarchive:负责把压缩包(如 zip, tar.gz)解压开
============================================
1.get_url 模块(下载文件)
url: 下载地址
dest: 保存位置(必须写绝对路径)
force: 如果文件已存在,是否强制重新下载?
yes (总是下载), no (存在就不下)
============================================
2.unarchive 模块(解压文件)
src: 要解压的那个压缩包在哪里?
dest: 解压出来的内容放到哪个文件夹?
remote_src: ⚠️源文件在哪边?
no (默认): 压缩包在控制端(你这边)
yes: 压缩包已经在目标机器上了,直接解压✅️
creates: 🦄防重复解压
'如果这个文件存在,说明解压过了, 直接跳过'
- hosts: web01
gather_facts: no
tasks:
- name: Configure copy wp
# 拷贝配置文件
copy:
src: ./conf.d/wp.conf
dest: /etc/nginx/conf.d/
- name: Create dir /code
# 创建code目录-->主要是修改属主,属组
file:
path: /code/
state: directory
owner: www
group: www
- name: crul wp pack
# 下载wordpress包
get_url:
url: https://cn.wordpress.org/wordpress-6.0-zh_CN.tar.gz
dest: /tmp/
# 下载到临时目录(回收站)
force: no
- name: unpackage wp
# 解压它
unarchive:
src: /tmp/wordpress-6.0-zh_CN.tar.gz
remote_src: yes
# 在远程目标机器上!
dest: /code/
creates: /code/wordpress
# 如果有这个目录则跳过解压步骤!
- name: modify owner group
# 递归修改wordpress目录下的属主,属组
file:
path: /code/wordpress
owner: www
group: www
recurse: yes
# 递归修改
- name: Restart nginx server
# 重启nginx服务
systemd:
name: nginx
state: restarted
Terminal window
[root@m01 ~]# vim wp.yml
# 把上面的复制过去
[root@m01 ~]# ansible-playbook --syntax-check wp.yml
playbook: wp.yml
'终于是不报错了!'
[root@m01 ~]# ansible-playbook wp.yml
web01 : ok=6
# Windows 解析!
10.0.0.7 wp.kpyun.com
'浏览器访问测试!'

image-20260402192245691
image-20260402192245691

image-20260402192308270
image-20260402192308270

image-20260402192658144
image-20260402192658144

Terminal window
# 上面是web01
web02如何配置wordpress呢??❓️
1.拷贝配置文件(./conf.d/wp.conf)
2.把web01下的/code/wordpress目录拷贝过去
3.更改/code目录及文件下的属主属组为www
4.重启web02的nginx服务
============================================
[root@web02 ~]# scp web01:/etc/nginx/conf.d/wp.conf /etc/nginx/conf.d/
root@web01's password: '
wp.conf 100% 324 465.2KB/s
[root@web02 ~]# scp -r web01:/code/wordpress /code
# 把整个目录都拷贝过来!
[root@web02 ~]# chown -R www.www /code
[root@web02 ~]# systemctl restart nginx
# Windows 解析!
10.0.0.8 wp.kpyun.com
'浏览器访问测试!'

image-20260402202905597
image-20260402202905597

业务迁移#

Terminal window
业务背景: wp业务, 从一个老旧的设备迁移到新设备上
实现目标: 业务恢复, 迁移后直接登录就能看到原有的信息!
'以下步骤完成后,输入网址,直接恢复成原来的样子'
============================================
1)wordpress的配置文件导出
./conf.d/wp.conf
[root@m01 ~]# ls ./conf.d/wp.conf
./conf.d/wp.conf
# Ansible需要有!
2)原来/code/wordpress源码需要导出
[root@m01 ~]# scp -r 172.16.1.7:/code/wordpress .
[root@m01 ~]# ll -d wordpress/
drwxr-xr-x 5 root root 4096 Apr 2 20:50 wordpress/
'这里需要注意属主是root!!⚠️'
# ✅️东西比较多,我们压缩一下!
[root@m01 ~]# tar zcf wp.tar.gz ./wordpress/
[root@m01 ~]# ls wp.tar.gz
wp.tar.gz
3)数据库中的数据需要导出
# 方便后面导入的时候恢复业务!
'这里我只导出了一个wp库,后面数据库依旧要创建jiuzhao这个用户!'
[root@m01 ~]# ssh db02 "mysqladmin password 'oldboy123.com'"
# 给db01的root一个密码!
[root@m01 ~]# ssh db02 "mysqldump -uroot -poldboy123.com wp > /tmp/wp.sql"
# 把wp库导出
[root@m01 ~]# ssh db02 "ls /tmp/wp.sql"
/tmp/wp.sql
# 测试验证!
[root@m01 ~]# scp 172.16.1.52:/tmp/wp.sql .
wp.sql 100% 1077KB 96.3MB/s
'拷贝到当前目录来!'
4)配置文件的书写✍️
- hosts: webs
gather_facts: no
tasks:
- name: Configure nginx repo
yum_repository:
name: nginx-stable
description: nginx stable repo
baseurl: https://nginx.org/packages/centos/7/$basearch/
gpgcheck: no
enabled: yes
- name: Install nginx server
yum:
name: nginx
state: present
- name: Configure copy nginx file
copy:
src: ./nginx.conf
dest: /etc/nginx/
- name: Create group www
group:
name: www
gid: 888
- name: Create user www
user:
name: www
uid: 888
group: www
shell: /sbin/nologin
create_home: false
- name: Start nginx server
systemd:
name: nginx
state: started
enabled: yes
- hosts: webs
gather_facts: no
tasks:
- name: Install php server
yum:
name:
- php
- php-bcmath
- php-cli
- php-common
- php-devel
- php-embedded
- php-fpm
- php-gd
- php-intl
- php-mbstring
- php-mysqlnd
- php-opcache
- php-pdo
- php-process
- php-xml
- php-json
state: present
- name: Configure copy php
copy:
src: ./www.conf
dest: /etc/php-fpm.d/
- name: Start php server
systemd:
name: php-fpm
state: started
enabled: yes
- hosts: db02
gather_facts: no
tasks:
- name: Install mariadb server
yum:
name:
- mariadb-server
- python3-PyMySQL
# 改用 PyMySQL --> 连接进入MySQL
state: present
- name: Start mariadb server
systemd:
name: mariadb
state: started
enabled: yes
# 数据导入之前,需要copy到db02
- name: Copy wp.sql db
copy:
src: ./wp.sql
dest: /tmp/wp.sql
- name: Imoport wp.sql db
# 详细语法参考前面 mysql
mysql_db:
login_unix_socket: /var/lib/mysql/mysql.sock
login_user: root
name: wp
# 导入的数据库名称是wp
state: import
# 导入
target: /tmp/wp.sql
# sql文件在db02中
- name: Create db user jiuzhao
mysql_user:
login_unix_socket: /var/lib/mysql/mysql.sock
login_user: root
name: jiuzhao
password: oldboy123.com
priv: '*.*:ALL'
# 给所有的数据库和所有表授予所有权限
host: '172.16.1.%'
# 还要允许172.xxx网段连接
state: present
- name: Restart mysql server
systemd:
name: mariadb
state: restarted
  • 多出来 wp.sql 数据导入

    • 详细语法参考前面 📚mysql
  • 少建表部分!

  • 因为我们没有导出整个sql语句, 所以用户 jiuzhao 不能少

- hosts: webs
gather_facts: no
tasks:
- name: Configure copy wp
# 拷贝配置文件
copy:
src: ./conf.d/wp.conf
dest: /etc/nginx/conf.d/
- name: Create dir /code
# 创建code目录-->主要是修改属主,属组
file:
path: /code/
state: directory
owner: www
group: www
- name: unpackage wp
# 解压它
unarchive:
src: ./wp.tar.gz
remote_src: no
# 压缩包在本地(m01)
dest: /code/
creates: /code/wordpress
# 如果有这个目录则跳过解压步骤!
- name: modify owner group
# 递归修改wordpress目录下的属主,属组
file:
path: /code/wordpress
owner: www
group: www
recurse: yes
# 递归修改
- name: Restart nginx server
# 重启nginx服务
systemd:
name: nginx
state: restarted
  • 少下载 wordpress软件包 部分
  • 本地有,直接在本地解压至 webs

Terminal window
vim nginx.yml
vim php.yml
vim mysql.yml
vim wp.yml
# 把上面的东西都复制进去!
✅️web01 web02 db02 都恢复快照!
✅️别忘了做ssh免密登录
============================================
[root@m01 ~]# cd /home/
[root@m01 home]# ll
total 0
[root@m01 home]# ll
total 16
-rw-r--r-- 1 root root 1169 Apr 2 22:14 mysql.yml
-rw-r--r-- 1 root root 846 Apr 2 22:14 nginx.yml
-rw-r--r-- 1 root root 699 Apr 2 22:14 php.yml
-rw-r--r-- 1 root root 959 Apr 2 22:15 wp.yml
# 编写完后覆盖原来的配置!
[root@m01 home]# cp ./* ~
cp: overwrite '/root/mysql.yml'? y
cp: overwrite '/root/nginx.yml'? y
cp: overwrite '/root/php.yml'? y
cp: overwrite '/root/wp.yml'? y
[root@m01 home]# cd ~
[root@m01 ~]# ansible-playbook --syntax-check nginx.yml
playbook: nginx.yml
[root@m01 ~]# ansible-playbook --syntax-check php.yml
playbook: php.yml
[root@m01 ~]# ansible-playbook --syntax-check mysql.yml
playbook: mysql.yml
[root@m01 ~]# ansible-playbook --syntax-check wp.yml
playbook: wp.yml
'把命令编写成一个脚本!'
[root@m01 ~]# vim site.sh
ansible-playbook nginx.yml
ansible-playbook php.yml
ansible-playbook mysql.yml
ansible-playbook wp.yml
'运行脚本'
[root@m01 ~]# sh site.sh
🐴'浏览器测试验证'
# 分别解析到 web01 和 web02 试试看!
✅️http://wp.kpyun.com/

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Ansible剧本(playbook)
https://www.kpyun.fun/posts/automation/ansible/ansible02/
作者
久棹
发布于
2026-05-24
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
久棹
只要胆子大,天天寒暑假!
公告
欢迎来到久棹的技术小站!本站专注 Linux 运维学习笔记分享,如有问题欢迎交流探讨 🎉
分类
标签
站点统计
文章
98
分类
11
标签
203
总字数
244,453
运行时长
0
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.13.5
文章许可
CC BY-NC-SA 4.0

文章目录