Tech Racho エンジニアの「?」を「!」に。
  • インフラ

ルートファイルシステムがRead-OnlyなLinux環境でファイルを作成する方法

morimorihogeです。涼しくなってきましたね、ありがたい。今日は小ネタです。

昔々から動いているサーバーのメンテナンスというのはいつになっても無くならないものです。新規で立てたサービスなんかはコンテナオーケストレーションサービス(AWS ECSやらk8sなど)に載せていても、数年前(5年前overレベル)に構築した環境などだと今でもSSHしてメンテするシステムはどの会社にもそれなりに転がっていることでしょう。
今日は、そんなサーバー環境が死にかけたときに使えるかもしれない話です。

ディスク障害とread-onlyマウント起動

Linuxではディストリビューションにもよるかもしれませんが、何らかの事情でルートファイルシステムにディスク障害が発生した場合、read-onlyモードでマウントされた状態でOSが起動します。
この状態になっているとあらゆるファイルシステムへの書き込みが失敗するため、何をやっても cannot create temp file for here-document: Read-only file system といったエラーメッセージが出るようになってしまいます。

read-onlyでマウントされているかは起動時のメッセージなどにも表示されるとは思いますが、そもそもログが確認できない状態の場合などはmountコマンドで実際にread-onlyでマウントされているかを確認することができます。
以下の例では / である /dev/sda2ro、つまりRead Onlyでマウントされていることが分かります(通常は rw(Read-Write)となっているはず)。

root@example:~/composes# mount
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
(略)
/dev/sda2 on / type ext4 (ro,relatime,data=ordered)
(略)

ファイルをサルベージしたいが・・・これって詰んでる?

この状態はそもそもディスク障害が疑われるので速やかにファイルの待避をしたいのですが、以下の様な問題が出てきます。

  • そもそもバックアップしたいファイルはrootでないとアクセスできない場所にある
  • rootログインは許可しておらず、都度 sudo su - する運用にしていた
  • scp でファイル転送しようにも、SSHできるユーザー権限でバックアップしたいファイルにアクセスできない
  • chmod chownでアクセス許可を変更しようとしても、 Read-only file system のエラーが出て変更できない
  • ファイルシステムがRead-Onlyなので、新規のauthorized_keysなどの追加もできない
  • \(^o^)/

なかなか参りましたね。こういった状況でどうやって問題をくぐり抜けるのか、腕の見せ所さんです。Linux Adminとしての経験と手札の多さが試される。

ramdisk tmpfs(/dev/shm) を使って解決

いくつかの解決方法が考えられます(後述)が、ここではできるだけ他の環境に手を入れない方法を検討してみた所、 /dev/shm にramdiskがマウントされていることに気づきました。

# df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            208M     0  208M   0% /dev
tmpfs            49M  1.4M   47M   3% /run
/dev/sda2        20G   19G     0 100% /
tmpfs           241M   88K  241M   1% /dev/shm
(略)

mount コマンドの出力結果を確認しても、tmpfsは rw (Read-Write)であることが分かります。

$ mount
(略)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
(略)

というわけで、ここを一次作業領域として使えばよさそうですね。
ちなみに、/tmp をramdiskとしてマウントしているdistributionもあるようですが、Ubuntu系などは /tmp/ とは分かれてパーティショニングされていませんでした。なので、この場合 /tmp はRead-Onlyになっていて使えません。

ファイルをサルベージする

ここではramdiskの領域が241MBほどあり、バックアップしたいファイル群もそのサイズ以下だったので、

# tar zcf /opt/backup/files /dev/shm/backup-files.tgz

でバックアップし、そのファイルのpermissionをSSHユーザーでアクセスできるようにした上でscpすることで解決しました。
バックアップしたいファイルサイズがramdisk以下の場合であれば、これがお手軽そうです。

他に考えられる方法は?

その他に考えられる方法を検討してみます。実際にできるかどうかまでは確認していませんが、手段の案として。

  • ramdisk上にディレクトリを作り、 /root/.ssh をマウントする。ramdiskに置かれた.ssh/authorized_keysを編集すればrootとしてscpできるはず
  • nc などの標準入出力をやり取りできるプログラムを通じて無理矢理転送する( tar - を使うと標準出力にtarのアウトプットを出せる)
  • SSHした先で sudo を含むtar -で標準出力にデータ出力スクリプトを実行し、手元で受け取る
    • ssh hoge@example.com 'sudo tar zcf /opt/backup/files - |'tar zxf - みたいな?試してませんがこんな感じでやれるはず
  • aws-cli が入っている環境であれば、s3 syncなどを使ってバックアップ( gcloud などでも可、接続用の情報が環境変数から渡せる必要がある)

その他にも、色々追い込まれればなんとかする方法は思いつけそう

まとめ

たまたま扱ってた環境が今回の状況にハマったので試行錯誤してみました。
こういう普通じゃない状況に陥ったときにはLinuxベース力と経験が試されますね。精神衛生には良くないですが、たまにであれば頭の体操に良いかもしれません。ではでは。


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。