Ceph - 「膝の上」から「本番」へ

CEPH を選択します。 パート1

3 つのラック、XNUMX 個の光スイッチ、設定済みの BGP、数十台の SSD、あらゆる色とサイズの SAS ディスクの束、そして proxmox があり、すべての静的データを独自の SXNUMX ストレージに置きたいという要望がありました。 仮想化にこれらすべてが必要というわけではありませんが、オープンソースを使い始めたら、最後まで自分の趣味を追求してください。 唯一気になったのはBGPでした。 内部 BGP ルーティングほど無力で、無責任で、不道徳なものは世界中にありません。 そして、私たちはすぐにそれに飛び込むだろうということを知っていました。

Ceph - 「膝の上」から「本番」へ

タスクは簡単でした。CEPH はありましたが、あまりうまく機能しませんでした。 「良いこと」をする必要がありました。
私が受け取ったクラスターは異種混合で、急遽調整されたもので、実質的に調整されていませんでした。 これは、異なるノードの XNUMX つのグループで構成され、XNUMX つの共通グリッドがクラスターとパブリック ネットワークの両方として機能します。 ノードには XNUMX 種類のディスク (XNUMX つの別個の配置ルールで収集された XNUMX 種類の SSD、および XNUMX 番目のグループに収集されたサイズの異なる XNUMX 種類の HDD) が搭載されています。 サイズが異なる場合の問題は、OSD の重みを変えることで解決されました。

セットアップ自体は XNUMX つの部分に分かれています - オペレーティングシステムのチューニング и CEPH自体のチューニング とその設定。

OSのアップグレード

ネットワーク

レイテンシーが長いと、録音とバランシングの両方に影響を与えました。 記録時 - 他の配置グループのデータ レプリカが成功を確認するまで、クライアントは記録の成功に関する応答を受信しないためです。 CRUSH マップでレプリカを配布するルールはホストごとに XNUMX つのレプリカであるため、常にネットワークが使用されました。

したがって、私が最初に行うことにしたのは、現在のネットワークを少し調整すると同時に、別のネットワークに移行するよう説得することでした。

まず、ネットワークカードの設定を微調整しました。 まずキューを設定しました。

どうしたの:

ethtool -l ens1f1

root@ceph01:~# ethtool -l ens1f1
Channel parameters for ens1f1:
Pre-set maximums:
RX:     0
TX:     0
Other:      1
Combined:   63
Current hardware settings:
RX:     0
TX:     0
Other:      1
Combined:   1
root@ceph01:~# ethtool -g ens1f1
Ring parameters for ens1f1:
Pre-set maximums:
RX:     4096
RX Mini:    0
RX Jumbo:   0
TX:     4096
Current hardware settings:
RX:     256
RX Mini:    0
RX Jumbo:   0
TX:     256
root@ceph01:~# ethtool -l ens1f1
Channel parameters for ens1f1:
Pre-set maximums:
RX:     0
TX:     0
Other:      1
Combined:   63
Current hardware settings:
RX:     0
TX:     0
Other:      1
Combined:   1

現在のパラメータが最大値からはほど遠いことがわかります。 増加:

root@ceph01:~#ethtool -G ens1f0 rx 4096
root@ceph01:~#ethtool -G ens1f0 tx 4096
root@ceph01:~#ethtool -L ens1f0 combined 63

優れた記事に導かれて

https://blog.packagecloud.io/eng/2017/02/06/monitoring-tuning-linux-networking-stack-sending-data/

送信キューの長さが長くなりました テクスキューレン 1000から10まで

root@ceph01:~#ip link set ens1f0  txqueuelen 10000

さて、ceph 自体のドキュメントに従ってください

https://ceph.com/geen-categorie/ceph-loves-jumbo-frames/

増加した MTU 9000に。

root@ceph01:~#ip link set dev ens1f0  mtu 9000

上記のすべてが起動時にロードされるように /etc/network/interfaces に追加

cat / etc / network / interfaces

root@ceph01:~# cat /etc/network/interfaces
auto lo
iface lo inet loopback

auto ens1f0
iface ens1f0 inet manual
post-up /sbin/ethtool -G ens1f0 rx 4096
post-up /sbin/ethtool -G ens1f0 tx 4096
post-up /sbin/ethtool -L ens1f0 combined 63
post-up /sbin/ip link set ens1f0  txqueuelen 10000
mtu 9000

auto ens1f1
iface ens1f1 inet manual
post-up /sbin/ethtool -G ens1f1 rx 4096
post-up /sbin/ethtool -G ens1f1 tx 4096
post-up /sbin/ethtool -L ens1f1 combined 63
post-up /sbin/ip link set ens1f1  txqueuelen 10000
mtu 9000

その後、同じ記事に従って、4.15 カーネルのハンドルを慎重に調整し始めました。 ノードに 128G RAM があることを考慮すると、最終的には次の構成ファイルになりました。 sysctl

cat /etc/sysctl.d/50-ceph.conf

net.core.rmem_max = 56623104  
#Максимальный размер буфера приема данных для всех соединений  54M
net.core.wmem_max = 56623104
#Максимальный размер буфера передачи данных для всех соединений 54M
net.core.rmem_default = 56623104
#Размер буфера приема данных по умолчанию для всех соединений. 54M
net.core.wmem_default = 56623104
#Размер буфера передачи данных по умолчанию для всех соединений 54M  
# на каждый сокет
net.ipv4.tcp_rmem = 4096 87380 56623104
#Векторная (минимум, по умолчанию, максимум) переменная в файле tcp_rmem
# содержит 3 целых числа, определяющих размер приемного буфера сокетов TCP.
# Минимум: каждый сокет TCP имеет право использовать эту память по 
# факту своего создания. Возможность использования такого буфера 
# гарантируется даже при достижении порога ограничения (moderate memory pressure).
# Размер минимального буфера по умолчанию составляет 8 Кбайт (8192).
#Значение по умолчанию: количество памяти, допустимое для буфера 
# передачи сокета TCP по умолчанию. Это значение применяется взамен
# параметра /proc/sys/net/core/rmem_default, используемого другими протоколами.
# Значение используемого по умолчанию буфера обычно (по умолчанию) 
# составляет 87830 байт. Это определяет размер окна 65535 с 
# заданным по умолчанию значением tcp_adv_win_scale и tcp_app_win = 0, 
# несколько меньший, нежели определяет принятое по умолчанию значение tcp_app_win.
# Максимум: максимальный размер буфера, который может быть автоматически
# выделен для приема сокету TCP. Это значение не отменяет максимума, 
# заданного в файле /proc/sys/net/core/rmem_max. При «статическом»
# выделении памяти с помощью SO_RCVBUF этот параметр не имеет значения.
net.ipv4.tcp_wmem = 4096 65536 56623104
net.core.somaxconn = 5000    
# Максимальное число открытых сокетов, ждущих соединения.
net.ipv4.tcp_timestamps=1
# Разрешает использование временных меток (timestamps), в соответствии с RFC 1323.
net.ipv4.tcp_sack=1
# Разрешить выборочные подтверждения протокола TCP
net.core.netdev_max_backlog=5000 (дефолт 1000)
# максимальное количество пакетов в очереди на обработку, если 
# интерфейс получает пакеты быстрее, чем ядро может их обработать.
net.ipv4.tcp_max_tw_buckets=262144
# Максимальное число сокетов, находящихся в состоянии TIME-WAIT одновременно.
# При превышении этого порога – «лишний» сокет разрушается и пишется
# сообщение в системный журнал.
net.ipv4.tcp_tw_reuse=1
#Разрешаем повторное использование TIME-WAIT сокетов в случаях,
# если протокол считает это безопасным.
net.core.optmem_max=4194304
#Увеличить максимальный общий буфер-космической ALLOCATABLE
#измеряется в единицах страниц (4096 байт)
net.ipv4.tcp_low_latency=1
#Разрешает стеку TCP/IP отдавать предпочтение низкому времени ожидания
# перед более высокой пропускной способностью.
net.ipv4.tcp_adv_win_scale=1
# Эта переменная влияет на вычисление объема памяти в буфере сокета,
# выделяемой под размер TCP-окна и под буфер приложения.
# Если величина tcp_adv_win_scale отрицательная, то для вычисления размера
# используется следующее выражение:
# Bytes- bytes2в степени -tcp_adv_win_scale
# Где bytes – это размер окна в байтах. Если величина tcp_adv_win_scale
# положительная, то для определения размера используется следующее выражение:
# Bytes- bytes2в степени tcp_adv_win_scale
# Переменная принимает целое значение. Значение по-умолчанию – 2, 
# т.е. под буфер приложения отводится ¼ часть объема, определяемого переменной
# tcp_rmem.
net.ipv4.tcp_slow_start_after_idle=0
# механизм перезапуска медленного старта, который сбрасывает значение окна 
# перегрузки, если соединение не использовалось заданный период времени.
# Лучше отключить SSR на сервере, чтобы улучшить производительность 
# долгоживущих соединений.
net.ipv4.tcp_no_metrics_save=1
#Не сохранять результаты измерений TCP соединения в кеше при его закрытии.
net.ipv4.tcp_syncookies=0
#Отключить механизм отправки syncookie
net.ipv4.tcp_ecn=0
#Explicit Congestion Notification (Явное Уведомление о Перегруженности) в 
# TCP-соединениях. Используется для уведомления о возникновении «затора» 
# на маршруте к заданному хосту или сети. Может использоваться для извещения
# хоста-отправителя о необходимости снизить скорость передачи пакетов через
# конкретный маршрутизатор или брандмауэр.
net.ipv4.conf.all.send_redirects=0
# выключает выдачу ICMP Redirect … другим хостам. Эта опция обязательно
# должна быть включена, если хост выступает в роли маршрутизатора любого рода.
# У нас нет маршрутизации.
net.ipv4.ip_forward=0
#Сопсно отключение форвардинга. Мы не шлюз, докер на машинах не поднят,
# нам это не нужно.
net.ipv4.icmp_echo_ignore_broadcasts=1
#Не отвечаем на ICMP ECHO запросы, переданные широковещательными пакетами
net.ipv4.tcp_fin_timeout=10
#определяет время сохранения сокета в состоянии FIN-WAIT-2 после его
# закрытия локальной стороной. Дефолт 60
net.core.netdev_budget=600 # (дефолт 300)
# Если выполнение программных прерываний не выполняются достаточно долго,
# то темп роста входящих данных может превысить возможность ядра 
# опустошить буфер. В результате буферы NIC переполнятся, и трафик будет потерян.
# Иногда, необходимо увеличить длительность работы SoftIRQs
# (программных прерываний) с CPU. За это отвечает netdev_budget. 
# Значение по умолчанию 300. Параметр заставит процесс SoftIRQ обработать
# 300 пакетов от NIC перед тем как отпустить CPU
net.ipv4.tcp_fastopen=3
# TFO TCP Fast Open
# если и клиент и сервер имеют поддержку TFO, о которой сообщают за счет
# специального флага в TCP пакете. В нашем случае является плацебо, просто
# выглядит красиво)

С光沢ネットワーク は、別の 10Gbps ネットワーク インターフェイスに別のフラット ネットワークに割り当てられました。 各マシンにはデュアルポート ネットワーク カードが装備されていました。 メラノックス 10/25 Gbps、10 つの個別の 16 Gbps スイッチに接続。 OSPF を使用して集約が実行されました。これは、lacp を使用したボンディングでは、何らかの理由で合計最大 XNUMX Gbps のスループットが示されたためです。一方、ospf は、各マシンで両方の XNUMX Gbps をうまく利用できました。 将来の計画では、これらのメラノックスで ROCE を利用して遅延を短縮する予定でした。 ネットワークのこの部分を設定する方法:

  1. マシン自体は BGP 上の外部 IP アドレスを持っているため、ソフトウェアが必要です。 (正確に言うと、この記事を書いている時点では frr=6.0-1 ) すでに立っていた。
  2. 合計で、マシンには 4 つのネットワーク インターフェイスがあり、それぞれに XNUMX つのインターフェイスがあり、合計 XNUMX つのポートがありました。 XNUMX つのネットワーク カードは XNUMX つのポートを備えた工場出荷時に確認され、BGP が構成されていました。XNUMX つ目のネットワーク カードは、XNUMX つのポートを備えた XNUMX つの異なるスイッチを確認し、OSPF が設定されていました。

OSPF の設定の詳細: 主なタスクは、XNUMX つのリンクを集約し、フォールト トレランスを実現することです。
10.10.10.0 つのネットワーク インターフェイスは、24 つのシンプルなフラット ネットワーク (10.10.20.0/24 および XNUMX/XNUMX) に構成されます。

1: ens1f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc mq state UP group default qlen 1000
inet 10.10.10.2/24 brd 10.10.10.255 scope global ens1f0
2: ens1f1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc mq state UP group default qlen 1000
inet 10.10.20.2/24 brd 10.10.20.255 scope global ens1f1

どの車がお互いを認識するかによって。

ディスク

次のステップはディスクを最適化することでした。 SSDの場合、スケジューラを次のように変更しました ヌープ、HDD用 - 締め切り。 率直に言うと、NOOP は「先入れ先出し」の原則に基づいて動作します。英語では「FIFO (First In First Out)」のように聞こえます。 リクエストは到着するとキューに入れられます。 DEADLINE はより読み取り指向であり、キューに入れられたプロセスは操作時にディスクへのほぼ排他的なアクセスを取得します。 これは私たちのシステムに最適です。結局のところ、各ディスクで動作するプロセスは OSD デーモン XNUMX つだけです。
(I/O スケジューラについて詳しく知りたい方は、ここでそれについて読むことができます:
http://www.admin-magazine.com/HPC/Articles/Linux-I-O-Schedulers

ロシア語で読みたい人: https://www.opennet.ru/base/sys/linux_shedulers.txt.html)

Linux のチューニングに関する推奨事項では、nr_request を増やすことも推奨されています。

nr_requests
nr_requests の値は、I/O スケジューラがブロック デバイスにデータを送受信する前にバッファリングされる I/O リクエストの量を決定します。これは、I/O リクエストの値よりも大きなキューを処理できる RAID カード/ブロック デバイスを使用している場合に発生します。 /O スケジューラが に設定されている場合、nr_requests の値を上げると、サーバー上で大量の I/O が発生した場合に、全体的な改善とサーバーの負荷の軽減に役立つ可能性があります。 Deadline または CFQ をスケジューラとして使用している場合は、nr_request 値をキューの深さの値の 2 倍に設定することをお勧めします。

しかし! CEPH の開発者である国民自身が、彼らの優先順位システムがより適切に機能すると私たちに確信させています。

Ceph - 「膝の上」から「本番」へ

WBThrottle および/または nr_requests

WBThrottle および/または nr_requests
ファイル ストレージは書き込みにバッファリングされた I/O を使用します。 ファイル ストレージ ログが高速メディアにある場合、これにより多くの利点がもたらされます。 クライアント要求は、データがログに書き込まれるとすぐに通知され、後で標準の Linux 機能を使用してデータ ディスク自体にフラッシュされます。 これにより、スピンドル OSD は、小さなバーストで書き込むときに SSD と同様の書き込みレイテンシを実現できます。 この遅延ライトバックにより、カーネル自体がディスク I/O リクエストを再編成し、それらをマージするか、既存のディスク ヘッドがプラッター上でより最適なパスを選択できるようにすることもできます。 最終的な効果は、直接 I/O または同期 I/O で可能となるよりもわずかに多くの I/O を各ディスクから絞り出すことができることです。

ただし、特定の Ceph クラスターに受信されるレコードの量が、基礎となるディスクのすべての能力を超える場合、特定の問題が発生します。 このシナリオでは、ディスクへの書き込みを待機している保留中の I/O 操作の合計数が制御不能に増加し、その結果、I/O キューがディスク全体と Ceph キューをいっぱいにする可能性があります。 読み取りリクエストは書き込みリクエスト間でスタックするため、特に影響を受けます。プライマリ ディスクにフラッシュするまでに数秒かかる場合があります。

この問題を解決するために、Ceph には WBThrottle と呼ばれるライトバック スロットル メカニズムがファイル ストレージに組み込まれています。 これは、カーネル自体によって有効になっているために自然に発生するよりも早く、キューに入れてフラッシュ プロセスを開始できる遅延書き込み I/O の全体量を制限するように設計されています。 残念ながら、テストの結果、デフォルト値では読み取りレイテンシへの影響を軽減できるレベルまで既存の動作を軽減できない可能性があることが判明しました。 調整によりこの動作が変更され、書き込みキュー全体の長さが短縮され、この影響が軽減される可能性があります。 ただし、トレードオフがあります。キューに入れることができるエントリの全体的な最大数を減らすことにより、受信リクエストの順序付けの効率を最大化するカーネル自体の能力が低下する可能性があります。 特定のユースケースやワークロードにさらに何が必要かを少し考え、それらに合わせて調整することは価値があります。

このような書き込みバックログ キューの深さを制御するには、WBThrottle 設定を使用して未処理の I/O 操作の全体の最大数を減らすか、カーネル自体のブロック レベルで未処理の操作の最大値を減らすことができます。 どちらも同じ動作を効果的に制御でき、ユーザーの設定がこの設定の実装の基礎となります。
Ceph の操作優先順位システムは、ディスク レベルでの短いクエリの方が効率的であることにも注意してください。 キュー全体を特定のディスクに縮小することで、キューの主な場所が Ceph に移動し、I/O 操作の優先順位をより詳細に制御できるようになります。 次の例を考えてみましょう。

echo 8 > /sys/block/sda/queue/nr_requests

http://onreader.mdl.ru/MasteringCeph/content/Ch09.html#030202

COMMON

さらにカーネルをいくつか調整して、車を柔らかく滑らかにし、ハードウェアのパフォーマンスを少しだけ引き出します。

cat /etc/sysctl.d/60-ceph2.conf

 kernel.pid_max = 4194303
#Дисков в каждой машине по 25, потому рассчитывали что процессов будет много
kernel.threads-max=2097152
# Тредов, естессно, тоже.
vm.max_map_count=524288
# Увеличили количество областей карты памяти процесса. 
# Как следует из документации по ядерным переменным 
# Области карты памяти используется как побочный эффект вызова
# malloc, напрямую с помощью mmap, mprotect и madvise, а также при загрузке
# общих библиотек.
fs.aio-max-nr=50000000
# Подтюним параметры input-output
# Ядро Linux предоставляет функцию асинхронного неблокирующего ввода-вывода (AIO),
# которая позволяет процессу инициировать несколько операций ввода-вывода
# одновременно, не дожидаясь завершения какой-либо из них. 
# Это помогает повысить производительность приложений, 
# которые могут перекрывать обработку и ввод-вывод.
# Параметр aio-max-nr определяет максимальное количество допустимых 
# одновременных запросов.
vm.min_free_kbytes=1048576
# минимальный размер свободной памяти который необходимо поддерживать.
# Выставлен 1Gb, чего вполне достаточно для работы операционной системы, 
# и позволяет избегать OOM Killer для процессов OSD. Хотя памяти и так
# как у дурака фантиков, но запас карман не тянет
vm.swappiness=10
# Говорим использовать своп если осталось свободным 10% памяти.
# На машинах 128G оперативы, и 10% это 12 Гигов. Более чем достаточно для работы.
# Штатный параметр в 60% заставлял тормозить систему, залезая в своп,
# когда есть еще куча свободной памяти
vm.vfs_cache_pressure=1000
# Увеличиваем со штатных 100. Заставляем ядро активнее выгружать
# неиспользуемые страницы памяти из кеша.
vm.zone_reclaim_mode=0
# Позволяет  устанавливать более или менее агрессивные подходы к
# восстановлению памяти, когда в зоне заканчивается память. 
# Если он установлен на ноль, то не происходит восстановление зоны.
# Для файловых серверов или рабочих нагрузок
# выгодно, если их данные кэшированы, zone_reclaim_mode
# оставить отключенным, поскольку эффект кэширования, 
# вероятно, будет более важным, чем местонахождение данных.
vm.dirty_ratio=20
# Процент оперативной памяти, который можно выделить под "грязные" страницы
# Вычисляли из примерного расчета: 
# В система 128 гигов памяти.
# Примерно по 20 дисков SSD, у которых в настройках CEPH указано 
# выделять под кэширование по 3G оперативы.
# Примерно по 40 дисков HDD, для которых этот параметр равен 1G
# 20% от 128 это 25.6 гигов. Итого, в случае максимальной утилизации памяти,
# для системы останется 2.4G памяти. Чего ей должно хватить чтоб выжить и дождаться
# стука копыт кавалерии - то есть пришествия DevOps который все починит.
vm.dirty_background_ratio=3
# процент системной памяти, который можно заполнить dirty pages до того,
# как фоновые процессы pdflush/flush/kdmflush запишут их на диск
fs.file-max=524288
# Ну и открытых файлов у нас,вероятно, будет сильно больше, чем указано по дефолту. 

CEPH への浸漬

さらに詳しく説明したい設定:

猫 /etc/ceph/ceph.conf

osd:
journal_aio: true               # Три параметра, включающие 
journal_block_align: true       # прямой i/o
journal_dio: true               # на журнал
journal_max_write_bytes: 1073714824 # Немного растянем максимальный размер
# разово записываемой операции в журнал
journal_max_write_entries: 10000    # Ну и количество одновременных записей
journal_queue_max_bytes: 10485760000 
journal_queue_max_ops: 50000
rocksdb_separate_wal_dir: true      # Решили делать отдельный wal                                                                            
# Даже попытались выбить под это дело                                                                                                                                                                                     
# NVMe
bluestore_block_db_create: true     # Ну и под журнал отдельное устройство
bluestore_block_db_size: '5368709120 #5G'
bluestore_block_wal_create: true
bluestore_block_wal_size: '1073741824   #1G' 
bluestore_cache_size_hdd: '3221225472   # 3G' 
# большой объем оперативы позволяет 
# хранить достаточно большие объемы
bluestore_cache_size_ssd: '9663676416   # 9G' 
keyring: /var/lib/ceph/osd/ceph-$id/keyring
osd_client_message_size_cap: '1073741824 #1G'
osd_disk_thread_ioprio_class: idle
osd_disk_thread_ioprio_priority: 7
osd_disk_threads: 2 # количество тредов у демона на один диск
osd_failsafe_full_ratio: 0.95
osd_heartbeat_grace: 5
osd_heartbeat_interval: 3
osd_map_dedup: true
osd_max_backfills: 2 # количество одновременных операций заполнения на один ОСД.
osd_max_write_size: 256
osd_mon_heartbeat_interval: 5
osd_op_threads: 16
osd_op_num_threads_per_shard: 1
osd_op_num_threads_per_shard_hdd: 2
osd_op_num_threads_per_shard_ssd: 2
osd_pool_default_min_size: 1     # Особенности жадности. Очень быстро стало
osd_pool_default_size: 2         # нехватать места, потому как временное                                                                                                                                                      
# решение приняли уменьшение количество 
# реплик данных
osd_recovery_delay_start: 10.000000
osd_recovery_max_active: 2
osd_recovery_max_chunk: 1048576
osd_recovery_max_single_start: 3
osd_recovery_op_priority: 1
osd_recovery_priority: 1            # параметр регулируем по необходимости на ходу
osd_recovery_sleep: 2
osd_scrub_chunk_max: 4

バージョン 12.2.12 で QA 用にテストされたパラメータの一部は、ceph バージョン 12.2.2 では欠落しています。たとえば、 osd_recovery_threads。 したがって、計画には 12.2.12 への本番環境の更新が含まれていました。 実践では、12.2.2 つのクラスター内でバージョン 12.2.12 と XNUMX 間の互換性が確認されており、ローリング アップデートが可能です。

テストクラスター

当然、テストには実戦時と同じバージョンが必要ですが、私がクラスターを使い始めた時点では、リポジトリには新しいバージョンしかありませんでした。 見てみると、マイナー バージョンで確認できることはそれほど大きくありません (1393 に対する構成内の行 1436 新しいバージョンで)、新しいバージョンのテストを開始することにしました(とにかく更新します。なぜ古いジャンクを使用するのですか)

私たちが古いバージョンを残そうとした唯一のものはパッケージです ceph-デプロイ 一部のユーティリティ (および一部の従業員) がその構文に合わせて調整されているためです。 新しいバージョンはかなり異なりましたが、クラスター自体の動作には影響せず、バージョンに残されました。 1.5.39

ceph-disk コマンドには、非推奨であるため ceph-volume コマンドを使用することが明確に記載されているため、古いものに時間を無駄にすることなく、このコマンドを使用して OSD の作成を開始しました。

計画では、XNUMX 台の SSD ドライブのミラーを作成し、そこに OSD ログを配置し、そのミラーをスピンドル SAS に配置することでした。 こうすることで、ログが保存されたディスクが落下した場合でもデータの問題から身を守ることができます。

ドキュメントに従ってクラスターの作成を開始しました

猫 /etc/ceph/ceph.conf

root@ceph01-qa:~# cat /etc/ceph/ceph.conf # положили заранее подготовленный конфиг
[client]
rbd_cache = true
rbd_cache_max_dirty = 50331648
rbd_cache_max_dirty_age = 2
rbd_cache_size = 67108864
rbd_cache_target_dirty = 33554432
rbd_cache_writethrough_until_flush = true
rbd_concurrent_management_ops = 10
rbd_default_format = 2
[global]
auth_client_required = cephx
auth_cluster_required = cephx
auth_service_required = cephx
cluster network = 10.10.10.0/24
debug_asok = 0/0
debug_auth = 0/0
debug_buffer = 0/0
debug_client = 0/0
debug_context = 0/0
debug_crush = 0/0
debug_filer = 0/0
debug_filestore = 0/0
debug_finisher = 0/0
debug_heartbeatmap = 0/0
debug_journal = 0/0
debug_journaler = 0/0
debug_lockdep = 0/0
debug_mon = 0/0
debug_monc = 0/0
debug_ms = 0/0
debug_objclass = 0/0
debug_objectcatcher = 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_rgw = 0/0
debug_throttle = 0/0
debug_timer = 0/0
debug_tp = 0/0
fsid = d0000000d-4000-4b00-b00b-0123qwe123qwf9
mon_host = ceph01-q, ceph02-q, ceph03-q
mon_initial_members = ceph01-q, ceph02-q, ceph03-q
public network = 8.8.8.8/28 # адрес изменен, естественно ))
rgw_dns_name = s3-qa.mycompany.ru # и этот адрес измен
rgw_host = s3-qa.mycompany.ru # и этот тоже
[mon]
mon allow pool delete = true
mon_max_pg_per_osd = 300 # больше трехсот плейсмент групп
# на диск не решились
# хотя параметр, естественно, зависит от количества пулов,
# их размеров и количества OSD. Иметь мало но здоровых PG
# тоже не лучший выбор - страдает точность балансировки
mon_osd_backfillfull_ratio = 0.9
mon_osd_down_out_interval = 5
mon_osd_full_ratio = 0.95 # пока для SSD дисков местом для их
# журнала является тот-же девайс что и для ОСД
# решили что 5% от диска (который сам размером 1.2Tb)
#  должно вполне хватить, и коррелирует с параметром
# bluestore_block_db_size плюс вариативность на большие 
# плейсмент группы
mon_osd_nearfull_ratio = 0.9
mon_pg_warn_max_per_osd = 520
[osd]
bluestore_block_db_create = true
bluestore_block_db_size = 5368709120 #5G
bluestore_block_wal_create = true
bluestore_block_wal_size = 1073741824 #1G
bluestore_cache_size_hdd = 3221225472 # 3G
bluestore_cache_size_ssd = 9663676416 # 9G
journal_aio = true
journal_block_align = true
journal_dio = true
journal_max_write_bytes = 1073714824
journal_max_write_entries = 10000
journal_queue_max_bytes = 10485760000
journal_queue_max_ops = 50000
keyring = /var/lib/ceph/osd/ceph-$id/keyring
osd_client_message_size_cap = 1073741824 #1G
osd_disk_thread_ioprio_class = idle
osd_disk_thread_ioprio_priority = 7
osd_disk_threads = 2
osd_failsafe_full_ratio = 0.95
osd_heartbeat_grace = 5
osd_heartbeat_interval = 3
osd_map_dedup = true
osd_max_backfills = 4
osd_max_write_size = 256
osd_mon_heartbeat_interval = 5
osd_op_num_threads_per_shard = 1
osd_op_num_threads_per_shard_hdd = 2
osd_op_num_threads_per_shard_ssd = 2
osd_op_threads = 16
osd_pool_default_min_size = 1
osd_pool_default_size = 2
osd_recovery_delay_start = 10.0
osd_recovery_max_active = 1
osd_recovery_max_chunk = 1048576
osd_recovery_max_single_start = 3
osd_recovery_op_priority = 1
osd_recovery_priority = 1
osd_recovery_sleep = 2
osd_scrub_chunk_max = 4
osd_scrub_chunk_min = 2
osd_scrub_sleep = 0.1
rocksdb_separate_wal_dir = true

# создаем мониторы
root@ceph01-qa:~#ceph-deploy mon create ceph01-q
# генерируем ключи для аутентификации нод в кластере
root@ceph01-qa:~#ceph-deploy gatherkeys ceph01-q
# Это если поштучно. Если у нас несколько машин доступны - те, которые описаны в конфиге в секции 
# mon_initial_members = ceph01-q, ceph02-q, ceph03-q
# можно запустить эти две команды в виде одной
root@ceph01-qa:~#ceph-deploy mon create-initial
# Положим ключи в указанные в конфиге места
root@ceph01-qa:~#cat ceph.bootstrap-osd.keyring > /var/lib/ceph/bootstrap-osd/ceph.keyring 
root@ceph01-qa:~#cat ceph.bootstrap-mgr.keyring > /var/lib/ceph/bootstrap-mgr/ceph.keyring 
root@ceph01-qa:~#cat ceph.bootstrap-rgw.keyring > /var/lib/ceph/bootstrap-rgw/ceph.keyring
# создадим ключ для управления кластером
root@ceph01-qa:~#ceph-deploy admin ceph01-q
# и менеджер, плагинами управлять
root@ceph01-qa:~#ceph-deploy mgr create ceph01-q

クラスターバージョン 12.2.12 でこのバージョンの ceph-deploy を使用しているときに最初につまずいたのは、ソフトウェア RAID で db を使用して OSD を作成しようとしたときのエラーでした。

root@ceph01-qa:~#ceph-volume lvm create --bluestore --data /dev/sde --block.db /dev/md0
blkid could not detect a PARTUUID for device: /dev/md1

確かに、blkid は PARTUUID ではないようなので、パーティションを手動で作成する必要がありました。

root@ceph01-qa:~#parted /dev/md0 mklabel GPT 
# разделов будет много, 
# без GPT их создать не получится
# размер раздела мы указали в конфиге выше = bluestore_block_db_size: '5368709120 #5G'
# Дисков у меня 20 под OSD, руками создавать разделы лень
# потому сделал цикл
root@ceph01-qa:~#for i in {1..20}; do echo -e "nnnn+5Gnw" | fdisk /dev/md0; done

すべての準備ができているようです。OSD を再度作成しようとすると、次のエラーが表示されます (ちなみに、戦闘では再現されませんでした)。

WAL へのパスを指定せずに db を指定して、bluestore タイプの OSD を作成する場合

root@ceph01-qa:~#ceph-volume lvm create --bluestore --data /dev/sde --block.db /dev/md0
stderr: 2019-04-12 10:39:27.211242 7eff461b6e00 -1 bluestore(/var/lib/ceph/osd/ceph-0/) _read_fsid unparsable uuid
stderr: 2019-04-12 10:39:27.213185 7eff461b6e00 -1 bdev(0x55824c273680 /var/lib/ceph/osd/ceph-0//block.wal) open open got: (22) Invalid argument
stderr: 2019-04-12 10:39:27.213201 7eff461b6e00 -1 bluestore(/var/lib/ceph/osd/ceph-0/) _open_db add block device(/var/lib/ceph/osd/ceph-0//block.wal) returned: (22) Invalid argument
stderr: 2019-04-12 10:39:27.999039 7eff461b6e00 -1 bluestore(/var/lib/ceph/osd/ceph-0/) mkfs failed, (22) Invalid argument
stderr: 2019-04-12 10:39:27.999057 7eff461b6e00 -1 OSD::mkfs: ObjectStore::mkfs failed with error (22) Invalid argument
stderr: 2019-04-12 10:39:27.999141 7eff461b6e00 -1  ** ERROR: error creating empty object store in /var/lib/ceph/osd/ceph-0/: (22) Invalid argumen

さらに、同じミラー上 (または選択した別の場所) に WAL 用に別のパーティションを作成し、OSD の作成時にそれを指定すると、すべてがスムーズに進みます (別個の WAL の外観を除いて、これは実行できない場合があります)。欲しかった)。

しかし、WAL を NVMe に移行することはまだ遠い計画にあったため、この実践は不必要であるとは言えませんでした。

root@ceph01-qa:~#ceph-volume lvm create --bluestore --data /dev/sdf --block.wal  /dev/md0p2 --block.db /dev/md1p2

モニター、マネージャー、OSD を作成しました。 ここで、異なるタイプのディスク (SSD 上の高速プールと、SAS パンケーキ上の大規模だが遅いプール) を使用する予定なので、それらを別の方法でグループ化したいと思います。

サーバーに 20 個のディスクがあり、最初の XNUMX 個が XNUMX つのタイプで、XNUMX 番目が別のタイプであると仮定します。
初期のデフォルトのカードは次のようになります。

Ceph OSD ツリー

root@ceph01-q:~# ceph osd ツリー
ID クラス 重み タイプ 名前 ステータス リウェイト PRI-AFF
-1 14.54799 ルートのデフォルト
-3 9.09200 ホスト ceph01-q
0 ssd 1.00000 osd.0 アップ 1.00000 1.00000
1 ssd 1.00000 osd.1 アップ 1.00000 1.00000
2 ssd 1.00000 osd.2 アップ 1.00000 1.00000
3 ssd 1.00000 osd.3 アップ 1.00000 1.00000
4 HDD 1.00000 osd.4 アップ 1.00000 1.00000
5 HDD 0.27299 osd.5 アップ 1.00000 1.00000
6 HDD 0.27299 osd.6 アップ 1.00000 1.00000
7 HDD 0.27299 osd.7 アップ 1.00000 1.00000
8 HDD 0.27299 osd.8 アップ 1.00000 1.00000
9 HDD 0.27299 osd.9 アップ 1.00000 1.00000
10 HDD 0.27299 osd.10 アップ 1.00000 1.00000
11 HDD 0.27299 osd.11 アップ 1.00000 1.00000
12 HDD 0.27299 osd.12 アップ 1.00000 1.00000
13 HDD 0.27299 osd.13 アップ 1.00000 1.00000
14 HDD 0.27299 osd.14 アップ 1.00000 1.00000
15 HDD 0.27299 osd.15 アップ 1.00000 1.00000
16 HDD 0.27299 osd.16 アップ 1.00000 1.00000
17 HDD 0.27299 osd.17 アップ 1.00000 1.00000
18 HDD 0.27299 osd.18 アップ 1.00000 1.00000
19 HDD 0.27299 osd.19 アップ 1.00000 1.00000
-5 5.45599 ホスト ceph02-q
20 ssd 0.27299 osd.20 アップ 1.00000 1.00000
21 ssd 0.27299 osd.21 アップ 1.00000 1.00000
22 ssd 0.27299 osd.22 アップ 1.00000 1.00000
23 ssd 0.27299 osd.23 アップ 1.00000 1.00000
24 HDD 0.27299 osd.24 アップ 1.00000 1.00000
25 HDD 0.27299 osd.25 アップ 1.00000 1.00000
26 HDD 0.27299 osd.26 アップ 1.00000 1.00000
27 HDD 0.27299 osd.27 アップ 1.00000 1.00000
28 HDD 0.27299 osd.28 アップ 1.00000 1.00000
29 HDD 0.27299 osd.29 アップ 1.00000 1.00000
30 HDD 0.27299 osd.30 アップ 1.00000 1.00000
31 HDD 0.27299 osd.31 アップ 1.00000 1.00000
32 HDD 0.27299 osd.32 アップ 1.00000 1.00000
33 HDD 0.27299 osd.33 アップ 1.00000 1.00000
34 HDD 0.27299 osd.34 アップ 1.00000 1.00000
35 HDD 0.27299 osd.35 アップ 1.00000 1.00000
36 HDD 0.27299 osd.36 アップ 1.00000 1.00000
37 HDD 0.27299 osd.37 アップ 1.00000 1.00000
38 HDD 0.27299 osd.38 アップ 1.00000 1.00000
39 HDD 0.27299 osd.39 アップ 1.00000 1.00000
-7 6.08690 ホスト ceph03-q
40 ssd 0.27299 osd.40 アップ 1.00000 1.00000
41 ssd 0.27299 osd.41 アップ 1.00000 1.00000
42 ssd 0.27299 osd.42 アップ 1.00000 1.00000
43 ssd 0.27299 osd.43 アップ 1.00000 1.00000
44 HDD 0.27299 osd.44 アップ 1.00000 1.00000
45 HDD 0.27299 osd.45 アップ 1.00000 1.00000
46 HDD 0.27299 osd.46 アップ 1.00000 1.00000
47 HDD 0.27299 osd.47 アップ 1.00000 1.00000
48 HDD 0.27299 osd.48 アップ 1.00000 1.00000
49 HDD 0.27299 osd.49 アップ 1.00000 1.00000
50 HDD 0.27299 osd.50 アップ 1.00000 1.00000
51 HDD 0.27299 osd.51 アップ 1.00000 1.00000
52 HDD 0.27299 osd.52 アップ 1.00000 1.00000
53 HDD 0.27299 osd.53 アップ 1.00000 1.00000
54 HDD 0.27299 osd.54 アップ 1.00000 1.00000
55 HDD 0.27299 osd.55 アップ 1.00000 1.00000
56 HDD 0.27299 osd.56 アップ 1.00000 1.00000
57 HDD 0.27299 osd.57 アップ 1.00000 1.00000
58 HDD 0.27299 osd.58 アップ 1.00000 1.00000
59 HDD 0.89999 osd.59 アップ 1.00000 1.00000

ブラックジャックなどを使用して独自の仮想ラックとサーバーを作成してみましょう。

root@ceph01-q:~#ceph osd crush add-bucket rack01 root #создали новый root
root@ceph01-q:~#ceph osd crush add-bucket ceph01-q host #создали новый хост
root@ceph01-q:~#ceph osd crush move ceph01-q root=rack01 #переставили сервер в другую стойку
root@ceph01-q:~#osd crush add 28 1.0 host=ceph02-q # Добавили ОСД в сервер
# Если криво создали то можно удалить
root@ceph01-q:~# ceph osd crush remove osd.4
root@ceph01-q:~# ceph osd crush remove rack01

私たちが遭遇した問題 戦闘 クラスター、新しいホストを作成して既存のラックに移動しようとするとき - コマンド ceph osd クラッシュ移動 ceph01-host root=rack01 凍りつき、モニターが次々と落下し始めた。 単純な CTRL+C でコマンドを中止すると、クラスターは生きている世界に戻りました。

検索すると次の問題が見つかりました。 https://tracker.ceph.com/issues/23386

解決策は、クラッシュマップをダンプし、そこからセクションを削除することであることが判明しました ルールの複製_ルールセット

root@ceph01-prod:~#ceph osd getcrushmap -o crushmap.row #Дампим карту в сыром виде
root@ceph01-prod:~#crushtool -d crushmap.row -o crushmap.txt #переводим в читаемый
root@ceph01-prod:~#vim  crushmap.txt #редактируем, удаляя rule replicated_ruleset
root@ceph01-prod:~#crushtool -c crushmap.txt  -o new_crushmap.row #компилируем обратно
root@ceph01-prod:~#ceph osd setcrushmap -i  new_crushmap.row #загружаем в кластер

Achtung: この操作により、OSD 間の配置グループの再バランスが発生する可能性があります。 それは私たちにもこの問題を引き起こしましたが、ほんのわずかでした。

そして、テスト クラスターで遭遇した奇妙なことは、OSD サーバーを再起動した後、新しいサーバーとラックに移動したことを忘れて、ルートのデフォルトに戻ってしまったことでした。
その結果、SSD ドライブ用に別のルートを作成し、スピンドル ドライブ用に別のルートを作成するという最終的なスキームを組み立てた後、すべての OSD をラックに移し、デフォルトのルートを削除しました。 再起動後、OSD が所定の位置に留まり始めました。
後でドキュメントを調べたところ、この動作の原因となるパラメーターが見つかりました。 彼については第二部で

ディスクの種類ごとに異なるグループを作成する方法。

まず、SSD 用と HDD 用の XNUMX つのルートを作成しました。

root@ceph01-q:~#ceph osd crush add-bucket ssd-root root
root@ceph01-q:~#ceph osd crush add-bucket hdd-root root

サーバーは物理的に異なるラックに配置されているため、便宜上、サーバーを配置したラックを作成しました。

# Стойки:
root@ceph01-q:~#ceph osd crush add-bucket ssd-rack01 rack
root@ceph01-q:~#ceph osd crush add-bucket ssd-rack02 rack
root@ceph01-q:~#ceph osd crush add-bucket ssd-rack03 rack
root@ceph01-q:~#ceph osd crush add-bucket hdd-rack01 rack
root@ceph01-q:~#ceph osd crush add-bucket hdd-rack01 rack
root@ceph01-q:~#ceph osd crush add-bucket hdd-rack01 rack
# Сервера
root@ceph01-q:~#ceph osd crush add-bucket ssd-ceph01-q host
root@ceph01-q:~#ceph osd crush add-bucket ssd-ceph02-q host
root@ceph01-q:~#ceph osd crush add-bucket ssd-ceph03-q host
root@ceph01-q:~#ceph osd crush add-bucket hdd-ceph01-q host
root@ceph01-q:~#ceph osd crush add-bucket hdd-ceph02-q host
root@ceph01-q:~#ceph osd crush add-bucket hdd-ceph02-q host

ディスクを種類に応じて異なるサーバーに分散します。

root@ceph01-q:~# Диски с 0 по 3 это SSD, находятся в ceph01-q, ставим их в сервер 
root@ceph01-q:~#  ssd-ceph01-q
root@ceph01-q:~#ceph osd crush add 0 1 host=ssd-ceph01-q
root@ceph01-q:~#ceph osd crush add 1 1 host=ssd-ceph01-q
root@ceph01-q:~#ceph osd crush add 2 1 host=ssd-ceph01-q
root@ceph01-q:~#ceph osd crush add 3 1 host=ssd-ceph01-q
root-ceph01-q:~# аналогично с другими серверами

ディスクを ssd-root ルートと hdd-root ルートに分散させたので、root-default は空のままにして、削除できるようにしました。

root-ceph01-q:~#ceph osd crush remove default

次に、作成するプールにバインドする分散ルールを作成する必要があります。ルールでは、どのルートがプール データを配置できるか、およびレプリカの一意性のレベルを指定します。たとえば、レプリカは異なるサーバー上に存在する必要があります。または別のラックに配置します (そのようなディストリビューションがある場合は、別のルートに配置することもできます)

タイプを選択する前に、ドキュメントを読むことをお勧めします。
http://docs.ceph.com/docs/jewel/rados/operations/crush-map/#crushmaprules

root-ceph01-q:~#ceph osd crush rule create-simple rule-ssd ssd-root host firstn
root-ceph01-q:~#ceph osd crush rule create-simple rule-hdd hdd-root host firstn
root-ceph01-q:~# Мы указали два правила, в которых данные реплицируются 
root-ceph01-q:~# между хостами - то есть реплика должна лежать на другом хосте,
root-ceph01-q:~# даже если они в одной стойке
root-ceph01-q:~# В продакшене, если есть возможность, лучше распределить хосты
root-ceph01-q:~# по стойкам и указать распределять реплики по стойкам:
root-ceph01-q:~# ##ceph osd crush rule create-simple rule-ssd ssd-root rack firstn

さて、将来的に仮想化のディスク イメージを保存するプールを作成します - PROXMOX:

    root-ceph01-q:~# #ceph osd pool create {NAME} {pg_num}  {pgp_num}
root-ceph01-q:~# ceph osd pool create ssd_pool 1024 1024 
root-ceph01-q:~# ceph osd pool create hdd_pool 1024 1024

そして、これらのプールにどの配置ルールを使用するかを指示します

 root-ceph01-q:~#ceph osd crush rule ls # смотрим список правил
root-ceph01-q:~#ceph osd crush rule dump rule-ssd | grep rule_id #выбираем ID нужного
root-ceph01-q:~#ceph osd pool set ssd_pool crush_rule 2

配置グループの数の選択には、クラスターの既存のビジョン、つまりおよそいくつの OSD が存在するか、プール内にどのくらいのデータ量 (総ボリュームのパーセンテージとして) が含まれるか、何が含まれているかなどを考慮してアプローチする必要があります。データの総量。

合計で、ディスク上に 300 を超える配置グループを持たないことをお勧めします。また、小さな配置グループ (つまり、プール全体が 10 Tb を占有し、その中に 10 の PG がある場合) を使用するとバランスが取りやすくなります。テラバイトのレンガ (pg) を投げてバランスを取るのは問題があります。小さなサイズの砂粒を含む砂をバケツに注ぎやすく、より均等にします)。

ただし、PG の数が増えると、PG の位置を計算するためにより多くのリソースが費やされ、メモリと CPU が使用され始めることを覚えておく必要があります。

大まかに理解すると、 電卓をください、CEPH ドキュメントの開発者によって提供されます。

材料のリスト:

https://blog.packagecloud.io/eng/2017/02/06/monitoring-tuning-linux-networking-stack-sending-data
http://www.admin-magazine.com/HPC/Articles/Linux-I-O-Schedulers
http://onreader.mdl.ru/MasteringCeph/content/Ch09.html#030202
https://tracker.ceph.com/issues/23386
https://ceph.com/pgcalc/

出所: habr.com

コメントを追加します