解决 ceph warn: pool <pool name> has too few pgs

本文分析了Ceph集群中因pool的PG数量不足导致的HEALTH_WARN警告问题,介绍了问题产生的原因,并提供了三种解决方案:增加PG数、删除多余pool及调整阈值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

pool xxx has too few pgs

  • 问题:
root@node-3:~# ceph -s
    cluster 04bb3d14-acee-431e-88cd-7256bccd10a1
     health HEALTH_WARN
            pool images has too few pgs
     monmap e1: 1 mons at {node-3=10.10.10.2:6789/0}
            election epoch 1, quorum 0 node-3
     osdmap e63: 4 osds: 4 up, 4 in
      pgmap v299609: 1636 pgs, 13 pools, 82237 MB data, 11833 objects
            90099 MB used, 14804 GB / 14892 GB avail
                1636 active+clean
  client io 0 B/s rd, 3478 B/s wr, 2 op/s
root@node-3:~# ceph osd pool get images pg_num   
pg_num: 100
root@node-3:~# ceph df
GLOBAL:
    SIZE       AVAIL      RAW USED     %RAW USED 
    14892G     14804G       90099M          0.59 
POOLS:
    NAME                   ID     USED       %USED     MAX AVAIL     OBJECTS
    rbd                    0           0         0        14791G           0
    .rgw                   1         394         0        14791G           2
    images                 2      64278M      0.42        14791G        8049
    volumes                3       3016M      0.02        14791G         814
    backups                4           0         0        14791G           0
    compute                5      14942M      0.10        14791G        2915
    .rgw.root              6         848         0        14791G           3
    .rgw.control           7           0         0        14791G           8
    .rgw.gc                8           0         0        14791G          32
    .users.uid             9         778         0        14791G           4
    .users                 10         14         0        14791G           1
    .rgw.buckets.index     11          0         0        14791G           1
    .rgw.buckets           12       300k         0        14791G           4
root@node-3:~# ceph osd pool ls detail
pool 0 'rbd' replicated size 1 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 64 pgp_num 64 last_change 1 flags hashpspool stripe_width 0
pool 1 '.rgw' replicated size 1 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 128 pgp_num 128 last_change 2 flags hashpspool stripe_width 0
pool 2 'images' replicated size 1 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 100 pgp_num 100 last_change 62 flags hashpspool stripe_width 0
        removed_snaps [1~3]
pool 3 'volumes' replicated size 1 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 512 pgp_num 512 last_change 50 flags hashpspool stripe_width 0
        removed_snaps [1~3]
pool 4 'backups' replicated size 1 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 128 pgp_num 128 last_change 24 flags hashpspool stripe_width 0
pool 5 'compute' replicated size 1 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 256 pgp_num 256 last_change 42 flags hashpspool stripe_width 0
        removed_snaps [1~3]
pool 6 '.rgw.root' replicated size 1 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 64 pgp_num 64 last_change 28 owner 18446744073709551615 flags hashpspool stripe_width 0
pool 7 '.rgw.control' replicated size 1 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 64 pgp_num 64 last_change 30 owner 18446744073709551615 flags hashpspool stripe_width 0
pool 8 '.rgw.gc' replicated size 1 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 64 pgp_num 64 last_change 32 owner 18446744073709551615 flags hashpspool stripe_width 0
pool 9 '.users.uid' replicated size 1 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 64 pgp_num 64 last_change 34 owner 18446744073709551615 flags hashpspool stripe_width 0
pool 10 '.users' replicated size 1 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 64 pgp_num 64 last_change 39 owner 18446744073709551615 flags hashpspool stripe_width 0
pool 11 '.rgw.buckets.index' replicated size 1 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 64 pgp_num 64 last_change 51 owner 18446744073709551615 flags hashpspool stripe_width 0
pool 12 '.rgw.buckets' replicated size 1 min_size 1 crush_ruleset 0 object_hash rjenkins pg_num 64 pgp_num 64 last_change 53 owner 18446744073709551615 flags hashpspool stripe_width 0
  • 分析解决:

    1. 源码分析:
      在源码中搜索has too few pgs就定位到了mon/PGMonitor.cc中的get_health函数,代码块如下。在master版本中没有搜到,后来切换到0.94.6中,搜索到了;master中是“ pool images has many more objects per pg than average (too few pgs?)”
    2. 源码流程:
      1. 先从pg_map中取所有的pool的总的objects num,然后取所有pool的pg num, 然后计算average_objects_per_pg,这个是指整个集群中的所有objects和所有的pg的比率,也就是整个集群中每个pg有多少个objects;
      2. 取每个pool的objects num,然后取每个pool的pg num,然后计算objects_per_pg,这个值是每个pool中objects和pg的比率,也就是这个pool中每个pg有多少个objects.
      3. 计算ratio=objects_per_pg / average_objects_per_pg,这个比率是pool和集群平均值的比率。
      4. 取配置文件中的mon_pg_warn_max_object_skew这个参数的值,(默认为10)。
      5. 比较ratio和mon_pg_warn_max_object_skew这个参数值,然后就会出现了问题中的Health_warn警告。
  • 源码:

if (!pg_map.pg_stat.empty()) 
  for (ceph::unordered_map<int,pool_stat_t>::const_iterator p = pg_map.pg_pool_sum.begin();
       p != pg_map.pg_pool_sum.end();
       ++p) {
    const pg_pool_t *pi = mon->osdmon()->osdmap.get_pg_pool(p->first);
    if (!pi)
      continue;   // in case osdmap changes haven't propagated to PGMap yet
    if (pi->get_pg_num() > pi->get_pgp_num()) {
      ostringstream ss;
      ss << "pool " << mon->osdmon()->osdmap.get_pool_name(p->first) << " pg_num "
         << pi->get_pg_num() << " > pgp_num " << pi->get_pgp_num();
      summary.push_back(make_pair(HEALTH_WARN, ss.str()));
      if (detail)
        detail->push_back(make_pair(HEALTH_WARN, ss.str()));
    }
    int average_objects_per_pg = pg_map.pg_sum.stats.sum.num_objects / pg_map.pg_stat.size();
    if (average_objects_per_pg > 0 &&
        pg_map.pg_sum.stats.sum.num_objects >= g_conf->mon_pg_warn_min_objects &&
        p->second.stats.sum.num_objects >= g_conf->mon_pg_warn_min_pool_objects) {
      int objects_per_pg = p->second.stats.sum.num_objects / pi->get_pg_num();
      float ratio = (float)objects_per_pg / (float)average_objects_per_pg;
      if (g_conf->mon_pg_warn_max_object_skew > 0 &&
          ratio > g_conf->mon_pg_warn_max_object_skew) {
        ostringstream ss;
        ss << "pool " << mon->osdmon()->osdmap.get_pool_name(p->first) << " has too few pgs";
        summary.push_back(make_pair(HEALTH_WARN, ss.str()));
        if (detail) {
          ostringstream ss;
          ss << "pool " << mon->osdmon()->osdmap.get_pool_name(p->first) << " objects per pg ("
             << objects_per_pg << ") is more than " << ratio << " times cluster average ("
             << average_objects_per_pg << ")";
          detail->push_back(make_pair(HEALTH_WARN, ss.str()));
        }
      }
    }

解决:
1. 增加相应pool的pg数
2. 删除多余的无用的pool,所以在ceph cluster中创建测试pool的时候,不要给太多的pg。
3. 修改mon_pg_warn_max_object_skew参数值,增加这个值,提高阈值。

<think>嗯,用户之前已经问过关于在单节点集群部署Ceph时遇到的问题,现在他们提供了更多的信息,特别是`kubectl describe cephblockpool`的输出。我需要仔细分析这些信息,看看问题出在哪里。 首先,用户执行了`kubectl describe cephblockpool replicapool -n rook-ceph`,结果显示配置中的`Failure Domain`是osd,副本大小size是2,这应该是正确的,因为用户有两个OSD。但是`kubectl get cephblockpool`显示PHASE是空的,AGE是2分12秒。可能意味着存储池没有正确进入Ready阶段,或者处于Pending状态。 根据之前的建议,用户已经调整了size为2,并且failureDomain设置为osd,这应该满足单节点两个OSD的条件。但为什么PHASE还是空的呢?可能需要检查Ceph集群的状态,特别是OSD是否正常运行,以及是否有其他配置问题。 接下来,用户可能没有看到任何事件(Events: <none>),这可能意味着问题不在BlockPool本身,而在底层Ceph集群。可能需要检查Ceph的健康状态,或者Operator的日志。例如,Ceph可能因为PG数量不足或配置问题而无法创建存储池。 另外,用户提到单节点集群运行了3个mon,这可能导致资源竞争或配置问题,尤其是在单节点环境下运行多个mon可能并不推荐。不过,根据Rook的文档,单节点部署可能需要特定的配置,例如使用HostNetwork或者调整mon的副本数。 可能还需要检查存储池的PG(Placement Group)数量是否正确设置。默认情况下,如果没有指定pg_num和pgp_num,Rook可能会设置一个默认值,但可能在单节点环境下需要调整。例如,如果PG数量设置过高,而OSD数量不足,可能导致无法分配。 此外,用户的Ceph版本和Rook版本是否兼容也是一个可能的问题点。如果版本不匹配,可能会导致一些功能无法正常工作。 最后,用户可能需要进一步检查Operator的日志,查看是否有关于创建存储池时的错误信息。例如,执行`kubectl logs -n rook-ceph -l app=rook-ceph-operator`来获取更多线索。 总结起来,用户已经按照建议调整了配置,但问题仍然存在,需要进一步检查Ceph集群的健康状态、PG设置、版本兼容性以及Operator日志中的错误信息。</think>根据您提供的完整配置信息,存储池处于无状态且未完成创建的问题需要深入排查。以下是关键分析步骤: --- ### 一、配置合理性验证 从YAML配置看参数已符合单节点要求: ```yaml spec: failureDomain: osd # ✅ 正确设置为osd层级 replicated: size: 2 # ✅ 与2个OSD匹配 requireSafeReplicaSize: false # ✅ 允许降级副本 ``` **理论上该配置应能正常工作**,但实际未进入`Ready`阶段,需进一步排查。 --- ### 二、核心故障排查链 #### 1. 检查Ceph集群健康状态 ```bash kubectl exec -n rook-ceph deploy/rook-ceph-tools -- ceph -s ``` 重点关注以下输出字段: ```text health: HEALTH_OK? osdmap: osd: 2 osds: 2 up, 2 in pgmap: pgs: ... active+clean? ``` #### 2. 验证OSD实际分布 ```bash kubectl exec -n rook-ceph deploy/rook-ceph-tools -- ceph osd tree ``` 预期输出应包含: ```text ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT -1 0.02939 root default -3 0.02939 host master01 # 单节点下所有OSD在同一host 0 hdd 0.01469 osd.0 up 1.00000 1 hdd 0.01469 osd.1 up 1.00000 ``` #### 3. PG数量配置检查 通过以下命令查看存储池详情: ```bash kubectl exec -n rook-ceph deploy/rook-ceph-tools -- ceph osd pool get replicapool all ``` 重点关注参数: ```text pg_num: 128 # 若此值过高会导致PG无法分布 pgp_num: 128 ``` --- ### 三、典型问题场景分析 #### ❌ 场景1:PG数量设置过高 **症状**: 在仅有2个OSD的环境下,若`pg_num`超过OSD承载能力(如默认值128),会导致PG无法完成`active+clean`状态。 **解决方案**: 修改存储池定义,强制指定较低PG数: ```yaml spec: parameters: pg_num: "32" # 单节点推荐值= (Total_OSDs * 100)/副本数 ≈ 2*100/2=100 → 取32或64 pgp_num: "32" ``` #### ❌ 场景2:CRUSH Map配置错误 **症状**: 虽然配置了`failureDomain=osd`,但CRUSH规则未正确生成。 **验证方法**: ```bash kubectl exec -n rook-ceph deploy/rook-ceph-tools -- ceph osd crush rule ls ``` 正常应看到与存储池关联的规则(如`replicated_rule`)。 **修复措施**: 删除并重建存储池(需先备份数据): ```bash kubectl delete cephblockpool replicapool -n rook-ceph kubectl apply -f modified-pool.yaml ``` --- ### 四、高级诊断指令 #### 1. 实时监控存储池创建进度 ```bash watch -n 2 'kubectl exec -n rook-ceph deploy/rook-ceph-tools -- ceph osd pool stats replicapool' ``` 正常创建过程应显示`creating`状态及进度百分比。 #### 2. 检查Rook Operator日志 ```bash kubectl logs -n rook-ceph -l app=rook-ceph-operator --tail=200 | grep -i "block pool" ``` 典型错误日志模式: ```text failed to create pool: [ERR] ... # 具体错误描述 ``` --- ### 五、单节点优化参数建议 | 参数 | 推荐值 | 作用 | |---------------------|--------|----------------------------------------------------------------------| | `metadataService` | 关闭 | 单节点无需冗余元数据服务 | | `skipPoolCreate` | false | 确保Operator主动创建池 | | `preservePoolsOnDelete` | true | 防止误删配置 | 完整优化示例: ```yaml apiVersion: ceph.rook.io/v1 kind: CephBlockPool metadata: name: replicapool namespace: rook-ceph spec: failureDomain: osd replicated: size: 2 requireSafeReplicaSize: false parameters: pg_num: "32" pgp_num: "32" preservePoolsOnDelete: true ``` --- ### 六、重建存储池操作流程 如果诊断确认配置无误但仍无法创建,建议强制重建: ```bash # 1. 删除残留配置 kubectl delete cephblockpool replicapool -n rook-ceph --wait=false kubectl patch cephblockpool replicapool -n rook-ceph -p '{"metadata":{"finalizers":[]}}' --type=merge # 2. 清理底层数据(危险!确认无数据后再执行) kubectl exec -n rook-ceph deploy/rook-ceph-tools -- ceph osd pool rm replicapool replicapool --yes-i-really-really-mean-it # 3. 应用新配置 kubectl apply -f optimized-pool.yaml ``` --- 请根据上述步骤执行后提供以下信息以便进一步分析: 1. `ceph -s`完整输出 2. Operator日志中与存储池相关的错误片段 3. `ceph osd pool ls detail`的输出内容
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值