まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

2024/05

RHEL(RedHat Enterprise Linux) を使っている人は珍しくないと思いますが、RHCOS(RedHat CoreOS、以下 "RHCOS") は名前を聞いたことはあっても使っている人はあまり多くないのではないかと思っています。 そんな RedHat CoreOS 4.15.0 を手元の VirtualBox 仮想環境にインストールし、かつ使いやすいように少しカスタマイズしてみました。その手順を紹介します(VirtualBox に依存した部分はないつもりなので、他の仮想環境や物理環境でも同様に実施できると思っています)。


【RHCOS とは?】
RedHat が提供する Linux カーネルを中心とした軽量な Linux 環境であり、自動化やリモートアップデートの機能があります。現在は RedHat OCP(OpenShift Container Platform) のコンポーネントとしてのみサポートされています。
2024050400



【RHCOS のインストールに必要なもの】
他の Linux にない、CoreOS の特徴の1つでもあるのが「インストーラーがない」です。インストーラーはコア機能の一部ではない(言われてみればまあその通りかも・・)ということなんでしょうかね。 他の Linux の多くはインストール DVD(ISO) が用意されていて、その DVD で起動するとインストーラーが立ち上がって・・・という方法でインストールするものばかりですが、CoreOS ではこの方法は提供されていません。つまりインストーラー無しでインストールする必要があります。

ただこの辺りが全く考慮されていないわけでもありません。インストール用の ISO はダウンロード可能な形で提供されています。ただインストール時に指定する必要のあるホスト名やユーザー名、そのユーザーの公開鍵情報を入力する UI は用意されていません。ではこれらの情報をどのように指定するかというと「HTTP でアクセス可能な外部ファイル(Ignition ファイルといいます)として用意し、インストール時にその URL を指定して取得する」ことになります。したがってインストール時にはインストール先となるサーバー以外に HTTP サーバーが必要になります。

更にはこの「HTTP でアクセス可能な外部ファイル」も用意する必要があるのですが、その作業自体は同 HTTP サーバー上で実行できます。したがって「インストール前の準備作業を行い、インストール時の HTTP サーバーとして稼働するサーバーが同一ネットワーク上に1台必要」ということになります。

今回、このサーバーを CentOS 7(Minimal) で用意しました。他のディストリビューションでも同様に可能だと思いますが、適宜読み替えてください。


【HTTP サーバーと Ignition ファイルの準備】
まず HTTP サーバーとなる CentOS に root 権限でログインし、後述の作業を実行する上で必要になるツールをあらかじめインストールしておきます(HTTP サーバーとして Apache HTTPD を使う前提で以下を説明しています):
# yum install -y httpd wget

この後外部からこの HTTP サーバーへのアクセスがあるので、ファイアウォールを無効にするか、80 番ポートを解放します(以下では CentOS7 のファイアウォールを無効にしています):
# systemctl stop firewalld



また Ignition ファイルは JSON 形式なのですが、編集時には YAML で編集します。編集後に YAML -> JSON の変換を行うのですが、Ignition ファイルとしての変換を実行してくれる butane(以前の名称は fcct)というツールもインストールしておきます:
# cd
# wget https://github.com/coreos/butane/releases/download/v0.20.0/butane-x86_64-unknown-linux-gnu
# mv butane-x86_64-unknown-linux-gnu butane
# chmod +x butane

また RHCOS は、インストール直後はコンソールからのログインができず、外部サーバーからの SSH 接続のみが可能です。その際に利用する鍵ファイルを用意します(既にある鍵ペアを使うことも可能ですが、ここでは新規に作成する前提で紹介します):
# ssh-keygen

"ssh-keygen" というコマンドを入力すると色々パラメータの入力を求められますが、全てそのまま Enter でも構いません(その場合は秘密鍵が ~/.ssh/id_rsa に、公開鍵が ~/.ssh/id_rsa.pub にそれぞれ作成されます):
2024050401


鍵ペアが用意できたら Ignition ファイルを作ります。まずは ignition.yaml というファイル名で以下のような YAML フォーマットのテキストファイルを作ります(赤字はコメントなので、実際には不要です):
variant: fcos
version: 1.0.0
storage:
  files:
    - path: /etc/hostname
      mode: 0644
      contents:
        inline: rhcos (ホスト名)
passwd:
  users:
    - name: core (ログインユーザー名)
      groups:
        - sudo (sudo 権限を与える)
      ssh_authorized_keys:
        - ssh-rsa XXXXXXXXXXXXX(公開鍵ファイル ~/.ssh/id_rsa.pub の内容)XXXXXXXXXXXXXXXX...

RHCOS の特徴でもあるのですが、この Ignition ファイルの中で /etc/hostname の内容を直接書き込む形でホスト名を指定します。またログインユーザー名やその権限(所属グループ)もこの Ignition ファイルの中で指定します。 ssh_authorized_keys の値は(先ほど作成した)鍵ペアの公開鍵ファイルの中身をそのまま1行で記載します。

ignition.yaml ファイルが完成するとこんな↓感じになります:
2024050402


そして butane を使ってこの ignition.yaml ファイルを JSON 形式に変更します:
# ./butane ignition.yaml --pretty --output ignition.json

2024050404


できあがった ignition.json は以下のような内容でした:
2024050405


この ignition.json を HTTP アクセス可能なファイルとしてコピーします:
# cp ignition.json /var/www/html/
# systemctl restart httpd

これで Ignition ファイルは "http://(このサーバーの IP アドレス)/ignition.json" という URL で外部からアクセスできるようになり、RHCOS のインストール時に指定可能なファイルとしての準備が整いました。

なおこのサーバーの IP アドレスは "ip a" というコマンドで調べることができます(下図の例だと "192.168.0.102" であることがわかります):
2024050412


【RHCOS のインストール】
RHCOS をインストールするための ISO ファイルを取得します。RedHat Developer Subscription に(個人または企業アカウントで)登録した上で、RedHat CoreOS のダウンロードサイトから最新版の ISO ファイルをダウンロードします(2024-05-04 時点では 4.15.0 というバージョンが最新で、ファイル名は rhcos-4.15.0-x86_64-live.x86_64.iso でした)。物理サーバーにインストールする場合は DVD などブート可能なメディアに変換しておきます:
2024050406


RHCOS をインストールしたいサーバーにダウンロードした ISO(または DVD)をセットします(図は VirtualBox で ISO を DVD にセットした時の様子):
2024050407


そしてサーバーの電源を ON にします。ISO(DVD) から起動します:
2024050409


起動すると以下のような一般ユーザー(core)のプロンプトが表示される画面になります。これは ISO の Live 環境が起動している状態です:
2024050410


ここでプロンプトに以下のように入力します。"/dev/sda" はインストール先ディスクのデバイス名です(US キーボードレイアウトになっているので注意):
$ sudo coreos-installer install /dev/sda --ignition-url (ignition.json のURL) --insecure-ignition
※最後の "--insecure-ignition" は ignition.json の URL が https ではなく http の場合に必要です。

2024050413


Ignition ファイルへのアクセスができていればインストールが開始されます:
2024050414


インストールはすぐに完了してプロンプトに戻ります:
2024050415


"sudo shutdown -h now" でシャットダウンし、ISO(DVD) を取り除いてから再度起動します:

すると今度はこのような画面で起動します。これは Live DVD で起動した画面ではなく、ディスクにインストールされた RHCOS が起動していることを意味しています(画面内に IP アドレスが表示されていることも確認してください)。RHCOS のインストール自体はこれで完了です:
2024050416


ただし、この時点ではこの画面からログインすることはできません。Ignition ファイル内で作成するユーザー名は指定(上の例では "core")していましたが、パスワードは指定していません。この作成方法だと RHCOS にログインするには鍵ファイルを持つ他のサーバーから SSH 経由でのみログインできます。

試しに CentOS サーバーからログインしてみます。ユーザー名(core)と IP アドレスを指定して ssh でログインしてみます:
# ssh core@(RHCOS の IP アドレス)

2024050417


上図のようになると RHCOS に SSH で接続できています。core ユーザーには sudo 権限があるので、事実上の管理者権限を持って作業することはできます。シャットダウンもこの状態からであれば行うことができます。


というわけで、一応 RHCOS のインストールは完了し、SSH ログインによって OS を操作することも可能になりました。慣れていないと不思議に感じるかもしれませんが、一般的な RHCOS は(あくまでコンテナクラスタの OS としてしか使わないので)このように使います。

ただコンソールからログインできない(秘密鍵を持つサーバーからの SSH でないとログインできない)のはちょっと不便なので、最後にコンソールログインもできるように設定を変更します。


【RHCOS インストール後の設定変更】
RHCOS に直接ログインできるようにするにはパスワードを設定してあげるだけです。上の続きで SSH ログイン後に以下のコマンドを実行してパスワードを設定します:
$ sudo -i
# passwd core

パスワード設定後に exit して SSH 接続も切断します。ここまでの手順が成功していれば、CentOS 環境はもう不要なのでシャットダウンしてしまっても構いません。

最後に RHCOS のコンソールからパスワードでログインできるようになったことを確認します:
2024050418


これで CentOS に依存しない、単体で動作可能な RHCOS 環境ができあがりました。


まあ「どんな時に単体の RHCOS が必要か?」と聞かれると、(あまりオススメしませんが)アンチウィルスソフトの動作確認をしたいとか、コンテナに特殊なストレージデバイスを接続して使うような場合の手順や動作の確認時とか、かなり偏った用途くらいしか思いつかないのですが、レアな環境を手に入れることに興味を持つエンジニアにはウケるんじゃないかと思っています。



ものすごく久しぶりにブログを書いてます。業務で集中してインプットする期間が長かったからなのですが、少しずつアウトプットしていこうと思います。今日は SSD や HDD などのディスクを初期化する話です。

「ディスクの初期化ってフォーマットすればいいんじゃないの?」と考える人が多いかもしれませんが、場合によってはもう少し複雑な背景があったりします。まずはそんな背景から説明します。


【シンプルなケース】
一度何かの用途で OS をインストールするなりして使ったディスクがあり、これに新しい別の OS をインストールしたい、という場合であれば、大抵のケースではそもそもあらかじめディスクを初期化しておく必要もなく、OS のインストールの一環として使っているディスクを初期化したり、パーティショニングを変更したりすることができると思っています。仮に事前の初期化が必要であったとしても(例えば Linux のインストーラー DVD で起動した後に)fdisk でパーティショニングを変更したり、mkfs で特定のフォーマットに変更/初期化することができます。しかもこの方法であれば一度ディスクを取り出して、別のマシンに繋ぎなおして・・ といった手順も不要です。さほど難しい話ではないです。


【PXE のような特殊なケース】
後述するような初期化の方法をとらなければいけないような特殊なケースとはどんなケースが考えられるでしょうか? その1つが「PXE(Pre eXecution Environment)」と呼ばれる起動やインストールを行う場合です。まずはこの PXE について説明します。

エンジニアならばこんな画面を一度くらいは見たことある人が大半だと思うのですが、これは BIOS と呼ばれる OS 起動前に実行されるソフトウェアの設定画面です(機種によって見栄えは異なります)。その中にこのような「起動優先順位」を設定する項目があります:
BIOS起動順位の変更


上図の場合だと以下のように設定されています:
1 CD/DVD
2 ハードディスク
3 リムーバブルデバイス(USB メモリなど)
4 ネットワーク

この起動優先順位設定により、この PC に電源を入れると・・・
1 DVD ドライブに起動可能なメディア(インストール DVD など)が入っていたら、そこから起動
2 1に該当せず、ハードディスクに OS がインストールされていたら、そこから起動
3 2に該当せず、起動可能な USB メモリが刺さっていたら、そこから起動
4 3に該当せず、ネットワーク経由で起動できる環境が揃っていれば、そこから起動
5 4にも該当しなかった場合は何も起動しない

・・という優先順位を経て起動対象が決まります。1、2、3(、5)は何となくわかる人が多数だと思うのですが、4の「ネットワーク経由で起動できる環境」はあまり詳しくない人が多いのではないでしょうか? 実はこれが PXE なのです。PXE そのものの詳しい説明はウィキペディアに譲りますが、簡単に言うと DHCP, TFTP, HTTP などのプロトコルを組み合わせて事前に必要な環境を用意しておくことで、電源を入れた時にネットワークカードが繋がった先から(OS 起動前に) IP アドレスを取得し、必要なファイルもダウンロードして起動(と、必要であれば起動後のインストール)するための環境です。「PXE ブート」とか「PXE インストール」と呼んだりもします。

PXE ブートする場合は上述のように低い起動優先順位が設定されることが多いです。理由は
・何もインストールされていない状態のディスクに、
・ネットワーク経由で OS をインストールして、
・インストール後は、そのインストールされた OS を起動する
という使い方をするケースが大半なので、これを実現するために少なくともディスクよりは下の起動優先順位が設定されている必要があります。また何かあった時の緊急対応用 DVD などはディスクよりも優先的に起動できる必要があるため、DVD の優先順位は高めになることが多いのでした(個人的には USB メディアも同じ理由で高めに設定することが多いです)。

ともあれ PXE ブートは何かの OS を複数台の PC にまとめてインストールするようなケースや、複雑に入り組むサーバー環境を(1つ1つ手作業で構築するのではなく)PXE ブートによってある程度まとめて作ってしまうようなケースに使われるもの、という印象があります。


【PXE だと何が問題になるのか?】
さて、このような PXE ブートを経て環境構築するようなサーバー環境(極端な例だと、PXE ブートによるインストールだけがサポートされているようなサーバー環境)があったとします。PXE ブートで OS もインストールされ、構築完了まであと一息・・・という所でオペレーションをミスしてしまって、環境構築に失敗してしまい、初めからやり直さないといけなくなったケースを想像してみてください。

それまでの作業や時間が無駄になってしまったのはショックですが、PXE ブートの環境が残っていればある程度は「電源をオンにするだけ」で済む環境なので、(手作業部分の量にもよりますが)イチから作り直すほどのショックはないはずです。というわけで、改めて電源を入れなおして・・・ 

・・・とここで気付くはずです。環境構築には失敗してやり直さなければいけなくなっているのですが、ディスクには OS が導入済みです。PXE 環境だと上述のような起動優先順位に設定されていることが多いため、電源を入れなおすと PXE ブートの前にインストール済みの OS が起動してしまうのでした。

そして「そうか。じゃあネットワークインストールの起動優先順位をディスクよりも上にして・・・」と考えて設定し直した場合、確かに PXE ブートによって環境構築をやり直す所まではできるのですが、次回(再)起動時の際にも OS がインストールされたディスクではなく PXE ブートが始まってしまいます。環境構築時に自動的に数度のリブートが伴うようなサーバー環境(例:某社のコンテナクラスタプラットフォーム)の場合は OS 導入直後の絶妙なタイミングを測って起動優先順位を変更する必要があり、失敗するとまた PXE ブートが始まって・・・ という無限ループに陥ってしまうのです。話が単純ではなく、かなり複雑になることがご理解いただけるでしょうか?

※これは VMWare や VirtualBox などの仮想サーバー環境であればさほど問題ではないです。ディスクはディスクイメージというファイルになっているケースがほとんどで、「ディスクを初期化する」=「ディスクイメージファイルを初期化する」と考えれば、要は既存のイメージファイルを削除し、新しいディスクイメージファイルを作って付け替えてあげるだけです。 でも物理サーバー環境だとそうはいきません。

上述の PXE ブート無限ループ問題を解決するには、起動優先順位を変更するのではなく、「ディスクに導入された OS 環境をなかったことに(初期化)した上で再度 PXE ブートからやり直す」必要があるのでした。 正確には「ディスクの OS が起動できない状態にした上で、再度 PXE ブートからやり直す」必要があります。

この「OS が起動できない状態」というのが問題です。実は OS の各パーティションをフォーマットしたり、極端な例ではパーティションを初期化(例えば全パーティションを削除してパーティションが1つもない状態にする)してもパーティションとは別に存在する MBR(マスターブートレコード)には(grub などと呼ばれる)起動する OS の情報が残ってしまうのでした。この MBR に情報が残った状態で PXE ブートを試みると、ディスクには OS が存在すると判断されてしまい、一方でパーティションは存在していないので実際には起動できなくなって止まってしまう、という状態に陥ってしまいます。

・・・前置きが長くなってしまいましたが、この状態を回避するには、改めてこのブログエントリのサブジェクトでもある「ディスクを MBR ごと初期化する」必要があるのでした。以下、その手順を紹介します。


【ディスクを MBR ごと初期化する手順】
実は前置きの長さに比べて本体が超あっさりなんですが(苦笑)、以下その手順を紹介します:
  • Ubuntu などの起動可能なインストール DVD を用意して、DVD ドライブに入れて DVD から起動して(DVD がない場合は USB から起動して)、
  • ターミナルなどの画面から以下のコマンドを実行してからシャットダウン
 $ sudo dd if=/dev/zero of=/dev/sda bs=512 count=1

"/dev/sda" 部分は対象ディスクのデバイス名です(分からない場合は fdisk コマンドで確認できます)。MBR はディスクの先頭 512 バイト(固定)に格納されるという特徴から、先頭 512 バイトを無理やり無駄な情報で埋めることで MBR を消す、という処理を実現しています。 fdisk コマンドや dd コマンドであれば大半の Linux ディストリビューション・インストールメディア内に用意されているはずなので、このディストリビューションだと使えない、ということはほぼないはず。

上述のように、これが問題になるのは物理サーバー環境であることが多いと思うのですが、この方法であれば対象の物理サーバーからディスクを取り出して、別のサーバーに付け替えて・・・といった余計な作業も発生しません。手順やり直しの際に必要と考えると、PXE ブートを伴う物理サーバー環境構築においては事実上必須のオペレーションになると考えています。




このページのトップヘ