当前位置: 首页 > news >正文

Windows 作为 Ansible 节点的完整部署流程(含 Docker 部署 Ansible)

前言

在日常运维中,Windows 主机上往往存在大量的 bat、ps1 脚本,每台机器跑的脚本还不一样,有些甚至需要多台机器联动。手动维护既麻烦,又容易出错。

我的场景里,Windows 系统非常关键,不允许开发人员或普通用户随意访问,因此需要一个安全、统一的方式来管理这些脚本。

最开始考虑的方案是 JenkinsAnsible

  • Jenkins 的优势在于能直观看到节点是否在线,但权限粒度不足:用户可以新建任意任务并选择指定节点执行,风险太大(比如误操作删除文件)。

    目前开发同事工作需要登录 Jenkins 并创建 Job。

  • Ansible 没有内置的节点在线监控,且 Windows 作为节点无需额外安装 agent 和开启 SSH 服务器,只要启用系统自带的 WinRM 功能即可。

    Ansible 目前完全由 IT 管理,不用担心权限泄露问题

综合考虑后,还是选择了 Ansible 来统一管理 Windows 脚本。下面记录下从原理到完整落地的全过程。


一、工作原理

Windows 作为 Ansible 节点的核心机制,可以用一句话概括:

控制端发送 PowerShell/命令 → Windows 执行 → 返回 JSON 结果 → 控制端解析

具体分为几个部分:

  1. 三要素

    • 控制节点(Linux 上的 Ansible)
    • 被管理节点(Windows,不需要安装 Ansible)
    • 通信协议(WinRM,默认端口 5985/5986)
  2. 连接与认证

    • 控制端通过 pywinrm 库和 Windows WinRM 服务通信
    • 常见认证:basic、NTLM、Kerberos
    • 内网环境可以用 basic+HTTP,生产推荐 Kerberos/HTTPS
  3. 模块执行流程

    • 控制端选择目标主机
    • 建立 WinRM 会话
    • 传输 PowerShell 模块/命令到 Windows
    • Windows 执行并产出 JSON 结果
    • 结果返回控制端解析
  4. 文件与脚本管理

    • win_copy:复制文件
    • win_command / win_shell:执行 bat/命令
    • win_powershell:执行 PowerShell 脚本
  5. 幂等性

    • 尽量使用模块(如 win_featurewin_package),而不是裸命令
    • 自写脚本需处理“检查-执行”逻辑
  6. 权限

    • 通常用管理员账号或 become_method: runas
  7. 离线环境

    • Windows 开启 WinRM 不需要联网
    • 控制端 Linux 如需安装 pywinrm,可提前下载 wheel 包离线安装

二、Ansible 版本要求

  • 2.8 及以上版本原生支持 Windows 节点

  • 推荐使用最新稳定版,兼容性更好

  • 查看版本:

    ansible --version
    
  • 检查支持的模块:

    ansible-doc -l | grep win
    

如果版本过旧,可以通过 pip install --upgrade ansible 升级(离线环境提前下载好包)。


三、环境部署

这里给一个完整的部署流程。

Ansible 部署(Docker)

  • 1、Ansible 官方 镜像不更新了
  • 2、用 Python 镜像部署 Ansible 更加轻量级,更方便自定义

所以下面使用 Python 镜像进行 Ansible 部署。

Ansible 容器镜像

docker pull python:3.9.23-trixie

拉取 python:3.9.23-trixie 容器镜像

编写 Dockerfile 并构建镜像

vim DockerfileFROM python:3.9.23-trixie
ARG http_proxy="http://IP:PORT"
ARG https_proxy="http://IP:PORT"  # 代理,用不上可以不加
RUN apt update && apt install -y sshpass git
RUN pip install ansible pywinrmdocker build -t python:3.9.23-trixie-ansible .

测试

docker run --rm python:3.9.23-trixie /bin/bash -c "ansible --version && ansible-doc -l | grep win"

显示 Ansible 版本号和 win 支持模块即容器镜像完成构建。

启动 Ansible

docker run -it --name ansible -v /root/ansible/ansible:/etc/ansible python:3.9.23-trixie /bin/bash

把本地 /root/ansible/ansible 目录映射到容器的 /etc/ansible 目录
不用 -p 映射端口出来,Ansible 能访问 Win 节点端口就行,Win 节点不用访问 Ansible。

三、Windows 节点配置

为方便测试,后续连接 Wiundows 均使用以下账号密码:

  • 账号:lian
  • 密码:lian

且 Windows 的 IP 为 192.168.62.148

开启 WinRM

  • Ansible 官方在 Github 上有个开启 WinRM 脚本的 Powershell 脚本
    https://github.com/ansible/ansible-documentation/blob/devel/examples/scripts/ConfigureRemotingForAnsible.ps1

但官方不建议使用这个脚本(安全问题),建议最好自己敲 PowerShell 命令去开启服务,如果非要用的话建议删除并只保留自己需要的命令。

感兴趣的可以试一下上面 ps1 脚本,开启 WinRM 总共就两条命令,这里我就手敲执行好了。

管理员 PowerShell 执行:

# 启用 WinRM(管理员)
winrm quickconfig -q# 允许 Basic 认证 & 明文传输(建议仅限内网/测试用)
winrm set winrm/config/service/auth '@{Basic="true"}'
winrm set winrm/config/service '@{AllowUnencrypted="true"}'
# 执行这一句的时候会要求网络类型改为‘域’或‘专用’(默认‘公共’)
# 在‘网络设置’→‘以太网’→‘网络’→点击勾选‘专用’,再执行命令即可生效# 放行防火墙
New-NetFirewallRule -Name "WinRM" -DisplayName "WinRM" -Protocol TCP -LocalPort 5985 -Action Allow# 授权用户可通过 WinRM 远程执行命令(Remote Management Users 是 Windows 用户组)
net localgroup "Remote Management Users" ansible /add# 检查监听器
winrm e winrm/config/listener

四、配置 Ansible Inventory

在 Ansible 的 /etc/ansible/hosts 内写入:

[windows]
192.168.62.148[windows:vars]
ansible_user=lian
ansible_password=lian
ansible_connection=winrm
ansible_winrm_transport=basic
ansible_port=5985

⚠ 注意:如果用 Docker 容器跑的 Ansible,192.168.62.148 必须能从宿主机/容器访问。


五、测试连通性

在 Ansible 容器里执行:

ansible windows -m win_ping

成功输出:

win01 | SUCCESS => {"changed": false,"ping": "pong"
}

六、执行脚本示例

把 Windows 上的脚本都放到 Ansible 控制端,然后在执行时传输到 Windows 节点再运行,这样 更好管理 脚本。

先准备个测试用的 BAT 批处理脚本(test.bat):

@echo off
chcp 65001 >nulecho ================================
echo 当前路径信息
echo ================================
echo 当前路径是:%cd%
echo.
echo 当前目录下的文件和文件夹:
dir
echo.echo ================================
echo 当前时间和时区信息
echo ================================
echo 当前日期和时间:%date% %time%
echo.
echo 当前时区:
where tzutil >nul 2>&1 && tzutil /g
echo.pause

PowerShell 脚本(test.ps1):

# 获取当前时间
$time = Get-Date -Format "yyyy-MM-dd HH:mm:ss"# 获取计算机名
$computer = $env:COMPUTERNAME# 获取当前用户名
$user = $env:USERNAME# 输出结果
Write-Output "当前时间: $time"
Write-Output "计算机名: $computer"
Write-Output "当前用户名: $user"

这两个脚本都放到 Ansible/etc/ansible/file 目录下。

在 Ansible 上调用 Windows bat 脚本,有三种解决方法:

方法 1:win_copy + 执行

先把脚本从控制节点复制到 Windows,再执行。

vim test1.yml
- name: Run scripts on Windowshosts: windowstasks:- name: Copy bat file to Windowsansible.windows.win_copy:src: /etc/ansible/file/test.batdest: C:\Users\lian\Desktop\script\test.bat- name: Run bat fileansible.windows.win_command: C:\Users\lian\Desktop\script\test.bat- name: Copy ps1 script to Windowsansible.windows.win_copy:src: /etc/ansible/file/test.ps1dest: C:\Users\lian\Desktop\script\test.ps1- name: Run ps1 fileansible.windows.win_powershell:script: |& "C:\Users\lian\Desktop\script\test.ps1"
ansible-playbook test1.yml

这样 Windows 脚本统一放在 Ansible 项目里(比如 /etc/ansible/file/ 目录),方便版本管理。

如果要打印脚本输出的,playbook 脚本改为如下:

- name: Run scripts on Windowshosts: windowstasks:- name: Copy bat file to Windowsansible.windows.win_copy:src: /etc/ansible/file/test.batdest: C:\Users\lian\Desktop\script\test.bat- name: Run bat file and show outputansible.windows.win_command: C:\Users\lian\Desktop\script\test.batregister: bat_result- name: Display bat outputdebug:var: bat_result.stdout_lines- name: Copy ps1 script to Windowsansible.windows.win_copy:src: /etc/ansible/file/test.ps1dest: C:\Users\lian\Desktop\script\test.ps1- name: Run ps1 file and show outputansible.windows.win_shell: powershell.exe -ExecutionPolicy Bypass -File C:\Users\lian\Desktop\script\test.ps1register: ps1_result- name: Display ps1 outputdebug:var: ps1_result.stdout_lines

另外会发现,Windows 执行这些脚本只有返回到 Ansilble 只有执行和打印输出信息如果脚本本身就有问题,Ansible 执行过程是不会中断、也不会有脚本以外的报错等信息
这样可以结合输出,追加脚本打印输出,跟据 Windows 执行脚本时返回的信息,判断输出结果符不符合预期(如:Success),符合的话就是正确执行。

方法 2:直接传脚本内容(小脚本用)

如果脚本不大,可以直接嵌到 Playbook,用 win_powershell / win_shellinline script 方式:

- name: Run scripts on Windows (inline)hosts: windowstasks:- name: Run bat inlineansible.windows.win_shell: |if not exist "C:\Users\lian\Desktop\script\test2.bat" echo. > "C:\Users\lian\Desktop\script\test2.bat"echo echo Hello from BAT > "C:\Users\lian\Desktop\script\test2.bat""C:\Users\lian\Desktop\script\test2.bat"- name: Run ps1 inlineansible.windows.win_powershell:script: |Write-Output "Hello from PowerShell"

缺点:脚本内容写在 YAML 里,不好维护,适合临时命令。

方法 3:Ansible roles + 模板化(更适合大规模)

方法 1 差不多。

把 bat/ps1 脚本放到 /etc/ansible/file/目录下,用 win_copy 统一分发并执行,方便团队协作和版本控制。

vim test3.yml
- name: Copy and run BAThosts: windowstasks:- block:- name: Copy BAT filewin_copy:src: /etc/ansible/file/test.batdest: C:\Users\lian\Desktop\script\test.bat- name: Run BAT filewin_command: C:\Users\lian\Desktop\script\test.battags:- bat- name: Copy and run PS1hosts: windowstasks:- block:- name: Copy PS1 filewin_copy:src: /etc/ansible/file/test.ps1dest: C:\Users\lian\Desktop\script\test.ps1- name: Run PS1 filewin_powershell:script: C:\Users\lian\Desktop\script\test.ps1tags:- ps1

执行:

ansible-playbook -i windows test3.yml -t bat

注意事项

测试过程中,发现 Windows LTSC 版阉 割太多,好多事情都做不了,一个简单的 CMD、简单的 bat 脚本,都会把变量里的内容打印并识别成执行语句。

Ansible 里的 win_xx 等命令就更不用说了,Windows LTSC 上很多依赖调用不了,执行会报错。

当然,用 Windows Home 版 作为 Ansbile 节点也不行,因为它无法开启 WinRM 服务。
所以实际上,只能用 Server 版专业/企业版 作为 Ansible 节点。

好在我实际使用场景都是 Window Server 版,所以不用担心功能严格问题。


总结

  1. Ansible 控制端(Docker 内)通过 Python 的 pywinrm 库发送 WinRM 请求。
  2. Windows 节点 WinRM 服务接收请求 → 验证用户身份 → 调用 PowerShell 引擎执行命令。
  3. 返回结果 通过 WinRM 协议传回 Ansible。
  4. Ansible 汇总输出,显示在控制端。

虽说 Windows 的 bat/ps1 脚本也可以存放到 Windows 节点上,但不好管理。

Windows 的脚本都放到 Ansible 上,并且 Playbook 也在 Ansible 上,再加上 Git 仓库,这样便于对整套 Playbook 和 Windows 脚本进行版本管理。可实现,一个平台(Ansible)上就可以完成脚本编写 + 下发了。

http://www.dtcms.com/a/410151.html

相关文章:

  • 今日面试之快问快答:Redis篇
  • 微论-神经网络的亲情密码,权重矩阵的家庭关系论
  • 建个个人网站一年多少钱凡科网网页版登录入口
  • html论坛网站模板小企业网站建设公司
  • 邮件服务器软件哪个好?2025邮件服务器软件推荐
  • langchain-基于agent架构的开发
  • vector深度求索(下)模拟篇
  • 服务器密码错误被锁定如何解决?
  • 远程软件横评:UU远程、ToDesk、向日葵
  • 金仓数据库替代MongoDB:电子证照系统国产化改造实战
  • 关于XLang语言的第三轮答疑
  • 地图网站开发企业网站模板素材
  • Nginx生产环境编译配置升级回退新增模块全解析
  • wordpress 企业站开发wordpress主题配置文件
  • OpenAI携手SAP与微软:推动德国公共部门主权云AI落地
  • NVIDIA Dynamo深度解析:如何优雅地解决LLM推理中的KV缓存瓶颈
  • 三星首款XR头显亮相高通骁龙峰会,微美全息多场景覆盖巩固VR/AR竞争力
  • Redis03-缓存知识点
  • 5网站开发项目经理接到网站开发怎么开展
  • 云原生周刊:K8s 故障排查秘籍
  • D017 vue+django+neo4j音乐知识图谱推荐可视化分析系统|带管理员角色+爬虫
  • 设计模式(C++)详解——迭代器模式(1)
  • 怎么知道网站有没有做301重定向建立网站商城建议
  • 仁寿建设局网站青岛专业网站排名推广
  • Notepad++ 本地提权漏洞|复现|分析
  • HCIP-IoT 真题详解(章节D),嵌入式基础与南向开发 /Part1
  • JavaEE初阶3.0
  • 【网络协议】IoT 设备入网认证机制
  • 微信小程序学习(二)
  • 微信小程序里 uni.navigateTo 用的多了, 容易报错,