Ubuntuの古いカーネルを削除して/bootを空ける方法
/bootが満杯でaptが停止したら、実行中のカーネルを確認して安全に削除します。linux-imageの見分け方と、aptが設定を再試行する場合の復旧手順を解説します。
古いカーネルで /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 の release string を表示します。この文字列をどこかにコピーして保存してください。このバージョンは必ず削除してはいけません。
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 のようにバージョンを含まないものは、meta パッケージです。カーネル本体は含まれていません。役割は、最新バージョンのカーネルに依存し、apt upgrade によって新しいカーネルを取り込ませることだけです。meta パッケージを削除すると、マシンはカーネル更新を受け取らなくなります。その後に警告は表示されません。
各ファミリーの役割は次のとおりです。linux-image-* には、/boot にある圧縮済みカーネルが含まれます。linux-modules-* と linux-modules-extra-* には、/lib/modules 配下のドライバーが含まれます。linux-headers-* には、/usr/src にあるビルド用ヘッダーが含まれます。つまり、ヘッダーを purge すると root filesystem の容量は解放されますが、/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 を使って自分でインストールした kernel は手動としてマークされるため、どれだけ古くなっても autoremove によって削除されることはありません。
apt-mark showmanual | grep -E '^linux-'この出力に含まれるバージョン付きの kernel は、autoremove から認識されません。自分で確認した一覧のバージョン文字列を使って、手動インストールとして戻します。
sudo apt-mark auto linux-image-6.8.0-40-generic linux-modules-6.8.0-40-generic
sudo apt autoremove --purge --dry-runmeta パッケージは手動としてマークしたままにします。meta パッケージは、ユーザーが明示的に要求したパッケージであるため、手動として扱う必要があります。
意図的に指定した kernel を削除する
特定のバージョンを、ポリシーで許可される時期を待たずに、すぐ削除したい場合があります。イメージパッケージを指定し、apt に残りの処理を任せます。
sudo apt purge linux-image-6.8.0-40-genericapt は処理を開始する前に削除対象の一覧を表示します。これは linux-modules-extra-* がイメージパッケージに依存しており、同じトランザクションで削除する必要があるためです。表示された一覧が、実際の安全確認になります。ここで、削除するつもりだったバージョンと一緒に meta package まで削除対象になっていないか確認できます。想定外の項目が含まれている場合は、n と回答します。続いて sudo apt autoremove --purge を実行し、存在する理由を失った module パッケージと header パッケージを削除します。
実行中の 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その時点からファイアウォールの再読み込みに失敗し、この kernel がブート後にまだ扱っていないファイルシステムの種類もマウントできなくなります。一方、/boot/vmlinuz-$(uname -r) もなくなるため、ブートメニューに現在実行中の kernel が表示されなくなり、次回の再起動で別の kernel が起動します。マシンはネットワークトラフィックを処理し続けますが、すでに起動不能です。毎回、uname -r を削除対象の一覧と照合してください。
/boot が一杯で apt をまったく実行できない場合
この状態になると、このページを探すことになります。apt autoremove は、構成が途中で止まっている kernel package の設定を完了するために dpkg を必要とします。この処理では initramfs を再構築しますが、空き容量のない /boot に書き込む必要があります。1 回だけ手動で処理して、このループを解消します。
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 の自動削除ルールでカーネルを保護し、クリーンアップはユーザーに任せるか、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 がそのファイルより十分に大きくない場合、次のカーネルのインストールは上記とまったく同じ理由で失敗します。アップグレード中ではなく、今のうちに対処してください。この確認には 1 分もかかりません。VPS の他の ディスク健全性チェックとあわせて実行する価値があります。特にリリースアップグレードの直前は重要です。Ubuntu 24.04 を 26.04 に移行すると、処理の早い段階で新しいカーネルがインストールされます。/boot の空き容量が不足していると、do-release-upgrade は処理を続行できません。LTS サーバーにまだそのアップグレードが提示されていない場合、原因は障害ではなく時期です。Ubuntu は LTS から LTS へのアップグレードを、26.04.1 ポイントリリースがリリースされるまで保留します。そのため、先に /boot を整えておくための明確な期間があります。
FAQ
Ubuntu は削除せずに古い kernel を残すのはなぜですか?
起動に失敗する kernel しかない場合、選択できるものがなくなるためです。以前のバージョンを残しておけば、不適切な更新から provider の rescue console ではなく GRUB メニューで復旧できます。apt はそのため、一部の kernel パッケージを自動削除から保護し、常に実行中の kernel を含めます。リリースによってポリシーが変わっているため、apt-config dump | grep -i neverautoremove を実行して、使用中のリリースで保護される正確なパターンを確認してください。
apt autoremove --purge は production server で安全に実行できますか?
dry run の結果を先に確認すれば安全です。何も書き込まない sudo apt autoremove --purge --dry-run を実行し、表示された一覧を確認してください。linux-generic や linux-image-generic などの meta package が含まれている場合は中止します。これらを削除すると、以後の kernel 更新が停止します。uname -r が出力するバージョン文字列が含まれている場合も中止してください。どちらも含まれていなければ、削除対象は古い kernel と孤立した依存関係です。
apt autoremove で何も削除されず、/boot もまだ満杯です。どうすればよいですか?
古い kernel は、ほぼ確実に manual としてマークされています。autoremove が処理するのは automatic としてマークされたパッケージだけです。apt-mark showmanual | grep -E '^linux-' を実行してください。そこに表示されたバージョン付き kernel は、いずれかの時点で手動インストールされています。sudo apt-mark auto linux-image-<version> で automatic としてマークし、もう一度 dry run を実行してください。または、そのバージョンだけを sudo apt purge linux-image-<version> で直接 purge します。
/boot のファイルを手動で削除できますか?
/boot が満杯に近く、そのため apt が壊れた kernel パッケージを構成できない場合に限り、意図した一度限りの対応として実行してください。uname -r の出力にないバージョンの initrd.img-<version> ファイルを1つ削除し、直ちに sudo apt --fix-broken install、sudo apt autoremove --purge、sudo update-grub を実行します。これらの後続処理を行わずにファイルを削除すると、dpkg はファイルが消失したパッケージを記録したままになり、GRUB メニューには存在しないファイルを指すエントリが残ります。その結果、誤操作を行った時点ではなく、次回の再起動時にマシンが起動できなくなります。