EC2 インスタンスを利用した環境の構築のファーストステップ

EC2 を触った際のメモ。
手探りでやっていたので、誤りがあったらご容赦をm(_ _)m

# AWS アカウントの設定
## 初期設定
IAM アカウントによる利用を行うため、以下を参考に初期の設定を実施する。

AWSアカウントを取得したら速攻でやっておくべき初期設定まとめ
http://qiita.com/tmknom/items/303db2d1d928db720888

## IAM ロールの利用
EC2 に IAM ロールを割り当てることで、ロールが割り当てられている EC2 インスタンスに AWS のアクセス権限を付与することができ、スクリプトを作成する際にアクセス ID とシークレットキーをスクリプト内に埋め込まなくても、ロールに応じた AWS の各種操作を実行することができる。# 実際には、IAM ロールのメタデータ (http://169.254.169.254/latest/meta-data/iam/security-credentials/<ロール名>) から自動的に取得が行われているらしい。


# EC2 インスタンス作成時の注意点
## 作成時にしか設定できないこと
ストレージの種類の設定
ストレージの種類に変更が必要な場合は、スナップショットを取得し、そのスナップショットから新しいストレージでボリュームを作成し再アタッチが必要
## IAM ロールの設定
現状は、新規作成時にのみ IAM ロールを設定可能。そのため、IAM ロールを今後利用するかは不明な場合でも、空の IAM ロールを割り当ててその後にメンテナンスする方法をとったほうが良い


**参考資料**
AWS EC2 with IAM Role: No credentials specified or obtained from persisted/shell defaults.
http://panduchunduri.com/aws-ec2-with-iam-role-no-credentials-specified-or-obtained-from-persistedshell-defaults/
Amazon リソースネーム（ARN）と AWS サービスの名前空間
https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws-arns-and-namespaces.html
AWS リソースの管理に関するポリシーの例
http://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_examples.html
IAM ポリシーエレメントの参照
http://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_elements.html
Windows で EBS ボリュームのストレージ領域を拡張する
http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/ebs-expand-volume.html


# EC2 インスタンスの作成
AWS Tools for Windows PowerShell で、Powershell を使用して EC2 インスタンスを作成することが可能。
Amazon が提供している Windows の AMI であれば、初期状態でインストールされているが、ローカルの環境から実行したい場合などは、以下からダウンロードが可能。
AWS Tools for Windows PowerShell 
https://aws.amazon.com/jp/powershell/
複雑な構成を構築する場合には、CloudFormation の利用を検討する。

## フィルターの確認
help get-ec2image -Paramter filter のような形式で、使用できるフィルターを確認できるため、AMI の取得等で、使用するリソースのフィルターを設定する場合に、どのような条件が使用できるかはこれで確認する

## Sysprep の実行
EC2Config サービスを使用して Sysprep の実行をお行うことができる。

EC2Config サービスを使用した Windows インスタンスの設定
http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/UsingConfig_WinAMI.html
Sysprep を使って標準の Amazon マシンイメージを作成します。
http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/ami-create-standard.html
EC2 ConfigService SettingsのAdministrator Passwordの設定項目についての確認
https://forums.aws.amazon.com/message.jspa?messageID=575792
Amazon EC2（Windows Server 2012）の カスタムAMI の作成
http://dev.classmethod.jp/cloud/aws/windows2012-ec2-clone/

## インスタンスメタデータの取得
インスタンス内で、 http://169.254.169.254/latest/meta-data/ にアクセスをすることで、メタデータを取得することができる。
タグの情報を取得できるため、タグの内容をスクリプトで取得してインスタンスの構築に利用することができないかも検討する。

インスタンスメタデータとユーザーデータ
http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-metadata.html


**参考資料**
Tagging Amazon EC2 Instances at Launch 
https://blogs.aws.amazon.com/net/post/Tx2CCTE5QGSFDUW/Tagging-Amazon-EC2-Instances-at-Launch
AWS Tools for Windows PowerShell でインスタンス作成
http://d.hatena.ne.jp/neo_karo_jp/20130626/1372220563
AWSのEC2インスタンスをスクリプトで作成する (2)
http://koba965.blog.fc2.com/blog-entry-13.html
AWSエンジニアのためのはじめてのPowerShell
http://dev.classmethod.jp/cloud/aws/aws-tools-for-windows-powershell/
AWS Tools for Windows PowerShell -フィルタ-
http://www.simpline.co.jp/tech/?p=528
Filtering by StartTime with the AWS PowerShell Cmdlets
http://mikefrobbins.com/2015/04/09/filtering-by-starttime-with-the-aws-powershell-cmdlets/


# EC2 インスタンスから外部ネットワーク (インターネット) へのアクセス
## インターネットと相互接続をする場合 : 
インターネットゲートウェイを設定しているサブネットを構築し、インスタンスにパブリック IP を付与
ルートテーブルで 0.0.0.0/0 をインターネットゲートウェイに向ける
## インターネットにアクセスできればよい場合：
NAT ゲートウェイを構築することで、インターネットに出るための環境が構築できる。
ルートテーブルで 0.0.0.0/0 を NAT ゲートウェイに向ける

## S3 へのアクセス
セキュリティグループでプレフィックス ID を使用することで、AWS のリソースへのアクセス許可として使用することができる。
現状、S3 のアクセスがプレフィックス  ID を使用してアクセスを許可することができるため、アウトバウンドのルールで制限をするときに利用する。
	
Get-EC2PrefixList Cmdlet
http://docs.aws.amazon.com/powershell/latest/reference/items/Get-EC2PrefixList.html
	
VPC エンドポイントを作成することで、NAT ゲートウェイを使用しなくても S3 のアクセスルートを作成することができる。

**参考資料**
VPCエンドポイントとアウトバウンドについてhttp://www.simpline.co.jp/tech/?p=853


# EC2 インスタンスで使用するイメージのアップロード
今回は検証していないが、手元の仮想マシンのイメージを AWS 上にアップロードして使用することも可能。
EC2Config サービスについては、以下からダウンロードすることが可能。

EC2Config の最新バージョンのインストールhttp://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/UsingConfig_Install.html

インスタンスを (AMI はエクスポートできないらしいので、一度インスタンス化する) S3 にエクスポートしてダウンロードすることも可能なため、手元の環境に作成した環境を DL したいというような相互の運用が可能

**参考資料**
What Is VM Import/Export?
http://docs.aws.amazon.com/ja_jp/vm-import/latest/userguide/what-is-vmimport.html
Using the New Import Cmdlets for Amazon EC2 
https://blogs.aws.amazon.com/net/post/TxQYNEB9LIO2OC/Using-the-New-Import-Cmdlets-for-Amazon-EC2あたらしいAmazon EC2のImport Cmdletsをつかってみる
http://aws.typepad.com/sajp/2015/08/using-the-new-import-cmdlets-for-amazon-ec2.html
Import-EC2Image Cmdlet
http://docs.aws.amazon.com/powershell/latest/reference/items/Import-EC2Image.html
New-EC2InstanceExportTask Cmdlet
http://docs.aws.amazon.com/powershell/latest/reference/Index.html


# 起動時に任意の処理を実行
起動時のスクリプト実行には UserData の仕組みを利用することができる。
UserData内に<PowerShell></PowerShell>を記載することで、PowerShell のスクリプトを起動後 (起動直後ではなく起動後から数分のタイムラグがある) に実行することができる。

デフォルトの設定では、ユーザーデータは初回に一度のみ実行されるが、「<persist>true</persist>」を設定することで、毎回実行されるように設定を変更することも可能。

## 記載方法の例
```
<powershell>
処理を記載
</powershell>
<persist>true</persist>
```

New-EC2Instanse 等でユーザーデータを指定したい場合に Base64 エンコーディングする場合は、以下のようなコマンドで変換を行う。

```
$script = {
Write-Output $msg
}

$UserData = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($Script))

$Script = @"
Write-Output `$msg
"@

$UserData = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($Script))
```

**参考資料**
ユーザーデータでスクリプトを実行する
http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/WindowsGuide/ec2-instance-metadata.html#user-data-execution


# ユーザーデータの使用
参考資料のスクリプトを元に、ドメイン参加を行うことが可能。
Add-Computer を使用する場合、既にコンピューターアカウントが作成されている場合 (向こうの状態も含む) には、ドメインの参加が実施できないため利用時には注意する。
既にコンピューターアカウントが作成されており、上書きでドメイン参加を実施する場合は、ＷＭI を使用する。

ドメイン参加に使用するユーザーのアカウント名 / パスワードをユーザーデータのスクリプト内に記載した場合は、メタデータや管理コンソールからユーザーデータを表示した際に内容が確認できるということを覚えておく。

**参考資料**
EC2 User DataによるActive Directoryドメインへの自動参加http://aws.typepad.com/sajp/2014/08/ec2-user-data_active-directory.html
AWS - Auto join EC2 Windows instance to Active Directory Domain
http://techblogsearch.com/a/aws-auto-join-ec2-windows-instance-to-active-directory-domain.html
AWS - Auto join EC2 Windows instance to Active Directory Domain 
http://thesysadminswatercooler.blogspot.jp/2015/09/aws-autoscale-windows-server-and-join.html
[SOLVED] Domain Join Assistance: Account Already Exists
https://social.technet.microsoft.com/Forums/windowsserver/en-US/d602f35b-4c8c-44c4-a447-554189059867/solved-domain-join-assistance-account-already-exists?forum=winserverpowershell
Day 39: Injecting a Start-up Script Into an AWS Instance Using User Data 
http://www.systemcentercentral.com/day-39-injecting-start-script-aws-instance-using-user-data/
EC2 Windows instance user data scripthttps://us-east-1.zone/ec2-windows-instance-user-data-script/
EC2インスタンスが自動的にMicrosoft Active Directoryドメインに参加するように構成する方法
→ AWS のディレクトリサービスまたは、AD Connector を使用している場合の方法http://aws.typepad.com/sajp/2016/05/how-to-configure-your-ec2-instances-to-automatically-join-a-microsoft-active-directory-domain.html


# EC2 インスタンスから S3 へのアクセスの制限
IAM ロールを割り当てることで制御を行うのがシンプル。
以下のようなロールを割り当てることで、バケット内のファイルの一覧取得とファイルのダウンロードを実施することが可能。
インスタンス展開時に最新のファイルを入手する場合などは、AMI に含めるのではなく、S3 から取得させることでファイル変更によるマスターイメージの修正を不要にできる。# 起動中のインスタンスのファイル変更を考慮する必要は DSC の利用を検討。定期的な起動/停止 (再起動) があり、再起動時に新規にファイルを取得すればよいのであれば、永続化したユーザーデータにスクリプトを仕込むことで対応することができる可能性がある。

```
{
	 "Version": "2012-10-17",
	 "Statement": [
	 {
		 "Effect": "Allow",
		 "Action": [
		 "s3:GetObject",
		 "s3:ListBucket"
		 ],
		 "Resource": ["arn:aws:s3:::examplebucket/*"]
	 }
	 ]
}
```

# PowerShell
## AWS CLI のコマンドとの対応
AWS CLI と　AWS Tools for PowerShell の対応については、「Get-AWSCmdletname」の「AwsCliCommand」オプションを使用することで確認できる。

Get-AWSCmdletName 
http://docs.aws.amazon.com/powershell/latest/reference/items/Get-AWSCmdletName.html
## PoweShell 内で使用する資格情報の設定
スクリプト内にアクセスキー / シークレットキーを書くのは望ましくないが、以下のような内容で資格情報を設定することが可能
Set-AWSCredentials -AccessKey <アクセスキー> -SecretKey <シークレットキー>
Set-DefaultAwsRegion ap-northeast-1

## 資格情報のストア
Using AWS Credentials
http://docs.aws.amazon.com/powershell/latest/userguide/specifying-your-aws-credentials.html
AWS - Assume IAM using PowerShell on an instance
http://stackoverflow.com/questions/23800197/aws-assume-iam-using-powershell-on-an-instance
How to assign AWS credentials to SYSTEM user?
http://stackoverflow.com/questions/32613651/how-to-assign-aws-credentials-to-system-user

**参考資料**
AWS Tools for Windows PowerShell Cmdlet Reference
http://docs.aws.amazon.com/powershell/latest/reference/
AWS Tools for Windows PowerShell のドキュメント 
https://aws.amazon.com/jp/documentation/powershell/
AWS Tools for Windows PowerShell
https://aws.amazon.com/jp/powershell/
AWS Tools for Windows PowerShellを使ってみた
http://dev.classmethod.jp/cloud/aws/aws-tools-powershell/
AWSエンジニアのためのはじめてのPowerShell
http://dev.classmethod.jp/cloud/aws/aws-tools-for-windows-powershell/
[AWSマイスターシリーズ] AWS CLI / AWS Tools for Windows PowerShell
http://www.slideshare.net/AmazonWebServicesJapan/aws-aws-cli
Aws tools for power shellをつかいこなそう
http://www.slideshare.net/GentaWatanabe/aws-tools-for-power-shell
AWS+Windows環境における大規模ソーシャルゲーム開発／運用の実際
http://gihyo.jp/admin/serial/01/grani/0003
AWS Tools for Windows PowerShell でインスタンス作成
http://d.hatena.ne.jp/neo_karo_jp/20130626/1372220563
Pro PowerShell for Amazon Web Services
https://www.amazon.co.jp/dp/B00HG2CQ3O


# 請求情報
デフォルトでは、AWS アカウントの所有者が請求情報へのアクセス権を保持している。IAM アカウントのユーザーは請求のコンソールにアクセスができないため、明示的にアクセスを許可する必要がある。
1. AWS ルートアカウント (AWS アカウント作成に使用したメールアドレスのアカウント) で、AWS Web サイトへのアクセスをアクティベート
2. 請求情報が確認できるように権限の付与

Billing and Cost Management の権限リファレンス
https://docs.aws.amazon.com/ja_jp/awsaccountbilling/latest/aboutv2/billing-permissions-ref.html
「AdministratorAccess」の管理ポリシーが付与されている場合、すべての操作が可能な状態のため、明示的にポータルのアクセスを許可しなくてもアクティベートすれば表示可能な状態となっているはず。

**参考情報**
Monitoring Your Estimated Costs with Windows PowerShell https://blogs.aws.amazon.com/net/post/Tx1MXO6CUVIPUPN/Monitoring-Your-Estimated-Costs-with-Windows-PowerShell
Get-AWSBillingEstimate.ps1 https://gist.github.com/Sam-Martin/5dac054187ba10e97f3d
請求の情報およびツールへのアクセス許可https://docs.aws.amazon.com/ja_jp/awsaccountbilling/latest/aboutv2/grantaccess.html


# 通知
バッチからメールを送信したい場合などは、SES による実現することが可能
デフォルトの状態では、サンドボックスの状態で動作しており、送信先やメール送信数の制限があるため、申請しサンドボックスの制限を解除する必要がある。
https://console.aws.amazon.com/support/home?region=us-east-1#/case/create?issueType=service-limit-increase&limitType=service-code-ses
管理用メールとして、特定の送信先に少量のメールを送るだけであれば、サンドボックスでも動作させることができる。

SES の SMTP アカウントを作成した場合、初期のポリシーでは、Raw メールのみ許可されている状態となっているため、アクションに通常のメールによる送信を許可する。
"Action": ["ses:SendEmail", "ses:SendRawEmail"]

API 経由でメールを送信するか、SMTP サーバーに接続をしてメールを送信するかによって、使用する情報が異なる。

|送信方法|使用する情報|
|:--|:--|
|API|IAM のアクセスキー ID とシークレットアクセスキー|
|SMTPインターフェース|SES の SMTP 資格情報で作成した IAM ロールのアクセスキー ID とパスワード(ここで取得したパスワードはシークレットアクセスキーではなく SMTP パスワードとなる)|

Amazon SES での認証情報の使用
https://docs.aws.amazon.com/ja_jp/ses/latest/DeveloperGuide/using-credentials.html

シークレットアクセスキーと SMTP パスワードは異なる情報となるため、任意に作成した IAM ユーザーや IAM ロールのシークレットアクセスキーでメールを送信する場合、シークレットアクセスキーを SMTP パスワードに変換する必要がある。
サンプルのプログラムは以下から取得可能 (Java のプログラム)
Amazon SES SMTP 認証情報を取得する
https://docs.aws.amazon.com/ja_jp/ses/latest/DeveloperGuide/smtp-credentials.html

```
javac SesSmtpCredentialGenerator.java
SET AWS_SECRET_ACCESS_KEY=AAAAAAAAAAAAAAAAAAA
java SesSmtpCredentialGenerator
```

**参考情報**
Sending email through Amazon SES with PowerShell 
http://www.fl3m.com/2012/08/sending-email-through-amazon-ses-with.html
Sending custom notifications from PowerShell using AWS SNS
http://social.technet.microsoft.com/wiki/contents/articles/30192.sending-custom-notifications-from-powershell-using-aws-sns.aspx
Amazon SES API を使用して E メールを送信する
https://docs.aws.amazon.com/ja_jp/ses/latest/DeveloperGuide/send-email-api.html
AWS SESをちゃんと使うためにやるべきこと
http://qiita.com/zaru/items/4be9b55ba807670cf224