feat: expose G14 preview via FRP

This commit is contained in:
Codex
2026-05-25 10:45:35 +08:00
parent 2fe40c637a
commit 8e8c7febc3
4 changed files with 122 additions and 5 deletions
+20 -2
View File
@@ -7,8 +7,9 @@ The DEV reverse link is D601 to master edge through frp.
- `hwlab-tunnel-client` owns the frp client health contract.
- `hwlab-cloud-web` owns the public browser entry on port `16666`.
- `hwlab-edge-proxy` owns public API/health ingress on port `16667`.
- `frps.dev.toml` reserves `16666` and `16667` only as TCP `remotePort` values; do not also bind
them as `vhostHTTPPort`, because that collides with the DEV TCP proxy.
- `frps.dev.toml` reserves D601 `16666` / `16667`, G14 `17666` / `17667`, and tunnel health `7402`
as TCP `remotePort` values; do not also bind them as `vhostHTTPPort`, because that collides with
the DEV TCP proxy.
- `deploy/deploy.json` is the source for the public endpoints and FRP proxy
mapping. Run `node scripts/deploy-contract-plan.mjs --check` to detect drift
such as public `6666`/`6667` reuse before any future apply command.
@@ -16,3 +17,20 @@ The DEV reverse link is D601 to master edge through frp.
material out of band before a real deployment.
- UniDesk backend, provider-gateway, and microservice proxy are not HWLAB runtime
substitutes.
## G14 public preview
G14 uses a separate preview port range and must not reuse D601's `16666` / `16667`:
- G14 browser endpoint: `http://74.48.78.17:17666`
- G14 API/edge endpoint: `http://74.48.78.17:17667`
- G14 frpc proxy names: `hwlab-g14-cloud-web` and `hwlab-g14-edge-proxy`
- G14 k3s Deployment: `hwlab-dev/hwlab-g14-frpc`, generated by `scripts/g14-gitops-render.mjs`
- Master frps allow-list template: `deploy/frp/frps.dev.toml`
- G14 frpc local template: `deploy/frp/frpc.g14.toml`
Only `hwlab-cloud-web:8080` and `hwlab-edge-proxy:6667` are exposed through FRP.
Internal services, Tekton, Argo CD, registry, database, and simulator services stay ClusterIP-only.
The master-side `/opt/hwlab-frp/frps.dev.toml` may need a manual allow-list update matching `deploy/frp/frps.dev.toml` before
the G14 frpc Deployment can register `17666` and `17667`; this is an edge operation, not a D601
client change.
+17
View File
@@ -0,0 +1,17 @@
serverAddr = "74.48.78.17"
serverPort = 7000
loginFailExit = true
[[proxies]]
name = "hwlab-g14-cloud-web"
type = "tcp"
localIP = "hwlab-cloud-web.hwlab-dev.svc.cluster.local"
localPort = 8080
remotePort = 17666
[[proxies]]
name = "hwlab-g14-edge-proxy"
type = "tcp"
localIP = "hwlab-edge-proxy.hwlab-dev.svc.cluster.local"
localPort = 6667
remotePort = 17667
+8
View File
@@ -8,6 +8,14 @@ end = 16666
start = 16667
end = 16667
[[allowPorts]]
start = 17666
end = 17666
[[allowPorts]]
start = 17667
end = 17667
[[allowPorts]]
start = 7402
end = 7402
+77 -3
View File
@@ -13,8 +13,8 @@ const defaultRegistryPrefix = process.env.HWLAB_G14_REGISTRY_PREFIX || "127.0.0.
const defaultSourceRepo = process.env.HWLAB_G14_GIT_URL || "git@github.com:pikasTech/HWLAB.git";
const defaultBranch = process.env.HWLAB_G14_BRANCH || "G14";
const defaultGitopsBranch = process.env.HWLAB_G14_GITOPS_BRANCH || "G14-gitops";
const defaultRuntimeEndpoint = "http://hwlab-edge-proxy.hwlab-dev.svc.cluster.local:6667";
const defaultWebEndpoint = "http://hwlab-cloud-web.hwlab-dev.svc.cluster.local:8080";
const defaultRuntimeEndpoint = process.env.HWLAB_G14_RUNTIME_ENDPOINT || "http://74.48.78.17:17667";
const defaultWebEndpoint = process.env.HWLAB_G14_WEB_ENDPOINT || "http://74.48.78.17:17666";
const defaultProxyUrl = process.env.HWLAB_G14_PROXY_URL || "http://127.0.0.1:10808";
const defaultAllProxyUrl = process.env.HWLAB_G14_ALL_PROXY_URL || "socks5h://127.0.0.1:10808";
const defaultNoProxy = process.env.HWLAB_G14_NO_PROXY || "127.0.0.1,localhost,::1,10.0.0.0/8,10.42.0.0/16,10.43.0.0/16,192.168.0.0/16,.svc,.cluster.local,kubernetes.default.svc,registry.hwlab-ci.svc,hwlab-registry.hwlab-ci.svc";
@@ -871,12 +871,82 @@ function argoApplication(args) {
};
}
function g14FrpcManifest() {
const labels = {
"app.kubernetes.io/name": "hwlab-g14-frpc",
"app.kubernetes.io/part-of": "hwlab",
"hwlab.pikastech.local/environment": "dev",
"hwlab.pikastech.local/gitops-target": "g14"
};
return {
apiVersion: "v1",
kind: "List",
items: [
{
apiVersion: "v1",
kind: "ConfigMap",
metadata: {
name: "hwlab-g14-frpc-config",
namespace: "hwlab-dev",
labels
},
data: {
"frpc.toml": `serverAddr = "74.48.78.17"
serverPort = 7000
loginFailExit = true
[[proxies]]
name = "hwlab-g14-cloud-web"
type = "tcp"
localIP = "hwlab-cloud-web.hwlab-dev.svc.cluster.local"
localPort = 8080
remotePort = 17666
[[proxies]]
name = "hwlab-g14-edge-proxy"
type = "tcp"
localIP = "hwlab-edge-proxy.hwlab-dev.svc.cluster.local"
localPort = 6667
remotePort = 17667
`
}
},
{
apiVersion: "apps/v1",
kind: "Deployment",
metadata: {
name: "hwlab-g14-frpc",
namespace: "hwlab-dev",
labels
},
spec: {
replicas: 1,
selector: { matchLabels: { "app.kubernetes.io/name": "hwlab-g14-frpc" } },
template: {
metadata: { labels },
spec: {
containers: [{
name: "frpc",
image: "fatedier/frpc:v0.68.1",
imagePullPolicy: "IfNotPresent",
args: ["-c", "/etc/frp/frpc.toml"],
volumeMounts: [{ name: "config", mountPath: "/etc/frp", readOnly: true }]
}],
volumes: [{ name: "config", configMap: { name: "hwlab-g14-frpc-config" } }]
}
}
}
}
]
};
}
function runtimeKustomization({ source }) {
return {
apiVersion: "kustomize.config.k8s.io/v1beta1",
kind: "Kustomization",
namespace: "hwlab-dev",
resources: ["namespace.yaml", "code-agent-codex-config.yaml", "services.yaml", "health-contract.yaml", "workloads.yaml"]
resources: ["namespace.yaml", "code-agent-codex-config.yaml", "services.yaml", "health-contract.yaml", "workloads.yaml", "g14-frpc.yaml"]
};
}
@@ -890,6 +960,7 @@ This directory is generated from \`CI.json\`, \`deploy/deploy.json\`, and \`depl
- Artifact contract: images are tagged by source git commit \`${source.short}\` and pushed to \`${args.registryPrefix}\`.
- Branch split: source branch \`${args.sourceBranch}\` remains the watched code branch; generated desired state is promoted to \`${args.gitopsBranch}\`.
- CD: Argo CD Application \`argocd/hwlab-g14-dev\` consumes \`${args.gitopsBranch}:deploy/gitops/g14/runtime\`.
- Public preview: FRP exposes only G14 web \`${args.webEndpoint}\` and edge/API \`${args.runtimeEndpoint}\` through \`hwlab-g14-frpc\`; D601 keeps \`:16666/:16667\`.
- D601 boundary: this path does not target D601, does not use UniDesk Code Queue, and does not change D601 production traffic.
- Concurrency: CI builds are per source commit and do not acquire the legacy DEV CD Lease; Argo CD reconciles the Git desired state.
`;
@@ -925,6 +996,8 @@ async function plannedFiles(args) {
sourceRepo: args.sourceRepo,
registryPrefix: args.registryPrefix,
runtimePath: "deploy/gitops/g14/runtime",
publicEndpoints: { web: args.webEndpoint, runtime: args.runtimeEndpoint },
frpDeployment: "hwlab-dev/hwlab-g14-frpc",
tektonPipeline: "hwlab-ci/hwlab-g14-ci-image-publish",
argoApplication: "argocd/hwlab-g14-dev"
});
@@ -942,6 +1015,7 @@ async function plannedFiles(args) {
putJson("runtime/services.yaml", transformListNamespace(services, deploy.namespace, labels, annotations));
putJson("runtime/health-contract.yaml", transformHealthContract(health, deploy.namespace, labels, annotations, args.runtimeEndpoint, args.webEndpoint));
putJson("runtime/workloads.yaml", transformWorkloads({ workloads, deploy, source, registryPrefix: args.registryPrefix, runtimeEndpoint: args.runtimeEndpoint, webEndpoint: args.webEndpoint }));
putJson("runtime/g14-frpc.yaml", g14FrpcManifest());
return { files, source };
}