想定読者
- VDI基盤の運営者
- 複数人のユーザに対して、WindowsのRDP基盤を提供している方
AppStreamとは...の前に
アプリケーション仮想化
Citrix に代表されるように、
以前はOn-premにあった基幹系システム要件で、どうしても稼働しているアプリケーションのバージョンアップができない、
だけど、サポート期限が切れてしまった、といった延命措置のために利用されるケースが多かったのではないかと思います。
今はクラウドにシステム稼働基盤がリフト、リフトアンドシフトした関係で、
認証・認可を行ったユーザが取り扱うことのアプリケーションを制限したいといったような使い方の変化があるのかなと思います。
AppStream 2.0とは
1.0はないの?の疑問は、こちらのブログをご覧ください。
私も参考にさせていただいて、へぇと思った一人です。
参考1:AWS再入門ブログリレー Amazon AppStream 2.0 編
参考2:[アップデート] AppStream 2.0 にネイティブデスクトップエクスペリエンスのサポートが追加されました
2020年8月のサービスアップデートで何があったのか
以下のアナウンスが行われています。
Amazon AppStream 2.0 にネイティブデスクトップエクスペリエンスのサポートが追加されました
これにより、AWS の VDI サービスの単純に選択肢が増えました。
今までは、Amazon Workspace がNGだった場合は、
EC2でWindows Serverを作成して、RDP接続する形しか選択肢はありませんでした。
このサービスアップデートにより、複数人で利用する際のVDI基盤の選択肢が広がったのかなと思います。
ということで、少し自分でも所管を知りたく3時間程度で環境作ってみました。
システム管理者の観点で試してみた
前述で参考にさせていただいたクラスメソッドさんのブログでは触れられていなかった点について、
システム管理者の方が気にするだろうなという視点で見てみました。
CloudFormationで実験環境構築
CloudFormationで以下のテンプレートを使って作成しています。
- テスト環境作成のCloudFormation
AWSTemplateFormatVersion: "2010-09-09"
Description:
VPC and Subnet Create
Metadata:
"AWS::CloudFormation::Interface":
ParameterGroups:
- Label:
default: "Project Name Prefix"
Parameters:
- PJPrefix
- Label:
default: "Network Configuration"
Parameters:
- VPCCIDR
- PublicSubnetCCIDR
- PublicSubnetDCIDR
- PrivateSubnetCCIDR
- PrivateSubnetDCIDR
ParameterLabels:
VPCCIDR:
default: "VPC CIDR"
PublicSubnetCCIDR:
default: "PublicSubnetC CIDR"
PublicSubnetDCIDR:
default: "PublicSubnetD CIDR"
PrivateSubnetCCIDR:
default: "PrivateSubnetC CIDR"
PrivateSubnetDCIDR:
default: "PrivateSubnetD CIDR"
## ------------------------------------------------------------#
## Input Parameters
## ------------------------------------------------------------#
Parameters:
PJPrefix:
Type: String
VPCCIDR:
Type: String
Default: "10.0.0.0/16"
PublicSubnetCCIDR:
Type: String
Default: "10.0.1.0/24"
PublicSubnetDCIDR:
Type: String
Default: "10.0.2.0/24"
PrivateSubnetCCIDR:
Type: String
Default: "10.0.11.0/24"
PrivateSubnetDCIDR:
Type: String
Default: "10.0.12.0/24"
Resources:
## ------------------------------------------------------------#
## VPC
## ------------------------------------------------------------#
## VPC Create
VPC:
Type: "AWS::EC2::VPC"
Properties:
CidrBlock: !Ref VPCCIDR
EnableDnsSupport: "true"
EnableDnsHostnames: "true"
InstanceTenancy: default
Tags:
- Key: Name
Value: !Sub "${PJPrefix}-vpc"
## InternetGateway Create
InternetGateway:
Type: "AWS::EC2::InternetGateway"
Properties:
Tags:
- Key: Name
Value: !Sub "${PJPrefix}-igw"
## IGW Attach
InternetGatewayAttachment:
Type: "AWS::EC2::VPCGatewayAttachment"
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC
## ------------------------------------------------------------#
## Subnet
## ------------------------------------------------------------#
## Public SubnetC Create
PublicSubnetC:
Type: "AWS::EC2::Subnet"
Properties:
AvailabilityZone: "ap-northeast-1c"
CidrBlock: !Ref PublicSubnetCCIDR
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub "${PJPrefix}-public-subnet-c"
## Public SubnetD Create
PublicSubnetD:
Type: "AWS::EC2::Subnet"
Properties:
AvailabilityZone: "ap-northeast-1d"
CidrBlock: !Ref PublicSubnetDCIDR
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub "${PJPrefix}-public-subnet-d"
## Private SubnetC Create
PrivateSubnetC:
Type: "AWS::EC2::Subnet"
Properties:
AvailabilityZone: "ap-northeast-1c"
CidrBlock: !Ref PrivateSubnetCCIDR
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub "${PJPrefix}-private-subnet-c"
## Private SubnetD Create
PrivateSubnetD:
Type: "AWS::EC2::Subnet"
Properties:
AvailabilityZone: "ap-northeast-1d"
CidrBlock: !Ref PrivateSubnetDCIDR
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub "${PJPrefix}-private-subnet-d"
## ------------------------------------------------------------#
## RouteTable
## ------------------------------------------------------------#
## Public RouteTableC Create
PublicRouteTableC:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub "${PJPrefix}-public-route-c"
## Public RouteTableD Create
PublicRouteTableD:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub "${PJPrefix}-public-route-d"
## Private RouteTableC Create
PrivateRouteTableC:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub "${PJPrefix}-private-route-c"
## Private RouteTableD Create
PrivateRouteTableD:
Type: "AWS::EC2::RouteTable"
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub "${PJPrefix}-private-route-d"
## ------------------------------------------------------------#
## Routing
## ------------------------------------------------------------#
## PublicRouteC Create
PublicRouteC:
Type: "AWS::EC2::Route"
Properties:
RouteTableId: !Ref PublicRouteTableC
DestinationCidrBlock: "0.0.0.0/0"
GatewayId: !Ref InternetGateway
## PublicRouteD Create
PublicRouteC:
Type: "AWS::EC2::Route"
Properties:
RouteTableId: !Ref PublicRouteTableD
DestinationCidrBlock: "0.0.0.0/0"
GatewayId: !Ref InternetGateway
## ------------------------------------------------------------#
## RouteTable Associate
## ------------------------------------------------------------#
## PublicRouteTable Associate SubnetC
PublicSubnetARouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
SubnetId: !Ref PublicSubnetC
RouteTableId: !Ref PublicRouteTableC
## PublicRouteTable Associate SubnetD
PublicSubnetARouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
SubnetId: !Ref PublicSubnetD
RouteTableId: !Ref PublicRouteTableD
## PrivateRouteTable Associate SubnetC
PrivateSubnetARouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
SubnetId: !Ref PrivateSubnetC
RouteTableId: !Ref PrivateRouteTableC
## PrivateRouteTable Associate SubnetD
PrivateSubnetCRouteTableAssociation:
Type: "AWS::EC2::SubnetRouteTableAssociation"
Properties:
SubnetId: !Ref PrivateSubnetD
RouteTableId: !Ref PrivateRouteTableD
## ------------------------------------------------------------#
## Output Parameters
## ------------------------------------------------------------#
Outputs:
## VPC
VPC:
Value: !Ref VPC
Export:
Name: !Sub "${PJPrefix}-vpc"
VPCCIDR:
Value: !Ref VPCCIDR
Export:
Name: !Sub "${PJPrefix}-vpc-cidr"
## Subnet
PublicSubnetC:
Value: !Ref PublicSubnetC
Export:
Name: !Sub "${PJPrefix}-public-subnet-c"
PublicSubnetCCIDR:
Value: !Ref PublicSubnetCCIDR
Export:
Name: !Sub "${PJPrefix}-public-subnet-c-cidr"
PublicSubnetD:
Value: !Ref PublicSubnetD
Export:
Name: !Sub "${PJPrefix}-public-subnet-d"
PublicSubnetDCIDR:
Value: !Ref PublicSubnetDCIDR
Export:
Name: !Sub "${PJPrefix}-public-subnet-d-cidr"
PrivateSubnetC:
Value: !Ref PrivateSubnetC
Export:
Name: !Sub "${PJPrefix}-private-subnet-c"
PrivateSubnetCCIDR:
Value: !Ref PrivateSubnetCCIDR
Export:
Name: !Sub "${PJPrefix}-private-subnet-c-cidr"
PrivateSubnetD:
Value: !Ref PrivateSubnetD
Export:
Name: !Sub "${PJPrefix}-private-subnet-d"
PrivateSubnetDCIDR:
Value: !Ref PrivateSubnetDCIDR
Export:
Name: !Sub "${PJPrefix}-private-subnet-d-cidr"
## Route
PublicRouteTableC:
Value: !Ref PublicRouteTableC
Export:
Name: !Sub "${PJPrefix}-public-route-c"
PublicRouteTableD:
Value: !Ref PublicRouteTableD
Export:
Name: !Sub "${PJPrefix}-public-route-d"
PrivateRouteTableC:
Value: !Ref PrivateRouteTableC
Export:
Name: !Sub "${PJPrefix}-private-route-c"
PrivateRouteTableD:
Value: !Ref PrivateRouteTableD
Export:
Name: !Sub "${PJPrefix}-private-route-d"
使用可能なベースイメージについて
2020年11月3日時点では、Windows Server 2012 R2, 2016, 2019 の3種類のみとなっています。
ClientOSに依存するアプリケーションを使っている方は、Amazon Workspace のみ選択肢となります。
参照: 自分の Windows デスクトップライセンスを使用する
ユーザプロファイルの保存について
AppStream 2.0 Desktop Viewは、インスタンス毎にユーザを紐付けるAmazon Workspaceと違い、
AutoScalling Policyで定義されているインスタンスをアクセスユーザで共有する仕様のため、
ユーザプロファイルは、インスタンス内部には保存できません。
一方で、S3 Bucket / Google Drive / OneDrive といった選択が可能となっています。
また、S3にユーザプロファイルを設定する場合、自動でS3 Bucketが作成されるうえに、
不意の削除を防ぐ、バケットポリシーも設定されていました。
(一通り検証終わって、削除するときにバケットポリシーの存在に気づきました。)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PreventAccidentalDeletionOfBucket",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:DeleteBucket",
"Resource": "arn:aws:s3:::${S3-bucket-name}"
}
]
}
ユーザ設定について
VDIサービスを使っているとシステム管理者の方が気にするであろうセキュリティの設定です。
以下の3点について設定可能です。
コピーアンドペーストの制限
双方向、あるいは単一方向(Local → Remote , Remote → Local )の設定となります。
ファイルのアップロード、ダウンロードの制限
双方向、あるいは単一方向(Local → Remote , Remote → Local )の設定となります。
プリンタの制限
Localにprint許可をする設定となります。
引用: Get Started with Amazon AppStream 2.0: Set Up With Sample Applications
When they choose Print in the application, they can download a .pdf file that they can print to a local printer.
You can disable this option to prevent users from printing to a local device.
ログオフ
画面上部にAppStream 2.0のツールバーが表示され、そちらからログオフをする形となるため、
いつもどおりのログオフ手順と異なる点はユーザに伝える必要はあるかと思います。
事前に伝えないと、問い合わせに繋がるかなと...
その他
Image作成する際に、予めデスクトップに用意されているImageAssistを利用するのですが、
私の場合、DesktopViewを試すことを目的としていたので、
ショートアイコンを削除してしまい、実態がどこにいるのか焦りましたので、
同じ事態に陥る方のために2020年11月3日時点のパスを記載します。
C:\\Program Files\\Amazon\\Photon\\AppCatalogHelper\\PhotonWindowsAppCatalogHelper.exe
所感
今回、まずはと思い3時間程度で、カスタムイメージの作成からFleetの作成までを行いました。
Amazon Workspaceの場合、前述の通り、ユーザをインスタンスに紐づけてしまうため、
全体のアカウント数に対して、アクティブユーザ数が少ない場合のVDIサービス基盤としての利用としてはいいのかなと思いました。
例えばシフト勤務などを行っている場合など、同時利用者数がアカウント数に対して少なくなると思いますので、
AppStrem 2.0 Desktop Viewを提供するといった形です。
また、50人程度の規模であれば、Amazon Cognitoで内部ユーザとして定義可能ですが、その場合 Photon User
と固定値になり、
ドメイン参加している場合は、個別のユーザ名になることも、事前に伝える必要があるかなと思います。
• 非ドメイン結合インスタンス: C:\\Users\\PhotonUser\\My Files\\Homeフォルダ
• ドメイン参加インスタンス: C:\\Users\\%username%\\My Files\\Homeフォルダ