AWS ParallelCluster 複数のS3バケットへのアクセス設定
AWS ParallelClusterで複数のS3バケットを利用したい場合、ParallelClusterの設定ファイルにどのように記述するとクラスターの運用をしやすいのか検証しました。
結論
s3_read_resource
と、s3_read_write_resource
で指定するS3バケットは各々複数指定できない- ただし、ワイルドカードを使えば複数バケットも指定できる
- 例)
s3_read_resource = arn:aws:s3:::*
- 例)
- ただし、ワイルドカードを使えば複数バケットも指定できる
- 複数のS3バケットへ細かいアクセス制限するには
additional_iam_policies
で任意のIAMポリシーを指定する - 任意のIAMポリシー内に複数S3バケットへのアクセス権限を設定して利用する
検証環境
ParallelClusterの設定項目である、読み取り専用のs3_read_resource
と、読み書きできるs3_read_write_resource
の設定書式は同じです。
本検証では読み取り専用のs3_read_resource
を例にあげています。
読み書きできるs3_read_write_resource
に置き換えていただいても設定方法は変わりありません。
項目 | 値 |
---|---|
ParallelCluster | 2.10.3 |
OS | Ubuntu 18.04 LTS |
AMI | aws-parallelcluster-2.10.3-ubuntu-1804-lts-hvm-x86_64-202103172101 |
Architecture | Intel |
HeadNode | t3.micro |
ComputeNode | c5.large |
S3バケットアクセス制御
Postainstallの説明からはじめます。カスタムブートストラップアクションとしてクラスター起動後にスクリプトを実行してクラスターの環境構築、ライブラリのインストールなど主にコンピュートノードのセットアップします。ParallelClusterではpostinstall scriptの機能で実現しています。
postinstall scripはS3バケットにシェルスクリプトを保存して利用します。ヘッドノード、コンピュートノードは初回起動時にS3バケットからスクリプトを読んで実行します。環境構築に必要なインストールが走る仕組みです。
そのためParallelClusterでHPCクラスターを構築するとpostinstall script保存用にS3バケット1個は必要になります。それ以外のS3バケットに保存してあるデータを取り出したい、計算・解析後にデータを異なるS3バケットに保存したいこともあります。
ParallelClusterの設定ファイルでどのように設定すると都合がよいのか検証します。
Working with Amazon S3 - AWS ParallelCluster
S3バケット情報
S3バケットを3個作成しました。各バケットにはテストファイルを保存してあります。
# Aバケット $ s3-tree blog-sample-bucket-a blog-sample-bucket-a ├── a.txt └── postinstall.sh 0 directories, 2 files # Bバケット $ s3-tree blog-sample-bucket-b blog-sample-bucket-b └── b.txt 0 directories, 1 file # Cバケット $ s3-tree blog-sample-bucket-c blog-sample-bucket-c └── c.txt 0 directories, 1 file
S3バケット1個へ読み取り専用アクセス
s3_read_resource
の項目にARNを指定してS3バケットへのアクセス権限を与えます。
Amazon リソースネーム (ARN) - AWS 全般のリファレンス
S3バケット名を1個指定してみます。
書式
s3_read_resource = arn:aws:s3:::[S3バケット名]/*
設定ファイル
以下のParallelClusterの設定ファイルでクラスターを作成しました。
# v2.10.3 [aws] aws_region_name = us-east-1 [aliases] ssh = ssh {CFN_USER}@{MASTER_IP} {ARGS} [global] cluster_template = default update_check = true sanity_check = true [cluster default] key_name = sandbox-key-useast1 scheduler = slurm # --- HeadNode Setting --- base_os = ubuntu1804 master_instance_type = t3.micro master_root_volume_size = 30 # --- Netowrk Setting --- vpc_settings = default # --- Compute Setting --- queue_settings = spot1 # --- PostInstall Setting --- s3_read_resource = arn:aws:s3:::blog-sample-bucket-a/* post_install = s3://blog-sample-bucket-a/postinstall.sh tags = { "Name" : "Blog-Sample-ClusterOK" } [vpc default] vpc_id = vpc-07edfc27679c9ca80 master_subnet_id = subnet-0ab2754446b2f87a4 compute_subnet_id = subnet-0ab2754446b2f87a4 use_public_ips = true # 検証用設定: パブリックサブネットで起動しているため [queue spot1] compute_resource_settings = spot1_resource placement_group = DYNAMIC compute_type = spot [compute_resource spot1_resource] instance_type = c5.large max_count = 16
S3バケットアクセステスト
ヘッドノードからaws s3
コマンドでS3バケットへアクセスしてチェックします。
Aバケットには読み取りアクセス権があるためダウンロードできました。
$ aws s3 cp s3://blog-sample-bucket-a/a.txt . download: s3://blog-sample-bucket-a/a.txt to ./a.txt
Aバケットへアップロードは権限がないためできません。
$ touch headnodet.txt $ aws s3 cp ./headnodet.txt s3://blog-sample-bucket-a upload failed: ./headnodet.txt to s3://blog-sample-bucket-a/headnodet.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Deniedk
Bバケットには権限がないためダウンロードはできません。
$ aws s3 cp s3://blog-sample-bucket-b/b.txt . fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden
ParallelClusterのIAMロール確認
s3_read_resource
の設定を入れるとIAMポリシー名S3Readが追加されます。設定ファイル内で指定したS3バケット名がResourceに登録されています。
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:Get*", "s3:List*" ], "Resource": [ "arn:aws:s3:::blog-sample-bucket-a/*" ], "Effect": "Allow", "Sid": "S3Read" } ] }
2バケットへ読み取り専用アクセス NGパターン
Bバケットにもアクセスしたいので以下の書式で設定ファイルを変更します。
NGパターンS3バケット指定の書式
s3_read_resource = arn:aws:s3:::blog-sample-bucket-a/*, arn:aws:s3:::blog-sample-bucket-b/*
設定ファイル
以下の設定ファイルでクラスターを作成しました。
# v2.10.3 [aws] aws_region_name = us-east-1 [aliases] ssh = ssh {CFN_USER}@{MASTER_IP} {ARGS} [global] cluster_template = default update_check = true sanity_check = true [cluster default] key_name = sandbox-key-useast1 scheduler = slurm # --- HeadNode Setting --- base_os = ubuntu1804 master_instance_type = t3.micro master_root_volume_size = 30 # --- Netowrk Setting --- vpc_settings = default # --- Compute Setting --- queue_settings = spot1 # --- PostInstall Setting --- s3_read_resource = arn:aws:s3:::blog-sample-bucket-a/*, arn:aws:s3:::blog-sample-bucket-b/* post_install = s3://blog-sample-bucket-a/postinstall.sh tags = { "Name" : "Blog-Sample-ClusterNG" } [vpc default] vpc_id = vpc-07edfc27679c9ca80 master_subnet_id = subnet-0ab2754446b2f87a4 compute_subnet_id = subnet-0ab2754446b2f87a4 use_public_ips = true # 検証用設定: パブリックサブネットで起動しているため [queue spot1] compute_resource_settings = spot1_resource placement_group = DYNAMIC compute_type = spot [compute_resource spot1_resource] instance_type = c5.large max_count = 16
S3バケットアクセステスト
Aバケットからダウンロードができなくなりました。
$ aws s3 cp s3://blog-sample-bucket-a/a.txt . fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden
Bバケットからダウンロードができないのは同じです。
$ aws s3 cp s3://blog-sample-bucket-b/b.txt . fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden
Aバケットからダウンロードできなくなった原因を確認します。
ParallelClusterのIAMロール確認
ヘッドノードのIAMロールを確認します。IAMロールはpcluster create
コマンドでクラスター作成時に生成され、ヘッドノードと、コンピュートノードに割り当てられます。
Resourceで指定する書式が誤っています。s3_read_resource
で指定した内容がそのまま反映されています。
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:Get*", "s3:List*" ], "Resource": [ "arn:aws:s3:::blog-sample-bucket-a/*, arn:aws:s3:::blog-sample-bucket-b/*" ], "Effect": "Allow", "Sid": "S3Read" } ] }
本来は下記の書式でIAMポリシーが作成されることを期待していました。ParallelClusterの設定ファイルでは複数のS3バケット登録には対応していないことがわかりました。
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:Get*", "s3:List*" ], "Resource": [ "arn:aws:s3:::blog-sample-bucket-a/*", "arn:aws:s3:::blog-sample-bucket-b/*" ], "Effect": "Allow", "Sid": "S3Read" } ] }
S3バケットアクセステスト
手動でIAMポリシーを修正するとヘッドノードでダウンロードできるようになりました。しかし、ParallelClusterで管理している設定と乖離が生まれます。次により良いS3バケットの指定方法を考えます。
# AバケットOK $ aws s3 cp s3://blog-sample-bucket-a/a.txt . download: s3://blog-sample-bucket-a/a.txt to ./a.txt # BバケットOK $ aws s3 cp s3://blog-sample-bucket-b/b.txt . download: s3://blog-sample-bucket-b/b.txt to ./b.txt # CバケットNG $ aws s3 cp s3://blog-sample-bucket-c/c.txt . fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden
2バケットへ読み取り専用アクセス OKパターン
先に必要な権限を与えたIAMポリシーを作成します。Aバケット、Bバケットへ読み取り専用のIAMポリシーを作りました。ヘッドノードからaws s3 ls
コマンドでバケット名を確認したいのでS3バケット全体に対してリストは許可しています。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:ListAllMyBuckets", "Resource": "*" }, { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetObject", "s3:GetObjectVersion", "s3:GetObjectACL" ], "Resource": [ "arn:aws:s3:::blog-sample-bucket-a", "arn:aws:s3:::blog-sample-bucket-a/*", "arn:aws:s3:::blog-sample-bucket-b", "arn:aws:s3:::blog-sample-bucket-b/*" ] } ] }
設定ファイル
additional_iam_policies
の項目に作成したIAMポリシーのARNを指定します。s3_read_resource
はコメントアウトしました。作成したIAMポリシーでAバケットへの読み取り権限があります。
# v2.10.3 [aws] aws_region_name = us-east-1 [aliases] ssh = ssh {CFN_USER}@{MASTER_IP} {ARGS} [global] cluster_template = default update_check = true sanity_check = true [cluster default] key_name = sandbox-key-useast1 scheduler = slurm # --- HeadNode Setting --- base_os = ubuntu1804 master_instance_type = t3.micro master_root_volume_size = 30 # --- Netowrk Setting --- vpc_settings = default # --- Compute Setting --- queue_settings = spot1 # --- PostInstall Setting --- # s3_read_resource = arn:aws:s3:::blog-sample-bucket-a/* # コメントアウトしました post_install = s3://blog-sample-bucket-a/postinstall.sh --- IAM Policy--- additional_iam_policies = arn:aws:iam::[YOUR_ACCOUNT_ID]:policy/BlogSampleParallelclusterPolicy # --- Tag --- tags = { "Name" : "Blog-Sample-ClusterPolicy" } [vpc default] vpc_id = vpc-07edfc27679c9ca80 master_subnet_id = subnet-0ab2754446b2f87a4 compute_subnet_id = subnet-0ab2754446b2f87a4 use_public_ips = true [queue spot1] compute_resource_settings = spot1_resource placement_group = DYNAMIC compute_type = spot [compute_resource spot1_resource] instance_type = c5.large max_count = 16
S3バケットアクセステスト
ParallelClusterで自動作成されるIAMロールに独自に作成したIAMポリシーがアタッチされて、クラスターが作成されます。
# AバケットOK $ aws s3 cp s3://blog-sample-bucket-a/a.txt . download: s3://blog-sample-bucket-a/a.txt to ./a.txt # BバケットOK $ aws s3 cp s3://blog-sample-bucket-b/b.txt . download: s3://blog-sample-bucket-b/b.txt to ./b.txt # CバケットNG $ aws s3 cp s3://blog-sample-bucket-c/c.txt . fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden
ワイルドカード指定
s3_read_resource
またはs3_read_write_resource
にはS3バケットのARNを1つ指定することがわかりました。
ARNで指定する箇所にワイルドカードを使うと複数のバケットに許可を与えることができます。
以下の例ではすべてのS3バケットに読み取り専用の権限を与えられます。
s3_read_resource = arn:aws:s3:::*
S3バケットアクセステスト
ParallelClusterの設定ファイルは省略します。この設定ファイルから作成したクラスターのヘッドノードでS3バケットのアクセスをテストしました。ABCすべてのバケットのファイルをダウンロードできています。
ABCバケット以外のS3バケットにも読み取り権限があるためセキュリティを考慮した上で指定方法をご検討ください。
# AバケットOK $ aws s3 cp s3://blog-sample-bucket-a/a.txt . download: s3://blog-sample-bucket-a/a.txt to ./a.txt # BバケットOK $ aws s3 cp s3://blog-sample-bucket-b/b.txt . download: s3://blog-sample-bucket-b/b.txt to ./b.txt # CバケットOK $ aws s3 cp s3://blog-sample-bucket-c/c.txt . download: s3://blog-sample-bucket-c/c.txt to ./c.txt
まとめ
s3_read_resource
と、s3_read_write_resource
にS3バケットを,(カンマ)
区切りで連ねても生成されるIAMポリシーの書式に誤りがある(ParallelClusterの設定ファイルで対応していない)
S3バケットへのアクセスを制限したいときはadditional_iam_policies
に自作のIAMポリシーを指定してクラスターを作成する必要がある。
指定するIAMポリシーはS3バケット以外にも自由に設定できるため、必要に応じてその他AWSリソースへの権限付与し柔軟なクラスター環境が構築できる。
個人的なベストプラクティス
s3_read_resource
でpostinstall.shのファイルを保存してある単体のS3バケットを指定する。
postainstall.shは必ずといってもいいくらい利用するため。
インプットデータなどデータソース置き場のS3バケット、解析、演算終了後のデータ保存先のS3バケットへのアクセス制御はIAMポリシーを作成する。
additional_iam_policies
でIAMポリシーを指定するのがクラスター再構築しなくても設定変更できて使い勝手よいです。
IAMポリシーのARNはクラスターで管理されます。IAMポリシーの中身の設定はクラスターで管理外です。クラスター構築後にIAMポリシーの設定内容を変更しても問題ありません。
IAMポリシーの例
Bバケットは読み取り専用、Cバケットは読み書き可能なIAMポリシーを作成します。ヘッドノードからaws s3 ls
コマンドでバケット名を確認したいのでS3バケット全体に対してリストは許可しています。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:ListAllMyBuckets", "Resource": "*" }, { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetObject", "s3:GetObjectVersion", "s3:GetObjectACL" ], "Resource": [ "arn:aws:s3:::blog-sample-bucket-b", "arn:aws:s3:::blog-sample-bucket-b/*" ] }, { "Effect": "Allow", "Action": [ "s3:DeleteObject", "s3:ListBucket", "s3:GetObject", "s3:PutObject", "s3:GetObjectVersion", "s3:GetObjectACL", "s3:PutObjectACL" ], "Resource": [ "arn:aws:s3:::blog-sample-bucket-c", "arn:aws:s3:::blog-sample-bucket-c/*" ] } ] }
ParallelClusterの設定ファイル
s3_read_resource
でpostainstall.shの保存してあるAバケットを指定しました。
additional_iam_policies
で作成したIAMポリシー名を指定して、クラスターを作成します。
s3_read_resource = arn:aws:s3:::blog-sample-bucket-a/* post_install = s3://blog-sample-bucket-a/postinstall.sh additional_iam_policies = arn:aws:iam::[YOUR_ACCOUNT_ID]:policy/[IAM_POLICY]
S3バケットアクセステスト
Cバケットだけはアップロードもできているので意図通りです。
# Donwload ## AバケットOK $ aws s3 cp s3://blog-sample-bucket-a/a.txt . download: s3://blog-sample-bucket-a/a.txt to ./a.txt ## BバケットOK $ aws s3 cp s3://blog-sample-bucket-b/b.txt . download: s3://blog-sample-bucket-b/b.txt to ./b.txt ## CバケットOK $ aws s3 cp s3://blog-sample-bucket-c/c.txt . download: s3://blog-sample-bucket-c/c.txt to ./c.txt # Upload ## AバケットNG $ aws s3 cp a.txt s3://blog-sample-bucket-a/ upload failed: ./a.txt to s3://blog-sample-bucket-a/a.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied ## BバケットNG $ aws s3 cp a.txt s3://blog-sample-bucket-b/ upload failed: ./a.txt to s3://blog-sample-bucket-b/a.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied ## CバケットOK $ aws s3 cp a.txt s3://blog-sample-bucket-c/ upload: ./a.txt to s3://blog-sample-bucket-c/a.txt
おわりに
ParallelClusterの設定ファイルで管理されるリソースから切り離すと柔軟性を持たせられます。ただ、管理が煩雑になるので悩みどころです。PoCではじめる場合は余り悩まずParallelCluster設定ファイルで作成できるものは利用した方がよいでしょう、クラスター作って壊してのトライ&エラーの方が検証がスムーズです。