minecluster/lib/k8s/server-status.ts

85 lines
2.9 KiB
TypeScript

import k8s from "@kubernetes/client-node";
import { getUserDeployments } from "./k8s-server-control.js";
import { getServerEntries } from "../database/queries/server-queries.js";
import kc from "./k8s-config.js";
const k8sMetrics = new k8s.Metrics(kc);
const namespace = process.env.MCL_SERVER_NAMESPACE;
function getServerMetrics(podMetricsRes, serverId, serverAvailable) {
const pod = podMetricsRes.items.find(({ metadata: md }) => {
return (
md.annotations &&
md.annotations["minecluster.dunemask.net/id"] === serverId
);
});
if (!serverAvailable || !pod) return null;
const podCpus = pod.containers.map(
({ usage }) => parseInt(usage.cpu) / 1_000_000,
);
const podMems = pod.containers.map(
({ usage }) => parseInt(usage.memory) / 1024,
);
return {
cpu: Math.ceil(podCpus.reduce((a, b) => a + b)),
memory: Math.ceil(podMems.reduce((a, b) => a + b)),
};
}
function getServerStatus(server) {
const { containers } = server.spec.template.spec;
const services = containers.map(({ name }) => name.split("-").pop());
const serverStatusList = server.status.conditions.map(
({ type: statusType, status: sts }) => ({ statusType, sts }),
);
const deploymentAvailable =
serverStatusList.find(
(ss) => ss.statusType === "Available" && ss.sts === "True",
) !== undefined;
const serverAvailable = services.includes(`server`) && deploymentAvailable;
const ftpAvailable = services.includes("ftp"); // TODO this needs some handling for container creation
return { serverAvailable, ftpAvailable, services, deploymentAvailable };
}
export async function getInstances(cairoId) {
const [serverDeployments, podMetricsRes, entries] = await Promise.all([
getUserDeployments(cairoId),
k8sMetrics.getPodMetrics(namespace),
getServerEntries(),
]);
var serverId, metrics;
const serverInstances = serverDeployments.map((s) => {
serverId = s.metadata.annotations["minecluster.dunemask.net/id"];
const entry = entries.find((e) => e.id === serverId);
const { ftpAvailable, serverAvailable, services, deploymentAvailable } =
getServerStatus(s);
metrics = getServerMetrics(podMetricsRes, serverId, serverAvailable);
return {
name: !!entry ? entry.name : "Unknown",
host: !!entry ? entry.host : "Unkonwn",
id: serverId,
metrics,
services,
serverAvailable,
ftpAvailable,
deploymentAvailable,
};
});
return serverInstances;
}
export async function getNamespaceMetrics() {
const serverInstances = await getInstances();
var clusterMetrics = { cpu: 0, memory: 0 };
if (servers.length > 1) {
const clusterCpu = serverInstances
.map(({ metrics }) => (metrics ? metrics.cpu : 0))
.reduce((a, b) => a + b);
const clusterMem = serverInstances
.map(({ metrics }) => (metrics ? metrics.memory : 0))
.reduce((a, b) => a + b);
clusterMetrics = { cpu: clusterCpu, memory: clusterMem };
}
return clusterMetrics;
}