Amazon Web Services ブログ

Amazon FSx for Windows File Server を Windows コンテナの永続ストレージとして使用する

この投稿は、Marcio Morales、Sandeep Srinivas Indraganti、Alain Vetier、Pavneet Ahluwalia による寄稿です。

このブログ投稿では、Amazon Elastic Container Service (ECS) で動作中の Windows コンテナ用の永続ストレージとして、Amazon FSx for Windows File Server を使用する方法について順を追って説明します。AWS System Manager ドキュメントを使用して、コンテナインスタンス上のファイル共有マッピングを自動化し、Docker ボリュームをコンテナに提供するための ECS タスク定義を設定します。

現在、Amazon FSx File Share を介して Windows コンテナの永続ストレージを公式にサポートしています。マネージド機能は、以下で強調表示されているワークアラウンドに必要とされる差別化されていない手間がかかる作業を取り除くことを目的としています。

では、これをどのように実現するかをご説明します。

Windows Server バージョン 1709 (Windows Server 2016「半期チャネル」) で「SMB グローバルマッピング」と呼ばれる SMB プロトコルの既存の機能を活用します。SMB グローバルマッピングを使用すると、SMB 共有をホストにマウントし、その共有上のディレクトリをコンテナに渡すことができます。コンテナを特定のサーバー、共有、ユーザー名、またはパスワードで設定する必要はありません。これらはすべてホストが代わりに処理します。コンテナは、ローカルストレージがある場合と同じように機能します。

前提条件および仮定

  • コンピューターに AWS CLIAWS Tools for PowerShell を適切にインストールし、設定しています。
  • ECS コンテナインスタンスとして Windows Server 2019 Amazon Machine Images を使用し、ECS クラスターをセットアップしています。公式ドキュメント。
  • ECS コンテナインスタンスが Active Directory ドメインのメンバーです。
  • このブログ投稿では、Managed Microsoft AD としての AWS Directory Service について説明していますが、ECS コンテナーインスタンスがドメインに参加できる限り、他の Active Directory シナリオでも有効です。
  • Amazon FSx for Windows File Server がデプロイされています
  • このブログ投稿は、Amazon ECS 上の Windows コンテナインスタンスにのみ適用されます。

このブログでは、以下を行います。

  1. System Manager パラメータストアで、ユーザー名とパスワード用の 2 つのパラメータを作成する。
  2. System Manager ドキュメントを作成し、ECS コンテナインスタンスで SMB グローバルマッピングをセットアップする。
  3. KMS と SSM ポリシーを既存の ECS ロールに添付する。
  4. System Manager ドキュメントを実行し、ECS コンテナインスタンスで SMB グローバルマッピングをセットアップする。
  5. タスク定義を作成してコンテナを起動し、結果を確認する。

1.System Manager パラメータストアで、ユーザー名とパスワード用の 2 つのパラメータを作成する。

PowerShell コンソールで、2 つの SSM パラメータを作成します。Active Directory ユーザーアカウント情報を保存する「domainUserName」と AWS KMS が暗号化したパスワードを保存する「domainUserPassword」という名前を選択します。-Value は、ECS コンテナインスタンスと Amazon FSx for Windows File Server が提供するファイル共有との間での共有認証/承認フェーズで使用するよう設計した、既存のユーザーアカウントとパスワードである必要があります。

Write-SSMParameter -Name 'domainUserName' -Value 'DOMAIN\USERNAME' -Type String
Write-SSMParameter -Name 'domainUserPassword' -Value 'PASSWORD' -Type SecureString -KeyId "KMSKeyId"

In the above command if you don't specify the KeyId parameter by default SSM uses the following key-id: *key/alias/aws/ssm*

2.System Manager ドキュメントを作成し、ECS コンテナインスタンスで SMB グローバルマッピングをセットアップする。

以下のコンテンツを使用して JSON ファイル (filename.json) をローカルに作成し、以下に示す変更を行います。

  • New-SMBGlobalMapping コマンドで、「FSx DNS NAME」を Amazon FSx for Windows File Server の DNS 名に、「Directory」を Docker コンテナボリュームで使用する共有内に作成した既存のディレクトリに置き換えます。また、必要に応じて、-LocalPath パラメータ値を G: ではなく、お好みのドライブ文字に置き換えます。
{
    "schemaVersion": "2.2",
    "description": "Map SMB Share using SMBGlobalMappings for Windows Containers",
    "mainSteps": [
        {
            "action": "aws:runPowerShellScript",
            "name": "runPowerShellWithSecureString",
            "precondition": {
                "StringEquals": [
                    "platformType",
                    "Windows"
                ]
            },
            "inputs": {
                "runCommand": [
                    "$username = (Get-SSMParameterValue -Name domainUserName).Parameters[0].Value",
                    "$password = (Get-SSMParameterValue -Name domainUserPassword -WithDecryption $True).Parameters[0].Value | ConvertTo-SecureString -asPlainText -Force",
                    "$credential = New-Object System.Management.Automation.PSCredential($username,$password)",
                    "New-SmbGlobalMapping -RemotePath '\\\\FSxDNSNAME\\share\\Directory' -Credential $credential -LocalPath G: -RequirePrivacy $true -ErrorAction Stop"
                ]
            }
        }
    ]
}

上記の JSON スクリプトは、新しい SMB グローバルマッピングを作成し、 ‘domainUserName' and 'domainUserPassword' SSM parameters created during step-1 を使用して、FSX Windows 共有から ECS コンテナインスタンスのローカルドライブ「G:」にパス「\\ Share \\ Directory」をマッピングします。

2.1 ローカルマシンで作成したファイルを使って、SSM ドキュメントを作成しましょう。PowerShell コンソールで、

$json = Get-Content C:\filename.json | Out-String
New-SSMDocument -DocumentType Command -Name document name -Content $json

「オプション」2.2 ディレクトリにはボリュームとして Docker コンテナに示されたすべてのデータ (アプリのソース、データベース、機密ファイルなど) が含まれるため、セキュリティのために、メインの Docker ボリュームストレージとして使用する指定ディレクトリの継承を無効にし、認証済みユーザーを削除することが推奨されます。その後、SMB ファイル共有を認証するためのユーザーアカウントとして選択した既存のユーザーアカウントを追加します。[Modify Permission] を選択します。

3.KMS と SSM ポリシーを既存の ECS ロールに添付する。

ECS コンテナインスタンスから KMS および System Manager の使用を有効にするには、ECS Windows クラスターの構築時に作成した ECS インスタンスロールに正しい IAM ポリシーが添付されていることを確認する必要があります。通常、ECS が作成したコンテナインスタンス IAM ロールは、ecsInstanceRole といいます。

まず、新しいポリシーを作成して、ecsInstanceRole に添付します。このポリシーは、セキュアな文字列値を持つ SSM パラメータが使用する kms:Decrypt API を呼び出すアクセス許可をインスタンスに付与します。これは、ステップ 1 で作成したパスワードパラメータを意味します。JSON ファイルを作成し、以下の例を使用してコンピューターに保存します。

  • region:account を、ECS 環境を起動したリージョンとアカウント ID に置き換えます。
  • key-id を、「domainUserPassword」SSM パラメータの作成中に使用したキーの ID に置き換えます。デフォルトでは、SSM は次のキー ID を使用します。key/alias/aws/ssm
{"Version":"2012-10-17",
   "Statement":[
      {"Effect":"Allow",
         "Action":[
            "kms:Decrypt"
         ],
         "Resource":[
            "arn:aws:kms:region:account-id:key/key-id"
         ]
      }
   ]
}

3.1 次に、ecsInstanceRole にポリシーを作成し、添付します。PowerShell コンソールで、以下を実行します。
*Replace ACCOUNT-ID with the Account ID number.*

New-IAMPolicy -PolicyName "SSMSecureString" -policyDocument (Get-Content -Raw MySamplePolicy.json)
Register-IAMRolePolicy -RoleName ecsInstanceRole -PolicyArn arn:aws:iam::ACCOUNT-ID:policy/SSMSecureString

3.2 IAM 管理ポリシー AmazonEC2RoleforSSM を ecsInstanceRole に添付します。

Register-IAMRolePolicy -RoleName ecsInstanceRole -PolicyArn arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM

4.System Manager ドキュメントを実行し、ECS コンテナインスタンスで SMB グローバルマッピングをセットアップする。

最後に、結果を見てみましょう。 PowerShell コンソールから以下のコマンドを実行し、SSMCommand を呼び出して、ステップ 2 で作成したドキュメントを実行します。

Send-SSMCommand -InstanceId instance-id -DocumentName SMBGlobalMappings 

注: ECS クラスターに複数の ECS Windows コンテナインスタンスがある場合は、それらすべてに対して上記のコマンドを実行する必要があります。これをワンステップで行うには、-InstanceId パラメータを使用して、最大 50 個までのインスタンス ID を指定します。

私の例のような出力を受け取ることになります。 ステータスを見ると、SSM が Amazon EC2 インスタンスに対してコマンドを実行しているため、「Pending」と表示されます。

CloudWatchOutputConfig : Amazon.SimpleSystemsManagement.Model.CloudWatchOutputConfig
CommandId : 71d161be-e200-48c3-bd2d-a9ffe1dcc94b
Comment :
CompletedCount : 0
DeliveryTimedOutCount : 0
DocumentName : SMBGlobalMappings
DocumentVersion :
ErrorCount : 0
ExpiresAfter : 1/29/2020 12:27:00 AM
InstanceIds : {i-0e176f3c47e4fcb59}
MaxConcurrency : 50
MaxErrors : 0
NotificationConfig : Amazon.SimpleSystemsManagement.Model.NotificationConfig
OutputS3BucketName :
OutputS3KeyPrefix :
OutputS3Region :
Parameters : {}
RequestedDateTime : 1/28/2020 10:27:00 PM
ServiceRole :
Status : Pending
StatusDetails : Pending
TargetCount : 1
Targets : {}

4.1 以下に示すコマンド ID を使用して、上記のコマンドを実行し、SSM ドキュメントが正常に実行されたことを確認します。

Get-SSMCommandInvocation -CommandId "commandId" 

上記のコマンドは、ステータスが「Success」の次のような出力を返すと予想されます。

CommandId : dc383f39-8f8b-4cd1-987a-84c82ab1dd9c
CommandPlugins : {}
Comment :
DocumentName : CreateSMBGlobalMappingsFsxBlog
InstanceId : i-034ffa7bf391dcc80
InstanceName :
NotificationConfig : Amazon.SimpleSystemsManagement.Model.NotificationConfig
RequestedDateTime : 2/18/2020 8:45:56 PM
ServiceRole :
StandardErrorUrl :
StandardOutputUrl :
Status : Success
StatusDetails : Success
TraceOutput :

4.2 これで完了です。 ECS コンテナインスタンスに SMB 共有がマウントされました。RDP セッションまたは System Manager Session Manager を介して ECS コンテナインスタンスにアクセスし、PowerShell コンソールで次のコマンドを実行します。

Get-SMBGlobalMappings

このような結果が表示されるはずです。(以下の出力では、永続ストレージはこのブログで使用したディレクトリとなりますが、ご自身の場合、ステップ 2 で New-SmbGlobalMapping コマンドで使用した「ディレクトリ」になります。)

5.タスク定義を作成してコンテナを起動し、結果を確認する。

ディレクトリを G:\ ドライブからコンテナへのボリュームとして提供するには、タスク定義でボリュームオプションを設定する必要があります。

5.1 [Add Volume] をクリックする

ご覧のように、ボリュームタイプとしてバインドマウントを選択しました。バインドマウントを使用すると、Amazon EC2 インスタンスのファイルまたはディレクトリがコンテナにマウントされます。ファイルまたはディレクトリは、ホストマシン上のフルパスまたは相対パスによって参照されます。「SMB グローバルマッピング」という機能では、ホストで SMB 共有をマウントし、その共有上のディレクトリをコンテナに渡すことができます。コンテナを特定のサーバー、共有、ユーザー名、またはパスワードで設定する必要はありません。これらはすべてホストが代わりに処理します。コンテナは、ローカルストレージがある場合と同じように機能します。

特定のタスク定義のソースパスは、すべてのデータをコンテナに公開する共有内のディレクトリである必要があります。

app-state としてのマウントポイントの名前
ボリュームタイプ: Bind Mount
ソースパス: G:\Directory\app-state

G:\ はステップ 2 で SMB 共有のマウントポイントとして選択されたドライブ文字です。
Container1 は、このタスク定義で使用するために作成した共有内のディレクトリです。
app-state は、コンテナに公開されるディレクトリです。

5.2 ボリュームをタスク定義レベルで設定する次に、コンテナ定義 (タスク定義内) で、ステップ 5.1 で作成したばかりのボリュームへのコンテナ (コンテナパス) マッピングのマウントポイントを通知する必要があります。

タスク定義とコンテナ定義で行ったマウント設定を掘り下げると、次と同じになります。

docker container run -v G:\Container1\app-state:C:\dotnetapp\app-state

まとめ

これで全部です。 Amazon File Services for Amazon FSx でホストされている SMB 共有を介して、Amazon Container Service (ECS) を設定するだけで、コンテナボリュームをマウントできるようにました。コンテナへのデータ永続化のアプローチは、新しいクラウドネイティブのアプリには理想的ではありませんが、レガシアプリケーションには最適で、必須と言えます。このアプローチが極めてよく適合する例としては、レガシーの ASP.NET アプリケーションがあります。コードを変更せずにアプリケーションディレクトリをリダイレクトし、マルチ AZ 配置で Amazon FSx for Windows File Server を使用して高い可用性と災害対策を実現できるようになります。