☰
不再逐台装Docker:我用Ansible Playbook批量统一服务器环境
2026/10/14 22:29:42 网站建设 项目流程

不再逐台装Docker:我用Ansible Playbook批量统一服务器环境

前言

新机器少的时候,Docker 一台台装也还能接受;可一旦服务器数量上来,重复安装依赖、添加软件源、启动服务、设置开机自启,再去检查每台机器有没有漏步骤,很快就会变成一件又慢又容易出错的事。更麻烦的是,手工操作久了以后,同一批服务器还可能出现版本和配置不一致。

这次我把 Docker 的安装流程写进 Ansible Playbook,让控制节点通过 SSH 去执行:软件依赖、Docker 仓库、Docker 组件、服务启动和用户组配置都交给剧本统一完成。先在 Ubuntu 控制节点把 Ansible 安装好,再通过 Inventory 管理目标主机。

本地网络里验证成功以后,后半部分继续测试跨网络场景:把目标机的 SSH 端口通过公网 TCP 入口提供给 Ansible,再用同一份 Playbook 远程部署。

不过这篇配置里有两个地方必须先看清:Inventory 使用的是dbservers,Playbook 却写成docker_group;另外正文提到“剧本自动安装 cpolar”,但实际 Playbook 并没有这一任务。新版会保留代码不动,同时把这两个问题明确指出。

这种方式最适合重复性强、步骤固定的基础环境交付。以后再新增服务器,不需要重新翻安装笔记,也不用担心某一台漏掉软件源或开机自启;只要主机清单和变量准备好,就可以继续复用同一套剧本。

1 为什么这类任务适合交给Ansible

如果只是装一台服务器,手动执行命令并不复杂。

真正麻烦的是:

  • 机器数量越来越多;
  • 同样的步骤要重复执行;
  • 某台机器漏了一条命令;
  • 某台机器的软件源不同;
  • Docker 服务忘了开机自启;
  • 新同事接手以后又得重新理解整套安装流程。

Ansible 的价值就在这里:

把运维步骤从“靠人记住”变成“让剧本重复执行”。

它通过 SSH 管理目标主机,被控端不需要额外安装 Ansible Agent。

2 Ansible更适合做“标准化”,而不只是批量执行

Ansible 常见能力包括:

  • 配置管理;
  • 应用部署;
  • 任务自动化;
  • IT 编排;
  • 批量执行;
  • 文件分发;
  • 服务管理;
  • 用户与权限管理。

它和单纯 Shell 脚本最大的区别之一,是大量模块具备幂等特性。

也就是说:

目标已经符合要求时,再执行一次通常不会重复修改。

不过“Ansible 天然幂等”也不能理解成所有 shell、command、自定义脚本都自动幂等。

真正是否安全重复执行,还要看具体用了什么模块、任务怎么写。

3 先在Ubuntu控制节点安装Ansible

先更新系统:

sudoaptupdatesudoaptupgrade-y

然后安装:

aptinstall-yansible

这里通过 APT 安装的是:

当前软件源中提供的 Ansible 版本。

更准确地说,不应该简单写成“安装最新版”。

安装完成后查看版本:

ansible--version

4 如果没有/etc/ansible目录,就手动创建

先查看:

ls/etc/ansible

如果目录不存在,再创建:

mkdir-p/etc/ansible

接下来准备 Inventory 和 Ansible 配置。

5 先创建一个本机Inventory做最小验证

写入:

cat>/etc/ansible/hosts<<EOF [local] localhost ansible_connection=local EOF

这个配置定义:

[local]

并让 localhost 使用本地连接。

然后创建:

cat>/etc/ansible/ansible.cfg<<EOF [defaults] inventory = /etc/ansible/hosts host_key_checking = False remote_user = root stdout_callback = yaml EOF

其中几个参数值得看一下:

  • inventory:默认主机清单;
  • host_key_checking = False:关闭 SSH 主机指纹检查;
  • remote_user = root:默认远程用户设为 root;
  • stdout_callback = yaml:调整输出格式。

为了实验方便,关闭 Host Key Checking 可以减少第一次连接时的交互。

但正式环境中,这会降低对 SSH 主机身份的校验能力。

6 先用ping模块验证Ansible本身

执行:

ansible localhost-mping

这里的ping不是普通 ICMP ping。

它验证的是:

Ansible 能不能正常执行模块并获得响应。

这一步成功以后,再继续配置其他目标主机。

7 准备目标主机Inventory

进入:

cd/etc/ansible

然后配置:

[dbservers]192.168.42.146ansible_user=rootansible_port=22ansible_password=*****

当前主机组叫:

dbservers

目标主机:

192.168.42.146

连接用户:

root

SSH 端口:

22

这里为了演示直接写了ansible_password。

长期环境不建议把真实密码明文留在 Inventory 文件里。

更合理的方式通常是:

  • SSH Key;
  • Ansible Vault;
  • 受控凭据管理。

8 Playbook负责把Docker安装步骤固化下来

部署文件:

deploy_docker.yml

配置如下:

--- - name: Ansible一键部署Docker环境 hosts: docker_group become: true tasks: - name: 安装yum工具依赖 yum: name: yum-utils state: present - name: 添加Docker yum软件源 yum_repository: name: docker-ce description: Docker CE stable repo baseurl: https://download.docker.com/linux/centos/$releasever/$basearch/stable gpgcheck: yes gpgkey: https://download.docker.com/linux/centos/gpg - name: 安装Docker全套组件 yum: name: - docker-ce - docker-ce-cli - containerd.io state: present - name: 启动docker服务并设置开机自启 systemd: name: docker state: started enabled: yes - name: 将登录用户加入docker组,免sudo操作docker user: name: "{{ ansible_user }}" groups: docker append: true

这个 Playbook 做了几件事:

  1. 安装yum-utils;
  2. 添加 Docker CE 软件源;
  3. 安装docker-ce、docker-ce-cli、containerd.io;
  4. 启动 Docker;
  5. 设置开机自启;
  6. 把登录用户加入 docker 组。

这就是把“手动安装 Docker”变成可重复执行的剧本。

9 这里有一个会直接影响执行的主机组错误

前面的 Inventory 定义的是:

[dbservers]

但 Playbook 写的是:

hosts: docker_group

两者并不一致。

如果 Inventory 里没有另外定义docker_group,执行时通常不会匹配到刚才那台dbservers主机。

所以真正执行前必须让:

Inventory主机组名称

和:

Playbook的hosts

一致。

代码块按照已有内容原样保留,不在这里直接修改。

10 执行Playbook

命令:

ansible-playbook -i hosts deploy_docker.yml

执行时 Ansible 会按照 Inventory 找目标主机,再逐个运行 Playbook 里的任务。

如果输出里出现:

  • ok
  • changed

说明任务已经被处理。

如果出现:

  • unreachable
  • failed

就要先看 SSH、权限、主机组和软件源。

11 在目标主机验证Docker

执行:

docker-vsystemctl statusdocker

看到 Docker 版本号,并且服务状态为:

active (running)

就说明 Docker 已经正常启动。

到这里,本地网络内的自动部署链已经基本完成。

12 当前Playbook并没有自动安装cpolar

这里需要特别区分。

前面的 Docker Playbook 只包含:

  • yum依赖;
  • Docker软件源;
  • Docker组件;
  • Docker服务;
  • docker用户组。

里面并没有 cpolar 安装任务。

因此更准确的描述应该是:

Docker由Ansible Playbook部署,cpolar在后续章节单独安装。

不能把两部分写成“一个Playbook全部自动完成”。

13 后半部分真正解决的是跨网络SSH

如果 Ansible 控制节点和目标主机在同一个局域网,可以直接使用:

192.168.42.146:22

但如果目标主机在另一处网络,控制节点不能直接访问内网 SSH,就需要先解决:

控制节点怎么连上目标机22端口。

这里使用 cpolar 建立 TCP 入口。

14 安装cpolar

执行:

sudocurlhttps://get.cpolar.sh|sh

然后检查服务:

sudosystemctl status cpolar

进入:

服务器IP:9200

查看 Web 管理界面:

15 给目标机22端口创建TCP入口

配置:

  • 隧道名称:ssh
  • 协议:tcp
  • 本地地址:22
  • 端口类型:随机临时 TCP 端口
  • 地区:China Top

创建后查看在线隧道:

示例得到:

  • 域名:2.tcp.cpolar.top
  • 端口:15197

这时从外部访问:

2.tcp.cpolar.top:15197

实际会转到目标主机:

22

16 Ansible只需要把Inventory改成远程SSH入口

把 Inventory 改成:

[dbservers]2.tcp.cpolar.topansible_user=rootansible_port=15197ansible_password=***

这时候 Ansible 的目标已经不再是内网 IP。

而是:

公网TCP地址 + 公网端口

但 SSH 背后的目标仍然是原来的 Linux 主机。

17 再执行同一份Playbook

继续运行:

ansible-playbook-ihosts deploy_docker.yml

然后到目标主机确认:

可以看到 Docker 已经安装。

这一步验证的是:

Ansible控制节点 → 公网TCP入口 → SSH → 目标主机 → Playbook

跨网络链路能够执行。

18 这并不是“把Docker容器直接暴露到公网”

这里容易产生一个概念混淆。

当前创建的是:

SSH 22端口的TCP入口。

目的只是让 Ansible 能远程连接目标主机。

它并没有自动把目标机上未来运行的每个 Docker 容器都发布出去。

如果以后某个容器需要远程访问,还需要针对那个容器实际监听的端口单独设计网络入口。

所以:

Ansible负责部署,SSH负责管理,cpolar负责网络入口。

三个角色不要混在一起。

19 把SSH映射到公网以后,安全比连通更重要

公开 SSH 入口以后,要特别注意:

  • 不建议长期使用 root + 密码登录;
  • 更推荐 SSH Key;
  • 能关闭 root 远程登录就关闭;
  • 能关闭密码登录就关闭;
  • 密钥和密码不要写进公开文章;
  • 固定地址不要随意公开;
  • 有条件时限制允许访问的来源。

尤其当前 Inventory 直接使用:

ansible_user=root

和:

ansible_password=***

这更适合演示,不适合长期生产环境照搬。

20 随机TCP入口适合先验证

随机 TCP 地址适合做:

  • 临时测试;
  • 验证 Ansible 跨网络连接;
  • 临时远程运维。

如果只是短时间部署一次,不一定需要固定地址。

21 长期运维再保留固定TCP地址

进入预留页面:

示例地区:

China VIP

固定 TCP 地址:

15.tcp.cpolar.top:13633

然后进入隧道列表:

将端口类型改为:

固定TCP端口

并绑定预留地址:

更新以后,SSH入口就不需要随着随机端口变化而不断修改 Inventory。

具体固定 TCP 套餐、地区和规则可能变化,应以实际账号页面为准。

22 固定地址解决的是Inventory稳定,不是SSH安全

固定 TCP 的真正价值是:

Ansible Inventory不需要频繁改地址和端口。

它并不会自动解决:

  • root登录风险;
  • 密码泄露;
  • SSH暴力尝试;
  • 主机身份验证;
  • 权限控制。

所以固定地址配置完成以后,安全加固仍然要单独做。

23 这篇真正跑通的链路

同网环境:

Ansible → SSH → 目标主机 → Playbook → Docker

跨网环境:

Ansible → 公网TCP入口 → SSH → 目标主机 → Playbook → Docker

真正完成的是:

  • Ansible安装;
  • Inventory;
  • 本机ping验证;
  • Docker Playbook;
  • Docker安装与服务验证;
  • SSH随机TCP入口;
  • 公网地址写入Inventory;
  • 跨网络Playbook执行;
  • 固定TCP地址。

需要特别注意:

  • dbservers和docker_group名称不一致;
  • cpolar没有写入Docker Playbook;
  • 明文密码不适合长期使用;
  • root SSH不适合直接照搬;
  • host_key_checking=False会降低SSH身份校验;
  • 公网SSH入口应该配合更严格认证。

总结

这次我觉得 Ansible 最有价值的地方,不是“少敲几条 Docker 命令”,而是把服务器交付流程固定成了一份可以反复执行的 Playbook。机器多以后,统一软件源、Docker组件、服务状态和权限,比每台机器靠人手操作可靠得多。

本地网络里跑通以后,同一份 Playbook 又继续通过远程 SSH 入口执行,说明 Ansible 真正依赖的是 SSH 可达性,而不是服务器必须和控制节点处在同一个局域网。

不过这套配置还不能直接照搬到生产环境:主机组名称要先统一,密码不应该明文保存,root远程登录和关闭Host Key Checking也都需要重新收紧。

如果后面继续完善,我更建议把SSH Key、Ansible Vault、变量文件和Role一起补上,让这份Playbook从“能批量装Docker”逐步变成真正可维护的服务器初始化方案。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询