> For the complete documentation index, see [llms.txt](https://documentation.alluxio.io/ee-ai-cn/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.alluxio.io/ee-ai-cn/administration/troubleshooting-alluxio.md).

# 故障排除

本指南帮助你诊断运行在 Kubernetes 上的 Alluxio 集群。它按照「你观察到的现象 → 能确认原因的健康检查或日志 → 恢复步骤」的顺序组织。

如果你在 Kubernetes 之外运行 Alluxio，日志内容和恢复步骤同样适用，但其中的 `kubectl` 命令不适用。

## 开始之前

你需要能访问两个命名空间，而且**看错命名空间是最常见的问题来源**：

| 命名空间             | 本文示例中写作            | 里面运行着什么                           |
| ---------------- | ------------------ | --------------------------------- |
| 你的 Alluxio 集群    | `alx-ns`           | Coordinator、worker、FUSE Pod、etcd  |
| Alluxio Operator | `alluxio-operator` | Operator、CSI 驱动、doctor controller |

几乎所有「命令没有任何输出」的情况，都是这两个命名空间搞混了。用下面的命令确认 你自己的：

```shell
# 你的 Alluxio 集群所在的命名空间
kubectl get alluxiocluster -A

# Operator、CSI 驱动和 doctor controller 所在的命名空间
kubectl get pod -A -l app.kubernetes.io/component=doctor-controller
```

本页出现的 `alx-ns` 和 `alluxio-operator` 都请替换成你自己的命名空间。

## 1. 先定位你的现象

从你实际看到的现象出发。每一行都链接到对应的诊断章节。

| 你观察到的现象                                   | 最可能的方向                | 跳转到                                                                    |
| ----------------------------------------- | --------------------- | ---------------------------------------------------------------------- |
| 应用报 `Transport endpoint is not connected` | FUSE 挂载丢失             | [应用侧看到的错误](#ying-yong-ce-kan-dao-de-cuo-wu)                            |
| 应用在已缓存路径上报 `Input/output error`           | 挂载背后的 worker 或 UFS 故障 | [应用侧看到的错误](#ying-yong-ce-kan-dao-de-cuo-wu)                            |
| 应用访问文件时卡住，没有报错                            | Worker 不可达，或 UFS 超时   | [检查集群健康状况](#id-2.-jian-cha-ji-qun-jian-kang-zhuang-kuang)              |
| 某个 Pod 不是 `READY`，或反复重启                   | 组件故障                  | [检查集群健康状况](#id-2.-jian-cha-ji-qun-jian-kang-zhuang-kuang)              |
| 读变慢，缓存命中率下降                               | 缓存或 worker 健康问题       | [仪表板能告诉你什么](#yi-biao-ban-neng-gao-su-ni-shen-me)                       |
| 缓存写满之后写入失败                                | Page store 容量         | [Worker 故障](#worker-gu-zhang)                                          |
| Worker 重启后要好几分钟才 `READY`                  | Page store 恢复         | [Worker 故障](#worker-gu-zhang)                                          |
| S3 API 对确实存在的路径返回 404 `NoSuchBucket`      | 路径未挂载                 | [S3 API 错误](#s3-api-cuo-wu)                                            |
| S3 API 端点拒绝连接                             | 未启用 S3 API            | [S3 API 错误](#s3-api-cuo-wu)                                            |
| `alluxio fs` 命令失败或卡住                      | Coordinator 或 etcd    | [Coordinator 故障](#coordinator-gu-zhang)                                |
| Alluxio 支持团队向你索要诊断包                       | —                     | [使用 Doctor 收集诊断快照](#id-4.-shi-yong-doctor-shou-ji-zhen-duan-kuai-zhao) |

如果你的现象不在表内，请按顺序做完第 2、3 节，然后收集一个诊断包交给支持团队。

## 2. 检查集群健康状况

下面这些检查用时不到一分钟，能排除大部分原因。

### 所有 Pod 都 ready 了吗？

状态是 `Running` 还不够——`READY` 列必须显示 Pod 内所有容器都健康。

Coordinator：

```shell
kubectl -n alx-ns get pod -l app.kubernetes.io/component=coordinator
```

Worker：

```shell
kubectl -n alx-ns get pod -l app.kubernetes.io/component=worker
```

```console
NAME                                      READY   STATUS    RESTARTS   AGE
alluxio-cluster-worker-59476bf8c5-lg4sc   1/1     Running   0          46h
alluxio-cluster-worker-59476bf8c5-vg6lc   1/1     Running   0          46h
```

FUSE Pod（DaemonSet 和 CSI 两种形态）：

```shell
kubectl -n alx-ns get pod -l 'app.kubernetes.io/component in (fuse, csi-fuse)'
```

```console
NAME                                           READY   STATUS    RESTARTS   AGE
alluxio-cluster-fuse-acee53e8f0a9-3gjbrdekk0   1/1     Running   0          57m
```

内置的 etcd 集群：

```shell
kubectl -n alx-ns get pod -l 'app.kubernetes.io/component=etcd,app.kubernetes.io/instance=alluxio-cluster'
```

```console
NAME                     READY   STATUS    RESTARTS   AGE
alluxio-cluster-etcd-0   1/1     Running   0          46h
alluxio-cluster-etcd-1   1/1     Running   0          46h
alluxio-cluster-etcd-2   1/1     Running   0          46h
```

`RESTARTS` 列和 `READY` 一样重要。当前 ready 但重启过好几次的 Pod，说明存在反复 发生的故障——参见[常见故障与恢复](#id-5.-chang-jian-gu-zhang-yu-hui-fu)，并查看上一个容器的日志。

快速计算某个组件的就绪比例：

```shell
kubectl -n alx-ns get pod -l app.kubernetes.io/component=worker -o jsonpath='{range .items[*]}{.status.containerStatuses[0].ready}{"\n"}{end}' | awk 'BEGIN{t=0}{s+=1;if($1=="true")t+=1}END{print t,"ready /",s,"expected =",t/s*100,"%"}'
```

```console
2 ready / 2 expected = 100 %
```

### Alluxio 能访问到你的存储吗？

如果 Pod 都健康但读取失败，下一个嫌疑就是底层存储（UFS）。下面的命令要在 worker 或 coordinator Pod 内执行，那里才有 Alluxio CLI 和集群配置：

```shell
kubectl -n alx-ns exec -it deploy/alluxio-cluster-coordinator -- bash
```

检查 UFS 基本操作：

```shell
./bin/alluxio exec ufsTest --path s3://your_bucket/test_path
```

```console
Running test: createAtomicTest...
Passed the test! time: 5205ms
...
Tests completed with 0 failed.
```

检查 UFS 读写吞吐——下面的示例用两个线程读写一个 512MB 的文件：

```shell
./bin/alluxio exec ufsIOTest --path s3://test_bucket/test_path --io-size 512m --threads 2
```

```console
{
  "readSpeedStat" : { ... },
  "writeSpeedStat" : { ... },
  "errors" : [ ],
  ...
}
```

零失败说明 UFS 可达，且凭证、region、endpoint 都配置正确。这里失败则说明问题出在 Alluxio 与存储之间，而不在 Alluxio 内部。

### 仪表板能告诉你什么

Grafana 仪表板是判断问题是全集群性的还是只影响单个组件的最快途径。三类面板能回答 大部分问题：

| 指标                                | 标签                      | 出问题时是什么样                                                |
| --------------------------------- | ----------------------- | ------------------------------------------------------- |
| `alluxio_data_access_bytes_count` | `method`                | `irate(...[5m])` 骤降说明客户端不再能访问到 worker。骤升说明负载发生了预期之外的变化。 |
| `alluxio_ufs_error`               | `ufs_type`、`error_code` | 任何持续上升都值得关注。按 `error_code` 分组——它能区分权限问题和连通性问题。          |
| `alluxio_ufs_data_access`         | `method`                | 客户端流量持平而 UFS 流量上升，说明缓存未命中增加了——原本缓存住的数据正在被重新拉取。          |
| `alluxio_fuse_result`             | `method`、`state`        | 按 `method` 分组看失败数，可以定位是哪个 POSIX 操作在失败。                  |

缓存命中率骤降通常有两种原因：worker 不健康导致其缓存丢失，或者访问模式发生了变化。 上面的 Pod 检查可以区分两者。

完整指标列表见[监控指标](/ee-ai-cn/reference/metrics.md)。

## 3. 阅读日志

### 哪个日志回答哪类问题

Alluxio 把一次请求分散到多个组件处理，所以显示**原因**的日志往往不是报出**错误** 的那个。按你想知道什么来选：

| 组件             | 命名空间     | 标签选择器                                             | 能在里面找到什么                                             |
| -------------- | -------- | ------------------------------------------------- | ---------------------------------------------------- |
| Coordinator    | 集群       | `app.kubernetes.io/component=coordinator`         | Job service：`load`、`free` 等异步作业的调度及其历史               |
| Worker         | 集群       | `app.kubernetes.io/component=worker`              | 读写服务、page store（缓存）操作、UFS 拉取、缓存驱逐、启动时的 page store 恢复 |
| FUSE           | 集群       | `app.kubernetes.io/component in (fuse, csi-fuse)` | 来自应用的 POSIX 操作及其看到的错误——应用可见的故障最先在这里显形                |
| CSI nodeplugin | operator | `app.kubernetes.io/component=csi-nodeplugin`      | 单个节点上卷的挂载与卸载——Pod 因为卷挂不上而起不来时看这里                     |
| CSI controller | operator | `app.kubernetes.io/component=csi-controller`      | 按卷创建和删除 FUSE Pod                                     |
| etcd           | 集群       | `app.kubernetes.io/component=etcd`                | Quorum 与成员问题                                         |

经验法则：从你的应用直接对话的那个组件开始（挂载路径看 FUSE，S3 API 看 worker）， 然后顺着错误往上游追。

### 读取组件日志

你通常事先并不知道 Pod 名，所以按组件选择更实用。Coordinator 只有一个 Pod：

```shell
kubectl -n alx-ns logs -l app.kubernetes.io/component=coordinator --tail=-1
```

Worker 有多个，给每行加上来源 Pod 前缀：

```shell
kubectl -n alx-ns logs -l app.kubernetes.io/component=worker --prefix --tail=-1
```

{% hint style="warning" %}
`kubectl logs -l` 在不加 `--tail=-1` 时，每个 Pod 只返回最后 10 行。不加这个参数， 你要找的那条错误会被静默丢掉。
{% endhint %}

要看某个特定 Pod，直接指定名字：

```shell
kubectl -n alx-ns logs alluxio-cluster-worker-59476bf8c5-lg4sc
```

只看问题，并多显示匹配后的一行，让堆栈可读：

```shell
kubectl -n alx-ns logs alluxio-cluster-fuse-acee53e8f0a9-3gjbrdekk0 | grep -A 1 'WARN\|ERROR'
```

```console
2024-07-04 17:29:53,499 ERROR HdfsUfsStatusIterator - Failed to list the path hdfs://localhost:9000/
java.net.ConnectException: Call From myhost/192.168.1.10 to localhost:9000 failed on connection exception: java.net.ConnectException: Connection refused; For more details see:  http://wiki.apache.org/hadoop/ConnectionRefused
```

如果 Pod 重启过，有用的日志属于**上一个**容器，当前容器是干净启动的：

```shell
kubectl -n alx-ns logs -p alluxio-cluster-worker-59476bf8c5-lg4sc
```

`kubectl logs` 只能看到当前容器写到 stdout 的内容。Alluxio 同时还会在 Pod 内写滚动 日志文件，默认位于 `/opt/alluxio/logs`（由 `alluxio.logs.dir` 决定），能回溯得更久：

```shell
# 看有哪些日志文件
kubectl -n alx-ns exec alluxio-cluster-worker-59476bf8c5-lg4sc -- ls -lht /opt/alluxio/logs

# 把当前的 worker 日志拷出来；coordinator Pod 里对应的是 coordinator.log
kubectl -n alx-ns cp alluxio-cluster-worker-59476bf8c5-lg4sc:/opt/alluxio/logs/worker.log ./worker.log
```

滚动后的文件名形如 `worker-<日期>-<序号>.log`。[Doctor 快照](#id-4.-shi-yong-doctor-shou-ji-zhen-duan-kuai-zhao) 会一次性把所有组件的这些文件都收集齐，通常比逐个 Pod 拷贝省事得多。

{% hint style="info" %}
Pod 被删除重建后，容器日志就没了。如果你在追查偶发故障，请在证据还在的时候 [使用 Doctor 收集诊断快照](#id-4.-shi-yong-doctor-shou-ji-zhen-duan-kuai-zhao)。
{% endhint %}

### 读取 CSI 驱动日志

FUSE 卷挂不上时，答案在与你的应用 Pod **位于同一节点**的 CSI node plugin 里：

```shell
# 1. 找到你的应用或 FUSE Pod 所在的节点
PODNS=alx-ns POD=alluxio-cluster-fuse-acee53e8f0a9-3gjbrdekk0
NODE_NAME=$(kubectl get pod -o jsonpath='{.spec.nodeName}' -n ${PODNS} ${POD})

# 2. 找到该节点上的 CSI node plugin Pod
CSI_POD_NAME=$(kubectl -n alluxio-operator get pod -l app.kubernetes.io/component=csi-nodeplugin --field-selector spec.nodeName=${NODE_NAME} -o jsonpath='{..metadata.name}')

# 3. 读取它的日志
kubectl -n alluxio-operator logs -c csi-nodeserver ${CSI_POD_NAME}
```

## 4. 使用 Doctor 收集诊断快照

Doctor 是 Operator 提供的诊断收集器。它把配置、日志、指标、硬件信息和集群状态打包 成一个归档。在上面的检查都做完仍无结论时，或 Alluxio 支持团队向你索要时，收集一个。

你通过创建 `CollectInfo` 资源来驱动 Doctor；doctor controller 监听到它之后完成实际 工作。

### 前置条件

doctor controller 必须运行在 operator 命名空间中。如果没有，请升级 Alluxio Operator。

```shell
kubectl -n alluxio-operator get pod -l app.kubernetes.io/component=doctor-controller
```

```console
NAME                                             READY   STATUS    RESTARTS   AGE
alluxio-doctor-controller-cc49c56b6-wlw8k        1/1     Running   0          19s
```

### 触发一次收集

Operator 创建的每个集群都自带一个 `CollectInfo`，在每天 UTC 零点运行，收集过去 24 小时的全部内容，每个归档保留 180 天。先看看你的集群里有哪些：

```shell
kubectl -n alx-ns get collectinfo
```

```console
NAME              LASTSCHEDULETIME       LASTSUCCESSFULTIME     AGE
alluxio-cluster   2026-09-03T00:00:00Z   2026-09-03T00:04:12Z   46h
```

如果不想等下一次定时运行，而要抓取**当下**的状态，创建一个一次性的 `CollectInfo`：

```shell
kubectl apply -f - <<'EOF'
apiVersion: k8s-operator.alluxio.com/v1
kind: CollectInfo
metadata:
  name: one-time-snapshot
  # 必须是 Alluxio 集群所在的命名空间
  namespace: alx-ns
spec:
  # 下面两个字段都已经是默认值，可以省略。真正让它只执行一次的，是没有设置
  # spec.scheduled.cron。
  type:
    - all
  logs:
    sinceSeconds: 86400
EOF
```

如果你要定义的是**定时**收集，那就仍然写成文件——它应该和集群 manifest 一起进版本 管理。

{% hint style="info" %}
旧的示例用 `spec.scheduled.enabled: false` 来触发单次运行。该字段已废弃，而且并不是 controller 实际检查的东西——**没有** `spec.scheduled.cron` 时 `CollectInfo` 就只运行 一次，**有** `cron` 时才按计划重复运行。
{% endhint %}

确认它已经完成——归档写完后 `LASTSUCCESSFULTIME` 才会有值：

```shell
kubectl -n alx-ns get collectinfo one-time-snapshot
```

这会收集过去一天的全部内容。对大多数问题这就是合适的默认值——如果不合适，见 [调整收集内容](#tiao-zheng-shou-ji-nei-rong)。

### 查找并下载诊断包

每次运行会在 doctor-controller Pod 的 `/data/doctor` 目录下生成一个 `.tar.gz` 归档，按产生它的 `CollectInfo` 命名：

```
<CollectInfo 名称>_<CollectInfo 命名空间>_<生成时间>.tar.gz
```

对于上面的 `one-time-snapshot`，文件名就是 `one-time-snapshot_alx-ns_2026-09-03-07-29-01.tar.gz`。

```shell
# 1. 获取 doctor controller Pod 名称
DOCTOR_NAME=$(kubectl -n alluxio-operator get pod -l app.kubernetes.io/component=doctor-controller -o jsonpath="{.items[0].metadata.name}")

# 2. 按时间倒序列出该 CollectInfo 产生的归档
kubectl -n alluxio-operator exec ${DOCTOR_NAME} -- ls -lht /data/doctor/one-time-snapshot_alx-ns_*.tar.gz

# 3. 把其中一个归档复制到本地
ARCHIVE_NAME=one-time-snapshot_alx-ns_2026-09-03-07-29-01.tar.gz
kubectl -n alluxio-operator cp ${DOCTOR_NAME}:/data/doctor/${ARCHIVE_NAME} ./${ARCHIVE_NAME}
```

去掉文件名过滤（`ls -lht /data/doctor`）可以看到全部归档；需要全部拿走时可以复制 整个目录（`kubectl -n alluxio-operator cp ${DOCTOR_NAME}:/data/doctor ./doctor`）。 按默认每日计划运行的集群每天会积累一个归档，因此整目录复制可能很大。

### 把诊断包发给 Alluxio

默认情况下归档留在你的集群里，由你自行发给支持团队。Alluxio 也可以提供一个它维护 的存储桶的凭证，让每次快照自动上传——在 `CollectInfo` 中加上 `upload` 配置块即可。 参见 [`spec.upload`](https://documentation.alluxio.io/ee-ai-cn/administration/pages/dGaXCqFCAXMdzqhVYdXZ#spec.upload)。

### 调整收集内容

默认值适用于大多数场景。最常见的两种调整是：

| 你的需求       | 在 `spec` 中加上                                                    |
| ---------- | --------------------------------------------------------------- |
| 需要一天以前的日志  | `logs: {sinceSeconds: 259200}` 表示三天                             |
| 需要更小、更快的归档 | `type: [config, dynamic-config, logs, meta]`——省去体积最大的 `metrics` |

包括收集计划、保留时长、指标精度在内的全部字段，见 [CollectInfo 参考](/ee-ai-cn/reference/collectinfo-crd.md)。

## 5. 常见故障与恢复

### 应用侧看到的错误

这些错误出现在你的应用里，而不是 Alluxio 里。FUSE 日志是确认原因的地方。

| 错误                                    | 发生了什么                                                    | 该怎么做                                                |
| ------------------------------------- | -------------------------------------------------------- | --------------------------------------------------- |
| `Transport endpoint is not connected` | 服务该挂载点的 FUSE 进程消失了。挂载点在应用的命名空间里还在，但背后已经没有东西，而且不会自行恢复。    | 确认 FUSE Pod 重新变为 `READY`，然后重启应用 Pod 以接上新的挂载。        |
| `Input/output error`                  | 一次读或写到达了 Alluxio 并失败了——通常是持有数据的 worker 不可达，或者 UFS 返回了错误。 | 在 FUSE 日志里找底层异常，再顺着它去看 worker 或 UFS。                |
| 操作卡住且无报错                              | Worker 或 UFS 没有响应，请求正在等待超时。                              | 先看 worker 是否 ready，再从 coordinator Pod 里跑 `ufsTest`。 |

FUSE Pod 卡在 `Init` 说明它根本没挂载成功——它在等待某个依赖，通常是 etcd 尚未 就绪。

### Worker 故障

Alluxio 在设计上容忍 worker 丢失：Kubernetes 会重启该 Pod，其上缓存的数据丢失， 读请求回退到 UFS。I/O 不会失败，但在缓存重新填充之前会变慢。

| 现象                                                                           | 原因                                                                                                  | 该怎么做                                                                                    |
| ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
| Worker 日志出现 `Insufficient page store space`                                  | Page store 已满，无法接受新的 page。                                                                          | 调大 page store 容量，或检查驱逐是否跟得上。参见[缓存驱逐](/ee-ai-cn/cache/cache-eviction.md)。                |
| Worker 启动失败：`quota (...) exceeds the total disk space (...) on ...`          | 配置的 page store 容量加上预留容量，超过了承载它的卷。                                                                   | 调小 page store 容量，或给该卷更多空间。                                                              |
| Worker 重启后要几分钟才 `READY`，日志显示 `Page store finished restoring N pages in M ms` | Page store 在启动时是顺序重建的。缓存大时确实需要几分钟。                                                                  | 这不是故障。随着缓存增长，worker 重启会更慢，滚动重启时要把这段时间算进去。                                               |
| Worker Pod 被 `OOMKilled`，或被 kubelet 驱逐                                       | 内存 limit 相对配置的堆内存和直接内存过低；或者使用 `emptyDir` 的 page store 超出了它的 `sizeLimit`。kubelet 驱逐不等于 Alluxio 缓存驱逐。 | 用 `kubectl -n alx-ns describe pod <worker-pod>` 区分两者。调高 limit，或把 page store 换到有实际容量的卷上。 |
| 日志提到客户端与 worker 之间时钟 `out of sync`                                           | 节点间时钟漂移会让缓存新鲜度校验失效，导致额外开销。                                                                          | 检查 Kubernetes 节点上的 NTP。                                                                 |

### Coordinator 故障

Coordinator 运行 job service，负责管理分布式 load 等异步作业。它会持久化作业历史 并在重启后恢复，Kubernetes 也会自动重启故障的 coordinator Pod。

如果作业历史损坏，未完成的作业会丢失，需要重新提交。`alluxio fs` 这类客户端命令 如果是卡住而不是报错，通常指向 coordinator 或其背后的 etcd。

### FUSE 故障

崩溃或无响应的 FUSE Pod 会由它的控制器（DaemonSet 或 CSI 驱动）自动重启。要强制 重启一个卡死的 Pod：

```shell
kubectl -n alx-ns delete pod <fuse-pod-name>
```

仍持有旧 Pod 挂载的应用会一直看到 `Transport endpoint is not connected`，直到它们 被重启。

### etcd 故障

Alluxio 能在一段宽限期内（通常 24 小时）容忍 etcd 不可用而不影响 I/O，所以能干净重启的 etcd pod 无需干预。

集群无法恢复时只能重建，那会丢掉挂载表——见 [重建 etcd](/ee-ai-cn/administration/managing-etcd.md#chong-jian-etcd)。如果 etcd 本身是健康的、只是想换一套， 请改走迁移流程以保住状态：[迁移到另一套 etcd](/ee-ai-cn/administration/managing-etcd.md#qian-yi-dao-ling-yi-tao-etcd)。

### S3 API 错误

S3 API 由 worker 自身提供服务，端口由 `alluxio.worker.rest.port` 决定（默认 `29998`）。没有单独的 proxy Pod。

| 现象                                                     | 原因                                           | 该怎么做                                                                                                    |
| ------------------------------------------------------ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| S3 端点连接被拒绝                                             | 未启用 S3 API。                                  | 设置 `alluxio.worker.s3.api.enabled=true`。Alluxio 2.x 的 `alluxio.proxy.s3.enabled` 在 3.x 中已不存在，设置它没有任何效果。 |
| 对预期存在的路径返回 `404 NoSuchBucket`                          | endpoint 之后的第一段路径是 Alluxio 的挂载名，而它没有解析到任何挂载。 | 列出挂载表，确认名称是否匹配。                                                                                         |
| Worker 日志出现 `Timeout waiting for connection from pool` | S3 客户端的连接池耗尽，通常发生在高并发下，或此前运行泄漏了连接。           | 为高并发负载显式设置 `alluxio.underfs.s3.connections.max`。                                                        |

## 相关文档

* [CollectInfo 参考](/ee-ai-cn/reference/collectinfo-crd.md) —— 诊断收集资源的全部字段
* [监控指标](/ee-ai-cn/reference/metrics.md) —— 仪表板背后的完整指标列表
* [缓存驱逐](/ee-ai-cn/cache/cache-eviction.md) —— 管理 page store 容量
* [在 Kubernetes 上安装](/ee-ai-cn/start/installing-on-kubernetes.md) —— 本页涉及的 Operator 与 CSI 组件
