{"id":2705,"date":"2021-01-06T08:00:00","date_gmt":"2021-01-06T07:00:00","guid":{"rendered":"https:\/\/www.my-it-brain.de\/wordpress\/?p=2705"},"modified":"2020-12-31T13:58:38","modified_gmt":"2020-12-31T12:58:38","slug":"backup-und-restore-im-kanboard-container-land","status":"publish","type":"post","link":"https:\/\/www.my-it-brain.de\/wordpress\/backup-und-restore-im-kanboard-container-land\/","title":{"rendered":"Backup und Restore im Kanboard-Container-Land"},"content":{"rendered":"\n<p>In &#8222;<a href=\"https:\/\/www.my-it-brain.de\/wordpress\/?p=2685\">Kanboard im Container<\/a>&#8220; habe ich einen Pod ins Leben gerufen, welcher die Anwendung Kanboard und eine dazugeh\u00f6rige Postgresql-Datenbank mittels Container bereitstellt. Backup und Restore zu konfigurieren und zu testen, habe ich letztes Wochenende nicht mehr geschafft. Dies hole ich in diesem Artikel nach.<\/p>\n\n\n\n<p>Da die Container selbst zustandslos sind, interessieren mich nur die persistent gespeicherten Daten, welche au\u00dferhalb der Container im Dateisystem des Hosts gespeichert werden.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"umgebung\">Umgebung<\/h2>\n\n\n\n<p>Auf einer virtuellen Maschine mit dem Gastbetriebssystem RHEL 8 l\u00e4uft ein <code>podman<\/code>-Pod namens <em>kanboardpod<\/em>. Dieser Pod beinhaltet neben dem Infrastruktur-Container, einen Kanboard-Container namens <em>kanboard<\/em> und einen Postgresql-Container namens <em>pgsql_db<\/em>.<\/p>\n\n\n\n<p>Die persistenten Daten des Kanboard-Containers werden in den Volumes <em>kanboard_data<\/em> und <em>kanboard_plugins<\/em> gespeichert. Die Datenbank-Dateien der Postgresql-DB liegen im Volume <em>pgsql_data<\/em>.<\/p>\n\n\n\n<p>Die Namen des Pods und der Container sind hilfreich, da die Container dar\u00fcber referenziert werden k\u00f6nnen. So muss man nicht mit den sperrigen IDs hantieren.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"backup\">Backup<\/h2>\n\n\n\n<p><strong>Kein Restore ohne Backup! Kein Backup, kein Mitleid!<\/strong><\/p>\n\n\n\n<p>Ich habe im Folgenden beschriebe Ans\u00e4tze f\u00fcr ein Backup. Wenn ihr noch weitere habt, freue ich mich \u00fcber eure Eingaben.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Ansatz 1: Backup auf Dateiebene &#8212; verworfen<\/h3>\n\n\n\n<p>Dieser Ansatz liegt nahe und ist einfach umzusetzen.<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Container stoppen<\/li><li>Verzeichnisse im Dateisystem sichern<\/li><li>Container wieder starten<\/li><\/ol>\n\n\n\n<p>F\u00fcr meinen konkreten Anwendungsfall w\u00e4re dies auch ausreichend. Einen Dienst f\u00fcr die Dauer einer Datensicherung komplett stoppen zu m\u00fcssen, ist jedoch nicht ideal. Daher schaue ich nach weiteren M\u00f6glichkeiten.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Ansatz 2: DB-Dump und Datei-Backup &#8212; Praktikabel aber m\u00f6glicherweise inkonsistent.<\/h3>\n\n\n\n<p>Bei diesem Ansatz bleibt die Anwendung w\u00e4hrend der Datensicherung verf\u00fcgbar. W\u00e4hrend das Volume <em>kanboard_data<\/em> auf Dateiebene mittels <code>tar<\/code> gesichert wird, wird die Datenbank mittels <code>pg_dump<\/code> aus dem Container heraus gesichert. Das Backup-Skript sieht wie folgt aus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#!\/bin\/bash\nkanboard_data=$(podman volume inspect kanboard_data --format {{.Mountpoint}})\nkanboard_plugins=$(podman volume inspect kanboard_plugins --format {{.Mountpoint}})\ntar czf kanboardfiles.tgz $kanboard_data $kanboard_plugins\npodman exec -t pgsql_db \/usr\/bin\/pg_dump kanboard | gzip &gt; ~\/kanboard.sql.gz<\/code><\/pre>\n\n\n\n<p><strong>Hinweis:<\/strong> Obiger Code-Schnipsel stammt aus der Kategorie Schnell-und-Schmutzig und sollte <strong>nicht<\/strong> in produktiven Umgebungen verwendet werden.<\/p>\n\n\n\n<p>Der DB-Dump wird dabei direkt aus dem Container in mein Home-Verzeichnis geschrieben. Am Ende habe ich zwei unabh\u00e4ngige Dateien, die nun au\u00dferhalb der Container-Umgebung liegen. Da diese jedoch immer noch auf dem gleichen Host liegen, handelt es sich um kein richtiges Backup. Doch ist es nun nicht mehr schwer, sie auf ein anderes, entferntes Medium zu \u00fcbertragen.<\/p>\n\n\n\n<p>Der gr\u00f6\u00dfte Nachteil dieses Ansatzes besteht darin, dass die Konsistenz der Sicherung nicht garantiert ist. Die Datenbank enth\u00e4lt Referenzen in das Dateisystem. Referenzen in der Datenbank und Inhalt des gesicherten Dateisystems m\u00fcssen nicht in jedem Fall zueinander passen, da w\u00e4hrend der Sicherung weiter in der Anwendung gearbeitet werden kann.<\/p>\n\n\n\n<p>Nun kann man nat\u00fcrlich vor der Sicherung den Container <em>kanboard<\/em> stoppen und anschlie\u00dfend wieder starten. Damit erh\u00e4lt man eine konsistente Sicherung zu dem Preis, dass die Anwendung tempor\u00e4r nicht verf\u00fcgbar ist. Damit unterscheidet sich der Ansatz gegen\u00fcber Ansatz 1 nur noch darin, dass der Container <em>pgsql_db<\/em> online bleibt und man die DB mit <code>pg_dump<\/code> sichert, statt eine Sicherung auf Dateisystemebene zu machen.<\/p>\n\n\n\n<p>Sch\u00f6n ist das nicht, doch mache ich es meiner Umgebung genau so.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Ansatz 3: Backup auf Basis eines konsistenten Dateisystem-Snapshots<\/h3>\n\n\n\n<p>Dies ist in meinen Augen der vern\u00fcnftigste Ansatz.<\/p>\n\n\n\n<p>Die persistenten Daten der Container liegen in einem Dateisystem. Unterst\u00fctzt dieses Dateisystem <a href=\"https:\/\/de.wikipedia.org\/wiki\/Schnappschuss_(Informationstechnik)\">Snapshots<\/a>, k\u00f6nnen diese genutzt werden, um die Dateisysteminhalte zum Zeitpunkt des Snapshots auf das Backup-Medium zu \u00fcbertragen und den Snapshot anschlie\u00dfend wieder zu entfernen. Anwendung und Datenbank k\u00f6nnen bei diesem Verfahren w\u00e4hrend der Sicherung weiterlaufen.<\/p>\n\n\n\n<p>Das so erstellte Datenbank-Backup befindet sich allerdings in einem Zustand, als w\u00e4re die Datenbank unsauber beendet worden. Nach einem Restore werden demnach die WAL-Logs ben\u00f6tigt (siehe <a href=\"https:\/\/www.postgresql.org\/docs\/9.6\/backup-file.html\">PostgreSQL 9.6.20 Documentation: 25.2. File System Level Backup<\/a>).<\/p>\n\n\n\n<p>Ich habe mich gegen diesen Ansatz entschieden, da mir in meiner Test-Umgebung noch die Erfahrung mit Dateisystem-Snapshots fehlt. Dies werde ich evtl. zu einem sp\u00e4teren Zeitpunkt unter die Lupe nehmen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Restore<\/h2>\n\n\n\n<p>Ich habe mich f\u00fcr den Ansatz 2 entschieden. Damit habe ich folgende zwei Dateien:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>kanboard.tgz &#8211; Enth\u00e4lt die persistenten Daten des Kanboards<\/li><li>kanboard.sql.gz &#8211; Enth\u00e4lt den Dump der Kanboard-Datenbank<\/li><\/ul>\n\n\n\n<p>Das <code>tar<\/code>-Archiv wird extrahiert und fertig. Um den DB-Dump mit dem Werkzeug <code>pg_restore<\/code> wieder einspielen zu k\u00f6nnen, muss dieser zuvor in ein Volume kopiert werden, das innerhalb des Postgresql-Containers zur Verf\u00fcgung steht. Anschlie\u00dfend kann die Datenbank mit folgendem Befehl wiederhergestellt werden:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># pg_restore -C -d kanboard kanboard.sql<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Fazit<\/h2>\n\n\n\n<p>Grunds\u00e4tzlich habe ich Ziel Nummer 5 &#8222;Backup und Restore&#8220; ebenfalls erreicht.<\/p>\n\n\n\n<p>Der Restore erfordert noch einiges an Handarbeit und ist etwas fummelig. Soetwas m\u00f6chte man in einer angespannten Situation nicht gerne haben. Hier ist noch etwas Feinschliff n\u00f6tig.<\/p>\n\n\n\n<p>Dar\u00fcber hinaus kann ich mir vorstellen auch noch einen automatisierten Restore-Test zu etablieren, welcher pr\u00fcft, ob sich ein erstellter DB-Dump auch wieder herstellen l\u00e4sst. Das ist dann aber sicher ein eigenes Wochenendprojekt. Und n\u00e4chstes Wochenende mache ich mal frei.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In &#8222;Kanboard im Container&#8220; habe ich einen Pod ins Leben gerufen, welcher die Anwendung Kanboard und eine dazugeh\u00f6rige Postgresql-Datenbank mittels Container bereitstellt. Backup und Restore zu konfigurieren und zu testen, habe ich letztes Wochenende nicht mehr geschafft. Dies hole ich in diesem Artikel nach. Da die Container selbst zustandslos sind, interessieren mich nur die persistent<span class=\"continue-reading\"> <a href=\"https:\/\/www.my-it-brain.de\/wordpress\/backup-und-restore-im-kanboard-container-land\/\">[Weiterlesen&#8230;]<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_metis_text_type":"","_metis_text_length":0,"_post_count":0,"footnotes":""},"categories":[57],"tags":[517,430,305],"class_list":["post-2705","post","type-post","status-publish","format-standard","hentry","category-wochenend-projekte","tag-container","tag-osbn","tag-planet"],"_links":{"self":[{"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts\/2705","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/comments?post=2705"}],"version-history":[{"count":4,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts\/2705\/revisions"}],"predecessor-version":[{"id":2712,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/posts\/2705\/revisions\/2712"}],"wp:attachment":[{"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/media?parent=2705"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/categories?post=2705"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.my-it-brain.de\/wordpress\/wp-json\/wp\/v2\/tags?post=2705"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}