ceph调优是一个比较漫长且多坑的过程,故开辟一个调优系列,记录下各种历程,既为了做笔记,也为了给后人提供经验吧
写在前面
松鼠哥的ceph专业课程上线啦!
面向新手同学,从0实战,全面入门ceph安装部署与运维,有需要的同学赶紧扫码订购吧:
调优是非常复杂,技术栈要求很宽泛的工作,这里介绍一下个人在调优过程中的学习记录,供大家参考
系统 - cpu调优
cpu调优这部份主要是两大块:
1、关闭处理器的节能模式,需要在bios里进行设置,可以将空闲cpu睡眠也一并关闭掉
2、将ceph相关进程绑定在指定的cpu core上并且让cpu只为ceph进程服务
对于第2点,绑定进程的好处,一方面是符合当前的硬件设计,尤其是硬件体系结构中的cache体系,绑定了core,就能很大程度避免进程切换到其他的core上,它的cache命中就会更高,尤其是带有numa设计的设备,做隔离能够比较明显地提高性能,另外一方面绑定core使得ceph进程更快地得到资源,在长期高负载运行的环境,更具稳定性和效率
当下比较主流的进程绑定core的方式有:
1、taskset
2、cgroup
3、numactl
当然,在程序代码中绑定core也是可以的,不过在ceph中实现是几乎无可能的,所以这里就不列举了
taskset
tasket通过给定的pid,将指定的程序限定运行在指定的core上,效果其实也不错,缺点就是程序运行之后再进行绑定,如果程序启动时已经在某个core上运行,而绑定的core是跨物理处理器,这种情况下绑定core就没有什么意义了;当然,taskset也可以启动某个进程来实现在进程一开始就锁定cpu core,但是taskset有明显的缺陷,那就是它不能指定程序从哪里分配内存,虽然从最近的地方分配内存是系统会尽量做的事,但是并不能保证它的内存使用是最优的,而且redhat官方也指出:
1 | important |
cgroup
crgoup是内核级的隔离手段,通过为指定的程序集指定它的子系统,来实现对程序使用资源的控制,它更擅长用来限制程序的资源使用量,例如使用cpu不超过某个值,或者内存使用不超过某个量,当然,通过配置与cpu的亲和性,也可以用来限制程序的运行core,但是仍不是最好的方案,国外有些资料甚至认为cgroup其实是备选方案,并不是很推荐的方案
numactl
numa(非一致内存访问)方式是首推的方案,它实现的控制、绑定更底层,并且在使用方式上更简单、灵活,关于numa相关的知识网上有不少,这里推荐一篇写得很不错的cpu拓扑及ceph使用时的优化,目前绝大部分的服务器设备都会使用numa架构进行设计,主要是因为当cpu的core(超线程)数量超过10个之后,SMP架构带来的总线共享冲突会导致访存性能瓶颈。使用numactl对radosgw进程进行绑定的具体步骤:
1、验证设备是否开启numa
1 | [root@ceph-c204 tanweijie]# grep -i numa /var/log/dmesg |
2、查看设备的numa分布情况,如果没有该命令,请安装yum install -y numactl
1 | [root@ceph-c204 tanweijie]# numactl --hardware |
3、查看具体的处理器情况
1 | [tanweijie@ceph-c204 tanweijie]# lscpu |
可以看到,笔者的设备中有两个node,每个node有一个物理cpu,超线程后,共有56个core,这里要注意一点,cpu的core在相同的node里,有可能是不连续的,在绑定的时候别搞错了;由此可以确定cpu core的分布情况,绑定的时候尽量使用同一个socket的core
4、执行命令查看当前程序的调度策略:
1 | [tanweijie@ceph-c204 tanweijie]# for i in $(pgrep radosgw) ; do taskset -pc $i ; done |
5、在/usr/lib/systemd/system/中找到对应的启动文件,例如要绑定第一个socket:
使用numactl来启动进程:
1 | ExecStart=/usr/bin/numactl -C 14-27,42-55 -m 1 /usr/bin/radosgw -f --cluster... |
这样就可以将rgw进程绑定在14-27,42-55一共28个core上面了,同时指定了rgw进程只能从node 1分配内存,这里会有个问题,如果指定的进程无法从指定的node里分配到内存,即分配失败,有可能会导致进程异常,或者直接被杀,所以在进行规划的时候要注意,分配core的时候要预测好进程消耗的内存上限
6、重新读取配置并重启服务:
1 | systemctl daemon-reload |
7、再次查看目标进程的numa调度策略:
1 | [root@gz-open-dw-c204 tanweijie]# for i in $(pgrep radosgw) ; do taskset -pc $i ; done |
8、htop查看实际效果
让cpu只为ceph服务
最佳的办法就是用isolcpus参数将cpu隔离出去,系统的调度器就再也不会把进程往指定的core上调度,然后再使用捆绑的方式将我们的进程绑定到隔离出来的cpu上,再使用一些手工方法将系统中断隔离出去,实现ceph进程对cpu的完全独占,岂不美哉!可惜的是,经过测试,在使用isolcpus将cpu隔离出去之后,再使用numactl来对进程进行绑定是行不通的,使用numactl -C xx指定那部分core,libnuma会报错,out of range,原因是numactl读取core的方式的限制,它只能从系统已经识别并允许调度的core上面进行指定,因此不可以指定那部分已经isolcpus的core,笔者尝试与numactl的代码贡献者联系,想看看有没有可能修改代码,重新编译来实现,毕竟numactl是最好的cpu隔离方式,对方给出的解答是,在较新版本的numactl提供了一个-a参数,可以使numactl检测到所有的cpu核心;另外一种方案就是使用taskset来启动程序,运行在isolcpus指定的隔离出来的cpu上,这种方式笔者尝试过,效果也不错,但是内存分配的方式实在不如意,大概是强迫症吧;这里最后介绍一下将系统中断转给某些cpu的方法:
1 | 修改/etc/sysconfig/irqbalance文件: |
系统 - 网络调优
网络调优方面主要是针对网卡以及中间设备,例如交换机,进行调整,具体调整参数要根据具体硬件来确定,这里仅对笔者的硬件环境给出建议
网络环境:
1、网卡 - 40Gbps的ib卡(PCIe卡拓展),目前只有一个
2、交换机为24口的ib交换机4036E
网络能进行调节的地方也不多,首先是开启ib卡的巨帧模式,即调节ib卡的MTU为65520;ib卡千兆网卡不同,它使用命令
1 | ifconfig ib1 mtu 65520 |
调节mtu会报错,起初以为是网卡驱动不支持,但是,ib卡能到40Gbps,怎么会连巨帧都不支持呢?经过调查,发现linux kernel官方提供的资料显示:
1 | Datagram vs Connected modes |
才发现是打开方式不对,应该是给mode文件注入模式,才能修改它的mtu,于是:
1 | echo "connected" > /sys/class/net/ib1/mode |
再次查看ib卡的mtu,发现mtu已经改好了~
1 | 8: ib1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65520 qdisc mq state UP qlen 1024 |
注意,这样修改后,重启系统后ib卡仍会恢复到datagram模式,解决办法就是修改文件/etc/infiniband/openib.conf中的SET_IPOIB_CM=yes,即默认开启连接模式;但是,对ceph节点修改接口的mtu不总是能提高性能,典型的场景就是节点通信链路上的交换设备不支持巨帧,那就适得其反了,因此,需要对节点经过的交换设备修改配置,使其支持巨帧转发,这样一来就能充分利用ib卡的性能了;这里就简单说下,4036E ib交换机的巨帧模式开启,是通过交换机的管理口,对交换机的接口mtu进行设置,它只能将mtu设置最大为4096,可能是这款交换机太老了吧~不过,从实测效果来看,性能还可以,用iperf3测试显示,单口链路速度稳定在26Gbps左右;,当然,交换机成为了链路瓶颈;
网络方面,除了链路上的优化外,系统的协议栈相关参数也可以进行优化,尤其是ib链路开启了巨帧模式,进行tcp协议栈优化以发挥巨帧模式的最大性能是十分有必要的,这里可以给出ib卡巨帧模式下linux网络优化的参考:
1 | net.ipv4.tcp_timestamps=0 |
参考资料来自ipoib_release_notes
对于网络优化,还有一种更彻底的优化方案,就是通过使用dpdk方式,直接脱离协议栈,能实现更高的网络性能,不过dpdk又是另外一个大项目,除非对性能要求苛刻,否则投入产出比估计不高
系统 - 内存调优
内存方面,主要是考虑一下几个方面:
1、尽量不让程序使用swap分区
2、尽量让程序访问最快的内存
3、尽量加大程序的cache
尽量不让程序使用swap分区
有些比较极端的用户可能会直接关闭、禁用swap分区,这么一来当然会使得程序不会去使用swap分区而完全使用内存,性能会有不少提升,但是,一旦系统的可用内存过低,程序无法正常分配到内存时,可能会引发各种各样的问题,甚至会直接宕机,这种高风险的方式是非常不建议使用的,比较稳妥的办法就是告诉系统,尽量使用内存,是在是没有办法的时候,才去使用swap分区,这样可以最大化避免程序被杀或者宕机,同时,将swap分区文件建立在ssd上面,也能获得较好的表现
让系统尽量不用swap的方法:
1、在sysctl中加入规则并重新读入配置
1 | echo "vm.swappiness = 0" >> /etc/sysctl.conf |
这就告诉系统,当内存消耗殆尽之后才开始使用swap分区
2、执行命令
1 | sync |
将必要数据数据写入硬盘,因为接下来我们要完全释放swap的空间,在swap中的数据应立即写入磁盘避免丢失
3、接下来
1 | swapoff -a |
关闭swap,这一步将会释放掉所有swap的占用并禁用掉swap, 如果swap占用较多,可能需要比较长的时间来进行同步
4、最后
1 | swapon -a |
重新将swap打开,此时swap完全free,同时因为设置了内存消耗殆尽后才开始使用swap分区,所以在内存规划合理的情况下,swap被用到的几率非常小
尽量让程序访问最快的内存
由上述的numactl绑定cpu的知识可知,在numa模式下,跨node访问内存速度会有很大差异,所以在绑定程序,尤其是rgw和osd这类进程的时候,最好同时注意到它们的所属node的关系,并且在使用numactl绑定的时候,同时指定-m参数,即指定进程从哪个node上分配内存,这样就能让程序运行得更快
尽量加大程序的cache
加大程序的cache其实是ceph层面的调优,主要是通过加大bluestore cache size 的值来指定cache,在笔者的环境中,bluestore cache size指定为1G,而rgw的rgw lru cache使用了10000,在500个线程(python)并发上传965KB文件的情况下,两节点共12个osd时,基本可以达到600MB的集群读写带宽,当然程序不完整,暂时还不能测试延时情况
以上就是系统级的调优方案,目前仍在探索中前进,未完待续。
参考资料
Working With NUMA/CPU Pinning
Managing Process Affinity in Linux
- 本文作者: 奋斗的松鼠
- 本文链接: http://www.strugglesquirrel.com/2018/04/03/ceph性能调优历程-系统篇/
- 版权声明: 本博客所有文章除特别声明外,创作版权均为作者个人所有,未经允许禁止转载!