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 一个命令,背后牵扯到 pyopensslcryptographyresolvelibrequestsdocker 五个库的版本兼容。任何一个不匹配,整个命令就崩溃。

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 上练手,欢迎交流踩坑经验。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注