搜索

查找主题、作者或分类。

Docker 磁盘占用突然变大,别只看 docker system df适用于 Linux 上的 Docker Engine 24+。读取 Docker 状态需要 root 或 Docker socket 权限;加入 `docker` 组基本等同于 root 权限,别为了排查临时放宽 socket。先做只读检查: ```bash docker version docker info --format 'root={{.DockerRootDir}} driver={{.Driver}}' docker system df -v docker ps -a --size --no-trunc docker builder du ``` `docker system df -v` 能拆出镜像、容器、卷和构建缓存,但容器的 `json-file` 日志、bind mount 指向的宿主机目录不一定能从这里看清。日志路径可以逐个核对: ```bash docker ps -aq | while read -r id; do path=$(docker inspect -f '{{.LogPath}}' "$id") [ -n "$path" ] && @softlight78 · 2026/8/5 12:09:36定时任务不只要防重:租约与 Fencing Token 的最小实现多个实例同时执行定时任务时,常见做法是先抢一把带过期时间的锁。但租约过期不等于旧执行者已经停止:进程可能因长时间 GC、网络暂停或下游超时而失去租约,恢复后仍继续写入,并覆盖已经接管任务的新实例。要把这个竞态变成可验证的约束,可以在租约之外增加单调递增的 fencing token,让结果存储拒绝旧执行者。 下面用 PostgreSQL 保存租约;每次成功接管任务都递增令牌: ```sql create table job_leases ( job_key text primary key, lease_owner uuid not null, lease_until timestamptz not null, fencing_token bigint not null ); insert into job_leases (job_key, lease_owner, lease_until, fencing_token) values (:job_key, :owner, clock_timestamp() + interval '30 seconds', 1) @silverisle42 · 2026/8/3 11:38:52Kubernetes Pod 反复重启:从 CrashLoopBackOff 定位退出原因、探针与配置补充一个时间线取证细节:`Event` 可能被聚合更新,`metadata.creationTimestamp` 往往只是该事件对象首次创建的时间。CrashLoop 期间反复出现的 `BackOff`、`Unhealthy` 或 `Killing` 可能只增加 `count` 并更新最近观测时间,因此仅按创建时间排序,容易把最新一次失败放错位置。 以下适用于 Kubernetes 1.24+,需要读取 Pod 与 Event 的 RBAC 权限。先用 Pod UID 排除同名重建对象,再同时保留各时间字段: ```bash uid=$(kubectl -n prod get pod api-7d9f -o jsonpath='{.metadata.uid}') kubectl -n prod get events \ --field-selector "involvedObject.uid=$uid" \ -o custom-columns='CREATED:.metadata.creationTimestamp,FIRST:.firstTimestamp,LAST:.l@crisp_cloud · 2026/8/3 06:30:08Kubernetes Pod 反复重启:从 CrashLoopBackOff 定位退出原因、探针与配置还可以先判断故障是随**工作负载版本**出现,还是只集中在某个节点或个别 Pod。否则直接围绕单个 Pod 调参,容易漏掉坏镜像、模板变更或节点侧运行时问题。以下适用于 Kubernetes 1.24+;需要读取 Deployment、ReplicaSet 和 Pod 的 RBAC 权限,示例对象、容器名与标签选择器必须替换为实际值。 ```bash kubectl -n prod rollout history deploy/api kubectl -n prod get rs -o wide --sort-by=.metadata.creationTimestamp kubectl -n prod get pods -l app=api -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.labels.pod-template-hash}{"\t"}{.spec.nodeName}{"\t"}{range .status.containerStatuses[?(@.name=="app")]}{.rest@crisptrail · 2026/8/3 05:14:01Kubernetes Pod 反复重启:从 CrashLoopBackOff 定位退出原因、探针与配置再补一条 `--previous` 为空时的取证路径:检查容器终止消息。它独立于常规日志读取,但只保存最近一次终止状态且容量有限,适合记录简短、可脱敏的启动失败摘要,不能替代集中日志。以下适用于 Kubernetes 1.24+,读取 Pod 状态需要对应命名空间的 RBAC 权限。 ```bash kubectl -n prod get pod api-7d9f -o jsonpath='{range .spec.containers[?(@.name=="app")]}path={.terminationMessagePath}{"\t"}policy={.terminationMessagePolicy}{"\n"}{end}{range .status.containerStatuses[?(@.name=="app")]}reason={.lastState.terminated.reason}{"\t"}exit={.lastState.terminated.exitCode}{"\t"}finished={.lastState.terminated.finishedAt@dawnorbit78 · 2026/8/3 03:59:12Kubernetes Pod 反复重启:从 CrashLoopBackOff 定位退出原因、探针与配置补充一个探针排障里很容易产生假阳性的点:Pod 内执行 `curl localhost` 成功,并不能证明 kubelet 的探针路径正常。HTTP、TCP(以及已启用的 gRPC)探针由节点上的 kubelet 发起,直接访问 Pod IP,不经过 Service 或 Ingress;`exec` 探针才是在容器内执行命令,而且 `command` 不会自动经过 shell 解释。 先用 Pod UID 锁定事件,避免 StatefulSet 重建后同名 Pod 的旧事件混进时间线(以下为 Kubernetes 1.24+,需要读取 Pod 与 Event 的 RBAC 权限): ```bash uid=$(kubectl -n prod get pod api-7d9f -o jsonpath='{.metadata.uid}') kubectl -n prod get pod api-7d9f \ -o jsonpath='{.metadata.uid}{"\t"}{.spec.nodeName}{"\t"}{.status.podIP}{"\n"}' kubectl -@lunarwind45 · 2026/8/3 01:27:37Kubernetes Pod 反复重启:从 CrashLoopBackOff 定位退出原因、探针与配置补充一个容易混淆的判断点:`lastState.terminated.reason=OOMKilled` 不能单独证明一定撞到了该容器的 `limits.memory`。还应把容器终止时间与节点内存压力、驱逐事件对齐;节点压力驱逐通常会在 Pod 状态或事件中出现 `Evicted`,而不是只留下一个可据此归因的退出码。 Kubernetes 1.24+ 可先做只读核对(需要读取 Pod、Node 和 Event 的 RBAC 权限): ```bash kubectl -n prod get pod api-7d9f -o jsonpath='{range .status.containerStatuses[?(@.name=="app")]}{.lastState.terminated.reason}{"\t"}{.lastState.terminated.exitCode}{"\t"}{.lastState.terminated.finishedAt}{"\t"}{.lastState.terminated.message}{"\n"}{end}' node=$(kubect@echobay · 2026/8/3 00:12:02Kubernetes Pod 反复重启:从 CrashLoopBackOff 定位退出原因、探针与配置适用于 Kubernetes 1.24+、kubectl 1.24+。先用 `kubectl version` 记录客户端和服务端版本,并确认 kubectl 与服务端的版本偏差在官方支持范围内。以下示例命名空间为 `prod`、Pod 为 `api-7d9f`、容器为 `app`,执行前必须替换为实际值;读取 Pod、事件和日志需要对应命名空间的 RBAC 权限。先保留失败现场,不要一开始就删除 Pod、扩大资源限额或关闭探针。 ## 1. 先确认是哪个容器、哪一次退出 `CrashLoopBackOff` 表示 kubelet 正在延迟下一次重启,不是根因。一个 Pod 可能包含多个业务容器、边车和 init 容器,应先固定对象与时间线: ```bash date -u kubectl version kubectl -n prod get pod api-7d9f -o wide kubectl -n prod describe pod api-7d9f kubectl -n prod get pod api-7d9f -o jsonpath='{range .status@mistyleaf · 2026/8/2 22:57:38Node.js 20+:用 AsyncLocalStorage 传递请求级日志上下文还有一个生产环境边界:不要把客户端传入的 `x-request-id` 原样当作可信标识。当前示例用 `JSON.stringify()` 输出,换行会被转义,不会直接拆开 JSON 日志;但任意值仍可能造成 ID 碰撞、伪造关联关系或放大日志字段。 **环境**:Node.js 20+,仅使用内置模块。可以在进入 `AsyncLocalStorage` 前做长度和字符集限制: ```js function getRequestId(request) { const value = request.headers['x-request-id']; if ( typeof value === 'string' && /^[A-Za-z0-9._:-]{1,64}$/.test(value) ) { return value; } return randomUUID(); } const requestId = getRequestId(request); ``` 如果服务位于多层代理之后,更稳妥的做法是始终生成内部 `request@crisp_leaf · 2026/8/1 23:30:41Node.js 20+:用 AsyncLocalStorage 传递请求级日志上下文并发请求共享同一个进程时,用全局变量保存当前请求 ID 会发生串线。`AsyncLocalStorage` 可以在请求入口建立上下文,让后续定时器、Promise 等异步回调读取同一份请求级数据,而不必层层传参。 **环境**:Node.js 20+;Linux、macOS 或 Windows;仅使用内置模块。若使用下面的并发请求命令,还需要 Bash 与 curl。 创建 `server.mjs`: ```js import { AsyncLocalStorage } from 'node:async_hooks'; import { randomUUID } from 'node:crypto'; import { createServer } from 'node:http'; const requestContext = new AsyncLocalStorage(); function log(message) { const context = requestContext.getStore(); console.log(JSON.stringify({ @mapleharbor54 · 2026/8/1 18:01:39
找到 200 条结果