实例报告已完成,但 Pod 不健康

症状

kubectl get chi 显示为 Completed,但 Pod 正在重启、卡在 CrashLoopBackOff,或缺失。客户端无法连接,而实例看起来处于健康状态。

原因

status.status 描述的是 operator 的协调过程,而不是数据库的运行状态。在早期版本中,operator 提交所有对象后,该过程就会被标记为已完成,而不会等待由此产生的 Pod 变为就绪。因此,导致 Pod 永远无法启动的清单最终会处于 Completed 状态。

此版本在两个方面弥补了这一差距:

  • 协调过程只有在每个主机的 StatefulSet 报告其所需副本数均已就绪后才会完成。
  • 如果主机在协调过程完成后变得不健康,状态会被移回 InProgress,并在主机恢复后返回 Completed

因此,在此版本中,带有失败 Pod 的持久 Completed 状态是不符合预期的。看到这种情况时,应怀疑该状态描述的是早于你所应用版本的 spec 生成结果。

检查实际健康状况

始终根据工作负载进行确认:

kubectl -n <namespace> get statefulset -l clickhouse.altinity.com/chi=<instance> \
  -o custom-columns=NAME:.metadata.name,DESIRED:.spec.replicas,READY:.status.readyReplicas

kubectl -n <namespace> get pods -l clickhouse.altinity.com/chi=<instance>

每个 StatefulSet 都必须显示 READY 等于 DESIRED。这是 operator 对主机就绪状态的定义,因此无论 status 字段显示什么,该比较结果都具有权威性。

然后读取状态记录,了解 operator 最近执行了什么操作,以及最近在哪里失败:

kubectl -n <namespace> get chi <instance> -o jsonpath='{.status.status}{"\n"}'
kubectl -n <namespace> get chi <instance> -o jsonpath='{.status.errors}' | tr ',' '\n'
kubectl -n <namespace> get chi <instance> -o jsonpath='{.status.actions}' | tr ',' '\n'

这两条记录都只保留最近十条,因此应将其视为近期记录,而不是完整历史。

查找实际原因

状态过时很少是实际问题所在。请确定 Pod 无法运行的原因:

kubectl -n <namespace> describe pod <pod>
kubectl -n <namespace> logs <pod> -c clickhouse --previous
kubectl -n <namespace> get events --sort-by=.lastTimestamp | tail -30

以下三个原因涵盖了其中的大多数情况:

证据原因
ImagePullBackOffErrImagePullPod 模板指定的镜像不存在或无法拉取。
Server 立即退出,日志中存在配置错误spec.configuration.settings 下存在无效条目。无法识别的设置路径会按原样写入 Server 配置,而 Server 会拒绝启动。
OOMKilled、退出代码 137容器内存限制过小。请参阅 合并期间 Server Pod 被 OOMKilled

对于使用错误镜像的 Pod 模板,请注意 operator 会按副本应用 Pod 模板,因此一个模板中的错误镜像可能导致部分主机健康、其他主机失败——这正是产生令人困惑的整体状态的情况。

保持失败的 Pod 存活以进行检查

当 Server 退出过快而无法进行调试时,请设置 troubleshoot 标志:

kubectl -n <namespace> patch chi <instance> --type=merge -p '{"spec":{"troubleshoot":"1"}}'

随后,operator 会在入口点失败后保持容器存活,并移除存活探针和就绪探针,以便 Pod 在操作期间不会被终止。进入容器,读取 operator 生成的配置,并修复 spec:

kubectl -n <namespace> exec <pod> -c clickhouse -- \
  ls -l /etc/clickhouse-server/config.d /etc/clickhouse-server/users.d /etc/clickhouse-server/conf.d

完成后移除该标志。设置该标志期间,Pod 没有任何探针,因此实例会报告存在已就绪的主机,但这些主机实际上并未提供服务。

恢复

修复 spec 并重新应用。失败的更新默认会回滚,因此恢复导致问题的字段并重新应用是通常的解决方式。

当协调看起来卡住时,需要了解 operator 的两个默认行为:

  • 失败的 StatefulSet 更新会回滚,超时时间为五分钟,轮询间隔为五秒。
  • 失败的 StatefulSet 创建会被忽略,因此 operator 会继续处理下一个主机,而不会阻塞整个实例。

确认恢复

kubectl -n <namespace> get statefulset -l clickhouse.altinity.com/chi=<instance> \
  -o custom-columns=NAME:.metadata.name,DESIRED:.spec.replicas,READY:.status.readyReplicas
kubectl -n <namespace> exec <pod> -c clickhouse -- clickhouse-client -q "SELECT 1"

ClickHouse 是 ClickHouse, Inc. 的注册商标。https://clickhouse.com

Alauda 是独立供应商。本产品与 ClickHouse, Inc. 没有任何关联,也未获得其认可或赞助。所有商标均归其各自所有者所有,此处使用这些商标仅用于标识目的。