前端填写的deployment的表单怎么变为后端deployment的yaml,以及如何被部署到k8s集群的 #
你问的这个流程,其实就是 前端表单 → 后端生成 YAML → K8s API Server 部署 的链路。 我给你详细拆开说:
1️⃣ 前端表单 → Deployment 配置数据 #
前端的表单(比如输入 应用名、镜像名、副本数、CPU/内存限制、端口 等)就是 Deployment 的核心字段。 前端提交的通常是 JSON 格式的数据,例如:
{
"name": "myapp",
"namespace": "default",
"replicas": 3,
"image": "nginx:1.21",
"cpu": "200m",
"memory": "256Mi",
"port": 80
}
2️⃣ 后端 → 转换为 K8s YAML/Manifest #
后端拿到这个 JSON,就会用模板(或者动态拼接)生成 Deployment 的 YAML 清单:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: nginx:1.21
resources:
limits:
cpu: "200m"
memory: "256Mi"
ports:
- containerPort: 80
⚡ 这里后端可能会用模板引擎(Go Template、Jinja2、Handlebars.js 等)来把表单字段替换进 YAML。
3️⃣ 后端 → 部署到 K8s 集群 #
后端有几种方式把 YAML 部署到 K8s:
方式 A:调用 kubectl apply
#
后端服务器上安装
kubectl
,把 YAML 写到临时文件,再执行:
kubectl apply -f deployment.yaml
方式 B:直接调用 Kubernetes API #
Kubernetes 提供了 RESTful API(
/apis/apps/v1/namespaces/{namespace}/deployments
)。后端可以把 YAML 转 JSON,然后调用 API。
例如 POST 请求:
POST /apis/apps/v1/namespaces/default/deployments Content-Type: application/json Authorization: Bearer <k8s-token>
方式 C:用官方 SDK #
不同语言都有 Kubernetes SDK:
- Go:
client-go
- Python:
kubernetes
- JavaScript/Node.js:
@kubernetes/client-node
这些 SDK 可以直接用对象方式定义 Deployment,再调用 createNamespacedDeployment()
方法。
4️⃣ 整体流程总结 #
flowchart LR
A[前端表单填写参数] --> B[提交 JSON 到后端]
B --> C[后端生成 YAML/JSON Manifest]
C --> D{部署到K8s?}
D -->|kubectl apply| E[K8s API Server]
D -->|REST API| E
D -->|SDK 调用| E
E --> F[etcd 存储资源对象]
F --> G[Scheduler 调度 Pod]
G --> H[Kubelet 在节点上拉取镜像并运行容器]
✅ 一句话总结:
前端表单就是把 Deployment 的字段参数化,后端把这些参数渲染成 K8s YAML/JSON,然后通过 kubectl
或 API 提交给 K8s API Server,由 K8s 完成调度和容器创建。
要不要我帮你写一个 Node.js 后端示例,从表单 JSON 自动生成 Deployment 并调用 Kubernetes API 创建?
根据源码,sealos前端表单到后端 YAML 及部署流程主要分为两步:
1. 前端表单转 deployment 的 YAML #
- 前端表单数据会被专门的函数(如
json2DeployCr
)转换为 Kubernetes 的 YAML 格式。 - 以
frontend/providers/applaunchpad/src/utils/deployYaml2Json.ts
为例,核心函数如下:
export const json2DeployCr = (data: AppEditType, type: 'deployment' | 'statefulset') => {
// ... 省略部分代码
// 构建 metadata、spec 等
const metadata = { name: data.appName, ... };
const commonSpec = { ... };
// 最终返回 deployment/statefulset 对象
// 转为 YAML 字符串使用 yaml.dump
return yaml.dump({
apiVersion: 'apps/v1',
kind: type === 'deployment' ? 'Deployment' : 'StatefulSet',
metadata,
spec: commonSpec
});
};
在页面里,通常会把表单数据收集后,调用如上方法或类似的 generateYamlList
方法,将数据转为 YAML:
[
{
filename: 'deployment.yaml',
value: json2DeployCr(data, 'deployment')
},
// 其它资源(service、configmap等)
]
2. YAML 被部署到 K8s 集群 #
- 前端生成 YAML 后,调用后端接口(如
applyYamlList
),后端会用 K8s 客户端 SDK 进行部署。 - 以
frontend/providers/applaunchpad/src/services/backend/kubernetes.ts
为例:
export async function getK8s({ kubeconfig }: { kubeconfig: string }) {
// ... 省略部分代码
const formatYaml: k8s.KubernetesObject[] = yamlList
.map((item) => yaml.loadAll(item))
.flat()
.map((item: any) => {
if (item.metadata) {
item.metadata.namespace = namespace;
}
return item;
});
if (type === 'create') {
return CreateYaml(kc, formatYaml);
} else if (type === 'replace') {
return replaceYaml(kc, formatYaml);
}
return CreateYaml(kc, formatYaml);
};
CreateYaml
和replaceYaml
等方法会调用 K8s API,把 YAML 应用到集群。
关键流程梳理 #
- 表单数据收集 → 通过如
json2DeployCr
等方法转为 YAML 字符串。 - YAML 列表生成 → 组织成如
[ { filename: 'deployment.yaml', value: <yaml字符串> } ]
- 前端调用后端接口(如
applyYamlList
)→ 后端解析 YAML 并用 K8s SDK apply 到集群。
相关关键代码汇总 #
- YAML 生成:
frontend/providers/applaunchpad/src/utils/deployYaml2Json.ts
(json2DeployCr
) - YAML 应用:
frontend/providers/applaunchpad/src/services/backend/kubernetes.ts
(CreateYaml
,replaceYaml
) - 表单到 YAML 调用链:
frontend/providers/applaunchpad/src/pages/app/edit/index.tsx
、frontend/providers/applaunchpad/src/services/backend/appService.ts
如需具体某一部分的完整函数/实现可进一步指定。
好的,我来帮你梳理一下这段 EditApp
组件的逻辑,以及前端表单到 YAML,再到调用后端 API 部署 Kubernetes 的整个链路。我会分步骤解释并用一个调用链的方式帮你理清思路。
1️⃣ 核心功能概览 #
EditApp
是一个 应用部署编辑页面,功能包括:
- 前端表单填写应用参数(镜像、端口、CPU/内存、存储、GPU 等)
- 实时生成对应的 Kubernetes YAML(Deployment、StatefulSet、Service、Ingress、HPA、ConfigMap、Secret)
- 支持“表单模式”和“YAML模式”编辑
- 校验资源配额、GPU、端口冲突
- 调用后端接口部署或更新应用
- 部署成功或失败反馈给用户
2️⃣ 前端表单 -> YAML 的转换 #
核心函数是 formData2Yamls
:
export const formData2Yamls = (data: AppEditType) => [
{ filename: 'service.yaml', value: json2Service(data) },
{ filename: 'deployment.yaml' or 'statefulset.yaml', value: json2DeployCr(data) },
...(data.configMapList.length > 0 ? [{ filename: 'configmap.yaml', value: json2ConfigMap(data) }] : []),
...(data.networks.some(item => item.openPublicDomain) ? [{ filename: 'ingress.yaml', value: json2Ingress(data) }] : []),
...(data.hpa.use ? [{ filename: 'hpa.yaml', value: json2HPA(data) }] : []),
...(data.secret.use ? [{ filename: 'secret.yaml', value: json2Secret(data) }] : [])
];
🔹 作用:将用户在表单中填写的数据,转换成 Kubernetes 可以理解的 YAML 对象。
json2Service
→ 生成 Service YAMLjson2DeployCr
→ Deployment / StatefulSet YAMLjson2Ingress
→ Ingress YAML(如果开启公网域名)json2HPA
→ HPA YAML(如果开启弹性伸缩)json2ConfigMap
/json2Secret
→ 对应资源
3️⃣ 用户点击“应用部署”按钮的流程 #
在 Header
组件中,有一个回调 applyCb
:
applyCb={() => {
formHook.handleSubmit(async (data) => {
const parseYamls = formData2Yamls(data);
setYamlList(parseYamls);
// GPU库存校验
if (data.gpu?.type) {
const inventory = countGpuInventory(data.gpu?.type);
if (data.gpu?.amount > inventory) return toast(...);
}
// 网络端口冲突校验
if (!checkNetworkPorts(data.networks)) return toast(...);
// 权限检查(编辑已有应用)
if (appName) await checkPermission(...);
// 弹出确认框
openConfirm(() => submitSuccess(parseYamls))();
}, submitError)();
}}
步骤解释:
handleSubmit
获取表单数据data
- 调用
formData2Yamls(data)
生成 YAML 列表 - 检查 GPU 配额
- 检查网络端口冲突
- 权限检查
- 弹出确认框
openConfirm
- 确认后调用
submitSuccess(parseYamls)
4️⃣ submitSuccess
-> 调用后端 API
#
const submitSuccess = useCallback(async (yamlList) => {
setIsLoading(true);
const parsedNewYamlList = yamlList.map(item => item.value);
if (appName) {
const patch = patchYamlList({ parsedOldYamlList: formOldYamls.current.map(i => i.value), parsedNewYamlList, originalYamlList: crOldYamls.current });
await putApp({ patch, appName, stateFulSetYaml: yamlList.find(i => i.filename === 'statefulset.yaml')?.value });
} else {
await postDeployApp(parsedNewYamlList);
}
router.replace(`/app/detail?name=${formHook.getValues('appName')}`);
toast({ title: t(applySuccess), status: 'success' });
}, [...])
🔹 作用:把 YAML 列表发送给后端接口:
postDeployApp(parsedNewYamlList)
→ 新建应用putApp({...})
→ 编辑已有应用(patch 差异化更新)
后端接收到 YAML 后,会调用 K8s API Server 部署资源(对应你之前贴的 K8sApi
+ CreateYaml/replaceYaml
逻辑)。
5️⃣ 调用链总结(表单到 YAML 到部署) #
用文字描述调用链:
前端用户填表单
│
▼
formHook.handleSubmit
│
▼
formData2Yamls() → YAML 列表
│
▼
校验 GPU / 网络端口 / 权限
│
▼
openConfirm() 确认
│
▼
submitSuccess(yamlList)
│
▼
postDeployApp / putApp (调用后端 API)
│
▼
后端接收 YAML
│
▼
调用 K8sApi + CreateYaml/replaceYaml
│
▼
K8s API Server
│
▼
Pod / Deployment / Service 等资源创建完成
│
▼
返回状态 → 前端 toast 提示成功
如果你需要,我可以帮你画一个 Mermaid 时序图,把这个表单到 YAML 再到 K8s API Server 的完整调用链可视化出来,看起来更直观。
你想让我画吗?
好的,我帮你画一个 Mermaid 时序图,把 前端表单 → YAML → 后端 API → K8s API Server → Pod/Service 的完整调用链直观表现出来:
sequenceDiagram
participant User as 用户
participant Frontend as 前端页面(Form / EditApp)
participant Backend as 后端 API(postDeployApp / putApp)
participant K8sApi as K8s API 层(K8sApi + CreateYaml/replaceYaml)
participant K8sServer as K8s API Server
User->>Frontend: 填写表单(镜像、CPU、内存、端口、存储等)
Frontend->>Frontend: formHook.handleSubmit()
Frontend->>Frontend: formData2Yamls() 生成 YAML 列表
Frontend->>Frontend: 校验 GPU / 网络端口 / 权限
Frontend->>User: 弹出确认框 openConfirm()
User->>Frontend: 点击确认
Frontend->>Frontend: submitSuccess(yamlList)
Frontend->>Backend: postDeployApp / putApp(yamlList)
Backend->>K8sApi: 解析 YAML 调用 CreateYaml / replaceYaml
K8sApi->>K8sServer: 调用 K8s API Server 创建 Deployment/Service/Ingress/ConfigMap/Secret 等
K8sServer-->>K8sApi: 返回资源创建结果
K8sApi-->>Backend: 返回部署结果
Backend-->>Frontend: 返回成功/失败状态
Frontend->>User: toast 提示部署成功或失败
✅ 说明:
- 前端负责收集表单数据、生成 YAML、校验资源和权限
- 后端负责接收 YAML、调用 K8s API 部署
- K8sApi 层封装了
KubernetesObjectApi
的操作(create/replace) - 最终 Kubernetes API Server 创建 Pod、Deployment、Service 等资源
我可以再帮你画一个 带 HPA、StatefulSet、Ingress 等资源细分的时序图,更详细地表现 YAML 对应不同资源的部署流程。
你希望我画这个更详细版本吗?
好,我们把前端表单提交到 YAML、再到不同 Kubernetes 资源的完整流程画出来,包括 Deployment/StatefulSet、Service、Ingress、ConfigMap、Secret、HPA 等。
sequenceDiagram
participant User as 用户
participant Frontend as 前端页面(Form / EditApp)
participant Backend as 后端 API(postDeployApp / putApp)
participant K8sApi as K8s API 层(CreateYaml / replaceYaml)
participant K8sServer as K8s API Server
participant Pod as Pod / StatefulSet
participant HPA as HPA Controller
participant Ingress as Ingress Controller
User->>Frontend: 填写表单(镜像、CPU、内存、端口、存储等)
Frontend->>Frontend: formHook.handleSubmit()
Frontend->>Frontend: formData2Yamls() 生成 YAML 列表
Frontend->>Frontend: 校验 GPU / 网络端口 / 权限
Frontend->>User: 弹出确认框 openConfirm()
User->>Frontend: 点击确认
Frontend->>Frontend: submitSuccess(yamlList)
Frontend->>Backend: postDeployApp / putApp(yamlList)
Backend->>K8sApi: 解析 YAML,按资源类型调用 CreateYaml / replaceYaml
alt Service YAML
K8sApi->>K8sServer: 创建 Service
K8sServer-->>K8sApi: 返回 Service 状态
end
alt Deployment / StatefulSet YAML
K8sApi->>K8sServer: 创建 Deployment / StatefulSet
K8sServer-->>Pod: 调度 Pod
Pod-->>K8sServer: Pod 就绪
K8sServer-->>K8sApi: 返回 Deployment/StatefulSet 状态
end
alt ConfigMap YAML
K8sApi->>K8sServer: 创建 ConfigMap
K8sServer-->>K8sApi: 返回状态
end
alt Secret YAML
K8sApi->>K8sServer: 创建 Secret
K8sServer-->>K8sApi: 返回状态
end
alt Ingress YAML
K8sApi->>K8sServer: 创建 Ingress
K8sServer-->>Ingress: 配置负载均衡 / 域名路由
Ingress-->>K8sServer: 状态更新
K8sServer-->>K8sApi: 返回状态
end
alt HPA YAML
K8sApi->>K8sServer: 创建 HPA
K8sServer-->>HPA: HPA 监控 Deployment / StatefulSet
HPA-->>Pod: 调整副本数
HPA-->>K8sServer: 返回状态
K8sServer-->>K8sApi: 返回 HPA 状态
end
K8sApi-->>Backend: 返回部署结果
Backend-->>Frontend: 返回成功/失败状态
Frontend->>User: toast 提示部署成功或失败
✅ 特点说明:
- 前端生成 YAML 时会根据表单决定资源类型(Deployment / StatefulSet / Service / Ingress / ConfigMap / Secret / HPA)
- 后端只负责把 YAML 调用 K8sApi 层部署
- K8sApi把每个 YAML 转化成 Kubernetes API 调用
- Kubernetes Server负责调度 Pod、更新 HPA、Ingress Controller 配置等
如果你需要,我可以帮你再画一个 交互流程+资源依赖图,显示哪个 YAML 依赖哪个资源(比如 Deployment 依赖 ConfigMap/Secret,Ingress 依赖 Service),更像 部署拓扑图。
你希望我画这个吗?
好的,我来帮你梳理这段代码的逻辑,重点是表单提交 → YAML 生成 → Kubernetes 资源创建/操作的调用链。为了方便理解,我会按流程和模块拆解。
1️⃣ K8sContext 接口 #
export interface K8sContext {
kc: KubeConfig; // kubeconfig
apiClient: KubernetesObjectApi;
k8sCore: CoreV1Api;
k8sApp: AppsV1Api;
k8sAutoscaling: AutoscalingV2Api;
k8sNetworkingApp: NetworkingV1Api;
k8sCustomObjects: CustomObjectsApi;
metricsClient: Metrics;
k8sExec: Exec;
kube_user: User | null;
namespace: string;
applyYamlList: (yamlList: string[], type: 'create' | 'replace') => Promise<KubernetesObject[]>;
getDeployApp: (appName: string) => Promise<V1Deployment | V1StatefulSet>;
getUserQuota: () => Promise<UserQuotaItemType[]>;
getUserBalance: () => Promise<number>;
}
- 这是整个 Kubernetes 操作上下文对象,封装了对各种 API 的客户端(Core、Apps、Autoscaling、Networking、CustomObjects)。
applyYamlList
:核心方法,将 YAML 列表应用到集群,可选择create
或replace
。getDeployApp
:获取 Deployment 或 StatefulSet,用于 pause/start/update 操作。
2️⃣ 表单 → YAML → 创建应用 #
export async function createApp(appForm: AppEditType, k8s: K8sContext) {
serverLoadInitData(); // 初始化前端数据
const { applyYamlList } = k8s;
// 给网络配置加上域名
appForm.networks = appForm.networks.map((network: any) => ({
...network,
domain: global.AppConfig.cloud.domain
}));
// 核心:表单数据转 YAML
const parseYamls = formData2Yamls(appForm);
const yamls = parseYamls.map((item) => item.value);
// 调用 applyYamlList 创建所有资源
await applyYamlList(yamls, 'create');
}
调用链:
- 用户在前端表单填入应用配置(镜像、CPU、内存、端口、存储、网络等)
formData2Yamls(appForm)
将表单数据转换为 Kubernetes YAML 列表,可能包含:- Deployment / StatefulSet
- Service
- Ingress
- ConfigMap
- Secret
- HPA
applyYamlList(yamls, 'create')
将 YAML 应用到 Kubernetes 集群- 内部通过
KubernetesObjectApi
调用create
或replace
- 生成对应的 Kubernetes 对象
- 内部通过
所以 表单 → formData2Yamls → YAML 列表 → applyYamlList → Kubernetes API → 集群对象 是创建应用的核心链路。
3️⃣ 获取应用资源信息 #
export async function getAppByName(appName: string, k8s: K8sContext) {
const { k8sApp, k8sCore, k8sNetworkingApp, k8sAutoscaling, namespace } = k8s;
const response = await Promise.allSettled([
k8sApp.readNamespacedDeployment(appName, namespace),
k8sApp.readNamespacedStatefulSet(appName, namespace),
k8sCore.readNamespacedConfigMap(appName, namespace),
k8sCore.listNamespacedService(namespace, undefined, undefined, undefined, undefined, `${appDeployKey}=${appName}`),
k8sNetworkingApp.listNamespacedIngress(namespace, undefined, undefined, undefined, undefined, `${appDeployKey}=${appName}`),
k8sCore.readNamespacedSecret(appName, namespace),
k8sAutoscaling.readNamespacedHorizontalPodAutoscaler(appName, namespace)
]);
return response;
}
- 并行获取一个应用相关的全部资源(Deployment、StatefulSet、ConfigMap、Service、Ingress、Secret、HPA)。
Promise.allSettled
确保即便某些资源不存在也不会抛出异常。- 最终返回一个结果列表,用于前端展示或进一步处理。
4️⃣ Pause / Start 应用 #
- pauseApp:
- 将
replicas=0
暂停应用 - 保存 HPA 配置到 annotation(
pauseKey
) - 修改 Ingress 的
ingress.class
为pause
- 删除 HPA
- 将
- startApp:
- 恢复副本数
- 根据
pauseKey
annotation 重新创建 HPA - 修改 Ingress 恢复
ingress.class
- 删除
pauseKey
annotation
核心逻辑:应用的暂停/启动通过修改 Deployment/StatefulSet 的 replicas
和 HPA,同时调整 Ingress 配置来实现。
5️⃣ 更新应用资源 #
export async function updateAppResources(appName: string, updateData, k8s: K8sContext)
- 更新 CPU、内存、镜像、命令、环境变量、replicas
- 如果
replicas=0
→ pause 逻辑 - 如果
replicas>0
→ start 逻辑 + 恢复 HPA - 通过 JSON Patch 精确修改 Deployment/StatefulSet 资源
流程:
- 获取当前 Deployment/StatefulSet (
getDeployApp
) - 计算 JSONPatch(CPU/Memory/Command/Args/Image/Env)
- 调用
patchNamespacedDeployment
/patchNamespacedStatefulSet
应用修改 - 如果涉及 replicas,则结合 pause/start 逻辑操作 HPA
6️⃣ 删除应用 #
export async function deleteAppByName(name: string, k8s: K8sContext)
- 删除应用相关的所有资源:
- Deployment / StatefulSet
- Service / ConfigMap / Secret
- Ingress
- PersistentVolumeClaim
- HorizontalPodAutoscaler
- cert-manager 的 Certificate / Issuer
- 使用
Promise.allSettled
并过滤 404 错误,保证删除流程健壮。
7️⃣ 总结表单到 YAML 调用链 #
- Pause/Start/Update 操作是基于 Deployment/StatefulSet 和 HPA 的 annotation + JSON Patch 机制
- 删除应用是把所有相关资源全部清理
getAppByName
用于把集群状态同步回前端,用于展示和编辑
如果你想,我可以帮你画一张更完整的 表单字段 → YAML 资源类型 → API 调用 → 集群对象 的图,把每种资源的依赖关系和 pause/start HPA 逻辑都展示出来,看起来像一个完整的应用部署拓扑。
你希望我画吗?
好,我们可以把整个 表单 → YAML → 集群资源 的流程画成一张完整的拓扑图,包括 Pause/Start/HPA 逻辑。
下面是用 Mermaid 表示的图:
flowchart TD
A["前端表单"] --> B["调用 formData2Yamls"]
B --> C["生成 YAML 列表"]
C --> D["调用 applyYamlList 创建或替换资源"]
D --> E["Kubernetes API Server"]
E --> F["创建 Deployment / StatefulSet"]
E --> G["创建 Service / ConfigMap / Secret"]
E --> H["创建 Ingress"]
E --> I["创建 HorizontalPodAutoscaler"]
subgraph Pause_Start["暂停/启动流程"]
J["暂停应用: replicas=0, 保存 HPA 配置"] --> K["删除 HPA"]
L["启动应用: 恢复 replicas, 重新创建 HPA"]
end
F --> Pause_Start
I --> Pause_Start
subgraph Delete_App["删除应用流程"]
M["删除 Deployment / StatefulSet"]
N["删除 Service / ConfigMap / Secret / PVC"]
O["删除 Ingress"]
P["删除 HPA"]
end
F --> Delete_App
G --> Delete_App
H --> Delete_App
I --> Delete_App
✅ 解释图中各部分 #
- 表单 → YAML → 集群
- 前端表单
AppEditType
→formData2Yamls
→ YAML 列表 →applyYamlList
→ Kubernetes API → 集群对象。
- 前端表单
- Pause/Start
- Pause:replicas 置 0 + HPA 保存到 annotation + 删除 HPA + Ingress 修改为
pause
- Start:replicas 恢复 + 根据 pauseKey annotation 重建 HPA + Ingress 恢复
- Pause:replicas 置 0 + HPA 保存到 annotation + 删除 HPA + Ingress 修改为
- 资源更新
- 通过 JSON Patch 精确更新 Deployment/StatefulSet 中容器的 CPU/Memory/Image/Command/Args/Env
- 如果涉及 replicas,则走 Pause/Start 逻辑
- 删除应用
- 删除全部相关资源,包括 Deployment/StatefulSet、Service、Ingress、ConfigMap、Secret、PVC、HPA、Certificate、Issuer
- 获取应用状态
getAppByName
获取集群资源 →adaptAppDetail
+transformFromLegacySchema
→ 前端标准化对象用于展示/编辑
如果你想,我可以帮你画一个 更细粒度的图,标出每种表单字段对应生成的 Kubernetes YAML 资源和字段路径,这样能直观看到表单字段到 Deployment/Service/HPA 的映射关系。
你希望我画这个更细粒度的图吗?
明白了,你希望把 前端表单字段 → YAML → Kubernetes 资源 → 字段路径 画成一个清晰的 Mermaid 流程图。我们可以按以下思路细化:
- 每个表单字段对应的 YAML 片段
- 每个 YAML 对应的 Kubernetes 资源类型
- 关键字段路径(如
spec.template.spec.containers[0].resources
)
我给你画一个示意 Mermaid 图:
flowchart TD
subgraph Form["前端表单"]
CPU["CPU"]
Memory["Memory"]
Replicas["副本数"]
Image["镜像"]
Command["启动命令"]
Args["命令参数"]
Env["环境变量"]
Network["网络配置"]
end
subgraph formData2Yamls["formData2Yamls(appForm)"]
CPU_YAML["resources.requests/limits.cpu"]
Memory_YAML["resources.requests/limits.memory"]
Replicas_YAML["spec.replicas"]
Image_YAML["spec.template.spec.containers[0].image"]
Command_YAML["spec.template.spec.containers[0].command"]
Args_YAML["spec.template.spec.containers[0].args"]
Env_YAML["spec.template.spec.containers[0].env"]
Network_YAML["Service/Ingress domain annotations"]
end
subgraph ApplyYAML["applyYamlList -> Kubernetes API"]
Deployment["Deployment / StatefulSet"]
Service["Service / ConfigMap / Secret"]
Ingress["Ingress"]
HPA["HorizontalPodAutoscaler"]
end
%% 表单字段到 YAML 映射
CPU --> CPU_YAML
Memory --> Memory_YAML
Replicas --> Replicas_YAML
Image --> Image_YAML
Command --> Command_YAML
Args --> Args_YAML
Env --> Env_YAML
Network --> Network_YAML
%% YAML 到 Kubernetes 资源映射
CPU_YAML --> Deployment
Memory_YAML --> Deployment
Replicas_YAML --> Deployment
Image_YAML --> Deployment
Command_YAML --> Deployment
Args_YAML --> Deployment
Env_YAML --> Deployment
Replicas_YAML --> HPA
CPU_YAML --> HPA
Memory_YAML --> HPA
Network_YAML --> Service
Network_YAML --> Ingress
💡 说明:
- 表单字段:前端 AppEditType 的字段
- YAML 片段:
formData2Yamls
生成的 YAML 对应字段路径 - Kubernetes 资源:最终创建的 Deployment、Service、Ingress、HPA
这个图能直观看到 字段 → YAML → K8s 资源 → 字段路径 的对应关系。
我可以帮你画 更详细版本,把每个字段对应的 完整 YAML 路径 都列出来,包括 HPA 的 min/max replicas、target CPU、Service 的 selector 等,这样就像一张完整映射表一样。
你希望我画这个完整详细版本吗?
好的,我帮你画一个完整、细粒度版本,把表单字段对应到具体 Kubernetes YAML 路径和资源类型,涵盖 Deployment、StatefulSet、Service、Ingress、HPA。下面是 Mermaid 流程图示例:
flowchart TD
%% 前端表单字段
subgraph Form["前端表单"]
CPU["CPU (resource.cpu)"]
Memory["内存 (resource.memory)"]
Replicas["副本数 (resource.replicas)"]
Image["镜像 (image)"]
Command["启动命令 (command)"]
Args["命令参数 (args)"]
Env["环境变量 (env)"]
NetworkDomain["网络域名 (networks.domain)"]
NetworkPort["网络端口 (networks.port)"]
end
%% formData2Yamls 生成 YAML 映射
subgraph YAML["formData2Yamls(appForm)生成 YAML"]
CPU_YAML["Deployment.spec.template.spec.containers[0].resources.requests/limits.cpu"]
Memory_YAML["Deployment.spec.template.spec.containers[0].resources.requests/limits.memory"]
Replicas_YAML["Deployment.spec.replicas"]
Image_YAML["Deployment.spec.template.spec.containers[0].image"]
Command_YAML["Deployment.spec.template.spec.containers[0].command"]
Args_YAML["Deployment.spec.template.spec.containers[0].args"]
Env_YAML["Deployment.spec.template.spec.containers[0].env"]
ServiceSelector["Service.spec.selector.app"]
ServicePort["Service.spec.ports"]
IngressHost["Ingress.spec.rules.host"]
IngressClass["Ingress.spec.ingressClassName / annotations"]
HPA_MinReplicas["HPA.spec.minReplicas"]
HPA_MaxReplicas["HPA.spec.maxReplicas"]
HPA_TargetCPU["HPA.spec.metrics[0].resource.target.averageUtilization"]
end
%% YAML 到 Kubernetes 资源映射
subgraph K8s["Kubernetes 资源"]
Deployment["Deployment / StatefulSet"]
Service["Service / ConfigMap / Secret"]
Ingress["Ingress"]
HPA["HorizontalPodAutoscaler"]
end
%% 表单字段到 YAML 映射
CPU --> CPU_YAML
Memory --> Memory_YAML
Replicas --> Replicas_YAML
Image --> Image_YAML
Command --> Command_YAML
Args --> Args_YAML
Env --> Env_YAML
NetworkDomain --> IngressHost
NetworkDomain --> ServiceSelector
NetworkPort --> ServicePort
%% YAML 到资源映射
CPU_YAML --> Deployment
Memory_YAML --> Deployment
Replicas_YAML --> Deployment
Image_YAML --> Deployment
Command_YAML --> Deployment
Args_YAML --> Deployment
Env_YAML --> Deployment
ServiceSelector --> Service
ServicePort --> Service
IngressHost --> Ingress
IngressClass --> Ingress
%% HPA 映射
Replicas --> HPA_MinReplicas
Replicas --> HPA_MaxReplicas
CPU --> HPA_TargetCPU
Memory --> HPA_TargetCPU
HPA_MinReplicas --> HPA
HPA_MaxReplicas --> HPA
HPA_TargetCPU --> HPA
🔹 特点 #
- 表单字段:左侧显示前端 AppEditType 字段
- 生成的 YAML:中间显示 formData2Yamls 生成的对应字段路径
- Kubernetes 资源:右侧显示 Deployment / StatefulSet / Service / Ingress / HPA
- HPA 关联:replicas、CPU、memory 会映射到 HPA 的 min/max replicas 和 target utilization
如果你愿意,我可以帮你再画一个 加上每个 YAML 字段生成逻辑的“注释版”图,比如:CPU → requests: cpu = floor(cpu*0.1)m, limits: cpu = cpu m
,这样就能完整看到 表单 → 数值处理 → YAML → K8s 的整个链路。
你希望我画这个注释版吗?
太好了,你把完整代码贴出来了 🙌。这个文件就是你之前问的“前端表单怎么变成后端 deployment 的 YAML”的关键逻辑。 我给你分块解释一下,让你能一眼看清楚 从前端 JSON → Kubernetes YAML 清单 的全过程。
🔑 整体思路 #
- 前端表单数据(
AppEditType
)通过 API 提交到后端。 - 后端用这些数据生成对应的 K8s YAML/Manifest:Deployment、Service、Ingress、ConfigMap、Secret、HPA 等。
- YAML 最终被提交给 Kubernetes API Server,部署应用。
📌 核心函数解析 #
1. json2DeployCr
#
作用:把表单数据转成 Deployment 或 StatefulSet 的 YAML。
流程:
- metadata:用应用名、标签、注解描述对象。
- spec.replicas:副本数(从表单里的
hpa.minReplicas
或replicas
拿)。 - containers:容器配置,包括镜像、命令、环境变量、CPU/内存/GPU 资源、端口。
- volumes/volumeMounts:配置存储卷(PVC/ConfigMap)。
- gpuMap:如果有 GPU,给 Pod 指定
nodeSelector
和runtimeClassName
。 - StatefulSet 特殊逻辑:生成
volumeClaimTemplates
,挂载数据卷。
输出:一个 Deployment 或 StatefulSet 的 YAML 字符串。
2. json2Service
#
作用:根据表单里网络配置,生成 Service YAML。
流程:
- 遍历
data.networks
:区分 NodePort 和 ClusterIP。 - 给每个端口生成对应的
Service
配置。 - 如果有 NodePort,就生成一个
type: NodePort
的 Service;否则生成默认的 ClusterIP。
输出:一个或多个 Service YAML(用 ---
分隔)。
3. json2Ingress
#
作用:生成 Ingress YAML,处理域名和 TLS。
流程:
- 遍历
data.networks
,找出需要对外暴露的服务(openPublicDomain
= true)。 - 生成 Ingress 配置(
rules
、tls
、nginx annotations)。 - 如果是自定义域名,还会额外生成 Issuer 和 Certificate(由 cert-manager 管理)。
输出:Ingress + TLS 证书的 YAML。
4. json2ConfigMap
#
作用:生成 ConfigMap YAML,把用户输入的配置文件/环境写进去。
5. json2Secret
#
作用:生成 Secret YAML,主要用于存储镜像仓库认证信息(dockerconfigjson
)。
6. json2HPA
#
作用:生成 HPA (HorizontalPodAutoscaler) YAML。
- 根据表单里的
hpa.target
(cpu/memory/gpu)生成对应的指标配置。 - 配置
minReplicas
、maxReplicas
、伸缩策略。
7. yamlString2Objects
#
辅助方法:把 YAML 字符串分割成多个对象,便于后续处理。
📊 整体流程图 #
flowchart TD
A[前端表单 AppEditType JSON] --> B[后端函数 json2DeployCr/json2Service/json2Ingress...]
B --> C[生成 YAML 字符串]
C --> D[提交到 K8s API Server]
D --> E[etcd 存储对象]
E --> F[Scheduler 调度 Pod]
F --> G[Kubelet 拉取镜像并运行容器]
✅ 总结一句话 #
这份代码就是一个 “表单数据 → Kubernetes YAML 工厂”:
- 把前端用户填写的参数(镜像、副本数、端口、存储、域名、环境变量、HPA …)
- 转换成标准的 Deployment / StatefulSet / Service / Ingress / ConfigMap / Secret / HPA YAML
- 然后再由后端去调用 Kubernetes API 部署到集群。
要不要我帮你画一个 表单字段 → YAML 字段映射表,让你快速查到「前端填的某个参数最后出现在 YAML 的哪一行」?
非常好的问题 👍 你前面贴的代码(前端表单转 YAML)是 生成 YAML 清单,而这一段代码就是 把 YAML 真正部署到 Kubernetes 集群 的逻辑。 我来帮你逐步拆解:
1. Kubernetes 客户端初始化 #
import * as k8s from '@kubernetes/client-node';
这里用的是 官方 Node.js Kubernetes Client,用来连接并操作 K8s 集群。
export function K8sApiDefault(): k8s.KubeConfig {
const kc = new k8s.KubeConfig();
kc.loadFromDefault(); // 默认读取 ~/.kube/config
return kc;
}
如果是本地调试,就直接加载 ~/.kube/config
里的 kubeconfig 文件。
2. 判断是否在集群内部运行 #
export function CheckIsInCluster(): [boolean, string] {
if (process.env.KUBERNETES_SERVICE_HOST && process.env.KUBERNETES_SERVICE_PORT) {
return [true, `https://${process.env.KUBERNETES_SERVICE_HOST}:${process.env.KUBERNETES_SERVICE_PORT}`];
}
return [false, ''];
}
如果代码运行在 K8s Pod 内部,Kubernetes 会注入 KUBERNETES_SERVICE_HOST
和 KUBERNETES_SERVICE_PORT
环境变量。
这样可以直接连 集群内的 API Server,而不用 kubeconfig 文件。
3. 加载 kubeconfig #
export function K8sApi(config: string): k8s.KubeConfig {
const kc = new k8s.KubeConfig();
kc.loadFromString(config);
...
return kc;
}
这里会优先用传入的 kubeconfig 字符串,并且如果代码运行在集群内部,会把 server 地址改为集群内的 API 地址。
4. 创建 YAML 到 K8s #
export async function CreateYaml(
kc: k8s.KubeConfig,
specs: k8s.KubernetesObject[]
)
specs
就是前端转出来的 YAML 解析成的 JSON 对象(Deployment, Service, Ingress 等等)。- 它用
KubernetesObjectApi
来client.create(spec)
。 - 创建成功的对象会 push 到
created
数组里。 - 如果中途失败,会回滚:把之前成功创建的对象都删除掉。
👉 这就是 把 YAML apply 到集群。
5. 更新/替换 YAML 到 K8s #
export async function replaceYaml(kc, specs)
逻辑:
- 先用
client.read(spec)
看资源是否存在。 - 如果存在,就
client.replace(spec)
更新(需要带上resourceVersion
才能替换)。 - 如果不存在,就
client.create(spec)
新建。
👉 这就是 kubectl apply 的效果。
6. 获取用户配额 #
export async function getUserQuota(kc, namespace)
调用 CoreV1Api.readNamespacedResourceQuota
,查询命名空间的 ResourceQuota,返回用户的 CPU、内存、存储、NodePort、GPU 使用情况。
相当于 kubectl describe quota
。
7. 获取用户余额 #
export async function getUserBalance(kc)
这里调用的是 Sealos 自定义 CRD account.sealos.io/v1/accounts
,从里面取余额。
说明这个平台在 Kubernetes 上做了 多租户和计费。
8. 封装统一的 K8s 操作入口 #
export async function getK8s({ kubeconfig }: { kubeconfig: string })
这个函数会返回一个对象,里面包含:
applyYamlList
→ 负责部署 YAML(create 或 replace)getDeployApp
→ 获取某个 app 的 Deployment/StatefulSetgetUserQuota
→ 查询用户配额getUserBalance
→ 查询用户余额- 还有一些 client (
k8sCore
,k8sApp
,k8sAutoscaling
,k8sNetworkingApp
等) 用于不同的资源操作。
🔗 前后端流程串起来 #
- 前端表单(用户填 app 名称、镜像、端口、存储等)。
- 前端转 YAML(用你之前贴的
json2DeployCr
、json2Service
等函数 → 生成 Deployment/Service/Ingress YAML 字符串)。 - 后端解析 YAML(用
yaml.loadAll
解析成 JSON 对象)。 - 后端调用 CreateYaml/replaceYaml → 通过 API Server 把对象部署到集群。
- Kubernetes 调度器负责拉镜像、创建 Pod。
总结一句话 #
👉 前端只是 表单转 YAML,
👉 后端这段代码才是 把 YAML apply 到 Kubernetes 集群,实现跟 kubectl apply -f xxx.yaml
一样的功能。
要不要我帮你画一个 前端表单 → YAML → API Server → 集群部署 的 流程图(Mermaid),直观一点?
好的 👍 我给你画一个 前端表单 → YAML → K8s 集群部署 的流程图,用 Mermaid 表示:
flowchart TD
A[用户在前端表单填写参数: 镜像/端口/存储/CPU等] --> B[前端将表单数据转换为 YAML]
B --> C[后端 API 接收 YAML]
C --> D[后端解析 YAML 为 JSON 对象]
D --> E[调用 CreateYaml / replaceYaml 方法]
E --> F[请求发送到 Kubernetes API Server]
F --> G[API Server 校验并存储到 etcd]
G --> H[调度器分配节点]
H --> I[Kubelet 拉取镜像并启动 Pod]
I --> J[应用成功运行在 Kubernetes 集群]
这个图走的流程其实就是:
- 前端:用户输入参数,转 YAML。
- 后端:接收 YAML → 转 JSON → 调用 K8s API。
- API Server:存到 etcd → 调度 → 创建 Pod。
- 最终应用部署成功。
要不要我再给你画一个 时序图(sequence diagram),表现前端、后端、K8s 之间的调用过程?
好嘞 👍 用 Mermaid 的 sequenceDiagram
来画会更直观,表现 前端、后端、K8s API Server 的交互流程:
sequenceDiagram
participant FE as 前端(表单页面)
participant BE as 后端(Node.js服务)
participant K8S as Kubernetes API Server
participant ETCD as etcd
participant Kubelet as 节点Kubelet
FE->>BE: 提交表单数据 (镜像/端口/CPU/存储等)
BE->>BE: 转换为 YAML (Deployment/Service/Ingress...)
BE->>K8S: 调用 CreateYaml/replaceYaml<br>提交资源对象
K8S->>ETCD: 校验并写入资源对象
K8S->>BE: 返回成功(资源已创建)
K8S->>Kubelet: 调度 Pod 到节点
Kubelet->>Kubelet: 拉取镜像,启动容器
Kubelet-->>K8S: 上报 Pod 状态 Running
K8S-->>BE: 应用状态可查询
BE-->>FE: 返回部署成功/状态信息
这样你能清楚看到:
- 前端 只管提交表单;
- 后端 负责转成 YAML 并调用 K8s API;
- API Server 校验+存储到 etcd;
- 调度器 & Kubelet 完成实际的 Pod 创建;
- 最终状态再层层返回到前端。
要不要我再给你加一版 失败场景的时序图(比如 YAML 校验失败 / 资源配额不足)?
KubeSphere 的前端填写 Deployment 表单后,核心流程如下: #
1. 前端表单如何转为 Deployment 的 YAML #
KubeSphere 的前端(如控制台)填写的 Deployment 表单数据,通常会被转换为 Kubernetes Deployment 资源对象的 JSON/YAML。
- 前端会收集表单数据,比如名称、镜像、labels、replicas、容器配置等。
- 这些数据会被组装成标准的 K8s Deployment 资源规范(JSON),如:
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": "example-deployment",
"namespace": "default",
"labels": { ... }
},
"spec": {
"replicas": 3,
"selector": { ... },
"template": { ... }
}
}
在 KubeSphere 的代码例子参考(测试数据):
var ksApiserverDeploy = `
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"labels": {
"app": "ks-apiserver",
"tier": "backend",
},
"name": "ks-apiserver",
"namespace": "kubesphere-system"
},
"spec": {
...
}
}
`
2. 如何被部署到 K8s 集群 #
- 前端会将 YAML/JSON 通过 API 请求发送到 KubeSphere 后端(通常是 RESTful 接口)。
- 后端负责将这些 Deployment 对象 apply 到 Kubernetes 集群。
后端关键实现如下:
2.1 接收并 apply 资源对象 #
后端会解析前端传来的 JSON/YAML,通过 K8s Dynamic Client 进行 apply:
func (t YamlInstaller) ForApply(tasks []json.RawMessage) (err error) {
for idx, js := range tasks {
gvr, utd, err := GetInfoFromBytes(js, t.Mapper)
if err != nil {
return err
}
opt := metav1.PatchOptions{FieldManager: "v1.FieldManager"}
_, err = t.DynamicCli.Resource(gvr).
Namespace(utd.GetNamespace()).
Patch(context.TODO(), utd.GetName(), types.ApplyPatchType, js, opt)
if err != nil {
return err
}
klog.Infof("[%d/%d] %s/%s applied", idx+1, len(tasks), gvr.Resource, utd.GetName())
}
return nil
}
- 前端 JSON 数据通过 API 传到后端,后端调用 K8s API,创建或更新 Deployment 资源。
2.2 典型调用链 #
- 前端表单 -> 组装标准 Deployment JSON
- 前端通过 API 发送到后端(如
/apis/apps/v1/namespaces/{namespace}/deployments
) - 后端用 DynamicClient、RestMapper 解析 JSON 并 apply 到集群
- 资源被成功创建或更新
相关代码参考 #
- 前端表单组装 Deployment 数据(可参考测试数据):
pkg/kapis/cluster/v1alpha1/handler_test.go:ksApiserverDeploy
- 后端应用 YAML/JSON 到 K8s 集群:
pkg/simple/client/application/yaml.go:YamlInstaller.ForApply
如需更详细的前端/后端源码入口或 API 路径,请补充需求!
好的,这段 Go 代码主要是 KubeSphere 里对 Kubernetes 集群配置的测试代码,虽然它本身是测试(_test.go
文件),但我们可以把它拆解来看,尤其聚焦 前端表单如何映射到 Deployment/YAML 资源 的逻辑。
我给你按层次解释:
1️⃣ 核心结构 #
- Cluster 对象
var cluster = &v1alpha1.Cluster{
ObjectMeta: metav1.ObjectMeta{Name: "gondor"},
Spec: v1alpha1.ClusterSpec{
Connection: v1alpha1.Connection{
Type: v1alpha1.ConnectionTypeProxy,
Token: "randomtoken",
},
},
}
- 这里模拟了一个 KubeSphere 集群对象。
- 前端表单如果创建集群,通常会填写:
cluster.name
cluster.connection.type
(直接/代理)cluster.connection.token
这些字段最终映射到 Cluster CRD。
- ConfigMap 数据
var hostMap = map[string]string{
"kubesphere.yaml": `
monitoring:
endpoint: http://prometheus-operated.kubesphere-monitoring-system.svc:9090
authentication:
jwtSecret: ...
oauthOptions:
accessTokenMaxAge: 0s
accessTokenInactivityTimeout: 0s
`,
}
- 模拟了集群的 配置数据。
- 在前端表单中,可能有 监控地址、JWT Secret、OAuth 配置。
- 后端会把这些字段组装成 ConfigMap 并写入
kubesphere-system
命名空间。
- Deployment 模板(JSON)
var ksApiserverDeploy = `{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": "ks-apiserver",
"namespace": "kubesphere-system",
"labels": {...}
},
"spec": {
"replicas": 1,
"template": {
"spec": {
"containers": [{
"name": "ks-apiserver",
"image": "kubesphere/ks-apiserver:v3.0.0",
"command": ["ks-apiserver","--logtostderr=true"]
}]
}
}
}
}`
这里是 KubeSphere Apiserver 的 Deployment 模板。
前端表单对应字段映射:
表单字段 Deployment 字段 镜像 containers[0].image
命令 containers[0].command
副本数 spec.replicas
环境变量/配置 containers[0].env
或 ConfigMap 挂载后端通过 JSON/Struct 解析后再写入 Kubernetes。
2️⃣ 核心方法:addMemberClusterResource
#
func addMemberClusterResource(targetCm *corev1.ConfigMap, t *testing.T) {
// 构造 clientSet
con, _ := clientcmd.NewClientConfigFromBytes(...)
cli, _ := con.ClientConfig()
c, _ := k8s.NewForConfig(cli)
// 创建命名空间
c.CoreV1().Namespaces().Create(...)
// 创建 ConfigMap
c.CoreV1().ConfigMaps(namespace).Create(targetCm)
// 创建 Deployment
deploy := appsv1.Deployment{}
json.Unmarshal([]byte(ksApiserverDeploy), &deploy)
c.AppsV1().Deployments(namespace).Create(&deploy)
}
🔹 做了什么 #
- 读取前端表单生成的 KubeConfig
- 初始化 Kubernetes client
- 创建 命名空间(如果不存在)
- 创建或更新 ConfigMap(前端表单字段:监控、JWT、OAuth)
- 创建 Deployment(前端表单字段:镜像、命令、replicas)
3️⃣ validateMemberClusterConfiguration
#
- 模拟了验证成员集群配置是否有效。
- 流程:
- 先写入 hostCm
- 调用
validateMemberClusterConfiguration
校验 - 再写入 memberCm
- 校验失败(确保检测到重复或错误的配置)
这里可以理解为:前端表单生成的 ConfigMap/YAML 经过后端组装 Deployment 后,最终要验证 集群是否可用、配置是否合理。
4️⃣ 总结:表单字段到 Deployment 映射 #
前端表单字段 | Kubernetes 资源 & YAML 路径 |
---|---|
镜像 | Deployment.spec.template.spec.containers[0].image |
命令 | Deployment.spec.template.spec.containers[0].command |
命令参数 | Deployment.spec.template.spec.containers[0].args |
副本数 | Deployment.spec.replicas |
环境变量/配置 | Deployment.spec.template.spec.containers[0].env / ConfigMap |
JWT Secret / OAuth / Monitoring | ConfigMap.data[“kubesphere.yaml”] |
- 逻辑关系:
- 表单 → 内存对象(Cluster / ConfigMap / Deployment Struct) → Kubernetes API → 真实资源
- 测试意图:
- 验证表单生成 Deployment 是否正确
- 校验成员集群配置是否合理
如果你需要,我可以帮你画一张 “前端表单字段 → YAML → Deployment/ConfigMap 映射图”,把上表可视化成 Mermaid 图,更直观地展示前端如何组装 Deployment 数据。
你希望我画这个图吗?
好的,这段代码实现的是 KubeSphere 后端用来将 YAML/JSON 应用到 Kubernetes 集群的一个 “安装器”,用的是动态客户端(dynamic.DynamicClient
),模仿 Helm 的接口。我们可以逐步解析它的逻辑,尤其是 前端提交的 YAML/JSON → K8s 资源 的过程。
1️⃣ 核心结构 #
type YamlInstaller struct {
Mapper meta.RESTMapper
DynamicCli *dynamic.DynamicClient
GvrListInfo []InsInfo
Namespace string
}
type InsInfo struct {
schema.GroupVersionResource
Name string
Namespace string
}
- Mapper:RESTMapper,用于把 GroupVersionKind(GVK)映射到 GroupVersionResource(GVR)。
- DynamicCli:动态客户端,可以操作任意类型的 Kubernetes 资源(Deployment/Service/ConfigMap/CRD 等)。
- GvrListInfo:记录已经安装的资源信息(用于卸载)。
- Namespace:资源默认命名空间。
总结:这个结构体就是一个 可对任意 YAML/JSON 应用、升级、删除的动态 Helm 安装器。
2️⃣ Install / Upgrade / Uninstall #
Install #
func (t YamlInstaller) Install(...) (string, error) {
return "", nil
}
- 这里暂未实现,实际上可以调用 Upgrade 来实现“安装”的逻辑。
Upgrade #
func (t YamlInstaller) Upgrade(ctx context.Context, release, chart string, values []byte, options ...helm.HelmOption) (string, error) {
yamlList, err := ReadYaml(values)
if err != nil {
return "", err
}
klog.Infof("attempting to apply %d yaml files", len(yamlList))
err = t.ForApply(yamlList)
return "", err
}
- values:前端传来的 YAML/JSON 内容([]byte)。
- ReadYaml:把 YAML/JSON 转成
[]json.RawMessage
(每个对象一个 json.RawMessage)。 - ForApply:核心方法,将每个对象应用到 Kubernetes。
说明:这里 Upgrade 就是“把 YAML/JSON 应用到集群”,前端表单的数据最终通过这个方法落地。
Uninstall #
func (t YamlInstaller) Uninstall(...) (string, error) {
for _, i := range t.GvrListInfo {
err := t.DynamicCli.Resource(i.GroupVersionResource).Namespace(i.Namespace).
Delete(ctx, i.Name, metav1.DeleteOptions{})
if apierrors.IsNotFound(err) {
continue
}
if err != nil {
return "", err
}
}
return "", nil
}
- 根据
GvrListInfo
卸载所有资源。 - 使用 Dynamic Client 的
Delete
方法。
3️⃣ 核心方法:ForApply #
func (t YamlInstaller) ForApply(tasks []json.RawMessage) (err error) {
for idx, js := range tasks {
gvr, utd, err := GetInfoFromBytes(js, t.Mapper)
if err != nil {
return err
}
opt := metav1.PatchOptions{FieldManager: "v1.FieldManager"}
_, err = t.DynamicCli.Resource(gvr).
Namespace(utd.GetNamespace()).
Patch(context.TODO(), utd.GetName(), types.ApplyPatchType, js, opt)
if err != nil {
return err
}
klog.Infof("[%d/%d] %s/%s applied", idx+1, len(tasks), gvr.Resource, utd.GetName())
}
return nil
}
核心步骤: #
- 解析 YAML/JSON → GVR + Unstructured
gvr, utd, err := GetInfoFromBytes(js, t.Mapper)
GetInfoFromBytes
:- 解析每个对象的 apiVersion/kind/name/namespace。
- 返回
GroupVersionResource
(GVR)和Unstructured
对象。
- 前端表单映射:
- Deployment、Service、ConfigMap 等资源的字段都在这里被解析。
- Apply 到集群
t.DynamicCli.Resource(gvr).
Namespace(utd.GetNamespace()).
Patch(context.TODO(), utd.GetName(), types.ApplyPatchType, js, opt)
- 使用 Server-Side Apply(
ApplyPatchType
),类似kubectl apply -f
:- 如果资源不存在 → 创建
- 如果资源存在 → 更新
- FieldManager 用于标记这个 patch 的来源。
- 日志记录
klog.Infof("[%d/%d] %s/%s applied", idx+1, len(tasks), gvr.Resource, utd.GetName())
- 打印应用进度。
4️⃣ 总结逻辑(前端表单到 K8s 资源) #
- 前端表单 → YAML/JSON 数据
- 例如:
- Deployment:镜像、replicas、资源限制
- Service:端口、类型
- ConfigMap/Secret:配置内容
- 例如:
- 后端调用
YamlInstaller.Upgrade
ReadYaml(values)
→ 切成多个json.RawMessage
ForApply
:GetInfoFromBytes
→ 获取 GVR + UnstructuredDynamicClient.Patch(ApplyPatchType)
→ 应用到 Kubernetes
- 资源应用完成,
GvrListInfo
保存,方便卸载
⚡ 核心点:前端表单字段并不直接写 Deployment 对象,而是被序列化成 YAML/JSON,通过 DynamicClient Apply 到集群。 也就是说:前端字段 → YAML → Unstructured → Kubernetes API。
如果你想,我可以帮你画一个 前端表单字段 → JSON/YAML → DynamicClient → Deployment/Service/ConfigMap 的流程图,把整个流程可视化,更直观。
你希望我画这个图吗?
根据 TKE 源码和文档,前端表单到后端 YAML 及部署到 K8s 的流程如下:
1. 前端如何将表单变为 Deployment 的 YAML #
- 前端页面(如工作负载创建页面)收集用户填写的 Deployment 信息(如名称、镜像、标签、副本数等)。
- 前端会将这些表单转换为标准的 Deployment YAML/JSON 对象。
相关配置与转换逻辑参考:
/** deployment的配置 */
export const deployment = (k8sVersion: string) => {
return generateResourceInfo({
k8sVersion,
resourceName: 'deployment',
requestType: {
list: 'deployments'
},
isRelevantToNamespace: true,
displayField,
actionField,
detailField
});
};
前端页面通过配置和表单数据,生成 deployment 的 YAML 内容。
表单提交前通常会用 YAML 解析库进行格式校验:
if (appCreation.spec.values.rawValuesType === 'yaml') {
try {
JsYAML.safeLoad(appCreation.spec.values.rawValues);
this.setState({
yamlValidator: { result: 0, message: '' }
});
} catch (error) {
this.setState({
yamlValidator: { result: 2, message: t('Yaml格式错误') }
});
return;
}
}
2. 如何被部署到 K8s 集群 #
- 前端最终提交 YAML/JSON 资源,会调用 WebAPI(通过 RESTful API)将资源发送到后端。
- 后端接收到 JSON/YAML 后,使用 K8s API 创建或更新资源。
关键 API 代码片段:
export async function updateResourceIns(resource: CreateResource[], regionId: number) {
const { resourceIns, clusterId, resourceInfo, namespace, jsonData, isStrategic = true } = resource[0];
const url = reduceK8sRestfulPath({ resourceInfo, namespace, specificName: resourceIns, clusterId });
const params: RequestParams = {
method: Method.patch,
url,
userDefinedHeader: {
'Content-Type': isStrategic ? 'application/strategic-merge-patch+json' : 'application/merge-patch+json'
},
data: jsonData,
apiParams: {
module: 'tke',
interfaceName: 'ForwardRequest',
regionId,
restParams: {
Method: Method.patch,
Path: url,
}
}
};
// 发起 HTTP 请求(patch 或 post),后端代理给 K8s API Server
}
- 后端会将这些数据代理到 K8s API Server 创建/更新 Deployment 资源。
3. 服务端(Go)侧实际部署代码示例 #
如果涉及业务逻辑触发 K8s 部署,可以参考如下:
func (c *Controller) installDeployment(ctx context.Context, MeshManager *v1.MeshManager, kubeClient kubernetes.Interface) error {
deploy := c.genDeployment(MeshManager)
deploymentClient := kubeClient.AppsV1().Deployments(namespace)
oldDeploy, err := deploymentClient.Get(ctx, deploy.Name, metav1.GetOptions{})
if err != nil {
if k8serrors.IsNotFound(err) {
_, err = deploymentClient.Create(ctx, deploy, metav1.CreateOptions{})
return err
}
return fmt.Errorf("get deployment failed: %v", err)
}
newDeploy := oldDeploy.DeepCopy()
newDeploy.Labels = deploy.Labels
newDeploy.Spec = deploy.Spec
// 保留部分原有属性
if len(oldDeploy.Spec.Template.Spec.Containers) == 1 {
newDeploy.Spec.Template.Spec.Containers[0].Resources = oldDeploy.Spec.Template.Spec.Containers[0].Resources
}
_, err = deploymentClient.Update(ctx, newDeploy, metav1.UpdateOptions{})
return err
}
4. 文档中的典型 YAML 示例 #
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: nginx-deployment
namespace: default
labels:
app: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx-deployment
template:
metadata:
labels:
app: nginx-deployment
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
总结流程 #
- 表单填写(前端收集数据并生成 Deployment YAML/JSON)。
- 前端校验并提交(如 YAML 校验、调用 RESTful API)。
- 后端处理(代理请求到 K8s API Server,创建/更新 Deployment)。
- K8s 集群中完成部署。
如需某一部分的详细源码实现可继续追问。