はじめに
本ブログでは、2020年になってからRook-Cephについて、機能や使い方などをいろいろと調べてまいりました。しかし一方で、そうやって調べた機能は、具体的にどのように利用するのか、どのような設定を行えばRook(というよりCeph)の機能を引き出すことができるのかについて、あまり理解をすることができていませんでした。例えば、Rook-Cephを利用する際、IOPSやスループットなどのパフォーマンスを引き上げるためには、どのような設定を行う必要があるのか、といった点が気になっております。
Rook-Cephの場合、ストレージの処理を行うのはCephの役割です。Cephは10年以上前に登場し、多くの本番環境で利用されてきたソフトウェアです。そのため、これまでのCephの運用や設計に関する知見・情報は多く公開されており、これらをたどることでCephを利用するうえでの最善策、Best Practiceを探ることができるのではないか、と考えました。
本記事では、CephのBest Practiceを探る第一弾として、Cephの公式Blogで紹介されているこちらの記事の内容について紹介いたします。また紹介をする中で、私個人の理解を進めるために補足として加えたもの、また本記事公開の時点で解釈が十分できていないものに対するメモなどを青字で加えています。解釈が不十分なもの、誤った記載のものについては、分かり次第すぐに修正していきたいと思います。
要点
- CephではBlueStoreという新しいストレージバックエンドが利用できるようになり、従来のFileStoreと比較してパフォーマンスが向上した。
- All-Flash deviceのCephクラスター環境でBlueStoreのパフォーマンス検証を行った。デフォルトの設定値ではLargeブロックサイズに対するパフォーマンスはよかったが、Smallブロックサイズに対するパフォーマンスは優れなかった。
- Smallブロックサイズに合わせてCephクラスターのパラメータチューニングを行った。具体的には、RocksDBのパフォーマンスの最適化、BlueStoreメタデータキャッシュの確保、PG Logの保存数の削減などを行った。
- チューニングの結果、特に書き込みのパフォーマンスにおいて大きな改善が見られ、IOPSは134%上昇、平均レイテンシは70%減少、そしてTailレイテンシは91%減少した。
Introduction
現代では、All-flashな構成のストレージに対する需要は高まっています。All-Flash構成のストレージは、高スループットと低レイテンシを両立するだけでなく、電力消費や冷却にかかるパワーを削減し、TCO (Total Cost of Ownership) を低下させる効果もあります。ストレージやデータベースに保存されたデータがビジネスの根幹を支えるようになり、より高いパフォーマンスや耐久性を求められる中で、Software-Definedでスケールアウトするようなストレージテクノロジーを利用することが求められています。
Red Hat Ceph Storage(RHCS)はオープンソースでスケーラビリティに優れたSoftware-Defined Storageソフトウェアです。NANDテクノロジーの向上により、フラッシュメディアをストレージに利用することは、手の届くようなものとなりました。RHCSにより、数百万IOPSと低レイテンシとを実現し、ミッションクリティカルなワークロードに向けたストレージを利用することができます。
高パフォーマンスを必要とするワークロードでは、しばしばブロックデバイスを利用します。CephはRBDというライブラリ経由でブロックデバイスを提供します。RBDブロックデバイスは多数のオブジェクトに分けられ、クラスター内に分散されています。このオブジェクトはPlacement Group (PG) と呼ばれるグループに分けられ、分散配置されます。またPGはクラスター全体にまたがってCeph OSDにオブジェクトを分散します。これはRBDボリュームからデータにアクセスする際の並列性を大きく向上します。
※上図は元記事より引用
Cephは新しいストレージバックエンドとしてBlueStoreをリリースし、これが以前のFileStoreと比較してパフォーマンスを向上することにつながりました。その理由としてはIOデータパスがシンプルになり、2重のwrite penaltyを避けていることが挙げられます。またBlueStoreがCephのパフォーマンスを向上したことにより、OSDのCPU使用率、特にフラッシュメディアを利用するOSDの値を削減することにつながりました。
※参考リンク:
BlueStore Intro
BlueStoreはCeph OSDのバックエンドストレージとして新しく利用できるものです。CephのオリジナルのオブジェクトストアであるFileStoreはRawブロックデバイス上にファイルシステムを必要とし、オブジェクトはファイルシステムに書き込まれるという形でした。一方BlueStoreはファイルシステムを介さずブロックデバイスに直接オブジェクトを書き込み、これによりパフォーマンスの改善がもたらされました。
BlueStore Under the Covers
以下の図はBlueStoreとFileStoreの構成の違いを表しています。
※上図は元記事より引用
FileStoreではデータを書き込む場合、まずCephジャーナルに書き込みます。その後データ・メタデータはそれぞれXFSを経由してデバイスへ書き込まれます。
BlueStoreでは、FileStoreと比べデータパスがシンプルになっています。データは直接Rawデバイスに書き込まれ、メタデータはRocksDBによって管理されます。またデバイスはデータ用・メタデータ用に分かれ、Rawデバイスにデータオブジェクトが書き込まれると、RocksDBは新しいデータオブジェクトに関する情報をアップデートします。
RocksDBはLevelDBをベースにFacebook社で開発が開始されたKey-Value形式のデータベースエンジンです。Log Structured Merge Tree (LSM Tree)を採用しており、LevelDBにはなかった多数の新機能(トランザクショナル、など)が追加されています。 CephのBlueStoreで採用した理由として、トランザクショナルでログ・ジャーナルへのコミットが素早いKey-Valueエンジンであったこと、ストレージバックエンドを抽象化すること、C++で書かれていることなどが挙げられています。
RocksDBは直接デバイスには書き込めず、BlueFSという専用のファイルシステムを利用します。BlueFSはRocksDBに必要な機能のみを備えたシンプルなファイルシステムです。
RocksDBは永続データのトランザクションログとしてWAL(Write-Ahead Log)を利用します。FileStoreでは全ての書き込みはジャーナルから始まるのに対し、BlueStoreは2つのデータパスが存在します。一つはデータの直接書き込みパス、もう一つはWALデバイスに書き込まれ、後ほど非同期的にディスクにフラッシュされるパスです。
BlueStoreの新機能として、他にも以下のようなものが紹介されています。
lowest levelのデータに対する圧縮が可能になった:RawデバイスにあるデータBlobを圧縮することが可能になり、RHCSで管理するあらゆるデータが圧縮できるようになりました。
データ・メタデータをチェックサム付きで保存することによる一致性の向上:永続ストレージからデータを読み込む際は、常にチェックサムを確認します。
※参考リンク:
テスト環境
本記事のテスト環境は、以下に示す通り、5台のRHCS All-Flash (NVMe) サーバーと7台のクライアントノード (Red Hat OpenStack Platform)を利用しています。
server/client | factors | value |
---|---|---|
5 x RHCS OSD Node Configuration | Chassis | Cisco UCS C220-M5SN Rack Server |
CPU | 2 x Intel® Xeon® Platinum 8180 28 core (56 HT cores) @ 2.50 GHz | |
Memory | 196GB | |
NIC | Cisco UCS VIC 1387 2 port x 40Gb | |
Storage (Ceph Data) | 7x Intel® SSD DC P4500 4.0 TB | |
Storage (Ceph Metadata) | 1x Intel® Optane™ SSD DC P4800X 375 GB | |
Storage (Ceph Pool Placement Groups) | 4096 | |
Software Configuration | RHEL 7.6, Linux Kernel 3.10, RHCS 3.2 (12.2.8-52) | |
7 x Client Hardware Configuration | Chassis | Cisco UCS B200 M4 Blade servers |
CPU | 2x Intel® Xeon® CPU E5-2640 v4 @ 2.40GHz | |
Memory | 528GB | |
NIC | Cisco UCS VIC 1387 2 port x 10Gb | |
Software Configuration | RHOSP 10, RHEL 7.6, Linux Kernel 3.10, Pbench-FIO 3.3 |
その他の情報は以下の通りです。
OSD
回転するメディアの場合は、メディアデバイスあたり1つのOSDを割り当てるのが推奨されています。今回はNVMeデバイスを使用しており、パフォーマンスを最大化するため、NVMeデバイスあたり2つのOSDを割り当てています。
ネットワーク
クライアントが利用する帯域を確保するため、2つのネットワークに分けています。1つはクライアントからOSDノードへのアクセス、もう一つはOSDノード間でのアクセスに利用します。
※上図は元記事より引用
テスト環境はACI Leaf-Spineトポロジーであり、2つのネットワークはいずれもJumbo Frame(MTUサイズは9000)を利用するよう設定しています。
※上図は元記事より引用
OSP(OpenStack Platform)側のネットワーク帯域幅はFiber Interconnect uplinkがボトルネックとなり、80Gbit/sしか利用することができませんでした。そのため、クライアントからCephクラスターまでのスループットは最大で~10GBytes/sになりました。
※参考リンク:
コンテナ化
今回利用するRHCSでは、Containerized Storage Daemons (CSD)を利用し、Cephのデーモンをコンテナとしてデプロイします。
Ceph Daemonをコンテナ化することで、一つのノード上に複数のサービスを配置することを可能にする柔軟性を提供します。これはOSD、Monitorなどの専用ノードの必要性をなくし、TCO (Total Cost of Ownership) を削減することができます(※1参照)。
今回は5つのノードのうち、3つのノードはOSD+MGR+MON、2つのノードはOSDのみが動作しています。各Cephサービスのリソース制限は次項に記載されています。
※1:TCOを削減できる理由としては、ノード数を削減することができるためかと推察しています。
CPUの割り当て
各RHCSノードは2×28の物理コアを備えています。さらにハイパースレッディングを利用し、合計112 vCPUを利用することが可能です。各サービスに対してどのようにCPUを割り当てるかについては、OSに充てる分をできるだけ温存しつつ、CPUの割り当てを決定しました。
まず、各サービスに対するCPUの割り当ては、以下の表に様になりました。
vCPU (Core) | Memory (GB) | |
---|---|---|
OS | 8 | 12 |
OSDコンテナ | 7 | 12 |
MONコンテナ | 3 | 6 |
MGRコンテナ | 3 | 6 |
OSDについては、1ノードあたり7つのNVMeがアタッチされており、それぞれのデバイスに2つOSDを割り当てます。そのため、OSDには合計98vCPUを割り当てることになります(※2参照)。
※2:(OSDコンテナあたりのvCPU数) × (1ノードあたりのNVMe数) × (1デバイスあたりのOSD数) = 7vCPU × 7NVME × 2OSD = 98vCPU
ベンチマークの方法
ベンチマークには標準ツールであるFIOを利用し、Ceph Block Storageのパフォーマンス計測を行いました。
計測当初は2つの異なるボリューム数で計測を行いました。
- 1クライアントあたり200GBのボリュームを12個(合計84ボリューム、16.8 TB)
- 1クライアントあたり200GBのボリュームを15個(合計105ボリューム、21TB)
しかしボリューム数12個の場合、ストレージサブシステムへの負荷をピークにすることができなかったため、いくつかの試験ではボリューム数を15個にし、より多くの負荷をかけました。なお、Replicated Poolの分を含めて、ストレージボリュームの合計使用量は42TBになりました。
FIO librbd IOengineを利用することで、 KVM/QEMUの設定をすることなく、Ceph RBDボリュームのストレージパフォーマンスをFIOで計測することができます。ここで利用するlibrbdライブラリはQEMUバックエンドで使うものとまったく同じなので、KVM/QEMUのパフォーマンスに近似することができます。例えば1クライアントあたり15個のRBDボリュームを7クライアントに与えた場合、1インスタンスあたり1つのRBDボリュームを割り当てた105のOSPインスタンスと同程度のワークロードを作り出すことができます。
なおテストに利用したFIOテンプレートファイルは以下の通りです。
[global] ioengine=rbd clientname=admin pool=rbdpool #IO-Depth changes depending on the test iodepth=$IODEPTH runtime=600 direct=1 sync=0 buffered=0 #Blocksize changes depending on the test bs=$BLOCKSIZE #RR,RW, or a mixed workload, this changes depending on the test rw=$TYPEOFTEST norandommap randrepeat=0 startdelay=15 rwmixread=70 invalidate=0 # mandatory time_based=1 refill_buffers ###compression/dedupe related #dedupe compress tests #dedupe_percentage=80 #buffer_compress_percentage=10 #buffer_pattern=0xdeadface ramp_time=180 write_bw_log=fio write_iops_log=fio write_lat_log=fio log_avg_msec=6000 write_hist_log=fio log_hist_msec=60000 [rbd_vol00] rbdname=template-vol00 numjobs = 1 clientname=admin pool=rbdpool # One section per volume [rbd_vol0X] rbdname=template-vol0X numjobs = 1 clientname=admin pool=rbdpool
検証前にはフルサイズボリュームのシーケンシャルな書き込みを行い、Cephのthin-provision メカニズムのインパクトを除去することで(※3参照)、安定して再現性のある結果を取得しました。また各テストの前には、OSD・クライアントノードからOSキャッシュをドロップしました。
各検証はランタイム900秒、起動時間180秒で4回行い、それらの平均を算出して結果としました。
※3:thin-provisioningにより必要な容量だけが割り当てられるため、あらかじめフルサイズボリュームの書き込みを行うことでその影響を除去することを目的とした作業と思われます。
※参考リンク:
パフォーマンスの比較
デフォルトの設定値の場合、RHCSはLargeブロックサイズのワークロードの場合、優れたパフォーマンスを記録しました。一方で、Smallブロックサイズのワークロードでは「保守的」な結果となり、あまりすぐれた結果とはなりませんでした。
この結果を受け、ブロックサイズの小さなワークロードに合わせてチューニングを行い、パフォーマンスの改善を目指しました。
今回利用したceph.conf
は以下のようになりました。
### PLEASE TAKE IN ACCOUNT THIS FILE IS CONFIGURED FOR BECHNMARK TESTING OF CEPH NOT PRODUCTION USE [client] rbd cache = False [client.openstack] admin socket = /var/run/openstack/$cluster-$type.$id.$pid.$cctid.asok log file = /var/log/ceph/qemu-guest-$pid.log # Please do not change this file directly since it is managed by Ansible and will be overwritten [global] # let's force the admin socket the way it was so we can properly check for existing instances # also the line $cluster-$name.$pid.$cctid.asok is only needed when running multiple instances # of the same daemon, thing ceph-ansible cannot do at the time of writing admin socket = $run_dir/$cluster-$name.asok auth client required = none auth cluster required = none auth service required = none auth supported = none cephx require signatures = False cephx sign messages = False cluster network = 1.1.1.0/24 debug asok = 0/0 debug auth = 0/0 debug bdev = 0/0 debug bluefs = 0/0 debug bluestore = 0/0 debug buffer = 0/0 debug civetweb = 0/0 debug client = 0/0 debug compressor = 0/0 debug context = 0/0 debug crush = 0/0 debug crypto = 0/0 debug dpdk = 0/0 debug eventtrace = 0/0 debug filer = 0/0 debug filestore = 0/0 debug finisher = 0/0 debug fuse = 0/0 debug heartbeatmap = 0/0 debug javaclient = 0/0 debug journal = 0/0 debug journaler = 0/0 debug kinetic = 0/0 debug kstore = 0/0 debug leveldb = 0/0 debug lockdep = 0/0 debug mds = 0/0 debug mds balancer = 0/0 debug mds locker = 0/0 debug mds log = 0/0 debug mds log expire = 0/0 debug mds migrator = 0/0 debug memdb = 0/0 debug mgr = 0/0 debug mgrc = 0/0 debug mon = 0/0 debug monc = 0/00 debug ms = 0/0 debug none = 0/0 debug objclass = 0/0 debug objectcacher = 0/0 debug objecter = 0/0 debug optracker = 0/0 debug osd = 0/0 debug paxos = 0/0 debug perfcounter = 0/0 debug rados = 0/0 debug rbd = 0/0 debug rbd mirror = 0/0 debug rbd replay = 0/0 debug refs = 0/0 debug reserver = 0/0 debug rgw = 0/0 debug rocksdb = 0/0 debug striper = 0/0 debug throttle = 0/0 debug timer = 0/0 debug tp = 0/0 debug xio = 0/0 fsid = 66f14b44-1e42-4869-9ebb-cbe0b0c4053d log file = /var/log/ceph/$cluster-$type-$id.log max open files = 131072 mon compact on trim = False mon host = 10.48.XX.14,10.48.XX.32,10.48.XX.16 mon initial members = ceph04,ceph05,ceph06 osd deep scrub interval = 137438953472 osd max scrubs = 16 osd objectstore = bluestore osd op threads = 2 osd pool default min size = 1 osd pool default size = 2 osd scrub load threshold = 0.01 osd scrub max interval = 137438953472 osd scrub min interval = 137438953472 perf = True public network = 10.48.22.0/24 rbd readahead disable after bytes = 0 rbd readahead max bytes = 4194304 rocksdb perf = True throttler perf counter = False [mon] mon allow pool delete = True mon health preluminous compat = True mon osd down out interval = 300 [osd] bluestore cache autotune = 0 bluestore cache kv ratio = 0.2 bluestore cache meta ratio = 0.8 bluestore cache size ssd = 8G bluestore csum type = none bluestore extent map shard max size = 200 bluestore extent map shard min size = 50 bluestore extent map shard target size = 100 bluestore rocksdb options = compression=kNoCompression,max_write_buffer_number=32,min_write_buffer_number_to_merge=2,recycle_log_file_num=32,compaction_style=kCompactionStyleLevel,write_buffer_size=67108864,target_file_size_base=67108864,max_background_compactions=31,level0_file_num_compaction_trigger=8,level0_slowdown_writes_trigger=32,level0_stop_writes_trigger=64,max_bytes_for_level_base=536870912,compaction_threads=32,max_bytes_for_level_multiplier=8,flusher_threads=8,compaction_readahead_size=2MB osd map share max epochs = 100 osd max backfills = 5 osd memory target = 4294967296 osd op num shards = 8 osd op num threads per shard = 2 osd min pg log entries = 10 osd max pg log entries = 10 osd pg log dups tracked = 10 osd pg log trim min = 10
チューニング
ここから最も重要だったチューニングの内容について触れていきます。
RocksDBのチューニング
RocksDBはOSDの書き込みパフォーマンスにおいて重要な役割を担います。RocksDBでのDB Compactionによるwrite amplificationを最小化するため(※4参照)、ceph.conf
のbluestore_rocksdb_options
に以下のような設定を行いました。
bluestore_rocksdb_options = compression=kNoCompression, max_write_buffer_number=32, min_write_buffer_number_to_merge=2, recycle_log_file_num=32, compaction_style=kCompactionStyleLevel, write_buffer_size=67108864, target_file_size_base=67108864, max_background_compactions=31, level0_file_num_compaction_trigger=8, level0_slowdown_writes_trigger=32, level0_stop_writes_trigger=64, max_bytes_for_level_base=536870912, compaction_threads=32, max_bytes_for_level_multiplier=8, flusher_threads=8, compaction_readahead_size=2MB
※4:DB Compactionとは、データベース・ファイルを書き直し、古いドキュメント・リビジョンや削除されたドキュメントを除去する作業を指します。ストレージ領域の確保やデータ量削減によるパフォーマンス向上を主な目的とします。
一方、Write Amplificationとは、フラッシュデバイス利用時に発生する書き込み処理が実際のデータ量を上回ることを指します。
フラッシュデバイスはその性質上、データを直接書き換えるということができません。書き込みの単位は「ページ」と呼ばれ、使用するページが「使用済み」(既にデータが存在)の場合は消去処理が必要となります。この消去できる単位は「ブロック」というページよりも大きな単位であり、新規に書き込む分がブロックに満たない場合でも、ブロック単位でデータは削除され、元のデータを再書き込みする必要があります。Write Amplificationにより、書き込み性能の低下やデバイスの寿命を早く迎えるという問題が発生します。
※参考リンク:
Ontrack - What is Write Amplification (WA) and how does it effect SSDs?
NetApp - フラッシュ デバイスの特徴(基本編) ~ フラッシュ デバイス構造から理解する書き込み量の増幅を改善する仕組み ~
BlueStoreキャッシュ
RHCS 3.2はbluestore cache autotuning
という機能が追加されました。これはBlueStoreで利用するキャッシュサイズを自動的に変更する機能であり、多くのワークロードでは有効になります。しかし今回の検証環境ではこの機能を無効にしたほうが良い結果が得られたことから、検証中はマニュアルでBlueStoreキャッシュの設定を行いました。
ランダムなSmallブロックサイズのワークロードに対しては、できる限り多くのBlueStore Metadata Cacheをキープすることが重要になります。OSDノードに適切なメモリが割り当てられていれば、BlueStoreキャッシュサイズを増加することで、パフォーマンスの向上がもたらされます。bluestore_cache_size_ssd
の値はデフォルトでは4GBに設定されていますが、ここでは8GBに変更しました。これはOSDあたりに割り当てた12GBのメモリのうち実に3分の2にあたります。
上記のようにBlueStore Cache Autotuningを無効化し、メモリ割り当てサイズを指定すると、BlueStoreのキャッシュはさらに3つに分かれます。
cache_meta
:BlueStore Onodeとそれに関連するデータに利用cache_kv
:RocksDBのブロックキャッシュに利用 (index/bloom-filters(※5参照)を含む)data cache
:データバッファ用にBlueStoreキャッシュとして利用
各キャッシュの容量は比率で指定することができます。ここではRBDワークロード向けにbluestore_cache_meta_ratio
の比率を上げ、BlueStore Onodeキャッシュ専用のキャッシュサイズを増加した。テスト中は以下のような比率にすることで最も優れた結果となりました。
bluestore_cache_autotune = 0 bluestore_cache_kv_ratio = 0.2 bluestore_cache_meta_ratio = 0.8
※5:Bloom Filtersとは確率的データ構造の一つで、ある要素が集合のメンバーであるかどうかのテストに使われます。RocksDBではSST (Sorted Static Table)にデータが含まれており、目的のデータを含むSST(エントリテーブル)を検索するためにBloom Filterを利用します。
※参考リンク:
Ceph Docs - BlueStore Config Reference #Automatic Cache Sizing
BLUESTORE: A NEW STORAGE BACKEND FOR CEPH – ONE YEAR IN (PDF)
リカバリープロセス
RHCSが(何らかの理由で)失敗したOSDに対してリカバリープロセスを行うとき、ログベースのリカバリを行います(※6参照)。この時、Smallブロックサイズの書き込みの場合は長い変更点のリストを生成し(※7参照)、それはPGログに書かなければならないものです。これがWrite Amplificationを発生し、パフォーマンスに影響を与えます。
検証中、PGログの保存する数を少なくしたときに、パフォーマンスが向上することが確認されました。ただこれには欠点もあり、結果的にリカバリ時間が増加します。
ここでのリストアのプロセスではBackfillを利用します(※8参照)。Backfillを利用する場合、、PGのハッシュ空間を徐々に移動し、元のPGと移動先のPGとを比較します。その結果、リカバリ時間が増加します(※9参照)。
検証中、PGログの数を減少させることで、Write Amplificationが減少することを確認しました。上記PGログに関するチューニングは、以下の通りになります。
osd_min_pg_log_entries = 10 osd_max_pg_log_entries = 10 osd_pg_log_dups_tracked = 10 osd_pg_log_trim_min = 10
※6:CephではすべてのCeph Poolのタイプを一致するために、Primary Log-Based Replicationを採用しています。まずデータを読み取るには、書き込みの完了したものを返す必要があります。これを扱う上で、Cephでは特定のPGに対する書き込みを、一つのPrimary OSDを経由するようにし、Primary OSDからSecondary OSDへと出力します。
※Ceph公式ドキュメントより
この時のPGの状態は、2つの数値で表すことができます。それは、Primary OSDにおける最新の書き込みのマップのエポック(バージョン番号)と、PGごとのバージョン番号です。
これに加えて、可能な限り最新の操作ログを保持します。この操作ログには、開始したがコミットされていない不安定な書き込みログや、ローカルでは最新でないオブジェクトなども含みます。このログを利用し、最新の書き込みがされたOSDとやり取りすることで、クライアントからコミットされたすべての書き込みログを含むログが決定されます。
※7:Smallブロックサイズのほうが変更点に関するログが多くなる理由については分かっておりません。Small ブロックサイズの場合Largeブロックサイズと比べてepochのリストが増加し、変更点に関するログが多く発生する、ということ?
※8:Cephではデータのリバランスや復旧の際、PG内の別のOSD上にあるデータを利用します。これをBackfill(埋め戻し)と呼んでいるのでは、と考えています。
※9:PG数が少ない場合、PGあたりのOSD数が増加するため、Backfill後のデータ比較の対象が多くなり、結果的にリカバリ時間が増加するのでは、と考えています。
※参考リンク:
RHEL 7.6の設定
CephノードのRHEL 7.6に関するチューニング設定 (/usr/lib/tuned/ceph-tuned/tuned.conf
)は、以下の通りです。
[main] summary=ceph_perf [cpu] governor=performance energy_perf_bias=performance min_perf_pct=100 force_latency=1 [disk] readahead=>4096 [sysctl] kernel.sched_min_granularity_ns = 10000000 kernel.sched_wakeup_granularity_ns = 15000000 fs.aio-max-nr=1048576 kernel.pid_max=4194303 fs.file-max=26234859 vm.zone_reclaim_mode=0 vm.swappiness=1 vm.dirty_ratio = 10 vm.dirty_background_ratio = 5 net.ipv4.tcp_rmem=4096 87380 134217728 net.ipv4.tcp_wmem=4096 65536 134217728 net.core.rmem_max=268435456 net.core.wmem_max=268435456 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_fin_timeout = 10 net.ipv4.tcp_slow_start_after_idle = 0 net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.all.accept_source_route = 0 net.ipv4.tcp_mtu_probing = 1 net.ipv4.tcp_timestamps = 0 net.core.netdev_max_backlog = 50000 net.ipv4.tcp_max_syn_backlog = 30000 net.ipv4.tcp_max_tw_buckets = 2000000
チューニングの結果
Smallブロックに合わせてチューニングした結果、下の図で見られるように、IOPS、平均レイテンシ、Tailレイテンシ(※1参照)0のいずれも改善されました。計測ではランダム読み込み、ランダム書き込み、ランダム読み込み・書き込みの両方について記録しており、このうち特にランダムの書き込みにおいてチューニング後の結果が大きく改善されました。
ワークロード | IOPS | 平均レイテンシ | Tailレイテンシ |
---|---|---|---|
ランダム読み込み | 43%向上 | 30%低下 | 36%低下 |
ランダム読み込み・書き込み | 132%向上 | 73%低下 | 90%低下 |
ランダム書き込み | 134%向上 | 70%低下 | 91%低下 |
※10:あるシステムが多くのRequestを処理する中で、その一部が処理に長時間を要する場合があります。Requestに対する処理時間の分布を表したときに、長時間かかるものがtail(=分布の裾の部分)にあたり、このようなレイテンシをTail Latencyと呼びます。Tail Latencyはシステムのパフォーマンスを低下させる影響があると指摘されており、その影響は、システムが複雑で大規模であるほど大きく、また並列処理を行う場合においては、より大きなパフォーマンス低下がもたらされる事があると言われています。
※参考リンク: