Ad hoc Apache Log Analyse mit Webalizer per Kommandozeile

Webalizer ist neben “awstats” ein Urgestein zur Analyse des Verlaufs von Webseitenzugriffen. Webalizer wertet Webserver-Log-Dateien aus; letztere müssen dafür eines unter mehreren normierten Formaten (z.B. das clf-Format; s. https://en.wikipedia.org/ wiki/ Common_Log_Format) aufweisen.

Ergebnis der Auswertung sind HTML-Seiten und Grafiken, die man z.B. über einen Webserver abrufen kann. Man installiert das Tool deshalb normalerweise auf einem zentralen Analyse-Webserver. Über periodische cron-Jobs

  • sammelt man sich dann regelmäßig aktuelle Log-Dateien anderer, zu analysierender produktiver Webserver zusammen,
  • transferiert die Logs dann zu der zentralen webalizer-Installation auf dem Analyse-Server,
  • lässt dort die Analyse durchführen
  • und ruft dann nach Bedarf die aufbereiteten Ergebnis-HTMLs auf.

Hört sich kompliziert an. Tatsächlich kann man sich als Anfänger schon mal im Gestrüpp der Konfigurationsoptionen und des Webserver-Setups verheddern. Die meisten Manuals und “docs” konzentrieren sich auf das obige Szenario – und verstellen so leider ein wenig den Blick auf das Wesentliche. In vielen Fällen geht es nämlich auch viel einfacher:

“webalizer” lässt sich auch auf der Kommandozeile einsetzen und ein Webserver ist überhaupt nicht nötig, wenn man mal ad hoc eine Log-Auswertung durchführen möchte oder muss.

Vor kurzem hatte ich einen solchen Fall – und fand das interessant genug, diesen kleinen Blog-Post zu schreiben.

Die Aufgabenstellung

Vor ein paar Tagen wandte sich ein Bekannter aus Norwegen, dessen Webseite plötzlich über fast 48 Stunden nicht mehr erreichbar war, an meine Frau. Als Ursache ergab sich schließlich, dass der dortige Weg-Hosting-Provider, der interessanterweise über einen sekundären Provider in den USA hosten lässt, Parameter zur Begrenzung der Bandbreite der Webserver-Zugriffe gesetzt hatte. (Off Topic: Dieses gestaffelte Hosting (man spricht auch von “Web-Hotels” – ist in Norwegen Gang und Gebe – ohne dass die Kunden erfahen würden, dass ihre Daten in die USA wandern. Aber da der Durchschnittsnorweger nach meiner Erfahrung an Datenschutz kaum interessiert ist, ist das dort auch kein Thema.)

Gedacht war die Bandbreitenbegrenzung nach erhaltener Auskunft wohl als einfache Sicherheitsmaßnahme; akut führte das Überschreiten der relativ geringen Grenzwerte aber zum Ausfall der Website über fast 2 Tage hinweg.

Nun hätte man ja vielleicht erwarten können, dass sich der norwegische Provider auch um die Ursache der offenbar gestiegenen Bandbreitenanforderungen kümmern würde. Auf Anfrage hatte unser Bekannte aber nur die lapidare Auskunft erhalten, es handele sich wohl um einen “normalen Anstieg des Datenverkehrs auf der Webseite”. So etwas macht mich immer misstrauisch. Es ist zwar nicht unser Job, die Webseite zu überwachen, aber wir haben uns dann im Auftrag des Bekannten mal die Apache Log-Dateien vom Provider zuschicken lassen.

Ich war gerade unterwegs und hatte nur meinen Laptop dabei, als die Log-Dateien eines ganzen Jahres per Mail eintrafen. Für eine erste Analyse genügten dann tatsächlich ein

  • Internetzugang (inkl. DNS-Server-Zugang),
  • “webalizer” auf der Kommandozeile
  • und ein Browser.

Einen Internetzugang erhielt ich über das Hotel, in dem ich abgestiegen war. Die bescheidenen Voraussetzungen sind natürlich nützlich, wenn man mal aus der Ferne Ursachenforschung betreiben soll und keinen Zugang zum betroffenen Webserver hat.

Webalizer auf der Kommandozeile

Man hat also
einen Haufen von Log-Dateien vorliegen und will die auswerten. Wie geht man vor?

  • Schritt 1: Zunächst muss man sich webalizer natürlich aus einem Paket-Repository seiner Linux-Distribution installieren. Dabei treten nach meiner Erfahrung keine Besonderheiten auf.
  • Schritt 2: Um die Arbeit etwas zu organisieren, sollte man sich ein “Log-Verzeichnis” zur Aufbewahrung der Log-Dateien bzw. ein “Zielverzeichnis” für die von webalizer erzeugten Output-Dateien anlegen. Bezeichnen wir die Pfade für unseren Fall mal mit “Path_To_Logs/logs_nw” bzw. “Path_To_Results/webalizer_nw”. Für systematische Arbeiten sollten die Verzeichnisse natürlich sprechende Namen bekommen.
  • Schritt 3: Es schadet nie, einen kurzen filternden Blick in die man-Seiten eines neuen Kommandos zu werfen. Wir lassen uns durch die Vielfalt der dortigen Optionen zu webalizer aber nicht verwirren. Die Kommandostruktur ist einfach:
    “webalizer [Optionen] Pfad_zu_einer_Log-Datei”.

    Nun zu den Optionen:

    • “-v” für “verbose” ist für das Experimentiern mit Linux-Kommandos immer gut.
    • Ferner erschient es logisch, dass wir die Ergebnisse irgendwie bezeichnen müssen; wir entdecken hierzu die Optionen “-n” und “-t” .
    • Dann ist klar, dass wir mehrere Dateien hintereinander auswerten müssen, ohne die Ergebnisse vorheriger Arbeit verlieren zu wollen. Wir finden hierzu die Option “-p” für “Incremental”.
    • Das Output-Verzeichnis muss bekannt gegeben werden; hierzu dient die Option “-o”.

    Für alles andere verlassen wir uns im Moment mal optimistisch auf Standardwerte.

  • Schritt 4: Wir bemühen schließlich die Kommandozeile – in meinem Fall mit:
    ich@mytux:~>webalizer -v -p -n norway-domain -t nw-since-2016 -o Path_To_Results/webalizer_nw  Path_To_Logs/logs_nw/LOG_FILE

LOG_FILE” ist oft von der Form “Domain-Bezeichnung_Monat-Jahr.gz” – z.B.: anracom.com-Jan-2016.gz”. Ja, gezippte Dateien sind zulässig; webalizer kümmert sich intern selbst um den Aufruf von “gunzip”.

Das war’s auch schon. Nun kann man auf der Kommandozeile seine vielen Log-Files händisch aufrufen. Oder aber ein kleines Script schreiben, das den Aufruf der verschiedenen Logdateien und die nötige Variation des Zeitanteils im Dateinamen für einen erledigt.

Während der Auswertung (mit der Option “-v”) erhält man auf der Standardausgabe (im Terminalfenster) typischerweise viele Meldungen zur Reverse-DNS-Analyse.

Ergebnisdarstellungen

Sieht man in das Zielverzeichnis und auf die dort erzeugten Dateien, so bietet sich einem ausschnittsweise etwa folgendes Bild

Es gibt also viel Grafik-Dateien, weitere Hilfsdateien und eine “index.html“-Datei. Letztere können wir aber im Browser unserer Wahl (meist über einen Menüpunkt “Datei öffnen”) direkt aufrufen.

Die Ergebnisse der Auswertungen werden uns danach in Form einfacher Tabellen und Grafiken im Browserfenster präsentiert. In meinem Fall ergab sich etwa folgende Einstiegsseite:

nExtrem auffällig ist hier sofort der ungewöhnlich hohe Wert an transferierten Daten – insbesondere im Februar 2017. Schauen wir uns das mal genau an, indem wir auf den Link für Februar klicken; ich zeige nachfolgend nur Ausschnitte aus der detaillierten Seite für selbigen Monat:

Diese Grafik spricht schon mal dafür, dass die Hauptzugriffe nicht aus einer mitteleuropäischen Zeitzone erfolgen. Faktisch zeigen weitere Graphen, die ich hier nicht abbilde, dass viele Besucher in den USA lokalisiert waren.

Es lohnt sich, danach eine Blick auf die vielen anderen Grafiken zu werfen, die einem webalizer zu anderen Zusammenhängen bzgöl. erfasster Zugriffsdaten anbietet. Als ich mir etwa die Zuordnung der Datentransfermenge zu Ursprungsadressen ansah, ergab sich Folgendes:

Aha, da erkennen wir, dass die großen Dateitransfers von einigen wenigen Hosts erzeugt werden. Eine genauere nachfolgende Analyse führt dann etwa über die Ermittlung der zugehörigen IP-Adressen (z.B. mit ping oder gezielten DNS-Abfragen) und ein systematisches Durchsuchen von Blacklists im Internet.

So erhalten wir für den Hauptbösewicht “ec2-52-3-105-23.compute-1.amazonaws.com” (IP: 52.3.127.144), der sich auf er Website des Bekannten schon in früheren Monaten hervorgetan hatte, einen Eintrag bei https://www.abuseipdb.com/ und http://ipaddress.com/blacklist-check/:

Und auch hier ist der ungebetene Gast des norwegischen Bekannten zu finden: https://myip.ms/view/blacklist/872644496/52.3.127.144 und http://whatismyipaddress.com/blacklist-check

Fazit: This guy is up to no good!

Generell gilt, dass bei anonymen Bot-/Crawler-Systemen, die unter Amazon AWS gehostet sind und die Daten von Webseiten komplett herunterladen, Vorsicht geboten ist.

Unser Plagegeist gehört ferner zu einem Bot-Netz namens “ltx71”:
https://udger.com/resources/ua-list/bot-detail?bot=ltx71
https://myip.ms/view/web_bots/1239532/Known_Web_Bots_ltx71_http_ltx71_com.html

Was Gutes ist über “ltx71” im Internet nicht in Erfahrung zu bringen. Die “Homepage” beinhaltet nur 2 Sätze: Ja, wir crawlen das Netz, aber für Sicherheitszwecke. Echt? Menschheitsfreunde? Auch ansonsten findet man auffallend wenig:
http://review.easycounter.com/ltx71-scam-report
http://www.diamantnetz.de/ wzn/a_infos/ botdestages.php
http://scamanalyze.com/check/ltx71.com.html
http://www.scamaider.com/is-ltx71.com-safe-legal.html

Der größte Traffic zu ltx71 kommt ferner angeblich von russischen
Systemen. (Sagen Analyseseiten zu Domainen). Was immer das bedeutet … Zudem umgehen ltx71-Crawler blockierende Anweisungen in einer evtl. angelegten “robots.txt”-Datei einer Zieldomäne. Alles nicht gut!

Bzgl. der Analyse verfährt man dann genauso mit den anderen, von webalizer ausgewiesenen dubiosen Datengreifern. In unserem Fall stellte sich heraus, dass ein weiterer Besucher auch zu ltx71 gehört.

Für mich gilt in einer solchen, nicht völlig klaren Situation die Leitlinie: Es gibt keine Freunde im Internet.

Schon gar nicht, wenn deren Systeme meine teuer bezahlten Ressourcen für dubiose Zwecke verbrauchen würden.

Gegenmaßnahmen?

Wir konnten unserem norwegischen Bekannten jedenfalls Bericht erstatten und erste Hinweise geben. Kümmern muss sich nun sein Provider.

Nur der Vollständigkeit halber: Sperren könnte man die dubiosen Crawler-Bots zunächst mal über Einträge in einer “.htaccess”-Datei im Hauptverzeichnis auf dem Webserver nach dem Muster

order allow,deny
deny from 52.3.127.144
deny from 52.23.169.223
deny from 52.207.224.143
deny from 54.225.29.79
deny from 52.3.105.23
deny from 54.172.241.121
deny from 104.197.241.64
allow from all

Das wird auf Dauer bei einem Botnetz aber nicht viel helfen; es werden im nächsten Monat mit Sicherheit andere IP-Adressen auftauchen. Dann muss man zu anderen Mitteln greifen, die aber nicht Gegenstand dieses Posts sein sollen.

Jedenfalls kann man Betreibern von Websites, deren Ressourcen in ungewöhnlicher Weise mit Beschlag belegt werden, nur raten, sich die Logs der betroffenen Websites regelmäßig und genau anzusehen. Dabei kann der sehr einfache durchzuführende Einsatz von webalizer bereits erste wertvolle Erkenntnisse zeitigen.

Links

http://www.webalizer.org/
http://www.techrepublic.com/ article/ analyzing-web-sites-with-webalizer/
https://lf.net/support/ techinfo/webserver/ webalizer.php
http://www.linux-community.de/ Internal/Artikel/ Print-Artikel/LinuxUser/2011/04/Zugriffsdaten-auswerten-mit-Webalizer
https://privatstrand.dirkschmidtke.de/ 2011/05/10/ webalizer-auf-logfiles-loslassen/

Fasching, Webhosting bei 1&1 und mein Tränenbecken – I

1&1 war und ist einer der Platzhirsche in Deutschland, was Web-Hosting angeht. Durch den Zukauf von Strato durch den Mutterkonzern hat sich die Marktdominanz noch erhöht. Auch dieser Blog läuft im Rahmen eines Web-Hosting-Pakets bei 1&1. Das PC-Magazin hat diesen Provider als Hoster im Jahr 2016 ausgezeichnet. 1&1 wirbt selbst viel mit einem guten Kundenservice.

Da ist es doch schön, wenn man die Wirklichkeit, wie sie ein Endkunde erlebt, auch mal mit dem werbewirksamen Anspruch des Unternehmens vergleichen kann. Hierzu bot sich mir in den letzten Tagen eine praxisnahe Gelegenheit – im Auftrag einer Kundin “K” von 1&1, die wir in Web-Angelegenheiten immer wieder betreuen.

Die Geschichte ist einfach zu gut, um sie für sich zu behalten. Sie hinterließ bei mir trotz des munteren Faschingstreibens in den letzten Tagen sehr gemischte Gefühle. Immer wieder fühlte ich mich in eine Art Tragik-Komödie versetzt – auch wenn 1&1 nun endlich eine Lösung für besagte Kundin gefunden zu haben scheint. Die Fastenzeit hat offenbar auch ihr Gutes …

Ich konzentriere mich in diesem Erfahrungsbericht zunächst auf das erlebte Kernproblem meiner Kundin – nämlich die unzureichende Webseiten-Performance – und faktische Ergebnisse von 8 Eskalationsversuchen meiner Wenigkeit.

Das Problem

Kundin “K” hat im letzten Herbst ihre Webseite von uns auf WordPress samt Kadence/Pinnacle-Theme umstellen lassen. Wir haben diese PHP-basierte Technologie verschiedentlich für Kunden im Einsatz. U.a. bei einem weiteren Webhosting-Kunden von 1&1, aber nicht nur dort. Getestet haben wir die erreichbare Performance ursprünglich auf eigenen Webservern unter Stressbedingungen, unter einem 12 Jahre alten Hosting-Vertrag bei Strato und unserem eigenen, ähnlich alten Vertrag bei 1&1. Bislang alles problemfrei.

Nach der Installation lief die Web-Site der Kundin zunächst auch wie erwartet. Antwortzeiten zum Abnahmezeitpunkt zwischen 1.2 und 3 Sek pro Seite – je nach Tageszeit.

Seit dem Jahreswechsel stellte besagte Kundin – nach Beschwerden ihrer eigenen Kundenklientel – jedoch fest, dass die Performance ihrer Site seit Januar immer schlechter wurde und zeitweise “unter aller Sau” war (Zitat; ein später konsultierter 1&1 Berater fand diesen Ausdruck durchaus angemessen).

Punktuelle Zugriffe Mitte/Ende Januar und Mitte Februar aus dem Ausland bestätigten den subjektiven Befund der Kundin. Auf Anforderung der Kundin haben wir das letzte Woche dann genauer überprüft. Während typischer Hauptlastzeiten mussten wir tatsächlich zeitweise Antwortzeiten im deutschen Internet zwischen 10 Sek und 30 Sek pro Webseite feststellen.

Eigene Tests unter einer 1&1-Testdomäne – um Faktoren bessere Antwortzeiten

Wir haben dann selbstverständlich die Site der Kundin für Tests mit identischen PHP-Programmen und (bis auf Links) identische Datenbanktabellen in einen anderen alten 1&1-(!)-Vertrag und auf damit assoziierte Web- und Datenbankserver bei 1&1 gespiegelt. Die Tests ergaben völlig andere Ergebnissen und eine um Faktoren bessere Performance!

Die Kundin hat dieses Ergebnis leider mit großer Verbitterung zur Kenntnis genommen. Sie wollte ihren Vertrag mit 1&1 daraufhin umgehend kündigen und den Anbieter wechseln. Was wegen Mindestvertragslaufzeiten aber zu keiner kurzfristigen Lösung geführt hätte.

Wir selbst vermuteten zunächst eine zu hohe Last auf den 1&1-Datenbankservern. Weitere Tests, die wir im Laufe der Zeit systematisch anstellten, haben diese These jedoch klar widerlegt.

Blieb eigentlich nur eine Überlastung der Webserver oder eine massive Benachteiligung der Kundin im Kampf um die Hosting-Ressourcen bei 1&1 als Erklärungsansatz übrig …

Dazu muss man wissen, dass die Kundin seit 14 Jahren bei 1&1 knapp 12 Euro/Monat für 3 Domänen ohne SSL-Zertifikat abdrückt und sich durchaus als Stammkundin fühlt. In ihrer Jugend war das noch was
wert.

Kontakt zum 24/7-Service von 1&1

Ich wandte mich letzte Woche dann im Auftrag unserer Kundin an 1&1 und hatte seitdem 8 mal Kontakt (zur Hotline und Hosting-Beratern) – mit steigender Eskalationstendenz meinerseits und wachsender Hilflosigkeit der Ansprechpartner (bis auf den letzten). Alle Ansprechpartner konzidierten immerhin ein größeres Problem – der eine oder andere schien geradezu geschockt von den schlechten Antwortzeiten zu sein; erst recht, wenn er dann als Kontrast die Zeiten der gleichen Anwendung auf unserer ebenfalls bei 1&1 gehosteten Testdomäne sah.

Besonders berührt hat das einen 1&1-Mitarbeiter, den wir am Faschingsdienstag um ca 23:00 Uhr konsultierten. Zu diesem Zeitpunkt hatten wir zähneknirschend und ohne jeden Erfolg bereits alle vorhergehenden Ratschläge von 1&1-Mitarbeitern (inkl. einer Vertragsumstellung) befolgt – ohne Erfolg. Der Support-Mitarbeiter hätte angesichts der Fakten gerne die “Techniker” involviert. Leider war trotz 24/7-Service bei der Technik um 23:00 Uhr niemand mehr erreichbar. Alaaf …

Meine Frau vergnügte sich zu diesem Zeitpunkt zu Recht vor dem TV und auf Facebook. Ich musste mir deshalb mein Tränenbecken aus dem Glasschrank selber holen. In weiser Voraussicht ließ ich es auf meinem Schreibtisch stehen.

1&1 empfiehlt der Kundin stereotyp eine Vertragsumstellung – aber dadurch wird zunächst nichts besser

Als Ursache des Dramas wurde von den ersten 5 Ansprechpartnern vor dem 28.02. ein zu alter Vertrag (mit Speicher- und Performance-Einschränkungen) vermutet bzw. unterstellt. Das ist für das erste Gespräch am 23.02. mit einem 1&1-Vertretern eine außerordentlich freundliche Darstellung des Gesprächsverlaufs! Hier half auch mein Freund – das Tränenbecken – nicht mehr; vielmehr musste im Anschluss der “porcelain god” selbst angerufen werden, um mich wieder in Faschingslaune zu versetzen.

Alle nachfolgenden Berater waren dagegen sehr freundlich und ausgesprochen service-minded. Auch wenn das bis heute Mittag keine Wendung zum Besseren zeitigte, möchte ich bei dieser Gelegenheit doch die Ruhe und Besonnenheit der meisten Ansprechpartner (alles Männer) ausdrücklich loben! Die hatten es angesichts der Fakten ja nun wirklich nicht leicht und stießen regelmäßig an ihre Grenzen.

Geredet haben die Mitarbeiter aus dem Support und auch die Hosting-Berater dann viel über Hauptspeicheranforderungen moderner Web-Anwendungen, tolle SSDs in den aktuellen Datenbankservern und die schlimmen Begrenzungen alter 1&1-Verträge. Ich will das hier gar nicht weiter kommentieren. Ich kenne den relativ geringen Hauptspeicherbedarf der PHP-Applikation WordPress mit diversen Plaugins ganz gut; und der Nutzen von SSDs auf einem gut gepufferten und parametrierten MySQL-Datenbankserver entfaltet sich auch erst unter ganz bestimmten Anforderungen. Ich arbeite da zeitweise mit ganz anderen Kalibern an PHP-Anwendungen.

Die technischen Limits zur Ausführung von PHP-Anwendungen, die für den alten Vertrag der Kundin angeblich angewendet würden, konnte aber keiner der Berater zitieren oder belegen. Natürlich konnte auch nicht bestätigt werden, dass die aktuelle Anwendung die gesetzten Limits überschreiten würde. Ein Berater gab auf Rückfrage vielmehr zu, dass er nicht mal Zugriff auf die alten Vertragskonditionen hätte (interne Serverstörung!).

Vielleicht wäre ja aber ein konfigurierbarer Cloud-Server für unsere Kundin das Richtige?? Na, super! Geringfügige Mehrkosten … Ach so … Und wer kümmert sich dann um den Cloudserver und dessen Sicherheit? Und was kostet das dann? …”Oh – ja, Ihre Kosten hatte ich gerade nicht auf dem Radar …” Tja… und bevor ich es angesichts der Vielfalt aktueller 1&1-Angebote vergesse : Wieso genau lief und läuft dieselbe Applikation gehostet unter einem anderen aber ebenso alten Vertrag nochmal so viel besser? Weil ich drei Euronen pro Monat mehr zahle, die allein von den 4,99 Euro für ein SSL-Zertifikat aufgefressen werden?

Jeder der 1&1-Berater wurde von uns über die unterschiedlichen Laufzeitergebnisse zwischen der Domäne der Kundin und einer Testdomäne unter einem anderen ebenso alten Vertrag informiert. Die letzten 4 Berater wurden ferner über die Ergebnisse von Cross-Tests zwischen den verschiedenen Vertragsdomänen und und über Datenbanktests unterrichtet, die den Datenbankserver der Kundin als Ursache ausschlossen. Wir haben die 1&1-Berater ferner darauf hingewiesen, dass in Perioden geringer Last (Faschingssonntag, morgens) auch Antwortzeiten < 2 Sek angeboten wurden – und das die festgestellten schlechten Antwortzeiten offenbar an Zeiten hoher Grundlast für die Webserver gekoppelt waren. Und wir stellten immer wieder die Frage, ob es denn nicht sein könne, dass irgendwo bei 1&1 eine zu hohe Last vorläge und ob denn nicht ein Umzug auf einen anderen ihrer (Web-) Server etwas bringen könne … ?

Mein Tränenbecken füllte sich dann interessanterweise auf magische Weise regelmäßig von selbst, wann immer ich das Stichwort “Stammkundin seit 14 Jahren” in Gesprächen mit dem 1&1-Support anzubringen versuchte. Besonders schnell geschah das, als ein 1&1-Gesprächspartner alte 1&1-Webhosting-Verträge mit alten Telekom-Verträgen verglich. Da würde man für schlechtere Leistung ja auch mehr zahlen als bei einem neuen Vertrag! Gott sei Dank war ein Blumentopf in der Nähe, als mein Freund – das Becken – überquoll. Ach, Deutschland, mein geliebte Servicewüste! Es ist Fasching und ich weiß – ich bin wieder daheim.

Kommentar der 1&1-Technik

Auch die 1&1-“Technik” ( 2nd-level Support ???) wurde dann mal eingeschaltet; das lapidare Resultat entsprechender Anstrengungen kam dann am Faschings-Sonntag per Mail:

Umstellung des Vertrags der Kundin

Nach etlichem Hin und Her (dazu mehr in einem anderen Blog-Beitrag) wurde der Vertrag der Kundin dann tatsächlich (bei Mehrkosten) auf ein aktuelles Paket “Unlimited Plus” umgestellt; dies geschah am 28.02. nach einem Sponsoringversuch durch eine geringfügige Gutschrift für bislang durch “K” in 2 Monaten erduldeten Qualen.

Zu den Erlebnissen während der praktischen Vertragsumstellung im nächsten Beitrag mehr; ich habe mir erneut mehrfach die Auffangschale unter tropfende Augen halten lassen. Eigentlich wollte sich unsere Kundin auf eine Vertragsänderung gar nicht mehr einlassen. Wir haben sie mühsam dazu motivieren müssen. “Alternative Chancen für die Schaffung neuer alternativer Fakten” würden heutzutage ja selbst Präsidenten eingeräumt – und den deutschen Verbraucherschutz könne sie ja immer noch einschalten.

Das traurige Ergebnis der Tarifumstellung war leider:
Von einer Verbesserung konnte weder am 28.02. noch am 01.03. die Rede sein. Am 01.03. wurde auf Anraten eines 1&1-Beraters dan zusätzlich die Datenbank auf einen neuen Datenbankserver des aktualisierten Vertrages verlagert. Effekt: Die Antwortzeiten wurden noch schlechter! Zufall oder System? Oder Faschings-Kater der 1&1-Server?

Das Tränenbecken musste erneut mehrfach ausgekippt werden. Erst recht nach dem darauf folgenden Telefonat mit “K”.

Performance am heutigen Vormittag (02.03.)

Ich stelle nachfolgend den Stand der Performance am heutigen Vormittag in mehreren Tabellen dar. Diese Zeitreihen verdeutlichen das grundsätzliche Problem, das die Kundin seit
Januar hatte, sehr gut; auch wenn hier nur die Spitze des Eisberges schlaglichtartig sichtbar wird.

Die obere Zeile in den nachfolgenden Tabellen entspricht jeweils der Web-Domäne aus dem aktuellen Vertrag “Unlimited Plus” der Kundin [K], die unter einer identisch konfigurierten “Testdomaine” [T] unter einem alten “Business 5.0”-Vertrag.

In beiden Fällen lief zunächst PHP 5.6 und dann (nach einer gezielten Umstellung) PHP 7 auf den gehosteten Web-Servern. Um die Dinge besser vergleichbar zu machen, erfolgte aus der Testdomäne heraus ein Zugriff auf einen Datenbankserver, der dem aktuellen Vertrag der Kundin zugeordnet ist.

Aufgerufen wurde dabei immer dieselben 3 Seiten in 2 Zyklen – abwechselnd für K und T.
Alle Werte in Sekunden !

Zeit 02.03.2017, 11:00 Uhr

K 7,0 3,2 4,4 7,6 3,0 2,7
T 1,1 0,8 0,6 0,9 0,6 0,5

Zeit 02.03.2017, 11:10 Uhr

K 5,9 4,5 6,3 5,9 11,0 6,3
T 0,9 1,9 2,1 2,0 1,1 0,6

Zeit 02.03.2017, 11:14 Uhr

K 11,3 11,3 4,8 7,6 8,9 10,5
T 1,6 1,0 0,7 0,7 0,9 1,3

Zeit 02.03.2017, 11:15 Uhr

K 5,3 9,3 12,8 11,8 8,4 5,4
T 4,3 0,9 1,1 1,0 1,0 1,2

Zeit 02.03.2017, 11:20 Uhr

K 16,0 5,8 9,4 10,2 13,6 14,6
T 0,9 0,9 0,6 0,9 0,8 0,7

Zeit 02.03.2017, 11:25 Uhr

K 15,0 15,5 23,5 21,3 21,4 12,3
T 1,6 1,7 1,0 0,8 0,5 5,6

Zeit 02.03.2017, 11:30 Uhr

K 6,5 8,0 6,6 10,0 8,0 12,1
T 1,5 0,7 2,1 0,9 0,8 0,6

Zeit 02.03.2017, 11:50 Uhr

K 8,5 8,1 7,6 7,8 5,4 5,6
T 0,6 1,2 0,9 0,7 0,6 0,8

Zeit 02.03.2017, 12:00 Uhr

K 15,2 13,3 16,6 11,4 9,2 15,2
T 0,6 1,2 1,2 0,9 0,8 1,0

Ein Kommentar ist eigentlich überflüssig. Antwortzeiten zwischen 6 und 23 Sekunden pro Webseite sind aus Kundensicht unakzeptabel. Erst recht,
wenn man zu einer Vertragsumstellung mit Mehrkosten geradezu genötigt wurde.

Und auch “K” kam sich angesichts der Daten natürlich veralbert vor und fand das einen Tag nach Aschermittwoch ziemlich unangemessen. Ich habe ihr angeboten, ihr zeitweise meine Tränenschale auszuleihen.

Fastenzeit und Licht am Ende des Tunnels

Gestern – am Aschermittwoch – gegen Mittag habe ich dann nochmal bei 1&1 angerufen. Der Mitarbeiter der Hotline verstand das Problem sofort und verglich die 20 Sekunden Antwortzeit auch brav mit der entsprechenden Zeit unserer Testdomäne bei 1&1. Dann gab es ein paar (sehr intelligente) Fragen zur Querverbindung auf die Datenbank der Kundin. Nebenbei studierte er die Kommentare seiner Vorgänger – und bat mich irgendwann, ihm Kommentare dazu zu ersparen. Dann fiel das Wort “Überlast”. Er kam dann mit einem Lösungsvorschlag, für den wir ihm aber 24 Stunden einräumen müssten. Es gab auch eine wenig transparente Bezeichnung des kostenfreien Lösungsansatzes – irgendwas mit “…-Flat” – im Effekt sollte das zu einer “echten” Verschiebung auf andere Server führen. Ach ne …. Der vorhergehende Vertragswechsel hatte einen solchen grundlegenden Wechsel dann wohl nicht bewirkt??? … Hm, und komischerweise sei diese Option bei dem Test-Domänen-Vertrag gar nicht aktiviert …

Es ist Aschermittwoch – und auch ohne die Berichte aus Passau gesehen zu haben, beginne ich zu beten ….

Erlösung

Heute zw. 12.00 und 13:00 Uhr scheint 1&1 dann gerochen zu haben, dass ich an diesem Blog-Artikel schrieb. Jedenfalls flog ich plötzlich aus der FTP-Verbindung zum 1&1-Webspace unserer Kundin raus und kam auch erst wieder rein, nachdem ich eine dynamische IP-Adressbestimmung des 1&1-FTP-Servers in unserer Firewall zuließ. Ein Hinweis auf eine substanzielle Änderung? Erhörung meiner Gebete vom Vortag? Also: neuer Test nach dem obigen Muster. Und plötzlich erhalten wir bereits den ganzen Nachmittag geradezu traumhafte Antwortzeiten. Aktueller Stand:

Zeit 02.03.2017, 17:15 Uhr

K 0,4 0,6 0,6 0,6 0,8 0,4
T 1,0 0,7 1,1 0,6 0,6 0,7

Ich bin jetzt so gerührt, dass ich wieder mein Tränenbecken bemühen muss. Mehr zu einer Bewertung des Vorgang aus ITSM-Sicht daher morgen.

SFTP mit Key-Authentication auf (gehosteten) Linux-Servern für Web-Entwickler mit unterschiedlichen Privilegien – II

Im ersten Artikel der Serie zur SFTP-Einrichtung auf gehosteten Servern

SFTP mit Key-Authentication auf (gehosteten) Linux-Servern für Web-Entwickler mit unterschiedlichen Privilegien – I

hatten wir erste grundlegende Aspekte der SSH-Einrichtung diskutiert. Im jetzigen Artikel diskutiere ich zunächst einige Verbesserungen der SSH-Einstellungen und wende mich dann der Einrichtung von 2 Usergruppen in der “/etc/sshd_config” zu.

Sicherheits-Hinweis für den Umgang mit der sshd-config auf Remote Servern

Fehler sind menschlich. Durch Zerstören der SSHD-Konfiguration kann man sich von gehosteten Servern selbst aussperren. Bevor man also an der sshd_config rumspielt, sollte man sich immer einen weiteren Zugangsweg zum Server für Notfälle sichern.

Server-Hoster bieten für den Ernstfall ein Booten in einen Maintenance-Modus an. Dass das funktioniert, sollte man mal getestet haben. Ein Gleiches gilt für evtl. Backup-Verfahren. Ferner sollte man bei sich Kopien aller wichtigen Konfigurationseinstellungen haben. Ich selbst lege vor Änderungen immer eine Kopie der funktionierenden ssd_config an. Die kann man im Ernstfall im Maintenance-Modus wieder zurückspielen.

Ferner sollte man 2 bis 3 andere ssh-Verbindungen offen halten, bevor man den sshd-Dämon neu startet. Der Server setzt normalerweise eine Grace-Time für bereits geöffnete Verbindungen. Dieses Zeitintervall kann man dann im Ernstfall noch für Änderungen der sshd_config oder ein Zurückspielen einer funktionierenden Konfigurationsdatei nutzen!

Von Vorteil ist es auch, eine von der Gruppe, für die die Einstellungen manipuliert werden, unabhängige, SSH-fähige UserID zur Verfügung zu haben.

Verbesserungen der SSH-Enrichtung

Aufgrund der schon seit einiger Zeit erhöhten Sicherheitsanforderungen Anforderungen müssen wir die SSH-Einrichtung verbessern. Ich kann an dieser Stelle leider nicht auf Details eingehen – es sind aber vor allem bekannte Probleme im Bereich des initialen “Key Exchange” [KEX] zu beheben:

Einerseits sind Standardparameter und Schlüssellängen für bestimmte zugehörige asymmetrische Algorithmen, die auf Primfaktorzerlegung und Modulo-Verfahren beruhen, unzulänglich. Leider sieht der Standard selbst Verfahren als Fallback-Optionen verbindlich vor, die aktuellen Anforderungen nicht mehr genügen. Andererseits muss man leider auch hinter Standard-Parameter für elliptische Kryptographie große Fragezeichen hinsichtlich ihrer Zufälligkeit setzen.

Ein Teil der Probleme wurde bereits 2015 adressiert; siehe z.B.:
https://weakdh.org/imperfect-forward-secrecy-ccs15.pdf.
Informationen bzgl. möglicher Maßnahmen findet man etwa hier:
https://stribika.github.io/ 2015/01/04/ secure-secure-shell.html.

Der erste Schritt zur Aufrüstung ist, dass wir uns die aktuelle Version von OpenSSH (z.Z. 7.2p2) beschaffen. Für Opensuse (ab der Version 13.1) nutzt man hierzu das network”-Repository.

Danach lassen wir nur die Protokollvariante 2 und lediglich zwei z.Z. noch als sicher eingeschätzte initiale Schlüsselaustausch-Verfahren des SSH-Protokolls zu. Ferner schränken wir die Klassen der für die Serveridentifikation möglichen Schlüssel ein. Hierzu dienen die folgenden Statements in der Datei “/etc/ssh/sshd_config” unseres Servers “serv”:

# We only allow for SSH 
protocol version 2 
Protocol 2

# We restrict the Key Exchange Algorithms !!!
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

# Minimum length in DH 
KexDHMin 2048

# We restrict HostKeys types for Host authentification for protocol version 2
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key

# We restrict Ciphers 
#RekeyLimit default none
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr

# UsePam can be set to "yes" to get more control options via PAM 
# siehe hierzu die Diskussion in einem kommenden Artikel
UsePAM  yes 

 
Man sollte für Zwecke im privaten oder Geschäftsumfeld zudem zugehörige flankierende Einstellungen in der lokalen Client-Konfigurations-Datei “/etc/ssh_config” vornehmen. Siehe den oben angegebenen Link.

Zwei Usergruppen und zweier Beispieluser

Im Folgenden verschaffen wir zwei exemplarischen SFTP-Usern

  • alpha : Mitglied der Entwicklergruppe “devgrp1und der Gruppe “devgrp2
  • beta : Mitglied der Entwicklergruppe “devgrp2“.

einen ersten elementaren SFTP-Zugang zu den Verzeichnissen “/srv/www/htdocs/webs/project/alpha”, “/srv/www/htdocs/webs/project/adm”, “/srv/www/htdocs/webs/project/test/beta”.

Zugang zu unterschiedlichen chroot-Verzeichnissen

Wir legen in einem ersten Anlauf zunächst das Verzeichnis “/srv/www/htdocs/webs/project/” als Dachverzeichnis an.

Dieses Verzeichnis wird uns gleichzeitig als chroot-Verzeichnis für alle beteiligten SFTP-User der Gruppe “devgrp1” dienen.

Ein weiteres untergeordnetes Verzeichnis “/srv/www/htdocs/webs/project/test” wird dagegen als chroot-Verzeichnis für die Mitglieder der Gruppe “devgrp2” verwendet.

An dieser Stelle muss auf einen wichtigen Punkt hingewiesen werden.

Jedes Verzeichnis, das unter SFTP als chroot-Jail für eine Usergruppe dienen soll, muss root gehören und nur root darf darauf Schreibrechte besitzen.

Ansonsten läuft man bei der Einrichtung des SFTP-Zugangs in Probleme, wie sie etwa hier geschildert sind:
http://superuser.com/questions/394298/sftp-chroot-result-in-broken-pipe

Also geben wir als User root auf dem Web/SFTP-Server “serv” Folgendes ein :

mytux:~ # mkdir /srv/www/htdocs/webs/project
mytux:~ # chgrp devgrp1 /srv/www/htdocs/webs/project
mytux:~ # chmod 750 mkdir /srv/www/htdocs/webs/project
mytux:~ # mkdir /srv/www/htdocs/webs/project/test
mytux:~ # chgrp devgrp2 /srv/www/htdocs/webs/project/test
mytux:~ # chmod 750 mkdir /srv/www/htdocs/webs/project/test
mytux:~ # mkdir /srv/www/htdocs/webs/project/alpha
mytux:~ # chgrp devgrp1 /srv/www/htdocs/webs/project/alpha
mytux:~ # chmod 770 mkdir /srv/www/htdocs/webs/project/alpha
mytux:~ # mkdir /srv/www/htdocs/webs/project/adm
mytux:~ # chgrp devgrp1 /srv/www/htdocs/webs/project/adm
mytux:~ # chmod 770 mkdir /srv/www/htdocs/webs/project/adm
mytux:~ # mkdir /srv/www/htdocs/webs/project/test/beta
mytux:~ # chgrp devgrp2 /srv/www/htdocs/webs/project/test/beta
mytux:~ # chmod 770 mkdir /srv/www/htdocs/webs/project/test/beta

 
Mitglieder der Gruppe “devgrp1” legen wir später auch als Mitglieder der Gruppe “devgrp2” an. Sie dürfen daher mit SFTP alle unter “/srv/www/htdocs/webs/project” liegenden Verzeichnisse einsehen; u.a. auch solche, die ”
devgrp2″ zugänglich sind, aber zusätzlich auch weitere Verzeichnisse. “devgrp1” hat gegenüber der Gruppe “devgrp2” also mehr Privilegien. Mitglieder der Gruppe “devgrp2” sehen theoretisch zunächst nur den Inhalt von Verzeichnissen unterhalb “/srv/www/htdocs/webs/project/test”.

Dabei gilt:

Schreiben und Unterverzeichnisse anlegen dürfen Mitglieder von “devgrp1” bzw. “devgrp2” aber nur in den Unter-Verzeichnissen “alpha” bzw. “beta” !

Berücksichtigung der künftigen SFTP-User-Gruppen in der SSHD-Konfigurationsdatei

Wir müssen den Usern “alpha” und “beta” zur Nutzung von SFTP zunächst grundsätzlich die Nutzung von SSH zugestehen. Dies führt zur Modifikation des “AllowUsers”-Eintrags in der Konfigurationsdatei, der im letzten Artikel diskutiert wurde :

AllowUsers usu alpha beta

Bei wenigen einzelnen Usern und Gruppen kann man vielleicht so arbeiten. Bei steigender Useranzahl werden die User aber typischerweise in Gruppen angeordnet. Dann ist es wichtig zu wissen, dass es auch die Direktive “AllowGroups” gibt. Insgesamt werden vom SSH-Daemon 4 Direktiven in folgender Reihenfolge abgearbeitet:

DenyUsers
AllowUsers
DenyGroups
AllowGroups

Das zuerst getroffene Muster zählt dabei unabhängig von nachfolgenden Muster-Treffern! Siehe:
https://en.wikibooks.org/ wiki/ OpenSSH/ Server
Nicht zutreffende Treffer führen automatisch zu einem Default-Ausschluss von der Nutzung.

Beachtet bitte auch, dass host-spezifische Zusätze der Form USER@HOST nur zu User-IDs – nicht aber (!) zu Gruppen-IDs – möglich sind. Siehe:
http://manpages.ubuntu.com/ manpages/ hardy/ man5/ sshd_config.5.html
Wildcards in Host-Ergänzungen sind unter obigem Link auch beschrieben:
http://manpages.ubuntu.com/ manpages/ hardy/ man5/ ssh_config.5.html

Ist der User “usu” ein Mitglied der Gruppe “adm”, so hätten wir in unserem Fall also auch schreiben können:

AllowGroups adm devgrp?

Man beachte, dass kein Komma sondern ein Blank zur Abtrennung mehrerer User oder Usergruppen voneinander benutzt wird.

Begrenzung des Zugriffs auf CHROOT-Verzeichnisse

Nun müssen wir bestimmte Verzeichnisse vorgeben, auf die sich der Zugang beschränken soll. Hierfür sind zwei Direktiven erforderlich:

  • Zum einen eine Einstellung zur Nutzung des internen SFTP-Mechanismus durch den jeweiligen User
  • und zum anderen eine Einstellung zur Definition eines alle Aktionen begrenzenden und kapselnden CHROOT-Verzeichnisses für jeden User.

Ich nehme diese Einstellung in user- und/oder gruppenspezifischen Segmenten der Konfigurationsdatei “/etc/sshd_config” vor. Solche Bereiche leitet man am Ende der Konfiguationsdatei durch die Schlüsselworte “Match Group” (oder “Match User”) ein.

Bei den nachfolgenden Direktiven für die Gruppe oder den User wiederhole ich dabei einen Teil der generellen sicherheitsrelevanten SSH-Einstellungen. Der Grund hierfür ist:

Muss ich mal auf die Schnelle und testweise grundlegende SSH-Einstellungen ändern, so setze ich die Direktiven für meine kritischen SFTP-User nicht automatisch außer Kraft.

Also ergänzen wir genau am Ende der Datei “/etc/ssh/sshd_config”:

Match Group devgrp1
    
    ForceCommand internal-sftp
        # ForceCommand internal-sftp -u 0007</strong>
        ChrootDirectory /srv/www/htdocs/webs/project
        RSAAuthentication yes
        PubkeyAuthentication yes
        PasswordAuthentication no 
        X11Forwarding no
        AllowTcpForwarding no
        AllowAgentForwarding no
        GatewayPorts no
Match  Group devgrp2,!devgrp1 
        ForceCommand internal-sftp
        # ForceCommand internal-sftp -u 0007
        ChrootDirectory /srv/www/htdocs/webs/project/test
        RSAAuthentication yes
        PubkeyAuthentication yes
        PasswordAuthentication no 
        X11Forwarding no
        AllowTcpForwarding no
        AllowAgentForwarding no
        GatewayPorts no

 
Interessant ist hier zunächst die zweite Match-Vorgabe

Match Group devgrp2,!devgrp1

Hier drücken wir aus, dass die nachfolgenden Parameter grundsätzlich für die Mitglieder/User der Gruppe “devgrp2” gelten soll, aber nicht für Mitglieder der Gruppe “devgrp1”. Die logische Negation erfolgt durch den Operator “!”.

In unserem Beispiel gelten die Anweisungen nach der zweiten “Match”-Zeile also lediglich für den User “beta” und evtl. andere User der Gruppe “devgrp2”.

Hinweis:

Zwischen den beiden Kriterien für die Gruppenmitgliedschaft ist ein Komma einzufügen, aber kein Blank vor oder nach dem trennenden Komma!

Interessant ist ferner die potentielle Option “-u” hinter der auskommentierten ForceCommand Anweisung:

ForceCommand internal-sftp -u 0007

Diese Direktive setzt für Open-SSH-Versionen ≥ 5.5 gezielt eine “umask”, die angeblich systemweite umask-Definitionen überschreibt. Nun ja – stimmt das wirklich? Wir kommen darauf im nächsten Artikel dieser Serie zurück.

Home-Verzeichnisse der User “alpha” und “beta”- und Ausschluss des Shell-Zugangs

Auf die Schritte zur User-Anlage und User-Zuordnung zu Gruppen gehe ich hier nicht genauer ein. Interessanter ist die Frage, wo sich eigentlich die Home-Verzeichnisse der User alpha und beta befinden sollen.

Diverse Artikel im Internet, die sich mit dem Aufsetzen von User-bezogenen Verzeichnissen unterhalb eines Chroot-Verzeichnisses befassen (s. die Links am Ende des Artikels), enthalten für unser Szenario eher verwirrende Information.

Zudem gilt:
Der SSHD-Dämon erwartet später die Public Key Files unserer User bei Default-Einstellungen an bestimmten Stellen in der Verzeichnisstruktur. Experimente mit einer Verlagerung der Home-Verzeichnisse in andere Bereiche des Dateibaums führen nach meiner Erfahrung schnell ins Chaos und zu mühsamem Suchen nach Fehlern. Das gilt selbst dann, wenn man später Pfade zu den Autorisierungsfiles explizit setzt. Also:

Einfach die Home-Verzeichnisse da lassen, wo sie normalerweise erzeugt werden. Wir entziehen unseren Entwicklern sowieso den Shell-Zugriff und engen ihren Wirkungskreis weiter per Chroot ein.

serv:~ # useradd -g devgrp1 -s /sbin/nologin -m -d /home/alpha -k /etc/skel alpha
serv:~ # passwd alpha 
serv:~ # useradd -g devgrp2 -s /sbin/nologin -m -d /home/beta -k /etc/skel beta
serv:~ # passwd beta 
serv:~ # usermod -G devgrp2 alpha

 

Generieren eines SSH-Schlüsselpaars pro SFTP-User

Da wir sicherheitsbewusste Administratoren sind, erlauben wir den eben angelegten Usern SSH/SFTP-Zugang nur auf Basis von SSH-Key-Authentication.

Wir wählen für unsere künftigen SFTP-User natürlich die Erzeugung eines SSH-Schlüssel-Paars, bei der der private Schlüssel mit einem Passwort geschützt wird. Schon aus Gründen
einer durchgehenden Sicherheitsphilosophie.

In Übereinstimmung mit den Sicherheitsrichtlinien von https://stribika.github.io/ 2015/01/04/ secure-secure-shell.html führen wir zur Schlüsselgenerierung folgende Kommandos aus – und kopieren danach den jeweiligen Public Keys zum SSH/SFTP-Server.

Wir zeigen das am Beispiel des Users “alpha” auf dem Client “mytux”. Wir erzeugen sowohl ein Key-Paar, das auf elliptischer Kryptographie basiert und eines, das bei hinreichender Schlüssel-Länge RSA unterstützt. Schlüssellängen unter 2048 Bit sind für RSA-angelehnte Verfahren (also nicht elliptische Verfahren) nicht mehr als sicher anzusehen.

Dabei setzen wir voraus, dass “alpha” ein Verzeichnis “~/.ssh” angelegt hat.

alpha@mytux:~/.ssh> ssh-keygen -t ed25519 -f ssh_host_ed25519_key
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in ssh_host_ed25519_key.
Your public key has been saved in ssh_host_ed25519_key.pub.
The key fingerprint is:
SHA256:wri++5yVtLbMQeinXxdqiduWm2gGAbTNaB8YPFJkNV8 ufo@mytux.mydomain
The key's randomart image is:
+--[ED25519 256]--+
|   =*.o   E      |
|  ..+B o .       |
|   .=o+ .        |
|   . +.o         |
|    . =.S   .    |
|     o.+ + o .   |
|    . ..O =..    |
|   . . OoOoo     |
|    ++=+B.+.     |
+----[SHA256]-----+

alpha@mytux:~/.ssh> ls
known_hosts  ssh_host_ed25519_key  ssh_host_ed25519_key.pub

alpha@mytux:~/.ssh> ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in ssh_host_rsa_key.
Your public key has been saved in ssh_host_rsa_key.pub.
The key fingerprint is:
SHA256:cQfc/m7HrB1fLFsL8TA27FtiYYDJa2BIGoS3JRS607w ufo@mytux.mydomain
The key's randomart image is:
+---[RSA 4096]----+
|  +=..   ...     |
| ..o+.. . +..    |
| ...+. o.+.o.    |
|  +.  . .o..+    |
| o o    So   @   |
|  . .   .   + O. |
|   E         *.*+|
|            . B=O|
|             oo+o|
+----[

 
Analog erzeugen wir ein zweites separates Schlüsselpaar für die Entwickler der Gruppe “devgrp2”. Wir legen dann als Schutz gegen Verlust Kopien dieser Schlüsselpaare in einem verschlüsselten Verzeichnis auf einem selbst kontrollierten Backup-Server an.

Dann bringen wir die Public (!) Key Datei für jeden User auf den Server. Dazu nutzen wir einen entsprechend privilegierten Benutzer (hier “usu”), der SSH-Zugang erhalten hat. Wir erinnern uns, dass wir bei der SSH-Einrichtung einen direkten SSH-Zugang des Users “root” verboten hatten. root auf dem System “mytux” kopiert den Public Key zwischenzeitlich in ein Verzeichnis “/home/usu/key_transfer” des Dummy Users “usu”. Dann transferieren wir mittels “scp”:

usu@mytux:~>scp -P 6xxxx -i ~/.ssh/id_rsa_usu /home/usu/key_transfer/ssh_host_ed25519_key.pub usu@serv.myhoster.net:/home/usu/key_transfer/
Enter passphrase for key '/home/ich/.ssh/id_rsa_usu': 
ssh_host_ed25519_key.pub    100%  390     0.4KB/s   00:00

 
“6xxxx” steht dabei für den verschobenen Port, unter dem der Server SSH anbietet. (Siehe hierzu den letzten Artikel dieser Serie).

Dann als root auf “serv”:

serv:~ # mkdir /home/alpha/.ssh
serv:~ # chown alpha.devgrp1 /home/alpha/.ssh
serv:~ # cp /home/usu/key_transfer/ssh_host_ed25519_key.pub /home/alpha/.ssh/ssh_host_ed25519_key.pub
serv:~ # chown 
alpha.devgrp1 /home/alpha/.ssh/ssh_host_ed25519_key.pub 
serv:~ # rm /home/usu/key_transfer/ssh_host_ed25519_key.pub 
serv:~ # touch /home/alpha/.ssh/authorized_keys
serv:~ # chown alpha.devgrp1 /home/alpha/.ssh/authorized_keys
serv:~ # cat /home/alpha/.ssh/ssh_host_ed25519_key.pub >> /home/alpha/.ssh/authorized_keys
serv:~ # chmod 600 /home/alpha/.ssh/authorized_keys
serv:~ # chmod 600 /home/alpha/.ssh/ssh_host_ed25519_key.pub 
serv:~ # chmod 700 /home/alpha/.ssh

 
Analog für alle anderen Public Keys und User. Andere Verfahren – auch manuelle – um den Public key auf den Server zu bringen, werden hier diskutiert:
https://www.digitalocean.com/ community/ tutorials/ how-to-configure-ssh-key-based-authentication-on-a-freebsd-server

Bitte beachtet:

Die Rechtesetzungen sind wichtig! Bei unzureichendem Schutz wird SSH die Keys ggf. nicht akzeptieren.

Test

Wir sind nun so weit, dass wir einen ersten Test durchführen können. Bevor wir den SSH-Server auf unserem Testsystem neu starten, checken wir nochmal, dass die notwendigen Einstellungen für Key-Authentifzierung in der Datei schon vorgenommen wurden:

AllowUsers usu alpha beta
AllowGroups adm devgrp1 devgrp2 
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile      .ssh/authorized_keys
PasswordAuthentication no
ChallengeResponseAuthentication no

 
Dann erfolgt ein Restart von sshd :

serv:~ # systemctl restart sshd.service

Wir probieren nun den Zugang mittels des Kommandos “sftp”; man beachte, dass die Option für den Port hier ein großes “P” erfordert !

ich@mytux:~> sftp -P 6xxxx -i ~/.ssh/ssh_host_ed25519_key beta@serv.myhoster.net
Enter passphrase for key '/home/ich/.ssh/ssh_host_ed25519_key': 
Connected to serv.myhoster.net
sftp> ls
beta 
sftp> pwd
Remote working directory: /
sftp> cd ../alpha
Couldn't stat remote file: No such file or directory
sftp> cd beta
sftp> pwd
Remote working directory: /beta
sftp> mkdir classes
sftp> ls -la
drwxr-xr-x    3 beta     devgrp2      4096 Feb 10 17:30 .
drwxr-xr-x    3 root     root         4096 Feb 10 16:30 ..
drwxr-xr-x    2 beta     devgrp2      4096 Feb 10 17:30 classes
sftp> cd classes
sftp> put /home/ich/classes/*
Uploading /home/ich/classes/class_ufo.php to /beta/classes/class_ufo.php
/home/ich/classes/class_ufo.php                                        100%    0     0KB/s   00:00    
Uploading /home/ich/classes/class_ufo2.php to /beta/classes/class_ufo2.php
/home/ich/classes/class_ufo2.php                                       100%    0     0KB/s   00:00    
sftp> ls
class_ufo.php    class_ufo2.php   
sftp>exit 
ich@mytux:~> 

 
Die letzten zwei Testfiles hatte ich als leere Files angelegt; daher die 0-Übertragungsrate!

Nun noch ein Kurztest für den User “alpha”:

ich@mytux:~> sftp -P 6xxxx -i ~/.ssh/ssh_host_ed25519_key alpha@serv.myhoster.net
Enter passphrase for key '/home/ich/.ssh/ssh_host_ed25519_key': 
Connected to serv.myhoster.net
sftp> ls
adm    alpha  test 
sftp> ls /test/beta/classes
/test/beta/classes/class_ufo.php   /test/beta/classes/class_ufo2.php
sftp> mkdir /test/beta/uploads
sftp> ls /test/beta
/test/beta/classes   /test/beta/uploads   
sftp> exit
ich@mytux:~>
r

 
Damit genug für heute. Im nächsten Artikel dieser Serie gehe ich dann etwas genauer auf Rechtethemen beim Anlegen von Files per SFTP ein.

Links

Generelles zu SSH/SFTP
http://en.wikibooks.org/ wiki/ OpenSSH/Cookbook/SFTP
http://wiki.ubuntuusers.de/SSH
http://www.computerhope.com/ unix/ sftp.htm

Userbezogene Chroot-Verzeichnisse
https://www.mynakedgirlfriend.de/ sichere-chroot-umgebung-fur-ssh-dateiubertragungen-sftp/
http://www.thegeekstuff.com/ 2012/03/ chroot-sftp-setup/
https://wiki.archlinux.org/ index.php/ Talk:SFTP_chroot

SSD Raid Arrays unter Linux – VIII – Setup von Raid-10-Arrays mit mdadm

Diese Serie an Posts befasst sich mit SSD-basierten SW-Raid-Systemen auf Linux-Workstations oder kleineren Server-Systemen. In den bisherigen Artikeln der Serie hatten wir uns u.a. mit dem Einsatz von Onboard-SATA3-Controllern auf Mainboards mit Intel-Chipsatz befasst und einen kritischen Blick auf die sog. iRST-Technologie mit “imsm”-Raid-Containern geworfen. Zudem hatten wir ein wenig über die Bootunterstützung im Zusammenspiel mit Grub2 und mögliche, problematische Aspekte von Raid-5-Arrays nachgedacht.

SSD Raid Arrays unter Linux – I – ein facettenreiches Thema
SSD Raid Arrays unter Linux – II – Hardwarecontroller ?
SSD Raid Arrays unter Linux – III – SW- Raid vs. Intel-iRST-Raid – Performance?
SSD Raid Arrays unter Linux – IV – OS und Daten auf einem Raid-Array?
SSD Raid Arrays unter Linux – V – SW-Raid vs. iRST-Raid – Boot-Unterstützung?
SSD Raid Arrays unter Linux – VI – SW-Raid vs. iRST-Raid – Flexibilität?
SSD Raid Arrays unter Linux – VII – problematische Aspekte von Raid-5-Arrays

In diesem Beitrag gehe ich darauf ein, wie ich meine md-basierten Raid-10-Arrays konkret mit Hilfe des Befehls “mdadm” aufsetze (Linux SW-Raid). Dabei diskutiere ich Voraussetzungen und einige wichtige Parameter. Eine Verallgemeinerung der Rezepte auf andere Raid-Varianten wie Raid-5 ist danach relativ einfach.

Voraussetzungen und SSD-Optimierung unter Linux

Da unsere Raid-Arrays aus SSDs zusammengesetzt werden, sind unter Linux einige Regeln zu beachten. Einen guten Überblick geben etwa folgende Artikel:

https://sites.google.com/site/easylinuxtipsproject/ssd
http://www.linux-magazine.com/Issues/2015/172/Tuning-Your-SSD
https://wiki.archlinux.org/index.php/Solid_State_Drives
https://wiki.debian.org/SSDOptimization

Hier einige Punkte, die ich als relevant einstufe:

  1. Auf allen SSDs, die in das Raid-System eingebunden werden, sollte man grundsätzlich ca. 7-12% frei, d.h. ohne Partition, belassen (Overprovisioning).
  2. Ein periodisches Absetzen des TRIM-Befehls “fstrim” per cron-Job ist dem Mounten eines (ext4-) Filesystems mit der “discard”-Option vorzuziehen.
  3. Ext4 sollte als Filesystem verwendet werden (in meinem Fall auf LVM Logical Volumes des Raid-Arrays; s.u.)
  4. Man sollte prüfen, dass die eingesetzten Tools zum Einrichten von Partitionen, LVM und Filesystemen das notwendige Alignment korrekt durchführen (YaST etwa tut dies automatisch, wenn unter den Einstellungen “Optimal” als Option gewählt wurde !)
  5. Partitionen sollte man großzügig anlegen – 25% sollten immer als freier Platz zur Verfügung stehen.
  6. Für LVM sind die Optionen
    “md_chunk_alignment = 1” und “issue_discards = 1”
    in der Datei “/etc/lvm/lvm.conf” zu setzen.
  7. Als Scheduler sollten die Low-Latency-Scheduler “deadline” oder “noop” verwendet werden.
  8. Wahl des AHCI-Modus für den SATA-Contoller (soweit nicht iRST/imsm-Array-Container) konfiguriert werden).

Punkt 1 dient sowohl der Lebensdauer als auch der Performance von SSDs. Bitte beachtet, dass u.a. dieser Punkt gegen den Einsatz der iRST-Technologie für Onboard-Controller spricht. Grund: iRST lässt einem keine Wahl bzgl. der Größe des zweiten Raid-Volumes in einem isms-Raid-Container! Für das zweite Volume wird der gesamte noch verfügbare physikalische Platz der eingebundenen Speichermedien genutzt. Siehe hierzu frühere Beiträge der Serie.

Punkt 2 dient der Performance; der TRIM-Befehl [fstrim unter Linux] ist allerdings auch mit Schreib-/Lösch-Operationen verbunden und belastet daher die SSD. Bei hinreichend großen Partitionen genügt im durchschnittlichen Tagesbetrieb nach meiner Erfahrung ein einmaliges Absetzen von “fstrim” pro Woche, um die Performance aufrecht zu erhalten.

Punkt 3 wird in vielen Internet-Artikeln zu diesem Thema als richtig angesehen, da die Node-Behandlung unter ext4 modernen SSD-Controllern entgegenkommt. Die Bevorzugung von ext4 kann sich jedoch ändern, wenn Btrfs erst einmal einen hinreichenden Reifegrad erhalten hat. Ich ignoriere Btrfs in diesem Artikel, da ich wenig Erfahrung mit diesem Filesystem habe – und die, die ich hatte, waren (noch) nicht gut. Allerdings sind ja auch XFS und zunehmend F2FS sehr populär. Ich behandle auch diese Filesysteme mangels produktiver Erfahrung nachfolgend nicht. Ein Blick in Tests ist aber sicher interessant (s. etwa:
http://www.phoronix.com/scan.php?page=article&item=linux-40-ssd&num=2,
https://www.phoronix.com/scan.php?page=news_item&px=Linux-4.4-FS-4-Way,
https://www.percona.com/blog/2012/03/15/ext4-vs-xfs-on-ssd/,
http://openbenchmarking.org/result/1608041-LO-LINUX44BT99
https://blog.pgaddict.com/posts/postgresql-performance-on-ext4-and-xfs, https://www.phoronix.com/scan.php?page=news_item&px=Linux-4.7-FS-5-Way,
http://infoteh.etf.unssa.rs.ba/zbornik/2016/radovi/RSS-2/RSS-2-8.pdf).
S. aber auch:
https://bbs.archlinux.org/viewtopic.php?id=207938
Die Unterschiede zwischen ext4 und XFS scheinen insgesamt nicht weltbewegend zu sein. Ich ziehe ext4 z.Z. wegen seiner guten Stabilität und wegen seiner guten Wiederherstellungsfähigkeit bei Filesystem-Fehlern im besonderen Btrfs vor. Hinzu kommt, dass ext4 die geringste Schreibbelastung durch Journaling auf die SSDs auszuüben scheint (s. z.B. http://www.ocsmag.com/2016/04/30/using-solid-state-drives-on-linux/).
Ferner ist bei ext4 die Unterstützung des fstrim-Befehls auch dann garantiert, wenn das Filesystem auf einem LVM-Volume und letzteres auf einem Raid-10-Array angelegt wird.

Punkt 4 behandle ich im nachfolgenden Abschnitt genauer.

Punkt 5 dient ebenfalls der Performance: Freie Blöcke des Filesystems stehen hinreichend und zusammenhängend zur
Verfügung; eine Fragmentierung von Linux-Filesystemen wird bei genügend freiem Platz weitgehend automatisch vermieden.

Punkt 6 dreht sich einerseits darum, dass ein Physical Volume, das direkt auf einem md-Raid-Array aufsetzt, automatisch an die zugrunde liegende Raid-Array-Struktur (im besonderen die sog. Chunk Size; s.u.) angepasst wird. Durch den 2-ten Parameter informiert LVM den SSD-Controller ferner über die Freigabe von Platz bei Löschungen oder Verkleinerungen von logischen Volumes. Siehe hierzu:
https://linux.die.net/man/5/lvm.conf,
https://nixaid.com/trim-in-linux-with-ssd-disk-lvm-and-encryption/

Punkt 7 hat damit zu tun, dass bestimmte Linux I/O Scheduler, wie der cfq-Scheduler, versuchen, seek-Zeiten für HDDs zu minimieren. Das ist bei SSDs aber überflüssig und verschwendet sogar CPU-Zeit; Scheduler wie “noop” oder “deadline” verringern dann die Latenz. Siehe hierzu und zur Einrichtung des Schedulers für SSDs die folgenden Links:
http://stackoverflow.com/questions/1009577/selecting-a-linux-i-o-scheduler
https://wiki.debian.org/SSDOptimization

Punkt 8 ist eine Standard-Empfehlung, die vor allem im Gegensatz zu potentiell möglichen “IDE”-Einstellungen zu sehen ist. Siehe etwa:
http://www.phoronix.com/scan.php?page=article&item=intel_linux_ahci&num=1
http://archive.benchmarkreviews.com/?option=com_content&task=view&id=505
Auf Systemen mit einem Intel-SATA3-Controller gibt es im BIOS oft auch die Option “RAID”. Ich habe bei Einrichtung eines reinen md-basierten Linux-SW-Raids auf solchen Systemen keine Performance-Differenzen zwischen den Einstellungen AHCI und RAID feststellen können. Der RAID-Modus fällt wohl auf den AHCI-Modus zurück, wenn der iRST nicht genutzt wird.

Alignment und die Hierarchie der Speicherorganisation

Punkt 4 ist technisch interessant: Hier geht es um die Ausrichtung von Partitions-Grenzen gemäß der definierten Sektorgrößen der HDDs/SSDs (typischerweise 512 Byte) und ein Ausrichten der Blocksize des Filesystems (für ext4 typischerweise 4KB (genauer 4 KiB (4096 Bytes); 1 MiB = 2048 * 512 Bytes) an der zugrunde liegenden Speicherstruktur.

Eine Erläuterung des Themas findet sich hier:
https://www.thomas-krenn.com/de/wiki/Partition_Alignment
Siehe auch:
https://wiki.ubuntuusers.de/SSD/Alignment/
https://wiki.debian.org/SSDOptimization

Alignment betrifft aber nicht nur Partitionsgrenzen. Alignment ist auf allen Ebenen der HD-/SSD-Speicherorganisation interessant (physikalische Partition, Raid-Array, LVM-Group, LVM-Volume, ext4-Filesystem). Dabei müssen auch Parameter des ext4-Filesystems an die Raid-Speicher-Organisation angepasst werden. In unserem Fall sieht die geplante Hierarchie der Speicherorganisation wie folgt aus:

=> 4 SSDs
=> pro SSD eine unformatierte Raid-Partition (Typ 0xFD)
=> md-Raid-Array mit Striping (je nach Raid-Typ)
=> Eine LVM Volume Group [VG] über das gesamte Raid-Array hinweg; das Raid-Array entspricht dabei einem LVM Physical Volume [PV]
=> Logische LVM Volumes [LVs] mit ext4 Filesystem

Die Anzahl zu lesender und zu schreibender Blöcke für den Erhalt bzw. die Speicherung von Information soll über die gesamte Hierarchie hinweg durch passendes Alignment minimiert werden.

In der Linux-Praxis muss man sich allerdings um ein korrektes Partition-Alignment kaum kümmern. Generell führen “gdisk” und “parted” mit der “-a optimal” Option das notwendige Partition-Alignment korrekt durch. Für Opensuse’s YaST-Partitioner kann man unter dem Punkt “Einstellungen” ein optimales Ausrichten von Partitionen anfordern; das führt intern zum Setzen der Option “-a optimal” für “parted”. [Ich gehe in diesem Artikel davon aus, dass mit einem GPT-Layout der SSDs gearbeitet wird.]

LVM2 (unter YaST) arbeitet ebenfalls korrekt – und allokiert typischerweise 4MiB große “Physical Extends” [PEs]. (Siehe zu LVM2-Grundlagen etwa https://www.thomas-krenn.com/de/wiki/LVM_Grundlagen). Das passt zu allen vorherigen Einstellungen. Typischerweise wird man eine logische Volume-Gruppe [VG] über das gesamte Array anlegen. Durch die oben bereits diskutierten Parameter in der “/etc/lvm/lvm.conf” nimmt das LVM-PV-Layout auch auf die darunter liegende Raid-Array-Speicherorganisation Rücksicht.

Ein potentiell mögliches LVM-Striping von Logical Volumes über die Physikalischen Volumes (PVs) einer Gruppe hinweg fällt in unserem Fall flach: Das Striping wird ja bereits vom md-Raid-Array übernommen.

[LVM-Seitenaspekte: Würden wir aber – was prinzipiell möglich ist – statt md-Arrays LVM-basierte Raid-Arrays einrichten, müssten wir über die sog. LVM-Stripe-Size genauer nachdenken. Die LVM Stripe-Size gibt vor, ab welcher Größe der zu schreibenden Informationsblöcke auf ein neues PV der Logical Volume Group [VG] geschrieben wird. Die Überlegungen, die wir weiter unten zur Chunk Size der md-Raid-Arrays anstellen, sind dazu ganz analog. Interessant wäre übrigens auch ein LVM-Striping über mehrere md-Raid-Arrays (als PVs der VG) hinweg. Auch dann ist die LVM-Stripe-Size von größerem Interesse. Mangels Masse an SSDs habe ich damit aber noch nicht experimentieren können.]

Bleibt noch das Anpassen bestimmter Parameter (stride, stripe-width) des ext4-Filesystems an die darunter liegende Raid-Struktur. (LVM als Zwischenschicht ist diesbzgl. so gut wie transparent!). Erläutert ist dies z.B. hier
https://gryzli.info/2015/02/26/calculating-filesystem-stride_size-and-stripe_width-for-best-performance-under-raid/

Die Filesystem-Parameter (stride, stripe-width) sorgen für eine optimale Gruppierung von Datenblöcken für den Transfer zum bzw. vom Raid-Array. Dabei spielt die sog. Chunk-Size [CS] des Raid-Arrays eine Rolle; diese wird manchmal analog wie bei LVM LVs auch “Stripe-Size” des Raid-Arrays genannt. Ich komme darauf weiter unten genauer zurück. Im Moment mag genügen, dass z.B. der YaST-Partitioner die genannten Parameter korrekt einstellt, wenn ihm die zugrunde liegenden Raid-Array-Parameter bekannt sind.

Dennoch empfehle ich in jedem Fall manuell zu prüfen, ob die Parameter OK sind. Informationen zu den gewählten Parametern eines konkreten ext4-FS erhält man über tune2fs -l, z.B.:

mytux:~ # tune2fs -l /dev/volssd1/lvssdtest
....
RAID stride:              8
RAID stripe width:        16   

 
Wie man die korrekten optimalen Werte anhand des Raid-Typs (hier Raid 10) und der Raid-Chunk-Size bestimmt, erläutere ich in einem Abschnitt weiter unten.

Die Parameter stride und stripe-width können auch im Nachhinein mit Hilfe von tune2fs angepasst werden (s. http://serverfault.com/questions/663066/is-it-possible-to-update-stripe-width-on-an-existing-and-used-ext4-fs).

Weitere Links zum Alignment von
SSD-Raid-Systemen finden sich hier:
http://dennisfleurbaaij.blogspot.de/2013/01/setting-up-linux-mdadm-raid-array-with.html
http://serverfault.com/questions/592149/ssd-software-raid-alignment-necessary
https://www.percona.com/blog/2011/06/09/aligning-io-on-a-hard-disk-raid-the-theory/
https://raid.wiki.kernel.org/index.php/RAID_setup

Welche Kernelversion?

Vor einem Monat hätte ich diesen Absatz noch nicht geschrieben. Inzwischen habe ich aber Tests von Raid-Arrays auf verschiedenen Systemen mit Opensuse Leap 42.1, 42.2, Opensuse Tumbleweed, Debian Jessie und verschiedenen Kernelversionen [4.1, 4.4, 4.7] durchgeführt. Leider ist die Performance von Raid-Arrays, ja sogar der zugrunde liegenden Einzel-SSDs dabei keineswegs eine Konstante. Woran das liegt, ist mir z.Z. ein Rätsel.

Im Moment spreche ich mich bei einem Vorhaben mit SSD-Raid-Arrays aufgrund eigener Tests aber noch klar für die Kernel-Version 4.1 aus.

Das ist aus meiner Sicht diejenige Kernelversion, die in Tests (z.B. mit FIO) konsistent die höchsten Durchsatzraten mit geringster Variationsbreite bietet. Spätere Kernelversionen haben entweder Fehler bzgl. md-Raid-10-Arrays (4.2, 4.3; s. https://wiki.archlinux.org/index.php/RAID) oder liefern seltsam schwankende Performancedaten (s. https://bugzilla.kernel.org/show_bug.cgi?id=191881).

Schritt 1 zum SW-Raid10-Array: Anlegen von Raid-Partitionen auf den SSDs

In meinem Fall sind die 4 SSDs unter /dev/sda, /dev/sdb, /dev/sdc, /dev/sdd ansprechbar. Auf diesen Platten lege ich auf einem System mit UEFI-BIOS zunächst je eine erste efi-Partition (Fat16) an. Dies ist nur eine Vorsichtsmaßnahme für den Fall, dass ich später doch mal eine bootbare Partition in einem der SW-Raid-Arrays selbst anlegen will (s. hierzu die früheren Artikel dieser Serie).

Danach habe ich auf den SSDs für das nachfolgende Beispiel mit Hilfe von “mkfs” je eine weitere unformatierte Partition “/dev/sda[bcd]2” des Typs “0xFD Linux Raid” angelegt. “parted” liefert danach folgende Infos für z.B. “/dev/sdb”; dabei kann die 3-te zusätzlich vorhandene Test-Partion ignoriert werden. Im Moment ist nur die zweite Partition relevant.

(parted) print /dev/sdb
Model: ATA Samsung SSD 850 (scsi)
Disk /dev/sda: 500GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 

Number  Start   End    Size    File system  Name     Flags
 1      1049kB  189MB  188MB   fat16        primary  boot
 2      189MB   226GB  225GB                primary  raid
 3      226GB   253GB  26.8GB               primary  raid

 
Warum habe ich die Partition 2 unformatiert gelassen? Weil ich später eine flexible Partitionierung des Raid-Arrays über LVM erreichen will!

Alignment Checks:
Die logische und physikalische Sektorgröße der Samsung EVO 850 ist 512 Byte. Passen dazu die Partitionsgrenzen? Das bekommt man z.B. mit Hilfe von parted heraus.

(parted) align-check                                                      
alignment type(min/opt)  [optimal]/minimal? optimal                       
Partition number? 2                                                     
  
2 aligned
(parted)   

 
Wie sieht der Output von fdisk aus?

fdisk -l -u /dev/sdb
Disk /dev/sdb: 465.8 GiB, 500107862016 bytes, 976773168 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 3BFE79AE-FA81-474E-BB76-082C630414ED

Device         Start       End   Sectors  Size Type
/dev/sdb1       2048    368639    366592  179M EFI System
/dev/sdb2     368640 440774655 440406016  210G Linux RAID
/dev/sdb3  440774656 493211647  52436992   25G Linux RAID

 
Und was sagt sfdisk?

sfdisk -d /dev/sdb
label: gpt
label-id: 3BFE79AE-FA81-474E-BB76-082C630414ED
device: /dev/sdb
unit: sectors
first-lba: 34
last-lba: 976773134

/dev/sdb1 : start=        2048, size=      366592, type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=2B60DB9C-3DE1-45AC-80FC-A51657CA5E49, name="primary"
/dev/sdb2 : start=      368640, size=   440406016, type=A19D880F-05FC-4D3B-A006-743F0F84911E, uuid=2F85AE30-BE40-4D49-BE4C-F240EDF48289, name="primary"
/dev/sdb3 : start=   440774656, size=    52436992, type=A19D880F-05FC-4D3B-A006-743F0F84911E, uuid=8A67ED48-0BE2-4E83-8803-F7A42D91F3CF, name="primary"

 
Man sieht, dass die erste (efi-) Partition auf 1MiB (2048 sectors) ausgerichtet ist. Auch alle anderen Partitionen liegen offenbar genau auf Sektorgrenzen.

Analog verfährt man für die anderen SSDs. Unter Opensuse kann man zum Einrichten der Partition bequem YaST’s Partitioner verwenden. Bei der Verwendung der Kommandozeile nicht vergessen, die für Raid-Arrays bestimmte GPT-Partitionen auf den Typ 0xFD zu setzen! (genauer: 0xFD00; s. hierzu https://raid.wiki.kernel.org/index.php/Partition_Types).

Schritt 2 zum SW-Raid10-Verbund: Festlegen bestimmter Parameter des Kommandos “mdadm” – Chunk Size, bitmap, layout

Nun wird es Zeit, das Raid-Array zu definieren. Unter Opensuse könnte man das z.B. mit Hilfe von YaST’s Partitioner machen. Davon rate ich aber explizit ab, weil YaST leider nur Standardparameter setzt und keine abweichende Setzung ermöglicht.

Vielmehr ist der Befehl “mdadm” mit bestimmten Parametersetzungen anzuwenden. Es gibt beim Anlegen von Raid-10-Arrays mit mdadm vor allem 3 Parameter, die für die Performance interessant sind:

  • Parameter “chunk“, für die Festlegung der sog. “Raid Chunk Size” [CS],
  • Parameter “bitmap“; der legt fest, ob Daten in Transferprozessen besonders markiert werden; er kann später eine evtl. mal notwendig werdende Resynchronisation von Raid-Arrays beschleunigen. Er kostet aber auch Schreib-Performance.
  • Parameter “layout” zur Festlegung des sog. Near-, Far- oder Offset-Layouts eines Raid-10-Arrays

Zur Bedeutung der Chunk Size des Raid-Arrays

Die Chunk-Size legt fest, ab welcher atomaren Größe Information statt auf genau eine auch auf weitere Platten des Raid-Systems geschrieben wird. Ich zitiere von “https://raid.wiki.kernel.org/index.php/RAID_setup“:

The chunk-size deserves an explanation. You can never write completely parallel to a set of disks. If you had two disks and wanted to write a byte,
you would have to write four bits on each disk. Actually, every second bit would go to disk 0 and the others to disk 1. Hardware just doesn’t support that. Instead, we choose some chunk-size, which we define as the smallest “atomic” mass of data that can be written to the devices. A write of 16 kB with a chunk size of 4 kB will cause the first and the third 4 kB chunks to be written to the first disk and the second and fourth chunks to be written to the second disk, in the RAID-0 case with two disks. Thus, for large writes, you may see lower overhead by having fairly large chunks, whereas arrays that are primarily holding small files may benefit more from a smaller chunk size. ….
For optimal performance, you should experiment with the chunk-size, as well as with the block-size of the filesystem you put on the array. For others experiments and performance charts, check out our Performance page…

Die man-Seite zu mdadm offenbart, dass die Chunk-Size in KiB definiert wird. Viele Artikel zu SW-Raid im Internet empfehlen eine Chunk-Size von ≥ 512KiB. 512KiB ist übrigens auch die Default-Einstellung von “mdadm” (welche z.B. auch von YaST herangezogen wird).

Aber ist diese Einstellung auch wirklich gut?
Mißtrauisch sollte einen u.a. die Tatsache machen, dass z.B. Intel bei der Anlage von imsm-Raid-Containern mittels iRST als Default eine viel kleinere Chunk Size von nur 32KiB wählt. Interessant, nicht wahr?

Nun erhält man bei einem Raid-10-System (im sog. NN-Layout; s.u.) ohne Pufferung maximal zweifache Schreib- und Lese-Geschwindigkeiten gegenüber dem Zugriff auf nur eine SSD. Diese Geschwindigkeitsvorteile sind offenbar aber durch einen einzelnen Raid-Zugriff nicht erreichbar, wenn die zu schreibenden oder zu lesenden Informationseinheiten kleiner oder gleich der Chunk-Size sind. Hiermit stellt sich also die Frage nach dem durchschnittlichen Lastprofil für das Raid-Array! Müssen im mittel kleine oder große Datenpakete zum/vom Array transferiert werden?

Was einem in diesem Zusammenhang auch noch einfällt, ist Folgendes:
Es wird vermutlich einen großen Unterschied machen, ob mehrere Jobs des Betriebssystems gleichzeitig Schreib- oder Lese-Operationen verlangen oder ob nur 1 Job sporadisch kleine Informationseinheiten abgreift bzw. schreibt. So wie im letzteren Fall etwa ein (virtualisiertes) Betriebssystem oder ggf. sequentielle Datenbanktransaktionen. Bei mehreren parallelen Jobs kann das System die Daten dagegen zu größeren Transfer-Einheiten bündeln.

So wird es auf einem Fileserver mit vielen Usern und bei statistischer Verteilung von Filedaten über die 2 effektiven Platten des Raid-Systems eine große Chunk-Size eher von Vorteil sein – auch wenn pro Job deutlich kleinere Dateibrocken vorliegen. Im Schnitt über alle Jobs liest man dann immer noch von oder schreibt auf 2 Platten gleichzeitig. Bei einer Linux-Workstation, auf der ggf. ein virtualisierter KVM-Gast ausgeführt wird, kann das aber ganz anders aussehen. Zudem besitzen aktuelle SSDs auch noch einen internen Write Cache, der einem dazwischenfunken kann.

Man muss also die konkrete Festlegung der Chunk Size auf sein Zielszenario und die dort gegebenen Verhältnisse anpassen. Bislang habe ich euch noch keine quantitativen Informationen über den Einfluss der Chunk Size geliefert. Im nächsten Beitrag dieser Serie werde ich aber Messdaten und Anhaltspunkte dafür liefern, dass eine CS von 32KiB gar kein so schlechter Kompromiss ist – zumindest für die Kernelversion 4.1.

Übrigens: Man kann die Chunk Size für ein SW Raid Array bei Bedarf im Nachhinein ändern. Das kostet aber erhebliche (!) Zeit, da das Raid-System umgeschrieben werden muss und es während dieser Zeit auch potentielle Ausfälle verkraften muss. Dafür müssen aufwändige Sicherheitsvorkehrungen getroffen werden. Siehe hierzu etwa:
https://forum.ubuntuusers.de/topic/chunksize-bei-mdadm-raid5-onthefly-aendern/
http://serverfault.com/questions/186518/is-it-possible-to-change-the-raid5-chunk-size-of-an-existing-device

Performance-relevant ist natürlich auch, dass die Chunk Size ein ganzzahliges Vielfaches der Blockgröße des Filesystems sein sollte. Im Beispiel dieses Artikels wähle ich

–chunk=32

Zur Bedeutung des “bitmap“-Parameters

Im letzten Artikel hatte ich ein Szenario beschrieben, in dem eine Platte eines Raid-5-Arrays ausfiel, weil ein SATA-Kabel locker saß. Für solche Fälle können sog. “Bitmaps” helfen, die Rebuild Zeit drastisch zu verkürzen. Hierbei werden bestimmte Raid Chunks, die sich im “Transaktionsstatus” befinden, zunächst als “unclean” markiert. Nach Abschluss der Schreibaktion dagegen als “clean”. Durch Zeitstempelvergleiche müssen bei einem nur temporären Ausfall einer Platte (Timeout; verursacht z.B. durch unsaubere Kabelkontakte oder Systemfehler/Systemcrashes) dann nicht alle Blöcke des File-Arrays rekonstruiert werden, sondern nur die als “unclean” markierten.

Zitat aus https://raid.wiki.kernel.org/index.php/Write-intent_bitmap:

When an array has a write-intent bitmap, a spindle (a device, often a hard drive) can be removed and re-added, then only blocks changes since the removal (as recorded in the bitmap) will be resynced. Therefore a write-intent bitmap reduces rebuild/recovery (md sync) time if:
     * the machine crashes (unclean shutdown)
     * one spindle is disconnected, then reconnected.
If one spindle fails and has to be replaced, a bitmap makes no difference.

Aber: die entsprechenden Bitmap-Informationen müssen bei jeder Plattentransaktion auch geschrieben werden. Das kostet Performance; siehe http://blog.liw.fi/posts/write-intent-bitmaps/. Durch Verlagern der Bitmap auf außerhalb des Raid-Systems liegende gepufferte Datenträger kann man die Write-Performance erhöhen. Interne Bitmaps verringern die Schreib-Performance wirklich spürbar – nämlich bis zu 30%.

Nun legt z.B. die Raid-Verwaltung von YaST’s Partitioner unter Opensuse leider automatisch eine interne Bitmap an, ohne dass man dies unter YaST beeinflussen könnte. Daher sollte man den “bitmap”-Parameter lieber direkt mit dem mdadm-Befehl unter Kontrolle bekommen.

Da die Rekonstruktion von Raid-10-SSD-Arrays im (NN-Layout) recht schnell von statten geht und sich dabei im Gegensatz zu Raid-5 auch die Schreiboperationen in Grenzen halten, verzichtet man für eine optimale Write-Performance von Raid-10-Arrays über SSDs eher ganz auf das Anlegen einer Bitmap. Meine Wahl für die zugehörige Option des mdadm-Befehls ist also (s. zur Syntax die man-Seite zu mdadm):

–bitmap=none

Erwähnt sei hier, dass das Anlegen von imsm-Raid-Containern mit Hilfe von BIOS-Funktionen (iRST) für den Z170-Sunrise Point-H Sata Controller) von Intel nicht zum automatischen Anlegen einer Bitmap führt. Bei Performancevergleichen zwischen reinen SW-Raids und iRST/imsm-Fake-Raids ist das zu berücksichtigen. Dabei gilt nach eigenen Tests:

Ein mit Hilfe vom mdadm angelegtes reines SW-Raid ist ohne Bitmap mindestens so schnell wie ein mit BIOS-Funktionen angelegter iRST/imsm-Raid-10-Container am gleichen SATA3-Controller.

Zur Bedeutung des Layouts für md-basierte SW-Raid-10-Arrays

Man kann sich Raid-10 z.B. als eine Kombination
aus Raid 1 und Raid 0 vorstellen (Stripe of Mirrors). Aber das “raid10”- und das “md_mod”-Modul für “komplexe” SW-Raid10-Arrays unter Linux erlauben über eine spezifische, direkte Raid-10-Umsetzung interessante zusätzliche Dinge. U.a. kann man Daten über verschiedene Bereiche der beteiligten Platten so verteilen, dass im optimalen Fall immer mehr als 2 effektive Platten die Leseperformance beeinflussen. Man spricht dann von sog. “Raid10-Layouts”:

  • das sog. Near Layout entspricht im wesentlichen einem konventionellen Raid-1+0-Layout.
  • Dass Far-Layout und Offset-Layout verteilen die Daten dagegen versetzt über die die Laufwerke; man nähert sich dadurch bzgl. des Lesens einem Striping über 4 Disks an. Das erhöht die Leseperformance drastisch in Richtung eines Raid-5-Systems – es kann aber zu Lasten der Schreib-Performance aufgrund zusätzliche Seek-Zeiten gehen.

Bzgl. der präzisen Organisation über verschiedenen Platten bzw. Plattenbereiche hinweg unterscheiden sich die Layouts deutlich. Das beeinflusst nicht nur die Performance: So ist dass Offset-Layout weniger gegen Ausfälle gewappnet als das Near- oder Far-Layout.

Wer mehr über unterschiedliche Layouts von md-Raid-10-Arrays erfahren möchte, kann etwa folgende Artikel zu Rate ziehen, die die Datenveteilung über die beteiligten Devices z.T. mit schönen Grafiken erklären:

http://www.ilsistemista.net/index.php/linux-a-unix/35-linux-software-raid-10-layouts-performance-near-far-and-offset-benchmark-analysis.html?start=1
https://www.suse.com/documentation/sles10/stor_admin/data/raidmdadmr10cpx.html
http://serverfault.com/questions/139022/explain-mds-raid10-f2
http://xmodulo.com/setup-raid10-linux.html
http://blog.jamponi.net/2007/12/some-raid10-performance-numbers.html

Der Leser muss sich für ein bestimmtes Layout entscheiden – und sollte die Performanceunterschiede idealerweise vorher mit Hilfe von Test-Arrays ermitteln. Mir persönlich kommt es auf gute Schreibperformance auch im Random-Bereich an. Ich verhalte mich daher konservativ und nutze das N2-Layout (also ein Near-Layout):

–layout=n2

Das ist übrigens auch der Defaultwert von mdadm.

Schritt 3 zum SW-Raid10-Array: Zusammenbinden der Raw-Partitionen der SSDs mittels “mdadm”

Wir sind nun soweit, den mdadm-Befehl abzusetzen. Danach wird Linux sofort beginnen, das Raid-Array aufzubauen; dies entspricht einem erstmaligen Synchronisationsprozess.

mdadm --create --verbose /dev/md127 --level=raid10 --bitmap=none --chunk=32 --layout=n2 --raid-devices=4 /dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2

 
Das Raid Device sollte hier mit “/dev/mdijk” bezeichnet werden. “ijk” steht dafür für drei Ziffern. Ein Device mit denselben Ziffern sollte es natürlich noch nicht geben (Check etwa mit cat /proc/mdstat). Daneben kann man dem Device aber auch noch einen echten “Namen” geben (s.u.).

Ist das Raid Array fertig sychronisiert, so zeigt einem etwa ein Blick in “/proc/mdstat”:

mytux:~ # cat /proc/mdstat
Personalities : [raid10] [raid6] [raid5] [raid4] 
md127 : active raid10 sdc2[
2] sdb2[1] sdd2[3] sda2[0]
      440143872 blocks super 1.2 32K chunks 2 near-copies [4/4] [UUUU

 

Optionaler Schritt 3.1 zum SW-Raid10-Verbund: Beschleunigung des initialen oder eines (Re-) Synchronisations-Prozesses

Die Synchronisation der Disks oder Partitionen, aus denen ein Array besteht, erfordert Zeit und belastet natürlich CPU wie I/O-Subsysteme. Wie für echte HW-Raid-Controller gibt es daher auf für SW-Raids Parameter, die es erlauben, die Performance der entsprechenden Hintergrundsprozesse zu steuern. Defaultwerte sorgen meist für eine sehr geringe Zusatzbelastung zum laufenden Linux-Betrieb.

Ich setze auf meinem System daher regelmäßig zwei relevante Parameter (speed_limit_max, speed_limit_min) nach oben – dies führt zu einer substanziellen Beschleunigung des Sync-Vorgangs, der für Raid10-SSD-Arrays mit effektiven 400GB auf modernen Systemen deutlich unter 5 Minuten abgeschlossen werden kann. Bei Default-Einstellungen würde das viel länger dauern.

echo 500000 > /proc/sys/dev/raid/speed_limit_max
echo 200000 > /proc/sys/dev/raid/speed_limit_min

Das kann man auch während des laufenden Sync-Prozesses absetzen. Wie sich das auf die Sync-Performance auswirkt, kann man etwa an folgendem Output für ein anderes Array auf einem anderen System ablesen:

alpha:~ # echo 500000 > /proc/sys/dev/raid/speed_limit_max
alpha:~ # echo 200000 > /proc/sys/dev/raid/speed_limit_min
alpha:~ # cat /proc/mdstat
Personalities : [raid10] 
md_d0 : active raid10 sdd3[3] sdc3[2] sdb3[1] sda3[0]
      167651328 blocks super 1.2 512K chunks 2 near-copies [4/4] [UUUU]
      [===>.................]  resync = 16.3% (27408896/167651328) finish=6.0min speed=384214K/sec
      
unused devices: <none>
alpha:~ # cat /proc/mdstat
Personalities : [raid10] 
md_d0 : active raid10 sdd3[3] sdc3[2] sdb3[1] sda3[0]
      167651328 blocks super 1.2 512K chunks 2 near-copies [4/4] [UUUU]
      [===>.................]  resync = 18.8% (31654272/167651328) finish=4.6min speed=486124K/sec
      
unused devices: <none>
alpha:~ # cat /proc/mdstat
Personalities : [raid10] 
md_d0 : active raid10 sdd3[3] sdc3[2] sdb3[1] sda3[0]
      167651328 blocks super 1.2 512K chunks 2 near-copies [4/4] [UUUU]
      [===>.................]  resync = 19.3% (32462592/167651328) finish=4.2min speed=525478K/sec

 
Man beachte das schnelle Ansteigen des “speed”-Wertes nach Anheben der Werte von “speed_limit_max” und “speed_limit_min”.

Optionaler Schritt 3.2: Explizite Benennung des Raid Arrays mittels der “mdadm”-Option “–name”

Eine explizite Benennung des Raid-Arrays setzt die Verwendung der Option “–name” voraus. Siehe hierzu die man-Seiten zu mdadm. Der dafür angegebene String schlägt sich in einem Devicenamen unter /dev/md/name nieder.

Beispiel – wir benennen nachfolgend das Device mit “d00”:

mdadm --create /dev/md127 --name=d00 --level=raid10 --bitmap=none --chunk=32 --layout=n2 --raid-devices=4 /dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2

 

Das Array “/dev/md127” erscheint dann wie folgt

mytux:~ # cat /proc/mdstat
md127 : active raid10 sdb2[1] sdd2[3] sda2[0] sdc2[2]
      440143872 blocks super 1.2 32K chunks 2 near-copies [4/4] [UUUU]

mytux:~ # mdadm --detail /dev/md127
/dev/md127:
        Version : 1.2
  Creation Time : Fri Dec  2 12:07:25 2016
     Raid Level : raid10
     Array Size : 440143872 (419.75 GiB 450.
71 GB)
  Used Dev Size : 220071936 (209.88 GiB 225.35 GB)
   Raid Devices : 4
  Total Devices : 4
    Persistence : Superblock is persistent

    Update Time : Fri Jan 13 14:56:39 2017
          State : clean 
 Active Devices : 4
Working Devices : 4
 Failed Devices : 0
  Spare Devices : 0

         Layout : near=2
     Chunk Size : 32K

           Name : mytux:d00  (local to host mytux)
           UUID : 96fc09a4:f70044d1:4258b0dd:bdfb2b81
         Events : 19

    Number   Major   Minor   RaidDevice State
       0       8        2        0      active sync set-A   /dev/sda2
       1       8       18        1      active sync set-B   /dev/sdb2
       2       8       34        2      active sync set-A   /dev/sdc2
       3       8       50        3      active sync set-B   /dev/sdd2

 

Tatsächlich findet man folgende Verlinkung vor:

mytux:~ # ls -la /dev/md  
total 0
....
lrwxrwxrwx  1 root root     8 Jan 13 16:10 d00 -> ../md127
....

 

Warum braucht man das?
Ich habe darüber auch eine Weile gerätselt, bis mir aufgefallen ist, dass ein und dasselbe Raid-Array “/dev/md127” bei einem Neustart des Systems auch mal als “/dev/md126” erscheinen kann. Stellt sich die Frage, wer eigentlich beim Booten die Devicenamen festlegt. Antwort: “udev“.

Offenbar gibt es hierbei aber Freiheitsgrade. Daher die explizite Namensgebung, um Eindeutigkeit zu schaffen. Nimmt ein User keine explizite Namensvergabe vor, so greifen bestimmte Regeln. Aus “/dev/md129” wird dann etwa der Name “129” (mit dem eindeutigen Device “/dev/md/129”).

Da der Name mit anderen Raid-Informationen im Superblock der beteiligten Partitionen hinterlegt wird, kann das Device /dev/md/name immer eindeutig rekonstruiert werden.

Wichtig wird dies etwa bei gezielt vorgenommenen Einträgen in der “/etc/fstab”. Da “/dev/md/name” eindeutig ist, kann man in der “/etc/fstab” damit operieren. Z.B., wenn man das Raid Array mit einem Filesystem versehen hat. Allerdings gilt: Best Practice wäre in der “/etc/fstab” die Nutzung der UUID, die dem Raid Array auch zugeteilt wird – wie man oben sieht.

Der YaST-Partitioner zeigt die Raid-Devices übrigens immer unter dem jeweils vergebenen Namen an.

Dennoch muss ich sagen, dass ich die Logik der Namensvergabe unter mdadm bis heute nicht völlig verstanden habe. Es werden nämlich auch Einträge zu den benannten Raid Arrays in der Datei “/etc/mdadm.conf” vorgenommen (Opensuse; Einstellung des Ortes der Datei über sysconfig. Auf anderen Systemen liegt mdadm.conf möglicherweise unter “/etc/mdadm/mdadm.conf”). Diese Datei wird bei Existenz beim Booten ggf. für das “Assemblen” eines Raid Arrays herangezogen.

Im Besonderen kann es dann zu Problemen kommen, wenn Raid Arrays unter einer bestimmten Betriebssystem-Installation auf der gleichen Hardware-Plattform erzeugt, modifiziert und dann unter einer anderen Betriebssystem-Installation weiterverwendet werden sollen. Manuelle Korrekturen der Datei mdadm.conf nimmt man etwa mit dem sukzessiven Absetzen von befehlen der Art

mdadm -Db /dev/md/name >> /etc/mdadm.conf

für alle Raid-Array Devices vor. Oder alternativ und gleichzeitig für alle Arrays :

mdadm –detail –scan >> /etc/mdadm.conf

Die alten Einträge zu Raid Arrays in der Datei sollte man natürlich löschen. Nach einer manuellen Korrektur von mdadm.conf sollte man unter bestimmten Betriebssystemversionen zur Sicherheit zudem auch noch “mkinitrd” bzw. “update-initramfs -u” laufen lassen – je nachdem wie das “initramfs” angelegt wird.

Der Kernel braucht die Datei “mdadm.conf” allerdings nicht zwingend; er kann die notwendigen Infos
auch direkt aus Superblock-Informationen der beteiligten Raid-Partitionen auslesen.

Ich bin bisher ganz gut damit gefahren, den “–name”-Parameter explizit zu verwenden, udev werkeln zu lassen – und bei Inkonsistenzen oder Problemen beim Wechsel zwischen verschiedenen Betriebssystem-Installationen die jeweilige “/etc/mdamd.conf” ganz zu löschen.

Empfehlung
Ich empfehle, als Namen immer explizit eine 3-stellige Nummer anzugeben – z.B. –name=127. “udev” richtet nimmt dann auch die Anlage des Devices als “/dev/md127” vor. Also:

mdadm --create /dev/md127 --name=127 --level=raid10 --bitmap=none --chunk=32 --layout=n2 --raid-devices=4 /dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2

 
Das funktioniert gut – auch über verschiedene Betriebssysteminstallationen und mdadm-Versionen hinweg.

Umbenennung eines Arrays:
Der Name eines Arrays kann im Nachhinein noch geändert werden. Siehe
http://askubuntu.com/questions/63980/how-do-i-rename-an-mdadm-raid-array
http://www.unixbulletin.com/rename-an-mdadm-raid-array/

Wie geht man dabei vor? Nehmen wir ein Beispiel-Array, dem die Bezeichnung “–name=d00” mitgegeben wurde. Wir wollen das Array künftig unter “/dev/md126” bzw. “/dev/md/126” ansprechen. Folgende Befehlskette ist für die Umbenennung nötig.

mytux:~ # mdadm --stop /dev/md/d00
mytux:~ # mdadm --assemble /dev/md/126 --name=126 --update=name /dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2
mytux:~ # mdadm -Db /dev/md/126 >> /etc/mdadm.conf

 
Danach:

  • Löschen alter Einträge für d00 in /etc/mdadm.conf.
  • Dann Reboot.

Links zum Thema der Raid-Array-Benennung
https://bugzilla.redhat.com/show_bug.cgi?id=606481
https://bugzilla.redhat.com/show_bug.cgi?id=1201962
http://serverfault.com/questions/494569/mdadm-raid-device-name-changed-on-reboot
https://ubuntuforums.org/showthread.php?t=2265120
http://unix.stackexchange.com/questions/23879/using-mdadm-examine-to-write-mdadm-conf
https://wiki.ubuntuusers.de/Software-RAID/
http://unix.stackexchange.com/questions/80501/no-etc-mdadm-conf-in-centos-6
http://askubuntu.com/questions/63980/how-do-i-rename-an-mdadm-raid-array

Schritt 4 zum SW-Raid10-Array: Anlegen einer LVM2 Volume Group und Logical Volumes

Nun könnte man das Array “/dev/mdxxx”, wenn man will, direkt formatieren und mit einem ext4-Filesystem versehen. Ich ziehe aus Flexibilitätsgründen aber vor, LVM einzusetzen. Das Anlegen von LVM Volume Groups und LVM Volumes erfolgt nach Lehrbuch. Ich gehe hier aus Platzgründen nicht auf Details ein. Standardparameter können herangezogen werden.

Auf das Setzen der Parameter

“md_chunk_alignment = 1” und “issue_discards = 1”

in der Datei “/
etc/lvm/lvm.conf” hatte ich bereits hingewiesen. Siehe hierzu auch :
http://pof.eslack.org/2013/01/12/ssd-alignment-on-linux-with-ext4-and-lvm/
Unter Opensuse kann man erneut YaST’s Partitioner zum bequemen Anlegen der Volume Groups und Volumes verwenden.

Schritt 5 zum SW-Raid10-Array: Berechnung und Check der Parameter stride und stripe-width des ext4-Filesystems

Bleibt noch, entweder das Raid-Array direkt zu oder angelegte LVM Logical Volumes mit einem ext4-Filesystem zu versehen. Wir hatten schon erwähnt, dass dabei folgende Größen berücksichtigt werden sollten:

  • Raid-Chunk-Size [CS]: Die Menge an Daten, die auf ein Laufwerk (genauer eine laufwerksbezogene 0xFD-Partition) des Raid-Arrays geschrieben wird, bevor ein Wechsel des Laufwerks erfolgt (s.o.). je nach Striping des Raid-Arrays kann dabei auf mehrere Laufwerke gleichzeitig geschrieben werden.
  • Block-Size [BS] des Filesystems : Das ist die Größe der Dateisystemblöcke in Bytes. Typisch unter Linux: 4096 Byte (4 KiB).
  • Stride-Size [STS] des Filesystems: Entspricht der Chunk Size als Vielfachem der BS. Bei 32 KiB Chunk Size mit 4 KiB Blöcken ergibt sich STS = 32 KiB/ 4 KiB = 8. Für eine Chunk-Size von 512KiB : STS = 128.
  • stripe-width [SW] des Filesystems: Entspricht der Menge an Blöcken, die insgesamt geschrieben wird, wenn volle Chunks parallel auf die Laufwerke des Raid-Arrays geschrieben werden. Diese berechnet sich daher als
    STS * Anzahl der effektiv nutzbaren Disk-Partitionen [ENDP].

In eckigen Klammern habe ich dabei Abkürzungen angegeben, die ich nachfolgend in Formeln verwende.

Diese Größen gehen in die notwendige Berechnung der stride– und stripe-width-Parameter des ext4-Filesystems ein. Ist N die Zahl der eingesetzten Raid-Disks (bzw. der zugrunde liegenden Partitionen), so gilt für die Anzahl effektiv nutzbarer Devices ENDP :

ENDP = N/2 für Raid 10 Systeme
ENDP = N-1 für Raid 5 Systeme

Also:

  • Bei einem Raid 10 mit (Partitionen von) 4 SSDs: ENDP = 2.
  • Bei einem RAID 5  mit (Partitionen von) 4 SSDs : ENDP = 3.

Für eine Chunk-Size von 32 KiB ergibt sich auf einem Raid-10-System mit 4 SSDs also:

SW = STS * ENDP = 8 * 2 = 16

Einen Online-Calculator findet man hier: https://busybox.net/~aldot/mkfs_stride.html

Wie man diese Parameter bei Anwendung des mkfs-Befehls einsetzt, entnimmt man der man-Seite zu mkfs.ext4. Siehe hierzu die Option “-E” mit nachfolgenden komma-separierten Optionen.

Hat man das Filesystem angelegt, kann man die Parameterwerte mit “tune2fs -l” prüfen. Testen sollte man auch, ob man nach einem Mounten /z.B. auf /mnt) den “fstrim”-Befehl erfolgreich ausführen kann (z.B. “fstrim -v /mnt“). Das sollte bei einem Raid-10-Array anstandslos funktionieren!

Fazit

Die Anlage eines md-Raid-10-Arrays mit Hilfe des mdadm-Befehls ist eigentlich simpel. Dennoch gibt es selbst bei einer Entscheidung für ein Raid-10-Array eine Vielzahl von Überlegungen, die im Vorfeld anzustellen sind. Ich habe versucht, einige Aspekte zu diskutieren. Letztlich wird es einem aber nicht erspart bleiben, im Vorfeld der Ausstattung eines Produktiv-Systems ein paar Tests zu fahren.

Der “bitmap”-Parameter ist durchaus performance-relevant; insbesondere ist bei Performancevergleichen mit iRST/
imsm-Raid-Containern zu beachten, ob auf dem Fake-Array eine Bitmap genutzt wird oder nicht.

Ein zentraler Parameter in dem ganzen Spiel ist aus meiner Sicht die Chunk-Size. Wir werden im nächsten Beitrag sehen, dass gerade im Random Read/Write-Bereich für Einzeljobs, die kleine Datenmengen schreiben, viel von dieser Größe abhängt.

Ich nehme hier mal vorweg, dass man hier zunächst die Extreme 32KiB und 512KiB für sein Zielszenario austesten sollte. Speziell für Fileserver sind große Chunk-Werte eher sinnvoll.

Ausblick

Im nächsten Artikel

SSD Raid Arrays unter Linux – IX – Chunk Size und Performance eines md-Raid-10-Arrays

präsentiere ich dann einige Ergebnisse von FIO-Tests für verschiedene Chunk-Size-Parameter unter Kernel 4.1.

Weitere Links

https://wiki.archlinux.org/index.php/RAID
https://wiki.ubuntuusers.de/Software-RAID/
https://wiki.mikejung.biz/Software_RAID
https://infogalactic.com/info/Non-standard_RAID_levels
http://forum.openmediavault.org/index.php/Thread/1333-Tuning-of-ext4-on-LVM-and-RAID/
http://en.linuxreviews.org/Mdadm

 

SSD Raid Arrays unter Linux – VII – problematische Aspekte von Raid-5-Arrays

In früheren Artikeln dieser Serie

SSD Raid Arrays unter Linux – III – SW- Raid vs. Intel-iRST-Raid – Performance?
SSD Raid Arrays unter Linux – V – SW-Raid vs. iRST-Raid – Boot-Unterstützung?
SSD Raid Arrays unter Linux – VI – SW-Raid vs. iRST-Raid – Flexibilität?

hatte ich am Beispiel des Intel Z170 RST Controllers ausgeführt, dass es auf einem reinen Linux-System für Raid-Setups nicht notwendig ist, iRST-Technologie zu benutzen. Man betreibt den Intel-Onboard-Controller besser als einfachen SATA3-Controller und nicht als iRST-Raid-Controller. Die (SSD)-Raid-Arrays baut man sich dann lieber mit Hilfe von mdadm als Linux-SW-Raid-Arrays. Man gewinnt dadurch an Flexibilität, hat keine Performance-Nachteile und kann sogar – wenn nötig – eine Linux-OS vom Array booten.

Bei Einsatz eines SW-Raid-Arrays für SSDs ist unter Linux allerdings ein wenig Umsicht angebracht. U.a. stellt sich die Frage nach der Wahl der Raid-Variante. In meinem Fall für vier SSDs. Da liegen als grundsätzliche Alternativen etwa Raid-10- oder Raid-5-Arrays nahe.

In diesem Beitrag möchte ich zwei Argumente dafür anführen, dass die Wahl eines Raid-5-Arrays nicht unbedingt die beste Entscheidung ist – und zwar

  • trotz des größeren nutzbaren Netto-Platzes auf dem SSD-Raid-Array
  • und trotz der im sequentiellen Read-Bereich für große Datenpakete besseren Performance.

Die Argumentation hat mit der Resynchronisation des Raid-Arrays nach einem Plattenausfall, der relativ schlechten Performance von Random-Write-Prozessen für kleine Datenpakete und der Nichtausführbarkeit des “fstrim”-Befehls zu tun (Stand Nov. 2016).

Nachtrag 14.06.2017:
Von all diesen Punkten ist der letzte derjenige, der sich am einfachsten überprüfen lässt. Zum zweiten Punkt werde ich bei Gelegenheit Daten nachliefern. Bzgl. des ersten Punktes bin ich mir inzwischen nicht mehr sicher, ob ich wirklich alle Einflussfaktoren verstanden habe. Ich habe den Artikel heute abgeändert; er spiegelt nun meine aktuelle Einschätzung wieder.

Was sprach im HDD-Zeitalter gegen Raid-5- oder Raid-6-Arrays?

Raid-5-Arrays stellten schon zu HDD-Zeiten ein Problem dar. Zu nennen war/ist hier aus meiner Sicht an erster Stelle der erhebliche Zeitbedarf zur Rekonstruktion eines degraded Raid-5- oder Raid-6-Arrays.

Ein degradiertes Array kann z.B. aufgrund des Ausfall einer Platte wegen echten HD-Defekten oder aber wegen einer losen SATA-Verbindung (ist mir schon passiert!) zu Stande kommen. Eine Degradierung kann aber durch einen ernsten Fehlers des Linux-Systems ausgelöst werden. Ja, letzteres kommt ab und zu auch mal unter Linux vor! Probleme gibt es u.U. auch dann, wenn Inhalte von Schreib-Caches bei einer Systemstörung nicht rechtzeitig auf alle Platten geschrieben werden konnten. Die Raid-SW muss nach einer Systemstörung mit Reboot u.U. eine Rekonstruktion betroffener Arrays vorschlagen, um wieder auf die sichere Seite zu kommen.

Überlebenswichtige Paritätsinformation muss dann wieder hergestellt werden; fehlerhafte Informationen auf der betroffenen Platte sind neu zu synchronisieren.

Statt Rekonstruktion spricht man oft auch von einer “Resynchronisierung” oder “Rebuild” eines Raid-Arrays. Ich verwende diese Ausrücke nachfolgend synonym.

Extrem lange Resynchronisationszeiten für Raid-Arrays mit mehreren Terrabyte an Kapazität gab es vor allem dann, wenn man die Zeitanteile für Rekonstruktionsaufgaben im Raid-
Controller oder aber in der Linux-SW zugunsten der produktiven Performance operativer Prozesse (also für den laufenden Alltagsbetrieb) reduzieren musste. Die Rekonstruktion eines Raid-5-Arrays konnte dann schon mal etliche Stunden in Anspruch nehmen. In dieser Zeit lebte man immer mit der Gefahr weiterer Ausfälle.

Resynchronisation von SW-Raid-Arrays mit SSDs

Nun sind SSDs ja sehr viel rascher als konventionelle HDDs. Aus diesem Grund sagten einige Systemadministratoren in Internet-Foren sogar eine Renaissance für Raid-5-Arrays voraus. Der Optimismus ist in der Praxis tatsächlich nachvollziehbar: Setzt man die Priorität für eine Raid-5-Resynchronisierung auf Mittelwerte, so liegen die Zeiten für ein 1TB-Array deutlich unter einer Stunde. Das ist aus meiner Sicht OK. Hinzu kommt bei Raid-5 ja die bessere Netto-Plattenplatzkapazität für Nutzdaten im Vergleich zu einem Raid-10-System.

Welche Faktoren beeinflussen die Resynchronisation eines Raid-5-Arrays?

Es erscheint klar, dass nach einem Verlust von Redundanz ggf. zwei Dinge notwendig sind:

  • Wiederherstellen von Information auf der ausgefallenen Platte/Partition bei einem Timeout oder auf einer Ersatz-Platte/Partition nach Totalausfall.
  • Erneutes Herstellen der Redundanz durch Berechnung und Schreiben valider Parity-Informationen.

Verkompliziert wird der Rekonstruktionsvorgang, wenn das Raid-5 Array im degradierten Zustand aktiv weiter betrieben wird oder betrieben werden muss. Zudem stellt sich die Frage, was die Ursache des Redundanzverlustes war und ob die ausgefallene Platte (oder Partition) aufgrund eines Defekts ersetzt werden muss – oder aber, ob die ursprünglich vorhandene Platte aus irgendwelchen Gründen nur einen vorübergehenden Timeout hatte, und weiterverwendet werden kann. Ein solcher Timeout kann z.B. durch ein locker sitzendes SATA-Kabel verursacht worden sein. Letzteres ist mir tatsächlich passiert (s.u.)!

Fall 1: Notwendiger Ersatz einer Platte/Partition nach einem Defekt
Dieser Fall ist logisch am einfachsten zu überblicken. Daten und Paritity-Informationen müssen dann auf der neuen Platte/Partition vollständig neu geschrieben werden.

Dazu muss der gesamte (!) Datenvorrat sukzessive von den verbliebenen Platten ausgelesen werden, über die noch vorhandenen Parity-Daten ist die verlorengegangene Information über Berechnungen zu rekonstruieren, der fehlende Datenanteil ist auf die neue Platte/Partition zuschreiben, Redundanz ist durch Berechnen und Schreiben neuer Parity-Information auf die neue Platte/Partition herzustellen. Das ist ein aufwändiger Vorgang, der die alten, noch funktionierenden Platten des Arrays enorm stresst, CPU kostet und vor allem viele Schreibvorgänge auf der neuen Platte/Partiton nach sich zieht.

Der ganze Prozess ist deshalb zwangsläufig langsam – es ist klar, dass ein weiterer Betrieb des degradierten Arrays nur mit schlechter Performance möglich sein wird. Die Wahrscheinlichkeit, dass eine weitere Platte im Rekonstruktionsprozess ausfällt, ist wegen der vielen Zugriffe nicht vernachlässigbar. Das Schreiben neuer Daten während eines weitergeführten Betriebs muss zudem in den Datentransfers zur neuen Platte und bei zugehörigen Paritätsberechnungen berücksichtigt werden. Das ist ein Grund dafür, die Array-Rekonstruktion möglichst ohne operative Belastung durchzuführen.

Fall 2: Die alte Platte/Partition kann weiter verwendet werden
Tja, da wird es dann komplizierter. Nehmen wir mal an, wir machen dem Array die ausgefallene Partition wieder zugänglich. In der Zwischenzeit lief/läuft aber der operative Betrieb auf dem Array weiter. Ein paar entscheidende Frage sind dann:

Woher soll das System eigentlich wissen, welche Parity-Information seit dem Ausfall noch verlässlich ist? Welche Sektoren und Blöcke
waren vom Ausfall betroffen? Welche Informaiton wurde neu hinzugefügt? Wo hat das zwischenzeitliche Überschreiben von Daten die ursprüngliche Parity-Information verändert?

Für die betroffenen Blöcke muss die Daten- und Parity-Information ja in jedem Fall neu berechnet und die nunmehr ungültige Information auf der wieder eingehängten Platte ersetzen!

Das Schreiben neuer Information kann aber irgendwo im Filesystem und damit auf der Platte erfolgt sein! Kennt das System die betroffenen Sektoren und Datenblöcke nicht, muss es deshalb im Rekonstruktionsprozess zur Sicherheit alle Daten des degradierten Arrays mit den veralteten Informationen auf der wieder eingegliederten Platte vergleichen und ggf. korrigieren!

Es wird klar: Man braucht für solche Situationen eine Art “Logging” der Adressen modifizierter Datenbereiche.

Bitmaps!
Linux SW-Raid (mittels mdadm) sieht für diesen Zweck das Schreiben sog. “Bitmaps” als Option für Raid-Arrays mit Datenredundanz vor. Genauere Informationen erhält man hier: https://raid.wiki.kernel.org/ index.php/ Write-intent_bitmap.

Ich zitiere den wichtigsten Punkt:

“When an array has a write-intent bitmap, a spindle (a device, often a hard drive) can be removed and re-added, then only blocks changes since the removal (as recorded in the bitmap) will be resynced. Therefore a write-intent bitmap reduces rebuild/recovery (md sync) time if:
  – the machine crashes (unclean shutdown)
  -one spindle is disconnected, then reconnected.
If one spindle fails and has to be replaced, a bitmap makes no difference.”

Für das Anschalten einer “Bitmap” und damit des gewünschten “Loggings” steht eine mdadm-Befehlsoption zur Verfügung (s. für die mdadm-Praxis einen späteren Artikel).

Haben Bitmaps auch Nachteile?
Leider muss ich die Frage mit Ja beantworten. Im Artikel
SSD Raid Arrays unter Linux – III – SW- Raid vs. Intel-iRST-Raid – Performance?
hatte ich ja verschiedene Performancedaten zum Vergleich eines reinen (über mdadm angelegten) Linux-SW-Raid-10-Arrays mit einem iRST-Raid-10-Array präsentiert. Dabei wurden erhebliche Unterschiede in der Performance von mdadm-SW-Arrays festgestellt, die mit unterschiedlichen Parametern angelegt wurden:

Die festgestellte, um bis zu 30% schlechtere sequentielle Write-Performance gehörte zu Linux-SW-Arrays, bei denen im operativen Betrieb eine Bitmap mit geschrieben wurde!

Bitmaps kosten also Schreib-Performance – manchmal in signifikanter Weise. Wie hoch die Einbußen genau sind, hängt jedoch auch davon ab, ob man die Bitmap-Daten auf das Array selbst oder auf eine Partition einer separaten Platte außerhalb des Arrays schreibt. Wir werden auf entsprechende Effekte und Zahlen in späteren Artikeln zurückkommen.

Raid-5 mit einem Onboard-Sata3-Controller – Intel Z170 Sunrise Point – und iRST-Technologie

Wie sieht es mit der Rekonstruktion eines Raid-5-Arrays nun eigentlich im schlimmsten Fall aus? Ich schildere hierzu mal eines meiner Erlebnisse:

In meiner grenzenlosen Naivität begann ich bei der Einrichtung meines SSD-Testsystem zunächst damit, unter Einsatz von iRST ein “Raid 5”-Array aufzubauen. Die SSDs hingen dabei am “Sunrise Point”-Controller im Z170-Chipsatz des Mainboards. Nun ist ja bekannt, dass eine gerade Anzahl von Platten und Raid-5 nicht sonderlich gut zueinander passen. Für einen ersten Anlauf mit einem Raid-5-Array sprachen aus meiner Sicht aber folgende Punkte:

  • Bessere Nutzung der (relativ teuren) Plattenkapazität als mit Raid-10.
  • Optimierung vieler (Fake-)
    Raid-Controller auf die Nutzung von Raid-5.
  • Schlechte Erfahrungen mit Raid-10 auf 3ware-Controllern bei Random I/O.

Meine vier 500 GB-SSDs [Samsung EVO 850] wurden also zu einem Linux-SW-Raid-Array zusammengeschaltet; dabei wurden ca. 460 GB pro Platte effektiv genutzt. Zum Aufsetzen nutzte ich die UEFI-BIOS-Bordmittel für den Intel-Controller (iRST). Die resultierende Performance war wirklich überzeugend:

Ein Read-Durchsatz im sequentiellen Bereich um die 1.45 GB/sec und hohe sequentielle Schreibraten im Bereich von 1.1 GB/sec ließen mich zunächst nicht an meinem Vorgehen zweifeln. Hinzu kam – im Vergleich zu Raid 10 – die relativ hohe verfügbare Plattenkapazität (> 1,36 GB bei 4 EVO 850 500GB SSDs).

Das Betriebssystem hatte ich im ersten Anlauf dummerweise auch auf dem Raid-Array selbst installiert. Das kostet, wie bereits in einem früheren Artikel festgestellt, ca. 10% an Performance. Ich habe die Entscheidung für Raid-5 dann aber aus einem anderen Grund als vordergründigen Performance-Einbußen bereut.

Resynchronisation des Raid-5-Systems nach Ausfall einer Platte

Es geschah nämlich etwas, dass normalerweise nicht passieren sollte. Ich hatte ein SATA-Verbindungskabel nicht richtig gesteckt. Als das PC-Gehäuse dann mal bewegt wurde, löste sich das Kabel aus der SSD – mit dem Effekt, dass das Array in einen “degraded” Zustand überging. Kein Problem, dachte ich. Genau für solche Situationen hat man ja ein RAID-System. Ich ließ das Array danach wieder aufbauen – der Resynchronisierungsprozess wurde mit der entsprechenden iRST-Funktionalität des Controllers im BIOS aufgesetzt; die eigentliche Ausführung erfolgte dann im neu gestarteten Linux-System unter Kontrolle der “md-raid”-Module des Kernels. Insgesamt nahm das nicht so viel Zeit in Anspruch wie aufgrund vieler Internet-Artikel befürchtet. Ich habe die Zeit nicht gemessen, aber es dauerte, wie gesagt, sicher deutlich weniger als 1 Stunde.

Was mich dann allerdings schockte, war ein Blick auf den SSD-Zustand mit Hilfe des Kommandos smartctl. Ist Smart im BIOS aktiviert, so ist eine Zustandsüberprüfung einzelner SSDs (zumindest auf meinem ASRock-Board) sowohl bei Einsatz eines nativen Linux-SW-Raids als auch bei Einsatz von iRST-Raid-Containern möglich. Die durch den Ausfall betroffene SSD lief bei mir als Device “/dev/sdd”. Die übrigen Devices des Raid-5-Arrays unter /dev/sda, /dev/sdb, /devsdc. Unter den vielen ausgewiesenen Smart-Daten stelle ich nachfolgend nur die Anzahl der “Total_LBAs_written” nach dem Resynchronisationsprozess dar:

Total_LBAs_Written
sda : 604127952
sdb : 846533123
sdc : 603302987
sdd: 3763859973 !!!

Vor dem Resynchronisationsprozess befand sich der Wert für “/dev/sdd” dagegen auf dem Niveau von “/dev/sdc” – also < 603302987 !!

Dass der Basiswert auf “/dev/sdb” so hoch war, lag übrigens daran, dass auf diesem Device noch andere Tests zur Performance einer einzelnen SDD durchgeführt worden waren.
Nach vielen, vielen weiteren Testläufen und ca. 12 (!) immer neuen initialen Raid-10-Synchronisationen über 100 GB, 200 GB oder 400 GB umfassende (Raid-10-) Arrays sieht das heute (Nov. 2016) so aus:

Total_LBAs_Written
sda: 979783261
sdb: 1211867704
sdc: 995650995
sdd: 4121599736

Es ist offensichtlich, dass die eine Resynchronisations-Aktion für die Wiederherstellung des ehemaligen Raid-5(!)-Arrays über die gesamte Platte “/dev/sdd” hinweg geschrieben hat (Daten- und Paritätsinformationen). Gleichzeitig ging der Parameter “Wear_Leveling_Count” der vom Ausfall betroffenen Platte um 1 Prozentpunkt nach unten. Die Belastung der (vorher ausgefallenen) Platte durch den einen Raid-5-
Resynchronisationsprozess ist also substanziell gewesen!

Wie lässt sich der extreme Befund zur Schreibbelastung erklären?

Im Artikel
SSD Raid Arrays unter Linux – III – SW- Raid vs. Intel-iRST-Raid – Performance?
hatten wir eine relativ gute Schreib-Performance des iRST-imsm-Raid-Arrays festgestellt. Eine spätere Überprüfung brachte dann die Ursache zu Tage:

Die iRST-BIOS-Funktionen legen die imsm-Raid-Container grundsätzlich ohne “Bitmap” an!

Nächste Frage: Welche Auswirkungen hat denn das Fehlen einer Bitmap auf eine Resynchronisation? Eine Antwort finden wir in folgendem Artikel:
https://raid.wiki.kernel.org/ index.php/ Replacing_a_ failed_drive

Dort wird erläutert, dass man im Falle von Timeouts versuchen kann und sollte, die ausgefallene Platte/Partition einem Raid-Array wieder zur Verfügung zu stellen. Ich zitiere aus dem Abschnitt “So you have no redundancy!”:

“Before attempting to replace a failed drive, you should ALWAYS attempt to restore redundancy before replacing a drive. If the array is redundant, a replace will just copy the dodgy drive, only stressing the old drives if it can’t read the dodgy drive. If the array is not redundant, then adding a new drive will stress the entire array as it has to recreate the new drive from the remaining old drives. This is true even for a mirror.”

Und:

“If you have set up a bitmap on your array, then even if you plan to replace the failed drive it is worth doing a re-add. With a bitmap, the raid will know which sectors need writing, and will recover the array for you. You can then consider doing a replace of the faulty drive.
mdmad /dev/mdN –re-add /dev/sdX1
mdadm /dev/mdN –add /dev/sdY1 –replace /dev/sdX1 –with /dev/sdY1
If possible, do not mount the partitions on the raid (or do it read-only) while the rebuild takes place, to avoid undue stress on the array.
If you do not have a bitmap then don’t re-add the old drive unless it was a (now fixed!) timeout problem and you don’t intend replacing the drive. Without a bitmap, then the raid will treat it like a new drive and do a total rebuild.

Aha! Der letzte Satz erklärt mein Erlebnis und bedeutet gleichzeitig:

Wenn schon Raid-5, dann bitte mit Bitmap!

Es ist eigentlich bemerkenswert, dass Intel für iRST-Raid-5-Arrays nicht automatisch die Anlage von Bitmaps vorsieht. Intel weiß wohl, dass die Schreibraten dann nicht mehr so werbewirksam wären!

Wie ist das Schreiben für eine Raid-5-Rekonstruktion – ohne Bitmap – im Vergleich zu einer normalen Plattenbelastung zu werten?

Zum Vergleich: Eine in einem anderen System seit 2 Jahren als Betriebssystemplatte mit virtuellen Maschinen im Dauereinsatz, aber nicht in einem Raid-Verbund befindliche Samsung EVO 840 Pro weist heute einen Wert von

Total_LBAs_Written
sdx: 7968906003

auf. Das ist also immer noch weniger als das Doppelte dessen, was mich eine einzige (!) Resync-Aktion einer Raid-5-SSD gekostet hat!

Wie oft muss man eigentlich mit einem Resync-Prozess rechnen?

Der oben genannte Artikel wiesen ja darauf hin, dass Crashes und unsaubere Shutdowns einen Rebuild-Vorgang für ein Array auslösen können. Machen wir uns nichts vor: Zumindest auf Linux-Desktop-Systemen kommt sowas öfter vor, als man sich das wünscht. Erst vor kurzem hatte ich mal einen Hänger des KDE-Plasma-Desktops auf meinem Testsystem. Das System war danach nicht mehr bedienbar. Ich befürchtete schon das
Schlimmste; der Filesystemzustand war zum Absturzzeitpunkt zwar fehlerhaft, der Plattenzustand über das Raid-Array hinweg aber noch konsistent. Das Filesystem-Fehler konnte nach einem Reboot ohne ein Raid-Rebuild korrigiert werden.

Aber dafür gibt es nun leider überhaupt keine Garantie – schon gar nicht im Falle eines Absturzes während eines intensiven Datentransfers (lesend und schreibend) zu dem Raid-5-Array. Ein inkonsistenter Zustand der Platten im Raid-System nach einem ernsthaften Systemfehler ist aus meiner Sicht dann eher wahrscheinlich. Und anschließend würde – bei fehlender Bitmap – vermutlich das gesamte Raid-5-System resynchronisiert werden.

Wie schaut es mit Raid-10 aus?

Ich habe für Tests in den letzten Monaten mehrfach Raid-10-Arrays angelegt und auch rekonstruiert. Die Wiederherstellung eines Raid-10-Arrays nach einem Timeout einer Platte erwies sich hinsichtlich der durchgeführten Schreiboperationen regelmäßig als relativ harmlos. Die Resynchronisation eines degradierten Raid-10-Array wird zudem erheblich (!) schneller als die eines gleich großen Raid-5-Arrays abgeschlossen.

Ein Grund liegt auf der Hand – im Falle von Raid-10 ist keine Paritätsinformation zu berechnen oder zu schreiben. Ich vermute ferner, dass im Zuge der Rekonstruktion nach einem Timeout möglicherweise nicht alle Daten, sondern lediglich abweichende, bereits genutzte und während des Timeouts geänderte Blöcke durch Schreibvorgänge abgeglichen werden. Das Prüfen auf Identität von Datenblöcken auf zwei Laufwerken lässt sich bei reiner Spiegelung ja relativ einfach und vor allem schnell durchführen.

Reichweite des TRIM-Befehls?

Ein wichtiger weiterer Punkt, der im Zusammenhang mit SSDs zu beachten ist, ist das Thema der sog. “Write Amplification” (s. https://en.wikipedia.org/ wiki/ Write_amplification). Ein Flash-Speicher muss vor einem Neubeschreiben erst gelöscht werden; das führt u.U. zu Verschiebungen von Speicherinhalten und mehrfachen Schreiboperationen. Das reduziert potentiell sowohl die Performance als auch die Lebenszeit von SSDs.

Neben den reinen Nutzdaten müssen im Normalbetrieb auf allen Platten eines Raid 5/6-Verbunds Paritätsinformationen geschrieben werden. Write Amplification (durch Verlagerung von Blöcken auf SSDs) trägt also gerade im Fall von Paritäts-Raids zusätzlich zu einer stärkeren Abnutzung der SSDs bei – gerade in kleineren Arrays (< 8 disks). Theoretisch ist aber die Anzahl der insgesamt durchzuführenden Schreiboperationen auch bei Raid-10 nicht kleiner als bei Raid-5. Insofern erscheint mir das Thema der Write Amplification als solches allein noch kein Argument für oder gegen Raid-5 oder Raid-10 zu sein.

Eine Konsequenz zur Aufrechterhaltung der Performance und zur Vermeidung von Zeitverlust durch Löschungen besetzter Blöcke bzw. durch das Suchen nach freien Blöcken auf der Platte ist aber, dass die Information über freie Knoten mit dahinterliegenden direkt beschreibbaren Speicherelementen regelmäßig upgedated werden muss. Das Filesystem muss den SSD-Controller – gemeint ist hier der Controller auf der SSD und nicht der Fake-Raid-Controller – über freigewordene, ungenutzte Speicherelemente informieren. [Der SSD-Controller muss mit den im Rahmen des (S)ATA-Protokolls übertragenen Information natürlich auch was anfangen können; letzteres ist heute praktisch bei allen Marken-SSDs der Fall.]

Unter Linux erledigt das der “fstrim“-Befehl für gemountete Partitionen: einerseits erfolgt dadurch die Weitergabe der Information zu freien Knoten; andererseits werden dann von den SSD-Controllern sog. “discard”-Operationen für logisch freigegebene Speicherelemente durchführt. Fortschrittliche Controllers sehen zudem regelmäßige Lösch- und Speicher-Reorganisationsverfahren auf den SSDs vor (SSD garbadge collection).

Nun können Betriebssystem und Raid-(Controlling)-SW in intelligenter Weise dazu beizutragen, um “Write Amplification” zu reduzieren. Hierfür sind meist Zwischenpufferungen von Operationen nötig. Siehe hierzu die interessanten Diskussionen unter

http://www.webhostingtalk.com/ showthread.php?t=1457939

http://cesg.tamu.edu/ wp-content/ uploads/2012/02/ hotstorage13.pdf

Aber:
Das Thema der Speicher-Freigabe und -Reorganisation bleibt unabhängig von der Anzahl der Schreiboperationen für SSD-Raid-Arrays bestehen. Somit stellt sich für die Auswahl eines bestimmten Raid-Verfahrens für SSDs auch die Frage, ob der “fstrim”-Befehl für die verschiedenen Raid-Varianten eigentlich durch die potentiell betroffenen Layer

Linux-Filesystem (z.B. ext4) – Logical Volume einer LVM-Gruppe – Array über Raid-Partitionen – Partitionen verschiedener SSDs

zu den Controllern der beteiligten SSDs durchgereicht wird.

Leider ist das gerade für Raid-5- oder Raid-6-Arrays nicht der Fall – weder im Falle von mdadm-SW-Raid-Arrays noch im Falle des Einsatzes von iRST-Technologie und imsm-Raid-Containern. Ich erhalte bei entsprechenden Versuchen regelmäßig Meldungen, dass die zugrundeliegende Infrastruktur den fstrim-Befehl nicht unterstützen würde.

Auf meinen Test-Systemen konnte ich dagegen feststellen, dass der “fstrim”-Befehl an logische LVM-Volumes auf Raid-0-, Raid-1– und Raid-10-Arrays anstandslos durchgereicht wird – zumindest für ext4-Filesysteme. (Andere Filesysteme wie BTRFS habe ich nicht getestet; generell herrscht ja die begründete Meinung vor, dass EXT4 dem Verhalten von SSDs am besten entgegenkommt). Das gilt für reines SW-Raid unter mdadm wie auch für den Einsatz von iRST/imsm-Containern. (Diese Aussagen kann ich genau genommen im Moment nur für Opensuse-Leap 42.1/42.2 (Kernel 4.4) und ein Debian Jessie-Test-Systeme mit Kernel 4.7 treffen.)

D.h.: Potentielle Einschränkungen der Performance sind zumindest bei ext4-Filesystemen auf Raid-5-Arrays vorprogrammiert, wenn nicht der Plattencontroller selbst die Garbage Collection und Speicherreorganisation übernimmt. Tatsächlich konnte ich für ext4-Partitionen nach Durchführung von Tests, bei denen mehr als 40 % eines Filesystems beschrieben wurden, regelmäßig Performanceverbesserungen nach Absetzen eines fstrim-Befehls feststellen. Zwar keine weltbewegenden Änderungen, aber doch im 10% – 20%-Bereich. Einschränkungen der Performance tauchen mit dem Auffüllen einer Partition also mit hoher Wahrscheinlichkeit auf.

Nun wird und wurde von SSD-Herstellern und Kommentatoren im Internet oft angeführt, dass gerade größere SSDs, die für den professionellen Einsatz gedacht sind, selbst für eine regelmäßige Garbage Collection sorgen. Ich habe sowohl EVO 840 Pros und EVO 850 Pros mit 500GB Kapazität auf verschiedenen Systemen im Einsatz und setze ab und zu den fstrim-Befehl für eingerichtete Partitionen manuell ab. Die benötigten Zeiten zur Speicherreorganisation dauern für meine Gefühl relativ lange und betreffen manchmal etliche zig GB. Dabei werden offenbar auch echte Operationen auf den Disks durchgeführt. Das spricht aus meiner Sicht zumindest nicht für eine hohe Frequenz der automatischen Garbage Collection durch die SSD-Controller von Samsung. Das mag bei anderen SSDs jedoch anders sein.

Aus meiner Sicht ist es daher empfehlenswert, vor dem produktiven Einsatz sicherzustellen, dass der fstrim-Befehl im angestrebten Raid-Verbund funktioniert.

Warnung von Red Hat vor dem Einsatz von SW-Raid-5 mit SSDs

Wie eine Recherche im Internet ergab, warnt(e) Red Hat vor dem Einsatz u.a. von Raid-5 für SSDs; s.

https://access.redhat.com/ documentation/ en-US/Red_Hat_ Enterprise_Linux/ 6/html/ Storage_Administration_Guide/ ch-ssd.html

https://access.redhat.com/ documentation/ en-US/ Red_Hat_Enterprise_Linux/ 7/html/ Storage_Administration_Guide/ ch-ssd.html

Zitat:

Red Hat also warns that software RAID levels 1, 4, 5, and 6 are not recommended for use on SSDs. During the initialization stage of these RAID levels, some RAID management utilities (such as mdadm) write to all of the blocks on the storage device to ensure that checksums operate properly. This will cause the performance of the SSD to degrade quickly.

Schlechte Schreibperformance von Raid-5 bei kleinen Datenpaketen?

Das anderes Argument gegen Raid-5 war die meist schlechte Performance für Random I/O-Bereich und dies vor allem bei einer kleinen Größe der stückweise zu schreibenden Datenpakete. Write-Caches einiger echter HW-Raid-Controller haben hier geholfen; der Einsatz eines Schreibpuffers ist aber – wie oben erläutert – auch mit Risiken verbunden; Batteriepuffer waren für dedizierte HW-Raid-Controller daher meist obligatorisch.

Eine vergleichsweise schlechte Performance attestieren viele Admins Raid-5-Arrays auch heute noch – selbst bei Einsatz von SSDs. Ich bin hier etwas vorsichtiger. Weder Raid-10 noch Raid-5 sind bei kleinen Datenpaketgrößen besonders schnell. Die Performance hängt aber auch stark von anderen Faktoren ab; u.a. von Raid-Array-Parametern, wie der Chunk Size, aber auch dem Lastprofil.

Um das Thema Performance Raid-5 vs. Raid-10 von SW-Raids unter Linux kümmere ich mich deshalb genauer in einem der kommenden Artikel. Bzgl. konkreter Zahlen muss ich den Leser deshalb noch vertrösten.

Fazit

Legt man die obigen Erfahrungen zugrunde, so läuft die Entscheidung zwischen Raid-10 und Raid-5 im Normalbetrieb auf

  • eine Abwägung von Performance-Vor- und -Nachteilen,
  • eine Bewertung des effektiv verfügbaren Plattenplatzes
  • und eine Bewertung des SSD-Verschleißes, der im Fall der Resynchronisation eines Degraded Raid-5-Arrays auftritt,

hinaus.

Man sollte ein Raid-5-Array aus meiner Sicht jedenfalls nicht ohne eine Bitmap betreiben. Das führt aber wieder zu zusätzlichen Schreibprozessen. Selbst wenn man die auf eine Platte außerhalb des Raid-Arrays verlagert, muss man den Overhead und den resultierenden Durchsatz testen. Diese separate Platte muss hinreichend schnell ansprechbar sein und sollte nicht die native und hohe Schreibperformance eines Raid-5-Arrays ohne Bitmap beeinträchtigen. Sequentielle Schreibraten von > 1GB/sec sind auf einem Raid-5-Array mit Consumer-SSDs durchaus möglich; auch wenn die Menge der Bitmap-Daten im Vergleich zur Menge der Realdaten relativ klein sein sollte – die Schreibrate dafür muss zum Gesamtdurchsatz passen. Man würde vermuten, dass das besonders bei kleinen Datenpaketen problematisch wird.

Hinzu kommen potentielle Performance-Einbußen durch ein fehlendes Weiterreichen des fstrim-Befehls an Filesysteme auf Raid-5-Arrays. Das relativiert die Performance-Vorteile beim Lesen, die ein Raid-5-System gegenüber einem Raid-10-System für sequentielles Schreiben aufweist, etwas. Zudem gilt:

Wer aus irgendwelchen Gründen eine verbesserte Lese-Performance unter Raid 10 anstrebt, kann auch mal das Far-Layout oder ein Near/Far-Layout des Raid10-Arrays ausprobieren. Das Far-Layout geht allerdings zu Lasten der Schreibperformance – und dies besonderes für Random I/O. Aber Raid-5 ist gerade für häufigen Random I/O kleinerer zu schreibender Datenmengen noch weniger performant.

Insgesamt erschien/erscheint mir das Aufsetzen eines Raid-5-Arrays doch ein
ziemlicher Balanceakt zu sein. Ich befasse mich in den kommenden Artikeln daher zuerst mit Raid-10-Arrays.

Ausblick

Im nächsten Beitrag
SSD Raid Arrays unter Linux – VIII – Setup von Raid-10-Arrays mit mdadm
gehe ich endlich ein wenig mehr auf praktische Schritte ein. Diskutiert wird dort die Anlage und Parametrierung eines SW-Raid-10-Arrays mit Hilfe von mdadm.

Interessante Links

https://www.thomas-krenn.com/ de/wiki/ ATA_Trim

https://wiki.debian.org/ SSDOptimization

http://cesg.tamu.edu/ wp-content/ uploads/2012/02/ hotstorage13.pdf

https://en.wikipedia.org/ wiki/Write_amplification

http://www.webhostingtalk.com/ showthread.php?t=1457939

http://serverfault.com/questions/ 513909/ what-are-the-main-points-to-avoid-raid5-with-ssd

https://lowendtalk.com/ discussion/ 10000/ don-t-build-ssd-in-raid5

https://www.reddit.com/ r/sysadmin/ comments/ 3m9req/ how_would_you_configure_ an_mdadm_raid_5_w_ssds/? st=ivpbg325&sh=a09d50fd

http://researchweb.watson.ibm.com/ haifa/ conferences/ systor2011/ present/ session5_talk2_systor2011.pdf

http://superuser.com/ questions/ 461506/ intel-matrix-storage-manager-vs-linux-software-raid

Bzgl. der grundsätzlichen Einstellung von LVMs und des Absetzens von TRIM-Anweisungen im Kontext von LVM-Operationen siehe etwa:
http://blog.neutrino.es/ 2013/ howto-properly-activate-trim-for-your-ssd-on-linux-fstrim-lvm-and-dmcrypt/

Near/Far-Layout füe Linux SW-Raid-10
http://www.ilsistemista.net/ index.php/ linux-a-unix/ 35-linux-software-raid-10-layouts-performance-near-far-and-offset-benchmark-analysis.html?start=1

Bitmaps
http://www.tutorialspoint.com/ unix_commands/ mdadm.htm