Fedora CoreOSをベアメタルにインストールする

## それはある休日のこと

FilunKはミニサーバを１台持っています。しばらく ``Hyper-V Server 2019`` を使っていましたが久しく動かしていなかったため、

> せっかくならコンテナ向けのOSに乗り換えよう

と思いついたため、FilunKは南米ジャングルの奥地に潜入したのです……
そして見つけたのが、Fedora CoreOS(FCOS)でした。

## Fedora CoreOSとは

``Container Linux`` というコンテナホスト向けOSを開発していたCore OSをRed Hat社が買収。
これをProject Atomicで開発していた``Fedora Atomic Host`` ``Centos Atomic Host`` と統合し、``Fedora CoreOS`` として提供されています。

## 導入OSバージョン

[Fedora CoreOS](https://getfedora.org/ja/coreos/)
今回導入したのは ``stable 31.20200118.3.0`` です。

## 導入にあたって必要なもの

| 必要なもの | 利用目的 |
|:--:|:--|
| ISOファイル | liveメディアによる起動・インストール |
| Rawファイル | インストール媒体 |
| Rawのsignatureファイル | インストール媒体のチェック |
| FCOS設定ファイル | インストール時の設定を記述 |
| Fedora CoreOS Config Transpiler(fcct) | FCOS設定ファイルをIgnitionファイルに変換する |
| 別の端末 | HTTPサーバを稼働させる |

ISOファイル・Rawファイルはダウンロード画面にあるため、すぐ見つけることができると思います。
ただし、Rawファイルのsignatureファイルは、Rawファイルのダウンロードリンク下にある、　``Verify signature & SHA256`` → ``Download the checksum file and signature`` のsignatureのリンクを押すことでダウンロードできます。

fcctはダウンロードページにはなく、Githubのリンクからダウンロードします。
[coreos/fcct](https://github.com/coreos/fcct/releases)
利用している端末に合わせて実行ファイルをダウンロードして、名称をfcctに変更しておくことをおすすめします。

ignitionファイルはこの後のインストール手順で説明します。

__この通り、よくあるLinux OSではISOだけで十分だけれども、Fedora CoreOS導入にはこれだけの準備が必要です。__


## 下ごしらえ

ではインストールしていきましょう。
とはいえ、導入にこれだけの部品が必要です。それぞれをいい感じにしていかなければなりません。

### １．ISOをブータブルにする。

Linux OSでもおなじみ、ISOをブータブルにする作業です。ISOをCDやDVDに焼くのもいいですが、FilunKはいつもUSBを使用しています。
USBでブータブルメディアを作成するツールはいくつもありますが、いつも[balenaEtcher](https://www.balena.io/etcher/)を使用しています。

### ２．Ignitionファイルを作成する

Ignitionファイルはこれから導入するFCOSの設定を記述するファイルです。ただし、IgnitionファイルそのものはJSONで人の手で作るのは大変であるため、まずはYAMLファイルで作成し、fcctでトランスパイルしてJSONファイルを作成します。

今回のFCOS設定ファイルは以下の内容です。

``` yml
variant: fcos
version: 1.0.0
passwd:
  users:
    - name: core
      ssh_authorized_keys:
        - ssh-rsa <<ssh-key>>
storage: 
  files: 
    - path: /etc/NetworkManager/system-connections/eth0.nmconnection
      mode: 0600
      overwrite: true
      contents: 
        inline: |+
          [connection]
          type=ethernet
          interface-name=eth0

          [ethernet]
          mac-address=<<mac-address>>

          [ipv4]
          method=manual
          addresses=<<ipv4>>/<<subnet>>
          gateway=<<gateway-ipv4>>
          dns=<<dns-ipv4>>
```

この中で必須なのは``variant``プロパティ、``version``プロパティ、``passwd``プロパティです。
では、少しずつ見ていきましょう。

``` yml
variant: fcos
version: 1.0.0
```
今回のYAMLがfcosのヴァリアントで、バージョン1.0.0、という意味。これはFCOSのIgnitionファイルを作成する場合は基本的に固定で良いかと思います（もしかしたら今後のverアップでversionプロパティが変更されるかも？）。

``` yml
passwd:
  users:
    - name: core
      ssh_authorized_keys:
        - ssh-rsa <<ssh-key>>
```
``passwd``プロパティは内部に``users``プロパティを持ち、``users``プロパティはリストを取ります。
 ``name``プロパティは最低でも１つ、coreユーザを指定します。coreユーザはFCOSの中で特殊なユーザで、パスワード無しsudoが可能なユーザです(実質的なrootユーザ）。SSH接続を行うため、``ssh_authiorized_keys``プロパティに使用する公開鍵を記述します（\<\<ssh_key>>）。

ちなみにこの設定、SSH接続はできますが、ローカル端末に対して直接ログインすることができないです。なぜなら、パスワードの設定を行っていなからです。``password_hash``プロパティを設定すれば可能なようですが、平文パスワードをハッシュ化する必要があるため、~~めんどくさい~~設定を見送りました。

``` yml
storage: 
  files: 
    - path: /etc/NetworkManager/system-connections/eth0.nmconnection
      mode: 0600
      overwrite: true
      contents: 
        inline: |+
          [connection]
          type=ethernet
          interface-name=eth0

          [ethernet]
          mac-address=<<mac-address>>

          [ipv4]
          method=manual
          addresses=<<ipv4>>/<<subnet>>
          gateway=<<gateway-ipv4>>
          dns=<<dns-ipv4>>
```

``storage``プロパティの``files``プロパティはインストール時に定義するファイルの情報及び内容を記載します。上記の通り、NetworkManagerのIPアドレス設定について上書きしようとしています。必要なコネクションの分だけ追加することが可能なので、ethが複数ある場合でも対応できます。
ただ面倒なのは\<\<mac-address>>ですかね。これは後々にliveブートしたときに確認するといいかもです。

他にはsystemdの動作ユニットの設定を行ったり、いろいろできるので他のプロパティは[公式](https://github.com/coreos/fcct/blob/master/docs/configuration-v1_0.md)を参照してください。

そしてこれをfcctで処理を行い、Ignitionファイルにします。
ちなみにダウンロードしたfcctツールは、実行権限さえ付けば動作する実行ファイルです。

``` bash
# --input: 入力ファイルを指定
# --output: 出力ファイルを指定
# --pretty: インデント・改行をつけて出力
./fcct --input fcos.yml --pretty --output fcos.json
```

### ３．　HTTPサーバを立てる

どうしてOSインストールをするのにHTTPサーバを建てないといけないの？　という疑問は当然です。だって、FilunKも頭をかしげました。
結論どうしてかというと、

・インストール前にIgnitionファイルをローカルにダウンロードする必要がある
・__OSの実体データ=RawファイルをHTTPサーバ経由で取得する必要がある__

なので、インストールする筐体とは別の端末にHTTPサーバを立てて、以下のファイルを公開する必要があります。

* Ignitionファイル
* Rawファイル
* RawファイルのSignatureファイル

端末にHTTPサーバを立てる方法は「[ワンライナーWebサーバを集めてみた](https://qiita.com/sudahiroshi/items/e74d61d939f18779970d)」がわかりやすいと思います。

## 本調理

### １．Liveブートする

作成したブータブルメディアを使用して、サーバを起動します。

### ２．Ignitionファイルを取得する。

``wget``コマンドで簡単、とはいきません。なぜならFCOSのLive環境にはwgetコマンドがないから。
そのため、``curl``コマンドとリダイレクトを使用してIgnitionファイルを取得します。

``` bash
curl http://192.168.xxx.xxx:5000/fcos.json | fcos.json
```


### ３．インストールコマンドを実行する

後はコマンドを１つ叩けばOKなのですが、ここで注意が必要です。

#### もし、すでに他のパーティションがディスクにあったら……

おま環かもしれませんが、インストール処理が途中でエラーになってしまいました。
そのため、インストールを行う前に、ディスクのワイプを行いました。
今回はSATA接続のHDDが乗っているので、以下のコマンドでワイプしました。

``` bash
# -v：進捗を表示
# -n [count]：乱数の書き込み回数。デフォルトは３回
shred -v -n 1 /dev/sda
```

#### いざ実行

コマンドは以下の形で実行しました。
もしかしたらショートパラメータで指定すると、エラーになるかもです。少なくともFilunKはエラーになりました。

``` bash
# install： サブコマンド
# /dev/sda：インストール先デバイス
# --ignition [path]：Ignitionファイルのファイルパス
# --image-uri [uri]：OS実体データのリソースパス
sudo coreos-installer install /dev/sda\
--ignition fcos.json \
--image-uri http://192.168.xxx.xxx:5000/fedora-coreos-31.20200118.3.0-metal.x86_64.raw.xz
```

コンソールにERRORのログが出てこなければ正常終了です。よくあるLinuxのインストールのように、『再起動してください』なんてメッセージはなく、ただ処理がリターンされるbashでよく見る動きなので拍子抜けかもしれません。

こうなればブートメディアを抜いて再起動です。

``` bash
sudo systemctl reboot
```

で、うまく行くと思うでしょ？

ところがどっこい、[初回ブートの際にNetworkManagerの設定が正しく反映されない](https://github.com/coreos/fedora-coreos-tracker/issues/358)という既知の問題があるわけで、初回は全く見当違いのIPアドレスが割り振られます（ネットワーク内にDHCPがある場合）。そのため、

* SSH接続をして（DHCPから割り振られたIPアドレスは少し待つとコンソールに表示されます）から再起動し直す。
* 強制電源断で再起動

する必要があります。

## そうして稼働したFedora CoreOS

とりあえずなんとか起動して、SSH接続もできる状態になりました。あとはこの上でコンテナを立てていくだけですね。
まあ、__コンテナを立てるのも勉強しながらなのですが__。

## 参考

[さくらのナレッジ - Container Linuxの後継となる新たなコンテナ向けOS「Fedora CoreOS」](https://knowledge.sakura.ad.jp/23287/)
[仮想化通信 - Fedora CoreOSを使う](https://tech.virtualtech.jp/entry/2019/11/26/181622)