Microsoft 存储空间直通(Storage Spaces Direct,简称 S2D)允许将多台 Windows Server 节点的本地磁盘通过网络直接汇聚成一个存储池,配合故障转移集群实现高可用。它的能力很强大,但日常管理基本依赖 PowerShell 命令和故障转移集群管理器,图形化体验并不理想。对于需要长期盯着存储池容量、虚拟磁盘健康度和节点状态的运维团队来说,用 Vue 3 搭建一套 Web 管理台是很实际的选择。本文将从工程化角度出发,完整讲解如何把 S2D 的管理能力封装成一套结构清晰的前端项目。

一、整体架构设计:前后端如何分工
S2D 的所有管理操作最终都要落到 Windows Server 上执行,浏览器里的 Vue 应用不可能直接调用 PowerShell。因此工程上必须采用前后端分离架构:Vue 3 负责界面展示与交互,一个 ASP.NET Core 或者 Node.js 中间层负责接收 HTTP 请求,在集群管理节点上执行 PowerShell,再把 JSON 结果返回给前端。
这个中间层是整个方案的关键。建议在服务端把 PowerShell 输出统一转换成结构稳定的 DTO,例如节点信息包含节点名、状态、容量、剩余空间,虚拟磁盘信息包含名称、健康状态、冗余类型、已用容量。前端永远只消费这些稳定字段,而不关心底层命令的细节。这样即使将来 S2D 命令输出格式变化,也只需要改后端转换逻辑,前端零改动。
认证方面,由于管理平台权限敏感,建议后端采用 Windows 集成认证或者 JWT 加 HTTPS,前端在路由守卫里统一处理 401 跳转。不要把 PowerShell 直接暴露成通用执行接口,那等于开了一个远程命令执行的后门,务必只暴露白名单化的业务接口。
二、Vue 3 工程初始化与目录规划
使用 Vite 创建项目是目前的标准做法,脚手架选择 Vue 3 加 TypeScript,状态管理用 Pinia,路由用 Vue Router 4。工程化不只是把项目跑起来,更重要的是目录结构能够支撑长期迭代。一个比较实用的目录划分如下:
s2d-console/ ├── src/ │ ├── api/ # axios 封装与各模块接口 │ ├── stores/ # Pinia 状态仓库 │ ├── views/ # 页面级组件 │ │ ├── Dashboard.vue │ │ ├── Nodes.vue │ │ └── VirtualDisks.vue │ ├── components/ # 可复用组件 │ │ ├── NodeCard.vue │ │ └── HealthBadge.vue │ ├── composables/ # 组合式函数 │ └── types/ # 与后端 DTO 对应的类型定义 ├── vite.config.ts └── package.json
类型定义要与后端 DTO 保持同步,这是 TypeScript 项目最容易失控的地方。可以在 types/s2d.d.ts 里集中声明接口,例如 StorageNode、VirtualDisk 等,所有组件和 store 都从这里导入类型,避免同一个结构在各处重复手写导致不一致。
Pinia 的使用建议按业务域拆分 store,比如 useNodeStore 管节点数据,useDiskStore 管虚拟磁盘。Dashboard 页面往往需要同时消费多个 store,按域拆分比按页面拆分更容易复用。
三、核心功能实现:数据获取与可视化
数据刷新策略需要在轮询和 WebSocket 之间做取舍。S2D 的指标变化频率通常不高,节点容量、磁盘健康状态每 10 到 30 秒采集一次完全够用,因此简单的轮询反而是最稳妥的方案。用 Vue 3 的组合式 API 可以把轮询逻辑抽成一个可复用函数:
import { onMounted, onUnmounted, ref } from 'vue'
export function usePolling(fetcher: () => Promise<void>, interval = 15000) {
let timer: number | undefined
onMounted(() => {
fetcher()
timer = window.setInterval(fetcher, interval)
})
onUnmounted(() => {
if (timer) window.clearInterval(timer)
})
}在 Dashboard 页面里,调用 usePolling 定时拉取数据,再交给 ECharts 渲染。存储池容量用环形图,IOPS 和延迟用时间序列折线图,节点列表用卡片网格展示。节点卡片组件内部根据健康状态渲染不同颜色的 HealthBadge,Healthy 显示绿色、Warning 显示橙色、Unhealthy 显示红色,让值班人员一眼就能定位问题节点。
虚拟磁盘页面建议用表格呈现,列包括名称、 resiliancy 类型(镜像、擦除编码)、容量、健康状态。表格组件可以基于 Element Plus 或者 Naive UI 封装,再配合筛选功能按健康状态过滤。需要注意 S2D 集群在修复(repairing)状态时虚拟磁盘健康度会处于过渡态,前端要为这类状态设计专门的展示样式,而不是简单归入异常红色。
<script setup lang="ts">
import { useDiskStore } from '@/stores/useDiskStore'
import HealthBadge from '@/components/HealthBadge.vue'
const store = useDiskStore()
</script>
<template>
<el-table :data="store.disks">
<el-table-column prop="name" label="虚拟磁盘" />
<el-table-column prop="resiliency" label="冗余类型" />
<el-table-column prop="capacityGB" label="容量 (GB)" />
<el-table-column label="健康状态">
<template #default="{ row }">
<HealthBadge :status="row.healthStatus" />
</template>
</el-table-column>
</el-table>
</template>四、告警与异常处理的工程细节
监控平台的价值在于出问题时能第一时间发现。前端可以做一层轻量告警:当轮询返回的节点状态从 Healthy 变为 Warning 或 Unhealthy 时,通过浏览器 Notification API 弹出提醒,同时在页面顶部挂一条持久的警告横幅。状态变化检测放在 Pinia store 的 action 里做,因为 store 是唯一持有历史状态的地方,组件里做会重复且容易遗漏。
接口异常处理同样不能马虎。PowerShell 命令执行超时、集群暂时不可达都是常见情况,axios 拦截器里统一捕获错误,给 store 打上 offline 标记,界面显示数据时间戳和失联提示,而不是让用户盯着一份过期的假数据。这一点在运维场景里尤其重要,过期数据比没有数据更危险。
最后在部署环节,Vue 项目打包后是纯静态文件,可以由后端 ASP.NET Core 直接托管,也可以放到 IIS 上独立部署,配置好 HTTPS 和反向代理即可。整体方案技术门槛不高,却能显著改善 S2D 日常管理的体验,对于维护超融合集群的团队来说是性价比很高的投入。
Vue 3Microsoft S2D存储直通修改时间:2026-09-07 11:07:07