# 故障排除

本指南提供了一种结构化的方法来对 Kubernetes 上的 Alluxio 集群进行故障排除。它涵盖了从初始健康检查到详细诊断和常见问题恢复程序的方方面面。

## 1. 初始健康检查

当您遇到问题时，请从这些高级检查开始，以快速评估 Alluxio 集群及其依赖项的整体健康状况。

### 检查组件状态

验证所有 Alluxio 和 etcd pod 是否正在运行并处于 `READY` 状态。`Running` 状态是不够的；`READY` 列应显示 pod 中的所有容器都处于健康状态。

检查 Alluxio Coordinator pod 的就绪状态：

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

检查 Alluxio worker pod 的就绪状态：

```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
```

检查 Alluxio 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
```

您还可以使用此单行命令获取特定组件的就绪百分比：

worker 示例：

```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 %
```

### 验证 UFS 连接性

确保 Alluxio 可以与底层存储系统（UFS）通信。

运行 `ufsTest` 以检查基本的 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.
```

运行 `ufsIOTest` 以检查 UFS 读/写吞吐量：

此示例使用两个线程写入和读取一个 512MB 的文件：

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

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

没有错误的成功测试表明 UFS 可访问且配置正确。

### 通过仪表板监控关键指标

Grafana 仪表板提供了发现异常的最快方法。请关注以下关键领域：

* **活跃度**：查看 worker（`irate(alluxio_data_access_bytes_count[5m])`）和 FUSE（`alluxio_fuse_result`）的每秒请求数（RPS）。突然的、意外的峰值或下降可能表示有问题。
* **UFS 数据流**：监控 `alluxio_ufs_data_access` 和 `alluxio_ufs_error` 指标。错误增加是 UFS 连接性或权限问题的明确信号。
* **缓存命中率**：整体缓存命中率的突然下降可能表示 worker 不健康或数据访问模式发生了意外变化。

## 2. 收集详细诊断信息

如果初始健康检查未能揭示问题，您需要通过检查日志和收集完整的诊断快照来深入挖掘。

### 检查日志

#### Alluxio 进程日志

检查日志以查找特定的错误消息。

获取特定 pod 的所有日志（例如，一个 worker）：

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

过滤 WARN 或 ERROR 消息并显示匹配后的行：

```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
```

检查先前失败的容器的日志：

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

#### Kubernetes CSI 驱动程序日志

如果您怀疑 FUSE pod 挂载有问题，请检查与您的应用程序 pod 在同一 Kubernetes 节点上运行的 Alluxio CSI 节点插件的日志。

```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. 在该节点上找到 Alluxio CSI 节点插件 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. 从 csi-nodeserver 容器获取日志
kubectl -n alluxio-operator logs -c csi-nodeserver ${CSI_POD_NAME}
```

### 生成诊断快照

对于复杂问题，`doctor` 工具会收集您集群状态的全面快照，这对于离线分析或与支持团队共享非常有价值。

快照包括：

* 配置文件
* Kubernetes 节点的硬件规格
* 来自 etcd 的数据（挂载、配额等）
* 所有 Alluxio 组件的日志
* 指定时间范围内的指标
* 作业服务历史记录
* 元信息

#### 先决条件

确保 `alluxio-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
```

#### 收集快照

默认情况下，会随您的集群创建一个 `Doctor` ，每天执行一次快照。您也可以触发一次性收集或自定义计划。

要触发一次性收集，请创建一个 YAML 文件（`collect-now.yaml`）：

```yaml
apiVersion: k8s-operator.alluxio.com/v1
kind: CollectInfo
metadata:
  name: one-time-snapshot
  namespace: alx-ns
spec:
  scheduled:
    enabled: false # 当 enabled 为 false 时触发单次运行
```

然后应用它：

```shell
kubectl apply -f collect-now.yaml
```

#### 访问和下载快照

收集的快照（作为 `.tar.gz` 文件）存储在挂载到 doctor-controller pod 的卷中。

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

# 2. 列出 Doctor 内部的快照
kubectl -n alluxio-operator exec -it ${DOCTOR_NAME} -- ls /data/doctor

# 3. 将快照复制到您的本地计算机
kubectl -n alluxio-operator cp ${DOCTOR_NAME}:/data/doctor ./doctor
```

#### 快照上传（Upload）

默认情况下，Doctor 采集到的诊断结果包仅存储在集群内的 doctor-controller 相关的存储中。此外也提供了一个可选的便捷功能， 允许您将这些诊断结果自动上传到由 Alluxio 维护和分析的专用 S3 存储桶。

如果您希望 Alluxio 团队能协助您进行集群的健康状况分析，您可以启用此功能。

如何启用：

1. 请联系 Alluxio 支持团队，告知您需要开通此功能。
2. 我们将为您提供专用的 awsKey 和 awsSecret。
3. 您将这些凭证配置到 spec.upload 字段中。

一旦配置完成，采集结果将会被安全地上传。我们的团队将能够访问这些报告，帮助您进行数据分析、问题跟踪，并主动为您排查和预防潜在的集群问题。

#### 详细配置

```yaml
apiVersion: k8s-operator.alluxio.com/v1
kind: CollectInfo
metadata:
  name: example-doctor
  # 必须与 Alluxio 集群在同一个 namespace
  namespace: alx-ns
spec:
  # 设置定时采集
  scheduled:
    # false 表示立即执行一次；true 表示启用定时执行
    enabled: false
    # 仅在 enabled: true 时生效
    cron: "0 0 * * *"
    # 仅在 enabled: true 时生效
    timeZone: "Asia/Shanghai"
    # 仅在 enabled: true 时生效, 采集结果的保留时间
    expiration: "720h"

  # 采集的信息类型
  type:
    - all

  # 日志采集配置
  logs:
    # 采集过去 1 小时（3600秒）的日志
    # 注意：如果留空，默认采集过去 1 天 (86400 秒) 的日志
    sinceSeconds: 3600
    # tail: 1000 # 也可以使用 tail 采集最后 1000 行
    # sinceTime: "2025-11-12T06:00:00Z" # 也可以使用 sinceTime 采集某个时间点之后的日志

  # 指标采集配置
  metrics:
    # 采集从现在回溯 24 小时内的指标
    duration: 24h
    # 采样间隔为 5 分钟
    step: 5m

  # （可选）上传配置
  # upload:
  #   account: test
  #   productionId: xxx # 可选
  #   awsKey: <alluxio-provided-key>
  #   awsSecret: <alluxio-provided-secret>
```

#### 字段详细说明

`spec.scheduled`

用于配置定时采集任务。

* `enabled` (boolean):
  * `false` (默认): CRD 被应用 (`kubectl apply`) 后立即执行一次采集。
  * `true`: 启用定时采集，采集将按照 `cron` 表达式定义的时间循环执行。
* `cron` (string): 仅在 `enabled: true` 时生效。定义任务执行周期的 Cron 表达式。
  * 示例: `"0 0 * * *"` 表示每天的午夜执行。
  * 语法参考: [Kubernetes Cron 语法](https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/cron-jobs/#cron-schedule-syntax)
* `timeZone` (string): 仅在 `enabled: true` 时生效。定义 `cron` 表达式所基于的时区。
  * 示例: `"Asia/Shanghai"`
  * 时区参考: [Kubernetes 时区列表](https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/cron-jobs/#time-zones)
* `expiration` (string): 仅在 `enabled: true` 时生效。定义每次定时采集的结果在集群中的保留时间，过期后将被自动清理。
  * 示例: `"720h"` (保留 30 天)
  * 格式参考: [Go Duration 格式](https://golang.org/pkg/time/#ParseDuration)

`spec.type`

定义要采集的信息类型。

* `all` (默认): 如果不指定 `type` 字段，或者指定为 `all`，将采集以下所有信息。
* 指定一个或多个类型:
  * `config`: Alluxio 配置信息。
  * `hardware`: 节点硬件信息。
  * `etcd`: Etcd 中存储的信息。
  * `job-history`: Job 历史记录。
  * `logs`: Coordinator, Worker, FUSE 等组件的日志。
  * `metrics`: Alluxio 各组件的 Prometheus 指标。

`spec.logs`

定义日志采集的范围，基于 Kubernetes 的 `PodLogOptions`。 参考： [Kubernetes PodLogOptions](https://pkg.go.dev/k8s.io/api/core/v1#PodLogOptions)

* **默认行为:** 如果 `logs` 字段**完全留空**或不配置，Operator 将默认采集**过去 1 天 (86400 秒)** 的日志。
* `tail` :
  * 采集每个容器日志的最后 N 行。
  * 示例: `1000` (采集最后 1000 行)。
* `sinceSeconds` :
  * 采集从现在回溯 N 秒内的日志。
  * 示例: `3600` (采集过去 1 小时)。
* `sinceTime` :
  * 采集某个绝对时间点 (RFC3339 格式) 之后的日志。
  * 示例: `"2025-11-12T06:00:00Z"` (采集 UTC 时间 11月12日早上6点之后的日志)。
* **采集规则:**
  1. `tail` 具有最高优先级, 当 `tail` 被设置时，`sinceSeconds` 和 `sinceTime` 字段将被忽略。
  2. 仅在 `tail` 未设置时，`sinceSeconds` 或 `sinceTime` 才会生效，但是只能设置其中一个。
  3. 默认行为 (如果全部留空)，将采集过去 1 天 (86400 秒) 的日志。

`spec.metrics`

定义 Prometheus 指标的采集范围。

* `duration` (string): 采集从“现在”开始回溯的时长。
  * 示例: `24h` (采集过去24小时的指标)。
* `step` (string): 采集的时间间隔（采样精度）。
  * 示例: `1m` (每分钟采样一次)。

`spec.upload` (可选)

提供将采集结果（压缩包）自动上传到 Alluxio 提供的 AWS S3 存储桶的方式。

* **默认行为:** 如果不配置 `upload` 块，采集到的信息（"doctor"的结果）将**不会**被自动上传。您需要手动从 Operator 的 Pod 或其挂载的存储中获取结果。（*注：这里你需要根据实际情况确认结果的本地存储位置并补充说明*）。
* `account` (string): 必须。Alluxio 提供的账户信息。
* `productionId` (string): 可选。用于标识客户环境的产品 ID。
* `awsKey` (string): 必须。Alluxio 提供的 AWS Access Key。
* `awsSecret` (string): 必须。Alluxio 提供的 AWS Secret Key。

## 3. 常见问题和恢复程序

以下是针对常见组件故障的逐步恢复指南。

### Coordinator 故障

Coordinator 运行 Alluxio 异步任务服务，该服务负责管理异步任务，例如用于缓存预加载任务。它会持久化其任务历史记录，并可在重启后恢复其状态。Kubernetes 将自动重启失败的Coordinator pod。如果作业历史记录损坏，任何未完成的作业可能会丢失，需要重新提交。

### Worker 故障

Alluxio 被设计为对 worker 故障具有弹性。如果 worker pod 失败，Kubernetes 将自动重启它。该 worker 上缓存中存储的数据将丢失，但这不会导致 I/O 操作失败（尽管可能会暂时降低性能，因为数据需要重新获取）。

### FUSE 故障

如果 FUSE pod 崩溃或变得无响应，它将由其控制器（DaemonSet 或 CSI 驱动程序）自动重启。如果 FUSE pod 挂起，您可以强制重启：

```shell
# 手动删除 pod 以触发重启
kubectl delete pod <fuse-pod-name>
```

### ETCD 故障

Alluxio 有一个宽限期（通常为 24 小时）来容忍 etcd 故障而不会中断 I/O。如果集成的 etcd 集群失败且无法通过简单的 pod 重启来恢复，您可能需要重建它。

**警告：这是一个破坏性操作，只应作为最后手段执行。**

1. **关闭 Alluxio 集群：** `kubectl delete -f alluxio-cluster.yaml`
2. **删除原始的 etcd PVC：** `kubectl -n alx-ns delete pvc -l app.kubernetes.io/component=etcd`
3. **清除节点上的 etcd 数据：** 手动登录到托管 etcd pod 的每个 Kubernetes 节点，并删除 etcd PV 使用的主机路径目录的内容。
4. **重新创建集群：** `kubectl create -f alluxio-cluster.yaml`。operator 将配置一个新的、空的 etcd 集群。
5. **重新挂载 UFS 路径：** 如果您没有使用 `UnderFileSystem` CRD 来管理挂载，您将需要使用 `alluxio fs mount` 手动重新添加它们。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://documentation.alluxio.io/ee-ai-cn/ai-3.8-15.1.x-cn/administration/troubleshooting-alluxio.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
