AWS認定ソリューションアーキテクト-プロフェッショナルに合格するためにやったことまとめ

8月にアソシエイトに合格し、じゃあプロフェッショナルも取るかと思ったものの、日本語のソースだとプロフェッショナルに受かるためにどんなことをしたらいいかの情報が少なかったので、自分がやったことのまとめ。
※2017年10月時点での情報だと思ってください

よく問われるサービス

  • コンピューティング

    • EC2,Elastic Beanstalk
  • ストレージ
    • S3, EFS, Glacier, Storage Gateway
  • データベース
    • RDS, DynamoDB, ElastiCache, Amazon Redshift
  • ネットワーク&コンテンツ配信
    • VPC, CloudFront, Direct Connect, Route53
  • 管理者ツール
    • CloudWatch, CloudFormation, CloudTrail, OpsWorks
  • セキュリティ、アイデンティティ、コンプライアンス
    • IAM, Certificate Manager, Directory Service, CloudHSM
  • 分析
    • EMR, CloudSearch, Kinesis, Data Pipeline
  • モバイルサービス
    • Cognito
  • アプリケーションサービス
    • SWF, Elastic Transcoder
  • メッセージング
    • Simple Queue Service, Simple Notification Service, Simple Email Service

最低限読んでおく資料

まずはここを見て各サービスの概要を把握する。

概要をつかんだらこれを読んで細かいハマりポイントを理解する。

試験ガイドにあるようにホワイトペーパーも出題範囲。英語多め。各種ベストプラクティスくらいは読んでおく。

いわゆるCDP。典型的な設計パターンがまとめられている。

主要なサービスのドキュメントは一通り読む。

気を付けるポイント

  • 各種IDフェデレーション

AssumeRole, AssumeRoleWithWebIdentity, AssumeRoleWithSAML, GetFederationToken, GetSessionTokenがそれぞれどのようなケースで使うのが適当かを押さえる。

  • EC2のインスタンスタイプ
    「T2はバースト可能」「R4はメモリ最適化」といった用途を押さえる。回答の選択肢の中にさらっと出たりする。

  • VPN, DirectConnect, VPC peeringの特徴やユースケース
    オンプレミスとのハイブリッド環境でよく問われる。冗長化する(SPOFをなくす)方法も押さえておく。

  • EBSのIOPS
    最大値および最大値を超えるIOPSが必要な場合の設計方法を押さえる。

  • VPCにおいて予約されているIP

  • 各種サービスがどのレベルで提供されるのか(AZ、リージョン、グローバル)
    単一リージョンから複数リージョンへの移行や、グローバルレベルでの可用性・耐障害性に関する問題がよく出る。

  • CloudFormation, Elastic Beanstalk, OpsWorks
    それぞれの特徴や違い、作成(デプロイ)・変更・削除・中止方法を押さえる。

  • キャッシュエンジンの違い
    ElastiCacheにおけるmemcachedおよびRedisそれぞれの特徴を理解する。

  • 一括請求 (コンソリデーティッドビリング)
    請求を統合する方法および共有されるもの/されないものを押さえる。

有料学習サービス

  • Linux Academy

    • AWS SAプロ用のコースがあって、動画とハンズオンで学習できる。
    • 動画は英語のみで字幕もないが、活用資料集で概要を把握していれば十分理解できるレベル。
    • 登録後7日間は無料。その後は月額料金($29)が発生。無料期間だけで終わることもできる(ただし、ハンズオンは利用不可)。
    • 登録時にクレジットカードかpaypalの登録必須。
    • 独自の模擬試験もついていて、個人的にかなり良かった(無料期間だけで終わったけど…)

他にも海外のブログだとQwikLABSとかa Cloud Guruが評判が良かった(僕は使ってないです)

模擬試験について

公式の模擬試験は一度は受けた方がいい。問題形式や時間配分を体感できるのは重要。
アソシエイトに受かった時に模擬試験を無料で受験できるバウチャーがもらえるので、それを使うのが吉。
ただし、僕が受けた時は日本語がひどくて、日本語として何を言っているか分からない問題が多々あった(本番はまともだった)。もし模擬試験を受けてその日本語に恐怖を覚えても、本番ではそこまで怯える必要はないと思う。

本試験予約時の注意

  • 支払ページの請求先住所は英語で入力。全部入りきらなくても気にしない。

赤字で「英語で入力しろ」と注意書きもあるけど、英語で入力するとフォームの文字数制限で書ききれない。これじゃAWS困るだろと思って日本語で入力するとtemporary errorになる。このtemporary errorが日本語入力のせいだと気付かず、LiveChatで聞いたりして1週間以上待った…。
ちなみに英語で住所を入力して全部入りきらなくても郵便番号欄もあるので、中の人が補完してくれるとのこと。

  • 試験会場の住所が全部表示されない時は英語表示に切り替える

なぜか日本語表示だと郵便番号レベルの住所しか表示されず、とても不安な気持ちになるが、英語表示に切り替えるとちゃんと表示される。謎。

続きを読む

Lambda関数を作成する方法 ~S3へのファイルアップロードをトリガーにログ出力編~

はじめに

Lamba関数を作成しようといろいろ調べてみたが、
GUIのアップデートも早く、現状と同様の画面で作成している手順が見当たらなかったので、
自分の備忘録も含めて、Qiita記事に書き残しておくことにします。

今回実現したいこと

トリガー : S3バケットにファイルがアップロードされる
処理内容 : オブジェクトキーを含めたファイルパスをログに出力

設定方法

1. AWS Lambda設定画面を開き、関数の作成ボタンを押下。

image.png

2. 「一から作成」ボタンを押下

image.png

3. 「カスタムロールの作成」を選択

image.png

4. カスタムロールを作成

3.の操作後、新しいウィンドウで、カスタムロール作成画面が表示されるので、何も設定を変えず作成を行う。

image.png

5. Lamda関数の基本情報を入力

image.png

実行ロールについては、既存のロールを選択し、先ほど作成したロールを選択する。

6. Lamda関数が生成されました

image.png

トリガーが設定されていないので、設定を行います。

7. トリガーの設定

[トリガー]タブの「トリガーを追加」ボタンを押下

image.png

下記、詳細設定になります。

image.png

バケット欄に対象となるバケット名を指定し、「トリガーの有効化」設定を行います。

image.png

9. 実行ソースコードの修正

とりあえず動いていることを確認したいので、
アップロードされたら、バケット名とオブジェクトキーを出力するといった簡易なソースコードを用意します。

image.png

index.js

console.log('Loading function');

exports.handler = function(event, context) {
    var Bucket = event.Records[0].s3.bucket.name;
    var ObjKey = event.Records[0].s3.object.key;
    var FilePath = Bucket + '/' + ObjKey;
    console.log('BucketName : ' + Bucket);
    console.log('ObjKey : ' + ObjKey);
    console.log('FilePath : ' + FilePath);
};

「 Ctrl + S 」で保存し、指定のS3バケットにファイルをアップロードしてみてください。

10. ログ出力の確認

ログの確認は、 [モニタリング] タブの中にある、「CloudWatchのログを表示」というボタンを押下し、
遷移したページにて確認することができます。

image.png

一覧が表示される。

image.png

ログ出力中身確認。

image.png

無事、動作確認することができました。

とにかく動作検証なので、動くところまで、
必要な情報に関しては、今後随時更新していこうと思います。
最後までお読みいただき、ありがとうございました!

続きを読む

CloudWatchの料金が高い

同僚に「CloudWatchの料金高くね?」と指摘される
Slack料金通知画面
image.png

なんか高い!
Billingを確認。
image.png

どうやら詳細モニタリングを1分間にしていたからっぽい

EC2画面でとりあえず全て無効化する。5分間隔だと無料なんですね。
http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-cloudwatch-new.html

image.png

あとは見守るのみ

続きを読む

AWS Batchでキューの数を監視するCloudWatchカスタムメトリクスを作成してputしてみた

こんにちは、臼田です。 皆さん、Lambdaしてますか? AWS BatchはLambdaより長い時間を要する処理などに利用でき、マネージドでキューの管理やリトライ、AutoScaling等をやってくれて便利です。 初め […] 続きを読む

CloudWatchのログがS3にエクスポートされない

LambdaやBatchでCloudWatchに出力されたログのエクスポートを試みたところ一部のログがエクスポートされない状況にハマりました。

原因はログがエクスポートできる状態になるまでに最大12時間かかる事が原因でした。

参考

次の日にエクスポートしたら正常にエクスポートされました。

結構ハマった。

続きを読む

[EC2のスケジュール 停止] 会社から帰る時にスケジュール実行したlambdaからEC2(staging)をとめる

stgingで使っているEC2を停止するのを忘れてしまうということがよくありました。(主な犯人は僕です)手動で毎回止めるのもだるいし、人間は忘れっぽい生き物ですのでEC2のスケジュール停止をlambdaで実現しました。

設定の流れ

  1. EC2を停止するlambda関数を作成

    • EC2をlambdaから停止・起動するためのIAMのロールを作成
    • node.js で関数を実装
    • テスト
  2. CloudWatch Eventsでスケジュール設定

EC2を停止するlambda関数を作成

「一から作成」で新規関数を作成します。

https://gyazo.com/3a46795ca6ed2019674451fa7c40c265

lambdaからEC2の起動・停止をするにあたり、IAMのロールを作成します。

https://gyazo.com/890e460ddafeeb2aa003495293c8fe17

ポリシーを編集します。

https://gyazo.com/554b539050c1208cf8192ac161091941

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

EC2を停止するための関数コードを入力します。

const INSTANCE_ID = '*****';

var AWS = require('aws-sdk'); 
AWS.config.region = '******'; // 東京リージョン: ap-northeast-1

function ec2Stop(cb){
  var ec2 = new AWS.EC2();
  var params = {
    InstanceIds: [
      INSTANCE_ID
    ]
  };

  ec2.stopInstances(params, function(err, data) {
    if (!!err) {
      console.log(err, err.stack);
    } else {
      console.log(data);
      cb();
    }
  });
}

exports.handler = function(event, context) {
  console.log('start');
  ec2Stop(function() {
    context.done(null, 'Stoped Instance');
  });
};

この段階で「テスト」を実行して以下のようになれば成功です。

https://gyazo.com/88457ba6a983ca0785092d8ab60056c9

CloudWatch Eventsでスケジュール設定

トリガータブで新規のトリガーを追加します。

https://gyazo.com/dc62eb7532e618d4a67dd29558b73cbd

こんな感じで18時に自動で止まるようにします。

https://gyazo.com/ab5e6d877d9775a50b6af2cba6e68bb1

cronの設定はUTCで時間を設定する必要があるので cron(0 9 * * ? *) です。
平日だけなどのパターンは以下に記載されているので参考にしてください。

http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/tutorial-scheduled-events-schedule-expressions.html

まとめ

これでヒューマンエラー・めんどくさい作業なしでEC2が止まるようになりました。

参考にしたLambdaのScheduleイベントでEC2を自動起動&自動停止してみたのパクリになってしまいましたが、AWSのUIが変わっていたりしていたので、新しいUIのキャプチャでも貼っておくかということで手順をまとめてみました。

参考

LambdaのScheduleイベントでEC2を自動起動&自動停止してみた

続きを読む

logmonとALBのdrainingでリロード攻撃(F5アタック)へのパッシブ対策

以下の記事で紹介した小ネタの、具体的な利用例です。

1. 対策の内容

リロード攻撃(F5アタック)への対策としては、前段のApacheにmod_dosdetectorやmod_evasiveを入れる、WAFを導入する等があります。
このように、前段ですべて対応できれば良いのですが、

  • リロード攻撃を行っているのが正規ユーザである
  • リクエストによって(また、ユーザ毎に処理に必要なデータ量の多寡によって)レスポンスタイムにばらつきがある

というような場合、なかなか前段だけでの対処は難しいのではないかと思います。
そこで、Webアプリケーションサーバ(Tomcatなど)の処理が詰まってしまったときに、サービスの完全停止を避けるためにWebアプリケーションサーバの再起動を行うことがあると思いますが、

  • 「処理が詰まった」といっても、詰まり始めのうちは「特定の遅い処理」だけが「詰まる」のであり、それ以外のリクエストに対する処理は正常にレスポンスを返すことができている
  • 正常なレスポンスを返すことができるリクエストまで、再起動で中断するのは(なるべく)避けたい

ということで、Apacheのgraceful restartのような処理をしよう…というのが今回の内容です。

※きちんとgracefulな処理をするためには、Webアプリケーションサーバは複数台必要です。

2. ポリシー・IAM Roleの準備

まずは、先ほどの記事にある通り、以下の作業を行います。

  • ポリシーを設定する
  • 設定したポリシーをEC2用IAM Roleにアタッチする
  • そのIAM RoleをEC2(Webアプリケーションサーバ)にアタッチする

なお、今回のケースでは、「ec2:DescribeInstances」に対する権限は不要ですので、この部分はカットしても良いでしょう。

3. EC2上の設定

以下の記事を参考に、EC2(Webアプリケーションサーバ)にlogmonを導入します。

logmon.confには、以下の内容を設定します。

  • 1行目 : 監視対象のログファイル(Apacheのエラーログなら「:/var/log/httpd/error_log」など)
  • 2行目 : 監視対象のキーワード(正規表現/Tomcatのレスポンスが返らない場合を拾うのなら「[error] (70007)The timeout specified has expired」にマッチする内容)
  • 3行目 : 先の記事に示されているとおり

続いて、最初の記事で紹介したスクリプト「aws_utils.sh」を配置し(私の例では「/usr/local/sbin/」内)、「get_instance_id()」の部分だけ以下の内容に置き換えます。

aws_utils.sh(変更部分のみ)
#######################################
# 自身のインスタンス ID を取得する
# Returns:
#   INSTANCE ID
#######################################
get_my_instance_id() {
  instance_id=`/usr/bin/curl http://169.254.169.254/latest/meta-data/instance-id`
  if [ -z "$instance_id" ]; then
    echo 'host not found'
    exit 2
  fi
  echo ${instance_id}
}

※draining(登録解除の遅延)時間の長さに合わせて「SLEEP」の秒数も調整します。

それから、crontabから一定間隔で呼び出すスクリプト(私の例では「/usr/local/sbin/check_count.sh」)を配置します。

check_count.sh
#! /bin/sh

# スクリプトをインポートする
. /usr/local/sbin/aws_utils.sh

# トリガ判定
if [ `cat /tmp/logmon_count` -ge 20 ]; then

  # 閾値越え -> logmonサービス停止
  /sbin/service logmon stop

  # 二重トリガ起動防止(countを0に)
  echo 0 > /tmp/logmon_count

  # ALBでターゲットグループから外す
  ALB_TARGET_GROUP_ARN=('arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXXX:targetgroup/YYYY/zzzzzzzzzzzzzzzz' 'arn:aws:elasticloadbalancing:ap-northeast-1:XXXXXXXXXXXX:targetgroup/YYYY/zzzzzzzzzzzzzzzz')
  INSTANCE_ID=$(get_my_instance_id)

  for arn in ${ALB_TARGET_GROUP_ARN[@]}
  do
    alb_deregister ${arn} ${INSTANCE_ID}
  done

  # ALBでdraining完了待ち
  for arn in ${ALB_TARGET_GROUP_ARN[@]}
  do
    alb_waiter ${arn} ${INSTANCE_ID} 'unused' > /dev/null
  done

  # Webサービス停止
  /sbin/service tomcat8 stop

  /bin/sleep 10

  # サービス起動
  /sbin/service tomcat8 start

  /bin/sleep 10

  /sbin/service logmon start

  # ALBでターゲットグループに戻す
  for arn in ${ALB_TARGET_GROUP_ARN[@]}
  do
    alb_register ${arn} ${INSTANCE_ID}
  done

  # ターゲットグループに戻ったことを確認する
  for arn in ${ALB_TARGET_GROUP_ARN[@]}
  do
    alb_waiter ${arn} ${INSTANCE_ID} 'healthy' > /dev/null
  done

fi

# countを0に
echo 0 > /tmp/logmon_count

if文の「20」は閾値です。適切な値に調整してください。
この例ではWebアプリケーションサーバとしてTomcat8を使っていますが、適切なものに置き換えてください。Tomcatの場合は、draining前後でPrintClassHistogramの出力などもしておくと良いです。

また、この例ではEC2(Webアプリケーションサーバ)を複数のターゲットグループ(配列「ALB_TARGET_GROUP_ARN」)に登録しています。
それぞれのターゲットグループでdraining時間が違う場合は、時間が短いものを先に記述すると良いです(後述の通りログを記録する場合は特に)。
1つの場合は配列にせず、for文で回す必要もありません。

なお、この例ではログを /dev/null に捨てていますが、実際に使うときにはきちんとログファイルに記録しておいたほうが良いです(時刻などとあわせて)。

最後に、このスクリプトを、実行ユーザ(rootなど)のcrontabに登録します(私の例では1分間隔で実行⇒閾値は1分当たりのカウントに対して設定)。このとき、1行目に「SHELL=/bin/bash」を挿入しておきます。

crontab登録例
SHELL=/bin/bash

*/1 * * * * /bin/sh /usr/local/sbin/check_count.sh

設定できたら、カウントファイル(私の例では「/tmp/logmon_count」)に閾値以上の値を書き出して、正しくdraining→ターゲットから削除→Webアプリケーションサーバ再起動→ターゲットに登録が行われるか、確認します。

テスト
echo 20 > /tmp/logmon_count

4. 注意点

drainingすると再起動には時間が掛かるので、Webアプリケーションサーバは最低でも4台程度は必要です。

続きを読む

API Gatewayのログ出力を有効化する

前置き

Chaliceを使ってlambda関数の開発をしている為、簡単にCloudwatchのログが見れる。
が、lambdaで処理した後のレスポンスが取得出来ていない…

対応方法

IAMロールを新規作成・設定する

  1. IAMのダッシュボードへ移動する
  2. ロールを選択
  3. ロールの作成
  4. AWSサービス:API Gatewayを選択するスクリーンショット 2017-10-10 11.01.46.png

  5. AmazonAPIGatewayPushToCloudWatchLogs を選択する(これしか表示されていない、はず)

  6. ロール名、説明を入力する (ロール名はapiwateway-logs- とかにすればわかりやすそう)

  7. 作成したロールを選択して、ARNを記録するスクリーンショット_2017-10-10_11_06_21.png

API-GatewayにIAMロールを設定する

  1. API Gatewayのダッシュボードへ移動する
  2. 設定を選択
  3. CloudWatchログのロールARNに、上で記録したARNを記入して保存スクリーンショット_2017-10-10_11_06_49.png

ログを記録したいAPIを設定する

  1. APIを選択する
  2. ステージを選択する
  3. 設定タブにCloudWatch設定が表示されているので、チェックを入れて保存するスクリーンショット_2017-10-10_11_08_53.png

Cloudwatchのログを確認する

  1. API-Gateway-Execution-Logs_/ でログが出力されているスクリーンショット_2017-10-10_11_31_14.png

注意

Cloudwatchログの有効期間を設定して、ログ死しないように
ステージ毎に異なるロググループになってしまう(検索で対応は出来る)

結果

API Gatewayのログ出力は出来るようになったが、これだけではまだエラーレスポンスは取得できていない。
lambda関数の設定と、API Gatewayの設定も必要…

続きを読む

AWS Lambda と CloudWatch を使ってローカルで動かしていたcronの処理をサーバレスにする

AWS であれば自分にとって必要最小限のサービスで構成できそうなので乗り換えた次第です。 要件によっては GCP で構成しても良さそうかな・・・と思います。 続きを読む