在微服务与容器化部署日益普及的今天,快速生成Kubernetes集群的拓扑预览图成为团队沟通与文档编写的常见需求。使用Node.js搭配Vercel的无服务器函数,可以低成本实现一个Mock2Image接口,它接收模拟的集群状态数据,并返回一张包含节点与Pod信息的PNG图片。本文将通过一个完整项目说明如何在Vercel平台完成这一功能,重点解决依赖选型、图片渲染和部署配置三个关键环节。

一、Mock2Image的定位与运行环境选择
Mock2Image可以理解为一个接受集群模拟数据并输出图片的轻量服务。它的核心价值在于把结构化的K8s集群信息转化为直观的可视化图形,便于在文档、聊天群或CI报告中使用。在实现方式上,常见做法有启动无头浏览器截图或者使用服务端Canvas渲染,前者在Vercel的无服务器环境中资源消耗较大,后者则需要处理原生模块和字体兼容问题。本文选用@vercel/og提供的ImageResponse接口,底层基于Satori和Resvg将HTML字符串直接渲染为PNG,无需Chromium和node-canvas的原生依赖。
Vercel的Edge Runtime支持这种纯JavaScript渲染方式,能够在靠近用户的边缘节点快速返回图片。与传统的自建K8s服务相比,这个方案不需要维护常驻容器,也不需要为每个请求单独启动进程。通过设置函数超时和内存限制,可以稳定处理单个图片生成请求。接下来会说明如何搭建项目并组织K8s模拟数据,让接口在没有真实集群的情况下也能输出高度定制化的架构图。
二、项目结构与依赖配置
一个典型的Vercel无服务器函数项目可以按以下结构组织。将图片生成逻辑放在api目录下,Vercel会自动将其暴露为HTTP端点;模拟数据生成模块放在lib目录中,便于复用和测试。前端调用时只需向该端点发起GET请求,并附加尺寸、主题等查询参数即可。
project/ ├── api/ │ └── mock2image.js ├── lib/ │ └── k8s-data.js ├── package.json └── vercel.json
依赖方面只需要安装@vercel/og即可,它是Vercel官方提供的图片生成库,内部已处理字体加载与SVG转PNG的细节。执行以下命令完成初始化:
npm init -y npm install @vercel/og
安装完成后,在package.json中添加type字段为module,以便使用ES模块语法。同时创建vercel.json来配置函数超时时间,避免复杂图片渲染时被平台默认限制中断。
三、实现K8s集群数据模拟与图片渲染
模拟数据模块负责生成一组节点信息,包括节点名称、CPU、内存和Pod数量。这些数据可以直接手工编写,也可以从真实K8s API中拉取后做轻量转换。为了保持示例简洁,这里使用静态数组。
// lib/k8s-data.js
export function generateClusterData() {
const nodes = [
{ name: 'node-1', cpu: '4 vCPU', memory: '8 GiB', pods: 12 },
{ name: 'node-2', cpu: '4 vCPU', memory: '8 GiB', pods: 15 },
{ name: 'node-3', cpu: '8 vCPU', memory: '16 GiB', pods: 24 }
];
return { cluster: 'prod-cluster', nodes };
}
接口文件是核心,它从请求中解析参数,生成集群数据,然后拼接一段HTML字符串,将其交给ImageResponse渲染。模板字符串中的HTML标签需要使用实体转义以确保在代码块中正常显示,但实际运行时是普通字符串。这个接口采用Edge Runtime,可以显著降低冷启动时间。
// api/mock2image.js
import { ImageResponse } from '@vercel/og';
import { generateClusterData } from '../lib/k8s-data';
export const config = {
runtime: 'edge',
};
export default async function handler(req) {
const { searchParams } = new URL(req.url);
const width = Number(searchParams.get('width')) || 1200;
const height = Number(searchParams.get('height')) || 630;
const cluster = generateClusterData();
const html = `
<div style="width: ${width}px; height: ${height}px; display: flex; flex-direction: column; background: #0f172a; color: #e2e8f0; font-family: sans-serif; padding: 40px;">
<h1 style="font-size: 48px; margin: 0;">K8s Cluster Mock</h1>
<div style="display: flex; gap: 20px; margin-top: 40px;">
${cluster.nodes.map(node => `
<div style="flex: 1; background: #1e293b; border-radius: 12px; padding: 20px;">
<h2 style="font-size: 24px; margin: 0 0 12px;">${node.name}</h2>
<p style="font-size: 18px; margin: 4px 0;">CPU: ${node.cpu}</p>
<p style="font-size: 18px; margin: 4px 0;">Memory: ${node.memory}</p>
<p style="font-size: 18px; margin: 4px 0;">Pods: ${node.pods}</p>
</div>
`).join('')}
</div>
</div>
`;
return new ImageResponse(html, {
width,
height,
});
}
上述代码中,模板字符串内部使用了转义后的HTML实体,读者在实际运行时看到的是正常的<div>等标签。调用时可以通过?width=800&height=400改变图片尺寸,满足不同展示场景。如果希望在图片中包含服务Service和Deployment的信息,只需扩展generateClusterData返回的数据结构,并在HTML模板中增加对应的卡片区块即可。
四、部署到Vercel与常见问题排查
将项目推送到Git仓库后,在Vercel控制台导入项目,构建命令保持默认,输出目录留空即可。部署成功后,访问/api/mock2image路径就能得到一张PNG图片。为了设置更长的函数超时时间,可以在vercel.json中显式声明maxDuration,例如设置为30秒。
{
"functions": {
"api/mock2image.js": {
"maxDuration": 30
}
}
}
如果图片出现字体显示异常或中文乱码,可以检查@vercel/og是否成功加载了字体,或者将字体文件放在项目中的public目录并通过fetch额外注入。另外,Edge Runtime对内存有限制,当节点数量非常多时,HTML字符串会显著增大,建议控制一次渲染的节点数在20个以内。若超过限制,可以将数据分页,或者对图片进行降采样处理。
另一个常见问题是本地开发时接口返回500。此时需要确认Node.js版本不低于18,且@vercel/og版本与平台兼容。可以在本地运行vercel dev进行调试,查看控制台输出的具体错误堆栈。通过逐步排查,通常能够快速定位并解决依赖或语法层面的问题,顺利上线一个可用的K8s Mock2Image服务。
Node.jsVercel Mock2ImageK8s修改时间:2026-09-27 03:26:02