Wahl von CEPH. Teil 1
Wir hatten fünf Racks, zehn optische Switches, konfiguriertes BGP, ein paar Dutzend SSDs und eine Menge SAS-Festplatten in allen Farben und Größen, sowie Proxmox und den Wunsch, all die statischen Daten in einen eigenen S3-Speicher zu stecken. Es war nicht unbedingt nötig für die Virtualisierung, aber wenn man schon Open Source nutzt, sollte man das Hobby bis zum Ende verfolgen. Das Einzige, was mich beunruhigte, war das BGP. Es gibt niemanden auf der Welt, der so hilflos, verantwortungslos und moralisch fragwürdig ist, wie die interne BGP-Routing. Und ich wusste, dass wir uns bald darin verlieren würden.

Die Aufgabe war banal – es gab CEPH, der nicht besonders gut funktionierte. Es musste "gut" gemacht werden.
Der Cluster, der mir übergeben wurde, war heterogen, schnell zusammengestellt und praktisch nicht getunt. Er bestand aus zwei Gruppen verschiedener Nodes, mit einem gemeinsamen Netzwerk, das sowohl als Cluster- als auch als Public Network diente. Die Nodes waren mit vier Arten von Festplatten ausgestattet – zwei Arten von SSDs, die in zwei verschiedenen Placement Rules organisiert waren, und zwei Arten von HDDs unterschiedlicher Größe, die in einer dritten Gruppe zusammengefasst waren. Das Problem mit den unterschiedlichen Größen wurde durch verschiedene Gewichte der OSDs gelöst.
Die Konfiguration selbst wurde in zwei Teile aufgeteilt – Tuning des Betriebssystems und Optimierung von CEPH und dessen Einstellungen.
Upgrade des Betriebssystems
Netzwerk
Hohe Latenz wirkte sich sowohl beim Schreiben als auch beim Load-Balancing aus. Beim Schreiben, da der Client keine Bestätigung über einen erfolgreichen Schreibvorgang erhält, solange die Datenkopien in anderen Placement-Gruppen den Erfolg nicht bestätigen. Da die Replikationsregeln im CRUSH-Map so gestaltet waren, dass jeweils nur eine Replikat pro Host vorhanden ist, wurde die Verbindung immer belastet.
Deshalb habe ich mich zuerst entschieden, das aktuelle Netzwerk etwas anzupassen und parallel zu versuchen, auf separate Netzwerke umzusteigen.
Für den Anfang habe ich die Einstellungen der Netzwerkkarten angepasst. Ich begann mit der Konfiguration der Warteschlangen:
Was war vorhanden:
ethtool -l ens1f1
root@ceph01:~# ethtool -l ens1f1
Kanalparameter für ens1f1:
Voreingestellte Maximalwerte:
RX: 0
TX: 0
Sonstige: 1
Kombiniert: 63
Aktuelle Hardware-Einstellungen:
RX: 0
TX: 0
Sonstige: 1
Kombiniert: 1
root@ceph01:~# ethtool -g ens1f1
Ringparameter für ens1f1:
Voreingestellte Maximalwerte:
RX: 4096
RX Mini: 0
RX Jumbo: 0
TX: 4096
Aktuelle Hardware-Einstellungen:
RX: 256
RX Mini: 0
RX Jumbo: 0
TX: 256
root@ceph01:~# ethtool -l ens1f1
Kanalparameter für ens1f1:
Voreingestellte Maximalwerte:
RX: 0
TX: 0
Sonstige: 1
Kombiniert: 63
Aktuelle Hardware-Einstellungen:
RX: 0
TX: 0
Sonstige: 1
Kombiniert: 1Es ist deutlich, dass die aktuellen Parameter von den maximalen Werten entfernt sind. Ich habe sie erhöht:
root@ceph01:~#ethtool -G ens1f0 rx 4096
root@ceph01:~#ethtool -G ens1f0 tx 4096
root@ceph01:~#ethtool -L ens1f0 combined 63Gestützt auf einen hervorragenden Artikel
habe ich die Länge der Warteschlange für den Versand erhöht. txqueuelen von 1000 bis 10 000
root@ceph01:~#ip link set ens1f0 txqueuelen 10000Und gemäß der Dokumentation von Ceph
erhöht MTU auf 9000.
root@ceph01:~#ip link set dev ens1f0 mtu 9000Habe ich in /etc/network/interfaces hinzugefügt, damit all dies beim Start geladen wird
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 9000Nachfolgend, gemäß diesem Artikel, begann ich sorgfältig, die Kernelparameter 4.15 anzupassen. Angesichts von 128G RAM auf den Knoten entstand eine bestimmte Konfigurationsdatei für sysctl
cat /etc/sysctl.d/50-ceph.conf
net.core.rmem_max = 56623104
# Maximale Größe des Empfangspuffers für alle Verbindungen 54M
net.core.wmem_max = 56623104
# Maximale Größe des Übertragungspuffers für alle Verbindungen 54M
net.core.rmem_default = 56623104
# Standardgröße des Empfangspuffers für alle Verbindungen. 54M
net.core.wmem_default = 56623104
# Standardgröße des Übertragungspuffers für alle Verbindungen 54M
# für jeden Socket
net.ipv4.tcp_rmem = 4096 87380 56623104
# Vektorvariable (Minimum, Standard, Maximum) in der tcp_rmem-Datei
# bestehend aus 3 Ganzzahlen, die die Größe des Empfangspuffers von TCP-Sockets definieren.
# Minimum: Jeder TCP-Socket hat das Recht, diesen Speicher bei
# seiner Erstellung zu nutzen. Die Möglichkeit, diesen Puffer zu verwenden,
# wird sogar bei Erreichen des Schwellenlimits (moderate memory pressure) garantiert.
# Die Standardgröße des Minimalpuffers beträgt 8 KB (8192).
# Der Standardwert: erlaubter Speicher für den TCP-Socket-Übertragungspuffer.
# Dieser Wert ersetzt den Parameter /proc/sys/net/core/rmem_default,
# der von anderen Protokollen verwendet wird.
# Der standardmäßig verwendete Pufferwert beträgt in der Regel (standardmäßig)
# 87830 Bytes. Dies definiert die Fenstergröße 65535 mit
# dem standardmäßigen tcp_adv_win_scale-Wert und tcp_app_win = 0,
# etwas geringer als der standardmäßig festgelegte Wert für tcp_app_win.
# Maximum: Maximale Größe des Puffers, die für den Empfang eines TCP-Sockets
# automatisch zugewiesen werden kann. Dieser Wert hebt das Maximum,
# das in der Datei /proc/sys/net/core/rmem_max festgelegt ist, nicht auf.
# Bei "statischer" Speicherzuweisung mit Hilfe von SO_RCVBUF hat dieser Parameter keine Bedeutung.
net.ipv4.tcp_wmem = 4096 65536 56623104
net.core.somaxconn = 5000
# Maximale Anzahl offener Sockets, die auf Verbindungen warten.
net.ipv4.tcp_timestamps=1
# Erlaubt die Verwendung von Zeitstempeln (timestamps) gemäß RFC 1323.
net.ipv4.tcp_sack=1
# Erlauben Sie die selektive Bestätigung des TCP-Protokolls.
net.core.netdev_max_backlog=5000 (Standard 1000)
# Maximale Anzahl von Paketen in der Warteschlange, wenn
# das Interface Pakete schneller empfängt, als das Kernel sie verarbeiten kann.
net.ipv4.tcp_max_tw_buckets=262144
# Maximale Anzahl von Sockets, die sich gleichzeitig im STATE TIME-WAIT befinden.
# Bei Überschreitung dieser Schwelle wird ein "überflüssiger" Socket zerstört und eine
# Nachricht im Systemprotokoll geschrieben.
net.ipv4.tcp_tw_reuse=1
# Erlauben Sie die Wiederverwendung von TIME-WAIT-Sockets,
# wenn das Protokoll dies für sicher hält.
net.core.optmem_max=4194304
# Erhöhen Sie den maximalen gemeinsamen ALLOCATABLE-Speicher.
# gemessen in Seiten (4096 Bytes)
net.ipv4.tcp_low_latency=1
# Erlaubt dem TCP/IP-Stack, niedrige Verzögerung
# gegenüber höherer Bandbreite zu bevorzugen.
net.ipv4.tcp_adv_win_scale=1
# Diese Variable beeinflusst die Berechnung des Speicherplatzes im Socketpuffer,
# der für die Größe des TCP-Fensters und den Anwendungsbuffer zugewiesen ist.
# Wenn tcp_adv_win_scale negativ ist, wird folgende Formel für die Berechnung verwendet:
# Bytes - bytes2 hoch -tcp_adv_win_scale
# wobei bytes die Größe des Fensters in Bytes ist. Ist tcp_adv_win_scale positiv,
# wird folgende Formel verwendet:
# Bytes - bytes2 hoch tcp_adv_win_scale
# Die Variable nimmt einen ganzzahligen Wert an. Der Standardwert beträgt 2,
# das heißt, für den Anwendungsbuffer wird ¼ des Volumens,
# das durch tcp_rmem definiert ist, zugewiesen.
net.ipv4.tcp_slow_start_after_idle=0
# Mechanismus für den langsamen Start, der den Wert des Fenster einer
# Überlastung zurücksetzt, wenn die Verbindung für einen bestimmten Zeitraum nicht verwendet wurde.
# Es ist besser, SSR auf dem Server zu deaktivieren, um die Leistung
# langlebiger Verbindungen zu verbessern.
net.ipv4.tcp_no_metrics_save=1
# Speichern Sie die TCP-Verbindungsmetriken nicht im Cache beim Schließen.
net.ipv4.tcp_syncookies=0
# Deaktivieren Sie den Sendemechanismus für Syncookies.
net.ipv4.tcp_ecn=0
# Explicit Congestion Notification (explizite Überlastbenachrichtigung) in
# TCP-Verbindungen. Wird verwendet, um auf das Auftreten eines "Staus"
# auf dem Weg zu einem bestimmten Host oder Netzwerk hinzuweisen. Kann verwendet werden, um den
# sender-Host darüber zu informieren, dass die Übertragungsgeschwindigkeit über einen bestimmten Router
# oder eine Firewall verringert werden muss.
net.ipv4.conf.all.send_redirects=0
# Deaktiviert das Versenden von ICMP Redirect ... an andere Hosts. Diese Option
# muss aktiviert sein, wenn der Host als Router fungiert.
# Wir haben keine Routing.
net.ipv4.ip_forward=0
# Deaktivierung des Forwardings. Wir sind kein Gateway, Docker auf Maschinen läuft nicht,
# wir benötigen das nicht.
net.ipv4.icmp_echo_ignore_broadcasts=1
# Wir antworten nicht auf ICMP ECHO-Anfragen, die über Broadcast-Pakete gesendet werden.
net.ipv4.tcp_fin_timeout=10
# bestimmt die Zeit, in der der Socket in FIN-WAIT-2 nach seiner
# Schließung durch die lokale Seite verbleibt. Standard 60
net.core.netdev_budget=600 # (Standard 300)
# Wenn die Verarbeitung von Software-Interrupts nicht lange genug durchgeführt wird,
# kann die Rate des eingehenden Datenstroms die Fähigkeit des Kernels überschreiten,
# den Puffer zu leeren. Infolgedessen werden die NIC-Puffer überflutet, und der Datenverkehr geht verloren.
# Manchmal ist es notwendig, die Dauer von SoftIRQs
# (Software-Interrupts) mit der CPU zu erhöhen. Dafür ist netdev_budget verantwortlich.
# Der Standardwert beträgt 300. Der Parameter zwingt den SoftIRQ-Prozess,
# 300 Pakete von NIC zu verarbeiten, bevor er die CPU freigibt.
net.ipv4.tcp_fastopen=3
# TFO TCP Fast Open
# wenn sowohl der Client als auch der Server Unterstützung für TFO haben, die durch
# ein spezielles Flag im TCP-Paket signalisiert wird. In unserem Fall ist es ein Placebo, sieht einfach
# nur gut aus)ELuster-Netzwerk wurde auf separaten 10Gbps-Netzwerkschnittstellen in ein separates flaches Netzwerk ausgegliedert. Auf jeder Maschine wurden Netzwerk-Dual-Port-Karten installiert. Mellanox 10/25 Gbps, die in zwei separate 10Gbps-Switches gesteckt wurden. Die Aggregation erfolgte über OSPF, da das Bonding mit LACP aus unerfindlichen Gründen eine Gesamtbandbreite von maximal 16 Gbps zeigte, während OSPF erfolgreich beide Zehner auf jeder Maschine vollständig ausnutzte. In Zukunft war geplant, ROCE auf diesen Mellanox-Geräten zu nutzen, um die Latenz zu verringern. So wurde dieser Teil des Netzwerks eingerichtet:
- Da die Maschinen externe IP-Adressen über BGP haben, benötigen wir folgende Software — (genauer gesagt war das zum Zeitpunkt der Erstellung des Artikels ) bereits installiert.
- Insgesamt hatten die Maschinen zwei Netzwerkkarten mit je zwei Schnittstellen — insgesamt 4 Ports. Eine Netzwerkkarte mit zwei Ports zeigte auf die Fabrik, auf der BGP konfiguriert war, die andere mit zwei Ports zeigte auf zwei verschiedene Switches, und auf sie wurde OSPF angewendet.
Weitere Details zur OSPF-Konfiguration: Die Hauptaufgabe besteht darin, zwei Links zu aggregieren und Fehlertoleranz zu gewährleisten.
Die beiden Netzwerkschnittstellen sind in zwei einfache flache Netzwerke konfiguriert — 10.10.10.0/24 und 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 ens1f1über die Maschinen, die sich gegenseitig sehen.
DISK
Der nächste Schritt bestand darin, die Leistung der Festplatten zu optimieren. Für SSDs habe ich den Scheduler auf noop, für HDDs — deadline. Grob gesagt: NOOP funktioniert nach dem Prinzip "Wer zuerst kommt, mahlt zuerst", was im Englischen als "FIFO (First In, First Out)" bezeichnet wird. Anfragen werden in der Reihenfolge ihres Eingangs in eine Warteschlange gestellt. DEADLINE ist stärker auf das Lesen ausgelegt, zusätzlich erhält der Prozess aus der Warteschlange nahezu monopolistischen Zugang zur Festplatte während der Operation. Das passt hervorragend zu unserem System — denn nur ein Prozess arbeitet mit jeder Festplatte — OSD-Daemon.
(Wer tiefer in den I/O-Scheduler eintauchen möchte, kann hier darüber lesen:
Für diejenigen, die auf Russisch lesen möchten: )
In den Empfehlungen zur Optimierung von Linux wird auch geraten, nr_request
nr_requests
Der Wert von nr_requests bestimmt die Anzahl der I/O-Anfragen, die zwischengespeichert werden, bevor der I/O-Scheduler Daten an das Blockgerät sendet oder von diesem empfängt. Wenn Sie eine RAID-Karte oder ein Blockgerät verwenden, das eine größere Warteschlange verarbeiten kann, als der I/O-Scheduler eingestellt ist, kann eine Erhöhung des Wertes von nr_requests dabei helfen, die Durchsatzrate zu verbessern und die Serverlast zu reduzieren, wenn große Mengen an I/O auf dem Server auftreten. Bei Verwendung von Deadline oder CFQ als Scheduler wird empfohlen, den nr_request-Wert auf das Doppelte der Queue-Tiefe einzustellen.
ABER! Die Entwickler von CEPH selbst überzeugen uns, dass ihr Prioritätssystem besser funktioniert.

WBThrottle und/oder nr_requests
WBThrottle und/oder nr_requests
Der Dateispeicher nutzt für das Schreiben gepufferte Ein-/Ausgabeoperationen; dies bringt eine Reihe von Vorteilen mit sich, wenn das Protokoll des Dateispeichers auf einem schnelleren Medium liegt. Kundenanfragen erhalten eine Benachrichtigung, sobald die Daten im Protokoll geschrieben sind, und werden dann später gemäß der Standardfunktionalität von Linux auf die Datenträger zurückgeschrieben. Dies ermöglicht es OSD-Spindelplatten, eine Schreiblatenz ähnlich der von SSDs bei kleinen Paketaufzeichnungen bereitzustellen. Diese verzögerte Schreiboperation ermöglicht es dem Kernel auch, Ein-/Ausgabeanforderungen an die Festplatte neu zu strukturieren, in der Hoffnung, sie zu konsolidieren oder es den vorhandenen Köpfen der Festplatte zu ermöglichen, einen optimaleren Pfad über ihre Platten zu wählen. Das Endergebnis ist, dass Sie etwas mehr Ein-/Ausgabeoperationen aus jeder Festplatte herausholen können, als dies bei direkten oder synchronen Ein-/Ausgabeoperationen möglich wäre.
Allerdings tritt ein bestimmtes Problem auf, wenn die Menge der eingehenden Datensätze in diesem Ceph-Cluster die Kapazitäten der zugrunde liegenden Festplatten übersteigt. In einem solchen Szenario kann die Gesamtzahl der im Status eingefrorenen Ein-/Ausgabeoperationen, die auf eine Festplatte warten, unkontrolliert ansteigen und zu einer Überlastung der Ein-/Ausgabewarteschlangen führen, die die gesamte Festplatte und die Ceph-Warteschlangen füllt. Leseanfragen sind in besonderem Maße betroffen, da sie zwischen den Schreibanfragen stecken bleiben, die mehrere Sekunden benötigen können, um auf die primäre Festplatte geschrieben zu werden.
Um dieses Problem zu bewältigen, bietet Ceph eine integrierte Schreibverzögerungsdrosselung namens WBThrottle im Objektspeicher an. Sie wurde entwickelt, um die Gesamtzahl der Eingabe-/Ausgabeoperationen für verzögertes Schreiben zu begrenzen, die in Warteschlangen eingereiht werden können, und ihren Rückschreibprozess früher zu starten, als dies von dem Kernel auf natürliche Weise geschehen würde. Leider zeigt die Tests, dass die standardmäßigen Einstellungen möglicherweise immer noch nicht das bestehende Verhalten bis zu einem Niveau einschränken, das die Auswirkungen auf die Latenz der Leseoperationen reduzieren könnte. Eine Anpassung kann dieses Verhalten ändern, die Gesamtlängen der Schreibwarteschlangen reduzieren und somit die Auswirkungen verringern. Es gibt jedoch einen Kompromiss: Wenn Sie die maximale Anzahl an zulässigen Schreibvorgängen verringern, könnte dies die Fähigkeit des Kernels beeinträchtigen, die Effizienz bei der Priorisierung eingehender Anfragen zu maximieren. Es ist wichtig, darüber nachzudenken, was für Ihren spezifischen Anwendungsfall und Ihre Arbeitslasten am notwendigsten ist, und diese entsprechend anzupassen.
Um die Tiefe einer solchen Warteschlange für verzögerte Schreibvorgänge zu steuern, können Sie entweder die Gesamtzahl der unvollendeten Eingabe-/Ausgabeoperationen verringern, indem Sie die WBThrottle-Einstellungen anwenden, oder den maximalen Wert für unvollendete Operationen auf Blockebene in Ihrem Kernel senken. Beides kann das gleiche Verhalten effektiv steuern, und letztendlich werden Ihre Präferenzen den Rahmen dieser Einstellung bestimmen.
Es ist auch zu beachten, dass das vorhandene Prioritätssystem in Ceph für kürzere Anfragen auf Festplattenebene effizienter ist. Wenn die Gesamtwarteschlange für dieses Laufwerk verringert wird, verschiebt sich der primäre Standort in der Warteschlange zu Ceph, wo er mehr Kontrolle über die Priorität der Eingabe-/Ausgabeoperation hat. Lassen Sie uns folgendes Beispiel betrachten:
echo 8 > /sys/block/sda/queue/nr_requestsGEMEINSAM
Und noch ein paar Kernel-Einstellungen, die es Ihnen ermöglichen, Ihre Maschine sanfter und geschmeidiger zu machen, um noch etwas mehr Leistung aus der Hardware herauszuholen.
cat /etc/sysctl.d/60-ceph2.conf
kernel.pid_max = 4194303
# In jeder Maschine gibt es 25 Festplatten, daher haben wir mit vielen Prozessen gerechnet.
kernel.threads-max=2097152
# Natürlich auch bei den Threads.
vm.max_map_count=524288
# Anzahl der Map-Bereiche für den Prozess erhöht.
# Wie in der Dokumentation zu den Kernel-Variablen erwähnt
# werden Map-Bereiche als Nebeneffekt von Aufrufen
# wie malloc, mmap, mprotect und madvise verwendet, sowie beim Laden
# von gemeinsamen Bibliotheken.
fs.aio-max-nr=50000000
# Optimierung der Input-Output-Parameter.
# Der Linux-Kernel bietet die Funktion des asynchronen nicht-blockierenden Eingangs- und Ausgangs (AIO),
# die es einem Prozess ermöglicht, mehrere Eingabe-/Ausgabe-Operationen
# gleichzeitig zu initiieren, ohne auf den Abschluss einer davon zu warten.
# Dies trägt zur Leistungssteigerung von Anwendungen bei,
# die die Verarbeitung und die Eingabe/Ausgabe überlappen können.
# Der Parameter aio-max-nr definiert die maximale Anzahl von
# gleichzeitigen zulässigen Anfragen.
vm.min_free_kbytes=1048576
# Minimale Größe des freizuhaltenden Speichers.
# Mit 1 GB ausreichend für das Betriebssystem,
# um OOM Killer für OSD-Prozesse zu vermeiden. Obwohl der Speicher reichlich vorhanden ist,
# schadet ein kleines Polster nicht.
vm.swappiness=10
# Der Befehl verwendet Swap, wenn 10 % des Speichers frei bleiben.
# Bei Maschinen mit 128 GB RAM sind das 12 GB, mehr als genug für den Betrieb.
# Der Standardwert von 60 % führte dazu, dass das System verlangsamte,
# während es in den Swap-Speicher griff, obwohl noch viel freier Speicher vorhanden war.
vm.vfs_cache_pressure=1000
# Erhöhung gegenüber den standardmäßigen 100. Wir zwingen den Kernel dazu,
# unbenutzte Speicherseiten aktiver aus dem Cache zu entladen.
vm.zone_reclaim_mode=0
# Ermöglicht es, aggressivere oder weniger aggressive Ansätze zur
# Speicherwiederherstellung festzulegen, wenn der Speicher in der Zone erschöpft ist.
# Wenn es auf null gesetzt ist, erfolgt keine Wiederherstellung der Zone.
# Für Datei-Server oder Workloads
# ist es vorteilhaft, wenn deren Daten zwischengespeichert werden; zone_reclaim_mode
# sollte deaktiviert bleiben, da der Cache-Effekt
# möglicherweise wichtiger ist als der Standort der Daten.
vm.dirty_ratio=20
# Prozentsatz des Arbeitsspeichers, der für "dreckige" Seiten reserviert werden kann.
# Berechnet aus einer groben Schätzung:
# Das System hat 128 GB Speicher.
# Ca. 20 SSD-Laufwerke, die in den CEPH-Einstellungen
das Caching mit 3 GB RAM konfigurieren.
# Ca. 40 HDD-Laufwerke, für die dieser Parameter 1 GB beträgt.
# 20 % von 128 sind 25,6 GB. Das heißt, im Falle einer maximalen Speicherauslastung
# bleiben dem System 2,4 GB Speicher. Das sollte ausreichen, um zu überleben und auf das
# Rasseln der Hufe der Kavallerie zu warten – sprich auf den DevOps, der alles repariert.
vm.dirty_background_ratio=3
# Prozentsatz des Systemspeichers, der mit schmutzigen Seiten gefüllt werden kann,
# bevor die Hintergrundprozesse pdflush/flush/kdmflush diese auf die Festplatte schreiben.
fs.file-max=524288
# Und wahrscheinlich werden wir viel mehr offene Dateien haben, als standardmäßig angegeben. Einblick in CEPH
Einstellungen, auf die wir näher eingehen möchten:
cat /etc/ceph/ceph.conf
osd:
journal_aio: true # Drei Parameter, die
journal_block_align: true # direkten I/O ermöglichen
journal_dio: true # für das Journal
journal_max_write_bytes: 1073714824 # Maximale Größe
# der einmaligen Schreiboperation im Journal
journal_max_write_entries: 10000 # Anzahl der gleichzeitigen Einträge
journal_queue_max_bytes: 10485760000
journal_queue_max_ops: 50000
rocksdb_separate_wal_dir: true # Separate WAL-Ordner
# Wir haben versucht, das einzurichten
# NVMe
bluestore_block_db_create: true # Separates Gerät für das Journal
bluestore_block_db_size: '5368709120 #5G'
bluestore_block_wal_create: true
bluestore_block_wal_size: '1073741824 #1G'
bluestore_cache_size_hdd: '3221225472 # 3G'
# Hohe RAM-Kapazität ermöglicht
# das Speichern großer Datenmengen
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 # Anzahl der Threads pro Disk
osd_failsafe_full_ratio: 0.95
osd_heartbeat_grace: 5
osd_heartbeat_interval: 3
osd_map_dedup: true
osd_max_backfills: 2 # Anzahl der gleichzeitigen Fülloperationen pro 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 # Besonderheiten der Effizienz. Der Speicherplatz wurde extrem schnell
osd_pool_default_size: 2 # knapp, da wir beschlossen haben,
# die Anzahl der Datenreplikate zu reduzieren
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 # Priorität nach Bedarf regulierbar
osd_recovery_sleep: 2
osd_scrub_chunk_max: 4Einige Parameter, die in QA-Version 12.2.12 getestet wurden, fehlen in der Ceph-Version 12.2.2, zum Beispiel. osd_recovery_threads. Daher war ein Update auf Produktionsumgebung 12.2.12 geplant. Die Praxis zeigte die Kompatibilität der Versionen 12.2.2 und 12.2.12 innerhalb eines Clusters, was ein Rolling Update ermöglicht.
Testcluster
Natürlich war es notwendig, die gleiche Version zu haben wie in der Produktionsumgebung, aber zum Zeitpunkt meines Arbeitsbeginns mit dem Cluster gab es im Repository nur eine neuere Version. Da die Unterschiede in der Minor-Version nicht sehr groß waren (1393 Zeilen in den Konfigurationen im Vergleich zu 1436 in der neuen Version), haben wir beschlossen, die neue Version zu testen (wir müssen sowieso updaten, warum also auf altem Schrott sitzen).
Das Einzige, was wir von der alten Version behalten wollten, war das Paket ceph-deploy, da einige Utilities (und Mitarbeiter) auf deren Syntax ausgelegt waren. Die neue Version unterscheid sich erheblich, beeinträchtigte jedoch die Funktionalität des Clusters nicht, weshalb wir sie in der Version behielten. 1.5.39
Da das Team von ceph-disk eindeutig sagt, dass es veraltet ist und bitte die ceph-volume-Befehle verwenden sollen - begannen wir, OSDs genau mit diesem Befehl zu erstellen, ohne Zeit für die veraltete Version zu verschwenden.
Der Plan bestand darin, ein Spiegelungssystem aus zwei SSDs zu erstellen, auf denen wir die OSD-Logs unterbringen, die wiederum auf spindle-basierten SAS-Laufwerken liegen. So schützen wir uns vor Datenverlust im Falle eines Festplattenausfalls mit den Logs.
Wir haben begonnen, einen Cluster gemäß der Dokumentation zu erstellen.
cat /etc/ceph/ceph.conf
root@ceph01-qa:~# cat /etc/ceph/ceph.conf # vorab vorbereitete Konfiguration
[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 # Adresse geändert, natürlich ))
rgw_dns_name = s3-qa.mycompany.ru # und diese Adresse geändert
rgw_host = s3-qa.mycompany.ru # und diese auch
[mon]
mon allow pool delete = true
mon_max_pg_per_osd = 300 # mehr als dreihundert Placement Gruppen
# auf eine Disk haben wir uns nicht getraut
# obwohl der Parameter natürlich von der Anzahl der Pools,
# deren Größen und der Anzahl der OSD abhängt. Wenige, aber gesunde PGs
# sind auch keine optimale Wahl - die Balance könnte leiden
mon_osd_backfillfull_ratio = 0.9
mon_osd_down_out_interval = 5
mon_osd_full_ratio = 0.95 # vorerst ist der Platz für SSDs
# sowohl für deren Journal wie auch für die OSDs
# auf dem gleichen Gerät. Wir haben entschieden, dass 5%
# des Diskplatzes (der selbst 1,2TB groß ist)
# durchaus ausreichen sollte, was mit dem Parameter
# bluestore_block_db_size plus der Variabilität großer
# Placement Gruppen korreliert
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-qDas erste Problem, auf das ich bei dieser Version von ceph-deploy mit dem Cluster der Version 12.2.12 gestoßen bin, ist ein Fehler beim Versuch, ein OSD mit einer DB auf einer Software-RAID zu erstellen —
root@ceph01-qa:~#ceph-volume lvm create --bluestore --data /dev/sde --block.db /dev/md0
blkid konnte PARTUUID für das Gerät: /dev/md1 nicht erkennenIn der Tat zeigt blkid keine PARTUUID an, ich musste die Partitionen manuell erstellen:
root@ceph01-qa:~#parted /dev/md0 mklabel GPT
# Es werden viele Partitionen benötigt,
# ohne GPT ist dies nicht möglich
# Die Größe der Partition haben wir oben in der Konfiguration angegeben = bluestore_block_db_size: '5368709120 #5G'
# Ich habe 20 Festplatten für OSD, manuell Partitionen zu erstellen ist mühsam
# daher habe ich eine Schleife gemacht
root@ceph01-qa:~#for i in {1..20}; do echo -e "nnnn+5Gnw" | fdisk /dev/md0; doneAlles scheint bereit zu sein, versuchen wir erneut, ein OSD zu erstellen, und erhalten den folgenden Fehler (der übrigens in der Produktion nicht auftrat)
beim Erstellen eines bluestore OSDs ohne Angabe des Pfades zu WAL, aber mit Angabe der 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 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 argumentWenn Sie auf demselben Spiegel (oder an einem anderen Ort Ihrer Wahl) einen weiteren Bereich für WAL erstellen und ihn bei der Erstellung des OSD angeben, dann wird alles reibungslos ablaufen (abgesehen von dem zusätzlichen WAL, den Sie möglicherweise nicht wollten).
Da jedoch in den fernen Plänen war, das WAL auf NVMe auszulagern, erwies sich die Praxis als nützlich.
root@ceph01-qa:~#ceph-volume lvm create --bluestore --data /dev/sdf --block.wal /dev/md0p2 --block.db /dev/md1p2Wir haben Monitore, Manager und OSDs erstellt. Jetzt wollen wir sie unterschiedlich gruppieren, da wir planen, verschiedene Festplattentypen zu verwenden – schnelle Pools auf SSD und große, aber langsame auf SAS-Platten.
Nehmen wir an, dass auf den Servern jeweils 20 Platten sind, die ersten zehn sind vom einen Typ, die anderen zehn vom anderen.
Die ursprüngliche, standardmäßige Karte sieht so aus:
ceph osd tree
root@ceph01-q:~# ceph osd tree
ID KLASSE GEWICHT TYP NAME STATUS NEU-GEWICHT PRI-AFF
-1 14,54799 Wurzel standard
-3 9,09200 Host ceph01-q
0 ssd 1,00000 osd.0 aktiv 1,00000 1,00000
1 ssd 1,00000 osd.1 aktiv 1,00000 1,00000
2 ssd 1,00000 osd.2 aktiv 1,00000 1,00000
3 ssd 1,00000 osd.3 aktiv 1,00000 1,00000
4 hdd 1,00000 osd.4 aktiv 1,00000 1,00000
5 hdd 0,27299 osd.5 aktiv 1,00000 1,00000
6 hdd 0,27299 osd.6 aktiv 1,00000 1,00000
7 hdd 0,27299 osd.7 aktiv 1,00000 1,00000
8 hdd 0,27299 osd.8 aktiv 1,00000 1,00000
9 hdd 0,27299 osd.9 aktiv 1,00000 1,00000
10 hdd 0,27299 osd.10 aktiv 1,00000 1,00000
11 hdd 0,27299 osd.11 aktiv 1,00000 1,00000
12 hdd 0,27299 osd.12 aktiv 1,00000 1,00000
13 hdd 0,27299 osd.13 aktiv 1,00000 1,00000
14 hdd 0,27299 osd.14 aktiv 1,00000 1,00000
15 hdd 0,27299 osd.15 aktiv 1,00000 1,00000
16 hdd 0,27299 osd.16 aktiv 1,00000 1,00000
17 hdd 0,27299 osd.17 aktiv 1,00000 1,00000
18 hdd 0,27299 osd.18 aktiv 1,00000 1,00000
19 hdd 0,27299 osd.19 aktiv 1,00000 1,00000
-5 5,45599 Host ceph02-q
20 ssd 0,27299 osd.20 aktiv 1,00000 1,00000
21 ssd 0,27299 osd.21 aktiv 1,00000 1,00000
22 ssd 0,27299 osd.22 aktiv 1,00000 1,00000
23 ssd 0,27299 osd.23 aktiv 1,00000 1,00000
24 hdd 0,27299 osd.24 aktiv 1,00000 1,00000
25 hdd 0,27299 osd.25 aktiv 1,00000 1,00000
26 hdd 0,27299 osd.26 aktiv 1,00000 1,00000
27 hdd 0,27299 osd.27 aktiv 1,00000 1,00000
28 hdd 0,27299 osd.28 aktiv 1,00000 1,00000
29 hdd 0,27299 osd.29 aktiv 1,00000 1,00000
30 hdd 0,27299 osd.30 aktiv 1,00000 1,00000
31 hdd 0,27299 osd.31 aktiv 1,00000 1,00000
32 hdd 0,27299 osd.32 aktiv 1,00000 1,00000
33 hdd 0,27299 osd.33 aktiv 1,00000 1,00000
34 hdd 0,27299 osd.34 aktiv 1,00000 1,00000
35 hdd 0,27299 osd.35 aktiv 1,00000 1,00000
36 hdd 0,27299 osd.36 aktiv 1,00000 1,00000
37 hdd 0,27299 osd.37 aktiv 1,00000 1,00000
38 hdd 0,27299 osd.38 aktiv 1,00000 1,00000
39 hdd 0.27299 osd.39 aktiv 1.00000 1.00000
-7 6.08690 host ceph03-q
40 ssd 0.27299 osd.40 aktiv 1.00000 1.00000
41 ssd 0.27299 osd.41 aktiv 1.00000 1.00000
42 ssd 0.27299 osd.42 aktiv 1.00000 1.00000
43 ssd 0.27299 osd.43 aktiv 1.00000 1.00000
44 hdd 0.27299 osd.44 aktiv 1.00000 1.00000
45 hdd 0.27299 osd.45 aktiv 1.00000 1.00000
46 hdd 0.27299 osd.46 aktiv 1.00000 1.00000
47 hdd 0.27299 osd.47 aktiv 1.00000 1.00000
48 hdd 0.27299 osd.48 aktiv 1.00000 1.00000
49 hdd 0.27299 osd.49 aktiv 1.00000 1.00000
50 hdd 0.27299 osd.50 aktiv 1.00000 1.00000
51 hdd 0.27299 osd.51 aktiv 1.00000 1.00000
52 hdd 0.27299 osd.52 aktiv 1.00000 1.00000
53 hdd 0.27299 osd.53 aktiv 1.00000 1.00000
54 hdd 0.27299 osd.54 aktiv 1.00000 1.00000
55 hdd 0.27299 osd.55 aktiv 1.00000 1.00000
56 hdd 0.27299 osd.56 aktiv 1.00000 1.00000
57 hdd 0.27299 osd.57 aktiv 1.00000 1.00000
58 hdd 0.27299 osd.58 aktiv 1.00000 1.00000
59 hdd 0.89999 osd.59 aktiv 1.00000 1.00000
Lassen Sie uns virtuelle Racks und Server mit Blackjack und anderem erstellen:
root@ceph01-q:~#ceph osd crush add-bucket rack01 root #neuen root erstellt
root@ceph01-q:~#ceph osd crush add-bucket ceph01-q host #neuen Host erstellt
root@ceph01-q:~#ceph osd crush move ceph01-q root=rack01 #Server in ein anderes Rack verschoben
root@ceph01-q:~#osd crush add 28 1.0 host=ceph02-q # OSD zum Server hinzugefügt
# Wenn falsch erstellt, kann man löschen
root@ceph01-q:~# ceph osd crush remove osd.4
root@ceph01-q:~# ceph osd crush remove rack01Probleme, denen wir begegnet sind in operationalerweise Cluster, beim Versuch neue Hosts zu erstellen und sie in ein bestehendes Rack zu verschieben — Befehl ceph osd crush move ceph01-host root=rack01 Es kam zu einer Unterbrechung, und die Monitore fielen nacheinander aus. Ein einfaches CTRL+C brachte das Cluster zurück in die Welt der Lebenden.
Die Suche ergab folgendes Problem:
Die Lösung bestand darin, die Crushmap zu dumpen und den Abschnitt zu entfernen rule replicated_ruleset.
root@ceph01-prod:~#ceph osd getcrushmap -o crushmap.row #Dump der Karte im Raw-Format
root@ceph01-prod:~#crushtool -d crushmap.row -o crushmap.txt #Konvertierung in lesbaren Text
root@ceph01-prod:~#vim crushmap.txt #Bearbeiten und Entfernen des rule replicated_ruleset
root@ceph01-prod:~#crushtool -c crushmap.txt -o new_crushmap.row #Wieder zurückkompilieren
root@ceph01-prod:~#ceph osd setcrushmap -i new_crushmap.row #Laden in das ClusterAchtung: Diese Operation kann das Rebalancing der Placement Groups zwischen OSD verursachen. Bei uns führte dies allerdings nur zu minimalen Veränderungen.
Eine Merkwürdigkeit, mit der wir im Testcluster konfrontiert wurden, ist, dass nach einem Neustart des OSD-Servers diese vergaßen, dass sie auf neue Server und Racks verschoben wurden und zurück in den Root-Default gingen.
Insgesamt haben wir ein Endschema erstellt, in dem wir separate Roots für SSDs und für HDDs angelegt haben. Wir haben alle OSDs über die Racks verteilt und einfach den Default-Root entfernt. Nach dem Neustart blieben die OSDs an ihren Plätzen.
Nach eingehender Prüfung der Dokumentation haben wir den Parameter gefunden, der für dieses Verhalten verantwortlich ist. Darüber wird in Teil zwei gesprochen.
Wie wir verschiedene Gruppen nach Festplattentypen erstellt haben.
Zunächst haben wir zwei Root-Punkte erstellt – für SSD und für HDD.
root@ceph01-q:~#ceph osd crush add-bucket ssd-root root
root@ceph01-q:~#ceph osd crush add-bucket hdd-root rootDa die physischen Server in verschiedenen Racks stehen, haben wir zur Vereinfachung Racks erstellt und die Server dort platziert.
# Стойки:
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 hostUnd haben die Festplatten nach ihren Typen auf verschiedene Server verteilt.
root@ceph01-q:~# Festplatten von 0 bis 3 sind SSD, befinden sich in ceph01-q, wir platzieren sie im 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:~# ähnlich bei anderen ServernNachdem wir die Festplatten auf den Root-Punkten ssd-root und hdd-root verteilt haben, blieb root-default leer, daher können wir ihn löschen.
root-ceph01-q:~#ceph osd crush remove defaultZuerst müssen wir Verteilungsregeln erstellen, die wir mit den zu schaffenden Pools verknüpfen. In den Regeln geben wir an, in welche Root-Daten unser Pool abgelegt werden kann und welches Maß an Einmaligkeit die Replikate haben müssen – beispielsweise müssen die Replikate auf unterschiedlichen Servern oder in verschiedenen Racks liegen (es ist sogar möglich, unterschiedliche Roots zu verwenden, wenn wir eine solche Verteilung haben).
Bevor Sie einen Typ auswählen, sollten Sie die Dokumentation lesen:
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:~# Wir haben zwei Regeln angegeben, in denen die Daten repliziert werden
root-ceph01-q:~# zwischen Hosts – das heißt, die Replikat muss auf einem anderen Host liegen,
root-ceph01-q:~# selbst wenn sie im selben Rack sind.
root-ceph01-q:~# In der Produktion, wenn möglich, sollten die Hosts besser auf
root-ceph01-q:~# Racks verteilt werden, und die Replikate sollten nach Racks verteilt werden:
root-ceph01-q:~# ##ceph osd crush rule create-simple rule-ssd ssd-root rack firstnNun erstellen wir die Pools, in denen wir zukünftig die Image-Daten unserer Virtualisierung – PROXMOX – speichern möchten:
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 1024Und wir geben diesen Pools an, welche Platzierungsregeln sie verwenden sollen.
root-ceph01-q:~#ceph osd crush rule ls # wir sehen uns die RegelListe an
root-ceph01-q:~#ceph osd crush rule dump rule-ssd | grep rule_id # wir wählen die benötigte ID aus
root-ceph01-q:~#ceph osd pool set ssd_pool crush_rule 2
Bei der Auswahl der Anzahl der Placement-Gruppen sollte man bereits eine Vorstellung von seinem Cluster haben – wie viele OSDs werden voraussichtlich vorhanden sein, wie viel Prozent der Gesamtdatenmenge werden im Pool gespeichert, und wie viel Daten insgesamt.
Insgesamt sollten nicht mehr als 300 Placement-Gruppen pro Disk vorhanden sein, und es ist einfacher, mit kleineren Placement-Gruppen zu balancieren – wenn Ihr gesamter Pool beispielsweise 10 TB umfasst und 10 PGs hat, wird es problematisch sein, große Terabyte-Steine (PGs) hin und her zu schieben; es ist einfacher und gleichmäßiger, Sand mit kleinen Körnern in Eimern zu transportieren.
Es sollte jedoch bedacht werden, dass je mehr PGs vorhanden sind, desto mehr Ressourcen für die Berechnung ihrer Position benötigt werden – der Speicher und die CPU beginnen, genutzt zu werden.
Ein ungefähres Verständnis kann , bereitgestellt von den Entwicklern der CEPH-Dokumentation.
Liste der Materialien:
Quelle: habr.com
