自動運転AIチャレンジのGPU環境をブラウザから実行してみた

# はじめに
[技術チャレンジ部](https://challenge-club.connpass.com/)のとも(Tomo)です。チームTPACで[自動運転AIチャレンジ2024](https://www.jsae.or.jp/jaaic/2024ver/summary/)に[参加中](https://www.jsae.or.jp/jaaic/2024ver/contest/)です。
[自動運転AIチャレンジ2024](https://www.jsae.or.jp/jaaic/2024ver/summary/)、楽しんでますか? 楽しむためには、開発環境も大切。
[こちら](https://github.com/AutomotiveAIChallenge/aichallenge-documentation-2024/issues/21#issue-2350681869)にある、
> 休日カフェでPC広げてのんびりと開発したいですよね。（切実）

…に共感! したい! を実現する方法として、今回はProxmox VEを使用してみました。
インストールしただけですが、GPUの活用や外部からのアクセスについても触れてみたいと思います。
詳細を解析しきれていない部分があるため、「やってみた」記事と思っていただければと思います。

# 環境
- PC: [ZBOX E](https://qiita.com/air-gh/items/d0721ec05abdab28fe01)
  - GPU: RTX 4070 Laptop GPU
- ホストOS: Proxmox VE
- ゲストOS(VM): Ubuntu 22.04 Desktop

# インストール
早速インストールにつまづきました。
今回使用したZBOX Eには、RTX 4070 Laptop GPUが搭載されていますが、CPU内蔵GPUは見えない(?)ようです。また、新しめのGPUは、インストールメディア内蔵のドライバーでうまく表示できないことがあるようです。
このあたりの事情は、GPUが内蔵されていないCPU + GPUの環境と同じかと思います。
Proxmox VEでは、インストールにGUIとCUIが選べるため、CUIを選んでインストールしました。インストール時に複雑な設定は不要なため、CUIインストールでも十分かと思います。

# ゲストOSのインストール
本大会では、Ubuntu 22.04 Desktopを使用しますので、以下のように準備しました。
- isoイメージを、画面左のlocal -> ISO イメージから、Ubuntuのインストーラーisoファイルをアップロード
- 画面右上のCreate VMから、VMを作成
  - OSで、Use CD/DVD disc image file (iso)を選び、ISO imageとしてアップロードしたisoファイルを選択

VMの主な設定は、以下のようにしてみました。
- System
  - Graphic card: Default
  - Machine: q35
  - BIOS: OVMF (UEFI)
- Disks
  - Bus/Device: VirtIO Block
- CPU
  - Type: host
- Network
  - Model: VirtIO (paravirtualized)

他にもTPMを有効にしたり、DisksでCacheを有効にするのもありかと思います。
メモリやストレージのサイズはお好みで。

そして、VMを起動してConsoleからUbuntuをインストールします。
これで、インストール後のUbuntuもブラウザから使えます。
[自動運転AIチャレンジのCPU環境](https://automotiveaichallenge.github.io/aichallenge-documentation-2024/setup/headless-simulation.html)は、もうブラウザで動きます。

…が、せっかくのGPUが、もったいない!

# GPUパススルー
VMのUbuntuからGPUが見えるようになれば、[自動運転AIチャレンジのGPU環境](https://automotiveaichallenge.github.io/aichallenge-documentation-2024/setup/visible-simulation.html)も動くかと思い、やってみました。
[本家Wiki](https://pve.proxmox.com/wiki/PCI(e)_Passthrough)を参考に、以下を実施しました。
- PCのBIOS設定
  - VT-dを有効化
- Proxmox VEのgrub設定
  - /etc/default/grubの`GRUB_CMDLINE_LINUX_DEFAULT`に`intel_iommu=on`と`iommu=pt`を追加
    - `GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_iommu=on iommu=pt"`となる
  - `update-grub`と再起動を実行し、上記を有効化
- VMの設定
  - 画面左の作成したVM -> 画面上のAdd -> PCI Device -> Raw Deviceで
    - RTX 4070を選択
    - All Functionsにチェック

![add-pci.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764521/e4e1bc52-17ac-4ea5-cb84-58a62732dcb2.png)

これで、VMのUbuntuを起動し、`lspci`を実行すると、
```
01:00.0 VGA compatible controller: NVIDIA Corporation Device 2820 (rev a1)
```
が見えるようになるかと思います。

VMのUbuntuを起動すると、ディスプレイに表示されていたProxmox VEのloginコンソールは表示されなくなるので、事前にsshでのログインを確認しておくのがよいかもしれません。

あとは、[自動運転AIチャレンジのGPU実行環境の構築手順](https://automotiveaichallenge.github.io/aichallenge-documentation-2024/setup/visible-simulation.html)を見ながら、nvidiaドライバーや描画ありAWSIMなどを入れて、GPU環境を実行すると、このような画面になります。

![console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3764521/f5c093ff-d6ed-29d4-bfd6-08efa874a0aa.png)

フレームレートは低いですが、雰囲気があるとモチベーションも上がるというものでしょうか。

…が、これだと、おうちではブラウザ開発ができるものの、カフェからアクセスできない…?

# 外部からのアクセス
Proxmox VEはブラウザからアクセスできるサービスなので、外部からそのホストのポートへアクセスできれば、外部からもアクセスできることになります。デフォルトでは、TCPの8006番ポートです。

外部からの特定ポートへのアクセスには、様々な方法があるので、検索していただければと思いますが、今回は以下の2つの方法を用意してみました。
いずれも分量がありそうな内容のため、設定の詳細は一旦省きますが、ご紹介までです。いつか別記事化したい!

## WireGuardによるVPN
ポートフォワーディングすれば外部からアクセスできるようになりますが、それだと誰でもアクセスできてしまいます。
外部から家のネットワークへのアクセスにVPNを用いれば、アクセスを限定できそうです。
技術チャレンジ部のメンバーに教えてもらった、[WireGuard](https://www.wireguard.com/)を入れて、アクセスできるように設定してみました。
WireGuardは接続がめっちゃ速いのがいい!

## OAuth2 Proxyによる認証付きリバースプロキシ
こちらも技術チャレンジ部のメンバーに教えてもらったのですが、[OAuth2 Proxy](https://oauth2-proxy.github.io/oauth2-proxy/)を入れれば、いろんなサービスに認証を付加できるとのこと。
これなら、ユーザーを限定しつつ、いろんな人に使ってもらうような運用ができそうです。

色々試した結果、リバースプロキシに[Caddy](https://caddyserver.com/)を使いつつ、[OAuth2 Proxy](https://oauth2-proxy.github.io/oauth2-proxy/)と[Dex IdP](https://dexidp.io/)で認証する運用に落ち着きました。

# おわりに
自動運転AIチャレンジ、切り口によっては様々な技術チャレンジにつながる要素が詰まっているように感じました。
一緒に大会を盛り上げていければと思います!