2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

NGCコンテナをカスタマイズしてSingularity Image Fileを作る

Last updated at Posted at 2021-02-23

はじめに

コンピュータビジョンの研究に取り組む大学院生です。
研究に関連する実験は研究室のサーバーや産総研のサーバーABCIに接続して行っています。この時、Singularityを使って仮想環境を構築しています。Singularityとは?というお話はこちらの記事が詳しいのでこちらを参照していただければと思うのですが、簡単に言えば「管理者権限が無くても実行できるDockerのようなもの」というように私は認識しています。管理者権限を持っているローカルのマシンでSingularityイメージを作成して、これを管理者権限を持っていないサーバーにアップロードすることで、同じ仮想環境をサーバー上に用意することができるという感じです。

Singularityでは、DockerコンテナをSingularityイメージに変換することも可能で、今まではNVIDIA GPU Cloud (NGC)で提供されているPyTorch用のコンテナを利用していたのですが、このコンテナではOpenCVが上手くインポートできない(依存しているパッケージがインストールされておらず、インストールには管理者権限が必要)ということが私の中で問題になり、このコンテナをベースにしてカスタマイズしたSingularityイメージを作成しようということになりました。

NGCのユーザーガイドでは、Dockerfileを書くなどしてNGCコンテナをカスタマイズするやり方は載っていたのですが、Singularityで使うという今回の目的を満たすには、カスタマイズしたコンテナをDocker Hubにアップロードして、それをSingularityイメージに変換するというやや遠回り感のある工程になりそうだったため、Singularity定義ファイルを作ることでNGCコンテナをカスタマイズしたSIngularityイメージを作成するということを試みました。本記事はこの作業の備忘録になります。

本記事の流れ

環境

  • OS: macOS BigSur 11.2.1
  • Homebrew 3.0.1

Homebrewのインストール

Homebrewのインストールでは以前こちらの記事で紹介しているのでこちらをご参照ください。

VirtualboxとVagrantのインストール

MacでSingularityを動かすためにまずVirtualboxとVagrantを導入します。VirtualboxやVagrantとは?みたいな話はこちらの記事が詳しいです。簡単に言うとこの2つで仮想マシンを構築します。

以下でしばらくhomebrew-caskの導入について書いてますが、homebrew-caskを新たに導入する必要がないことが判明したので、しばらく読み飛ばしてください。

Homebrewは導入済みだったのですが、CUIベースでないアプリケーションをインストールするにはHomebrew-caskを導入する必要があったので、まずHomebrew-caskを以下のコマンドで入れます。

$ brew install cask

するとCLT(CommandLineTools)が最新版じゃないと怒られてしまいました。

なので指示通りにCLTを最新版にします。

$ sudo rm -rf /Library/Developer/CommandLineTools

パスワードが聞かれるので入力します。その後、次のコマンド。

$ sudo xcode-select --install

これを実行すると突然GUIウィンドウが出てきて「インストールしますか?」みたいなことを聞かれるので「インストールする」を選ぶとインストールが始まります。

Homebrew-caskのリポジトリによるとHomebrew-caskはHomebrewに統合されたみたいで新たにインストールする必要ないみたいです。
次のコマンドでbrewのバージョンを確認するとhomebrew-caskもちゃんと入っていることが確認できます。

$ brew -v

brew_ver.png
なので、brew caskでインストールしたい場合もbrew cask installと明示的に書く必要はなく、普通にbrew installでvitualboxやvagrantをインストールできます。

$ brew install virtualbox && \
  brew install vagrant && \
  brew install vagrant-manager

以下のコマンドを実行することで、これらがhomebrew-caskでインストールされていることを確認できます。

$ brew list --cask

このコマンドは、以前はbrew cask listというコマンドだったようで、実行することでhomebrew-caskでインストールしたソフトウェアの一覧が表示されます。

virtulaboxとvagrantのインストールが終わったら、システム環境設定でこれらの使用を許可する必要があります。(参照:Vagrant upでエラーが出て躓いた時の解決方法)

仮想マシンの立ち上げとSingularityのインストール

今回はSingularity 3.5をインストールします(これはABCIで使えるSingularityのバージョンが3.5なので、これに合わせています)ので、Singularity 3.5のドキュメントに従って仮想マシンにSingularityをインストールします。

Vagrantfileという、仮想マシンの設定ファイルを保存するディレクトリを作ります。

~$ mkdir vm-singularity && \
   cd vm-singularity

次に、仮想マシンにSingularity 3.5をインストールします。

~/vm-singularity$ export VM=sylabs/singularity-3.5-ubuntu-bionic64 && \
                  vagrant init $VM

これでSingularityがインストールできたら仮想マシンを立ち上げます。
動作は確認していませんが、後述のように、容量がデフォルトの20GBでは足りないことが明らかな時は仮想マシンを立ち上げる前にVagrantfileを先に書き換えておくと、後々楽かもしれません(この辺りの話は情報提供いただければ幸いです)。

~/vm-singularity$ vagrant up && \
                  vagrant ssh

これでターミナルの表示が

vagrant@vagrant:~$ 

のようになり、仮想マシンを操作することができるようになります。
次のコマンドでSingularityが正しくインストールされているか確認することができます。

vagrant@vagrant:~$ singularity version

手元では3.5.1と表示されました。

仮想マシンに割り当てるディスクを増やす

デフォルトでは仮想マシンには20GBのディスクが割り当てられていましたが、これでは足りなかった(singularity buildを実行した際にno space left on deviceというエラーが出ます)ので増設を試みます。
ディスクサイズはdf -hコマンドで確認できます。
スクリーンショット 2021-02-23 1.21.16.png
/にマウントしている/dev/mapper/vagrant--vg-rootのSizeが19Gとなっています。今回はこれを増量します。
まずは先程作ったディレクトリ~/vm-singularityの直下にあるVagrantfileを編集します。
仮想マシンに入ってしまっている場合は一度出て、仮想マシンを停止します。

vagrant@vagrant:~$ exit
~/vm-singularity$ vagrant halt

次にVagrantfileの編集によってディスク容量を増やせるようにする、vagrant-disksizeというプラグインをインストールします(参照:Vagrantfileに一行書くだけでVMのディスク容量を増やす方法)。

~/vm-singularity$ vagrant plugin install vagrant-disksize

ここからVagrantfileを編集します。最初にvagrant upをする前にVagrantfileの編集をしておくと、Vagrantfileの編集以降の作業は省略できる可能性があります(確認はしていません)。

~/vm-singularity$ vim Vagrantfile

次の1行を加えます。

Vagrantfile
Vagrant.configure("2") do |config|
    config.vm.box = "sylabs/singularity-3.5-ubuntu-bionic64"
    config.disksize.size = '30GB' # <=この行を新たに追加する。 

ここでは30GBとしていますが、今回用いるNGCコンテナがそれなりに大きいファイルであり、実際にやってみると30GBでも足りず、再び増量することになってしまい二度手間だったので最初から50GBにしておくと良かったです(40GBでもやってみましたがそれでも足りず、50GBにしたら最後までできるようになりました)。
ただし、このやり方はディスクを増やすことはできても減らすことはできないようなので、n度手間でも少しずつ増やしていくのが良いのかもしれません。
次に仮想マシンを再び立ち上げ接続します。立ち上げ時のメッセージで

==> default: Resized disk: old 20480 MB, req 30720 MB new 30720 MB
==> default: You may need to resize the filesystem from within the guest.

という表示があり、Vagrantfileの内容が反映されていることが確認できます。
しかし、このままではまだ/dev/mapper/vagrant--vg-rootに割り当てられたディスクの容量は増えていません。df -hコマンドで確認してみると19Gとなったままでした。
そこでこちらの記事を参考に、以下の操作を行いました。
まず次のコマンドでディスクの状態を確認します。

vagrant@vagrant:~$ sudo fdisk -l

スクリーンショット 2021-02-23 1.37.31.png
ディスク/dev/sdaには30GB割り当てられているものの/dev/mapper/vagrant--vg-rootには19GBしか割り当てられていないことが確認できます。
またDeviceは/dev/sda1の一つだけであることも確認できます。このDeviceのId8eは次のステップで必要になるのでデバイスの状態は予め確認しておきましょう。
次にパーティションを作成します。

vagrant@vagrant:~$ sudo fdisk /dev/sda

コマンド実行後に表示される画面の指示に従って次のようにコマンドを打っていきます。

n # パーティション作成
p # primaryを選択
2 # パーティション番号(Deviceが1つだけなのでEnterを押してもデフォルトで2が選択されます)
Enter # パーティション開始位置(デフォルトのままいきます)
Enter # パーティション終了位置(デフォルトのままいきます)
t # タイプ変更
2 # パーティション番号
8e # 拡張したいパーティションと同じになるように、先程fdiskで確認したIdの文字列
w # 保存して終了

実際にこれらを行った画面は以下のようになります。
スクリーンショット 2021-02-23 1.37.44.png
ディスクの状態を確認します。

vagrant@vagrant:~$ sudo fdisk -l

スクリーンショット 2021-02-23 1.37.55.png
/dev/sda2が新たに加わっていることが確認できたら、一度仮想マシンを再起動し、再び接続します。

vagrant@vagrant:~$ exit
~/vm-singularity$ vagrant reload
~/vm-singularity$ vagrant ssh

次に先程作成したパーティション/dev/sda2の物理ボリュームを作成します。

vagrant@vagrant:~$ sudo pvcreate /dev/sda2

スクリーンショット 2021-02-23 1.40.20.png
物理ボリュームとは?みたいな話はこちらの記事が参考になりましたので興味のある方は覗いてみてください。
次はボリュームグループに新しいパーティションを追加します。
この際にボリュームグループの名前が必要なので次のコマンドで確認します。

vagrant@vagrant:~$ sudo vgdisplay

スクリーンショット 2021-02-23 1.47.06.png
するとVG Nameはvagrant-vgとなっていることが確認できましたので、次のコマンドでこのボリュームグループに新しいパーティションを追加します。

vagrant@vagrant:~$ sudo vgextend vagrant-vg /dev/sda2

次はディスクを拡張します。拡張したいディスクは/dev/mapper/vagrant--vg-rootであったので次のようにコマンドします。

vagrant@vagrant:~$ sudo lvextend -l +100%FREE /dev/mapper/vagrant--vg-root

スクリーンショット 2021-02-23 1.49.37.png
そして最後にファイルシステムを拡張します。ファイルシステムがext3もしくはext4の場合はresize2fsコマンドでできますが、そうでない場合は別のコマンドを使う必要があるようです。ファイルシステムは次のコマンドで確認できます。

vagrant@vagrant:~$ mount

一覧がたくさん出てきますが、/dev/mapper/vagrant--vg-rootを探すと以下のように書いてありました。

/dev/mapper/vagrant--vg-root on / type ext4 (rw,relatime,errors=remount-ro,data=ordered)

ファイルシステムがext4であることが確認できたので、こちらも先程と同様に/dev/mapper/vagrant--vg-rootを指定して、次のコマンドを実行します。

vagrant@vagrant:~$ sudo resize2fs /dev/mapper/vagrant--vg-root

スクリーンショット 2021-02-23 1.53.11.png
これで仮想マシンに割り当てるディスクの増量は完了しました。df -hコマンドで、/dev/mapper/vagrant--vg-rootの容量が30GBに増えていることが確認できました。
スクリーンショット 2021-02-23 1.53.26.png

Singularity定義ファイルの作成

定義ファイルを編集するためにまず仮想マシン内にvimをインストールします。

vagrant@vagrant:~$ sudo apt update
vagrant@vagrant:~$ sudo apt install vim

これで仮想マシン内でvimを使って定義ファイルを編集できるようになりました。
定義ファイルでは色々と設定することが可能ですが、ここではNGCコンテナでOpenCVを正しくインポートできるようにすることが目標なので、シンプルな定義ファイルを作成します。その他様々なオプションなどはSingularityのドキュメントを参照してください。
Singularity定義ファイルを次のように編集します。

my_pytorch.def
Bootstrap: docker
From: nvcr.io/nvidia/pytorch:20.12-py3

%post
    apt update
    apt -y upgrade

    # opencvが依存しているパッケージのインストール
    apt install -y libgl1-mesa-dev

    # singularity image fileのサイズをなるべく小さくするために余計なファイルを削除
    apt autoremove -y
    apt clean
    rm -rf /usr/local/src/*
    rm -rf /var/lib/apt/lists/*

    # pipのパスが通っていなかったため絶対パスでpipコマンドを使う
    /opt/conda/bin/pip install --no-cache-dir opencv-python

Fromの部分でベースにするNGCコンテナを指定しています。ここではNGCのPyTorchコンテナで最新のバージョンであるpytorch:20.12.-py3を選択しています。
また、余計なファイルを削除する部分はこちらの記事を参考にしています。

Singularity Image Fileの作成

ようやくここまで来ました。
先程作ったSingularity定義ファイルをビルドしてSingularity Image Fileを作成します。

vagrant@vagrant:~$ sudo singularity build my_pytorch.sif my_pytorch.def

ビルドには結構時間がかかります。実行が終わるとカレントディレクトリにmy_pytorch.sifができています。
仮想マシン内の/vagrantは仮想マシンを作成したディレクトリvm-singularityをマウントしていますので、次のようにすることで、Singularity Image Fileを仮想マシンの外に移すことができます。

vagrant@vagrant:~$ mv my_pytorch.sif /vagrant/my_pytorch.sif

すると~/vm-singularityの直下にmy_pytorch.sifが移動しています。
これを使用したいサーバーにscpコマンドなどで送るとサーバーでこの仮想環境を使用できるようになります。

実際にサーバーにこのmy_pytorch.sifを送り、ちゃんとOpenCVがインポートできるようになったことが確認できました。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?