20190716のAWSに関する記事は17件です。

AWS ELBでSSL化した際にLaravelのメール認証(EmailVerification)ができなくなった話

起きたこと

ELBでSSL化を行った際に、Laraveのメール認証が動かなくなってしまった。

エラーを探ってるとこんなメッセージが
This request has been blocked;. the content must be served over HTTPS.

結論

ここに記載してあるとおり
TLS/SSL証明を行うロードバランサの裏でアプリケーションが実行されている場合は別で対応が必要みたいです。

Tip!! AWS Elastic Load Balancingを使用している場合、$headersの値は
Request::HEADER_X_FORWARDED_AWS_ELBに設定する必要があります。$headersで使用する
内容の詳細は、Symfonyのtrusting proxiesドキュメントを参照してください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

VScode�でAWS Cloud9の操作 | アクセスエラーの原因と対処法

概要

VScode でAWS Cloud9の操作 - Qiita

参考の手順に従いVSCodeにLive Sync for AWS Cloud9をセットアップした。

しかし、エラーが発生しCloud9にアクセスできない。

その対処方を備忘録として残す。

問題

Environmentsは表示されるが、Connectするとエラーが発生している。

SnapCrab_NoName_2019-7-16_20-56-49_No-00.jpg

エラー内容

SnapCrab_NoName_2019-7-16_20-57-1_No-00.jpg

User: arn:aws:iam::714834470136:user/local-vscode-t3500 is not authorized to perform: cloud9:CreateEnvironmentToken on resource: 5992e3f14a604d23a5146be72951fe99 with an explicit deny

原因

原因は、Cloud9を作成したユーザと、VSCodeに登録した ユーザ異なる ためであった。

I believe what is happening is that another user has created the environment and that user has not shared the environment with the user you specified in VS Code. I believe the fix would be to log into the Cloud9 web interface and click the "Share" button and add the user that you're using in VS Code.

How to delete C9 Environment? · Issue #4 · iann0036/cloud9-sync

対策

Cloud9の設定から、VSCodeに登録した ユーザを招待 することで、Environmentへのアクセス権限を得ることができ、無事VSCodeからアクセスできた。

SnapCrab_NoName_2019-7-16_20-57-50_No-00.jpg

以上

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

s3cmd --help 日本語訳

業務で必要になったため、自分用に訳します。
s3cmdすら今更感がありますが、version 1.5.2準拠です(最新は2.0.2のよう)。
この内容で日本語訳を作っておきたいと思うレベルの英語力なので、なにか間違いがあればご指摘いただけると大変助かります。

前文

s3cmdは、Amazon S3ストレージ内のオブジェクトを管理するためのツールです。 「バケット」の作成と削除、そしてこれらのバケットの「オブジェクト」のアップロード、ダウンロード、削除を可能にします。

オプション

-h, --help

ヘルプを表示します。

--configure

対話型(再)設定ツールを起動します。 オプションで --configure s3://some-bucketを使用すると特定のバケットへのアクセスをテストします。

-c FILE, --config=FILE

設定をファイルから読み込みます。デフォルトのファイルパスは$HOME/.s3cfgです。

--dump-config

設定ファイルとコマンドラインオプションを解析した後、現在の設定をダンプします。

--access_key=ACCESS_KEY

AWSのアクセスキーを指定します。

--secret_key=SECRET_KEY

AWSのシークレットキーを指定します。

-n, --dry-run

アップロードまたはダウンロードする必要があるものだけを表示し、実際には実行しません。 バケットリストやその他の情報を取得するためにS3リクエストを実行する可能性があります(ファイル転送コマンドのみ)。

-s, --ssl

S3との通信にHTTPS接続を利用します。

--no-ssl

HTTPSを利用しません。(※デフォルト)

-e, --encrypt

S3へのアップロード前にファイルを暗号化します。

--no-encrypt

ファイルを暗号化しません。

-f, --force

上書きやその他の危険な操作を強制実行します。

--continue

getコマンド使用時、部分的にダウンロードされたファイルの取得を続行します(の場合のみ)。

--continue-put

部分的にアップロードされたファイルまたはマルチパートアップロード内パートのアップロードを続行します。 サイズとmd5が一致しないファイル/パートを再起動し、スキップします。

注:MD5チェックサムは、ファイルの等価性を(部分的に)チェックするために必ずしも十分ではありません。 ご自身の責任でこれを有効にしてください。

--upload-id=UPLOAD_ID

--continue-putと同様に既存のアップロードを続けたい場合や、複数の部分的なアップロードがある場合は、マルチパートアップロードのUPLOAD_IDを設定します。s3cmd multipart [URI]を使用して`、指定されたURIにどのUPLOAD_IDが関連付けられているかを確認します。

--skip-existing

getおよびsyncコマンド使用時、転送先に存在するファイルをスキップします。

-r, --recursive

再帰的アップロード、ダウンロード、削除を実行します。

--check-md5

syncコマンドでファイルを比較する際にMD5チェックサムを確認します。(※デフォルト)

--no-check-md5

syncコマンドでファイルを比較する際にMD5チェックサムを確認せず、ファイルサイズのみで比較します。転送速度が大幅に向上する可能性がありますが、変更されたファイルを見逃すこともあります。

-P, --acl-public

だれでも読み取り可能になるようにACLを付与してオブジェクトを保存します。

--acl-private

あなただけがアクセスを許可されているデフォルトのACLを付与してオブジェクトを保存します。

--acl-grant=PERMISSION:EMAIL or USER_CANONICAL_ID

指定のamazonユーザーに権限を与えます。パーミッションはread, write, read_acp, write_acp, full_control, allのいずれかです。

--acl-revoke=PERMISSION:USER_CANONICAL_ID

指定のamazonユーザーに与えられた権限を取り消します。パーミッションはread, write, read_acp, write_acp, full_control, allのいずれかです。

-D NUM, --restore-days=NUM

restoreコマンド使用時、復元されたファイルを利用可能に保つ日数を指定します。

--delete-removed

syncコマンド使用時、対応するローカルファイルがないリモートオブジェクトを削除します。

--no-delete-removed

リモートオブジェクトを削除しません。

--delete-after

syncコマンド使用時、新規アップロード後に削除を実行します。

--delay-updates

syncコマンド使用時、更新されたすべてのファイルを最後に配置します。

--max-delete=NUM

delおよびsyncコマンド使用時、指定の数値NUMを超える数のファイルを削除しません。

--add-destination=ADDITIONAL_DESTINATIONS

最後の引数に加えて、並列アップロード用の追加の転送先を指定します。 繰り返す可能性があります。

--delete-after-fetch

getおよびsyncコマンド使用時、ローカルファイルにフェッチした後にリモートオブジェクトを削除します。

-p, --preserve

ファイルシステムの属性(モード、所有権、タイムスタンプ)を保持します。 syncコマンドのデフォルトです。

--no-preserve

ファイルシステムの属性を保持しません。

--exclude=GLOB

GLOBに一致するファイル名とパスは同期から除外されます。

--exclude-from=FILE

--excludeのGLOBをファイルから読み込みます。

--rexclude=REGEXP

REGEXP(正規表現)に一致するファイル名とパスは同期から除外されます。

--rexclude-from=FILE

--rexcludeのREGEXPをファイルから読み込みます。

--include=GLOB

以前に--(r)exclude(-from)パターンの1つによって除外されていたとしても、GLOBに一致するファイル名とパスが同期に含まれます。

--include-from=FILE

--includeのGLOBをファイルから読み込みます。

--rinclude=REGEXP

--includeと同じですが、GLOBの代わりにREGEXP(正規表現)を使用します。

--rinclude-from=FILE

--rincludeのREGEXPをファイルから読み込みます。

--ignore-failed-copy

キーが見つからず失敗した場合でも、終了しません。

--files-from=FILE

FILEからソースファイル名のリストを読みます。 標準入力から読み込むには - を使用してください。

--region=REGION, --bucket-location=REGION

バケットを作成するリージョンを指定します。

--reduced-redundancy, --rr

putcpmvコマンド使用時、'低冗長化' でオブジェクトを保存します。GBあたりの価格が下がります。

--no-reduced-redundancy, --no-rr

putcpmvコマンド使用時、'低冗長化' せずにオブジェクトを保存します。GBあたりの価格が高くなります。

--access-logging-target-prefix=LOG_TARGET_PREFIX

cfmodifyおよびaccesslogコマンド使用時、アクセスログのターゲットプレフィックス(S3 URI)を指定します。

--no-access-logging

cfmodifyおよびaccesslogコマンド使用時、アクセスログ出力を無効にします。

--default-mime-type=DEFAULT_MIME_TYPE

格納されているオブジェクトのデフォルトのMIMEタイプを指定します。 アプリケーションのデフォルトはbinary/octet-streamです。

-M, --guess-mime-type

拡張子またはMIME magicでファイルのMIMEタイプを推測します。 -default-mime-typeオプションで指定されているデフォルトのMIMEタイプにフォールバックします。

--no-guess-mime-type

MIMEタイプを推測せず、代わりにデフォルトのタイプを使用します。

--no-mime-magic

MIMEタイプを推測するときに、mime magicを使用しません。

-m MIME/TYPE, --mime-type=MIME/TYPE

MIMEタイプを強制します。 --default-mime-type--guess-mime-typeの両方をオーバーライドします。

--add-header=NAME:VALUE

アップロード要求に指定されたHTTPヘッダーを追加します。 複数回使用できます。 例えば、このオプションを使用して 'Expires'または 'Cache-Control'ヘッダー(あるいはその両方)を設定します。

--remove-header=NAME

modifyコマンド使用時、指定されたHTTPヘッダを削除します。 複数回使用できます。 たとえば、このオプションを使用して 'Expires 'または 'Cache-Control 'ヘッダー(あるいはその両方)を削除します。

--server-side-encryption

putsynccpmodifyコマンド使用時、オブジェクトを配置する際にサーバー側の暗号化を使用するように指定します。

--encoding=ENCODING

自動検出された端末とファイルシステムのエンコーディング(文字セット)をENCODINGで上書きします。

--add-encoding-exts=EXTENSIONs

S3へのアップロード時に、[css, js, html]などコンマ区切りの拡張子にエンコードを追加します。

--verbatim

コマンドラインで指定されているS3名を使用してください。 前処理やエンコードなどは行われません。注意して使用してください。

--disable-multipart

--multipart-chunk-size-mbで指定されたファイルサイズより大きいファイルはマルチパートアップロードを無効にします。

--multipart-chunk-size-mb=SIZE

マルチパートアップロードの各チャンクのサイズを指定します。 SIZEより大きいファイルはマルチスレッド - マルチパートとして自動的にアップロードされ、小さいファイルは従来の方法でアップロードされます。 SIZEはメガバイト単位で、デフォルトのチャンクサイズは15MB、最小許容チャンクサイズは5MB、最大は5GBです。

--list-md5

lsコマンド使用時、バケットリストにMD5チェックサムを含めます。

-H, --human-readable-sizes

判読可能な形式でサイズを表示します(例:1234→1kB)。

--ws-index=WEBSITE_INDEX

ws-createコマンド使用時、index-documentを指定します。

--ws-error=WEBSITE_ERROR

ws-createコマンド使用時、error-documentを指定します。

--expiry-date=EXPIRY_DATE

expireコマンド使用時、有効期限ルールがいつ有効になるかを示します。

--expiry-days=EXPIRY_DAYS

expireコマンド使用時、オブジェクトの作成から有効期限ルールが有効になるまでの日数を示します。

--expiry-prefix=EXPIRY_PREFIX

expireコマンド使用時、有効期限ルールが適用されるプレフィックスを使用して1つ以上のオブジェクトを識別します。

--progress

進行状況メーターを表示します(TTYのデフォルト)。

--no-progress

進行状況メーターを表示しません(TTYでない場合のデフォルト)。

--enable

cfmodifyコマンド使用時、特定のCloudFrontディストリビューションを有効にします。

--disable

cfmodifyコマンド使用時、特定のCloudFrontディストリビューションを無効にします。

--cf-invalidate

CloudFrontにアップロードされたファイルを無効にします。 [cfinval]コマンドも参照してください。

--cf-invalidate-default-index

Custom OriginおよびS3静的Webサイトを使用している場合は、デフォルトのインデックスファイルを無効にします。

--cf-no-invalidate-default-index-root

Custom OriginおよびS3静的Webサイトを使用している場合は、デフォルトのインデックスファイルへのパスを無効にしません。

--cf-add-cname=CNAME

cfcreateおよびcfmodifyコマンド使用時、指定されたCNAMEをCloudFrontディストリビューションに追加します。

--cf-remove-cname=CNAME

cfmodifyコマンド使用時、指定されたCNAMEをCloudFrontディストリビューションから削除します。

--cf-comment=COMMENT

cfcreateおよびcfmodifyコマンド使用時、CloudFrontディストリビューションにCOMMENTを設定します。

--cf-default-root-object=DEFAULT_ROOT_OBJECT

cfcreateおよびcfmodifyコマンド使用時、URLにオブジェクトが指定されていない場合に返されるデフォルトのルートオブジェクトを相対パスで設定します。

(例:/default/index.html または s3://bucket/default/index.html → default/index.html)

-v, --verbose

詳細出力を有効にします。

-d, --debug

デバッグ出力を有効にします。

--version

s3cmdのバージョンを表示します。

-F, --follow-symlinks

通常のファイルであるかのようにシンボリックリンクに対応します。

--cache-file=FILE

ローカルソースのMD5チェックサムを含むキャッシュファイルを指定します。

-q, --quiet

標準出力へ出力せずに実行します。

--ca-certs=CA_CERTS_FILE

システムデフォルトの代わりに使用するSSL CA証明書ファイルへのパスを指定します。

--check-certificate

SSL証明書の有効性を確認します。

--no-check-certificate

SSL証明書の有効性を確認しません。

--signature-v2

新しい署名方法の代わりにAWS Signatureバージョン2を使用します。 まだAWS Signature v4を搭載していないS3ライクなシステムに役立ちます。

コマンド

バケットを作成する

s3cmd mb s3://BUCKET

バケットを削除する

s3cmd rb s3://BUCKET

バケットまたはオブジェクトを一覧表示する

s3cmd ls [s3://BUCKET[/PREFIX]]

すべてのバケットのすべてのオブジェクトを一覧表示する

s3cmd la

バケットにファイルをアップロードする

s3cmd put FILE [FILE...] s3://BUCKET[/PREFIX]

バケットからファイルをダウンロードする

s3cmd get s3://BUCKET/OBJECT LOCAL_FILE

バケットからファイルを削除する

s3cmd del s3://BUCKET/OBJECT
s3cmd rm s3://BUCKET/OBJECT # del のエイリアス

アーカイブからファイルを復元する

s3cmd restore s3://BUCKET/OBJECT

ディレクトリツリーをS3と同期する

オプションで上書きされない限り、sizeとmd5チェックサムを使用してファイルの鮮度をチェックします。

s3cmd sync LOCAL_DIR s3://BUCKET[/PREFIX] or s3://BUCKET[/PREFIX] LOCAL_DIR

バケットの使用量を確認する

s3cmd du [s3://BUCKET[/PREFIX]]

バケットやファイルに関する情報を取得する

s3cmd info s3://BUCKET[/OBJECT]

バケット間でオブジェクトをコピーする

s3cmd cp s3://BUCKET1/OBJECT1 s3://BUCKET2[/OBJECT2]

オブジェクトのメタデータを変更する

s3cmd modify s3://BUCKET1/OBJECT

バケット間でオブジェクトを移動する

s3cmd mv s3://BUCKET1/OBJECT1 s3://BUCKET2[/OBJECT2]

バケットやファイルのアクセスコントロールリスト (ACL)を変更する

s3cmd setacl s3://BUCKET[/OBJECT]

バケットポリシーを変更する

s3cmd setpolicy FILE s3://BUCKET

マルチパートアップロードを表示する

s3cmd multipart s3://BUCKET [Id]

マルチパートアップロードを中止する

s3cmd abortmp s3://BUCKET/OBJECT Id

マルチパートアップロードのパートを一覧表示する

s3cmd listmp s3://BUCKET/OBJECT Id

バケットのアクセスログ出力を有効化または無効化する

s3cmd accesslog s3://BUCKET

秘密鍵を使って任意の文字列に署名する

s3cmd sign STRING-TO-SIGN

有効期限付きの限定公開アクセスを提供するためにS3 URLに署名する

s3cmd signurl s3://BUCKET/OBJECT <expiry_epoch|+expiry_offset>

バケット内の無効なファイル名を修正する

s3cmd fixbucket s3://BUCKET[/PREFIX]

バケットからウェブサイトを作成する

s3cmd ws-create s3://BUCKET

ウェブサイトを削除する

s3cmd ws-delete s3://BUCKET

ウェブサイトの情報を表示する

s3cmd ws-info s3://BUCKET

バケットの有効期限ルールを設定または削除する

s3cmd expire s3://BUCKET

バケットのライフサイクルポリシーを設定する

s3cmd setlifecycle s3://BUCKET

バケットのライフサイクルポリシーを削除する

s3cmd dellifecycle s3://BUCKET

CloudFrontディストリビューションを一覧表示する

s3cmd cflist

CloudFrontディストリビューションのパラメータを表示する

s3cmd cfinfo [cf://DIST_ID]

CloudFrontディストリビューションを作成する

s3cmd cfcreate s3://BUCKET

CloudFrontディストリビューションを削除する

s3cmd cfdelete cf://DIST_ID

CloudFrontディストリビューションのパラメータを変更する

s3cmd cfmodify cf://DIST_ID

CloudFrontの無効リクエストのステータスを表示する

s3cmd cfinvalinfo cf://DIST_ID[/INVAL_ID]
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

httpsのリダイレクト(S3+CloudFront+Route53)

概要と注意

wwEBサイトの引越しの時などに、Route53+S3でS3の静的Webサイトホスティング機能を使うと便利。
しかし、httpsをリダイレクトしたい場合、S3単体ではSSL証明書を扱うことができないため、CloudFront経由で行う。

S3 Static Website hostingで全てのリクエストをリダイレクトするように設定する。

AWS Certificate Managerで証明書を作る。

CloudFrontのDistributionを作りOriginにS3 Static Website hostingのエンドポイントと証明書を設定する。

Route53にS3が向くようにAレコードをを追加する。

※バージニア北部で作成してください!!!CloudFront に SSL Certificate が東京リージョンを指定できないため。

1.ドメインを登録し、Route53のNSレコードを登録する

AWS Certificate Manager - ELB(+ACM発行証明書)→EC2の1-3を参考に設定する。

2.ACM から SSL/TLS 証明書を取得する

AWS Certificate Manager - ELB(+ACM発行証明書)→EC2の4を参考に証明書を取得する。

3.S3 バケットを作成し、リクエストを別のドメイン名にリダイレクトするようにバケットを設定する

「エンドポイント」は後で使います。
「リクエストをダイレクトする」にし、*リクエストをリダイレクトする先のドメイン (oldexample.com) * の名前を入力します。
プロトコルは「https」のみにします。
image.png

4.CloudFront ディストリビューションを作成または更新する

Origin Domain Name:「3.S3 バケットを作成し、リクエストを別のドメイン名にリダイレクトするようにバケットを設定する」のStatic Website hostingのエンドポイントを入力
Viewer Protocol Policy:HTTP and HTTPS
image.png

Alternate Domain Names(CNAMEs):ユーザーがコンテンツにアクセスするために使用するリダイレクト元(newexample.com)を入力する。
SSL Certificate:Custom SSL Certificate にし、「#2.ACM から SSL/TLS 証明書を取得する」で取得したACMを選択。
image.png

5.CloudFront ディストリビューションにトラフィックをルーティングする Route 53 レコードを作成する

タイプ: A - IPv4 address
エイリアス:はい
エイリアス先: CloudFront ディストリビューション
ルーティングポリシー:シンプル
image.png
CloudFrontのStatusがDeployedになるまで30分ほどかかるため、エイリアス先に表示されるのに時間がかかります。
ほかに表示がされない場合は、Route 53 エイリアスリソースレコードセットを作成する際に目的のエイリアス先が選択できないのはなぜですか?
を参照しましょう。

6.テストする

どちらの場合も、DNS クエリをリダイレクトする先のドメインのコンテンツが表示されるか確認しましょう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

新入社員とはじめるAWS ~Lambdaをつかってサーバーを自動で起動・停止させてみよう編~

自己紹介

はじめまして。
4月にとあるSIerに新卒入社した、たからといいます。

もともと勉強していたのはWebの分野で、開発か新しめの技術に触れられる部署を希望していたのですが残念ながら叶わず!
しかし色々あってAWSを勉強させてもらってます!

興味はあったのですが、何から手を付けていいかわからなかったところ、勉強する機会がもらえて非常にありがたいです。
そこで自分が実際に触って動かした内容をまとめていこうと思います!

こんな人向け

・AWS興味あるけど触ったことないよ
大丈夫です!こちらの記事などを参考にサーバーを立てるとこまでやってみて下さい!
接続とかApacheのインストールはしなくても大丈夫です!

AWSはサーバー起動くらいしかやったことないよ

EC2以外もちょっと触ってみたいよ

っていうぐらいの層の人向けに書いてます!

やりたいこと

・EC2で立てたサーバーを、決めた時間に自動で停止したり起動させたい
・土日など、サーバー使わないよ!っていう日だけ自動で停止させて、月曜の朝に自動で起動させて少しでも節約させます。AWSは従量課金制なので。。

登場人物

AWS Lambda

2019-07-16_14h58_40.png

「らむだ」と読みます。

・他のAWSと連携したりして、サーバーを立てずに特定の関数(メソッド)だけ実行できます。

使用例:
・サーバーのログやエラーなどをSlackに通知させる
・S3(AWSのクラウドストレージサービス)に送られた画像ファイルを自動でリサイズする
といった風に、各サービス間を連携させる関数を作れます。

・今回はこいつを使って、決まった時刻にサーバを起動&停止させる関数を作ります。

IAMロール

2019-07-16_15h00_11.png

・各AWSサービスを利用するための権限設定ができます。

「あいあむ」と読みます。「I am」とかかってるんですかね!おぼえやすい!

・構築された環境を、初心者がワンクリックで崩壊させるのを防いでくれるような設定ができたりします。

・作成したIAMロールに、いろいろな権限を持たせる形で運用します。こちらの記事が理解しやすかったです!
AWS アカウント、IAM ユーザー、IAM グループ、IAM ロールの違い

Lambdaで作った関数を実行するのにもIAMロールが必要になるため、こちらも作成します。

CloudWatch Events

2019-07-16_14h59_23.png

AWSの各種リソースに対しトリガを設定すれば、何かを実行してくれるよ

・今回は、
決まった時刻に、事前に作っておいたLambdaの関数を起動中のサーバに対して発動させる
というふうに使います。

・こちらを参考に
Amazon CloudWatch Eventsについて

 やってみよう

IAMロールの作成

まずはLambdaの実行に必要な権限設定(IAMロールの作成)から始めていきます。
AWSマネジメントコンソールから、「IAM」と検索して出てきたやつに飛びましょう!
2019-07-11_16h19_51.png

その中のロールという項目を開いてあげましょう。
2019-07-11_16h47_46.png

開いたページの中の、【ロールの作成】という項目をクリック。
次のページの「このロールを使用するサービスを選択」から【Lambda】を選択し、次のステップへ進みます。

2019-07-11_16h52_32.png

次に、ロールに付与するアクセス権限ポリシーを選択する画面に飛びます。
用意されている中から選ぶこともできるのですが、ここでは自分でポリシーを作成します!
【ポリシーの作成】をクリックします。
ポリシー作成画面で、【JSON】タブを開いたあと、以下のコードをコピペしましょう!

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:Start*",
        "ec2:Stop*"
      ],
      "Resource": "*"
    }
  ]
}

2019-07-11_17h01_44.png

「lambda_start_stop_ec2」という名前をつけて、ポリシーの作成を完了します。

2019-07-11_17h16_44.png

前の画面に戻り、作成したポリシーをロールにアタッチして次に進みます!
2019-07-16_10h15_17.png

次は「タグの追加」という画面に進みますが、こちらは特になにもせず次に進みます。

確認画面にてロール名を入力します。
ここも「lambda_start_stop_ec2」としてあげて、作成ボタンを押しましょう!
これでロールの完成です!

2019-07-16_10h21_54.png

Lambda関数の作成

次はいよいよ、インスタンスへ自動停止・自動起動の命令を送る関数を作っていきます!
まずは停止の方から!

Stop関数の作成

コンソールからLambdaを開き、【関数の作成】をクリックします。
最初のオプションではデフォルトの【一から作成】を選択します。
その後は以下のスクショに従って入力してください。

2019-07-16_10h46_14.png

①関数名:StopEC2Instances
②ランタイム:Python2.7
③実行ロール:既存のロールを使用する
④既存のロール:先の手順で作った「lambda_start_stop_ec2」を使用

入力が終わったら、【関数の作成】をクリックし、次に進みます。

作成した関数の設定画面に進むので、下の方にある「関数コード」の画面にインスタンスを停止させるコードを記述していきます。
こちらには初期状態で「Hello from Lambda!」を表示する関数が書かれていますが、こちらをすべて削除して、以下のコードをコピペします。

import boto3

# Enter the region your instances are in, e.g. 'us-east-1'
region = 'XX-XXXXX-X'

# Enter your instances here: ex. ['X-XXXXXXXX', 'X-XXXXXXXX']
instances = ['X-XXXXXXXX']
def lambda_handler(event, context):
    ec2 = boto3.client('ec2', region_name=region)
    ec2.stop_instances(InstanceIds=instances)
    print 'stopped your instances: ' + str(instances)

こちらがインスタンスを停止させるコードです。
このコード内のリージョンとインスタンスIDの部分を変更して、自分のインスタンスが対象になるように設定していきます。
2019-07-16_14h25_19.png

リージョンについては、AWS画面右上に
2019-07-16_11h08_17.png
このように表示されているリージョンを確認したあと、こちらのリンクからリージョンコードを確認し、書き換えてください!
例 オハイオ:'us-east-2'

次にインスタンスIDですが、関数の対象にしたいインスタンスのIDを、EC2のコンソールから確認しましょう!
2019-07-16_11h23_07.png
ダッシュボードから「インスタンス」を選択し、表示されたインスタンスIDをもとに、Lambdaのコードを書き換えてあげましょう!

タイムアウトまでの実行時間を変更する

デフォルトだと関数の実行時間が3秒になっていますが、実際はもっとかかるためこのままだと実行中にタイムアウトになってしまいます。
そのため、同じ画面の下の方にある【基本設定】の項目から、タイムアウトの時間を30秒に変更します。
2019-07-16_11h36_32.png

これらの設定が終わったら、右上の「保存」ボタンを押して完了です!
2019-07-16_11h29_37.png

これでインスタンスを停止させる関数ができました!

Start関数の作成

基本的にはStopの関数を作るときと同じです。
Lambdaのコンソールから「関数の作成」を押して再度進めましょう。
関数名を「StartEC2Instances」にし、同じように進めていきいます。
起動のコードはこちらになります。

import boto3

# Enter the region your instances are in, e.g. 'us-east-1'
region = 'XX-XXXXX-X'

# Enter your instances here: ex. ['X-XXXXXXXX', 'X-XXXXXXXX']
instances = ['X-XXXXXXXX']
def lambda_handler(event, context):
    ec2 = boto3.client('ec2', region_name=region)
    ec2.start_instances(InstanceIds=instances)
    print 'started your instances: ' + str(instances)

こちらも自分のリージョンとインスタンスIDを入力します。
その後、タイムアウトの設定もさきほど同様に変更し、保存ボタンを押して完成です。

これで自動停止・自動起動させるための関数ができました!

CloudWatch Eventsの設定

上の作業で作成した関数を、CloudWatch Eventsという機能を使って、決められた時刻に起動してもらうように設定していきます!

まずはインスタンス停止の関数(StopEC2Instances)からセットしていきましょう。

AWSのコンソールよりCloudWatchを開き、左側のメニューから「ルール」を選択。
出てきた画面より【ルールの作成】をクリックします。

2019-07-16_12h01_07.png

次の画面では以下のスクショに従って入力します。
2019-07-16_13h12_16.png

Cron式の設定

③のCron式でイベントを起動する時間を指定します!
一見むずかしそうに見えますが、全然そんなことないです!

0/5 * * * ? *

この式は左から、

・分 ・時間 ・日 ・月 ・曜日 ・年

を表しています。
※参考画像
2019-07-16_13h21_48.png

Amazonのガイドを参考に設定してみて下さい!

参考までに、式を2つ載せておきます。

#毎週金曜の20時
00 11 ? * FRI *

#毎週月曜の朝8時
0 23 ? * MON *

以下の注意点を読みつつ、好みの時間になるよういじってみて下さい!

・注意点その1 タイムゾーンの違い
上の式では、金曜の20時にとなっているにも関わらず、式の時間の項目(左から2つ目)は11時になっています。
これはAWSで使われているタイムゾーンがUTC(日本はJST)であることから生じるズレです。
以下のサイトで希望の時間を変換して使いましょう。
時差計算

・注意点その2 Cron式上のはてなマーク

cron 式の日フィールドと曜日フィールドを同時に指定することはできません。
一方のフィールドに値 (または *) を指定する場合、もう一方のフィールドで ? (疑問符) を使用する必要があります。

のようです。
つまり、

#毎週金曜の20時
00 11 * * FRI *

曜日フィールドに値がある(右から2つ目)のに、日フィールド(左から3つ目)が*になっているため、この式はアウトです。
なので、

00 11 ? * FRI *

このように日フィールドにハテナを入れてあげれば大丈夫です!

Cron式の設定が終わったら、ターゲットの追加で先程作ったLambda関数を指定して次に進みましょう!あと少しです!

2019-07-16_13h46_05.png

次の画面でルールの名前を入力し(ここではStopEC2Instances)、状態が有効になっていることを確かめて、右下の作成ボタンを押せば完成です!

同じ要領で、自動起動のルールも設定してあげましょう!

動作確認

こちらの関数が実際に動くかどうかを確かめます。
先程作ったイベントのルール内のCron式を、現在時刻の5分後などに設定し、EC2のコンソールからちゃんと停止するか試してみましょう!

EC2のインスタンスの画面を開いて、
2019-07-16_14h30_09.png

指定時刻を過ぎたら更新ボタンを押して、インスタンスの状態がrunning→stoppedになっていれば成功です!

動作状況は、CloudWatchコンソールのログ→ロググループ→ログストリームから確認できます!

自動起動の方も動作確認ができれば、あとは好みの時間に設定し直すだけで完成です!
おつかれさまでした!!

注意点

起動したインスタンスは、使わなければ停止しておきましょう。
私は起動しっぱにしてたら、いつのまにか無料期間超えたようで5ドルの請求が発生しましたw

・参考にした記事
LambdaとCloudWatch EventsでEC2の自動起動&自動停止をやってみた(Python版)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

新入社員とはじめるAWS Lambda

自己紹介

はじめまして。
4月にとあるSIerに新卒入社した、たからといいます。

もともと勉強していたのはWebの分野で、開発か新しめの技術に触れられる部署を希望していたのですが残念ながら叶わず!
しかし色々あってAWSを勉強させてもらってます!

興味はあったのですが、何から手を付けていいかわからなかったところ、勉強する機会がもらえて非常にありがたいです。
そこで自分が実際に触って動かした内容をまとめていこうと思います!

こんな人向け

・AWS興味あるけど触ったことないよ
大丈夫です!こちらの記事などを参考にサーバーを立てるとこまでやってみて下さい!
接続とかApacheのインストールはしなくても大丈夫です!

AWSはサーバー起動くらいしかやったことないよ

EC2以外もちょっと触ってみたいよ

っていうぐらいの層の人向けに書いてます!

やりたいこと

・EC2で立てたサーバーを、決めた時間に自動で停止したり起動させたい
・土日など、サーバー使わないよ!っていう日だけ自動で停止させて、月曜の朝に自動で起動させて少しでも節約させます。AWSは従量課金制なので。。

登場人物

AWS Lambda

2019-07-16_14h58_40.png

「らむだ」と読みます。

・他のAWSと連携したりして、サーバーを立てずに特定の関数(メソッド)だけ実行できます。

使用例:
・サーバーのログやエラーなどをSlackに通知させる
・S3(AWSのクラウドストレージサービス)に送られた画像ファイルを自動でリサイズする
といった風に、各サービス間を連携させる関数を作れます。

・今回はこいつを使って、決まった時刻にサーバを起動&停止させる関数を作ります。

IAMロール

2019-07-16_15h00_11.png

・各AWSサービスを利用するための権限設定ができます。

「あいあむ」と読みます。「I am」とかかってるんですかね!おぼえやすい!

・構築された環境を、初心者がワンクリックで崩壊させるのを防いでくれるような設定ができたりします。

・作成したIAMロールに、いろいろな権限を持たせる形で運用します。こちらの記事が理解しやすかったです!
AWS アカウント、IAM ユーザー、IAM グループ、IAM ロールの違い

Lambdaで作った関数を実行するのにもIAMロールが必要になるため、こちらも作成します。

CloudWatch Events

2019-07-16_14h59_23.png

AWSの各種リソースに対しトリガを設定すれば、何かを実行してくれるよ

・今回は、
決まった時刻に、事前に作っておいたLambdaの関数を起動中のサーバに対して発動させる
というふうに使います。

・こちらを参考に
Amazon CloudWatch Eventsについて

 やってみよう

IAMロールの作成

まずはLambdaの実行に必要な権限設定(IAMロールの作成)から始めていきます。
AWSマネジメントコンソールから、「IAM」と検索して出てきたやつに飛びましょう!
2019-07-11_16h19_51.png

その中のロールという項目を開いてあげましょう。
2019-07-11_16h47_46.png

開いたページの中の、【ロールの作成】という項目をクリック。
次のページの「このロールを使用するサービスを選択」から【Lambda】を選択し、次のステップへ進みます。

2019-07-11_16h52_32.png

次に、ロールに付与するアクセス権限ポリシーを選択する画面に飛びます。
用意されている中から選ぶこともできるのですが、ここでは自分でポリシーを作成します!
【ポリシーの作成】をクリックします。
ポリシー作成画面で、【JSON】タブを開いたあと、以下のコードをコピペしましょう!

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:Start*",
        "ec2:Stop*"
      ],
      "Resource": "*"
    }
  ]
}

2019-07-11_17h01_44.png

「lambda_start_stop_ec2」という名前をつけて、ポリシーの作成を完了します。

2019-07-11_17h16_44.png

前の画面に戻り、作成したポリシーをロールにアタッチして次に進みます!
2019-07-16_10h15_17.png

次は「タグの追加」という画面に進みますが、こちらは特になにもせず次に進みます。

確認画面にてロール名を入力します。
ここも「lambda_start_stop_ec2」としてあげて、作成ボタンを押しましょう!
これでロールの完成です!

2019-07-16_10h21_54.png

Lambda関数の作成

次はいよいよ、インスタンスへ自動停止・自動起動の命令を送る関数を作っていきます!
まずは停止の方から!

Stop関数の作成

コンソールからLambdaを開き、【関数の作成】をクリックします。
最初のオプションではデフォルトの【一から作成】を選択します。
その後は以下のスクショに従って入力してください。

2019-07-16_10h46_14.png

①関数名:StopEC2Instances
②ランタイム:Python2.7
③実行ロール:既存のロールを使用する
④既存のロール:先の手順で作った「lambda_start_stop_ec2」を使用

入力が終わったら、【関数の作成】をクリックし、次に進みます。

作成した関数の設定画面に進むので、下の方にある「関数コード」の画面にインスタンスを停止させるコードを記述していきます。
こちらには初期状態で「Hello from Lambda!」を表示する関数が書かれていますが、こちらをすべて削除して、以下のコードをコピペします。

import boto3

# Enter the region your instances are in, e.g. 'us-east-1'
region = 'XX-XXXXX-X'

# Enter your instances here: ex. ['X-XXXXXXXX', 'X-XXXXXXXX']
instances = ['X-XXXXXXXX']
def lambda_handler(event, context):
    ec2 = boto3.client('ec2', region_name=region)
    ec2.stop_instances(InstanceIds=instances)
    print 'stopped your instances: ' + str(instances)

こちらがインスタンスを停止させるコードです。
このコード内のリージョンとインスタンスIDの部分を変更して、自分のインスタンスが対象になるように設定していきます。
2019-07-16_14h25_19.png

リージョンについては、AWS画面右上に
2019-07-16_11h08_17.png
このように表示されているリージョンを確認したあと、こちらのリンクからリージョンコードを確認し、書き換えてください!
例 オハイオ:'us-east-2'

次にインスタンスIDですが、関数の対象にしたいインスタンスのIDを、EC2のコンソールから確認しましょう!
2019-07-16_11h23_07.png
ダッシュボードから「インスタンス」を選択し、表示されたインスタンスIDをもとに、Lambdaのコードを書き換えてあげましょう!

タイムアウトまでの実行時間を変更する

デフォルトだと関数の実行時間が3秒になっていますが、実際はもっとかかるためこのままだと実行中にタイムアウトになってしまいます。
そのため、同じ画面の下の方にある【基本設定】の項目から、タイムアウトの時間を30秒に変更します。
2019-07-16_11h36_32.png

これらの設定が終わったら、右上の「保存」ボタンを押して完了です!
2019-07-16_11h29_37.png

これでインスタンスを停止させる関数ができました!

Start関数の作成

基本的にはStopの関数を作るときと同じです。
Lambdaのコンソールから「関数の作成」を押して再度進めましょう。
関数名を「StartEC2Instances」にし、同じように進めていきいます。
起動のコードはこちらになります。

import boto3

# Enter the region your instances are in, e.g. 'us-east-1'
region = 'XX-XXXXX-X'

# Enter your instances here: ex. ['X-XXXXXXXX', 'X-XXXXXXXX']
instances = ['X-XXXXXXXX']
def lambda_handler(event, context):
    ec2 = boto3.client('ec2', region_name=region)
    ec2.start_instances(InstanceIds=instances)
    print 'started your instances: ' + str(instances)

こちらも自分のリージョンとインスタンスIDを入力します。
その後、タイムアウトの設定もさきほど同様に変更し、保存ボタンを押して完成です。

これで自動停止・自動起動させるための関数ができました!

CloudWatch Eventsの設定

上の作業で作成した関数を、CloudWatch Eventsという機能を使って、決められた時刻に起動してもらうように設定していきます!

まずはインスタンス停止の関数(StopEC2Instances)からセットしていきましょう。

AWSのコンソールよりCloudWatchを開き、左側のメニューから「ルール」を選択。
出てきた画面より【ルールの作成】をクリックします。

2019-07-16_12h01_07.png

次の画面では以下のスクショに従って入力します。
2019-07-16_13h12_16.png

Cron式の設定

③のCron式でイベントを起動する時間を指定します!
一見むずかしそうに見えますが、全然そんなことないです!

0/5 * * * ? *

この式は左から、

・分 ・時間 ・日 ・月 ・曜日 ・年

を表しています。
※参考画像
2019-07-16_13h21_48.png

Amazonのガイドを参考に設定してみて下さい!

参考までに、式を2つ載せておきます。

#毎週金曜の20時
00 11 ? * FRI *

#毎週月曜の朝8時
0 23 ? * MON *

以下の注意点を読みつつ、好みの時間になるよういじってみて下さい!

・注意点その1 タイムゾーンの違い
上の式では、金曜の20時にとなっているにも関わらず、式の時間の項目(左から2つ目)は11時になっています。
これはAWSで使われているタイムゾーンがUTC(日本はJST)であることから生じるズレです。
以下のサイトで希望の時間を変換して使いましょう。
時差計算

・注意点その2 Cron式上のはてなマーク

cron 式の日フィールドと曜日フィールドを同時に指定することはできません。
一方のフィールドに値 (または *) を指定する場合、もう一方のフィールドで ? (疑問符) を使用する必要があります。

のようです。
つまり、

#毎週金曜の20時
00 11 * * FRI *

曜日フィールドに値がある(右から2つ目)のに、日フィールド(左から3つ目)が*になっているため、この式はアウトです。
なので、

00 11 ? * FRI *

このように日フィールドにハテナを入れてあげれば大丈夫です!

Cron式の設定が終わったら、ターゲットの追加で先程作ったLambda関数を指定して次に進みましょう!あと少しです!

2019-07-16_13h46_05.png

次の画面でルールの名前を入力し(ここではStopEC2Instances)、状態が有効になっていることを確かめて、右下の作成ボタンを押せば完成です!

同じ要領で、自動起動のルールも設定してあげましょう!

動作確認

こちらの関数が実際に動くかどうかを確かめます。
先程作ったイベントのルール内のCron式を、現在時刻の5分後などに設定し、EC2のコンソールからちゃんと停止するか試してみましょう!

EC2のインスタンスの画面を開いて、
2019-07-16_14h30_09.png

指定時刻を過ぎたら更新ボタンを押して、インスタンスの状態がrunning→stoppedになっていれば成功です!

動作状況は、CloudWatchコンソールのログ→ロググループ→ログストリームから確認できます!

自動起動の方も動作確認ができれば、あとは好みの時間に設定し直すだけで完成です!
おつかれさまでした!!

注意点

起動したインスタンスは、使わなければ停止しておきましょう。
私は起動しっぱにしてたら、いつのまにか無料期間超えたようで5ドルの請求が発生しましたw

・参考にした記事
LambdaとCloudWatch EventsでEC2の自動起動&自動停止をやってみた(Python版)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EC2インスタンスへのログイン方法

EC2インスタンスへのログインの手順

ホームディレクトリに移動する。

$ cd ~

ホームディレクトリから隠しファイルである「.ssh」というディレクトリ(ファイル名)

$ ls -a

https://gyazo.com/a3b158acc0ade19fe9db319a24ba3b39

ホームディレクトリから.sshにcdコマンド(絶対パス?)で移動する。

$ cd ~/.ssh

.sshから、以下のコマンドを実行して、EC2インスタンスへのログインする。

$ ssh -i pemキー名 ec2-user@ 自身のIPアドレス

「pemキー名」は、AWSの鍵の名前を指す。

「自身のIPアドレス」は、インスタンス作成時に作成される数字

ログインが完了すると、以下のような画面になる。
https://gyazo.com/d8358a055227c0859543a3e47b016775

※隠しファイルのリストを見たい時は、-aで一覧表示できる。

$ ls -a

また、Finderにおいて、隠しファイルの一覧を表示させるには、

シフトキー + command + .

のコマンドを実行すると、以下のような挙動となる。
https://gyazo.com/045020868a0f15b3e5fab25f5482588e

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[AWS]VSCodeでSAMのHelloWorldを5分で行う

AWS Toolkit for Visual Studio Code の正式版がリリースされたということで、早速HelloWorldしてみました。

今回はPythonを使います。node.jsもほぼ同じでできます。

0. 環境準備

VSCode

肝心のVSCode以下からインストールします。
https://code.visualstudio.com/

Docker

DockerはLambdaローカル実行時に使用するので必須です。
インストールしてない方はここからインストールします。
https://hub.docker.com

Python

awscliをインストールする際に使います。
インストールされてない場合は、インストールしてください。

$ python --version
Python 3.7.0
$ pip --version
pip 19.1.1

AWS Cli

以下コマンドでawsとsamをインストールしましょう。

$ pip install awscli
$ pip aws-sam-cli

インストール済みの場合は、awscliのバージョンを上げておきましょう。

$ pip install -U aws-sam-cli

aws configureでaws のアクセスキーとシークレットキーを設定しましょう。

$ aws configure

AWS Toolkit for Visual Studio Code

VSCodeの拡張機能で「AWS Toolkit」と検索して、インストールします。

1. HelloWorldローカル実行

1-1. テンプレ作成

コマンドパレット(Macなら、Shift + ⌘ + P) を開き、
「aws create new Sam Application」を選択します。

以下の順に聞かれるので入力します。

  • 開発する言語(今回はPython3.7を選びました)
  • ディレクトリ(今回はtest)
  • プロジェクト名(今回はhello)

test/helloが作られていればOKです。

1-2. ローカル実行

hello_world/app.pyを開きます。

以下の上に 「Run Locally | Debug Locally | Configure」と表示されているので、
「Run Locally」をクリックしていきなり実行します。

def lambda_handler(event, context):
{"statusCode":200,"body":"{\"message\": \"hello world\"}"}
Local invoke of SAM Application has ended.

こんな感じで出力されればOKです(最初はコンテナが起動するので時間がかかります)。
これでローカルでLambdaが実行できました。

2. デプロイ

  1. デプロイ用のS3バケットを作成($ aws s3 mb s3://BUCKET_NAME)
  2. コマンドパレットを開いて、「aws Deploy SAM Application」を選択
  3. デプロイするテンプレートの選択。今回は「hello/template.yaml」を選択
  4. リージョンの選択。今回は「Asia Pacific (Tokyo)」を選択
  5. 1で作成したS3バケット名を指定
  6. cloudformationのstack名を入力(プロジェクト名をいれておけばまずOK)
Successfully deployed SAM Application to CloudFormation Stack: hello with profile: ****

上記出力されれば無事にデプロイされました。

VSCodeの左メニューのAWSアイコンを選択すると、
CloudFormationおよびLambdaの所に、デプロイしたhelloが表示されていると思います。

AWSコンソール「API GateWay」>「hello」>「ステージ」>「Prod」>「URL の呼び出し」
のURLに/helloをつけてブラウザ等でアクセスすると「hello_word」のメッセージが表示されます。

URLは以下の感じ。
https://*********.execute-api.ap-northeast-1.amazonaws.com/Prod/hello

これで、Lambdaのデプロイができました(APIが作れました)。

削除する際は、VSCodeからCloudFormationのhelloを選択して、「Delete CloudFormation Stack」をしてください。
これで関連するサービスがすべて消えます。

番外編

AWS Toolkit for Visual Studio Code がなかった頃はコマンドでやってましたので、コマンドでもやってみます。

1. HelloWorldローカル実行

0.環境準備 は済んでいるものとします。

1-1. テンプレ作成

$ cd test
$ sam init -r python3.7 -n hello

testディレクトリにhelloプロジェクトをPython3.7で作成します。

以下の通り、作成されます。

$ cd hello
$ tree
.
|-- README.md
|-- event.json
|-- hello_world
|   |-- __init__.py
|   |-- __pycache__
|   |   |-- __init__.cpython-37.pyc
|   |   `-- app.cpython-37.pyc
|   |-- app.py
|   `-- requirements.txt
|-- template.yaml
`-- tests
    `-- unit
        |-- __init__.py
        |-- __pycache__
        |   |-- __init__.cpython-37.pyc
        |   `-- test_handler.cpython-37.pyc
        `-- test_handler.py

1-2. ローカル実行

以下のコマンドで実行します。
hello worldが出力されればOK

$ cd hello
$ sam local invoke -e event.json
〜(){"statusCode": 200, "body": "{\"message\": \"hello world\"}"}

2. デプロイ

デプロイ用のS3バケットを作ります。作ってあればOKです

$ aws s3 mb s3://BUCKET_NAME

以下コマンドでパッケージ化したものをS3に設置

$ sam package --template-file template.yaml --output-template-file packaged.yaml --s3-bucket BUCKET_NAME
$ sam deploy --template-file packaged.yaml --stack-name hello --capabilities CAPABILITY_IAM

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - hello

AWSコンソールから,CloudFormation, Lambda, APIGateWay を確認してみてください。
作成されているはずです。

削除する際は、CloudFormationから削除すれば関連するサービスまとめて削除してくれます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[AWS]VSCodeでSAM(Lambda)のHelloWorldを5分で行う

AWS Toolkit for Visual Studio Code の正式版がリリースされたということで、早速HelloWorldしてみました。

今回はPythonを使います。node.jsもほぼ同じでできます。

0. 環境準備

VSCode

肝心のVSCode以下からインストールします。
https://code.visualstudio.com/

Docker

DockerはLambdaローカル実行時に使用するので必須です。
インストールしてない方はここからインストールします。
https://hub.docker.com

Python

awscliをインストールする際に使います。
インストールされてない場合は、インストールしてください。

$ python --version
Python 3.7.0
$ pip --version
pip 19.1.1

AWS Cli

以下コマンドでawsとsamをインストールしましょう。

$ pip install awscli
$ pip aws-sam-cli

インストール済みの場合は、awscliのバージョンを上げておきましょう。

$ pip install -U aws-sam-cli

aws configureでaws のアクセスキーとシークレットキーを設定しましょう。

$ aws configure

AWS Toolkit for Visual Studio Code

VSCodeの拡張機能で「AWS Toolkit」と検索して、インストールします。

1. HelloWorldローカル実行

1-1. テンプレ作成

コマンドパレット(Macなら、Shift + ⌘ + P) を開き、
「aws create new Sam Application」を選択します。

以下の順に聞かれるので入力します。

  • 開発する言語(今回はPython3.7を選びました)
  • ディレクトリ(今回はtest)
  • プロジェクト名(今回はhello)

test/helloが作られていればOKです。

1-2. ローカル実行

hello_world/app.pyを開きます。

以下の上に 「Run Locally | Debug Locally | Configure」と表示されているので、
「Run Locally」をクリックしていきなり実行します。

def lambda_handler(event, context):
{"statusCode":200,"body":"{\"message\": \"hello world\"}"}
Local invoke of SAM Application has ended.

こんな感じで出力されればOKです(最初はコンテナが起動するので時間がかかります)。
これでローカルでLambdaが実行できました。

2. デプロイ

  1. デプロイ用のS3バケットを作成($ aws s3 mb s3://BUCKET_NAME)
  2. コマンドパレットを開いて、「aws Deploy SAM Application」を選択
  3. デプロイするテンプレートの選択。今回は「hello/template.yaml」を選択
  4. リージョンの選択。今回は「Asia Pacific (Tokyo)」を選択
  5. 1で作成したS3バケット名を指定
  6. cloudformationのstack名を入力(プロジェクト名をいれておけばまずOK)
Successfully deployed SAM Application to CloudFormation Stack: hello with profile: ****

上記出力されれば無事にデプロイされました。

VSCodeの左メニューのAWSアイコンを選択すると、
CloudFormationおよびLambdaの所に、デプロイしたhelloが表示されていると思います。

AWSコンソール「API GateWay」>「hello」>「ステージ」>「Prod」>「URL の呼び出し」
のURLに/helloをつけてブラウザ等でアクセスすると「hello_word」のメッセージが表示されます。

URLは以下の感じ。
https://*********.execute-api.ap-northeast-1.amazonaws.com/Prod/hello

これで、Lambdaのデプロイができました(APIが作れました)。

削除する際は、VSCodeからCloudFormationのhelloを選択して、「Delete CloudFormation Stack」をしてください。
これで関連するサービスがすべて消えます。

番外編

AWS Toolkit for Visual Studio Code がなかった頃はコマンドでやってましたので、コマンドでもやってみます。

1. HelloWorldローカル実行

0.環境準備 は済んでいるものとします。

1-1. テンプレ作成

$ cd test
$ sam init -r python3.7 -n hello

testディレクトリにhelloプロジェクトをPython3.7で作成します。

以下の通り、作成されます。

$ cd hello
$ tree
.
|-- README.md
|-- event.json
|-- hello_world
|   |-- __init__.py
|   |-- __pycache__
|   |   |-- __init__.cpython-37.pyc
|   |   `-- app.cpython-37.pyc
|   |-- app.py
|   `-- requirements.txt
|-- template.yaml
`-- tests
    `-- unit
        |-- __init__.py
        |-- __pycache__
        |   |-- __init__.cpython-37.pyc
        |   `-- test_handler.cpython-37.pyc
        `-- test_handler.py

1-2. ローカル実行

以下のコマンドで実行します。
hello worldが出力されればOK

$ cd hello
$ sam local invoke -e event.json
〜(){"statusCode": 200, "body": "{\"message\": \"hello world\"}"}

2. デプロイ

デプロイ用のS3バケットを作ります。作ってあればOKです

$ aws s3 mb s3://BUCKET_NAME

以下コマンドでパッケージ化したものをS3に設置

$ sam package --template-file template.yaml --output-template-file packaged.yaml --s3-bucket BUCKET_NAME
$ sam deploy --template-file packaged.yaml --stack-name hello --capabilities CAPABILITY_IAM

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - hello

AWSコンソールから,CloudFormation, Lambda, APIGateWay を確認してみてください。
作成されているはずです。

削除する際は、CloudFormationから削除すれば関連するサービスまとめて削除してくれます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[AWS] EMR調査メモ

EMR

  • 公式
  • Amazon EMR は、業界をリードするクラウドネイティブなビッグデータプラットフォームです。大規模環境で大量のデータを迅速かつコスト効率よく処理できます

公式HPから引用

クラスター作成

  1. クラスター名を入力
  2. ログ記録するかチェック
    • 今回はログ記録しない
  3. 起動モードは「クラスター」を選択
  4. リソース選択
    • emr-5.24.1 を選択
  5. アプリケーション
    • Core Hadoop: Hadoop 2.8.5 with Ganglia 3.7.2, Hive 2.3.4, Hue 4.4.0, Mahout 0.13.0, Pig 0.17.0, and Tez 0.9.1
  6. インスタンスタイプ
    • m3.xlarge
  7. インスタンス数
    • 1
  8. EC2キーペア
  9. アクセス権限
    • デフォルト

EC2ログイン

  • 上記で指定したキーペアの権限を「400」に変更
  • EMR用のEC2インスタンスを確認しログインする
    • ex) ssh -i "xxxx.pem" ec2-user@xxxx.xxxx.compute.amazonaws.com

S3DistCp

ファイル集約

s3-dist-cp --src /data/incoming/hourly_table --dest s3://my-tables/processing/daily_table --targetSize=10 --groupBy=’.*/hourly_table/.*/(\d\d)/.*\.log’
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Amazon VPC エンドポイント の GatewayとInterface

1.GatewayとInterface

下記の通り、VPCエンドポイントの方式には、GatewayとInterfaceがある。Gatewayはs3とdynamodのみ。
image.png

Gateway
VPCのルートテーブルを書き換えてVPCエンドポイントのゲートウェイ経由でAWSのAPIエンドポイントへアクセスする。
ゲートウェイVPCエンドポイントではAWSのAPIへはパブリックIPへ向いており、アクセス制御はゲートウェイのアクセスポリシーで行います。

Interface
サービスのエンドポイントとENIをPrivateLinkと呼ばれるものでリンクされます。
DNSを使ってENIのプライベートIPに<サービス名>.<リージョン>.amazonaws.comのようなAレコードが設定されます。
インターフェイスVPCエンドポイントではENIに対してアクセスするため、アクセス制御はセキュリティグループで行います。

詳しくは下記のページが参考になりました。
タイプによる違いを整理:ゲートウェイとインターフェース

2.Gateway

ここでは、[com.amazonaws.ap-northeast-1.s3]を選択します。
image.png

エンドポイントにアクセスできるVPCとサブネットを指定します。
ここでは、わざとカスタムで特定のバケットに対し、GetとPutのみ許可するようなポリシーを設定しています。詳細は、Amazon S3 のエンドポイントポリシーの使用
を参考にしてください。

{
  "Statement": [
    {
      "Sid": "Access-to-specific-bucket-only",
      "Principal": "*",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Effect": "Allow",
      "Resource": ["arn:aws:s3:::naata-vpcep",
                   "arn:aws:s3:::naata-vpcep/*"]
    }
  ]
}

image.png

なお、ルートテーブルに以下のとおり、追加されていることがわかります。
image.png

検証してみます。

特定のバケットへのGetとPutのみ許可しているので、これはもちろんアクセスできません。

aws s3 ls --region ap-northeast-1
An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied

下記のとおり、特定のバケットへのputが成功していることがわかります。

aws s3 cp test.txt s3://naata-vpcep
upload: ./test.txt to s3://naata-vpcep/test.txt

3.Interface

ここでは、プライベートサブネットに配置してあるEC2インスタンスから、sshを利用せずセッションマネージャーを利用して接続したいと思います。

エンドポイントは同じように4つ作成すればよい。
com.amazonaws.ap-northeast-1.ssm
com.amazonaws.ap-northeast-1.ssmmessage
com.amazonaws.ap-northeast-1.ec2
com.amazonaws.ap-northeast-1.ec2messages
Systems Manager 用 VPC エンドポイントを作成する

「com.amazonaws.ap-northeast-1.ssm」を選択します。
image.png

VPCエンドポイントを設定するVPCを選択して、ENIを配置するサブネットを選択します。
[プライベート DNS 名を有効にする]で「このエンドポイントで有効にする」にチェックを入れます。
【注意】
「このエンドポイントで有効にする」でチェックを入れている場合、VPCの設定でDNS 解決DNS ホスト名を有効にしておく必要があります。
image.png
ENIに設定するセキュリティグループを選択します。※対象のEC2からHTTPS(443)を受け取れるセキュリティグループとするのが基本です。
image.png

作成されたら、DNS Namesが3つ作成されと思います。
<エンドポイントID>-XXXXXXXX.ssm.<リージョン>.vpce.amazonaws.com
<エンドポイントID>-XXXXXXXX-.ssm.ap-northeast-1.vpce.amazonaws.com
ssm.ap-northeast-1.amazonaws.com
image.png

セッションマネージャを確認し、接続できるか確認してみましょう。
image.png

コマンドを打てるコンソールまでは開いたが、何も反応しない。。。
image.png

そこで、こちらのページにある内容で解決!
セッションマネージャーのログの出力先として設定されている s3やCloudWatch Logsのロググループの設定を確認し、接続することができた。
image.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[AWS] AWSソリューションアーキテクトアソシエイト合格までにしたこと

AWSソリューションアーキテクトアソシエイト

先日受験し無事合格することができました
受験対策として自分が行ったことを記録して置こうと思います

AWSソリューションアーキテクトアソシエイトは長いので、「SAA」と略します

SAAとは

  • AWS認定の一つ
  • AWS のテクノロジーを使用して安全で堅牢なアプリケーションを構築およびデプロイするための知識を効果的に証明できる、とされている

対象者

  • 可用性、優れたコスト効率、耐障害性を備え、スケーラブルな AWS 上での分散システムの設計に関して、少なくとも 1 年の実務経験のある方が対象

詳しくは

合格までの事前知識とスケジュール

事前知識

  • AWSは「少し触ったことがある」程度
  • EC2、S3などの有名サービスは「知っている」程度
  • どのように組み合わせたらシステムが構築できるかについては全く無知
  • 初心者

スケジュール

  • 4月
    • 対策本を読む
  • 5月
    • Udemy講座をひたすら見る
  • 6月
    • Udemy講座をひたすら見る
    • Architecting on AWS の受講
    • 問題集を解く
  • 7月
    • 受験&合格

合格までにしたこと&合格貢献度

  1. 対策本
  2. Udemy講座
  3. Architecting on AWS の受講
  4. AWS公式模擬試験

1. 対策本

まず上記書籍を購入しAWSとは何か、AWSソリューションアーキテクトアソシエイトとは何かを勉強しました

この本で得られたことは

  • SAAでカバーすべきサービスが分かる
  • 構成図も載っているのでサービスをどのように組み合わせてシステム構成すればよいか分かる
  • AWSベストプラクティス「5つの柱」について章別に記載されているのでそれぞれについてしっかり学べる
  • 各章末に確認問題があるので知識確認になる
  • 模擬問題がDLでき本番試験にかなり似た問題を事前に解いて感覚を養える

まず手始めにAWSを知る、SAAを知るには丁度良いかと思います
ページ数も膨大、というほどではないので早い人だと数日で読み終えられると思います

2. Udemy講座

上記講座は、様々な合格記事を拝見している中でオススメされていたので自身でも購入
結果、この講座にて合格できたと言っても過言ではないくらいにお世話になった

本講座で得られたことは

  • ハンズオンによりAWSを実際に触りながら対象のサービスを理解できる
  • 細かく章立てされているので移動時間に必要な箇所だけを見られる
  • 噛み砕かれた説明を聞くことで理解がしやすい
  • 問題集が「3回分」ついていて かつ 内容がかなり本番に近い

この講座がなければ合格は無理だったなと振り返って思います
「問題集」がかなり役に立ちます
本番にかなり似た問題が出題されるので知識確認をするのに最適です
この問題でしっかりと点を取れるようになれば合格は近いと思います

3. Architecting on AWS の受講

縁あって上記コースを受講することができました
3日間のコースとなっています

本講座でえられたことは

  • 3日間集中してみっちりと学習することができる
  • AWSマスターのような方々から直接学ぶことができ得るものが大きい
  • 「AWSの考えた」を学ぶことができる

AWS公式だけあってとても内容の濃い講座でした
2日座学、1日ハンズオンでしたが、座学の濃さに頭破裂する寸前でしたw
この講座で最も学びがあったのは「AWS」がどのように考えて様々なサービスや機能を作っているか、を知ることができたことです
これをしっかり意識しているかどうかでかなり差が出ると感じます

4. AWS公式模擬問題

公式の模擬問題です
オンラインで受験可能で「25問」の問題を解くことができます
点数ではなく%で結果が通知されます

模擬問題で得られたことは

  • 試験のリハーサルになった
  • 自身の実力を知ることができた

問題は本番と比べるとかなり簡単でした
ですので模擬問題でしっかりと点が取れてないと合格はかなり厳しいと感じます

振り返り

自分がなぜ合格できたかを振り返ってみます

  • 良質な学習コンテンツを通して学べた
  • 問題集を繰り返し解いた

良質な学習コンテンツを通して学べた

Udemy講座は本当に役立ちました
この講座だけで本当に合格ラインまではいけると思います
(オススメし過ぎて回し者みたいですね、、、)

Architecting on AWS は「AWSの考え」を知れたとても良い講座でした
ただし非常に高額ですので無理に受講する必要はないかと思います
SAA合格に必須ではないでしょう

問題集を繰り返し解いた

対策本(1回分)、Udemy講座(3回分)、計4回分の問題を解きました
本番試験の問題と遜色ないレベルの問題で非常に有益でした
4回分全てを繰り返し解き合格点が取れるようにしました

あとがき

簡単ですが自分の合格に関するまとめです
問題を解くことで合格に近づきましたが、
それに加えて「AWSだからこの場合はこうする」「これは○○のパターンだ」といういった考え方でできたら合格はすぐだと思います
微力でもお役に立ったらと思います

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[豆知識?]突然死したEC2インスタンスは停止から起動で蘇生できる

概要

掲題の通りにEC2インスタンスが突然死し、ホスティングしているサービスがダウン、SSHログイン不可、各種メトリクス取得不可、AWSコンソールからのインスタンスの再起動でも改善されないという時に以下の手順を実行してみてください

この突然死は事前に過度な負荷があったわけでもなく、なにか作業しているわけでもなく、ほんとうに突然ぽっくりとお亡くなることを指します

結論

一旦「停止」してから「開始」することで復活します

なぜなのか

上記のケースはインスタンスのホスト障害による可能性があります。(最終的にはサポートに確認することをお勧めします)
一旦停止し、再度起動することで正常なホスト上でインスタンスが起動される仕組みのようです(サポート担当者から教えて頂きました)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS CloudFormationのLambda-BackedカスタムリソースでネストされたJSONを返しても参照できない

AWS CloudFormationn(CFn)のLambda-Backedカスタムリソースを利用していてレスポンスとしてネストされたJSONを返そうとしたらハマったので調べてみました。

ハマった内容

Lambda-Backedカスタムリソースで

import cfnresponse
def handler(event, context):
  data = {
    "hoge": "hoge",
    "foo": {
      "hoge": "foohoge"
    }
  }
  cfnresponse.send(event, context, cfnresponse.SUCCESS, data)

のようにCFnへレスポンスを返してCFnテンプレートで

Outputs:
  hoge:
    Value: !GetAtt CustomResource.hoge
  foo:
    Value: !GetAtt CustomResource.foo.hoge

と、カスタムリソースの値を参照すると!GetAtt CustomResource.foo.hoge でエラーになりました。
エラー内容はCustomResource attribute error: Vendor response doesn't contain foo.hoge key

解決策

Lambda-BackedカスタムリソースでJSONを返す場合はネストせずフラットなJSONを返しましょう。

以下検証内容となります。

検証内容

前提

  • AWSアカウントがある
  • AWS CLIが利用できる
  • AWS Lambda、CloudFormationの作成権限がある

エラーにならないケース

テンプレート

Lambda関数ではネストされたJSONを返しますが、!GetAtt ではネストされた値を参照しないパターンです。
これでスタック作成してもエラーになりません。

cfn-template.yaml
Resources:
  CustomResource:
    Type: Custom::CustomResource
    Properties:
      ServiceToken: !GetAtt CustomResourceFunction.Arn

  CustomResourceFunction:
    Type: AWS::Lambda::Function
    Properties:
      Handler: index.handler
      Role: !GetAtt FunctionExecutionRole.Arn
      Code:
        ZipFile: !Sub |
          import cfnresponse
          def handler(event, context):
            data = {
              "hoge": "hoge",
              "foo": {
                "hoge": "foohoge"
              }
            }
            cfnresponse.send(event, context, cfnresponse.SUCCESS, data)
      Runtime: python3.7

  FunctionExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
        - Effect: Allow
          Principal:
            Service:
            - lambda.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: "/"
      Policies:
      - PolicyName: root
        PolicyDocument:
          Version: '2012-10-17'
          Statement:
          - Effect: Allow
            Action:
              - logs:CreateLogGroup
              - logs:CreateLogStream
              - logs:PutLogEvents
            Resource: "arn:aws:logs:*:*:*"

Outputs:
  hoge:
    Value: !GetAtt CustomResource.hoge

スタック作成して確認する

> aws cloudformation create-stack \
  --stack-name cfn-response-test \
  --template-body file://cfn-template.yaml \
  --capabilities CAPABILITY_IAM

{
    "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a"
}


> aws cloudformation describe-stacks \
  --stack-name cfn-response-test

{
    "Stacks": [
        {
            "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "StackName": "cfn-response-test",
            "CreationTime": "2019-06-26T01:47:20.177Z",
            "RollbackConfiguration": {},
            "StackStatus": "CREATE_COMPLETE",
            "DisableRollback": false,
            "NotificationARNs": [],
            "Capabilities": [
                "CAPABILITY_IAM"
            ],
            "Outputs": [
                {
                    "OutputKey": "hoge",
                    "OutputValue": "hoge"
                }
            ],
            "Tags": [],
            "EnableTerminationProtection": false,
            "DriftInformation": {
                "StackDriftStatus": "NOT_CHECKED"
            }
        }
    ]
}

正常に作成できました。Lambda関数のログを確認しておきます。

> aws cloudformation list-stack-resources \
  --stack-name cfn-response-test

{
    "StackResourceSummaries": [
        {
            "LogicalResourceId": "CustomResource",
            "PhysicalResourceId": "2019/06/26/[$LATEST]f518c197bb8541f0b651a151bb201560",
            "ResourceType": "Custom::CustomResource",
            "LastUpdatedTimestamp": "2019-06-26T01:47:45.532Z",
            "ResourceStatus": "CREATE_COMPLETE",
            "DriftInformation": {
                "StackResourceDriftStatus": "NOT_CHECKED"
            }
        },
        {
            "LogicalResourceId": "CustomResourceFunction",
            "PhysicalResourceId": "cfn-response-test-CustomResourceFunction-HI0ITG58NF7G",
            "ResourceType": "AWS::Lambda::Function",
            "LastUpdatedTimestamp": "2019-06-26T01:47:39.855Z",
            "ResourceStatus": "CREATE_COMPLETE",
            "DriftInformation": {
                "StackResourceDriftStatus": "NOT_CHECKED"
            }
        },
        (略)
    ]
}


> aws logs get-log-events \
  --log-group-name /aws/lambda/cfn-response-test-CustomResourceFunction-HI0ITG58NF7G \
  --log-stream-name '2019/06/26/[$LATEST]f518c197bb8541f0b651a151bb201560' \
  --output=text \
  --query "events[*].message"

START RequestId: db73aff3-d14a-4ff1-92cc-6335d23279aa Version: $LATEST
        https://cloudformation-custom-resource-response-useast1.s3.amazonaws.com/(略)
        Response body:
        {"Status": "SUCCESS", "Reason": "See the details in CloudWatch Log Stream: 2019/06/26/[$LATEST]f518c197bb8541f0b651a151bb201560", "PhysicalResourceId": "2019/06/26/[$LATEST]f518c197bb8541f0b651a151bb201560", "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a", "RequestId": "c734ee9f-7963-4626-bf6e-40d7e24a99ab", "LogicalResourceId": "CustomResource", "NoEcho": false, "Data": {"hoge": "hoge", "foo": {"hoge": "foohoge"}}}
        Status code: OK
        END RequestId: db73aff3-d14a-4ff1-92cc-6335d23279aa
        REPORT RequestId: db73aff3-d14a-4ff1-92cc-6335d23279aa  Duration: 310.53 ms     Billed Duration: 400 ms         Memory Size: 128 MB   Max Memory Used: 24 MB

レスポンス内容のData でネストされたJSONを返していることが確認できます。

エラーにならないケース

Outputs の定義を変更して確認します。

テンプレート(抜粋)

cfn-template.yaml_抜粋
Outputs:
  hoge:
    Value: !GetAtt CustomResource.hoge
  foo:
    Value: !GetAtt CustomResource.foo.hoge

スタック更新して確認する

> aws cloudformation update-stack \
  --stack-name cfn-response-test \
  --template-body file://cfn-template.yaml \
  --capabilities CAPABILITY_IAM

{
    "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a"
}


> aws cloudformation describe-stacks \
  --stack-name cfn-response-test

{
    "Stacks": [
        {
            "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "StackName": "cfn-response-test",
            "CreationTime": "2019-06-26T01:47:20.177Z",
            "LastUpdatedTime": "2019-06-26T01:50:44.408Z",
            "RollbackConfiguration": {},
            "StackStatus": "UPDATE_ROLLBACK_COMPLETE",
            "DisableRollback": false,
            "NotificationARNs": [],
            "Capabilities": [
                "CAPABILITY_IAM"
            ],
            "Outputs": [
                {
                    "OutputKey": "hoge",
                    "OutputValue": "hoge"
                }
            ],
            "Tags": [],
            "EnableTerminationProtection": false,
            "DriftInformation": {
                "StackDriftStatus": "NOT_CHECKED"
            }
        }
    ]
}

UPDATE_ROLLBACK_COMPLETE となり更新に失敗しました。
イベントを取得してエラー内容を確認します。

> aws cloudformation describe-stack-events \
  --stack-name cfn-response-test

{
    "StackEvents": [
        {
            "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "EventId": "e01c4f90-97b4-11e9-bb14-12f81177eb92",
            "StackName": "cfn-response-test",
            "LogicalResourceId": "cfn-response-test",
            "PhysicalResourceId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "ResourceType": "AWS::CloudFormation::Stack",
            "Timestamp": "2019-06-26T01:51:12.126Z",
            "ResourceStatus": "UPDATE_ROLLBACK_COMPLETE"
        },
        {
            "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "EventId": "df9dd0c0-97b4-11e9-9cbb-0eaa79b17470",
            "StackName": "cfn-response-test",
            "LogicalResourceId": "cfn-response-test",
            "PhysicalResourceId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "ResourceType": "AWS::CloudFormation::Stack",
            "Timestamp": "2019-06-26T01:51:11.295Z",
            "ResourceStatus": "UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS"
        },
        {
            "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "EventId": "d1776100-97b4-11e9-a0b3-0a20b68b404c",
            "StackName": "cfn-response-test",
            "LogicalResourceId": "cfn-response-test",
            "PhysicalResourceId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "ResourceType": "AWS::CloudFormation::Stack",
            "Timestamp": "2019-06-26T01:50:47.544Z",
            "ResourceStatus": "UPDATE_ROLLBACK_IN_PROGRESS",
            "ResourceStatusReason": "CustomResource attribute error: Vendor response doesn't contain foo.hoge key in object arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a|CustomResource|c734ee9f-7963-4626-bf6e-40d7e24a99ab in S3 bucket cloudformation-custom-resource-storage-useast1"
        },
        (略)
    ]
}

CustomResource attribute error: Vendor response doesn't contain foo.hoge key とエラー内容が確認できます。

参照方法を変えてみる

!GetAtt CustomResource.foo.hoge としているのがダメなのかなと考えて参照方法を変更してみました。

テンプレート(抜粋)

cfn-template.yaml_抜粋
Outputs:
  hoge:
    Value: !GetAtt CustomResource.hoge
  foo:
    Value: !GetAtt CustomResource.foo['hoge']

スタック更新して確認する

> aws cloudformation update-stack \
  --stack-name cfn-response-test \
  --template-body file://cfn-template.yaml \
  --capabilities CAPABILITY_IAM

{
    "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a"
}


> aws cloudformation describe-stacks \
  --stack-name cfn-response-test

{
    "Stacks": [
        {
            "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "StackName": "cfn-response-test",
            "CreationTime": "2019-06-26T01:47:20.177Z",
            "LastUpdatedTime": "2019-06-26T01:54:45.226Z",
            "RollbackConfiguration": {},
            "StackStatus": "UPDATE_ROLLBACK_COMPLETE",
            "DisableRollback": false,
            "NotificationARNs": [],
            "Capabilities": [
                "CAPABILITY_IAM"
            ],
            "Outputs": [
                {
                    "OutputKey": "hoge",
                    "OutputValue": "hoge"
                }
            ],
            "Tags": [],
            "EnableTerminationProtection": false,
            "DriftInformation": {
                "StackDriftStatus": "NOT_CHECKED"
            }
        }
    ]
}


> aws cloudformation describe-stack-events \
  --stack-name cfn-response-test

{
    "StackEvents": [
        {
            "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "EventId": "6f1d0b80-97b5-11e9-b714-0a2e8057061e",
            "StackName": "cfn-response-test",
            "LogicalResourceId": "cfn-response-test",
            "PhysicalResourceId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "ResourceType": "AWS::CloudFormation::Stack",
            "Timestamp": "2019-06-26T01:55:12.038Z",
            "ResourceStatus": "UPDATE_ROLLBACK_COMPLETE"
        },
        {
            "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "EventId": "6eb6f6b0-97b5-11e9-aaf5-0a437bda7b86",
            "StackName": "cfn-response-test",
            "LogicalResourceId": "cfn-response-test",
            "PhysicalResourceId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "ResourceType": "AWS::CloudFormation::Stack",
            "Timestamp": "2019-06-26T01:55:11.375Z",
            "ResourceStatus": "UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS"
        },
        {
            "StackId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "EventId": "609a23e0-97b5-11e9-a31e-0e366af4fd90",
            "StackName": "cfn-response-test",
            "LogicalResourceId": "cfn-response-test",
            "PhysicalResourceId": "arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a",
            "ResourceType": "AWS::CloudFormation::Stack",
            "Timestamp": "2019-06-26T01:54:47.692Z",
            "ResourceStatus": "UPDATE_ROLLBACK_IN_PROGRESS",
            "ResourceStatusReason": "CustomResource attribute error: Vendor response doesn't contain foo['hoge'] key in object arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/cfn-response-test/55d8cd90-97b4-11e9-aa0c-128a65397f5a|CustomResource|c734ee9f-7963-4626-bf6e-40d7e24a99ab in S3 bucket cloudformation-custom-resource-storage-useast1"
        },
        (略)
    ]
}

CustomResource attribute error: Vendor response doesn't contain foo['hoge'] key とエラーになりました。

まとめ

Lambda-BackedカスタムリソースでネストされたJSONを返しても!GetAtt では参照できないことがわかりました。ドキュメントにはDataの型がType: JSON object と定義されているのですが制限があるみたいです。。。

カスタムリソースの応答オブジェクト - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/crpg-ref-responses.html

参考

カスタムリソースの応答オブジェクト - AWS CloudFormation
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/crpg-ref-responses.html

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AMI をアカウント跨ぎで(他リージョンへ)スケジュールコピーする Lambda 関数

以前、AMIを他リージョンへスケジュールコピーするLambda関数という記事を書きましたが、それをアカウントを跨いで実行するためのものです。

ポイント

  • コピー対象の AMI 全てにコピー先のアカウントに対するアクセス権を付与する
  • コピー元アカウントの KMS キーを利用できるようにコピー先で作成する Lambda 関数のロールに必要なポリシーを付与する
  • コピー先アカウントからはコピー元のタグは不可視なので、別項目(「説明」:description)をキーにしてコピー対象を絞り込む

なお、今回は、

  • AMI のアクセス権付与はコピー元アカウントで
  • AMI コピーはコピー先アカウントで

それぞれ実行するための Lambda 関数を作成します。

※前回同様、コピー元の AMI は KMS カスタマー管理キーで暗号化されているものとします(デフォルトキー=AWS マネージドキーは不可)。

作業内容

1. コピー元アカウントで KMS キーにキーユーザーを登録

AMI 暗号化のために使っている KMS カスタマー管理キーに対して、

  • 4. の Lambda 関数で利用するロール(キーユーザーとして)
    • 前回記事「1. ロール作成」と同じ要領で作成。面倒なら 4. の Lambda 関数作成時に合わせて作成して KMS カスタマー管理キーに追加する。↓の 2. も同様。
  • コピー先アカウント(アカウント ID)

を追加します。

2. コピー先アカウントで KMS カスタマー管理キーを作成してキーユーザーを登録

カスタマー管理キーを作成し、キーユーザーとして 5. の Lambda 関数で利用するロールを追加します。

3. コピー先アカウントでポリシーを登録

コピー元アカウントの KMS カスタマー管理キーを使えるように、コピー先アカウントに以下のポリシーを登録します。

ポリシー登録
{ 
    "Version": "2012-10-17", 
    "Statement": [ 
        { 
            "Sid": "AllowUseOfCMK", 
            "Effect": "Allow", 
            "Action": [ 
                "kms:Encrypt", 
                "kms:Decrypt", 
                "kms:ReEncrypt*", 
                "kms:GenerateDataKey*", 
                "kms:DescribeKey" 
            ], 
            "Resource": "arn:aws:kms:ap-northeast-1:【コピー元アカウントID】:key/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" 
        }, 
        { 
            "Sid": "AllowUseofCMKToCreateEncryptedResources", 
            "Effect": "Allow", 
            "Action": "kms:CreateGrant", 
            "Resource": "arn:aws:kms:ap-northeast-1:【コピー元アカウントID】:key/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", 
            "Condition": { 
                "Bool": { 
                    "kms:GrantIsForAWSResource": true 
                } 
            } 
        } 
    ] 
}

※「key/」の後ろにはコピー元 AMI の暗号化に使う KMS カスタマー管理キーの ID を入力します。

登録したら、2. の KMS カスタマー管理キーのキーユーザーとして登録した Lambda 関数のロールにこのポリシーを追加で付与します。

4. コピー元アカウントで AMI アクセス権付与のための Lambda 関数を作成

Python 3.7 で以下のコードを登録します。

AMIアクセス権付与
import boto3 
import os 

def lambda_handler(event, context): 
    region = os.environ["REGION"] 
    tagKey = os.environ["TAG_KEY"] 
    owner  = os.environ["OWNER"] 
    share  = os.environ["SHARE"] 

    # 変更対象のイメージを抽出 
    client = boto3.client('ec2', region) 
    images = client.describe_images( 
        Filters=[{'Name':'tag-key','Values':[tagKey]}], 
        Owners=[owner] 
    ) 

    # 変更対象イメージがあれば変更実行 
    for image in images['Images']: 
        modifyKey = image['ImageId'] 
        print("Modifying Image Attribute '{}'.".format(modifyKey)) 
        client.modify_image_attribute( 
            ImageId=modifyKey, 
            LaunchPermission={'Add':[{'UserId':share}]} 
        ) 
        for snapshot in image['BlockDeviceMappings']: 
            client.modify_snapshot_attribute( 
                CreateVolumePermission={'Add':[{'UserId':share}]}, 
                SnapshotId=snapshot['Ebs']['SnapshotId'] 
            ) 

環境変数等は以下のように入力します。
attr-change.png

なお、AMI の抽出対応を 5. と同様に「説明」(description)にしたい場合は 5. を参考にコードを書き替えてください。

テストしてみてうまく動作したら、必要に応じて CloudWatch イベントの cron 式で定時実行をセットします。

5. コピー先アカウントで AMI コピーを行う Lambda 関数を作成

Python 3.7 で以下のコードを登録します。

AMIコピー
import boto3 
import os 

def lambda_handler(event, context): 
    sourceRegion = os.environ["SOURCE_REGION"] 
    destRegion = os.environ["DEST_REGION"] 
    sourceDescription = os.environ["SOURCE_DESCRIPTION"] 
    destTagKey = os.environ["DEST_TAG_KEY"] 
    owner = os.environ["OWNER"] 
    encryptKey = os.environ["ENCRYPT_KEY"] 

    # コピー対象のイメージを抽出 
    sourceClient = boto3.client('ec2', sourceRegion) 
    sourceImages = sourceClient.describe_images( 
        Filters=[{'Name':'description','Values':[sourceDescription]}], 
        Owners=[owner] 
    ) 

    # 削除対象のイメージを抽出 
    destClient = boto3.client('ec2', destRegion) 
    deleteImages = destClient.describe_images( 
        Filters=[{'Name':'tag-key','Values':[destTagKey]}], 
        Owners=[owner] 
    ) 

    # コピー対象イメージがあればコピー実行 
    for sourceImage in sourceImages['Images']: 
        copyKey = sourceImage['ImageId'] 
        print("Copying Image '{}' to {}.".format(copyKey, destRegion)) 
        new_ami = destClient.copy_image( 
            DryRun=False, 
            SourceRegion=sourceRegion, 
            SourceImageId=copyKey, 
            Name=sourceImage['Name'], 
            Description='', 
            Encrypted=True, 
            KmsKeyId=encryptKey 
            ) 
        destClient.create_tags(Resources=[new_ami['ImageId']], Tags=[{'Key':destTagKey,'Value':''}]) 

    # 削除対象イメージがあれば削除実行 
    for deleteImage in deleteImages['Images']: 
        deleteKey = deleteImage['ImageId'] 
        print("Deleting Image '{}' from {}.".format(deleteKey, destRegion)) 
        try: 
            destClient.deregister_image(ImageId=deleteKey) 
            for snapshot in deleteImage['BlockDeviceMappings']: 
                destClient.delete_snapshot(SnapshotId=snapshot['Ebs']['SnapshotId'], DryRun=False) 
        except destClient.exceptions.NoSuchEntityException: 
            print("Image '{}' not found.".format(deleteKey)) 

環境変数等は以下のように入力します。
attr-copy.png

※コピー対象の AMI の絞り込みには以下の項目を使います。
attr-ami.png

テストしてみてうまく動作したら、必要に応じて CloudWatch イベントの cron 式で定時実行をセットします(4. の 10 ~ 15 分程度後の時間を指定)。

その他

以前、一度にコピーできる AMI の数は 25 個だった気がするのですが、最近実行してみたところ 50 個まで同時にコピーできるようになっていました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Terraform設計・運用のノウハウ

概要

Terraformを使い始めて一年ほど経ったので、設計や運用上のノウハウを公開していこうと思います。
基本的にAWSを使うことが多いので、AWS寄りの話になります。

設計編

利用可能なプロバイダを調べる

TerraformはAWSやGCPといったクラウドサービスをコード化できることで有名ですが、オフィシャルだけでも様々なプロバイダに対応しています。
私はAWSのほか、GitHubやDatadogをコード化して運用してます。

ネットワーク設計

サービスを構築する上で本番環境のほかに開発やステージング環境を作りますが、環境の分け方は大きく分けて次のいずれかになることが多いと思います。

  1. 1つのVPCに全ての環境を入れる
  2. 環境ごとにVPCを分ける
  3. 環境ごとにAWSアカウントを分ける

2のパターンで設計する場合、Terraformで構成を組む際はVPCをdevelopmentstagingproductionに分離し、更に各VPCで共通となるサービスを配置するためのmanagementを作成します。managementには踏み台であったり、CI/CDを管理するインスタンスを配置しています。
ネットワーク上はmanagementから各環境にVPCペアリングで接続できますが、環境間(例えばdevelopmentからstagingstagingからproduction)の接続はルートテーブル上で制限しています。

開発基盤の概要-Page-3 (2).png

Workspaceを使う

Terraformで環境ごとのリソースを管理する方法は大きく分けて2つあります。

  1. 環境ごとにディレクトリを分けて管理
  2. Workspaceを使う

TerraformにはWorkspaceと呼ばれる環境ごとにリソースを管理する仕組みがあります。
先に上げたネットワーク構成にWorkspaceを適用することで、VPC単位のリソース構成が管理しやすくなります。

$ terraform workspace list
  default
* development
  production
  staging

managementVPCはWorkspace管理下から除外しています。

ディレクトリ設計

Terraformでリソースを管理する場合、悩むことになるのがディレクトリ構成かと思います。最もシンプルな構成は以下のような構成ではないでしょうか。

terraform
  aws
    ec2
      main.tf
      variables.tf
      outputs.tf
      providers.tf
      backend.tf
      version.tf
    security_group
      main.tf
      variables.tf
      outputs.tf
      providers.tf
      backend.tf
      version.tf
    ...

サービスが1つであれば上記構成でも運用できそうですが、サービスがスケールするにつれ、サブドメインで動く別のシステムや、リージョンをまたいだ構成も生まれる可能性があります。

最近私が設計していて割と汎用的に使えると思ってる構成は以下のようなものです。

terraform
  providers
    aws
      global: AWS全般に関する設定
        general:
          global
            iam
            route53
            ...
          ap-northeast-1
            cognito
            cloudtrail
            ...
        management: Management VPC
          global
            iam
            waf
            ...
          ap-northeast-1
            vpc
            security_group
            ...
        workspace: 環境ごとの設定
          global
            iam
            waf
            ...
          ap-northeast-1
            vpc
            ecs
            ...
      {SERVICE NAME}: サービス名。例えばqiita
        general
          global
            route53
            ...
          workspace
            ap-northeast-1
              global
                route53
                cloudfront
                ...
    datadog
      ...
    github
      ...

利点としては、

  • Terraformの実行単位がAWSのサービス構成と同じ (誤ってリソースを操作した際の影響範囲が限定される)
  • AWS全般に関わる設定をbase、特定のサービスに依存する設定を{SERVICE_DOMAIN}下に配置することで、リソースの構成が視覚化される

などが挙げられます。
moduleはあえて使わず、

Terraform Best Practiceを読む

Terraform Best Practiceを読みましょう。中でもNaming conventionsは非常に有用です。いくつか気になるポイントをまとめてみました。

  • Resource and data source arguments
    • リソース名や変数、出力名の区切り文字には-の代わりに_を使う
    • リソース名にはリソースタイプを含めない (例えば、aws_route_tableのリソース名にroute_tableなどのタイプを含めない)
    • 単一リソースや妥当な名前がない場合、リソース名はthisとする
    • tagsdepends_onlifecycleはリソースの最後に記述する
  • Variables
    • default = []がある場合、type = "list"は省略する
    • default = {}がある場合、type = "map"は省略する
    • listmapの変数名は複数形を使用する
  • Outputs
    • 名前は{name}_{type}_{attribute}形式が望ましい

実装編

Docker版Terraformを使う

Docker版のTerraformを利用しましょう。

バージョンを指定する

利用するバージョンを明確化することで、無用なトラブルを回避することができます。

Terraform

terraform {
  required_version = "= 0.12.4"
}

Docker版Terraformを利用する場合、イメージのバージョンはlatestではなく、0.12.4のように番号で指定することをお勧めします。

プロバイダバージョン

provider "aws" {
  version = "= 2.19.0"
}

モジュールバージョン

module "foo" {
  source  = "terraform-aws-modules/security-group/aws"
  version = "3.0.1"
}

尚、sourceがGitHubの場合はversionが使えないので、代わりにrefでバージョンを指定する必要がある。

module "foo" {
  source = "github.com/azavea/terraform-aws-acm-certificate?ref=1.1.0"
}

tfstateファイルの管理方法

リソースの状態を管理するtfstateファイルはローカルやGitで管理するべきではありません。TerraformのBackend機能を使うことで、tfstateをDynamoDBやS3で管理することができます。
AWSを利用しているのであれば、S3がお手軽かと思います。

terraform {
  backend "s3" {
    bucket = "mybucket"
    key    = "path/to/my/key"
    region = "us-east-1"
  }
}

尚、S3を使う場合、対象バケットのバージョニングの有効化を強くお勧めします。tfstateを誤って削除したり、Terraformのバージョンアップでファイル構成が書き換わっても、簡単にステートファイルを復元することができます。

Terraform Module Registryを使う

Terraform Module Registryでは、汎用的に使えるモジュールが公開されてます。AWSで言えばEC2やSecurity Groupなど、いくつかの変数を渡すだけでリソースを作成してくれます。
Registryには大きく分けて、Terraformコミュニティが作ったものと、HashiCorpによって検証されたVerifiedモジュールがあります。
運用で使う場合は、検索時にVerifiedにチェックを付けることをお勧めします。

Screen_Shot_2019-07-15_at_23_21_12.png

フォーマットを整形する

fmtコマンドでディレクトリ下のファイルに対しまとめて整形してくれます。

# 0.11まで
$ terraform fmt

# 0.12以降
$ terraform fmt -recursive

環境ごとに異なる値を読み込む方法

変数名はWorkspace名を含めて定義します。

variable "rds_cluster" {
  default = {
    "default.engine_version"    = "5.7.12"
    "production.engine_version" = "5.7.22"
  }
}

リソース作成時にlookup関数を使うことで、現在有効なWorkspaceがproductionであれば5.7.22、それ以外であれば5.7.11の値が設定されます。

resource "aws_rds_cluster" "this" {
  engine_version = lookup(
    var.rds_cluster,
    "${terraform.workspace}.engine_version",
    var.rds_cluster["default.engine_version"],
  )
  ...

lifecycleでリソースを保護する

リソースにlifecycleブロックを指定することで、リソース作成・更新時の動作を変更することができます。lifecycleにはいくつかのタイプがありますが、prevent_destroyを指定することで、強制的なリソース再作成が発生したときにエラーを発生するようになります。

main.tf
lifecycle {
  prevent_destroy = true
}

destroyを実行した結果。

$ terraform destroy
...
Error: Instance cannot be destroyed

  on main.tf line 55:
  55: resource "aws_eip" "this" {

Resource aws_eip.this has lifecycle.prevent_destroy set, but the plan calls
for this resource to be destroyed. To avoid this error and continue with the
plan, either disable lifecycle.prevent_destroy or reduce the scope of the plan
using the -target flag

リソースを強制的に削除したい場合は、prevent_destroyfalseにするか、ブロックごと削除して、applyを実行します。

prevent_destroyはあくまでTerraform上で削除を保護するためのもので、AWSコンソールやCLIからは削除することが可能です。EC2やRDSなどいくつかのサービスには削除保護のオプションがあるので、別途有効化しておくことをお勧めします。

IAM PolicyのJSONはaws_iam_policy_documentで定義する

以下のリソースはIAMポリシーがヒアドキュメント形式で書かれており、可読性が低いです。

main.tf
resource "aws_iam_policy" "example" {
  # ... other configuration ...
  policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "*",
    "Resource": "*"
  }
}
POLICY
}

ヒアドキュメントはこのように置き換えることができます。HCLで書けるのでだいぶスッキリします。

main.tf
resource "aws_iam_policy" "example" {
  # ... other configuration ...
  policy = data.aws_iam_policy_document.example.json
}

data "aws_iam_policy_document" "example" {
  version = "2012-10-17"
  statement {
   effect = "Allow"
    actions = ["*"]
    resources = ["*"
  }
}

デバッグログを出力する

環境変数TF_LOGにログレベルを渡すことで、ログを出力することができます。ファイルに出力したい場合はTF_LOG_PATHも指定すると良いでしょう。

実行速度を改善する

Terraformのコマンドに--parallelismを渡すことで、APIの同時呼び出し数を変更することができます。

$ terraform plan --parallelism=20

デフォルト値は10です。パフォーマンスを見て数値を変えて見ると良さそうです。
尚、環境変数で指定する場合はTF_CLI_ARGS_planTF_CLI_ARGS_applyTF_CLI_ARGS_destroyを指定します。

拡張ライブラリ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AWS Certified Machine Learning – Specialtyを受けてきた

AWS Certified Machine Learning – Specialtyを受けてきました。
取得を考えている方の参考になれば幸いです。

試験概要

https://aws.amazon.com/jp/certification/certified-machine-learning-specialty/

  • 時間:170分
  • 問題数:65問1

事前準備

  1. courseraでStanfordが提供している機械学習のオンライントレーニングを受講する
  2. 模擬試験を受ける
  3. 本を読む
  4. サンプル問題を解く
  5. AWSの無料オンライントレーニングを受講する

特に、1.courseraのオンライントレーニングはオススメです。

結果

幸い合格でした。
(スコアはAWSの認定のサイトからダウンロードします。)

受験者スコア: 871

The AWS Certified Machine Learning - Specialty (MLS-C01) の試験結果は、100 から 1000 の間
の値で示されます。合格に必要な最低スコアは 750 です。

受験者のスペック

参考になるかわかりませんが。。。

  • AWS歴:5年
  • クラウド関連の保有資格
    • AWS: アソシエイト×3+プロフェッショナル×2+Big Data+Security+Network
    • GCP: クラウドアーキテクト+データエンジニア
  • 外観:メガネぼーず

難易度について

AWSの知識よりも機械学習の知識が問われる問題が多かったです。
また、他のAWSの試験に比べ、要求されるAWSの知識はかなり浅めに感じました。
そのため難易度は、こんな感じではないかと思います。

機械学習を仕事で利用されている方 → 簡単
AWSのエンジニアだが機械学習は初学者(=自分) → 難しい

感想

時間はかなり余りました。落ち着いてゆっくり解いても、十分試験時間内に収まると思います。


  1. 試験ガイドに記載が無いので、問題数は変わるかもしれません 

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む