Terraform 搭建,Ansible 配置:VPS 上的 WordPress 自动化实践(Part 2)
前言
在 Part 1 里,我用 Terraform 在 VPS 上创建了 MySQL 和 WordPress 两个 Docker 容器,站点成功跑起来了。
但 Terraform 的职责到“资源创建”为止。容器跑起来之后,里面装了什么插件、站点 URL 是什么、数据库有没有备份——这些属于配置管理,是 Ansible 的领域。
这篇文章记录 Part 2 的完整过程:从零开始安装 Ansible,写第一个 inventory,跑通 ping 模块,最终用 Playbook 在容器里执行 WP-CLI 命令。过程中踩的坑依然是重点。
环境准备
VPS 是 Ubuntu(jammy),上面已经有 Docker 和 Terraform。
安装 Ansible
Ubuntu 仓库提供了两个包:
| 包 | 说明 |
|---|---|
ansible-core | 官方核心,轻量,推荐 |
ansible | 全家桶,体积大 |
练习阶段装 ansible-core 就够了:
bash
sudo apt-get install -y ansible-core
练习 1:基础连通性
Ansible 需要一个 inventory 告诉它管理哪些主机。因为目标就是 VPS 本机,我们用 ansible_connection=local 避免走 SSH。
创建 inventory.ini:
ini
[local] localhost ansible_connection=local
测试连通性:
bash
ansible -i inventory.ini local -m ping
成功输出:
text
localhost | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
看到 "ping": "pong" 就说明 Ansible 能连上并执行 Python 了。
练习 2:检查容器状态
这个练习要检查 Terraform 创建的 wp-app-practice 容器是否在运行。需要 community.dockercollection。
踩坑一:ansible-galaxy 崩溃
bash
ansible-galaxy collection install community.docker
报错:
text
AttributeError: module 'lib' has no attribute 'X509_V_FLAG_NOTIFY_POLICY'
这是 pyopenssl 版本过旧导致的。用 pip 升级:
bash
pip3 install --user --upgrade pyopenssl cryptography
踩坑二:resolvelib 版本不兼容
升级后又报:
text
TypeError: CollectionDependencyProvider.find_matches() got an unexpected keyword argument 'identifier'
这是 Ansible 与新版 resolvelib 的 API 不兼容。降级解决:
bash
pip3 install --user 'resolvelib>=0.5.3,<0.6.0'
踩坑三:Galaxy 服务器 API 报错
降级后继续报:
text
ERROR! Unexpected Exception: '/api/v3/plugin/ansible/content/published/collections/index/community/docker/versions/'
这已经是 Ansible 与 Galaxy 服务端的兼容问题了。与其继续修,不如绕开 ansible-galaxy,手动安装。
手动安装 collection
下载 tarball:
bash
curl -LO https://galaxy.ansible.com/download/community-docker-3.8.0.tar.gz
解压后发现 tarball 没有顶层目录,所有文件直接在根下。所以整体移动为 community/docker:
bash
mkdir -p ~/.ansible/collections/ansible_collections/community mkdir -p /tmp/docker-collection tar -xzf community-docker-3.8.0.tar.gz -C /tmp/docker-collection mv /tmp/docker-collection ~/.ansible/collections/ansible_collections/community/docker
验证:
bash
ansible-doc community.docker.docker_container_info | head -20
能输出模块文档就说明安装成功。
踩坑四:http+docker 报错
写一个 check-container.yml:
yaml
---
- name: 检查 WordPress 容器状态
hosts: local
gather_facts: false
tasks:
- name: 获取 wp-app-practice 容器信息
community.docker.docker_container_info:
name: wp-app-practice
register: container_info
- name: 显示容器状态
ansible.builtin.debug:
msg: "容器状态: {{ container_info.container.State.Status }}"
- name: 显示容器 IP
ansible.builtin.debug:
msg: "容器 IP: {{ container_info.container.NetworkSettings.Networks['wp-practice-net'].IPAddress }}"
运行后报错:
text
Error connecting: Error while fetching server API version: Not supported URL scheme http+docker
这是 requests 2.32.0 之后与旧版 docker 库的不兼容问题。
先升级 docker 库:
bash
pip3 install --user --upgrade docker
如果还报错,降级 requests:
bash
pip3 install --user 'requests<2.32.0'
修复后运行成功:
text
TASK [显示容器状态] ***
ok: [localhost] => {
"msg": "容器状态: running"
}
TASK [显示容器 IP] ***
ok: [localhost] => {
"msg": "容器 IP: 172.20.0.3"
}
练习 3:用 WP-CLI 操作 WordPress
WP-CLI 是 WordPress 官方命令行工具。Docker 官方镜像没有预装,先手动装:
bash
docker exec wp-app-practice bash -c "curl -sO https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar && chmod +x wp-cli.phar && mv wp-cli.phar /usr/local/bin/wp"
验证:
bash
docker exec wp-app-practice wp --info --allow-root
输出 WP-CLI version: 2.12.0。
然后写 wp-cli-tasks.yml:
yaml
---
- name: 用 WP-CLI 操作 WordPress
hosts: local
gather_facts: false
vars:
container: wp-app-practice
tasks:
- name: 查看 WP-CLI 版本
community.docker.docker_container_exec:
container: "{{ container }}"
command: wp --info --allow-root
register: wp_info
- name: 显示 WP-CLI 信息
ansible.builtin.debug:
msg: "{{ wp_info.stdout_lines }}"
- name: 列出已安装插件
community.docker.docker_container_exec:
container: "{{ container }}"
command: wp plugin list --allow-root
register: plugin_list
- name: 显示插件列表
ansible.builtin.debug:
msg: "{{ plugin_list.stdout_lines }}"
- name: 查看站点 URL
community.docker.docker_container_exec:
container: "{{ container }}"
command: wp option get siteurl --allow-root
register: site_url
- name: 显示站点 URL
ansible.builtin.debug:
msg: "站点 URL: {{ site_url.stdout }}"
运行:
bash
ansible-playbook -i inventory.ini wp-cli-tasks.yml
输出:
text
TASK [显示插件列表] ***
ok: [localhost] => {
"msg": [
"name\tstatus\tupdate\tversion\tupdate_version\tauto_update",
"akismet\tinactive\tavailable\t5.7\t5.7.2\toff",
"hello\tinactive\tnone\t1.7.2\t\toff"
]
}
TASK [显示站点 URL] ***
ok: [localhost] => {
"msg": "站点 URL: http://x162-43-92-249.tail9c4209.ts.net:8081"
}
PLAY RECAP ***
localhost : ok=7 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
一个值得注意的细节
docker_container_exec 模块总是报告 changed,即使命令只是查询。原因是它本质是“执行命令”,Ansible 无法判断命令是否改变了系统状态。
如果希望查询类任务报告 ok,可以加 changed_when: false:
yaml
- name: 查看 WP-CLI 版本
community.docker.docker_container_exec:
container: "{{ container }}"
command: wp --info --allow-root
register: wp_info
changed_when: false
这是 Ansible 里很常用的技巧——显式告诉 Ansible 这个任务不会改变状态。
这次踩坑教会我的事
Ansible 的依赖链比想象中脆弱。
ansible-galaxy 一个命令,背后牵扯到 pyopenssl、cryptography、resolvelib、requests、docker 五个库的版本兼容。任何一个不匹配,整个命令就崩溃。
Ubuntu 系统自带的 Python 包(/usr/lib/python3/dist-packages/)和 pip 用户包(~/.local/lib/python3.10/site-packages/)混在一起,更是雪上加霜。
经验:遇到 Ansible 报错,先查 Python 包版本。 pip3 install --user 能覆盖系统包,是修复这类问题的常用手段。
下一步
Part 3 会尝试更有实际意义的操作:
- 用 Ansible 创建测试文章、安装插件
- 导出数据库备份到 VPS
- 写一个健康检查 playbook(容器状态 + HTTP 200 + 站点 URL 可达)
Terraform 负责“搭台子”,Ansible 负责“唱戏”,两者配合才算完整的自动化。
如果你也在 VPS 上练手,欢迎交流踩坑经验。
