CfnClusterとSingularityで、伸縮自在なコンテナHPC環境をつくる

記事タイトルとURLをコピーする

Click here to read in English.

前回の記事では、HPC用途に特化したコンテナSingularityAmazon EC2で動かしました。EC2インスタンスにSingularityをインストールし、OpenFOAMのコンテナをつくったり(build)実行したり(exec)してみました。ただし前回使用した環境はEC2インスタンスを1台立てただけであったため、大量のジョブを投入したり、複数のコアを使用するジョブを実行するには不向きでした

AWS上にEC2ベースでクラスタを立ち上げられるツールとしてCfnClusterがあります。これを使うと、ジョブスケジューラを含んだMasterノードと、 Auto Scalingにより増減するComputeノードから成るクラスタ環境を容易に構築できます

この記事では、CfnClusterを使用してSingularityが動作するクラスタ環境を構築し、OpenFOAMでParameter Sweepをするジョブを投入してみます。またジョブの実行結果をGUIで可視化します。最後に、この環境を使用するのに要したAWS利用料を確認します

構成図

今回構築する環境の構成は以下の図の通りです。ただし、CfnClusterにより構築される管理用のリソース(DynamoDBなど)は省略しています この記事で構築する環境は、3種類の役割を持ったサーバで構成されます。PrePost, Master, Computeの3種類です

PrePost(OS: Ubuntu)

このEC2インスタンスには、CfnClusterがインストールされています。ここで$ cfnclusterコマンドを実行することにより、クラスタの作成、削除、管理ができます。また手順の後半ではここにGUIをインストールして、クラスタで実行されたジョブの実行結果を可視化します

Master(OS: Amazon Linux)

このEC2インスタンスは、CfnClusterによって起動し管理されます。ジョブスケジューラがインストールされており、$ qsubなどのコマンドを実行することでジョブの投入・確認・削除や、Computeノードの状態確認ができます

Compute(OS: Amazon Linux)

このEC2インスタンス群はAuto Scaling Groupに所属しており、Masterでのジョブ投入状況によって増減します。今回の手順通りに環境を構築すると、0台から10台の範囲で増減します。OpenFOAMによる流体解析はこのインスタンス群で実行されます

CfnClusterの機能により、MasterとComputeの間ではNFSによりディスクが共有されます。OpenFOAMのジョブは、Singularity Hubからダウンロードしたコンテナを使って実行しますが、コンテナはこの共有されたディスクに保存されます

投入するジョブについて

こちらAWS Batchに関する記事と同様、OpenFOAMのチュートリアルの1つであるpitzDailyの流入境界条件を変えて、計720通りのシミュレーションを実行します。流入速度のx成分, y成分, z成分を、一定の範囲内で変化させます。せっかくSingularityを使うのでMPIを使用するジョブを流したいところですが、それはfuture workとします

やってみる

EC2へのSSH接続用Key Pairの作成

AWSマネジメントコンソールにログインし、お好みのリージョンを選択します。まずはEC2へのSSH接続で使用するキーペアを作成する必要があるため、"EC2"をクリックします。"Key Pairs", "Create Key Pair"の順にクリックし、作成するキーペアの名前を入力して"Create"をクリックします。秘密鍵(.pemファイル)のダウンロードウィンドウが開くので、なくさずに かつ 漏洩させずに保管しておきます

PrePostインスタンスの構築

VPC, Subnet, PrePostインスタンスなどを構築するため、CloudFormationを使用します。まず、使用するテンプレートをこちらからダウンロードしておきます。次に、マネジメントコンソールのトップ画面で"CloudFormation"をクリックします。CloudFormationをはじめて使う場合、以下のような画面が開くので"Create New Stack"を選択します 「ファイルを選択」のボタンをクリックし、先ほどダウンロードしたCloudFormationのテンプレートを選択します。その後"Next"をクリックします 次の画面で各設定項目を入力します

項目名 詳細
Stack name CloudFormationのstackの名称を入力します。迷ったら singularity-on-cfncluster とでもしておきましょう
InstanceTypeParameter PrePostのインスタンスタイプを選択します。今回の手順通りの内容であればt2.microで十分動作します
KeyPairName PrePostへのSSH接続で使用するキーペアを選択します
SourceIp PrePostへのSSH接続元として許可するIPアドレスを入力します。通常はこちらにアクセスした際に表示されるIPアドレスの末尾に/32をつければよいです

IAMリソースが作成されることを理解してチェックを入れ、"Create"をクリックします これでCloudFormationによる環境自動構築が始まります。自動的にPrePostがlaunchされ、CfnClusterがインストールされます

CfnClusterによるクラスタの構築

ここから、構築されたPrePostにSSH接続し、CfnClusterを実行してクラスタ(MasterおよびComputeノード)を構築します。CloudFormation stackのOutputs欄に、PrePostIpという項目でPrePostのグローバルIPが表示されています このIPに対して、以下の認証情報でSSH接続します

項目名 設定値
ユーザ名 ubuntu
Key Pair CloudFormation stack作成時に選択したKey Pair

SSH接続できたら、以下のコマンドを実行して、CfnClusterの設定ファイルを開きます

$ vim .cfncluster/config

このファイルの内容が表示されるはずです。修正すべきか所が、{Region}, {AccessKey}のように{ }つきで表示されています。それぞれ、CloudFormation stackのOutputs欄に表示されている内容に修正します

この設定ファイルでは、2種類のクラスターテンプレートを定義しています。1つめのt2_singularityは、全てのノードがt2.microで起動します。クラスタでジョブを意図したとおりに実行できるかを、少量のジョブを投入しながら確認するときなどにおすすめです。2つめのc4_singularityは、全てのノードがc4.xlargeで起動し、同一のPlacement Groupに所属します。こちらは大量にジョブを実行する際におすすめです。どちらのクラスタにもSingularityが自動的にインストールされます。Computeノードは0台から10台の間で自動的に増減し、spotインスタンスで起動します

今回はc4_singularityの設定でクラスタを起動します。以下のコマンドを実行すると、クラスタが自動で構築されます

$ cfncluster create cluster01 -t c4_singularity

ちなみに、設定ファイルのcluster_template = t2_singularityの部分でデフォルトをt2_singularityにしているため、-tオプションなしだとt2_singularityの設定で構築されます。構築が完了すると、以下のようにMasterのIPアドレスが標準出力されます

$ cfncluster create cluster01 -t c4_singularity
Beginning cluster creation for cluster: cluster01
Creating stack named: cfncluster-cluster01
Status: cfncluster-cluster01 - CREATE_COMPLETE
Output:"MasterPublicIP"="xxx.xxx.xxx.xxx"
Output:"MasterPrivateIP"="yyy.yyy.yyy.yyy"
Output:"GangliaPublicURL"="http://xxx.xxx.xxx.xxx/ganglia/"
Output:"GangliaPrivateURL"="http://yyy.yyy.yyy.yyy/ganglia/"

Masterでのジョブの投入

表示されたMasterのグローバルIPに対して、以下の認証情報でSSH接続します

項目名 設定値
ユーザ名 ec2-user
Key Pair CfnClusterの設定ファイルで指定したKey Pair

SSH接続できたら、以下のコマンドを実行します

$ git clone https://github.com/TakahisaShiratori/singularity-on-cfncluster.git
$ cd singularity-on-cfncluster
$ python submit_batch.py

submit_batch.pyは、OpenFOAMのコンテナをダウンロードした後、pitzDailyの流入境界条件を少しづつ変えながら720のジョブを投入します。最後に$ qstatを実行し、投入されたジョブの一覧を表示します。ジョブが投入されてからComputeノードがlaunchされるため、ジョブの完了まで少々時間がかかります(CfnClusterの設定ファイルでinitial_queue_sizeを増やしておくと、常時その台数のComputeノードが起動するため、即ジョブが実行されるようになります)。可視化までやってみたい方は、この待ち時間の間に計算結果の可視化の項の最初のコマンドを実行しておくのがおすすめです。ジョブが完了してから$ lsをすると、計算結果を格納した各ジョブごとのディレクトリがあることが分かります

計算結果の可視化

せっかく計算ができたので、PrePostにOpenFOAMとGUIをインストールして、結果を可視化してみます。計算結果のファイルは、保存されているディスク(Masterの/home)をPrePostにNFSマウントして読み込みます。以下の手順ではX2GoとUbuntu MATEを使用しますが、他にお好みのGUIがあればそれをご使用ください

PrePostにSSH接続して、以下のコマンドを実行します

$ wget https://raw.githubusercontent.com/TakahisaShiratori/singularity-on-cfncluster/master/install_openfoam_gui.sh
$ bash install_openfoam_gui.sh

wgetで入手しているinstall_openfoam_gui.shには、OpenFOAM, X2Go ServerとUbuntu MATEのインストールコマンドが記載されています。インストール完了まで時間がかかるので、しばらく待ちます

インストールが完了したら、X2GoクライアントでPrePostに接続します。X2Goクライアントの使い方は、CFD Directこちらのページが参考になります。接続できたら、NFSマウントに必要なツールをインストールし、マウントポイントを作成します。ターミナルを立ち上げて以下のコマンドを実行します

$ sudo apt-get -y install nfs-common
$ sudo mkdir /cluster01_home

NFSマウントのための通信ができるよう、AWSのマネジメントコンソールからSecurity Groupの設定を変更します。cfncluster-cluster01-ComputeSecurityGroup-xxxxxxxxxxxxxのような名前のSecurity Groupがあるので、PrePostをこれに加えます 以下の{MasterPrivateIp}を置き換えてPrePostで実行すると、NFSマウントができます

$ sudo mount -t nfs -o hard,intr,noatime,vers=3,_netdev {MasterPrivateIp}:/home /cluster01_home

マウントが出来たら、OpenFOAM実行用ディレクトリ$FOAM_RUNを作成し、計算結果ファイルをそこにコピーして可視化します。コマンドとしては、例えばJob ID 1の実行結果を可視化する場合、以下の内容になります

$ mkdir -p $FOAM_RUN
$ sudo sh -c "cp -r /cluster01_home/ec2-user/singularity-on-cfncluster/job_* $FOAM_RUN"
$ sudo chown -R ubuntu:ubuntu $FOAM_RUN
$ cd $FOAM_RUN/job_1/pitzDaily
$ paraFoam

ParaViewが起動すれば成功です。表示内容をもろもろ設定すると、以下のように計算結果が表示されます

環境の削除

構築した環境をもう使わないのであれば、削除してAWS利用料がかからないようにします。その手順を以下に示します

まず、変更したPrePostのSecurity Groupを元に戻します。これをやっておかないと、クラスタの削除が途中で止まってしまいます

次にPrePostで以下のコマンドを実行し、クラスタを削除します

$ cfncluster delete cluster01

最後に、CloudFormationのstackを削除し、PrePost(EC2), Subnet, VPCなどを削除します

AWS利用料金の確認

私は上記の手順を、Singaporeリージョン(ap-southeast-1)で一通り実行しました。私が検証で使用したAWSアカウントでは、同リージョンには他のリソースが一切なく、上記手順のために要したAWS利用料金を把握しやすいためです。AWSマネジメントコンソールで確認したところ、0.57米ドルで実行できたようです

まとめ

本記事ではCfnClusterで構築したクラスタでSingularityを動作させました。これにより、コンテナの利便性、ジョブ量に応じた計算ノードの自動増減、MPIの利用の3つの要素を並立することができます。サンプルのジョブとしてOpenFOAMのチュートリアルの1つであるpitzDailyを720ケース実行しました。今回のサンプルジョブはMPIは使用していないので、機会があればMPIを使ったジョブが実行できるか試してみたいです