Keuze voor CEPH. Deel 1
We hadden vijf racks, tien optische switches, geconfigureerde BGP, een paar dozen SSD's en een hoop SAS-schijven in alle vormen en maten, en ook Proxmox en de drang om alle statische data in onze eigen S3-opslag te stoppen. Niet dat dit alles nodig was voor virtualisatie, maar als je al met open source bezig bent, ga dan volledig voor je passie. Het enige waar ik me zorgen over maakte, was BGP. In de wereld is er niemand die zo hulpeloos, onverantwoordelijk en onethisch is als interne routering via BGP. En ik wist dat we er heel snel in zouden duiken.

De taak was vrij eenvoudig - we hadden CEPH dat niet erg goed werkte. We moesten het 'goed' maken.
Het cluster dat ik kreeg was heterogeen, snel in elkaar gezet en praktisch niet getweaked. Het bestond uit twee groepen verschillende knooppunten, met een gemeenschappelijk netwerk dat zowel als cluster- als publieke netwerk diende. De knooppunten waren uitgerust met vier soorten schijven - twee types SSD's, samengevoegd in twee aparte plaatsingsregels en twee types HDD's van verschillende formaten, samengevoegd in een derde groep. Het probleem met verschillende groottes werd opgelost door verschillende gewichten voor OSD.
De configuratie zelf werd in twee delen verdeeld - tuning van het besturingssysteem en tuning van CEPH zelf en zijn instellingen.
Optimalisatie van het besturingssysteem
Netwerk global log /dev/log local0 log /dev/log local1 notice chroot /var/lib/haproxy stats timeout 30s user haproxy group haproxy daemondefaults log global mode http option httplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000frontend http_front bind *:80 stats uri /haproxy?stats default_backend http_backbackend http_back balance roundrobin server server_name1 private_ip1:80 check server server_name2 private_ip2:80 check
Hoge latency beïnvloedde zowel het schrijven als de balancing. Bij het schrijven - omdat de client geen bevestiging van een succesvolle schrijfactie ontvangt totdat de replica's van de gegevens in andere plaatsingsgroepen het succes hebben bevestigd. Aangezien de replicatieregels in de CRUSH-kaart één replica per host waren, werd het netwerk altijd gebruikt.
Daarom besloot ik allereerst de huidige netwerkconfiguratie een beetje aan te passen, terwijl ik tegelijkertijd probeerde mensen over te halen om over te stappen naar gescheiden netwerken.
Om te beginnen heb ik de instellingen van de netwerkkaarten aangepast. Ik begon met de configuratie van de wachtrijen:
wat er was:
ethtool -l ens1f1
root@ceph01:~# ethtool -l ens1f1
Kanaalparameters voor ens1f1:
Voorgedefinieerde maximums:
RX: 0
TX: 0
Overig: 1
Gecombineerd: 63
Huidige hardware-instellingen:
RX: 0
TX: 0
Overig: 1
Gecombineerd: 1
root@ceph01:~# ethtool -g ens1f1
Ringparameters voor ens1f1:
Voorgedefinieerde maximums:
RX: 4096
RX Mini: 0
RX Jumbo: 0
TX: 4096
Huidige hardware-instellingen:
RX: 256
RX Mini: 0
RX Jumbo: 0
TX: 256
root@ceph01:~# ethtool -l ens1f1
Kanaalparameters voor ens1f1:
Voorgedefinieerde maximums:
RX: 0
TX: 0
Overig: 1
Gecombineerd: 63
Huidige hardware-instellingen:
RX: 0
TX: 0
Overig: 1
Gecombineerd: 1Het is duidelijk dat de huidige parameters ver weg zijn van de maximums. Ik heb ze verhoogd:
root@ceph01:~#ethtool -G ens1f0 rx 4096
root@ceph01:~#ethtool -G ens1f0 tx 4096
root@ceph01:~#ethtool -L ens1f0 combined 63Geïnspireerd door een uitstekend artikel
heb ik de lengte van de verzendwachtrij vergroot txqueuelen van 1000 tot 10 000
root@ceph01:~#ip link set ens1f0 txqueuelen 10000En volgens de documentatie van Ceph
verhoogd MTU tot 9000.
root@ceph01:~#ip link set dev ens1f0 mtu 9000Toegevoegd aan /etc/network/interfaces, zodat alles hierboven bij het opstarten wordt geladen
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 9000Daarna, volgens ditzelfde artikel, begon ik aandachtig de instellingen voor kernel 4.15 aan te passen. Gezien het feit dat de knooppunten 128G RAM hebben, resulteerde dit in een bepaalde configuratiebestand voor , beschikbaar zijn voor
cat /etc/sysctl.d/50-ceph.conf
net.core.rmem_max = 56623104
# Maximale grootte van de ontvangstbuffer voor alle verbindingen 54M
net.core.wmem_max = 56623104
# Maximale grootte van de verzendbuffer voor alle verbindingen 54M
net.core.rmem_default = 56623104
# Standaardgrootte van de ontvangstbuffer voor alle verbindingen. 54M
net.core.wmem_default = 56623104
# Standaardgrootte van de verzendbuffer voor alle verbindingen 54M
# per socket
net.ipv4.tcp_rmem = 4096 87380 56623104
# Vectorvariabele (minimum, standaard, maximum) in het bestand tcp_rmem
# bevat 3 gehele getallen die de grootte van de ontvangstbuffer van TCP-sockets bepalen.
# Minimum: elke TCP-socket heeft recht om dit geheugen te gebruiken op
# het moment van zijn creatie. Het gebruik van zo'n buffer
# is gegarandeerd, zelfs bij het bereiken van de limiet (matige geheugendruk).
# De standaardwaarde van de minimale buffer bedraagt 8 KB (8192).
# Standaardwaarde: hoeveelheid geheugen toegestaan voor de standaard tegenrekening van de TCP-socket.
# Deze waarde vervangt
# de parameter /proc/sys/net/core/rmem_default, die door andere protocollen wordt gebruikt.
# De standaardgrootte van de gebruikte buffer is doorgaans (standaard)
# 87830 bytes. Dit definieert de venstergrootte 65535 met
# de standaardwaarde tcp_adv_win_scale en tcp_app_win = 0,
# iets minder dan de standaardwaarde van tcp_app_win.
# Maximum: maximale grootte van de buffer die automatisch
# kan worden gealloceerd voor ontvangst door de TCP-socket. Deze waarde laat de maximumwaarde,
# ingesteld in het bestand /proc/sys/net/core/rmem_max, onverlet. Bij "statische"
# geheugenallocatie met SO_RCVBUF heeft deze parameter geen waarde.
net.ipv4.tcp_wmem = 4096 65536 56623104
net.core.somaxconn = 5000
# Maximale aantal open sockets dat op verbindingen wacht.
net.ipv4.tcp_timestamps=1
# Staat het gebruik van tijdstempels toe (timestamps), conform RFC 1323.
net.ipv4.tcp_sack=1
# Staat selectieve bevestigingen van het TCP-protocol toe
net.core.netdev_max_backlog=5000 (standaard 1000)
# maximaal aantal pakketten in de wachtrij voor verwerking als
# de interface pakketten sneller ontvangt dan de kernel ze kan verwerken.
net.ipv4.tcp_max_tw_buckets=262144
# Maximale aantal sockets in de TIME-WAIT-status tegelijkertijd.
# Bij overschrijding van deze drempel - wordt de "overbodige" socket vernietigd en wordt er
# een bericht in het systeemlog geschreven.
net.ipv4.tcp_tw_reuse=1
# Staat hergebruik van TIME-WAIT sockets toe in gevallen,
# als het protocol dat veilig acht.
net.core.optmem_max=4194304
# Verhoog de maximale totale beschikbare buffer
# gemeten in paginagrootte (4096 bytes)
net.ipv4.tcp_low_latency=1
# Staat de TCP/IP-stack toe om te kiezen voor lage latentie
# boven hogere doorvoersnelheid.
net.ipv4.tcp_adv_win_scale=1
# Deze variabele beïnvloedt de berekening van de hoeveelheid geheugen in de socketbuffer,
# toegewezen aan de grootte van het TCP-venster en de applicatiebuffer.
# Als tcp_adv_win_scale negatief is, wordt voor de berekening van de grootte
# de volgende uitdrukking gebruikt:
# Bytes - bytes2 tot de macht -tcp_adv_win_scale
# Waar bytes de grootte van het venster in bytes is. Als tcp_adv_win_scale positief is,
# wordt voor de bepaling van de grootte de volgende uitdrukking gebruikt:
# Bytes - bytes2 tot de macht tcp_adv_win_scale
# De variabele neemt een geheel getal aan. De standaardwaarde is 2,
# d.w.z. ¼ deel van het volume, bepaald door de variabele
# tcp_rmem, is gereserveerd voor de applicatiebuffer.
net.ipv4.tcp_slow_start_after_idle=0
# mechanisme voor het opnieuw starten van een langzame start, dat de waarde van het venster
# voor congestie reset als de verbinding gedurende een bepaalde periode niet is gebruikt.
# Het is beter om SSR op de server uit te schakelen om de prestaties van
# langdurige verbindingen te verbeteren.
net.ipv4.tcp_no_metrics_save=1
# Bewaart de resultaten van netwerkmetingen niet in de cache bij het sluiten van de verbinding.
net.ipv4.tcp_syncookies=0
# Schakel het mechanisme voor het verzenden van syncookies uit
net.ipv4.tcp_ecn=0
# Expliciete Congestie Kennisgeving (Explicit Congestion Notification) in
# TCP-verbindingen. Wordt gebruikt om aan te geven dat er een "congestie"
# op de route naar een bepaald host of netwerk is. Kan worden gebruikt om de
# verzendhost te informeren dat deze de snelheid van de pakketoverdracht moet verlagen via
# een specifieke router of firewall.
net.ipv4.conf.all.send_redirects=0
# schakelt het verzenden van ICMP Redirect ... naar andere hosts uit. Deze optie moet absoluut
# ingeschakeld zijn als de host als router fungeert van welke aard dan ook.
# Wij hebben geen routering.
net.ipv4.ip_forward=0
# Dus het uitschakelen van forwarding. We zijn geen gateway, docker op de machines is niet opgezet,
# dit hebben we niet nodig.
net.ipv4.icmp_echo_ignore_broadcasts=1
# Reageer niet op ICMP ECHO-verzoeken die via broadcastpakketten worden verzonden
net.ipv4.tcp_fin_timeout=10
# bepaalt de tijd dat de socket in de FIN-WAIT-2-status blijft na
# sluiting door de lokale kant. Standaard 60
net.core.netdev_budget=600 # (standaard 300)
# Als de uitvoering van software-interrupts niet lang genoeg duurt,
# kan de snelheid van de inkomende gegevens de mogelijkheid van de kernel overtreffen
# om de buffer te legen. Hierdoor kunnen de buffers van de NIC overvol raken, en gaat het verkeer verloren.
# Soms is het nodig om de langdurigheid van SoftIRQs
# (software-interrupts) met CPU te verhogen. Dit wordt geregeld door netdev_budget.
# Standaardwaarde is 300. De parameter dwingt het SoftIRQ-proces om
# 300 pakketten van de NIC te verwerken voordat het de CPU loslaat
net.ipv4.tcp_fastopen=3
# TFO TCP Fast Open
# als zowel de client als de server TFO-ondersteuning hebben, wat wordt aangegeven door
# een speciale vlag in het TCP-pakket. In ons geval is het een placebo, gewoon
# mooi om te zien)metluster netwerk werd toegewezen aan afzonderlijke 10Gbps netwerkinterfaces in een aparte platte netwerkomgeving. Op elke machine zijn netwerkaansluitingen met twee poorten geïnstalleerd mellanox 10/25 Gbps, verbonden met twee afzonderlijke 10Gbps switches. Aggregatie vond plaats met behulp van OSPF, omdat de bonding met lacp om de een of andere reden een totale bandbreedte aangaf van maximaal 16 Gbps, terwijl ospf met succes beide verbindingen op elke machine volledig benutten. In de toekomst was het plan om ROCE op deze mellanochs te gebruiken om de latentie te verlagen. Hoe deze netwerkcomponent is ingesteld:
- Aangezien de machines externe ip-adressen hebben via BGP, hebben we de software nodig — (en precies op het moment van schrijven van dit artikel was dit ) al geïnstalleerd.
- In totaal hadden de machines twee netwerken met elk twee interfaces — samen 4 poorten. Eén netwerkkaart met twee poorten keek naar de fabriek en daarop was BGP ingesteld, de tweede — met twee poorten keek naar twee verschillende switches en daarop was OSPF ingesteld.
Meer over de configuratie van OSPF: De hoofdtaak is het aggregateren van twee links en het hebben van fouttolerantie.
twee netwerkinterfaces zijn ingesteld in twee eenvoudige platte netwerken — 10.10.10.0/24 en 10.10.20.0/24
1: ens1f0: 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: mtu 9000 qdisc mq state UP group default qlen 1000
inet 10.10.20.2/24 brd 10.10.20.255 scope global ens1f1waarop de machines elkaar zien.
SCHIJF
De volgende stap was om de schijven te optimaliseren. Voor SSD heb ik de scheduler gewijzigd in noop, voor HDD — deadline. Grof gezegd werkt NOOP volgens het principe 'wie het eerst komt, het eerst maalt', wat in het Engels klinkt als 'FIFO (First In, First Out)'. Verzoeken komen in de wachtrij naarmate zij binnenkomen. DEADLINE is meer gericht op lezen, plus het proces ontvangt bijna monopolistische toegang tot de schijf op het moment van de operatie. Dit past uitstekend bij ons systeem — er werkt immers maar één proces per schijf — OSD daemon.
(Degenen die zich willen verdiepen in de I/O scheduler kunnen er hier meer over lezen:
Voor degenen die liever in het Russisch lezen: )
In de aanbevelingen voor het tunen van Linux wordt ook aanbevolen om nr_request te verhogen
nr_requests
De waarde van nr_requests bepaalt het aantal I/O-verzoeken dat wordt gebufferd voordat de I/O-scheduler gegevens naar het blokapparaat verzendt of ontvangt. Als je een RAID-kaart of blokapparaat gebruikt dat een grotere wachtrij kan verwerken dan wat de I/O-scheduler is ingesteld op, kan het verhogen van de waarde van nr_requests helpen om de doorvoersnelheid te verbeteren en de serverbelasting te verminderen wanneer er grote hoeveelheden I/O op de server plaatsvinden. Als je Deadline of CFQ als scheduler gebruikt, wordt aanbevolen om de nr_request-waarde in te stellen op 2 keer de waarde van de wachttiepte.
Echter, de ontwikkelaars van CEPH zelf verzekeren ons dat hun prioriteitensysteem beter functioneert.

WBThrottle en/of nr_requests
WBThrottle en/of nr_requests
Het bestandssysteem gebruikt gebufferde invoer/uitvoerbewerkingen voor schrijven; dit biedt verschillende voordelen wanneer het log van het bestandssysteem op een snellere opslagmedia is. Klantverzoeken krijgen meldingen wanneer de gegevens in het log zijn geschreven en worden vervolgens op een later tijdstip naar de eigen gegevensschijf weggeschreven, gebruikmakend van de standaardfunctionaliteit van Linux. Hierdoor kan OSD spinning disks schrijflatentie bieden die vergelijkbaar is met SSD's bij het schrijven van kleine pakketten. Deze uitgestelde schrijfvertraging stelt ook de kernel in staat om I/O-operatieverzoeken naar de schijf opnieuw te structureren in de hoop ze te combineren of de bestaande schijfkoppen een meer optimale route boven hun schijven te laten kiezen. Het uiteindelijke effect is dat je iets meer I/O-operaties uit elke schijf kunt halen dan wat mogelijk zou zijn bij directe of synchrone I/O-operaties.
Echter, er ontstaat een probleem als het volume van de binnenkomende records in deze Ceph-cluster alle mogelijkheden van de onderliggende schijven overschrijdt. In dit scenario kan het totale aantal I/O-operaties dat wacht om op de schijf te worden geschreven onbeheersbaar toenemen, resulterend in een wachtrij van I/O-operaties die de hele schijf en de Ceph-wachtrij kan vullen. Leesverzoeken worden bijzonder negatief beïnvloed, omdat ze vast komen te zitten tussen schrijfverzoeken die enkele seconden kunnen vereisen om op de hoofddisk te worden weggeschreven.
Om dit probleem op te lossen, heeft Ceph een ingebouwd mechanisme voor writeback uitgestelde opslag genaamd WBThrottle. Dit is ontworpen om het totale aantal uitgestelde schrijf-I/O-bewerkingen dat kan worden in de wachtrij geplaatst te beperken en eerder te beginnen met het proces van het legen ervan dan dit natuurlijk zou gebeuren door het systeem zelf. Helaas toont de test aan dat de standaardinstellingen nog steeds mogelijk niet het gedrag beperken tot een niveau dat de impact op de latentie van leesbewerkingen kan verminderen. Afstemming kan dit gedrag veranderen en de totale lengte van de schrijf wachtrijen verminderen en mogelijk de impact beperken. Er is echter een compromis: door het totale aantal toegestane wachtrijen te verlagen, kunt u de mogelijkheid van het systeem om zijn efficiëntie bij het ordenen van binnenkomende verzoeken te maximaliseren verminderen. Het is de moeite waard om na te denken over wat meer nodig is voor uw specifieke gebruiksgeval en workloads en dit dienovereenkomstig aan te passen.
Om de diepte van deze uitgestelde schrijf wachtrij te beheren, kunt u ofwel het totale aantal onafgeronde I/O-bewerkingen verlagen door de WBThrottle-instellingen aan te passen, of het maximale aantal onafgeronde bewerkingen op het blokniveau binnen uw systeem verlagen. Beide kunnen effectief hetzelfde gedrag beheren en het zijn uw voorkeuren die de implementatie van deze instelling bepalen.
Daarnaast is het vermeldenswaard dat het huidige prioriteitssysteem van Ceph effectiever is voor kortere verzoeken op blokniveau. Door de totale wachtrij naar deze schijf te verkorten, verschuift de belangrijkste locatie in de wachtrij naar Ceph, waar het meer controle heeft over de prioriteit van de I/O-bewerking. Overweeg het volgende voorbeeld:
echo 8 > /sys/block/sda/queue/nr_requestsALGEMEEN
En nog een paar kernelinstellingen die uw systeem soepel kunnen laten draaien en wat extra prestaties uit de hardware kunnen persen.
cat /etc/sysctl.d/60-ceph2.conf
kernel.pid_max = 4194303
# Er zijn 25 schijven in elke machine, daarom hebben we berekend dat er veel processen zullen zijn
kernel.threads-max=2097152
# Threads zijn, uiteraard, ook van belang.
vm.max_map_count=524288
# We hebben het aantal geheugenkaarten voor het proces vergroot.
# Zoals blijkt uit de documentatie over kernelvariabelen
# worden geheugenkaarten gebruikt als bijeffect van de aanroep
# malloc, direct via mmap, mprotect en madvise, evenals bij het laden
# van gedeelde bibliotheken.
fs.aio-max-nr=50000000
# We optimaliseren de input-output parameters
# De Linux-kernel biedt de functie voor asynchrone niet-blokkerende input-output (AIO),
# waarmee een proces meerdere input-outputoperaties kan initiëren
# tegelijkertijd, zonder te wachten op de voltooiing van een van hen.
# Dit helpt de prestaties van applicaties te verbeteren,
# die het verwerken en input-output kunnen overlappen.
# De aio-max-nr parameter bepaalt het maximale aantal toegestane
# gelijktijdige aanvragen.
vm.min_free_kbytes=1048576
# De minimale vrij te houden geheugengrootte.
# Ingesteld op 1 Gb, wat ruim genoeg is voor het functioneren van het besturingssysteem,
# en helpt om OOM Killer voor OSD-processen te vermijden. Hoewel het geheugen al
# in overvloed beschikbaar is, maar een reserve is nooit verkeerd.
vm.swappiness=10
# We zeggen dat swap gebruikt moet worden als er nog 10% van het geheugen vrij is.
# Op machines met 128G RAM is 10% gelijk aan 12 Gigabytes. Meer dan genoeg om te functioneren.
# De standaardinstelling van 60% zorgde ervoor dat het systeem langzamer werd door in de swap te komen,
# wanneer er nog voldoende vrij geheugen beschikbaar was.
vm.vfs_cache_pressure=1000
# We verhogen deze waarde van de standaard 100. We dwingen de kernel om actiever
# ongebruikte geheugenpagina's uit de cache te verwijderen.
vm.zone_reclaim_mode=0
# Dit maakt het mogelijk om meer of minder agressieve benaderingen in te stellen voor
# het herstellen van geheugen, wanneer het geheugen in een zone opraakt.
# Als het op nul is ingesteld, vindt er geen zone-herstel plaats.
# Voor bestandsservers of werkbelastingen
# is het voordelig als hun gegevens in de cache zijn, terwijl het zone_reclaim_mode
# uitgeschakeld moet blijven, omdat het effect van cachen
# waarschijnlijk belangrijker zal zijn dan de locatie van de gegevens.
vm.dirty_ratio=20
# Percentage van het systeemgeheugen dat kan worden toegewezen aan "vuile" pagina's
# Berekening gedaan op basis van een schatting:
# Het systeem heeft 128 gigabyte geheugen.
# Ongeveer 20 SSD-schijven, waarvoor in de CEPH-instellingen is opgegeven
# dat er 3G RAM voor caching moet worden toegewezen.
# Ongeveer 40 HDD-schijven, waarvoor deze parameter gelijk is aan 1G
# 20% van 128 is 25.6 gigabytes. Dus, bij maximale geheugenutilisatie,
# blijft er 2.4G geheugen over voor het systeem. Dit zou voldoende moeten zijn om te overleven en te wachten
# op de komst van de DevOps die alles zal herstellen.
vm.dirty_background_ratio=3
# Percentage van het systeemgeheugen dat kan worden gevuld met vuile pagina's voordat,
# de achtergrondprocessen pdflush/flush/kdmflush deze naar de schijf schrijven
fs.file-max=524288
# En waarschijnlijk zullen we veel meer open bestanden hebben dan standaard is opgegeven. Verdiep in CEPH
Instellingen waar we dieper op in willen gaan:
cat /etc/ceph/ceph.conf
osd:
journal_aio: true # Drie parameters die directe i/o inschakelen
journal_block_align: true # rechtstreekse i/o
journal_dio: true # naar het log
journal_max_write_bytes: 1073714824 # Laten we de maximale grootte iets uitrekken
# van de eenmalig naar het log geschreven operatie
journal_max_write_entries: 10000 # En het aantal gelijktijdige vermeldingen
journal_queue_max_bytes: 10485760000
journal_queue_max_ops: 50000
rocksdb_separate_wal_dir: true # We hebben ervoor gekozen een aparte WAL te maken
# We hebben zelfs geprobeerd om hier iets voor te creëren
# NVMe
bluestore_block_db_create: true # En voor het log een apart apparaat
bluestore_block_db_size: '5368709120 #5G'
bluestore_block_wal_create: true
bluestore_block_wal_size: '1073741824 #1G'
bluestore_cache_size_hdd: '3221225472 # 3G'
# een groot volume RAM maakt het mogelijk om
# voldoende grote volumes op te slaan
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 # aantal threads voor de daemon op één schijf
osd_failsafe_full_ratio: 0.95
osd_heartbeat_grace: 5
osd_heartbeat_interval: 3
osd_map_dedup: true
osd_max_backfills: 2 # aantal gelijktijdige vuloperaties op één 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 # Eigenschappen van hebzucht. Ruimte is snel
osd_pool_default_size: 2 # gaan ontbreken, omdat we tijdelijk
# hebben besloten het aantal
# gegevensreplicaties te verminderen
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 die we indien nodig doorlopend aanpassen
osd_recovery_sleep: 2
osd_scrub_chunk_max: 4Sommige parameters die op QA werden getest in versie 12.2.12 ontbreken in versie ceph 12.2.2, bijvoorbeeld osd_recovery_threads. Daarom was het plan om te upgraden naar 12.2.12 in productie. De praktijk heeft aangetoond dat de versies 12.2.2 en 12.2.12 compatibel zijn in één cluster, wat een rolling update mogelijk maakt.
Testcluster
Natuurlijk was het noodzakelijk om dezelfde versie te hebben voor de test als die in productie, maar op het moment dat ik begon met werken met het cluster, was er alleen een nieuwere versie beschikbaar in de repository. Na te hebben gekeken wat de verschillen waren in de minor versie, bleek dat deze niet zo groot waren (1393 regels in de configuraties tegenover 1436 de nieuwe versie), besloten we te beginnen met testen van de nieuwe (het was toch nodig om te upgraden, dus waarom met oude rommel verdergaan)
Het enige wat we hebben proberen te behouden van de oude versie was het pakket ceph-deploy, aangezien een deel van de tools (en een deel van de medewerkers) was afgestemd op de syntaxis ervan. De nieuwe versie verschild behoorlijk, maar had verder geen invloed op de werking van het cluster, dat bleef in de oude versie. 1.5.39
Aangezien het team van ceph-disk duidelijk aangeeft dat het deprecated is en dat je, beste mensen, de ceph-volume command moet gebruiken — begonnen we OSD's te creëren met deze command, zonder tijd te verspillen aan verouderde opties.
Het plan was als volgt — een mirror creëren van twee SSD's, waarop we de logs van OSD's plaatsen, die op hun beurt zich bevinden op gespinde SAS-schijven. Op die manier dekken we ons in voor dataproblemen bij het falen van een schijf met de log.
We begonnen met het opzetten van het cluster volgens de documentatie.
cat /etc/ceph/ceph.conf
root@ceph01-qa:~# cat /etc/ceph/ceph.conf # vooraf voorbereide configuratie
[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 # adres gewijzigd, natuurlijk ))
rgw_dns_name = s3-qa.mycompany.ru # en dit adres ook gewijzigd
rgw_host = s3-qa.mycompany.ru # en dit ook
[mon]
mon allow pool delete = true
mon_max_pg_per_osd = 300 # meer dan driehonderd plaatsingsgroepen
# op de schijf niet geprobeerd
# hoewel deze parameter, vanzelfsprekend, afhangt van het aantal pools,
# hun groottes en het aantal OSD's. Weinig maar gezonde PG's
# is ook niet de beste keuze - de nauwkeurigheid van balans
mon_osd_backfillfull_ratio = 0.9
mon_osd_down_out_interval = 5
mon_osd_full_ratio = 0.95 # voor SSD-schijven is de ruimte voor hun
# journal hetzelfde apparaat als voor de OSD
# we besloten dat 5% van de schijf (die zelf 1,2TB groot is)
# dat moet genoeg zijn, en correleert met de parameter
# bluestore_block_db_size plus variabiliteit op grote
# plaatsingsgroepen
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-qHet eerste waar ik op stuitte bij het werken met deze versie van ceph-deploy met cluster versie 12.2.12, is een fout bij het proberen een OSD met db aan te maken op software RAID —
root@ceph01-qa:~#ceph-volume lvm create --bluestore --data /dev/sde --block.db /dev/md0
blkid kon geen PARTUUID detecteren voor apparaat: /dev/md1Inderdaad, blkid toont geen PARTUUID, dus ik moest handmatig partities aanmaken:
root@ceph01-qa:~#parted /dev/md0 mklabel GPT
# Er zullen veel partities zijn,
# zonder GPT kunnen ze niet worden aangemaakt
# De grootte van de partitie hebben we hierboven in de configuratie opgegeven = bluestore_block_db_size: '5368709120 #5G'
# Ik heb 20 schijven voor OSD, handmatig partities aanmaken is te veel werk
# dus ik maakte een lus
root@ceph01-qa:~#for i in {1..20}; do echo -e "nnnn+5Gnw" | fdisk /dev/md0; doneAlles lijkt klaar, laten we opnieuw proberen een OSD aan te maken en we krijgen de volgende fout (die, trouwens, niet op de productieomgeving werd gereproduceerd)
bij het aanmaken van een OSD van het type bluestore zonder het pad naar WAL op te geven, maar met het aangeven van 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 onverwerkbare uuid
stderr: 2019-04-12 10:39:27.213185 7eff461b6e00 -1 bdev(0x55824c273680 /var/lib/ceph/osd/ceph-0//block.wal) open open kreeg: (22) Ongeldig argument
stderr: 2019-04-12 10:39:27.213201 7eff461b6e00 -1 bluestore(/var/lib/ceph/osd/ceph-0/) _open_db voegt blok apparaat (/var/lib/ceph/osd/ceph-0//block.wal) terug: (22) Ongeldig argument
stderr: 2019-04-12 10:39:27.999039 7eff461b6e00 -1 bluestore(/var/lib/ceph/osd/ceph-0/) mkfs mislukt, (22) Ongeldig argument
stderr: 2019-04-12 10:39:27.999057 7eff461b6e00 -1 OSD::mkfs: ObjectStore::mkfs mislukt met fout (22) Ongeldig argument
stderr: 2019-04-12 10:39:27.999141 7eff461b6e00 -1 ** FOUT: fout bij het aanmaken van de lege objectopslag in /var/lib/ceph/osd/ceph-0/: (22) Ongeldig argumentAls je echter op dezelfde spiegel (of op een andere plaats, wat je maar wilt) nog een partitie voor WAL aanmaakt en deze opgeeft bij het aanmaken van OSD — dan verloopt alles soepel (met uitzondering van het verschijnen van een aparte WAL, die je mogelijk niet wilde).
Maar omdat het in de verre toekomst de bedoeling was om WAL naar NVMe te verplaatsen, bleek deze oefening nuttig.
root@ceph01-qa:~#ceph-volume lvm create --bluestore --data /dev/sdf --block.wal /dev/md0p2 --block.db /dev/md1p2We hebben monitoren, managers en OSD's aangemaakt. Nu willen we ze op verschillende manieren groeperen, omdat we van plan zijn schijven van verschillende types te hebben — snelle pools op SSD en grote, maar langzame op traditionele HDD's.
Laten we aannemen dat er op de servers 20 schijven zijn, de eerste tien zijn één type, de tweede is een ander.
De initiële, standaard kaart ziet er zo uit:
ceph osd tree
root@ceph01-q:~# ceph osd tree
ID KLASSE GEWICHT TYPE NAAM STATUS HERWEEG PRI-AFF
-1 14.54799 root default
-3 9.09200 host 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
Laten we onze virtuele racks en servers maken met blackjack en zo meer:
root@ceph01-q:~#ceph osd crush add-bucket rack01 root #nieuwe root gemaakt
root@ceph01-q:~#ceph osd crush add-bucket ceph01-q host #nieuwe host gemaakt
root@ceph01-q:~#ceph osd crush move ceph01-q root=rack01 #server naar ander rack verhuisd
root@ceph01-q:~#osd crush add 28 1.0 host=ceph02-q # OSD aan server toegevoegd
# Als iets verkeerd is aangemaakt kan het worden verwijderd
root@ceph01-q:~# ceph osd crush remove osd.4
root@ceph01-q:~# ceph osd crush remove rack01De problemen die we tegenkwamen in de productie cluster bij het proberen om nieuwe hosts aan te maken en deze naar een bestaand rack te verplaatsen - het commando ceph osd crush move ceph01-host root=rack01 bevroor, en de monitoren begonnen een voor een te vallen. Het onderbreken van het commando met CTRL+C bracht het cluster weer tot leven.
Onderzoek toonde het volgende probleem aan:
De oplossing was om de crushmap te dumpen en het gedeelte rule replicated_ruleset
root@ceph01-prod:~#ceph osd getcrushmap -o crushmap.row #Dump de kaart in rauwe vorm
root@ceph01-prod:~#crushtool -d crushmap.row -o crushmap.txt #vertaal het naar leesbaar
root@ceph01-prod:~#vim crushmap.txt #bewerk, verwijder de rule replicated_ruleset
root@ceph01-prod:~#crushtool -c crushmap.txt -o new_crushmap.row #compileer opnieuw
root@ceph01-prod:~#ceph osd setcrushmap -i new_crushmap.row #laden in clusterWaarschuwing: deze operatie kan een herschikking van de plaatsingsgroep tussen OSD veroorzaken. Dit heeft bij ons plaatsgevonden, maar in zeer beperkte mate.
Een vreemde zaak waarmee we in het testcluster te maken kregen, was dat na het herstarten van de server, OSD vergeten waren dat ze naar nieuwe servers en racks waren verplaatst en terugkeerden naar de root default.
Uiteindelijk, na het samenstellen van het eindschema waarbij we een aparte root voor SSD-schijven en een aparte voor spindel-schijven hebben gecreëerd, hebben we alle OSD's over de racks verdeeld en gewoon de default root verwijderd. Na een herstart bleven de OSD's op hun plek.
Later, na verder onderzoek in de documentatie, vonden we de parameter die verantwoordelijk is voor dit gedrag. Hierover in het tweede deel.
Hoe we verschillende groepen op basis van schijftypen hebben gemaakt.
We begonnen met het creëren van twee roots — één voor SSD en één voor HDD.
root@ceph01-q:~#ceph osd crush add-bucket ssd-root root
root@ceph01-q:~#ceph osd crush add-bucket hdd-root rootAangezien de servers fysiek in verschillende racks staan, hebben we voor het gemak racks gecreëerd en daar de servers in geplaatst.
# Стойки:
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 hosten hebben we de schijven op basis van hun typen over verschillende servers verdeeld.
root@ceph01-q:~# Schijven 0 tot 3 zijn SSD's, bevindende zich in ceph01-q, we plaatsen ze in de server
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:~# analogisch voor de andere servers.Door de schijven over de roots ssd-root en hdd-root te verdelen, hebben we de root-default leeg gelaten, dus kunnen we deze verwijderen.
root-ceph01-q:~#ceph osd crush remove defaultDaarna moeten we distributieregels aanmaken die we zullen koppelen aan de te creëren pools — in de regels geven we aan in welke root we de gegevens van onze pool kunnen plaatsen en het niveau van replica-uniekheid — bijvoorbeeld dat replicas zich verplicht op verschillende servers of in verschillende racks moeten bevinden (zelfs in verschillende roots, als we zo'n verdeling hebben).
Voordat u het type kiest, is het beter om de documentatie te lezen:
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:~# We hebben twee regels opgegeven waarbij de gegevens worden gerepliceerd
root-ceph01-q:~# tussen hosts - dat wil zeggen, de replica moet zich op een andere host bevinden,
root-ceph01-q:~# zelfs als ze zich in dezelfde rack bevinden.
root-ceph01-q:~# In productie, als het mogelijk is, is het beter om hosts te verdelen
root-ceph01-q:~# over racks en te specificeren om replicas te verdelen over racks:
root-ceph01-q:~# ##ceph osd crush rule create-simple rule-ssd ssd-root rack firstnLaten we pools aanmaken waarin we in de toekomst de schijven van onze virtualisatie willen opslaan — 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 1024En we geven deze pools aan welke plaatsingsregels ze moeten gebruiken.
root-ceph01-q:~#ceph osd crush rule ls # bekijk de lijst met regels
root-ceph01-q:~#ceph osd crush rule dump rule-ssd | grep rule_id # kies de benodigde ID
root-ceph01-q:~#ceph osd pool set ssd_pool crush_rule 2
Bij het kiezen van het aantal plaatsingsgroepen moet je rekening houden met een vooraf bepaald idee van je cluster — hoeveel OSD's er ongeveer zullen zijn, welk percentage van de totale opslagcapaciteit in de pool zal zitten, en hoeveel gegevens er in totaal zijn.
In totaal is het wenselijk om niet meer dan 300 plaatsingsgroepen per schijf te hebben, en het is eenvoudiger om te balanceren met kleine plaatsingsgroepen — bijvoorbeeld als je pool 10 Tb groot is en het heeft 10 PG's, dan zou het problematisch zijn om te balanceren door terabytes (pg) heen en weer te schuiven — het is gemakkelijker en gelijkmatiger om zand met een kleine korrelgrootte met emmers te verplaatsen.
Maar je moet wel bedenken dat hoe meer PG's er zijn, hoe meer middelen er verbruikt worden voor het berekenen van hun locatie — dat begint het geheugen en de CPU te belasten.
Een ruw begrip kan , verstrekt door de ontwikkelaars van de CEPH-documentatie.
Lijst met materialen:
Bron: habr.com
