首页
/ MinIO 健康检查端点全解:Liveness、Readiness 与 Cluster 探活机制的实战指南

MinIO 健康检查端点全解:Liveness、Readiness 与 Cluster 探活机制的实战指南

2026-09-04 22:16:51作者:宗隆裙

MinIO 在无认证状态下暴露了五个健康检查端点(/minio/health/live/minio/health/ready/minio/health/cluster/minio/health/cluster/read),它们是 Kubernetes 编排、服务网格流量治理与节点下线维护的核心探测入口。本文基于仓库文档 docs/metrics/healthcheck/README.md,逐端点解析其探测语义、返回码规则、响应头信息,并结合 cmd/healthcheck-handler.gocmd/healthcheck-router.gocmd/erasure-server-pool.go 的源码实现,讲清每个端点"什么时候返回 200、什么时候返回 503/412/503 Busy",以及维护模式下如何安全地把一个 MinIO 节点从集群中摘除。

端点总览与路由注册

MinIO 的健康检查端点全部挂载在保留桶路径前缀 /minio/health 之下。该前缀来自保留桶名 miniominioReservedBucket = "minio",见 cmd/generic-handlers.go 第 144-145 行)。路由注册在 cmd/healthcheck-router.go 中完成:

const (
    healthCheckPath            = "/health"
    healthCheckLivenessPath    = "/live"
    healthCheckReadinessPath   = "/ready"
    healthCheckClusterPath     = "/cluster"
    healthCheckClusterReadPath = "/cluster/read"
    healthCheckPathPrefix      = minioReservedBucketPath + healthCheckPath
)

每个端点同时注册了 GETHEAD 两种方法(便于 Kubernetes 用 httpGet 探活),并统一包裹了 httpTraceAll 中间件。这些端点不需要任何认证凭据,可以直接用 curl 或负载均衡器的健康检查任务访问:

端点 方法 语义 成功 失败
/minio/health/live GET / HEAD 存活探测(liveness) 200 503(服务未初始化/过载)
/minio/health/ready GET / HEAD 就绪探测(readiness) 200 503(etcd/KMS 不可达、过载)
/minio/health/cluster GET / HEAD 集群多数派探测 200 503(维护模式为 412)
/minio/health/cluster/read GET / HEAD 集群多数派探测 200 503(维护模式为 412)

Liveness 探测:/minio/health/live

文档对 liveness 的定义是:该端点总是返回 200 OK,只有在配置了 etcd 且 etcd 不可达时才会失败;探测失败时,Kubernetes 等平台会重启容器。配套的 Kubernetes 探针配置为:

livenessProbe:
  httpGet:
    path: /minio/health/live
    port: 9000
    scheme: HTTP
  initialDelaySeconds: 120
  periodSeconds: 30
  timeoutSeconds: 10
  successThreshold: 1
  failureThreshold: 3

各参数含义:initialDelaySeconds: 120 给 MinIO 留出启动与元数据初始化的时间;periodSeconds: 30 是探测周期;timeoutSeconds: 10 是单次探测超时;failureThreshold: 3 意味着连续 3 次失败(即 90 秒)才会触发容器重启。

源码层面,cmd/healthcheck-handler.go 中的 LivenessCheckHandler 比文档描述的检查逻辑更完整:

  1. 对象层未就绪newObjectLayerFn() 返回 nil 时,响应头写入 x-minio-server-status: offline,表明服务尚未初始化完成;
  2. 节点间互调豁免:如果请求带有 MinIO 内部节点间调用的标记头(MinIOPeerCall),直接返回 200,避免内部探测被负载状态干扰;
  3. 请求队列过载:当前排队中的 S3 请求数 globalHTTPStats.loadRequestsInQueue() 超过 API 并发池容量 globalAPIConfig.getRequestsPoolCapacity() 时,返回 ErrBusy(HTTP 503)。这是一个保护机制——进程活着但已无法承接新请求时,编排平台应介入;
  4. 以上均通过则返回 200 OK

值得注意的是源码注释明确指出:liveness 与 readiness 的关键差异在于 liveness 失败会导致 Pod 重启,因此它刻意不联系任何外部系统(如 KMS),只检查本进程的存活与负载状态。

Readiness 探测:/minio/health/ready

Readiness 探测用于决定流量是否应该路由到该容器——文档说明失败时 Kubernetes 会关闭对该容器的路由。Kubernetes 探针配置:

readinessProbe:
  httpGet:
    path: /minio/health/ready
    port: 9000
    scheme: HTTP
  initialDelaySeconds: 120
  periodSeconds: 15
  timeoutSeconds: 10
  successThreshold: 1
  failureThreshold: 3

与 liveness 相比,readiness 的探测周期更短(periodSeconds: 15),因为它的失败后果只是摘除流量(而非重启),探测可以更密集。

ReadinessCheckHandlercmd/healthcheck-handler.go)在过载检查之外,还额外执行两类外部依赖检查:

  • KMS 可达性:如果配置了 KMS(GlobalKMS != nil),会在 1 分钟超时内调用 GenerateKey 做一次密钥生成测试;失败则返回对应的 API 错误码。这保证挂载加密桶的对象流量不会被路由到无法解密的节点;
  • etcd 可达性:如果配置了 etcd(globalEtcdClient != nil),会以 defaultContextTimeout 的超时执行一次 Get("health")(借鉴 etcdctl 的 endpoint health 命令实现);不可达则返回错误,这正是文档所说"Only fails if etcd is configured and unreachable"的出处。

此外,与 liveness 相同的过载保护(队列长度超过并发池容量即返回 503 Busy)在 readiness 中同样生效。GET 请求会返回完整的 S3 风格 XML 错误体,HEAD 请求则只带状态码。

Cluster 探测:/minio/health/cluster(写多数派)

集群级探测回答的问题是:接收请求的这个节点所在集群,当前是否还具备对象写入能力? 集群具备写多数派(write quorum)时返回 200 OK,否则返回 503 Service Unavailable。文档给出的 503 示例:

curl http://minio1:9001/minio/health/cluster
HTTP/1.1 503 Service Unavailable
Accept-Ranges: bytes
Content-Length: 0
Server: MinIO
Vary: Origin
X-Amz-Bucket-Region: us-east-1
X-Minio-Write-Quorum: 3
X-Amz-Request-Id: 16239D6AB80EBECF
X-Xss-Protection: 1; mode=block
Date: Tue, 21 Jul 2020 00:36:14 GMT

ClusterCheckHandlercmd/healthcheck-handler.go)的执行流程:

  1. 先经 checkHealth(w) 做前置检查:对象层未初始化返回 503 并带 x-minio-server-status: offlineglobalBucketMetadataSysglobalIAMSys 未完成初始化时,分别返回 x-minio-server-status: bucket-metadata-offlineiam-offlinecmd/healthcheck-handler.go);
  2. 给探测上下文加上 globalAPIConfig.getClusterDeadline() 超时,默认 10 秒(可经 API 子系统的 cluster_deadline 配置项 / 环境变量 MINIO_API_CLUSTER_DEADLINE 调整,默认值 "10s",见 internal/config/api/api.gocmd/handler-api.go);
  3. 解析查询参数 maintenance(布尔)与 deployment-type,调用对象层的 Health(ctx, opts) 得到 HealthResult
  4. 无论健康与否,都会写入三个响应头:
    • x-minio-write-quorum:该集群要求的写多数派数量(示例中为 3);
    • x-minio-storage-class-defaults:当配置加载失败而使用默认存储类时为 true
    • x-minio-healing-drives:有盘正在纠删自愈时返回其数量;
  5. 不健康时:普通探测返回 503 Service Unavailable,维护模式(?maintenance=true)返回 412 Precondition Failed

多数派判定的源码逻辑

真正的多数派计算在 erasureServerPools.Healthcmd/erasure-server-pool.go)中完成,其核心算法值得展开:

  • 调用 StorageInfo(ctx, false) 拿到全集群所有盘的在线状态,按"池(pool)→ 纠删集(set)"维度统计每个集合中 DriveStateOk 的在线盘数 online 与正在自愈的盘数 healing
  • BackendInfo() 读取每个池的 StandardSCData(数据盘数 N)与 StandardSCParity(奇偶校验数 W)。读多数派 = N写多数派 = N;若 N == W(即无校验的极限配置),写多数派取 N+1;
  • 对每个池、每个纠删集分别判断:online >= 写多数派 决定该集的写健康,online >= 读多数派 决定读健康;任一个纠删集不满足,则整个集群标记为不健康result.Healthy 为各集结果的 AND);
  • 写健康日志级别是 logger.FatalKind,读健康是普通告警,二者都会记录"期望多数派 vs 在线盘数",便于排障。

以常见的 4 数据盘 + 2 校验盘纠删集为例,读多数派为 4、写多数派为 4,即每个纠删集至少 4 块盘在线,集群探测才返回 200。

Cluster 读探测:/minio/health/cluster/read

/minio/health/cluster/read 与写探测共用同一套 Health 计算,但判定的是读多数派:具备读多数派返回 200 OK,否则 503 Service Unavailable(维护模式下为 412):

curl http://minio1:9001/minio/health/cluster/read
HTTP/1.1 503 Service Unavailable
Accept-Ranges: bytes
Content-Length: 0
Server: MinIO
Vary: Origin
X-Amz-Bucket-Region: us-east-1
X-Minio-Write-Quorum: 3
X-Amz-Request-Id: 16239D6AB80EBECF
X-Xss-Protection: 1; mode=block
Date: Tue, 21 Jul 2020 00:36:14 GMT

ClusterReadCheckHandlercmd/healthcheck-handler.go)与写探测的差异在于:判定条件使用 result.HealthyRead,响应头写的是 x-minio-read-quorum 而非 x-minio-write-quorum。由于读多数派要求不低于写多数派(多数配置下两者相等),该端点适合让只读客户端(如报表、备份读)独立探测集群的读服务能力。

维护模式:安全地把节点下线

这是文档中最实用的场景:下线某节点做维护之前,先向该节点询问"你可以被关机吗"。 查询方式为在集群探测上附加 maintenance=true

curl http://minio1:9001/minio/health/cluster?maintenance=true
HTTP/1.1 412 Precondition Failed
Accept-Ranges: bytes
Content-Length: 0
Server: MinIO
Vary: Origin
X-Amz-Bucket-Region: us-east-1
X-Amz-Request-Id: 16239D63820C6E76
X-Xss-Protection: 1; mode=block
X-Minio-Write-Quorum: 3
Date: Tue, 21 Jul 2020 00:35:43 GMT
  • 返回 412 Precondition Failed下线该节点将导致集群失去写多数派(失去 HA),不要下线
  • 返回 200 OK:下线后集群仍满足多数派要求,可以安全执行维护。

源码揭示了维护模式的两个额外语义(cmd/erasure-server-pool.go):

  1. 排除本节点自身的盘Health 计算时,若 opts.Maintenance 为真,会把落在 globalLocalDrivesMap 中(即本机持有的盘)的盘从统计中剔除,模拟"本节点消失后"的集群状态再判断多数派——这正是文档所说"check if the node which received the request can be taken down for maintenance"的实现;
  2. 自愈中的盘会使维护探测失败opts.Maintenance 下还额外要求 drivesHealing == 0(有盘正在纠删自愈则 Healthy/HealthyRead 一并置假,并通过 x-minio-healing-drives 头报告自愈盘数)。若同时指定 deployment-type=vmware,还会记录自愈盘总数到日志——这是针对 vSphere 场景的额外观测点。

因此推荐的维护流程是:对目标节点执行 curl http://<node>:9000/minio/health/cluster?maintenance=true,得到 200 后再执行停止操作;得到 412 则说明当前节点不可摘除,应等待其他盘恢复或扩盘后再试。

配置与运行前提小结

围绕这些端点,源码中可以确认的运行前提与可调参数:

项目 说明 依据
端点前缀 全部位于保留路径 /minio/health/...,无需认证 cmd/healthcheck-router.go
支持方法 GET 与 HEAD,HEAD 仅回状态码,GET 失败时回 S3 风格错误体 cmd/healthcheck-handler.go
集群探测超时 默认 10 秒,可经 cluster_deadline / MINIO_API_CLUSTER_DEADLINE 调整 internal/config/api/api.gocmd/handler-api.go
过载保护 排队请求超过 API 并发池容量时,live/ready 返回 503(ErrBusy) cmd/healthcheck-handler.go
etcd / KMS 检查 仅 readiness 端点执行,且仅在相应组件已配置时执行 cmd/healthcheck-handler.go
维护模式 ?maintenance=true 剔除本节点盘并要求无盘自愈中;不安全时返回 412 cmd/erasure-server-pool.go

需要说明的适用前提:以上行为以当前仓库源码为准。liveness 在"对象层未初始化、请求队列过载"等情况下也会失败,这是文档"always responds with 200 OK"之外的补充事实,来源为 LivenessCheckHandler 的实现;deployment-type 参数目前仅在 VMware 场景产生额外日志行为(从源码结构看)。

小结

MinIO 的健康检查体系分为三个层次:进程层(live——进程是否活着且不过载)、就绪层(ready——外部依赖 etcd/KMS 是否可用)、集群层(cluster/cluster read——纠删集是否满足写/读多数派)。三层分别对应 Kubernetes 的 livenessProbe、readinessProbe 和服务网格/负载均衡的集群级健康治理;而 ?maintenance=true 的 412/200 语义则为节点滚动维护提供了明确的安全性判据。掌握各端点的返回码、x-minio-write-quorum 等响应头以及 cluster_deadline 超时配置,就足以在编排环境中完成对 MinIO 集群的完整健康治理。

登录后查看全文
热门项目推荐
相关项目推荐