[アップデート] AppStream 2.0のElastic Fleetsでセッションスクリプトがサポートされました

2022.04.19

しばたです。

Amazon AppStream 2.0のElastic Fleetsでセッションスクリプトの利用がサポートされました。
AWSからのアナウンスはこちらになります。

何が新しいのか?

AppStream 2.0ではユーザーがフリートインスタンスに接続する際(セッション利用時)に独自のスクリプトを実行することが可能であり、これが「セッションスクリプト」となります。
このセッションスクリプトはセッション開始直前(SessionStart)とセッション終了時(SessionTermination)の2つのタイミングで実行可能です。

これまではマシンイメージを自作するAlways-On FleetsおよびOn-Demand Fleetsでのみセッションスクリプトの指定が可能だったのですが、今回Elastic Fleetsにおいても指定可能になったことが新しいポイントとなります。

仕組み

セッションスクリプトは特定のパスに所定の形式のconfig.jsonファイルを配置することで設定します。

  • Windows環境 : C:\AppStream\SessionScripts\config.json
  • Linux環境 : /opt/appstream/SessionScripts/config.json

JSONファイルの具体的な内容については以下のドキュメントを参照してください。

従来のAlways-On FleetsおよびOn-Demand Fleetsにおいてはイメージ作成時点にImage Builderを使いOS内部にログインしてconfig.jsonおよびスクリプトファイルを仕込むことができますが、Image Builderが使えないElastic Fleetsではconfig.jsonとスクリプトファイルを1つのZipファイルにまとめてS3上に配置してやる必要があります。

そしてS3にアップされたZipファイルの中身が以下のディレクトリに展開されるとのことです。

  • Windows環境 : C:\AppStream\SessionScripts\
  • Linux環境 : /opt/appstream/SessionScripts/

展開された後のファイルの扱いについてはAlways-On FleetsおよびOn-Demand Fleetsの場合と同様です。

試してみた

それでは実際に試してみます。

今回は個人検証用AWSアカウントの東京リージョンにWindows Server 2019ベースのElastic Fleets環境を構築します。

S3バケットは以前の記事で作ったelastic-fleets-sample-20211121バケットを流用します。
ちなみに新規にS3バケットを作る場合はAppStream 2.0のサービスに対しs3:GetObjectを許可するバケットポリシーを設定しておいてください。

1. スクリプトの準備

まずは最初に以下の単純なスクリプト(MyCustomScript.ps1)とconfig.jsonを用意しZipファイルに固めておきます。

MyCustomScript.ps1

param([string]$message)

function Write-Message([string]$message) {
    Write-Output ("{0:yyyy/MM/dd HH:mm:ss} | {1}" -f (Get-Date), $message)
}

# 実行環境の内容を出力する簡単なスクリプト
Write-Message "Start $message"
Write-Message "user is $(whoami)"
Write-Message "pwd is $($pwd.Path)"
Write-Message "End $message"

config.jsonはスクリプトを引数違いで実行する設定に。

config.json

{
    "SessionStart": {
        "executables": [
            {
                "context": "system",
                "filename": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
                "arguments": "-File C:\\AppStream\\SessionScripts\\MyCustomScript.ps1 StartAsSystem",
                "s3LogEnabled": true
            },
            {
                "context": "user",
                "filename": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
                "arguments": "-File C:\\AppStream\\SessionScripts\\MyCustomScript.ps1 StartAsUser",
                "s3LogEnabled": true
            }
        ],
        "waitingTime": 30
    },
    "SessionTermination": {
        "executables": [
            {
                "context": "system",
                "filename": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
                "arguments": "-File C:\\AppStream\\SessionScripts\\MyCustomScript.ps1 TerminateAsSystem",
                "s3LogEnabled": true
            },
            {
                "context": "user",
                "filename": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
                "arguments": "-File C:\\AppStream\\SessionScripts\\MyCustomScript.ps1 TerminateAsUser",
                "s3LogEnabled": true
            }
        ],
        "waitingTime": 30
    }
}

ZipファイルにまとめるコマンドはPowerShellを使った場合こんな感じになります。

# カレントディレクトリの全てのファイルを1つのZipファイルにまとめる例
Compress-Archive -Path .\* -DestinationPath ..\Dest\MyCustomScript.zip

(所定のディレクトリに2つのファイルを配置)

(2つのファイルをZipファイルにまとめる)

このZipファイル(MyCustomScript.zip)をS3にアップロードします。
今回はバケットの/customscript/配下にアップロードしました。

他に必要となるApplication向けの各種リソースの配備手順については割愛します。
今回は以前作ったPowerShell 7公開アプリケーション向けの各種リソースを流用します。

2. フリートの作成

続けて新規にElastic Fleetsを作成します。
フリートの作成を開始し、最初に「Elastic」を選択します。

続けてフリートの基本情報を入力、今回は「my-custom-script-fleet」という名前でWindows Server 2019ベースのイメージを使います。

基本情報の指定に「Session scripts settings」欄が新たに増えてますので、ここにS3にアップロードしたZipファイルおのパスを指定します。
今回の場合だとs3://elastic-fleets-sample-20211121/customscript/MyCustomScript.zipを指定する形になります。

その他のパラメーターについては環境に応じてよしなに設定します。
今回はPowerShell 7のアプリケーションを事前作成済みのVPC環境に展開する設定としています。

フリートがエラー無く作成できればOKです。

3. スタックの作成など

あとは通常のAppStream 2.0同様にスタックを作成しフリートと紐づけてやります。
ユーザープールの設定もよしなに行います。

4. 動作確認

環境の準備ができたあとは実際にAppStream 2.0を利用します。

セッション内部を確認するとC:\AppStream\SessionScripts\配下にZipファイルそのものと内部の各ファイル(config.json, MyCustomScript.ps1)が展開されていることがわかります。

今回はS3にスクリプトのログを出力する設定にしてますので、自動生成されるappstream-log-[リージョン名]-[アカウントID]-[ランダムID]バケットのユーザー毎のPrefix配下にSessionScriptsLogsという名前で実行ログが保存されます。

  • /SessionScriptsLogs/SessionStart/ : 開始スクリプトのログ
  • /SessionScriptsLogs/SessionTermination/ : 終了スクリプトのログ

開始スクリプトのPrefix配下を見ると下図の様に標準出力と標準エラー出力のログがそれぞれ別ファイルに出力されます。

終了スクリプトの場合も同様の構成となります。

最後に各ログファイルの内容を以下に記載します。
今回はエラー出力は無いスクリプトなので標準出力の内容のみ記載します。

セッション開始直前(SessionStart)スクリプトの実行結果

Systemコンテキストのスクリプト実行結果

2022/04/19 03:29:20 | Start StartAsSystem
2022/04/19 03:29:20 | user is nt authority\system
2022/04/19 03:29:20 | pwd is C:\Windows\system32
2022/04/19 03:29:20 | End StartAsSystem

Userコンテキストのスクリプト実行結果

2022/04/19 03:29:20 | Start StartAsUser
2022/04/19 03:29:20 | user is ec2amaz-22j9eln\photonuser
2022/04/19 03:29:20 | pwd is C:\Windows\system32
2022/04/19 03:29:20 | End StartAsUser

セッション終了時(SessionTermination)スクリプトの実行結果

Systemコンテキストのスクリプト実行結果

2022/04/19 03:35:43 | Start TerminateAsSystem
2022/04/19 03:35:43 | user is nt authority\system
2022/04/19 03:35:43 | pwd is C:\Windows\system32
2022/04/19 03:35:43 | End TerminateAsSystem

Userコンテキストのスクリプト実行結果

2022/04/19 03:35:43 | Start TerminateAsUser
2022/04/19 03:35:43 | user is ec2amaz-22j9eln\photonuser
2022/04/19 03:35:43 | pwd is C:\Windows\system32
2022/04/19 03:35:43 | End TerminateAsUser

スクリプト実行結果を見て

良い感じにスクリプトの実行結果がログ出力されました。
なんらかの設定ミスがある場合はログファイル自体がS3にアップロードされないため、ログがある時点でセッションスクリプトが正しく動作していることがわかります。

スクリプトの実行ユーザはSystemコンテキストの場合はSystemユーザー、Userコンテキストの場合はPhotonUserユーザーなのは従来通り変わりありません。
加えてSystemコンテキスト、Userコンテキストのスクリプトが同時に並列実行されていますが、これも従来通りの挙動となります。

終わりに

以上となります。

AppStream 2.0のセッションスクリプト自体が補助的な機能であまり使われることが無いとは思うものの、セッションスクリプトが無いためElastic Fleetsを採用できない方にとっては朗報だと思います。
機会があればぜひ使ってみてください。