Cisco Modeling LabsをAWSで動かそう

Cisco Modeling Labs（以下「CML」）をAWSで動かしたのですが，調べて出てくる情報が古かったり足りなかったりして構築に結構苦労したので後世のためにメモを残しておこうと思います。

# 対象読者

- CMLをAWSで動かしたい
- AWSの以下サービスについて何をするサービスなのか知っている
    - EC2
    - S3
    - IAM

# 手順

大まかには以下のような流れです

1. ライセンスの購入
1. ovaファイル・refplat ISOのダウンロード
1. ダウンロードしたファイルを手元のPCのVMware Workstationで読み込んで仮想マシンを作成し，初期設定
1. 仮想マシンをovaファイルにエクスポート
1. ovaファイルをEC2のAMIとしてAWSにインポートさせる
1. AMIからEC2インスタンスを作成

ovaファイル→VMware Workstationで動作する仮想マシン→ovaファイル→AMI→EC2インスタンス
という風にめっちゃ形態変化を挟んでいて無駄だらけに見えますが，それぞれにちゃんと理由があるので我慢して読んでもらえると助かります。

:::note info

構築には金銭的コストがかかるため，一度構築した経験を元に思い出しながら書いています。

また，調べれば誰でもすぐに分かるような内容は省略していきます。

:::

:::note info

実は，CMLをAWSで動かすためのツールをCiscoが公式に公開しています。

https://github.com/CiscoDevNet/cloud-cml

これでもできるとは思うんですが，

> The use of this tool is considered BETA.

とあるので今回は使わずにいきます。

:::

## ライセンスの購入

[Cisco Learning Network Store](https://learningnetworkstore.cisco.com/)で買えます。

https://learningnetworkstore.cisco.com/

実は，CMLはバージョン2.8からライセンス無しでも制限付きでシミュレーションができるようになっています。しかし，それと同時に搭載OSがUbuntu 24.04に上がっています。後の手順でovaファイルをAWSにインポートさせる際に利用する「VM Import/Export」というサービスの要件でUbuntu 24.04が弾かれる（2024/12/29時点）[^VM-Importの要件]ため，この記事ではライセンス必須のCML 2.7.2を想定して説明をしています。

[^VM-Importの要件]: 【参考文献】aws．“VM Import/Export でインポートするリソースの要件”．VM Import/Export　ユーザーガイド．[https://docs.aws.amazon.com/ja_jp/vm-import/latest/userguide/prerequisites.html](https://docs.aws.amazon.com/ja_jp/vm-import/latest/userguide/prerequisites.html)，(参照 2024-12-29)．

## ovaファイル・refplat ISOのダウンロード

これら２種類のファイルは，[Cisco Learning Network Store](https://learningnetworkstore.cisco.com/)から無料でダウンロードできます。上でも述べた通り，バージョン2.8で構築してしまうと後でVM Import/Exportの要件に引っかかる（2024/12/29時点）ので2.7.2をダウンロードしてください。

ovaファイルは仮想マシンに関する情報を１ファイルに詰め込んだものです。今回ダウンロードしたファイルをVMware Workstationで読み込んでもらうと，ある程度設定の終わったCMLが仮想マシンとしてポンと出てきます。ovaファイルは，AWSに読み込ませてAMIやEC2インスタンスにすることもできます。
refplat ISOはCMLでシミュレーションする各種ルーター・スイッチなどについての情報が入ったISOで，後でCMLの初期設定をするときに使います。 ~~「refplat」で調べるとCML関連の情報しか出てこないため，多分Cisco語です~~

## CMLの初期設定

先ほどダウンロードしたovaファイルをAWSに読み込ませて…といきたいところですが，そうはいきません。初期設定が終わっておらずリモートアクセスできないからです。リモートアクセスができない仮想マシンをAWSで扱うのは困難です。
というわけで，最初はVMware Workstationを使って仮想マシンの初期設定をする他ないのです。

### 一通りの動作確認まで

VMware Workstationでovaファイルを開き，出てきた仮想マシンにrefplat ISOを１つ挿して起動します。すると，OSをインストールしたときのような感じで初期設定画面が開きユーザー名・パスワードやネットワーク設定について色々聞かれていきます。

:::note info

起動時に

> Ethernet0 に使用できる PCIe スロットがありません。Ethernet0 を削除してもう一度やり直してください。 

というエラーが出た場合は「仮想マシンのバージョンをアップグレード」みたいな名前のボタンを押して，今より新しいバージョンを指定してみると良いです[^仮想マシンのバージョンをアップグレード]。（この辺りはあまりよく分かっていないです）

[^仮想マシンのバージョンをアップグレード]: 【参考文献】フリーライターズ．“VMware WorkstationでCisco Modeling Labs 2（CML2）を起動しようとした際に、よく遭遇するエラーメッセージ「Ethernet0に使用できるPCIeスロットがありません」について”．Python転職初心者向けエンジニアリングブログ．2024-10-07．[https://warp.ndl.go.jp/info:ndljp/pid/12003258/jipsti.jst.go.jp/sist/handbook/sist02_2007/main.htm](https://warp.ndl.go.jp/info:ndljp/pid/12003258/jipsti.jst.go.jp/sist/handbook/sist02_2007/main.htm)，(参照 2024-12-27)．

:::

ユーザーは２つ作らされます。CMLを下で支えるUbuntuの管理者ユーザー（以下「サバ管」）と，ラボでルーターなどを触る用のユーザー（以下「ラボユーザー」）です。

ネットワーク設定では，必ずDHCPを有効にしてください。静的にアドレスを設定しても当分は大丈夫ですが，後でAWSに置いたとき困ります。
実は，AWS上でのIPアドレス設定というのは「このNICからDHCP問い合わせが来たらこのアドレスを返す」というものに過ぎません。そのため，仮想マシン側で静的にアドレスを設定してしまうとAWS上のアドレスとインスタンス上のアドレスが食い違ってしまいます。また，VPCではAWS上に設定されたアドレスしか通信できないようになっています。これらのことより，EC2インスタンスとしてDHCPは事実上必須です。

初期設定の途中ではrefplat ISOの中身を仮想マシン本体に取り込むところがあります。そのため，refplat ISOは初期設定が終われば用済みになります。一方，昔のCMLではrefplat ISOの中身を仮想マシン本体に取り込まず，シミュレーション中も常に挿して使っていました。EC2インスタンスにリムーバブルディスクを挿すのは難しいので，当時の記事では「refplat ISOのデータを仮想マシン本体にコピーした上で，refplat ISOが挿さっていなくても挿さっているかのようにデータを参照できるようにする」という曲芸を仮想マシンに施してからAWSに送り込んでいました。もちろん今はそんなことしなくても大丈夫です。
~~最初から全部まとめてovaファイルにしてくれればいいのに~~

ログイン画面っぽいところまでこれたら初期設定は完了です。

初期設定でデータを取り込めるrefplat ISOは１枚のみですが，別のrefplat ISOから追加でデータを取り込むこともできます。HTTPSで仮想マシンの9090ポートにアクセスしサバ管でログインすれば取り込むためのボタンを見つけられるかと思いますので，ISOを挿した上でそのボタンを押してください。

初期設定が完了したら次は，ライセンス認証を行います。HTTPSで仮想マシンの443番ポート（デフォルト）にアクセスしてラボユーザーでログインし， ~~後は調べてください。~~

ライセンス認証が終わったらラボを使用できるはずです。適当にネットワーク機器を配置してpingでもやってみてください。

<details><summary>途中で容量が足りなくなった人へ</summary>

CMLが動作するマシンはLVMというストレージ技術を使っています。LVMではPV（Physical Volume，物理的なストレージ領域）を「VG」（「Volume Group」）というものにまとめ，そのVGをLV（Logical Volume，論理的なストレージ領域）で分け合って利用します。

今回扱っているマシンではディスク/dev/sdaの１パーティションがPVになっており，それ単体でVGを構成しています。そのVGを利用して２つのLVが存在し，それぞれ「/」用・「/var/」用に使われています。容量が無くなる主な原因はrefplat ISOから取り込まれるデータですが，それは/var/配下に格納されるので/var/用のLVを拡張すれば大抵の場合なんとかなると思います。

残念ながらVGにも/dev/sdaにも空きは無いので，より物理的な所から

1. VMware Workstationで/dev/sdaの容量を拡張
1. partedコマンドでPV用パーティションの領域を拡張
1. pvresizeコマンドでPVを拡張
1. （VGの総容量は自動で拡張される）
1. VGに発生した空き領域を利用し，lvextendコマンドで/var/用LVを拡張
1. resize2fsコマンドでLVの中のファイルシステムを拡張

という順番に拡張を行ってください。

</details>

:::note info

参考：CMLへの各種アクセス方法
| ポート番号 | プロトコル | アカウント | 利用できる機能 |
|:-:|:-:|:-:|:-:|
| 443（デフォルト） | HTTPS | ラボユーザー | ラボ |
| 9090 | HTTPS | サバ管 | cockpit（WebでUbuntuを操作できるGUI） |
| 22（デフォルト） | SSH | ラボユーザー | コンソールサーバー（ラボの各ノードにコンソール接続するための踏み台） |
| 1122 | SSH | サバ管 | UbuntuのCUI（VMware Workstationで見れる画面と同じ） |

1122番ポートへのアクセスだけデフォルトでは無効化されているので，使いたい場合は

```bash
sudo systemctl enable --now ssh.service
```

で有効化してあげてください。

:::

:::note warn

動作確認ができたら，仮想マシンとCMLライセンスとの紐付けを解除してください。CMLライセンスは同時に１台の仮想マシンとしか紐付けられないので，AWS上で動くCMLにライセンスを紐付けられなくなります。

現在使っている仮想マシンへのWebアクセスはこの後の手順でできなくなりますので，今のうちにやっておくことをお勧めします。

:::

### BIOSへの対応

動作確認ができたので早速AWSへ…とはまだいけません。

実は，「EC2インスタンスの上で仮想マシンを動かせない」という制約があります。CMLはルーターやスイッチを仮想マシンとしてシミュレートしていますので詰みと思われるかもしれませんが，唯一ベアメタルインスタンス（インスタンスタイプが`*.metal`）を利用することでこの制約を回避できます。しかし，ベアメタルインスタンスにはベアメタルインスタンスで「UEFI非対応」という制約があります。

UEFIというのはコンピューターを起動して最初にマザーボードで動くファームウェアの一種で，現在操作している仮想マシンもUEFIを使っています。ベアメタルインスタンスがUEFIに対応していないため他の種類のファームウェアを使う必要があるわけですが，他に利用できるファームウェアはBIOSという種類しかないのでBIOSを使うように仮想マシンをいじっていきます。

#### GPTからMBRへの変換[^GPTからMBRへの変換]

UEFI・BIOSといったファームウェアには「ディスク上で最初に起動すべきプログラム（ブートローダー）を見つけて起動する」という役割がありますが，探される側のディスクがどのような形式でデータを置いているか分かっていないと探すものも探せません。
そのためUEFIはGPT，BIOSはMBRという形式でデータが書かれたディスクにのみ対応することになっています。

つまり，ファームウェアをUEFIからBIOSに変更するにはディスク形式をGPTからMBRに変換する必要があるわけです。

[^GPTからMBRへの変換]: 【参考文献】たい焼き太陽さん．“UbuntuでブートディスクをGPTディスクからMBRディスクに変換する方法（おまけでMBR→GPT変換する方法も紹介します）”．結果だけでなく過程も見てください．2021-01-27．[https://taiyakisun.hatenablog.com/entry/2021/01/27/011459](https://taiyakisun.hatenablog.com/entry/2021/01/27/011459)，(参照 2024-12-27)．

まずは

```bash
sudo gdisk /dev/sda
```

でディスク操作ツールを起動します。/dev/sdaは変換するディスクですね。

ツールを起動できたらrを入力してリカバリーモードに入ります[^GPTからMBRへの変換が面倒な理由]。
成功したらgを入力してディスク形式の変換を指示します。
最後に，wを入力してディスクに書き込みを行います。

[^GPTからMBRへの変換が面倒な理由]: UEFI・GPTはBIOS・MBRの後継という位置付けであり，機能的にもGPTはMBRに対して上位互換と言っても過言ではありません。そのため，GPTからMBRへの変換は上手くいかないケースもありますしわざわざやろうとする人も多くありません。そういった事情から，リカバリーモードでないとGPTからMBRへの変換ができないようになっているのだと思います。

これでディスク形式がGPTからMBRに変わります。

#### GRUBの設置

UEFIはGPT形式のディスク内の，指定された場所にあるブートローダーを起動します。一方，BIOSはMBR形式のディスクの先頭にあるブートローダーを起動します。ファームウェアがUEFIからBIOSに変わっても同じように起動してもらうためには，以前使っていたのと同じブートローダーをディスクの先頭に設置する必要があります。
先ほどディスク形式を変換するのに使用したツール`gdisk`はブートローダーに関しては何もしてくれませんので，ブートローダーをディスクの先頭に設置する作業はgdiskに頼らず自分で行う必要があります。

（ファームウェアがUEFIだったときの）CMLはブートローダーとしてGRUBを使っています。起動時に何秒間か水色の画面が出るアレです。よって，MBR化したディスクの先頭にもGRUBを設置していきます。
GRUBの設置を行うためのツールは以下のコマンドでインストールできます。元々`grub-efi`というパッケージが入っていますが，これはGPT用のものなのでMBR用の`grub-pc`をインストールします[^grub-efiとgrub-pc]。

[^grub-efiとgrub-pc]: 【参考文献】“Why can't (and how can) I install both grub-pc and grub-efi packages?”．ask Ubuntu．2020-09-28．[https://askubuntu.com/questions/1253207/why-cant-and-how-can-i-install-both-grub-pc-and-grub-efi-packages](https://askubuntu.com/questions/1253207/why-cant-and-how-can-i-install-both-grub-pc-and-grub-efi-packages)，(参照 2024-12-28)．

```bash
sudo apt update
sudo apt install grub-pc
```

後は

```bash
sudo grub-install --target=i386-pc /dev/sda
```

を実行[^grub-installのtarget]すればGRUBの設置は完了です。GRUBの設定ファイルはUEFIでもBIOSでも共通なので，ファームウェアがUEFIからBIOSに変わっても同じように起動できます。

[^grub-installのtarget]: 【参考文献】“grub-install(8)”．Arch manual pages．2024-09．[https://man.archlinux.org/man/grub-install.8.en](https://man.archlinux.org/man/grub-install.8.en)，(参照 2024-12-28)．

#### 仮想マシンのマザーボード種別を変更する

ディスク側の対応は終わったので，次はファームウェアを搭載するマザーボードをBIOS対応のものに取り替えます。
マザーボードの取り替えなので，仮想マシンをシャットダウンしてから作業してください（VMware Workstationも閉じてしまった方が良いです）。

マザーボードの取り替えはVMware WorkstationのGUIからは操作できず，設定が書き込まれたvmxファイルをテキストエディターで編集する必要があります。テキストエディターを開いたら`chipset.motherboardLayout`を探してください。値が`acpi`になっているかと思いますが，この種類のマザーボードはBIOSを搭載していません。なのでこれをBIOS対応の`i440bx`に書き換えればOKです。

:::note info

この操作以降，仮想マシンに挿したNICが認識されなくなります。マザーボードが原因なのは明らかですが，AWSに取り込んだ際にはAWSが用意した仮想マザーボード？で動作するようになりNICもきちんと使えるようになります。

今やっていることはあくまで，BIOSでCMLが起動できるかをテストするための手順だと思って進めてください。

:::

#### 仮想マシンをBIOSで起動する

仮想マシンをBIOSで起動する準備ができたので，実際に起動してみます。

仮想マシンの設定画面に移動し「オプション」タブの「詳細」に移動してもらうとUEFI・BIOSのどちらかを選ぶ項目がありますので，UEFIからBIOSに変更します。
変更したら仮想マシンを起動し，いつものように起動してきたら成功です！

## 仮想マシンのエクスポート

やっと，AWSで動かせる状態の仮想マシンができあがりました。というわけで，仮想マシンをovaファイルにエクスポートしていきましょう。

エクスポート操作自体はそこそこメジャーな機能なので，調べればすぐにできるかなと思います。一見すると拡張子「.ova」でエクスポートする選択肢が無いように見えますが，「.ovf」とファイル形式は全く一緒ですので拡張子だけ変えてあげればOKです。

## ovaファイルをEC2のAMIに変換する

最後に，エクスポートして出てきたovaファイルをEC2に取り込んでいきましょう。

実は，ovaファイルを直接EC2インスタンスに変換する方法もあります。しかし，この方法は何故かあまり推奨されていません。僕も直接変換すれば良いのでは，と思っているのですが，AWS公式すら「AMIに変換した方が良い」と言っているのでAMIへの変換でいきます。

ovaファイルをAMIに変換するためには，まずS3にovaファイルをアップロードする必要があります。いちいちS3を経由するのは面倒ですが，経由しない方法が無いので仕方ありません。

ovaファイルのアップロードが終わったらAMIへの変換を行っていきます。ovaファイルをAMIに変換するためのツールとしては

- AWS CLIの`import-image`コマンド
- Migration Hub Orchestrator（マネジメントコンソールのGUIで操作できる）[^Migration-Hub-Orchestrator]

[^Migration-Hub-Orchestrator]: 【参考文献】aws．“イメージとしての VM のインポート”．VM Import/Export　ユーザーガイド．[https://docs.aws.amazon.com/ja_jp/vm-import/latest/userguide/import-vm-image.html](https://docs.aws.amazon.com/ja_jp/vm-import/latest/userguide/import-vm-image.html)，(参照 2024-12-30)．

の２つがあります。後者はGUIなので使いやすそうで魅力的ですが，オンプレミスからAWSへの大規模な移行を一元管理するサービスらしいので仮想マシン１台をインポートするだけの用途には適さないかと思います。よって，この記事では`import-image`を実行してovaファイルをAMIに変換していきます。

### VM Import/Exportに権限を付与する

:::note info

これ以降AWS CLIでの操作が出てきますが，個人的にはCloudShellの利用がオススメです。中身はLinuxですが，AWS CLIがインストールされている上にマネジメントコンソールと同じユーザーでのログインも済ませてあるので環境構築一切不要でAWS CLIが使えます。

:::

これは公式資料にも書いてある注意点なのですが，特に設定をいじっていない環境で`import-image`をいきなり実行すると権限の問題が発生します。
実は，`import-image`を実行したユーザーはS3・EC2に直接アクセスしません。実際にS3・EC2へのアクセスを行うのは，`import-image`によって呼び出されたサービス「vmie.amazonaws.com」（VM Import/Export）です。しかし，vmie.amazonaws.comはデフォルトで何もアクセス権限を持っていません。

そこで，「vmimport」という名前のIAMロールを作成しておきます。「vmimport」の中身は[公式資料](https://docs.aws.amazon.com/ja_jp/vm-import/latest/userguide/required-permissions.html)にも載っているのでこの記事では割愛します。

https://docs.aws.amazon.com/ja_jp/vm-import/latest/userguide/required-permissions.html

vmie.amazonaws.comは`import-image`が実行された際「vmimport」という名前のIAMロールを探して勝手に自身に付与します。勝手にIAMロールを自身に付与できるのは，vmimportの信頼ポリシーでvmie.amazonaws.comにのみそういった行為が認められているからです。vmimportには`import-image`の実行に必要な範囲でS3・EC2へのアクセスを許可する旨が書かれているので，vmimportが付与されたvmie.amazonaws.comはS3・EC2にアクセスしてovaファイルをAMIに変換することができるわけです。

### `import-image`の実行

「vmimport」を作成して権限問題が解決したので`import-image`を実行します。基本的にはその辺に載っている実行例に倣ってやれば良いですが，注意点として

- `--license-type BYOL`を指定する
    - `BYOL`ではなく`AWS`にするとライセンスをAWSが管理してくれるようになりますが，CMLのライセンスはサポートされていないようです
- `--boot-mode legacy-bios`を指定する
    - ファームウェアをBIOSにするかUEFIにするか選択するオプションです

の２点[^import-image]だけ忘れずに書いて実行してください。

実行後，しばらく待つとAMIのできあがりです。

[^import-image]: 【参考文献】aws．“import-image”．AWS CLI Command Reference．[https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/import-image.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/import-image.html)，(参照 2024-12-30)．

## AMIからEC2インスタンスを作成する

この操作はAWSでも一般的なものなので情報もたくさんあるかと思います。

前にも述べた通り，インスタンスタイプをベアメタル（`*.metal`）にするのを忘れないようにしてください。

セキュリティグループについては，前に挙げた「CMLへの各種アクセス方法」の４ポートを許可しましょう。

SSH接続についてはユーザー名・パスワードでログインできるように既に設定されていますので，キーペアの設定は無くて良いかと思います。

# 最後に

ここまで構築できた方は，お疲れ様でした！！
AWSを使うと仮想マシンを簡単にインターネット公開できますが，一方では特有の制約が多くなかなか苦しめられたかと思います。 ~~CCNPより先にLinuCレベル１とAWS Certified Cloud Practitionerを取得していて本当に良かった…~~

最後に１つ，ベアメタルインスタンスの利用料金はめっちゃ高いので浮かれてお金を溶かさないようにだけ注意です！