Amazon Web Services ブログ
Amazon AppStream 2.0でデスクトップアプリケーションのストリームをスケールする
Deepak Sury, Principal Product Manager – Amazon AppStream 2.0
デスクトップアプリケーションを書き換えることなくWebブラウザにストリーミングしたいですか?Amazon AppStream 2.0はフルマネージドの、セキュアなアプリケーションストリーミングサービスです。このサービスでなにができるかを知るためのかんたんな方法はエンドユーザーエクスペリエンスを無料で試してみることです。
この記事では、AppStream 2.0環境をスケールさせて、コストを最適化する方法について解説します。さらにセットアップとモニタリングについていくつか付け加えます。
AppStream 2.0 ワークフロー
Image Builderを使用して自分のアプリケーションをAppStream 2.0にインポートします。Image BuilderでAWS Management Consoleからデスクトップエクスペリエンスに接続して、自分のアプリをインストールしてテストすることができます。そして、Image Builderのスナップショットとしてイメージを作成します。
アプリケーションをふくむイメージを作成したあと、インスタンスタイプを選択してストリーミングインスタンスのフリートを起動します。フリートのそれぞれのインスタンスは1ユーザーだけで使用され、フリートで使用されるインスタンスタイプがアプリケーションパフォーマンスによる必要と適合するようにします。最後に、フリートをスタックにアタッチしてユーザーアクセスをセットアップします。以下の図はワークフローのなかでのそれぞれのリソースの役割を示しています。
図1: AppStream 2.0のワークフローを記述
AppStream 2.0のセットアップ
使いはじめるためには、コンソールのクイックリンクからサンプルのAppStream 2.0スタックをセットアップします。このサンプルでは、スタックにds-sampleという名前を付け、サンプルイメージを選択して、stream.standard.mediumインスタンスタイプを選んでいます。セットアップしたリソースはAWSコンソールまたは、以下のようにdescribe-stacksやdescribe-fleetsを使用して確認することができます:
図2: AppStream 2.0スタックの確認
図3: AppStream 2.0フリートの確認
ストリーミング環境へのユーザーアクセスをセットアップするには、既存のSAML 2.0準拠のディレクトリを使用することができます。ユーザーは既存の認証情報を使用してログインすることができます。別のやり方として、クイックにストリーミング接続をテスト、または自分のWebサイトからストリーミングセッションをスタートするには、ストリーミングURLを作成することができます。コンソールで、Stacks、Actions、Create URLを選択するか、以下のようにcreate-streaming-urlを呼び出します:
図4: ストリーミングURLの作成
ブラウザにストリーミングURLをペーストして、表示されたアプリケーションを開くことができます。
これでサンプル環境のセットアップができましたので、スケーリングに移りましょう。
AppStream 2.0のスケーリングとコスト最適化
インスタントオンのストリーミング接続を提供するために、AppStream 2.0フリートのインスタンスは常時稼働しています。稼働中のインスタンスに課金され、それぞれの稼働中のインスタンスは同時に1ユーザーのみを受け付けます。コストを最適化するには、インスタンスの稼働台数を同時にアプリをストリーミングしたいユーザー数にあわせます。このセクションではそのための3つのオプションを紹介していきます:
- フリートのオートスケーリング
- スケジュールをベースにした固定フリート
- スケジュールによるフリートのオートスケーリング
フリートのオートスケーリング
インスタンスの稼働台数を動的に更新するには、フリートのオートスケーリングを使用することができます。この機能はフリートのサイズを自動的に最小値と最大値の間でオンデマンドにスケールさせることができます。これはコンスタントにユーザーの需要が変動し、需要に応じてフリートを自動的にスケールさせたい場合に便利です。スケーリングポリシーのセットアップと管理の方法については、Fleet Auto Scalingを参照してください。
フリートへの変更はAmazon CloudWatchメトリクスを利用してトリガすることができます:
- CapacityUtilization – すでに使用されている稼働中のインスタンスのパーセンテージ
- AvailableCapacity – 未使用でユーザーからの接続を受け付けることができるインスタンスの台数
- InsufficientCapacityError – ユーザーのリクエストに応答できる稼働中のインスタンスが存在しないときにトリガされるエラー
AWS SDKまたはAWSマネージメントコンソールを使用してスケーリングポリシーの作成とアタッチができます。コンソールを使用してポリシーをセットアップするのが便利です。以下のステップになります:
- AWSマネージメントコンソールで、AppStream 2.0を開きます。
- Fleetを選んで、フリートを選択し、Scaling Policiesを選びます。
- Minimum capacityとMaximum capacityで、フリートの値を入力します。
図5: スケーリングポリシーを設定するフリートタブ
- それぞれのセクションでAdd Policyを選んでスケールアウトとスケールインポリシーを作成します。
図6: スケールアウトポリシーの追加
図7: スケールインポリシーの追加
ポリシーを作成した後、フリートの詳細の一部として表示されます。
スケーリングポリシーはCloudWatchアラームによってトリガーされます。このアラームはコンソールを使用してスケーリングポリシーを作成したときに自動的に作成されます。CloudWatchコンソールからアラームの確認と変更ができます。
図8: フリートをスケーリングするためのCloudWatchアラーム
スケジュールをベースにした固定フリート
コストを最適化して予測可能な需要に対応するための別のやり方は時刻または曜日にもとづいて稼働するインスタンスの台数を固定することです。これはトレーニングクラス、コールセンターのシフト、学校のコンピュータラボなどのシナリオで異なる時刻に固定されたユーザー数がサインインする場合に便利です。AppStream 2.0のupdate-fleetコマンドを使用して稼働中のインスタンス数をかんたんに設定することができます。フリートのコンピュートキャパシティを希望する値にアップデートしてください。稼働中のインスタンス数は、以下のように設定した希望する値に応じて変動します:
図9: フリートの希望するキャパシティをアップデート
自動的にフリートサイズをアップデートするLambdaファンクションをセットアップします。以下の例にしたがって自分のファンクションをセットアップします。以前にLambdaを使用したことがない場合は、Step 2: Create a HelloWorld Lambda Function and Explore the Consoleを参照してください。
フリートサイズを変更するファンクションを作成するには
- Lambdaコンソールで、 Create a Lambda functionを選択します。
- Blank Functionブループリントを選択します。これは自分のコードを追加することができる空のブループリントを作成します。
- 今回はトリガーセクションをスキップします。あとで、時間を、または別のインプットをベースにしたトリガーを追加できます。
- Configure functionセクションでは:
- 名前と説明を入力します。
- Runtimeでは、Node.js 4.3を選択します。
- Lambda function handler and roleで、Create a custom roleを選択します。
- IAMウィザードで、例えばLambda-AppStream-Adminのようにロール名を入力します。デフォルトのままにします。
- IAMロールが作成されたあと、”AmazonAppStreamFullAccess”というAppStream 2.0のマネージドポリシーをロールにアタッチします。より詳細な情報は、Working with Managed Policiesを参照してください。これによりLambdaがあなたのかわりにAppStream 2.0 APIをコールすることができます。くわしくは、Controlling Access to Amazon AppStream 2.0を参照してください。
- のこりのフィールドではデフォルト値のままNext, Create functionを選択します。
- AppStream 2.0のフリートサイズを変更するには、Codeを選択して以下のようにサンプルコードを追加します:
JavaScript
'use strict'; /** This AppStream2 Update-Fleet blueprint sets up a schedule for a streaming fleet **/ const AWS = require('aws-sdk'); const appstream = new AWS.AppStream(); const fleetParams = { Name: 'ds-sample-fleet', /* required */ ComputeCapacity: { DesiredInstances: 1 /* required */ } }; exports.handler = (event, context, callback) => { console.log('Received event:', JSON.stringify(event, null, 2)); var resource = event.resources[0]; var increase = resource.includes('weekday-9am-increase-capacity') try { if (increase) { fleetParams.ComputeCapacity.DesiredInstances = 3 } else { fleetParams.ComputeCapacity.DesiredInstances = 1 } appstream.updateFleet(fleetParams, (error, data) => { if (error) { console.log(error, error.stack); return callback(error); } console.log(data); return callback(null, data); }); } catch (error) { console.log('Caught Error: ', error); callback(error); } };
- コードをテストします。Testを選択して”Hello World”テストテンプレートを使用します。はじめてこれを実行するには、Save and Testを選択します。以下のようにスケーリングのアップデートをトリガーするテストインプットを作成します。
- update-fleetコールの結果がアウトプットのテキストとして表示されます。CLIを使用してLambdaファンクションの実行結果を確認することもできます。
つぎに、タイムベーススケジュールをセットアップするために、Lambdaファンクションを呼び出すトリガーをセットします。
Lambdaファンクションのトリガーをセットするには
- Triggers, Add triggerを選択します。
- CloudWatch Events – Scheduleを選択します。
- Schedule expressionでは、cronを選択します。cronの値はあとで編集することができます。
- トリガーが作成された後、weekday-9am-increase-capacityのイベントを開きます。
- CloudWatchコンソールで、イベントの詳細を編集します。平日の午前8時にフリートをスケールアウトするには、時間を00 17 ? * MON-FRI *になるように調整します。(シアトル(太平洋時間)ではない場合は、それぞれのタイムゾーンに変更してください)
- 平日の終わりにトリガーする別のイベントを追加することもできます。
これでセットしたスケジュール時刻に合わせて自動的にスケールアウトとスケールインするトリガーをセットアップしました。
スケジュールでのフリートのオートスケーリング
もっと複雑なシナリオをマネージするためにフリートスケーリングと時間ベースのスケジュールのアプローチを組み合わせて使用することができます。これは業務時間と業務時間外とで稼働するインスタンス数をマネージしながら需要の変更に対応するのに便利です。時刻または日付に基づいてフリートの最小および最大サイズをプログラムから変更し、デフォルトのスケールアウトおよびスケールインポリシーを適用することができます。これによってスケジュールをベースにした予測可能な最小の需要に応答することができます。
たとえば、平日のはじめに、同時に一定数のユーザーがストリーミング接続をリクエストすることが予測されます。フリートがスケールアウトして要求を満たすまで待っていたくはありません。しかしながら、一日のうちに、需要がスケールインまたはアウトすることが予測され、フリートのサイズを需要に合わせたいと思います。
これを実現するには、コンソールからスケーリングポリシーをセットアップして、スケジュールをベースにフリートの最小、最大および希望するキャパシティの変更をトリガーするLambdaファンクションを作成します。以前作成したLambdaファンクションのコードを以下のようなコードで置き換えます:
'use strict';
/** This AppStream2 Update-Fleet function sets up a schedule for a streaming fleet **/
const AWS = require('aws-sdk');
const appstream = new AWS.AppStream();
const applicationAutoScaling = new AWS.ApplicationAutoScaling();
const fleetParams = {
Name: 'ds-sample-fleet', /* required */
ComputeCapacity: {
DesiredInstances: 1 /* required */
}
};
var scalingParams = {
ResourceId: 'fleet/ds-sample-fleet', /* required - fleet name*/
ScalableDimension: 'appstream:fleet:DesiredCapacity', /* required */
ServiceNamespace: 'appstream', /* required */
MaxCapacity: 1,
MinCapacity: 6,
RoleARN: 'arn:aws:iam::659382443255:role/service-role/ApplicationAutoScalingForAmazonAppStreamAccess'
};
exports.handler = (event, context, callback) => {
console.log('Received this event now:', JSON.stringify(event, null, 2));
var resource = event.resources[0];
var increase = resource.includes('weekday-9am-increase-capacity')
try {
if (increase) {
//usage during business hours - start at capacity of 10 and scale
//if required. This implies at least 10 users can connect instantly.
//More users can connect as the scaling policy triggers addition of
//more instances. Maximum cap is 20 instances - fleet will not scale
//beyond 20. This is the cap for number of users.
fleetParams.ComputeCapacity.DesiredInstances = 10
scalingParams.MinCapacity = 10
scalingParams.MaxCapacity = 20
} else {
//usage during non-business hours - start at capacity of 1 and scale
//if required. This implies only 1 user can connect instantly.
//More users can connect as the scaling policy triggers addition of
//more instances.
fleetParams.ComputeCapacity.DesiredInstances = 1
scalingParams.MinCapacity = 1
scalingParams.MaxCapacity = 10
}
//Update minimum and maximum capacity used by the scaling policies
applicationAutoScaling.registerScalableTarget(scalingParams, (error, data) => {
if (error) console.log(error, error.stack);
else console.log(data);
});
//Update the desired capacity for the fleet. This sets
//the number of running instances to desired number of instances
appstream.updateFleet(fleetParams, (error, data) => {
if (error) {
console.log(error, error.stack);
return callback(error);
}
console.log(data);
return callback(null, data);
});
} catch (error) {
console.log('Caught Error: ', error);
callback(error);
}
};
注:このコードを実行するには、Lambdaファンクションで使用されるロールにIAMポリシーを追加する必要があります。このポリシーによってLambdaがあなたのかわりにアプリケーションオートスケーリングサービスを呼び出すことができます。
図10: Lambdaでアプリケーションオートスケーリングを使用するインラインポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:PassRole"
],
"Resource": "*"
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"application-autoscaling:*"
],
"Resource": "*"
}
]
}
利用状況のモニタリング
フリートのスケーリングをセットアップした後、AppStream 2.0でCloudWatchメトリクスを使用して、モニタリングのためのダッシュボードを作成することができます。これは確認した利用量をもとに時間ベースのスケーリングポリシーを最適化するのに役立ちます。
例えば、初期セットアップが非常に保守的でリソースをオーバープロビジョンしていたら、フリートの利用率が低い状態が長く続くでしょう。一方で、フリートサイズが小さすぎる場合、高利用率またはユーザーの接続をブロックしているキャパシティ不足のエラーがみられるでしょう。最大15ヶ月までCloudWatchメトリクスを確認してフリートスケーリングポリシーを調整することができます。
図11: カスタムAmazon CloudWatchメトリクスのダッシュボード
まとめ
これらはAppStream 2.0をスケーリングしてコストを最適化するためのいくつかのアイデアです。これが役に立ち、同様の記事を観たいと思ったらお知らせください。サービスに関してコメントがあれば、AWS forum for AppStream 2.0にフィードバックを投稿してください。
翻訳は渡邉が担当しました。原文はこちら。