Ubuntu: Probleme mit vollen Boot-Partitionen

Auf immer mehr meiner Ubuntu-Server-Installationen mit automatischen täglichen Updates bin ich in letzter Zeit auf das Problem voller Boot-Partitionen gestoßen. Aus historischen Gründen richtet der Ubuntu-Installer standardmäßig eine eigene Boot-Partition für die Kernel-Dateien ein, obwohl dies in den meisten Fällen vollkommen überflüssig ist. Im Boot-Verzeichnis landet bei jedem Kernel-Update die gerade neueste Kernel-Version samt diverser Zusatzdateien.

Pro Kernel-Version beträgt der Platzbedarf unter Ubuntu 16.04 ca. 50 MByte, wobei die Initrd-Datei mit ca. 36 MByte der bei weitem wichtigste Faktor ist. Ubuntu 14.04 war hier noch sparsamer, dort fand man mit ca. 25 MByte pro Kernel das Auslangen (Initrd-Datei mit 20 MByte).

Ganz egal, wie groß die Boot-Partition ist: ohne Aufräumarbeiten läuft sie früher oder später voll. Das führt dazu, dass Kernel-Updates nicht mehr (richtig) installiert werden können. Mit etwas Pech hängt Ubuntu beim nächsten Reboot. Bei einer lokalen Maschine kann man dann im Grub-Menü einen älteren Kernel auswählen, damit booten und Aufräumarbeiten durchführen. Bei einem Server ist das aber viel schwieriger.

Update 23.1.2017 15:10: Bessere Lösung mit Unattended-Upgrade::Remove-Unused-Dependencies "true" dokumentiert.

Analyse

df -h listet alle echten und virtuellen Dateisysteme auf. Die folgenden Daten stammen von einem Ubuntu-Server in einer virtuellen Maschine (KVM) mit einem nur 20 GByte großem Disk-Image. Spannend sind die Zeilen für das Root-Dateisystem (45% voll, d.h. alles OK) und für die Boot-Partition (100% voll, Vorsicht!):

df -h

Dateisystem             Größe Benutzt Verf. Verw% Eingehängt auf
udev                     477M       0  477M    0% /dev
tmpfs                    100M     11M   89M   11% /run
/dev/mapper/ub--vg-root   19G    7,8G  9,7G   45% /
tmpfs                    497M       0  497M    0% /dev/shm
tmpfs                    5,0M       0  5,0M    0% /run/lock
tmpfs                    497M       0  497M    0% /sys/fs/cgroup
/dev/vda1                236M    224M     0  100% /boot
tmpfs                    100M       0  100M    0% /run/user/1000

Die Boot-Partition wurde bei einem der letzten Kernel-Updates vollgeschrieben. Wenn Sie jetzt einen Reboot durchführen und ein wenig Pech haben, scheitert der Neustart!

Prävention

Es gibt viele verschiedene Wege, dem Problem aus dem Weg zu gehen:

  • Keine automatisches Update: Wenn Sie Updates manuell durchführen, können Sie die Fehlermeldungen über eine volle /boot-Partition nicht übersehen. Aber je mehr Server Sie administrieren, desto nützlicher sind automatische Updates.

  • Ausreichend große Boot-Partitionen: Eine größere Boot-Partition mindert die Häufigkeit des Problems natürlich, aber eben nicht dauerhaft. So wie auch die größte Festplatte irgendwann voll ist, gilt dies auch für die Boot-Partition ;-) Und es gibt noch ein kleines Problem: Sie können diesen Tipp nur beherzigen, wenn Sie eine Neuinstallation durchführen … Wie dem auch sei: 1 GByte muss heute als Minimalgröße für die Boot-Partition gelten.

  • Gar keine Boot-Partition: Bevor GRUB 2 sich durchgesetzt hat, war eine eigene Boot-Partitionen bei Server-Installationen eine Selbstverständlichkeit. GRUB 1 kam weder mit Software RAID noch mit LVM und (ohne Patches) nicht einmal mit ext4-Dateisystemen zurecht. Also speicherte man die Boot-Dateien in einer Partition ohne derartige Spezialitäten. GRUB 2 hat mit all dem überhaupt keine Probleme. Zwar gibt es auch heute noch Konfigurationsvarianten, bei denen eine eigene Boot-Partition notwendig oder zumindest empfehlenswert ist, bei typischen Server-Installation inkl. Software-RAID und LVM trifft dies aber nicht zu. Insofern spricht nichts dagegen, auf eine eigene Boot-Partition zu verzichten. Die Boot-Dateien landen dann einfach im /boot-Verzeichnis in der Systempartition. Da die Systempartition in aller Regel viel größer ist als die Boot-Partition, ist das Disk-full-Problem viel unwahrscheinlicher. Wie beim vorigen Tipp lässt sich auch dieser Ratschlag nur bei Neuinstallationen realisieren.

  • apt-get autoremove regelmäßig ausführen: Die vermutlich beste zweitbeste Lösung besteht darin, einmal wöchentlich per Cron apt-get autoremove auszuführen. Dieses Kommando entfernt nicht mehr benötigte Pakete. Dazu zählen auch nicht benötigte Kernel-Pakete. apt-get auto-remove rührt nie den aktuell laufenden Kernel an und belässt immer die aktuellsten zwei Kernel-Versionen. Nach apt-get autoremove gibt es also auf jeden Fall noch zwei, häufig sogar noch drei Kernel.

  • Remove-Unused-Dependencies: Die beste Lösung findet man, wenn man schlaue Twitter-Follower hat. Die Datei /etc/apt/apt.conf.d/50unattended-upgrades sieht die Option Remove-Unused-Dependencies vor. Wenn diese auf true gesetzt wird, kümmert sich unattended-upgrade selbst um apt-get autoremvoe und entfernt alle überflüssigen Pakete selbst. Stellt sich nur die Frage, warum die Option nicht standardmäßig aktiv ist.

# in /etc/apt/apt.conf.d/50unattended-upgrades ändern
...
// Do automatic removal of new unused dependencies after the
// upgrade (equivalent to apt-get autoremove)
Unattended-Upgrade::Remove-Unused-Dependencies "true";

Krisenintervention

Wenn df -h /boot 100% liefert, die Boot-Partition also schon voll ist, ist Vorsicht angebracht. In diesem Fall sollten Sie zuerst einmal Aufräumarbeiten mit apt-get autoremove durchführen. Wenn dabei Fehler auftreten (filesystem full), wiederholen Sie das Kommando.

Selbst nachdem Sie nun wieder Platz in der Boot-Partition geschaffen haben, besteht weiterhin die Gefahr, dass der zuletzt installierte Kernel nicht korrekt bzw. nicht vollständig installiert wurde. Testen Sie zuerst, welche Kernel-Version aktuell läuft:

uname -r
4.4.0-47-generic

Die Pakete dieser Kernel-Version dürfen Sie auf keinen Fall anrühren!

Dann testen Sie, welche Kernel-Versionen sich aktuell in /boot befinden:

ls /boot/vmlinuz-4.4.0-*
  /boot/vmlinuz-4.4.0-47-generic  
  /boot/vmlinuz-4.4.0-57-generic  
  /boot/vmlinuz-4.4.0-59-generic

Alle Kernel-Versionen mit Ausnahme der aktuell laufenden Version (in diesem Beispiel 4.4.0-47) installieren Sie nun neu. Dabei wird die jeweilige Initrd-Datei neu generiert und die Grub-Konfigurationsdatei neu geschrieben.

apt-get install --reinstall linux-image-4.4.0-57-generic
  ...
  update-initramfs: Generating /boot/initrd.img-4.4.0-57-generic
  ...
  Grub-Konfigurationsdatei wird generiert
  ...

apt-get install --reinstall linux-image-4.4.0-59-generic
  ...
  update-initramfs: Generating /boot/initrd.img-4.4.0-59-generic
  ...
  Grub-Konfigurationsdatei wird generiert
  ...

Erst wenn das ohne Fehlermeldungen gelungen ist, können Sie mit reboot eine Neuinstallation wagen.

19 Gedanken zu „Ubuntu: Probleme mit vollen Boot-Partitionen“

  1. bist du dir 100% sicher, dass „apt-get autoremove“ alte kernel entfernt? die manpage sagt nämlich etwas anderes: „autoremove wird benutzt, um Pakete zu entfernen, die automatisch installiert wurden, um Abhängigkeiten für andere Pakete zu erfüllen und die nicht mehr benötigt werden.“ außerdem meine ich mich zu erinnern dass bei den alten LTS-versionen (die dazwischen nutz ich nich) ein explizites suchen unterhalb von /boot notwendig war um altversionen zu identifizieren und gezielt entfernen zu können, was in einem hinreichend komplexen oneliner endete. erst seit 16.04 lts genügt IMHO ein „apt autoremove“ (nicht apt-get!) für diesen job.

    1. Ich bin mir sicher :-)

      apt-get autoremove entfernt Pakete ohne Abhängigkeiten, und das trifft auf die Kernel-Pakete zu. Da sind umgekehrt Regeln notwendig, damit autoremove nicht zu viel entfernt.

      Ob apt oder apt-get spielt keine Rolle. apt autoremove funktioniert genauso. Seit Ubuntu 16.04 ist eigentlich apt das empfohlene Kommando, aber aus langjähriger Tradition verwende ich weiterhin oft apt-get.

      1. Ich kann Michaels Ausführungen nur bestätigen; ich verwende ständig apt-get autoremove für alte Kernel.

      2. Ich habe wie empfohlen apt-get autoremove bei meinem 14.04.Ubutu versucht und er halte die Meldungen:
        W: Es wird keine Sperre für schreibgeschützte Sperrdatei /var/lib/dpkg/lock verwendet.
        E: Schreiben nach /var/cache/apt/ nicht möglich.
        E: Die Paketliste oder die Statusdatei konnte nicht eingelesen werden.
        Kann mir vielleicht jemand helfen?

  2. Das ist echt viel. Entweder ich verstehe gerade das Problem nicht, oder meine Distro macht es anders. Ich habe nur 100mb /boot-Partition mit 3 Kerneln die mittlerweile drin sind. Das originale 4.4 ist 4,5 MB groß, die beiden kompilierten 4.9er jeweils 7,6 MB groß. Ich habe rund 50MB frei für 3 weitere Kernel. Das Ubuntu Kernel 50MB groß ist, überrascht mich jetzt wirklich.

    1. Es gibt hier in der Tat distributionsspezifische Unterschiede. Fedora, RHEL, CentOS & Co. kümmern sich z.B. automatisch darum, überflüssige Kernel zu entfernen.

      Was die Kernel-Größe betrifft: Der Kernel an sich ist ja nicht das Problem, es sind die Zusatzdateien, speziell das Initrd-System, das inzwischen verrückt groß ist. Bei Ubuntu ist der Platzbedarf extrem, aber auch CentOS 7 genehmigt sich z.B. pro Kernel rund 40 MByte (dort werden gleich zwei verschiedene Initrd-Versionen installiert), Fedora 25 rund 30 MByte, openSUSE Leap 42.2 ca. 25 MByte pro Kernel-Version.

  3. Moin,

    also unbeaufsichtigte Updates sind wohl eher Geschmackssache, würde ich nie machen – aber jedem das seine und das nur am Rande.

    Viel wichtiger ist, dass bei Prävention ein sehr wichtiger Punkt fehlt und das wundert mich doch wenn du mehrere Server-Installationen im Einsatz hast -> Monitoring, ohne sowas kann man doch nicht leben!? Da wäre dann zur Neige gehender Speicherplatz nur einer von vielen Aspekten, bei denen du rechtzeitig gewarnt wirst bevor kritische Werte erreicht werden.

    Solltest du sowas echt nicht im Einsatz haben, kann ich dir das nur dringendst empfehlen…

    1. Ich spiele seit bald 13 Jahren auf allen meinen Servern (fast dreistellig) jede Nacht mit cron-apt die aktuellsten Updates ein.
      Es gab nur einmal Probleme damit (in 2016) – wenn ich das nicht täte, hätte ich ja gar keine Zeit mehr für Projekte.

      Alte kernel entfernt bei mir ein Script, welches am WE läuft.
      Es nimmt ganz stumpf den output von „dlocate -k”, löscht die meta-Pakete raus, die aktuellen Kernel/Header Pakete sowie die aktuell laufenden (uname -r hilft hierbei).

  4. Also erstmal richtet der Installer keine Bootpartition ein, wenn man das nicht selber auswählt. Der df-Ausgabe hier nach handelt es sich um ein verschlüsseltes System (auf einem Server eher unwahrscheinlich) oder ein LVM. Dort wiederum wäre die Aussage richtig, der Beitrag lässt es aber so aussehen, alsob immer eine Bootpartition vom Installer erstellt werden würde.

    Außerdem stimmt auch der Hinweis, dass ein System ohne Bootpartition nur mit einer Neuinstallation zu machen wäre nicht. Das Bootverzeichnis wird einfach ins Wurzelverzeichnis kopiert, die fstab angepasst und die GRUB-Konfiguration aktualisiert…

    1. OK, die Boot-Partition fällt nicht vom Himmel. Prinzipiell stimmt das, aber eben nur prinzipiell :-)

      Wenn ich bei einer Server-Installation die Partitionierung nicht manuell erledige, sondern einfach ‚Geführt / vollständige Festplatte verwenden‘ auswähle (egal, ob mit oder ohne LVM), bekomme ich die Boot-Partition schon. Und genau das mache ich halt‘ meistens, wenn ich Ubuntu in einer virtuellen Maschine einrichte. (Ich spreche hier immer nur von der Server-Version.) Und wenn ich einen Root-Server bei Hetzner, in der Cloud etc. einrichte, bekomme ich standardmäßig auch eine Boot-Partition, und ich muss mich in der Regel schon intensiv mit der Konfiguration auseinandersetzen, wenn ich das nicht will.

      Ad boot-Verzeichnis in die Systempartition verschieben: Ja, natürlich ist es möglich, aber der Platz der Boot-Partition lässt sich danach nur noch schwer nutzen, und beim Umstellen muss man höllisch aufpassen, damit GRUB kapiert, wo /boot jetzt ist und beim nächsten Mal brav wieder bootet …

  5. Hallo,

    danke das Problem mit voller /boot-Part. kenne ich.
    Leider funktioniert das autoremove nicht, wenn noch zusätzliche die Linux-Header-Dateien benötigt werden (z.B. wegen Virtualbox – vagrant). Diese mussten von mir immer händisch nachinstalliert werden (warum auch immer?). Leider läuft dann auch die Inode-Grenze aus. Als ich das zum ersten mal hatte, war ich verblüfft. Keinen Platz aber hatte noch 40% Kapazität. Ein df -i hilft dann.

  6. Unter CentOS gibt’s da ein praktisches Tool, um sowas zu vermeiden.

    package-cleanup –oldkernels –count=1

    Und dann /etc/yum.conf editieren, um die maximale Kernelanzahl zu definieren. Minimum ist 2.
    Gibt’s da nix Vergleichbares unter Ubuntu?

    1. Vergleichbar ist:

      # Datei /etc/apt/apt.conf.d/50unattended-upgrades
      Unattended-Upgrade::Remove-Unused-Dependencies "true";
      ...
      

      Man muss die Einstellung nur finden :-)

  7. Meine boot-Partition ist mit 150MB leider viel zu klein. Ich hatte diese Grössenempfehlung irgendwo gelesen und als Ahnungsloser so umgesetzt.
    Wie kann ich denn aus der boot-Partition eine /boot-Verzeichnis auf der System-Partition machen? (kein uefi)
    Also erstmal ein /boot2 anlegen, alles in /boot zippen und in /boot2 auspacken.
    Dann /boot zu /boot.bak umbenennen und /boot2 zu /boot.
    Sodann? grub-install oder dpkg-reconfigure grub-pc?

    1. OHNE GEWÄHR!!! (Ich habe es gerade in einer virtuellen Maschine getestet, aber wenn es bei Ihnen nicht klappt: Ihr Pech …)

      Alles mit sudo:

      cp -a /boot /new-boot
      umount /boot
      rmdir /boot
      mv /new-boot /boot
      update-grub
      

      Außerdem muss der /boot-Eintrag aus /etc/fstab entfernt werden. Danach hoffen, dass alles gut geht, und reboot :-)

      1. Tut update-grub denn den bootsector mit der neuen Info updaten? Oder nur eine neue bootconfig schreiben?
        Mir ist nicht klar was INSTALL_DEVICE bei grub-install ist. Ist das die Partition mit /boot (/dev/sdb5) oder der Bootloader auf /dev/sdb1? Oder die ganze Platte /dev/sdb? Wobei letzteres eigentlich nicht sein kann, denn der Bootsektor und die Boot-Partition mit /boot müssen ja nicht auf der selben Platte liegen.

        1. update-grub ist ein Mini-Script, das grub-mkconfig -o /boot/grub/grub.cfg ausführt. Sie haben recht mit Ihrer Frage, eigentlich wird damit nur /boot/grub/grub.cfg aktualisiert. Aber wie findet GRUB beim Rechnerstart die neue Konfigurationsdatei? Diese befindet sich jetzt ja in einer anderen Partition (in der Systempartition, nicht mehr in der separaten Boot-Partition).

          Konsequenterweise müsste somit nach update-grub noch ein Kommando ausgeführt werden:

          • Für BIOS-Systeme, GRUB im MBR: grub-install /dev/sda
          • Für EFI-Systeme, GRUB in der EFI-Partition: einfach nur grub-install

          Die Frage ist, warum es bei meinem Test (VirtualBox, also BIOS) auch ohne grub-install funktioniert hat.

          1. Es gibt noch einen dritten Fall: kein MBR, sondern GPT, Grub in einer bios_grub-Partition, aber gebootet wird nicht über UEFI.

Kommentare sind geschlossen.