Amazon Linux 2 をローカル仮想マシンで実行したくてSeed.isoをWindowsで作った「だけ」

# 目的

Amazon Linux 2 を 個人PCのローカル仮想マシンで実行するときに、
ISOファイルを自作する必要があります。
このISOファイルの作成で困ったので、ドキュメントとして残します。

これを読めば、あなたも今日からローカルAL2！
AWSを使い慣れていてAmazon Linuxをローカルでも使いたいなというときに便利です。

# Amazon Linux 2 をオンプレミスで！

これです。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/amazon-linux-2-virtual-machine.html

AWSでお世話になっている、Amazon Linux をオンプレミスでも活用してハッピーになりましょう。


# モチベーション

最近のCPUだと**WSL2ベースのDockerが使える**ので、VirtualBoxでAmazonLinuxするよりもハッピーになれます。
そう、Development Environment On Docker On WSL2 On Windows 10 です。

しかし今回は、VirtualBoxで動作検証をしています。
そもそもWindows10ProでWSL2のDockerを使って開発しようと考えていましたが、
古いCPUで**仮想化機能が物理レベルで足りなくて**できませんでした。

そこで、**Development Environment On Docker On AL2 On VirtualBox On Windows 10 をしよう！！**と、
「簡単に出来るのならAWSの従量課金を節約しよう」と、そういうわけです。

# isoが作れない

上記の公式ガイドで概要は理解できるし、とても丁寧に書かれていて助かります。
ところが、Windowsで作業していると「isoの作成」という壁が立ちはだかるのです。

（※WSL使えばいいじゃん）

### そもそもisoって？

isoというのは、CD/DVDにデータを書き込むためのイメージファイルです。
拡張子が、isoでもimgでも中身は同じです。
ここまでは良いでしょう。しかし、問題はこの先です。

### じゃあ作ってみよう

Linux系 ではこうやります。

```
genisoimage -output seed.iso -volid cidata -joliet -rock user-data meta-data
```

Unix系ではこうです。

```
hdiutil makehybrid -o seed.iso -hfs -joliet -iso -default-volume-name cidata seedconfig/
```

え？Windowsは？


### うっせぇわ

 Windowsに`genisoimage`？`hdiutil` ？`mkisofs`？そんなもの無いと見せつけてやる！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/2aa01c30-050e-7f46-d722-620c8885494d.png)

> 最新の流行は当然のIaC
> コンテナの状態もKibabaでチェック
> GitでPullしてDockerでRun
> 最近じゃ当然のツールです

> はぁ！？うっせぇうっせぇうっせぇわ
> 一切合切ペンギンな
> あなたじゃわからないかもね？

という歌詞があるとかないとか。

# 解決方法

CDRTFEを使います。

https://cdrtfe.sourceforge.io/

このGUIソフトにCUIがあり、`mkisofs`が含まれます。これを使いましょう。

公式サイトからインストーラーをダウンロードして使うか、
Chocolateyを使ってインストールします。

Chocolateyの場合のインストールコマンドです。

```posh
choco install cdrtfe -y
```

インストールが終わると、

`C:\Program Files (x86)\cdrtfe\tools\scripts\cmdshell.cmd`というバッチファイルがあります。
これをダブルクリックしてWindowsシェルを起動します。このバッチファイルが何をしているかというと、`cygwin`と`mkisofs`が使えるように環境変数`Path`を一時的に設定してくれています。環境変数は立ち上がったシェルを閉じたら元に戻ります。

立ち上がったシェルで`mkisofs`コマンドを実行してみます。

```
mkisofs: Missing pathspec.
Usage: mkisofs [options] [-find] file... [find expression]

Use mkisofs -help
to get a list all of valid options.

Use mkisofs -find -help
to get a list of all valid -find options.

Most important Options:
        -posix-H                Follow sylinks encountered on command line
```

コマンドのヘルプが表示されましたね。
このまま、`cd`で`user-data`と`meta-data`があるディレクトリに移動します。
`user-data`と`meta-data`の書き方はAWSのドキュメントを参考にしてください。

```posh
cd "Path_To_SeedConfigurationDirectory_Include_TextFiles"
```

[**先ほどのAWSドキュメント**](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/amazon-linux-2-virtual-machine.html#amazon-linux-2-virtual-machine-prepare)から下記のコマンドをコピーしてきます。

```posh
genisoimage -output seed.iso -volid cidata -joliet -rock user-data meta-data
```

それを先頭のコマンド名を書き換えて使います。
`genisoimage`と`mkisofs`はコマンドオプションの互換性があるそうです。ソースが同じなのかもですね。

```
mkisofs -output seed.iso -volid cidata -joliet -rock user-data meta-data
```

その結果、seed.isoファイルが生成されます。その時のログです。

```
Total translation table size: 0
Total rockridge attributes bytes: 363
Total directory bytes: 0
Path table size(bytes): 10
Max brk space used 10000
183 extents written (0 MB)
```

# seed.isoを仮想マシンに入れよう

さて、生成したseed.isoを仮想マシンに入れてみてください。
仮想マシンが立ち上がって、下記のようなプロンプトが表示されたら成功です。

```
amazonlinux login:
```

もしかして、下記のように表示されましたか？

```
localhost login:
```

`localhost`の部分が`meta-data`ファイルの`local-hostname: amazonlinux.onprem`と対応しています。
ファイルの内容が間違っているか、ファイルが読み込めていないかのどちらかだと思われます。

# DNS設定

今回は仮想マシンをブリッジ接続にして、静的IPを設定しました。
DNSも固定IPです。`meta-data`ファイルには`network-interfaces`の設定はありますが、
DNSの設定項目が見つかりません。[**cloud-init Documentation**](https://cloudinit.readthedocs.io/en/latest/index.html)に書き換え方の詳細がありますが、私では見つかりませんでした。DNSに接続できないとインターネットゲートウェイに行けないので`yum`とかできません。詰みです。

### 同一LAN内のPC例

- IPv4 : 192.168.0.1/24
- Gateway : 192.168.0.254
- DNS1 : 203.0.113.0
- DNS2 : 203.0.113.1

### 仮想マシンの設定

```yml:./meta-data
local-hostname: amazonlinux.onprem
# eth0 is the default network interface enabled in the image. You can configure

# eth0 is the default network interface enabled in the image. You can configure

network-interfaces: |
  iface eth0 inet static
  address 192.168.0.2
  network 192.168.0.0
  netmask 255.255.255.0
  broadcast 192.168.0.255
  gateway 192.168.0.254
```

```yml:./user-data
# cloud-config

# cloud-config

users:
# A user by the name `ec2-user` is created in the image by default.

  - default
chpasswd:
  list: |
    ec2-user:amazonamazonamazonamazonamazonamazonamazonamazonamazonamazonamazonamazon
# In the above line, do not add any spaces after 'ec2-user:'.

# In the above line, do not add any spaces after 'ec2-user:'.

boot, add following ‘write_files’ section:
write_files:
  - path: /etc/cloud/cloud.cfg.d/80_disable_network_after_firstboot.cfg
    content: |
      # Disable network configuration after first boot

      network:
        config: disabled
```

# SSH設定



sshdの設定ファイルを編集してみます。

```
sudo nano -l /etc/ssh/sshd_config
```

今回は65行目あたりにあったパスワード認証設定を有効化しました。

```diff_conf
- PasswordAuthentication no
+ PasswordAuthentication yes
```

```
sudo service sshd restart
```

上記のsshd設定ファイルの編集を省くには、`seed.iso`を作成するときの`meta-data`に1行追加します。

```yml
ssh_pwauth: True
```

仮想マシンを稼働させているホストから接続してみます。

```
ssh ec2-user@192.168.0.2
```

# 途中でつまづいたところ

- [YAML](https://www.wikiwand.com/ja/YAML)の定義ではインデントにタブが無いためエラーになる。

# やっぱり止めた

いろいろ頑張ったのですが、やめます。ネットワーク設定ができないからです。

`
stages.py[ERROR]: Unable to render networking. Network config is likely broken: No available network renderers found. Searched through list: ['eni', 'sysconfig', 'netplan']
`
[更に調査した結果](https://forums.aws.amazon.com/thread.jspa?threadID=318632)としては、将来のリリースに期待するしかなさそうです。応急処置として手動設定するしかないですね。

というわけで、cloud-initで自動設定するのが難しいことが分かりました。
ただし、cloud-initのドキュメントを読み込めば解決できる可能性も残っています。
とはいえ、当初の目的が「簡単に・節約」だった以上はOUTです。

オンプレAmazonLinux君にはご退場いただきます。
今までありがとうございました。

# まとめ

WSL2を使おう。Dockerを使おう。k8sを使おう。

**Excelsior!**