HPC/AIを日々使うユーザーなら一度は口(耳)にしたことがある言葉ではないでしょうか?ディストリビューションこそ同じでも、バージョンが違えば内部構成は大きく違ってきます。それゆえ使いたいアプリケーションに対応できないケースが頻発します。そうした場合、必要な環境をどうやって用意すればよいでしょうか?
かつては開発元からソースのtar ballをダウンロードして来たり、今なら多くはgit cloneしてビルドしてインストールすることになります。しかし、ビルド自体に必要なツールやライブラリ、コンパイラのバージョンまで合わせる必要があったりと、芋づる式に作業が増え、だんだん何をしたかったのか訳が分からなくなってきます。ようやく目的のものが出来上がっても、他のツールの利用に支障がでたり、手元の環境でrootで作業している場合など、システムを損壊しているケースもあります。その後に動作確認やベンチマークによる性能を確認し、得られた結果の再現性もチェックします。状況によっては最初からやり直しになることもあります。実行環境を含めたアプリケーション環境の構成とは、かように骨の折れる仕事になります。複数のアプリケーションや、バージョンを共存させようとすると、さらに別のギミックが必要になります。
一部のインテグレータはそうした作業をサービスとして販売していますし、昨今では動作環境の構築手順をリポジトリ等で共有したり、内容をレシピと呼ばれるJSON等のファイルで記述して、半自動的に動作環境を再現してくれるツール(Spack等)があります。多用されるPythonに限ってみても、ディストリビューションによるパッケージ、pip を使ってシステムやユーザー環境にばらばらにインストールされたパッケージ群、pyenv, anaconda等による環境切り替えなど多岐に渡っており、自分がどれを使っているのか訳が分からなくなっているケースを散見します。こうした場合、動作環境そのものを個別に分離して管理し、システム毎の相性を排除できるコンテナを利用する方が、ずっと有利かつ安心でしょう。また、コンテナの場合は出来上がったイメージや、それを再現する定義ファイルをリポジトリにおいて配布するというフローが標準的に用意されています。
Singularityの主な開発者を擁するSylabs社からは、無償のオープンソース(BSDライセンス)であるCE(CommunityEdition)版と、有償サポート付きのPRO版を提供しています。もちろん基本的な使い勝手は変わりません。一方で脆弱性対応などセキュリティ問題については、CE版は最新版にのみ対策が取られるため、機能や仕様を維持したままセキュリティ対応が必要な場合はPRO版の導入を検討してください。またHPCngというコミュニティのリポジトリがしばらくコミュニティ版として運用されて来ましたが、2021年5月にプロジェクトをフォークしています。しばらく混乱しそうですが、弊社としてはSylabs社の仕様を標準として取り扱います。フォーク自体は3.8のリリース直前だったので現時点では機能的にほぼ同一です。
既にPRO版を導入されている環境の場合はそのままお使いいただき、手元の環境に管理者権限があれば公開リポジトリにある通りの方法でビルドしてインストールします。Golangの導入さえできれば先述のような困難はありません。権限を持っていない一般ユーザーがホームディレクトリへインストールしても、一部の機能を除いて利用可能です。RHEL/CentOSの場合はEPELリポジトリに最新ではないもののパッケージがありますが、UbuntuのuniverseリポジトリにあるSingularityは同名のゲームですのでご注意ください(筆者はプレイしたことありません)。またWSLではカーネルの問題で、イメージ変換の一部は可能ですが、肝心のコンテナ実行ができません。
SingularityのイメージはSIF(Singularity Image Format)という独自のシングルファイル形式と、それを手元のファイルシステムに展開したsandbox形式の2種類となっています。一方、その元になるイメージとしては配布されているさまざまなイメージを再利用できます。またSingularityは以下のメジャーなリポジトリから直接イメージを取得して利用することができます。
ここではCentOS7の環境上で、DockerHubからUbuntu21.04LTSのイメージを取得して使ってみます。
$ singularity version 3.7-4.el7 $ singularity pull docker://ubuntu:21.04 INFO: Converting OCI blobs to SIF format INFO: Starting build… Getting image source signatures Copying blob 966b3c5c8637 done Copying config 7077954789 done Writing manifest to image destination Storing signatures 2021/07/19 17:01:13 info unpack layer: sha256:966b3c5c8637e41360eed39a59e6c16ee1e986f7f2b92244e4d39f7ca6669618 INFO: Creating SIF file… $ ls -l ubuntu_21.04.sif -rwxrwxr-x 1 pteck pteck 30900224 Jul 19 17:01 ubuntu_21.04.sif
単純にDockerのイメージを取得し、SIF形式に変換して保存します。pull サブコマンドの次に次のようにファイル名を指定することもできます。
$ singularity pull hippo.sif docker://ubuntu:21.04
できたイメージは意外なほど小さいことにお気づきでしょうか。SIFは内部でSquashFSという圧縮ファイルシステムを利用しており、デフォルトではgzip圧縮がかかっているためです。それではコンテナを起動し、その中で何らかの処理を実行してみましょう。
$ head -n 2 /etc/os-release NAME="CentOS Linux" VERSION="7 (Core)" $ singularity exec hippo.sif head -n 2 /etc/os-release NAME="Ubuntu" VERSION="21.04 (Hirsute Hippo)" $ singularity exec hippo.sif dpkg -l bash Desired=Unknown/Install/Remove/Purge/Hold | Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend |/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad) ||/ Name Version Architecture Description +++-==============-============-============-================================= ii bash 5.1-2ubuntu1 amd64 GNU Bourne Again SHell $ rpm -q bash bash-4.2.46-34.el7.x86_64
CentOS7の中にいるにも関わらず、hippo.sifにインストールされているUbuntu 21.04の内容が見えています。つまりこのコンテナの中ではユーザーはUbuntuの環境で作業ができます。ただし、コンテナはOSそのものを入れ替えているわけではないので、カーネルはCentOS7のままです。試してみます。
$ uname -r 3.10.0-1160.15.2.el7.x86_64 $ singularity exec hippo.sif uname -r 3.10.0-1160.15.2.el7.x86_64
確かに同一のカーネルです。このためカーネルバージョンに依存するプログラムなどでは問題が生ずることがあります。
さて、ここからがSingularityの主な特徴であるイメージファイルがシングルファイルで、かつ直接実行可能ということを示します。
$ ./hippo.sif head -n 2 /etc/os-release NAME="Ubuntu" VERSION="21.04 (Hirsute Hippo)"
そして、デフォルトでは起動したユーザーがコンテナ内に引き継がれており、ホームディレクトリも共有されていて、コンテナの外と同様に使うことができます。また、プロセス情報もコンテナの内外で同様に確認できます。以下のようにして試してみましょう。
$ ./hippo.sif ls -l ~ total 125776 drwx--x--x. 26 pteck pteck 4096 Jul 13 16:11 . drwxr-xr-x 1 pteck pteck 60 Jul 19 17:19 .. -rw------- 1 pteck pteck 16518 Jul 19 11:19 .bash_history -rw-r--r--. 1 pteck pteck 40 Oct 30 2020 .bash_logout -rw-r--r--. 1 pteck pteck 234 Oct 27 2020 .bash_profile -rw-r--r--. 1 pteck pteck 274 Nov 27 2020 .bashrc drwxrwxr-x. 8 pteck pteck 86 Mar 25 10:43 .cache ....... $ ./hippo.sif ls -l ~/.. total 4 drwx--x--x. 26 pteck pteck 4096 Jul 13 16:11 pteck $ ./hippo.sif tail /etc/passwd _apt:x:100:65534::/nonexistent:/usr/sbin/nologin pteck:x:1000:1000:Pacific Teck Japan:/home/pteck:/bin/bash
このようにホームディレクトリは自身のものだけが取り込まれており、他のユーザーについてはホームディレクトリのみならず、ユーザー名も引き継がれません。他のユーザーのホームディレクトリへシンボリックリンクがあっても、コンテナ内ではリンク切れとなりますのでご注意ください。
$ ./hippo.sif sleep 120 & [1] 30871 $ ps gux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND pteck 11166 0.0 0.0 139208 25700 tty1 Ss Jun08 0:00 -bash pteck 27618 0.0 0.0 173904 2528 ? S 16:06 0:00 sshd: pteck@pts/0 pteck 27619 0.0 0.0 139352 26048 pts/0 Ss 16:06 0:00 -bash pteck 30871 1.3 0.0 903344 19512 pts/0 Sl 17:30 0:00 Singularity runtime parent pteck 30885 0.3 0.0 2520 692 pts/0 S 17:30 0:00 /usr/bin/sleep 120 pteck 30904 0.0 0.0 155452 1876 pts/0 R+ 17:30 0:00 ps gux
プロセス空間も同一になるので、このようにコンテナの中と外のプロセスをどちらからも透過的に見ることができます。
今回はSingularityを使ってDockerHubにあるイメージからSIFイメージを作成・実行して、Singularityの基本的な動作を見てみました。
次回はこれにカスタマイズを入れて、独自イメージの作成を実施してみます。