Ubuntuの古いカーネルを削除して/bootを空ける方法
/bootが満杯になるとaptが「No space left on device」で停止します。起動中のカーネルを確認し、安全に古いlinux-imageパッケージを削除する手順を解説します。
/boot が古いカーネルでいっぱいになると apt が動作しなくなる理由
Ubuntu では、カーネルを更新するたびに新しいファイル一式が /boot に書き込まれ、以前のファイルも残ります。そのため、小容量の /boot パーティションがいっぱいになり、apt がインストールを完了できなくなります。修復は 2 つの手順で行います。まず、システム上のどのパッケージがカーネルで、現在どのカーネルで起動しているかを確認します。次に、残りを apt autoremove --purge で削除します。
順序が重要です。実行中のカーネルは削除してはいけないパッケージです。また、apt をまったく実行できない状態になっている場合もあります。最初に診断してください。
実際に発生する障害の状態
カーネルのバージョンをインストールすると、/boot に 2 つの大きなファイルが作成されます。圧縮カーネル(vmlinuz-<version>)と initramfs(初期 RAM ファイルシステム、initrd.img-<version>)です。initramfs は、実際の root をマウントする前にカーネルが展開する小さなアーカイブです。initramfs はインストール時にマシン上で構築されるため、インストールにはダウンロード帯域幅だけでなく、空き容量も必要です。空き容量がないと構築に失敗し、パッケージのインストールも失敗します。
update-initramfs: Generating /boot/initrd.img-6.8.0-64-generic
gzip: stdout: No space left on device
E: mkinitramfs failure gzip 1
update-initramfs: failed for /boot/initrd.img-6.8.0-64-generic with 1.
dpkg: error processing package linux-image-6.8.0-64-generic (--configure):
installed linux-image-6.8.0-64-generic package post-installation script subprocess returned error exit status 1バージョン文字列は環境によって異なります。圧縮方式の名前は /etc/initramfs-tools/initramfs.conf 内の COMPRESS= から取得されます。そのため、新しいイメージでは zstd と表示され、古いイメージでは gzip と表示される場合があります。この問題を示す行は No space left on device と、その下にある dpkg: error processing package の行です。
その後、パッケージは設定途中の状態になります。以降の apt の実行では、毎回このパッケージの設定が再試行され、同じように失敗して E: Sub-process /usr/bin/dpkg returned an error code (1) で終了します。ディスク容量の不足以外で重要なのはこの点です。unattended-upgrades はタイマーに従って実行され、同じエラーに遭遇して停止します。サーバーは正常に見えても、セキュリティパッチの適用が静かに停止します。また、無関係なパッケージのインストールを試みても同じ行で失敗し、その時点で追加しようとしていたものが原因だと思われます。そのため、Ubuntu で失敗する Tailscale のインストールも、まず apt のエラーとして読む価値があります。ここまで到達する前に apt update が失敗する場合は別の問題であり、deb822 sources への移行後に発生する重複エントリが原因であることがよくあります。
/boot が独立したパーティションか確認する
削除する前に、実際にどの容量を空けられるのかを確認します。
findmnt /boot
findmnt -T /boot
df -h /boot /最初のコマンドは、/boot が独立したマウントポイントである場合にだけ行を出力します。2 番目のコマンドは常に出力され、/boot を実際に保持しているファイルシステムの名前を表示します。これらが / と同じファイルシステムを示す場合、/boot は root ファイルシステム上の単なるディレクトリであり、単独で容量を使い切ることはありません。つまり、容量を使い切っているのは root ファイルシステムであり、古いカーネルは複数ある原因の 1 つにすぎません。その場合は sudo apt clean により、/var/cache/apt/archives 配下にダウンロードされた .deb ファイルが削除されるため、容量を空けられます。実際の /boot パーティションがあるマシンでは、キャッシュは別のファイルシステムに存在するため、apt clean を実行してもそこには何も空きません。
次に、比較の基準となる空き容量を確認します。
df -h /boot
ls -lh /boot/vmlinuz-$(uname -r) /boot/initrd.img-$(uname -r)Avail 列の値を、これら 2 つのファイルのサイズと比較します。initrd のほうが大きいファイルです。次回のカーネル更新では、ほぼ同じサイズのファイル 2 つ分の容量が必要になります。そのため、Avail が現在の initrd より小さい場合、次回の更新はすでに失敗します。
実行中の kernel を確認する
uname -r
cat /var/run/reboot-required.pkgsuname -r は、現在メモリ上で実行中の kernel のリリース文字列を表示します。この文字列をどこかに控えてください。このバージョンには必ず手を付けないでください。
2 つ目のファイルは、パッケージが再起動を要求した場合にのみ存在します。このファイルに linux-image の行がある場合、ディスク上には新しい kernel がインストールされていますが、マシンがインストール後に再起動されていないため、まだ使用されていません。可能であれば、削除前に再起動してください。apt は実行中の kernel と最新の kernel を保護します。そのため、古い kernel を実行したまま削除すると、必要以上にもう 1 つのバージョンが保持されます。
カーネルパッケージを一覧表示し、状態を確認する
dpkg --list | grep -E 'linux-(image|modules|headers|tools)' | awk '{print $1, $2}'最初のフィールドは、dpkg の状態コードです。iiはインストールと設定が完了していることを示します。iFはインストール済みですが、設定が途中までしか完了していないことを示します。これは、前述の失敗したアップグレードによって残る状態です。rcは削除済みですが、設定がディスク上に残っていることを示します。/bootの容量は消費せず、安全に purge できます。
2 番目のフィールドは、パッケージの種類を示します。linux-image-6.8.0-64-genericのように名前にバージョンが含まれるものは、特定のカーネルです。linux-image-generic、linux-headers-generic、linux-genericのように名前にバージョンが含まれないものは、メタパッケージです。カーネル本体は含まれていません。最新バージョンのカーネルに依存し、apt upgradeによって新しいカーネルを取り込むことだけが役割です。メタパッケージを削除すると、マシンはカーネル更新を受け取らなくなります。その後も警告は表示されません。
各ファミリーの役割は次のとおりです。linux-image-*には、/bootにある圧縮済みカーネルが格納されます。linux-modules-*とlinux-modules-extra-*には、/lib/modules以下のドライバーが格納されます。linux-headers-*には、/usr/src以下のビルド用ヘッダーが格納されます。つまり、ヘッダーを purge すると root ファイルシステムの容量は解放されますが、/bootの容量は解放されません。/bootパーティションが満杯で困っている場合は、イメージパッケージを探します。
ls -1 /boot/vmlinuz-*
ls -1 /lib/modules/この 2 つの一覧は、互いに対応し、dpkg --listの出力とも一致するはずです。/lib/modulesにあるディレクトリに対応するインストール済みパッケージがない場合、誰かが手作業でファイルを削除した後の残骸です。
apt が保持するカーネルを決める仕組み
apt autoremove は、保護対象と判断したカーネルを削除しません。保護対象には、現在実行中のカーネルが含まれます。保持ポリシーは Ubuntu のリリース間で変更されているため、どこかに記録された数値を信頼せず、自分のマシンで確認してください。
apt-config dump | grep -i -e neverautoremove -e versionedkernel
ls -l /etc/apt/apt.conf.d/01autoremove /etc/apt/apt.conf.d/01autoremove-kernelsAPT::NeverAutoRemove は、apt autoremove が変更しないパッケージ名パターンの一覧です。APT::VersionedKernelPackages は、apt がそもそもバージョン付きカーネルパッケージとして扱う名前の接頭辞一覧です。/etc/apt/apt.conf.d/01autoremove-kernels を生成するリリースでは、カーネルパッケージをインストールするたびに /etc/kernel/postinst.d/apt-auto-removal がそのファイルを書き換えます。そのため、手動で編集しても意味がありません。次回のカーネルインストール時に編集内容が上書きされます。ファイルが存在しないリリースでは、apt が同じ保護を内部的に適用します。いずれの場合も、apt-config dump で現在の環境に適用されているルールを確認できます。その出力が、使用中のリリースに対する正しい答えです。
安全に実行できるクリーンアップ
sudo apt update
sudo apt autoremove --purge --dry-run--dry-runはディスク上の内容を変更せず、実際に実行した場合に削除されるものを正確に表示します。表示された一覧を確認してください。停止すべき点が2つあります。linux-genericやlinux-image-genericのようなメタパッケージが削除対象に含まれている場合、何らかの処理によって自動インストール扱いになっています。削除すると、カーネルの更新が停止します。uname -rの文字列が削除対象に含まれている場合、実行中のカーネルが保護されていません。これは通常起こるべきではないため、先に原因を調査してください。
一覧に問題がなければ、実際に実行します。
sudo apt autoremove --purge
df -h /boot--purgeの方式では、パッケージだけでなく残った設定も削除します。追加で解放される容量はわずかですが、dpkg --listにrc行が蓄積するのを防げるため、次回の監査結果を読みやすくできます。
続いて、ブートメニューが再構築されたことを確認します。カーネルパッケージを削除すると、update-grubが自動的に実行されます。そのため、メニューには現存するファイルだけが参照されているはずです。
sudo grep -o 'vmlinuz-[^ ]*' /boot/grub/grub.cfg | sort -u
ls -1 /boot/vmlinuz-*最初の出力に表示された各バージョンは、2つ目の出力にもすべて表示されていなければなりません。存在しないファイルを指すメニューエントリがあると、正常に動作していたサーバーがGRUBプロンプトで停止する状態になります。これはカーネル更新後に起動しなくなるVPSに至る経路の1つです。この問題は、ここで回避するよりもrescue consoleから修復するほうがはるかに困難です。
apt autoremove で何も削除されないことがある理由
apt autoremove は、自動としてマークされたパッケージだけを削除します。これは、別のパッケージの依存関係としてインストールされたパッケージです。apt install linux-image-6.8.0-40-generic で自分でインストールしたカーネルは手動としてマークされるため、どれだけ古くなっても autoremove の対象にはなりません。
apt-mark showmanual | grep -E '^linux-'その出力に表示されるバージョン付きカーネルは、autoremove から見えません。自分の一覧にあるバージョン文字列を使って、手動として再登録します。
sudo apt-mark auto linux-image-6.8.0-40-generic linux-modules-6.8.0-40-generic
sudo apt autoremove --purge --dry-runメタパッケージは手動としてマークされたままにします。メタパッケージは、自分で指定してインストールしたパッケージなので、手動として扱うのが正しい状態です。
意図的に特定の kernel を削除する
ポリシーで許可されるタイミングを待たずに、特定のバージョンをすぐ削除したい場合があります。イメージパッケージを指定し、apt に残りの処理を任せます。
sudo apt purge linux-image-6.8.0-40-genericapt は処理を実行する前に削除対象の一覧を表示します。linux-modules-extra-* はイメージパッケージに依存しているため、同じトランザクションで削除する必要があります。表示された一覧が実際の安全確認になります。削除対象のバージョンと一緒にメタパッケージまで削除されようとしていないか、この一覧で確認できます。予期しない項目が含まれている場合は n と回答してください。その後、sudo apt autoremove --purge を実行して、不要になったモジュールパッケージとヘッダーパッケージを収集します。
実行中の kernel を削除してはいけない理由
メモリ上にある kernel は、関連ファイルを削除した後も実行され続けるため、最初は問題が起きていないように見えます。問題になるのは、その kernel がまだロードしていない機能です。linux-modules-$(uname -r) を完全削除すると /lib/modules/$(uname -r)/ も削除されるため、次のモジュール読み込みに失敗します。
modprobe: FATAL: Module nf_tables not found in directory /lib/modules/6.8.0-64-genericその時点から firewall の再読み込みに失敗し、この kernel がブート後にまだ扱っていないファイルシステム種別のマウントにも失敗します。一方、/boot/vmlinuz-$(uname -r) も失われるため、ブートメニューに現在実行中の kernel が表示されなくなり、次の再起動で別の環境が起動します。マシンはネットワークトラフィックを処理し続けますが、すでに起動不能です。毎回、uname -r と削除対象の一覧を照合してください。
/boot がいっぱいで apt をまったく実行できない場合
この状態になると、このページを探すことになります。apt autoremove が半端な状態の kernel package の設定を完了するには dpkg が必要です。この処理では initramfs を再構築しますが、空き容量のない /boot が必要になります。手動で一度だけループを断ち切ります。
uname -r
ls -1 /boot/initrd.img-*バージョンが uname -r から返された文字列ではない initrd を1つ選び、そのファイルだけを削除します。
sudo rm /boot/initrd.img-6.8.0-40-generic
sudo apt --fix-broken install
sudo apt autoremove --purge
sudo update-grub各行には理由があります。rm は意図的な例外で、ファイルが存在しない状態でも dpkg がそのファイルは存在すると認識するようにします。空き容量ができたため、apt --fix-broken install が失敗していた設定を完了します。続いて autoremove --purge が、削除したファイルに対応する package を他の古いバージョンとともに削除します。これにより dpkg の状態がディスク上の実体と一致します。update-grub は実際に存在するファイルからメニューを再構築します。rm と update-grub の間に再起動しないでください。この間は、メニューが削除したファイルを参照する可能性があります。dpkg が処理の中断を報告する場合は、sudo dpkg --configure -a が apt --fix-broken install と同じ修復を行います。
dnf システムで同じ作業を行う
VPS が Fedora または Rocky Linux などの RHEL 再構築版で動作している場合、仕組みは逆です。Debian と Ubuntu は apt の autoremove ルールでカーネルを保護し、クリーンアップを利用者に任せるか、unattended-upgrades に実行させます。一方、dnf は installonly_limit という数を適用し、新しいカーネルのインストールによってその数を超える場合、最も古いカーネルを自動的に削除します。現在適用されている値は grep installonly_limit /etc/dnf/dnf.conf と man 5 dnf.conf で確認し、既存の古いカーネルをまとめて削除するには sudo dnf remove --oldinstallonly を実行します。実行中のカーネルも保護されます。2 つのパッケージマネージャーの対応関係については、dnf と apt のコマンド対応を参照してください。
再発を防ぐ
覚えておくことに依存したクリーンアップは、いずれ失敗します。そのため、カーネルをインストールする処理に組み込みます。/etc/apt/apt.conf.d/50unattended-upgradesを開き、次のキーを探します。出荷時のファイルには、これらがコメント行としてすでに含まれています。
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";末尾に同じ設定を追加せず、コメントを解除してください。apt の設定では、キーに対する最後の代入が有効になります。重複した設定があると、ファイル内で値が食い違い、実際に有効な値が分からなくなります。パーサーが最終的に読み取った値を確認し、何も変更しない実行を監視します。
apt-config dump | grep -i 'Unattended-Upgrade::Remove'
sudo unattended-upgrade --dry-run --debug
sudo tail -n 40 /var/log/unattended-upgrades/unattended-upgrades.logログが証拠になります。実行のたびに記録されるため、容量不足で失敗したアップグレードも、マシンのパッチ適用が遅れていることに誰かが気付くよりずっと前に確認できます。この設定の残りの項目については、Ubuntu の自動セキュリティ更新で説明しています。
次のカーネルがインストールされる前に、確認すべき数値が1つあります。これは、このガイドの冒頭で実行したものと同じ2つのコマンドです。
df -h /boot
ls -lh /boot/initrd.img-$(uname -r)Availがそのファイルのサイズを十分に上回っていない場合、次のカーネルのインストールは上記の説明どおりに失敗します。アップグレード中ではなく、今のうちに対処してください。この確認は、他のVPS のディスク健全性チェックと併せても1分ほどで済みます。特にリリースアップグレードの直前には重要です。Ubuntu 24.04 を 26.04 に移行すると、処理の早い段階で新しいカーネルがインストールされ、do-release-upgradeは/bootの空き容量が不足していると処理を続行できないためです。
FAQ
Ubuntu は削除せずに古いカーネルを残すのはなぜですか?
起動に失敗するカーネルしかない場合、選択できるものがなくなるためです。1 つ前のバージョンを残しておけば、不正な更新から provider の rescue console ではなく GRUB メニューで復旧できます。apt はそのため、実行中のカーネルを必ず含む一連のカーネルパッケージを自動削除から保護します。リリース間でポリシーが変更されているため、apt-config dump | grep -i neverautoremove を実行して、使用中のリリースで保護される正確なパターンを確認してください。
apt autoremove --purge は本番サーバーで安全に実行できますか?
dry run の結果を先に確認すれば安全です。何も書き込まない sudo apt autoremove --purge --dry-run を実行し、表示された一覧を確認してください。linux-generic や linux-image-generic などの meta package が含まれている場合は中止してください。これらのいずれかを削除すると、今後のカーネル更新が停止します。uname -r が表示するバージョン文字列が含まれている場合も中止してください。どちらも含まれていなければ、削除対象は古いカーネルと孤立した依存パッケージです。
apt autoremove で何も削除されず、/boot もまだ満杯です。どうすればよいですか?
古いカーネルが manual としてマークされている可能性が非常に高く、autoremove は automatic としてマークされたパッケージだけを処理します。apt-mark showmanual | grep -E '^linux-' を実行してください。そこに表示されたバージョン付きカーネルは、いずれかの時点で手動インストールされています。sudo apt-mark auto linux-image-<version> で automatic に変更してから dry run を再実行するか、sudo apt purge linux-image-<version> でそのバージョンだけを直接 purge してください。
/boot のファイルを手動で削除できますか?
/boot が満杯で、apt が破損したカーネルパッケージを設定できない場合に限り、意図的な一回限りの対応として実行してください。uname -r の出力に含まれないバージョンの initrd.img-<version> ファイルを 1 つ削除し、直ちに sudo apt --fix-broken install、sudo apt autoremove --purge、sudo update-grub を実行してください。これらの後続手順を実行せずにファイルを削除すると、dpkg にはファイルが存在しないパッケージが記録されたままになり、GRUB メニューには存在しないファイルを参照するエントリが残ります。その結果、ミスをした時点ではなく、次回の再起動時にマシンが起動できなくなります。