リモートからOSをインストールする
概要
通常,OSをインストールするにはCDやUSB等のメディアを直接PCに接続し,その場で設定を行う. もちろん,インストール途中のPCにはSSHできないためリモートからこれらの作業を行うことはできない.
本記事では,すでにSSH接続できる遠隔地のPCに対し,新たにOSをインストールし,デュアルブートの形で設定する方法を解説する.
おおまかな流れとしては以下のとおりである.
背景
ローカル環境をLOCAL,リモートの環境をREMOTE,新たに作成する環境をNEWとする. なお,本記事とは直接関係ないが,中間ノードMIDが存在し,REMOTEはMID経由でしかアクセスできない. MID->REMOTEのアクセスは,mDNSを用いてIPアドレスの解決を行うことで実現している.
いま,REMOTEにSSHでき,システムが稼働中であるとする. REMOTEに存在する外部ストレージに新たにOSをインストールし,それを起動し,アクセスしたいとする. (同一ストレージデバイスの異なるパーティションに対しても今回は未検証だが,同一手順でできると思われる.この際はresize2fsで稼働中のファイルシステムを縮小し,新たなOS用の領域を確保する必要がある.) 現在稼働中のOSは/dev/sdaにあり,新たにインストールするOSは/dev/sdb1にインストールするとする.
実際の手順
仮想マシンのインストール
まずはREMOTE内でKVMを使って新たに仮想マシンを作成する. このとき,作成する仮想マシンのストレージ容量はあまり大きくならないように(例:8GB)する.
この例ではUbuntu16をインストールする.
REMOTE$ sudo virt-install \ --connect=qemu:///system \ -n ubuntu16 \ -r 1024 \ --disk path=new.img,size=8,format=raw \ --vcpus=1 \ --os-type linux \ --network network=default \ --nographics \ --extra-args='console=tty0 console=ttyS0,115200n8' \ --location http://ftp.jaist.ac.jp/pub/Linux/ubuntu/dists/xenial/main/installer-amd64/
ここで作成したOSが,新たに(仮想マシン上ではないく,ネイティブに)インストールするOSとなる. 注意点としては,
- swapを作成せずプライマリパーティションをひとつだけ作成する
- LVMを使わない
である.
なお,仮想マシンの保存先としてファイルを指定しているが,これを/dev/sdb1としてはいけない. インストール中に分かると思うが,仮想マシンでは仮想ストレージを作成するためにこれを直接起動することはできないからである.
インストールできたらシャットダウンする.
(オプション)シリアルコンソールを有効化する
Ubuntu16の場合はコンソール接続がそのままではできないので,インストール後に直接イメージファイルを編集して,コンソール接続できるようにする必要がある.
以下の記事に詳しい.
Ubuntu 16.04 LTS : KVM : 仮想マシン作成#1 : Server World
仮想マシンをセットアップ
仮想マシンを起動し,セットアップを行う.
SSHサーバのセットアップ
NEW$ sudo apt install openssh-server
.ssh/authorized_keysに公開鍵を登録する. なお,仮想マシンのIPアドレスは,
REMOTE$ virsh net-dhcp-leases default
で分かる.
(オプション)mDNSの設定
MIDからhostname.localでアクセスできるようにmDNSの設定を行う.
NEW$ sudo apt install avahi-daemon
自動シャットダウンスクリプトを仕込む
後ほどNEWを仮想マシンを経由せずに起動することになる. この際,ネットワークにエラーが発生した場合SSHで接続できず,手出しができなくなってしまう. そのため一定時間で自動的にシャットダウンするスクリプトを仕込む. 直接NEWにアクセスできなくとも,WOLを利用してMIDからREMOTEを起動することはできるのである.
/etc/rc.localにスクリプトを作成し,置いておく. 例えば10分後に自動でシャットダウンをする動作を記述. もちろん,無事にSSHできた場合はこのプロセスを殺す.
ネットワークの設定
OSごと異なる環境に移すことになるのでネットワークにも不調が出る(出た). 今回の問題は/etc/network/interfacesの記述が間違っていたことだった.
現在,
NEW$ cat /etc/network/interfaces # This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback # The primary network interface auto ens2 iface ens2 inet dhcp
となっているものを,
NEW$ cat /etc/network/interfaces # This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback # The primary network interface auto eno1 iface eno1 inet dhcp
と変更する.
なお,"eno1"の見つけ方であるが,これは何度か起動,自動シャットダウンを繰り返して見つけることになる. 具体的には件のシャットダウンスクリプト内部に,dmesgをダンプして保存する処理を仕込み,シャットダウンする. その後REMOTEが起動したら,NEWのパーティションをマウントし,ダンプされたファイルを確認する.
dmesg中の以下のような箇所を発見する.
[ 9.136448] e1000e 0000:00:19.0 eth0: registered PHC clock [ 9.136450] e1000e 0000:00:19.0 eth0: (PCI Express:2.5GT/s:Width x1) XX:XX:XX:XX:XX:XX [ 9.136452] e1000e 0000:00:19.0 eth0: Intel(R) PRO/1000 Network Connection [ 9.136478] e1000e 0000:00:19.0 eth0: MAC: 11, PHY: 12, PBA No: FFFFFF-0FF [ 9.136923] e1000e 0000:00:19.0 eno1: renamed from eth0
eth0が何にrenameされているか調べれば良い.
外部ストレージ(/dev/sdb)のセットアップ
fdisk等を使い,パーティション/dev/sdb1を作成する.
後から行う強引な方法のために/dev/sdb1をゼロ埋めで初期化する.
REMOTE$ sudo dd if=/dev/zero of=/dev/sdb1
仮想マシンの中身を外部ストレージに移す
まず新たに作成した仮想マシンを起動する.
先程作成した外部ストレージを仮想マシンにアタッチする.
REMOTE$ virsh attach-disk ubuntu16 /dev/sdb1 vdc --live
/dev/sda1の中身をddで外部ストレージにコピーする(!)
NEW$ sudo dd if=/dev/sda1 of=/dev/sdb1
NEWをシャットダウン.
ファイルシステムを直す.
NEWはもともと8GBのディスクに作られていたのでこのままではおかしなことになる. そこでfsckとresizeでファイルシステムを修正する.
REMOTE$ sudo e2fsck -f /dev/sdb1 REMOTE$ sudo resize2fs /dev/sdb2
GRUBをアップデート
新たに作成したOSをGRUBに登録する.
REMOTE$ sudo grub-mkdevicemap REMOTE$ sudo update-grub
リブート
NEWを起動するようにgrub-rebootを使い調整する. 表示方法は前の記事を参照のこと.
その後rebootし,無事起動してくれることを祈る.