分类 Ceph 下的文章

Ceph 性能差通常不是单点问题,是从内核到应用一系列设置叠加的结果。本文给一个我经常用的 checklist。

1. 内核 / 系统层

# 文件描述符
echo "* soft nofile 1048576" >> /etc/security/limits.conf
echo "* hard nofile 1048576" >> /etc/security/limits.conf

# 内核网络 buffer
sysctl -w net.core.rmem_max=268435456
sysctl -w net.core.wmem_max=268435456
sysctl -w net.ipv4.tcp_rmem="4096 87380 268435456"
sysctl -w net.ipv4.tcp_wmem="4096 65536 268435456"

# 关闭 transparent hugepage(OSD 内存碎片元凶)
echo never > /sys/kernel/mm/transparent_hugepage/enabled

2. 磁盘 / IO 调度

# NVMe / SSD 用 none 调度器
echo none > /sys/block/nvme0n1/queue/scheduler

# HDD 用 mq-deadline
echo mq-deadline > /sys/block/sdb/queue/scheduler

# 关闭 readahead 对 OSD 是反优化(OSD 自己管缓存)
blockdev --setra 0 /dev/sdb

3. 网络层

  • MTU 9000:jumbo frame 对 Ceph 复制流量收益巨大,但要全链路 9000
  • bond mode=4 (LACP):交换机配 LAG,单流也能跑多端口
  • public/cluster 分离:上面说过

4. Ceph 配置

# OSD 内存上限(按物理内存 70% / OSD 数)
ceph config set osd osd_memory_target 4G

# bluestore 缓存(默认对 SSD 偏小)
ceph config set osd bluestore_cache_size_ssd 4G
ceph config set osd bluestore_cache_size_hdd 2G

# 并发
ceph config set osd osd_op_num_shards 8
ceph config set osd osd_op_num_threads_per_shard 2

5. Pool 层

  • PG 数量:每 OSD 100-150 个 PG 是甜点,少了并发不够,多了元数据压力大
  • EC 还是副本:冷数据 EC 8+3,热数据 size=3 副本
  • min_size:副本池别设成 1,掉一个 OSD 就丢数据

6. 客户端

  • RBD:开 librbd cache rbd_cache=true
  • CephFS:客户端缓存 client_cache_size=1GiB
  • RGW:开 civetweb/beast 的 keep-alive

实测怎么 baseline

# RADOS 层基准
rados bench -p test 60 write -t 32
rados bench -p test 60 seq

# RBD 层
rbd bench --io-type write --io-size 4K --io-threads 16 --io-total 10G test/bench

调优前后跑同样的 bench,差异肉眼可见。

教训:Ceph 调优最大的坑是"调一个看一个"——很多参数会互相干扰,建议每次只改一个,跑 bench 对比。

默认 CRUSH 把数据按 host 分布,但生产经常需要按机架、机房分布做高可用。本文示范从默认改到机架感知的完整流程。

默认 CRUSH 长啥样

ceph osd tree

输出大概:

ID  CLASS  WEIGHT   TYPE NAME
-1         12.0     root default
-2         4.0          host node1
 0   hdd   1.0              osd.0
 ...

只有 root → host → osd 三层。

加 rack 一层

# 创建 rack
ceph osd crush add-bucket rack1 rack
ceph osd crush add-bucket rack2 rack

# 把 host 移到对应 rack 下
ceph osd crush move node1 rack=rack1
ceph osd crush move node2 rack=rack1
ceph osd crush move node3 rack=rack2

# 把 rack 挂到 root
ceph osd crush move rack1 root=default
ceph osd crush move rack2 root=default

改规则 — 副本跨机架

# 导出默认 rule
ceph osd getcrushmap -o /tmp/crush.bin
crushtool -d /tmp/crush.bin -o /tmp/crush.txt

# 改 rule,把 step chooseleaf type host 改成 type rack
vi /tmp/crush.txt

改完编译回去:

crushtool -c /tmp/crush.txt -o /tmp/crush.new
ceph osd setcrushmap -i /tmp/crush.new

验证

ceph pg dump | awk '/active+clean/ {print $1, $15}' | head
# 看 acting set 里的 OSD 是不是真的跨 rack 了

一个常见坑

如果 rack 数量 < pool 副本数(比如只有 2 个 rack 但 size=3),改完规则后 PG 会变 undersized。要么加 rack,要么把 size 降到 rack 数量。

进阶:upmap 平衡器

CRUSH 是伪随机,分布不可能完全均匀。打开 upmap 平衡器:

ceph balancer mode upmap
ceph balancer on

它会自动微调 PG 位置,把不均匀度降到 5% 以内。Nautilus 以上默认就是 upmap。

为什么用 cephadm 而不是 ceph-ansible

Nautilus 之后官方主推 cephadm,原因是它只依赖 SSH + container runtime,部署比 ansible 简洁很多。生产推荐直接上 cephadm,老的 ceph-deploy/ceph-ansible 维护不动了。

引导(bootstrap)

# 引导节点上
curl --silent --remote-name --location https://github.com/ceph/ceph/raw/quincy/src/cephadm/cephadm
chmod +x cephadm
./cephadm add-repo --release quincy
./cephadm install
cephadm bootstrap --mon-ip <第一个MON的IP> --initial-dashboard-password 'YourPassword'

引导完成会输出 dashboard URL 和 admin 凭据。

加节点 + 加 OSD

# 把其他节点加入集群
ceph orch host add node2 <node2-ip> _admin
ceph orch host add node3 <node3-ip>

# 自动发现并使用所有未用的盘
ceph orch apply osd --all-available-devices

# 或精确指定
ceph orch daemon add osd node2:/dev/sdb

第一周必做清单

  1. 改时间同步:所有节点 chronyd,偏移 >50ms MON 会闹脾气
  2. 关闭 swapswapoff -a + 注释 fstab
  3. public_network / cluster_network 分离:业务流量和复制流量分开物理网卡
  4. mon_max_pg_per_osd 调大:默认 250,集群规模小时容易撞
  5. 设 mon_allow_pool_delete=true:测试期允许删 pool(生产再关)
  6. dashboard 改 HTTPSceph dashboard create-self-signed-cert
  7. 配 telegraf/prometheus 抓监控ceph mgr module enable prometheus
  8. 加一份 admin keyring 备份:丢了集群进不去

一个反直觉的事

cephadm 部署后,所有服务都是容器,不要去 systemctl restart ceph-mon@xxx,要用 ceph orch daemon restart mon.xxx。否则状态会和 orchestrator 不一致。