K8S Heapdump Chrome DevTools
一、认识
在 Kubernetes
中部署 Node.js
服务后,如果收到内存不足报警时,我们需要通过 Heapdump
来生成内存快照, 进行快照采集。但是在 Kubernetes
集群多节点部署环境下, 有以下难点和挑战:
二、在 Kubernetes 集群多节点部署环境下, 如何生成特定的 Pod 快照文件?
2.2 通过访问特定 Pod IP
1. 访问指定 Pod
: 使用 kubectl
命令找到目标 Pod
的名称, 获取目标 Pod
的 IP
地址
kubectl get pods -n <namespace>
2. 触发 API
生成快照: 使用 curl
或类似工具访问目标 Pod
的 /heap-snapshot
路径
curl -X POST -H "x-auth-token: bolawen" http://<pod-ip>:3000/heap-snapshot
2.2 通过容器 Exec 直接触发
在某些情况下,无法直接通过 HTTP
调用接口,你可以通过 kubectl exec
手动触发 Heapdump
的生成。
1. 进入容器
kubectl exec -it <pod-name> -n <namespace> -- /bin/sh
2. 访问服务
三、在 Kubernetes 集群多节点部署环境下, 指定 Pod 生成快照时,如何保证服务的高可用性?
Heapdump
生成快照 会消耗大量的内存和 CPU
,从而会影响服务的正常运行。有时候, Node
服务会中断,根据当时服务器内存大小这个时间会在 2 ~ 30min
左右。
3.1 扩展 Pod 副本数
确保服务高可用性和生成 Heapdump
快照的核心策略是将快照生成的资源消耗隔离。可以通过扩展 Pod
副本数,通过负载均衡消除单个 Pod
性能下降的影响。
思路: 通过 Service
将 Node.js
服务暴露给外部访问,并结合 Deployment ReadinessProbe
确保 Service
仅将流量分发给健康的 Pod
, 保证服务稳定和服务高可用。配置Deployment replicas
, 配置 Node.js Pod
多个副本, 在生成 Heapdump
之前,通过 Kubernetes
修改 Pod
的 readinessProbe
,让流量从负载均衡中移除, 将当前 Pod
的流量隔离,防止因性能下降影响请求响应。这样即使某个 Pod
性能受损,服务流量会自动分配到其他健康的 Pod
,保证服务的高可用性。
Node.js
服务: 在生成 Heapdump
之前,通过 Kubernetes
修改 Pod
的 readinessProbe
,让流量从负载均衡中移除。生成后,恢复 Pod
。
function generateHeapSnapshot(snapshotType, onError, onSuccess) {
triggerGc();
fs.writeFileSync("/tmp/healthy", "0"); // 模拟 readinessProbe 不健康状态
const filename = path.join(
CONFIG.heapSnapshotDir,
`heapdump-${snapshotType}-${Date.now()}.heapsnapshot`
);
heapdump.writeSnapshot(filename, (err, file) => {
if (err) {
console.error(`Error writing heap snapshot (${snapshotType}):`, err);
onError?.(err);
} else {
console.log(`Heap snapshot (${snapshotType}) saved to ${file}`);
uploadViaScp(file);
onSuccess?.(file);
fs.writeFileSync("/tmp/healthy", "1"); // 恢复健康状态
}
});
}
Deployment
部署:
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
3.2 基于独立进程生成快照
确保服务高可用性和生成 Heapdump
快照的核心策略是将快照生成的资源消耗隔离。可以使用 child_process
独立进程分离快照生成逻辑,避免主服务受影响。
思路: 将生成 Heapdump
的任务交给一个独立的进程,避免主服务受到影响。快照生成由独立的脚本或服务运行。主服务通过异步调用启动快照生成服务。
const { spawn } = require("child_process");
// 在生成快照时启动独立的子进程
const heapdumpProcess = spawn("node", ["heapdump-script.js"], {
detached: true,
stdio: "ignore",
});
heapdumpProcess.unref();
3.2 基于 Job 分离快照生成与服务运行
确保服务高可用性和生成 Heapdump
快照的核心策略是将快照生成的资源消耗隔离。可以使用 Job
或 分离快照生成逻辑,避免主服务受影响。
思路: 通过 Kubernetes
的 Job
或 CronJob
创建临时 Pod
专门用于生成 Heapdump
,而不是在主服务 Pod
中生成。Heapdump
的生成在独立的 Pod
中进行,完全不影响主服务。
Job
部署:
apiVersion: batch/v1
kind: Job
metadata:
name: heapdump-generator
spec:
template:
spec:
containers:
- name: heapdump
image: my-service-image:latest
command: ["node", "generate-heapdump.js"]
restartPolicy: Never
Node.js
服务: 在服务代码中使用 Kubernetes API
触发 Job
const k8s = require("@kubernetes/client-node");
const kc = new k8s.KubeConfig();
kc.loadFromDefault();
const batchV1 = kc.makeApiClient(k8s.BatchV1Api);
batchV1.createNamespacedJob("default", {
metadata: { name: "heapdump-generator" },
spec: { ... },
});