Izbira CEPH. Del 1
Imeli smo pet omar, deset optičnih stikali, nastavljen BGP, nekaj deset SSD-jev in kup SAS diskov vseh barv in velikosti, pa še proxmox ter željo, da bi vso statiko spravili v lastno S3 skladišče. Ni bilo nujno vse to za virtualizacijo, ampak ko že uporabljaš opensource – potem se potrudi do konca. Edina stvar, ki me je skrbela, je bil BGP. Na svetu ni nikogar bolj nemočnega, brez odgovornosti in brez morale, kot notranje usmerjanje preko BGP. Vedel sem, da se bomo kmalu potopili v to.

Naloga je bila preprosta – imel sem CEPH, ki ni deloval najbolje. Treba je bilo izboljšati.
Klaster, ki sem ga podedoval, je bil raznolik, nastavljen na hitro in praktično brez optimizacije. Sestavljen je bil iz dveh skupin različnih vozlišč, z eno skupno mrežo, ki je opravljala vlogo tako klasterja kot javne mreže. Vozlišča so bila napolnjena s štirimi tipi diskov – dvema tipoma SSD, zbranima v dve ločeni pravili postavitve in dvema tipoma HDD različnih velikosti, zbranima v tretjo skupino. Težavo z različnimi velikostmi smo rešili z različnimi utežmi OSD.
Nastavitev smo razdelili na dve deli – tuning operacijskega sistema in tuning samega CEPH in njegovih nastavitev.
Nadgradnja OS
Mreža
Visoka latenca se je odražala tako pri pisanju kot pri uravnoteženju. Pri pisanju - ker stranka ne dobi odgovora o uspešnem pisanju, dokler replike podatkov v drugih skupinah ne potrdijo uspeha. Ker smo imeli pravila za razporeditev replik v CRUSH mapi z eno repliko na gostitelja, je bila mreža vedno v uporabi.
Zato sem se najprej odločil, da rahlo optimiziram trenutno mrežo, hkrati pa sem poskušal prepričati, da se preselimo na ločene mreže.
Na začetku sem prilagodil nastavitve omrežnih kartic. Začel sem z nastavitvijo vrstic:
kar je bilo:
ethtool -l ens1f1
root@ceph01:~# ethtool -l ens1f1
Parametri kanalov za ens1f1:
Prednastavljene maksime:
RX: 0
TX: 0
Ostalo: 1
Kombinirano: 63
Trenutne nastavitve strojne opreme:
RX: 0
TX: 0
Ostalo: 1
Kombinirano: 1
root@ceph01:~# ethtool -g ens1f1
Parametri obroča za ens1f1:
Prednastavljene maksime:
RX: 4096
RX Mini: 0
RX Jumbo: 0
TX: 4096
Trenutne nastavitve strojne opreme:
RX: 256
RX Mini: 0
RX Jumbo: 0
TX: 256
root@ceph01:~# ethtool -l ens1f1
Parametri kanalov za ens1f1:
Prednastavljene maksime:
RX: 0
TX: 0
Ostalo: 1
Kombinirano: 63
Trenutne nastavitve strojne opreme:
RX: 0
TX: 0
Ostalo: 1
Kombinirano: 1Vidno je, da so trenutni parametri daleč od maksimalnih. Povečal sem:
root@ceph01:~#ethtool -G ens1f0 rx 4096
root@ceph01:~#ethtool -G ens1f0 tx 4096
root@ceph01:~#ethtool -L ens1f0 combined 63V skladu z odličnim člankom
sem povečal dolžino pošiljanja vrste txqueuelen od 1000 do 10 000
root@ceph01:~#ip link set ens1f0 txqueuelen 10000Tako da, sledite dokumentaciji samog ceph
povećao MTU do 9000.
root@ceph01:~#ip link set dev ens1f0 mtu 9000Dodao u /etc/network/interfaces, da bi se sve navedeno učitavalo pri pokretanju
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 9000Nakon toga, prateći ovog istog članka, počeo sam pažljivo prilagođavati parametre jezgra 4.15. Uzimajući u obzir da na čvorovima ima 128G RAM, nastao je određeni konfiguracioni fajl za sysctl
cat /etc/sysctl.d/50-ceph.conf
net.core.rmem_max = 56623104
# Največja velikost prejemnega pomnilnika za vse povezave 54M
net.core.wmem_max = 56623104
# Največja velikost pošiljanja pomnilnika za vse povezave 54M
net.core.rmem_default = 56623104
# Privzeta velikost prejemnega pomnilnika za vse povezave. 54M
net.core.wmem_default = 56623104
# Privzeta velikost pošiljanja pomnilnika za vse povezave 54M
# na vsakem vtičniku
net.ipv4.tcp_rmem = 4096 87380 56623104
# Vektorska (minimum, privzeto, maksimum) spremenljivka v datoteki tcp_rmem
# vsebuje 3 cela števila, ki določajo velikost prejemnega pomnilnika vtičnikov TCP.
# Minimum: vsak vtičnik TCP ima pravico uporabljati to pomnilnik ob
# dejanskem nastanku. Možnost uporabe takega pomnilnika
# je zagotovljena tudi ob dosegi praga omejitve (zmerna obremenitev pomnilnika).
# Privzeta velikost najmanjšega pomnilnika znaša 8 Kbyte (8192).
#Privzeta vrednost: količina pomnilnika, dovoljena za pomnilnik
# pošiljanja vtičnika TCP privzeto. Ta vrednost se uporablja namesto
# parametra /proc/sys/net/core/rmem_default, ki ga uporabljajo drugi protokoli.
# Privzeta vrednost uporabljenega pomnilnika običajno (privzeto)
# znaša 87830 bajtov. To določa velikost okna 65535 s
# privzeto vrednostjo tcp_adv_win_scale in tcp_app_win = 0,
# nekoliko manj kot določa privzeta vrednost tcp_app_win.
# Maksimum: največja velikost pomnilnika, ki se lahko samodejno
# dodeli za prejem vtičniku TCP. Ta vrednost ne odpravi maksimuma,
# določenega v datoteki /proc/sys/net/core/rmem_max. Ob "statističnem"
# dodeljevanju pomnilnika s pomočjo SO_RCVBUF ta parameter nima pomena.
net.ipv4.tcp_wmem = 4096 65536 56623104
net.core.somaxconn = 5000
# Maksimalno število odprtih vtičnikov, ki čakajo na povezave.
net.ipv4.tcp_timestamps=1
# Omogoča uporabo časovnih žigov (timestamps) v skladu z RFC 1323.
net.ipv4.tcp_sack=1
# Omogočite izbirna potrjevanja TCP protokola
net.core.netdev_max_backlog=5000 (privzeto 1000)
# Maksimalno število paketov v čakalni vrsti za obdelavo, če
# vmesnik prejema pakete hitreje, kot jih jedro lahko obdela.
net.ipv4.tcp_max_tw_buckets=262144
# Maksimalno število vtičnikov, ki so hkrati v stanju TIME-WAIT.
# Pri presežku tega praga se "odvečna" vtičnika uniči in zapiše
# sporočilo v sistemski dnevnik.
net.ipv4.tcp_tw_reuse=1
#Dovoli ponovno uporabo TIME-WAIT vtičnikov v primerih,
# če protokol meni, da je to varno.
net.core.optmem_max=4194304
#Povečajte največji skupni pomnilnik ALLOCATABLE
# meri se v enotah strani (4096 bajt)
net.ipv4.tcp_low_latency=1
#Omogoča TCP/IP skladu, da daje prednost nizkemu času čakanja
# pred višjo propustnostjo.
net.ipv4.tcp_adv_win_scale=1
# Ta spremenljivka vpliva na izračun obsega pomnilnika v vtičniku,
# dodeljenega za velikost TCP-okna in za pomnilnik aplikacije.
# Če je vrednost tcp_adv_win_scale negativna, se za izračun velikosti
# uporablja naslednja enačba:
# Bytes - bytes2 na potenco -tcp_adv_win_scale
# Kjer bytes – je velikost okna v bajtih. Če je vrednost tcp_adv_win_scale
# pozitivna, se za določitev velikosti uporablja naslednja enačba:
# Bytes - bytes2 na potenco tcp_adv_win_scale
# Spremenljivka sprejema celo število. Privzeta vrednost je 2,
# torej je za pomnilnik aplikacije dodeljena ¼ dela obsega, ki ga določa spremenljivka
# tcp_rmem.
net.ipv4.tcp_slow_start_after_idle=0
# mehanizem ponovnega zagonavanja počasnega začetka, ki ponastavi vrednost okna
# preobremenitve, če povezava ni bila uporabljena določen čas.
# Bolje je onemogočiti SSR na strežniku za izboljšanje zmogljivosti
# dolgotrajnih povezav.
net.ipv4.tcp_no_metrics_save=1
#Ne shranjujte rezultatov meritev TCP povezave v predpomnilnik ob njeni zaprtju.
net.ipv4.tcp_syncookies=0
#Onemogočite mehanizem pošiljanja syncookie
net.ipv4.tcp_ecn=0
#Izrecno obvestilo o preobremenitvi v
# TCP povezavah. Uporablja se za obveščanje o pojavu "zastoja"
# na poti do določenega gostitelja ali omrežja. Lahko se uporablja za obveščanje
# gostitelja-pošiljatelja o potrebi po zmanjšanju hitrosti prenosa paketov skozi
# določen usmerjevalnik ali požarni zid.
net.ipv4.conf.all.send_redirects=0
# onemogoča izdajo ICMP Redirect … drugim gostiteljem. Ta možnost mora biti
# nujno omogočena, če gostitelj deluje kot usmerjevalnik kakršne koli vrste.
# Nimamo usmerjanja.
net.ipv4.ip_forward=0
#Lastno onemogočenje usmerjanja. Nismo prehod, Dockerji na strojih niso dvignjeni,
# tega ne potrebujemo.
net.ipv4.icmp_echo_ignore_broadcasts=1
#Ne odgovarjamo na ICMP ECHO prošnje, poslane v širinah
net.ipv4.tcp_fin_timeout=10
#določa čas, v katerem ostane vtičnik v stanju FIN-WAIT-2 po njegovi
# zaprtju s strani lokalne strani. Privzeto 60
net.core.netdev_budget=600 # (privzeto 300)
# Če izvajanje programskih prekinitev ni dovolj dolgo,
# lahko hitrost rasti prihajajočih podatkov preseže zmožnost jedra
# za praznjenje pomnilnika. Posledično se pomnilniški predpomnilniki NIC preplavijo, in promet bo izgubljen.
# Včasih je potrebno podaljšati trajanje delovanja SoftIRQs
# (programskih prekinitev) s CPU. Za to skrbi netdev_budget.
# Privzeta vrednost 300. Parameter bo proces SoftIRQ prisilil, da obdela
# 300 paketov od NIC pred tem, da pusti CPU
net.ipv4.tcp_fastopen=3
# TFO TCP Fast Open
# če ima tako odjemalec kot strežnik podporo TFO, o kateri obveščata
# poseben zastavek v TCP paketu. V našem primeru je to placebovski učinek, samo
# izgleda lepo)ZOmrežni je bila dodeljena na ločenih 10Gbps omrežnih vmesnikih v ločeno ravno omrežje. Na vsakem strežniku so bile nameščene dvoportne omrežne kartice. Mellanox 10/25 Gbps, vtičene v dva ločena 10Gbps stikala. Agregacija je bila izvedena s pomočjo OSPF, saj je vezanje z LACP nekako pokazalo skupno propustnost največ 16 Gbps, medtem ko je OSPF uspešno izkoristil polni pas na obeh desetkah na vsakem strežniku. V nadaljnjih načrtih je bilo izkoristiti ROCE na teh Mellanoxih za zmanjšanje latence. Kako smo nastavili ta del omrežja:
- Ker sami strežniki imajo zunanje IP naslove na BGP, potrebujemo program, (pravzaprav je bil ob času pisanja članka to ) že nameščen.
- Skupaj so imeli strežniki dve mrežni kartici, vsaka s po dvema vmesnikoma — skupaj 4 vrata. Ena mrežna kartica z dvema vratoma je gledala na tovarno in na njej je bil nastavljen BGP, druga — z dvema vratoma je gledala na dve različni stikali in na njo je bil usmerjen OSPF.
Podrobneje o nastavitvi OSPF: Glavna naloga je agregirati dve povezavi in imeti odpornost na napake.
dva omrežna vmesnika sta bila nastavljena v dve preprosti ravni omrežji — 10.10.10.0/24 in 10.10.20.0/24
1: ens1f0: mtu 9000 qdisc mq stanje UP skupina privzeto qlen 1000
inet 10.10.10.2/24 brd 10.10.10.255 obseg global ens1f0
2: ens1f1: mtu 9000 qdisc mq stanje UP skupina privzeto qlen 1000
inet 10.10.20.2/24 brd 10.10.20.255 obseg global ens1f1po katerih se strežniki med seboj vidijo.
DISK
Kot naslednji korak sem se odločil optimizirati delovanje diskov. Za SSD sem spremenil načrtovalnik na noop, za HDD — deadline. Če poenostavimo — NOOP deluje po načelu 'kdo prej pride, ta prej melje', kar v angleščini zveni kot 'FIFO (First In, First Out)'. Zahteve se postavijo v čakalno vrsto, ko pridejo. DEADLINE pa je bolj usmerjen na branje, plus postopek iz čakalne vrste dobi praktično monopolni dostop do diska v trenutku operacije. Za naš sistem je to odlično, saj z vsakim diskom dela le en proces — OSD daemon.
(Tisti, ki želijo poglobiti v načrtovalnik vnosa-izvoda, lahko o njem preberejo tukaj:
Tisti, ki raje berejo v ruščini: )
V priporočilih za optimizacijo Linuxa svetujejo tudi povečati nr_request
nr_requests
Vrednost nr_requests določa količino I/O zahtevkov, ki se shranijo v predpomnilniku, preden upravljalnik I/O pošlje/prejme podatke na blok napravo. Če uporabljate RAID kartico/blok napravo, ki lahko obvladuje večjo čakalno vrsto, kot je nastavljen upravljalnik I/O, lahko povečanje vrednosti nr_requests pripomore k izboljšanju skoziputja in zmanjša obremenitev strežnika, ko se na strežniku pojavijo velike količine I/O. Če uporabljate Deadline ali CFQ kot upravljalnik, se priporoča, da nastavite vrednost nr_request na 2-kratnik vrednosti globine čakalne vrste.
Vendar! Sami razvijalci CEPH nas prepričujejo, da njihov sistem prioritet deluje bolje.

WBThrottle in/ali nr_requests
WBThrottle in/ali nr_requests
Datotečni sistem uporablja za zapisovanje predpomnjene operacije vnosa/izvoda; to prinaša vrsto prednosti, če je dnevnik datotečnega sistema na hitrejšem nosilcu. Zahteve strank dobijo obvestila takoj, ko so podatki zapisani v dnevnik, nato se kasneje prenesejo na disk podatkov z uporabo standardne funkcionalnosti Linuxa. To omogoča OSD vrtečim diskih, da nudijo latenco zapisa, ki je primerljiva SSD-jem pri zapisih majhnimi paketi. Ta zakasnjen zapis tudi omogoča jedru, da prerazporedi zahteve operacij vnosa/izvoda na disk, v upanju, da jih lahko združi ali pa omogoči obstoječim glavam diska, da izberejo neke optimalnejše poti preko svojih plošč. Končni učinek je, da lahko iz vsakega diska iztisnete nekoliko več operacij vnosa/izvoda, kot bi to bilo mogoče pri neposrednih ali sinhronih operacijah vnosa/izvoda.
Vendar pa se pojavi določen problem, če količina prihajajočih zapisov v ta Ceph klaster preseže vse zmožnosti temelječih diskov. V takem scenariju se lahko skupno število obravnavanih operacij vnosa/izvoda, ki čakajo na zapis na disk, neobvladljivo povečuje, kar vodi do čakalne vrste operacij vnosa/izvoda, ki napolni celoten disk in čakalne vrste Ceph. Zahteve za branje so še posebej slabo prizadete, saj se zataknejo med zahtevami za zapis, ki lahko zahtevajo več sekund za prenos na glavni disk.
Za premagovanje tega izziva ima Ceph vgrajen mehanizem za uravnavanje odložene zapisovanja (writeback) z imenom WBThrottle, ki deluje v okviru shranjevanja datotek. Razvit je bil za omejitev skupnega števila vhodno/izhodnih operacij odložene zapisovanja, ki se lahko postavijo v čakalno vrsto in začnejo svoj proces praznjenja prej, kot bi se to zgodilo naravno. Žal testiranje kaže, da privzete vrednosti še vedno morda ne zmanjšujejo obstoječega vedenja na raven, ki lahko zmanjša vpliv na latenco bralnih operacij. Prilagoditev lahko spremeni to vedenje in zmanjša skupne dolžine zapisnih vrst ter omogoči, da to vpliva ne bo tako močno. Vendar pa obstaja nek kompromis: z zmanjšanjem skupnega največjega števila dovoljenih zapisov v vrsti lahko zmanjšate sposobnost jedra, da maksimalno optimizira svoje razporejanje prihajajočih zahtev. Malo se zamislite, kaj potrebujete bolj za svoj konkreten primer uporabe in delovne obremenitve ter prilagodite temu.
Za upravljanje globine take vrstice odložene zapisovanja lahko bodisi zmanjšate skupno največje število neizvedenih vhodno/izhodnih operacij z uporabo nastavitev WBThrottle, bodisi zmanjšate največjo vrednost za neizvedene operacije na blokovni ravni vašega jedra. Obe možnosti lahko učinkovito upravljata isto vedenje in vaša izbira bo osnova za izvajanje te nastavitve.
Prav tako je treba omeniti, da je obstojna v Ceph sistem prioritizacije operacij bolj učinkovita za krajše zahteve na ravni diska. Z zmanjšanjem skupne vrste za ta disk se osnovna lokacija v vrsti premakne v Ceph, kjer ima boljše stanje nad tem, kakšne prioritete ima vhodno/izhodna operacija. Oglejmo si naslednji primer:
echo 8 > /sys/block/sda/queue/nr_requestsSKUPNO
In še nekaj nastavitev jedra, ki omogočajo, da vaša naprava deluje mehko in svilnato ter iztisne še malo zmogljivosti iz strojne opreme.
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
# Подтюним параметры ввода-вывода
# Ядро Linux предоставляет функцию асинхронного неблокирующего ввода-вывода (AIO),
# которая позволяет процессу инициировать несколько операций ввода-вывода
# одновременно, не дожидаясь завершения какой-либо из них.
# Это помогает повысить производительность приложений,
# которые могут перекрывать обработку и ввод-вывод.
# Параметр aio-max-nr определяет максимальное количество допустимых
# одновременных запросов.
vm.min_free_kbytes=1048576
# Минимальный размер свободной памяти, который необходимо поддерживать.
# Выставлен 1 Гб, чего вполне достаточно для работы операционной системы,
# и позволяет избегать OOM Killer для процессов OSD. Хотя памяти и так
# как у дурака фантиков, но запас карман не тянет.
vm.swappiness=10
# Говорим использовать своп, если осталось свободным 10% памяти.
# На машинах 128 Гб оперативной памяти, и 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 указано
# выделять под кэширование по 3 Гб оперативной памяти.
# Примерно по 40 дисков HDD, для которых этот параметр равен 1 Гб.
# 20% от 128 это 25.6 Гб. Итого, в случае максимальной утилизации памяти,
# для системы останется 2.4 Гб памяти. Чего ей должно хватить, чтобы выжить и дождаться
# стука копыт кавалерии - то есть пришествия DevOps, который все починит.
vm.dirty_background_ratio=3
# Процент системной памяти, который можно заполнить dirty pages до того,
# как фоновые процессы pdflush/flush/kdmflush запишут их на диск.
fs.file-max=524288
# Ну и открытых файлов у нас, вероятно, будет сильно больше, чем указано по дефолту. Potop v CEPH
Nastavitve, na katerih bi se želeli podrobneje ustaviti:
cat /etc/ceph/ceph.conf
osd:
journal_aio: true # Tri parametri, ki vključujejo
journal_block_align: true # neposreden i/o
journal_dio: true # na dnevnik
journal_max_write_bytes: 1073714824 # Malo razširimo največjo velikost
# enkrat zapisane operacije v dnevniku
journal_max_write_entries: 10000 # In število hkratnih zapisov
journal_queue_max_bytes: 10485760000
journal_queue_max_ops: 50000
rocksdb_separate_wal_dir: true # Odločili smo se ustvariti ločeno wal
# Tudi poskusili smo nastaviti to zadevo
# NVMe
bluestore_block_db_create: true # In za dnevnik ločeno napravo
bluestore_block_db_size: '5368709120 #5G'
bluestore_block_wal_create: true
bluestore_block_wal_size: '1073741824 #1G'
bluestore_cache_size_hdd: '3221225472 # 3G'
# velika prostornina RAM omogoča
# shranjevanje dovolj velikih količin
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 # število nitk pri demonu za en disk
osd_failsafe_full_ratio: 0.95
osd_heartbeat_grace: 5
osd_heartbeat_interval: 3
osd_map_dedup: true
osd_max_backfills: 2 # število hkratnih operacij polnjenja na en OSD.
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 # Značilnosti pohlepnosti. Zelo hitro je postalo
osd_pool_default_size: 2 # pomanjkanje prostora, ker smo sprejeli
# začasno rešitev zmanjšanje števila
# replik podatkov
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 # parameter prilagajamo po potrebi na terenu
osd_recovery_sleep: 2
osd_scrub_chunk_max: 4Nekateri parametri, testirani na QA v različici 12.2.12, manjkajo v različici ceph 12.2.2, na primer osd_recovery_threads. Zato je bilo v načrte vključeno nadgradnjo v produkciji na 12.2.12. Praksa je pokazala združljivost v enem klasterju različic 12.2.2 in 12.2.12, kar omogoča rolling update.
Testni klaster
Seveda je bilo potrebno za testiranje imeti enako različico kot na produkciji, vendar je ob začetku mojega dela s klasterjem v repozitoriju bila samo novejša. Gledajoč, da razlike v manjših različicah niso prevelike,1393 vrstice v konfiguracijah proti 1436 v novi različici), smo se odločili, da začnemo testirati novo (tako ali tako se bomo posodobili, zakaj bi ostajali pri stari krami)
Edino, kar smo poskušali ohraniti iz stare različice, je paket ceph-deploy, saj so nekatere utilite (in del zaposlenih) bile zasnovane po njenem sintaksisu. Nova različica se je precej razlikovala, vendar ni vplivala na delovanje samega klasterja, zato je ostala različica 1.5.39
Ker ekipa ceph-disk jasno pravi, da je zastarela in naj se uporabljajo ukazi ceph-volume — smo začeli ustvarjati OSD prav s to ekipo, ne da bi izgubljali čas z zastarelim.
Načrt je bil takšen — ustvariti zrcalo iz dveh SSD diskov, na katerih bomo shranili dnevnike OSD, ki so se, mimoidoče, nahajali na vrtečih SAS-ih. Tako se zaščitimo pred težavami s podatki v primeru padca diska z dnevnikom.
Začeli smo ustvarjati klaster po dokumentaciji
cat /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-qPrvi problem na koji sam naišao prilikom rada s ovom verzijom ceph-deploy s klasterom verzije 12.2.12 je greška prilikom pokušaja stvaranja OSD-a s db na softverskom RAID-u —
root@ceph01-qa:~#ceph-volume lvm create --bluestore --data /dev/sde --block.db /dev/md0
blkid nije mogao otkriti PARTUUID za uređaj: /dev/md1Zaista, blkid ne prikazuje PARTUUID, morao sam ručno stvoriti particije:
root@ceph01-qa:~#parted /dev/md0 mklabel GPT
# bit će mnogo particija,
# bez GPT ih ne možemo stvoriti
# veličina particije koju smo naveli u konfiguraciji iznad = bluestore_block_db_size: '5368709120 #5G'
# Imam 20 diskova za OSD, ručno stvaranje particija mi se ne da
# pa sam napravio petlju
root@ceph01-qa:~#for i in {1..20}; do echo -e "nnnn+5Gnw" | fdisk /dev/md0; doneIzgleda da je sve spremno, pokušavamo ponovo stvoriti OSD i dobijamo sljedeću grešku (koja, usput, nije reproducirana na produkciji)
prilikom stvaranja OSD-a tipa bluestore bez navođenja puta do WAL, ali s navedenim db
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 nečitljivi uuid
stderr: 2019-04-12 10:39:27.213185 7eff461b6e00 -1 bdev(0x55824c273680 /var/lib/ceph/osd/ceph-0//block.wal) otvoreno otvoreno je dobilo: (22) Neispravan argument
stderr: 2019-04-12 10:39:27.213201 7eff461b6e00 -1 bluestore(/var/lib/ceph/osd/ceph-0/) _open_db dodaj blok uređaj(/var/lib/ceph/osd/ceph-0//block.wal) se vratio: (22) Neispravan argument
stderr: 2019-04-12 10:39:27.999039 7eff461b6e00 -1 bluestore(/var/lib/ceph/osd/ceph-0/) mkfs nije uspjelo, (22) Neispravan argument
stderr: 2019-04-12 10:39:27.999057 7eff461b6e00 -1 OSD::mkfs: ObjectStore::mkfs nije uspjelo s greškom (22) Neispravan argument
stderr: 2019-04-12 10:39:27.999141 7eff461b6e00 -1 ** GREŠKA: greška pri stvaranju praznog objektnog skladišta u /var/lib/ceph/osd/ceph-0/: (22) Neispravan argumentMeđutim, ako na istom zrcalu (ili na drugom mjestu, po izboru) stvorimo još jednu particiju za WAL i navedemo je prilikom stvaranja OSD-a — onda će sve proći glatko (uz izuzetak nastanka odvojenog WAL-a, kojeg možda niste željeli).
Ali, budući da je u daljnjim planovima bilo premjestiti WAL na NVMe, praksa se nije pokazala suvišnom.
root@ceph01-qa:~#ceph-volume lvm create --bluestore --data /dev/sdf --block.wal /dev/md0p2 --block.db /dev/md1p2Stvorili smo monitore, menadžere i OSD. Sada ih želimo grupisati na različite načine, jer planiramo imati diskove različitih tipova — brze grupe na SSD-u i velike, ali spore na klasičnim SAS diskovima.
Računat ćemo da na serverima ima 20 diskova, prva desetina je jedan tip, druga — drugi.
Početna, zadana, karta izgleda ovako:
ceph osd tree
root@ceph01-q:~# ceph osd tree
ID KLASA TEŽINA TIP IME STATUS REWEIGHT PRI-AFF
-1 14.54799 korijen zadani
-3 9.09200 domaćin ceph01-q
0 ssd 1.00000 osd.0 up 1.00000 1.00000
1 ssd 1.00000 osd.1 up 1.00000 1.00000
2 ssd 1.00000 osd.2 up 1.00000 1.00000
3 ssd 1.00000 osd.3 up 1.00000 1.00000
4 hdd 1.00000 osd.4 up 1.00000 1.00000
5 hdd 0.27299 osd.5 up 1.00000 1.00000
6 hdd 0.27299 osd.6 up 1.00000 1.00000
7 hdd 0.27299 osd.7 up 1.00000 1.00000
8 hdd 0.27299 osd.8 up 1.00000 1.00000
9 hdd 0.27299 osd.9 up 1.00000 1.00000
10 hdd 0.27299 osd.10 up 1.00000 1.00000
11 hdd 0.27299 osd.11 up 1.00000 1.00000
12 hdd 0.27299 osd.12 up 1.00000 1.00000
13 hdd 0.27299 osd.13 up 1.00000 1.00000
14 hdd 0.27299 osd.14 up 1.00000 1.00000
15 hdd 0.27299 osd.15 up 1.00000 1.00000
16 hdd 0.27299 osd.16 up 1.00000 1.00000
17 hdd 0.27299 osd.17 up 1.00000 1.00000
18 hdd 0.27299 osd.18 up 1.00000 1.00000
19 hdd 0.27299 osd.19 up 1.00000 1.00000
-5 5.45599 host ceph02-q
20 ssd 0.27299 osd.20 up 1.00000 1.00000
21 ssd 0.27299 osd.21 up 1.00000 1.00000
22 ssd 0.27299 osd.22 up 1.00000 1.00000
23 ssd 0.27299 osd.23 up 1.00000 1.00000
24 hdd 0.27299 osd.24 up 1.00000 1.00000
25 hdd 0.27299 osd.25 up 1.00000 1.00000
26 hdd 0.27299 osd.26 up 1.00000 1.00000
27 hdd 0.27299 osd.27 up 1.00000 1.00000
28 hdd 0.27299 osd.28 up 1.00000 1.00000
29 hdd 0.27299 osd.29 up 1.00000 1.00000
30 hdd 0.27299 osd.30 up 1.00000 1.00000
31 hdd 0.27299 osd.31 up 1.00000 1.00000
32 hdd 0.27299 osd.32 up 1.00000 1.00000
33 hdd 0.27299 osd.33 up 1.00000 1.00000
34 hdd 0.27299 osd.34 up 1.00000 1.00000
35 hdd 0.27299 osd.35 up 1.00000 1.00000
36 hdd 0.27299 osd.36 up 1.00000 1.00000
37 hdd 0.27299 osd.37 up 1.00000 1.00000
38 hdd 0.27299 osd.38 up 1.00000 1.00000
39 hdd 0.27299 osd.39 up 1.00000 1.00000
-7 6.08690 host ceph03-q
40 ssd 0.27299 osd.40 up 1.00000 1.00000
41 ssd 0.27299 osd.41 up 1.00000 1.00000
42 ssd 0.27299 osd.42 up 1.00000 1.00000
43 ssd 0.27299 osd.43 up 1.00000 1.00000
44 hdd 0.27299 osd.44 up 1.00000 1.00000
45 hdd 0.27299 osd.45 up 1.00000 1.00000
46 hdd 0.27299 osd.46 up 1.00000 1.00000
47 hdd 0.27299 osd.47 up 1.00000 1.00000
48 hdd 0.27299 osd.48 up 1.00000 1.00000
49 hdd 0.27299 osd.49 up 1.00000 1.00000
50 hdd 0.27299 osd.50 up 1.00000 1.00000
51 hdd 0.27299 osd.51 up 1.00000 1.00000
52 hdd 0.27299 osd.52 up 1.00000 1.00000
53 hdd 0.27299 osd.53 up 1.00000 1.00000
54 hdd 0.27299 osd.54 up 1.00000 1.00000
55 hdd 0.27299 osd.55 up 1.00000 1.00000
56 hdd 0.27299 osd.56 up 1.00000 1.00000
57 hdd 0.27299 osd.57 up 1.00000 1.00000
58 hdd 0.27299 osd.58 up 1.00000 1.00000
59 hdd 0.89999 osd.59 up 1.00000 1.00000
Ustvarimo svoje virtualne regale in strežnike z blackjackom in ostalim:
root@ceph01-q:~#ceph osd crush add-bucket rack01 root #ustvarili smo nov root
root@ceph01-q:~#ceph osd crush add-bucket ceph01-q host #ustvarili smo nov gostitelj
root@ceph01-q:~#ceph osd crush move ceph01-q root=rack01 #premestili smo strežnik v drugi regal
root@ceph01-q:~#osd crush add 28 1.0 host=ceph02-q # Dodali OSD v strežnik
# Če smo nepravilno ustvarili, lahko izbrišemo
root@ceph01-q:~# ceph osd crush remove osd.4
root@ceph01-q:~# ceph osd crush remove rack01Problemi, s katerimi smo se srečali pri boji klasterju, ko smo poskušali ustvariti novega gostitelja in ga premakniti v obstoječi regal — ukaz ceph osd crush move ceph01-host root=rack01 se je zagozdil in monitorji so začeli padati enega za drugim. Prekinitev ukaza s preprostim CTRL+C je vrnila klaster v svet živih.
Iskanje je pokazalo takšno težavo:
Rešitev je bila, da se izveže crushmap in odstrani odsek rule replicated_ruleset
root@ceph01-prod:~#ceph osd getcrushmap -o crushmap.row #Izvlečemo karto v surovi obliki
root@ceph01-prod:~#crushtool -d crushmap.row -o crushmap.txt #pretvorimo v berljivo
root@ceph01-prod:~#vim crushmap.txt #urejamo, odstranjujemo rule replicated_ruleset
root@ceph01-prod:~#crushtool -c crushmap.txt -o new_crushmap.row #kompiramo nazaj
root@ceph01-prod:~#ceph osd setcrushmap -i new_crushmap.row #naložimo v klasterPozor: ta operacija lahko povzroči ponovno uravnoteženje skupin postavljanja med OSD. Pri nas je to povzročilo le zelo majhna sprememba.
Nenavadnost, s katero smo se srečali v testnem klastru, je bila ta, da so OSD po ponovnem zagonu strežnika pozabili, da so bili preseljeni na nove strežnike in omare, in so se vrnili v privzeto root.
Na koncu, ko smo zgradili končno shemo, v kateri smo ustvarili ločen root za SSD diske in ločen za vrtljive, smo razporejali vse OSD po omarah in enostavno odstranili privzeti root. Po ponovnem zagonu so OSD ostali na svojih mestih.
Kasneje smo v dokumentaciji našli parameter, ki je odgovoren za to vedenje. O njem v drugem delu.
Kako smo ustvarili različne skupine po vrstah diskov.
Na začetku smo ustvarili dva root-a — za SSD in za HDD.
root@ceph01-q:~#ceph osd crush add-bucket ssd-root root
root@ceph01-q:~#ceph osd crush add-bucket hdd-root rootKer so fizično strežniki postavljeni v različnih omarah — za udobje smo ustvarili omare in v njih že strežnike.
# Стойки:
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 hostin razporedili diske po njihovih vrstah v različne strežnike.
root@ceph01-q:~# Diski od 0 do 3 so SSD, nahajajo se v ceph01-q, postavimo jih v strežnik
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:~# enako z drugimi strežniki.Ko smo razporedili diske po root-ih ssd-root in hdd-root, smo pustili root-default prazen, zato ga lahko odstranimo.
root-ceph01-q:~#ceph osd crush remove defaultNato je treba ustvariti pravila razporejanja, ki jih bomo povezali z ustvarjenimi bazeni — v pravilih bomo navedli, v katere root lahko shranimo podatke našega bazena in stopnjo edinstvenosti replik — na primer, replikacije morajo biti nujno na različnih strežnikih ali v različnih omarah (lahko celo v različnih root, če imamo takšno razporejanje).
Preden izberete tip, je bolje prebrati dokumentacijo:
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:~# Navedli smo dve pravili, v katerih se podatki replikirajo
root-ceph01-q:~# med gostitelji - torej replika mora biti na drugem gostitelju,
root-ceph01-q:~# tudi če so v isti omari.
root-ceph01-q:~# V produkciji, če je to mogoče, je bolje razporediti gostitelje
root-ceph01-q:~# po omarah in navesti razporejanje replik po omarah:
root-ceph01-q:~# ##ceph osd crush rule create-simple rule-ssd ssd-root rack firstnZato ustvarimo bazene, v katerih bomo v prihodnje shranjevali slike diskov naše virtualizacije - 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 1024In povemo tem bazenom, kakšna pravila razporeditve naj upoštevajo
root-ceph01-q:~#ceph osd crush rule ls # prikažemo seznam pravil
root-ceph01-q:~#ceph osd crush rule dump rule-ssd | grep rule_id #izberemo ID potrebnega
root-ceph01-q:~#ceph osd pool set ssd_pool crush_rule 2
Izbiri števila placement skupin je potrebno pristopiti z že obstoječim pogledom na svoj klaster - koliko približno OSD bo tam, kakšno količino podatkov (v odstotkih od skupne prostornine) bo v bazenu in koliko podatkov bo skupno.
Skupaj je priporočljivo, da na disk ni več kot 300 placement skupin, lažje bo uravnotežiti z manjšimi placement skupinami - torej, če vaš bazen zavzema 10 TB in vsebuje 10 PG - bo težko uravnotežiti s premikanjem terabajtnih gradnikov (pg), lažje bo preusmerjati pesek z majhnimi zrnci po vedrih.
Vendar je potrebno vedeti, da večje število PG pomeni večjo porabo virov za izračun njihove razporeditve - začnemo porabljati pomnilnik in CPU.
Približno razumevanje lahko , ki ga zagotavljajo razvijalci dokumentacije CEPH.
Seznam materialov:
Izvor: habr.com
