从传统运维到云运维演进历程之软件定义存储(三)上

上回书讲完了部署,部署完成之后,就开始了无休止的调优,对于Ceph运维人员来说最头痛的莫过于两件事:一、Ceph调优;二、Ceph运维。调优是件非常头疼的事情,下面来看看运维小哥是如何调优的,运维小哥根据网上资料进行了一个调优方法论(调优总结)。

企业建站必须是能够以充分展现企业形象为主要目的,是企业文化与产品对外扩展宣传的重要窗口,一个合格的网站不仅仅能为公司带来巨大的互联网上的收集和信息发布平台,成都创新互联公司面向各种领域:垃圾桶网站设计成都全网营销解决方案、网站设计等建站排名服务。


关卡三:部署调优关之调优(一)

难度:五颗星

优化方法论

通过对网上公开资料的分析进行总结,对Ceph的优化离不开以下几点:

硬件层面· 硬件规划· SSD选择· BIOS设置操作系统层面· Linux Kernel· 内存· Cgroup网络层面· 巨型帧· 中断亲和· 硬件加速Ceph层面· Ceph Configurations· PG Number调整

硬件优化

1、硬件规划· Processor

ceph-osd进程在运行过程中会消耗CPU资源,所以一般会为每一个ceph-osd进程绑定一个CPU核上。当然如果你使用EC方式,可能需要更多的CPU资源。

ceph-mon进程并不十分消耗CPU资源,所以不必为ceph-mon进程预留过多的CPU资源。

ceph-msd也是非常消耗CPU资源的,所以需要提供更多的CPU资源。

· 内存

ceph-mon和ceph-mds需要2G内存,每个ceph-osd进程需要1G内存,当然2G更好。

· 网络规划

万兆网络现在基本上是跑Ceph必备的,网络规划上,也尽量考虑分离cilent和cluster网络。

2、SSD选择

硬件的选择也直接决定了Ceph集群的性能,从成本考虑,一般选择SATA SSD作为Journal,Intel SSD DC S3500 Series(http://www.intel.com/content/www/us/en/solid-state-drives/solid-state-drives-dc-s3500-series.html)基本是目前看到的方案中的首选。400G的规格4K随机写可以达到11000 IOPS。如果在预算足够的情况下,推荐使用PCIE SSD,性能会得到进一步提升,但是由于Journal在向数据盘写入数据时Block后续请求,所以Journal的加入并未呈现出想象中的性能提升,但是的确会对Latency有很大的改善。

如何确定你的SSD是否适合作为SSD Journal,可以参考SéBASTIEN HAN的Ceph: How to Test if Your SSD Is Suitable as a Journal Device?(http://www.sebastien-han.fr/blog/2014/10/10/ceph-how-to-test-if-your-ssd-is-suitable-as-a-journal-device/),这里面他也列出了常见的SSD的测试结果,从结果来看SATA SSD中,Intel S3500性能表现最好。

3、BIOS设置

(1)Hyper-Threading(HT)

使用超线程(Hyper-Threading)技术,可以实现在一个CPU物理核心上提供两个逻辑线程并行处理任务,在拥有12个物理核心的E5 2620 v3中,配合超线程,可以达到24个逻辑线程。更多的逻辑线程可以让操作系统更好地利用CPU,让CPU尽可能处于工作状态。基本做云平台的,VT和HT打开都是必须的,超线程技术(HT)就是利用特殊的硬件指令,把两个逻辑内核模拟成两个物理芯片,让单个处理器都能使用线程级并行计算,进而兼容多线程操作系统和软件,减少了CPU的闲置时间,提高的CPU的运行效率。
从传统运维到云运维演进历程之软件定义存储(三)上
图1 打开超线程

(2)关闭节能

很多服务器出于能耗考虑,在出场时会在BIOS中打开节能模式,在节能模式下,CPU会根据机器负载动态调整频率。但是这个动态调频并不像想象中的那么美好,有时候会因此影响CPU的性能,在像Ceph这种需要高性能的应用场景下,建议关闭节能模式。关闭节能后,对性能还是有所提升的。

从传统运维到云运维演进历程之软件定义存储(三)上
图2关闭节能

当然也可以在操作系统级别进行调整,详细的调整过程请参考链接(http://www.servernoobs.com/avoiding-cpu-speed-scaling-in-modern-linux-distributions-running-cpu-at-full-speed-tips/),但是不知道是不是由于BIOS已经调整的缘故,所以在CentOS 6.6上并没有发现相关的设置。

for CPUFREQ in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor; do [ -f $CPUFREQ ] || continue; echo -n performance > $CPUFREQ; done

(3)NUMA

简单来说,NUMA思路就是将内存和CPU分割为多个区域,每个区域叫做NODE,然后将NODE高速互联。 node内cpu与内存访问速度快于访问其他node的内存,NUMA可能会在某些情况下影响ceph-osd(http://lists.ceph.com/pipermail/ceph-users-ceph.com/2013-December/036211.html)。解决的方案,一种是通过BIOS关闭NUMA,另外一种就是通过cgroup将ceph-osd进程与某一个CPU Core以及同一NODE下的内存进行绑定。但是第二种看起来更麻烦,所以一般部署的时候可以在系统层面关闭NUMA。
从传统运维到云运维演进历程之软件定义存储(三)上
图3 关闭NUMA

CentOS系统下,通过修改/etc/grub.conf文件,添加numa=off来关闭NUMA。

kernel /vmlinuz-2.6.32-504.12.2.el6.x86_64 ro root=UUID=870d47f8-0357-4a32-909f-74173a9f0633 rd_NO_LUKS rd_NO_LVM.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto  KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM   biosdevname=0 numa=off

操作系统优化

1、Linux Kernel

Linux操作系统在服务器市场中占据了相当大的份额,各种发行版及其衍生版在不同领域中承载着各式各样的服务。针对不同的应用环境,可以对Linux的性能进行相应的调整,性能调优涵盖了虚拟内存管理、I/O子系统、进程调度系统、文件系统等众多内容,这里仅讨论对于Ceph性能影响显著的部分内容。

在Linux的各种发行版中,为了保证对硬件的兼容和可靠性,很多内核参数都采用了较为保守的设置,然而这无法满足我们对于高性能计算的需求,为了Ceph能更好地利用系统资源,我们需要对部分参数进行调整。

(1)调度

Linux默认的I/O调度一般针对磁盘寻址慢的特性做了专门优化,但对于SSD而言,由于访问磁盘不同逻辑扇区的时间几乎是一样的,这个优化就没有什么作用了,反而耗费了CPU时间。所以,使用Noop调度器替代内核默认的CFQ。操作如下:

echo noop > /sys/block/sdX/queue/scheduler

而机械硬盘设置为:

echo deadline > /sys/block/sdX/queue/scheduler

(2)预读

Linux默认的预读read_ahead_kb并不适合RADOS对象存储读,建议设置更大值:

echo “8192” > /sys/block/sdX/queue/read_ahead_kb

(3)进程数量

OSD进程需要消耗大量进程。关于内核PID上限,如果单服务器OSD数量多的情况下,建议设置更大值:

echo 4194303 > /proc/sys/kernel/pid_max

调整CPU频率,使其运行在最高性能下:

echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor >/dev/null2、内存

(1)SMP和NUMA

SMP(Symmetric Multi Processor)架构中,所有的CPU共享全部资源,如总线、内存和I/O等。多个CPU之间对称工作,无主从或从属关系。每个CPU都需要通过总线访问内存,整个系统中的内存能被每个CPU平等(消耗时间相同)的访问。然而,在CPU数量不断增加后,总线的压力不断增加,最终导致CPU的处理能力大大降低。

NUMA架构体系中由多个节点组成,每个节点有若干CPU和它们独立的本地内存组成,各个节点通过互联模块(CrossbarSwitch)进行访问,所以每个CPU可以访问整个系统的内存。但是,访问本地内存的速度远比访问远程内存要快,导致在进程发生调度后可能需要访问远端内存,这种情况下程序的效率会大大降低。

Ceph目前并未对NUMA架构的内存做过多优化,在日常使用过程中,我们通常使用2~4颗CPU,这种情况下,选择SMP架构的内存在效率上还是要高一些。如果条件允许,可以通过进程绑定的方法,在保证CPU能尽可能访问自身内存的前提下,使用NUMA架构。

(2)SWAP

当系统中的物理内存不足时,就需要将一部分内存非活跃(inactive)内存页置换到交换分区(SWAP)中。有时候我们会发现,在物理内存还有剩余的情况下,交换分区就已经开始被使用了,这就涉及到kernel中关于交换分区的使用策略,由vm.swappiness这个内核参数控制,该参数代表使用交换分区的程度:当值为0时,表示进可能地避免换页操作;当值为100时,表示kernel会积极的换页,这会产生大量磁盘IO。因此,在内存充足的情况下,我们一般会将该参数设置为0以保证系统性能。设定Linux操作系统参数:vm.swappiness=0,配置到/etc/sysctl.conf。

(3)内存管理

Ceph默认使用TCmalloc管理内存,在非全闪存环境下,TCmalloc的性能已经足够。全闪存的环境中,建议增加TCmalloc的Cache大小或者使用jemalloc替换TCmalloc。

增加TCmalloc的Cache大小需要设置环境变量,建议设置为256MB大小:

TCMALLOC_MAX_TOTAL_THREAD_CACHE_BYTES=268435456

使用jemalloc需要重新编译打包Ceph,修改编译选项:

–with-jemalloc–without-tcmalloc3、Cgroup

Cgroups是control groups的缩写,是Linux内核提供的一种可以限制、记录、隔离进程组(process groups)所使用的物理资源(如CPU、Memory、IO等)的机制。最初由Google的工程师提出,后来被整合进Linux内核。Cgroups也是LXC为实现虚拟化所使用的资源管理手段,可以说没有Cgroups就没有LXC。Cgroups内容非常丰富,展开讨论完全可以单独写一篇,这里我们简单说下Cgroups在Ceph中的应用。

说到Cgroups,就不得不说下CPU的架构,以E5-2620 v3为例(见图4):整颗CPU共享L3缓存,每个物理核心有独立的L1和L2缓存,如果开启超线程后两个逻辑CPU会共享同一块L1和L2,所以,在使用Cgroups的时候,我们需要考虑CPU的缓存命中问题。

从传统运维到云运维演进历程之软件定义存储(三)上
图4 E5 2620 v3 CPU拓扑图

查看CPU的拓扑,可以通过hwloc工具(http://www.open-mpi.org/projects/hwloc/)来辨别CPU号码与真实物理核心的对应关系。例如在配置2个Intel(R) Xeon(R) CPU E5-2680 v2的服务器,CPU拓扑:

Machine (64GB)  NUMANode L#0 (P#0 32GB)    Socket L#0 + L3 L#0 (25MB)      L2 L#0 (256KB) + L1d L#0 (32KB) + L1i L#0 (32KB) + Core L#0        PU L#0 (P#0)        PU L#1 (P#20)      L2 L#1 (256KB) + L1d L#1 (32KB) + L1i L#1 (32KB) + Core L#1        PU L#2 (P#1)        PU L#3 (P#21)

      L2 L#2 (256KB) + L1d L#2 (32KB) + L1i L#2 (32KB) + Core L#2

        PU L#4 (P#2)

        PU L#5 (P#22)

      L2 L#3 (256KB) + L1d L#3 (32KB) + L1i L#3 (32KB) + Core L#3

        PU L#6 (P#3)

        PU L#7 (P#23)

      L2 L#4 (256KB) + L1d L#4 (32KB) + L1i L#4 (32KB) + Core L#4

        PU L#8 (P#4)

        PU L#9 (P#24)

      L2 L#5 (256KB) + L1d L#5 (32KB) + L1i L#5 (32KB) + Core L#5

        PU L#10 (P#5)

        PU L#11 (P#25)

      L2 L#6 (256KB) + L1d L#6 (32KB) + L1i L#6 (32KB) + Core L#6

        PU L#12 (P#6)

        PU L#13 (P#26)

      L2 L#7 (256KB) + L1d L#7 (32KB) + L1i L#7 (32KB) + Core L#7

        PU L#14 (P#7)

        PU L#15 (P#27)

      L2 L#8 (256KB) + L1d L#8 (32KB) + L1i L#8 (32KB) + Core L#8

        PU L#16 (P#8)

        PU L#17 (P#28)

      L2 L#9 (256KB) + L1d L#9 (32KB) + L1i L#9 (32KB) + Core L#9

        PU L#18 (P#9)

        PU L#19 (P#29)

    HostBridge L#0

      PCIBridge

        PCIBridge

          PCIBridge

            PCI 8086:1d6a

      PCIBridge

        PCI 8086:1521

          Net L#0 “eno1”

        PCI 8086:1521

          Net L#1 “eno2”

        PCI 8086:1521

          Net L#2 “eno3”

        PCI 8086:1521

          Net L#3 “eno4”

      PCIBridge

        PCI 1000:0079

          Block L#4 “sda”

          Block L#5 “sdb”

          Block L#6 “sdc”

          Block L#7 “sdd”

          Block L#8 “sde”

      PCIBridge

        PCI 102b:0522

          GPU L#9 “card0”

          GPU L#10 “controlD64”

      PCI 8086:1d02

        Block L#11 “sr0”

  NUMANode L#1 (P#1 32GB)

    Socket L#1 + L3 L#1 (25MB)

      L2 L#10 (256KB) + L1d L#10 (32KB) + L1i L#10 (32KB) + Core L#10

        PU L#20 (P#10)

        PU L#21 (P#30)

      L2 L#11 (256KB) + L1d L#11 (32KB) + L1i L#11 (32KB) + Core L#11

        PU L#22 (P#11)

        PU L#23 (P#31)

      L2 L#12 (256KB) + L1d L#12 (32KB) + L1i L#12 (32KB) + Core L#12

        PU L#24 (P#12)

        PU L#25 (P#32)

      L2 L#13 (256KB) + L1d L#13 (32KB) + L1i L#13 (32KB) + Core L#13

        PU L#26 (P#13)

        PU L#27 (P#33)

      L2 L#14 (256KB) + L1d L#14 (32KB) + L1i L#14 (32KB) + Core L#14

        PU L#28 (P#14)

        PU L#29 (P#34)

      L2 L#15 (256KB) + L1d L#15 (32KB) + L1i L#15 (32KB) + Core L#15

        PU L#30 (P#15)

        PU L#31 (P#35)

      L2 L#16 (256KB) + L1d L#16 (32KB) + L1i L#16 (32KB) + Core L#16

        PU L#32 (P#16)

        PU L#33 (P#36)

      L2 L#17 (256KB) + L1d L#17 (32KB) + L1i L#17 (32KB) + Core L#17

        PU L#34 (P#17)

        PU L#35 (P#37)

      L2 L#18 (256KB) + L1d L#18 (32KB) + L1i L#18 (32KB) + Core L#18

        PU L#36 (P#18)

        PU L#37 (P#38)

      L2 L#19 (256KB) + L1d L#19 (32KB) + L1i L#19 (32KB) + Core L#19

        PU L#38 (P#19)

        PU L#39 (P#39)

    HostBridge L#7

      PCIBridge

        PCI 8086:10fb

          Net L#12 “enp129s0f0”

        PCI 8086:10fb

          Net L#13 “enp129s0f1”

由此可见,操作系统识别的CPU号和物理核心是一一对应的关系,在对程序做CPU绑定或者使用Cgroups进行隔离时,注意不要跨CPU,以便更好地命中内存和缓存。另外也看到,不同HostBridge的对应PCI插槽位置不一样,管理着不同的资源,CPU中断设置时候也需要考虑这个因素。

总结一下,使用Cgroups的过程中,我们应当注意以下问题:

· 防止进程跨CPU核心迁移,以更好的利用缓存;

· 防止进程跨物理CPU迁移,以更好的利用内存和缓存;

· Ceph进程和其他进程会互相抢占资源,使用Cgroups做好隔离措施;

· 为Ceph进程预留足够多的CPU和内存资源,防止影响性能或产生OOM。尤其是高性能环境中并不能完全满足Ceph进程的开销,在高性能场景(全SSD)下,每个OSD进程可能需要高达6GHz的CPU和4GB以上的内存。

因为优化部分涉及内容较多,所以分为两篇文章来讲述,希望本文能够给予Ceph新手参考,请读者见仁见智,预知后事如何,请期待《部署调优关卡之调优二》。


当前名称:从传统运维到云运维演进历程之软件定义存储(三)上
文章路径:http://ybzwz.com/article/gejhoc.html