AWS ECSでDockerコンテナ管理入門(基本的な使い方、Blue/Green Deployment、AutoScalingなどいろいろ試してみた)

はじめに

Dockerを本番環境で利用するに当たり、私レベルではDockerのクラスタを管理することはなかなか難しい訳です。凄くめんどくさそうだし。
ということでAWS ECS(EC2 Container Service)ですよ。

記事書くまでも無いかなと思ったんですけど意外と手順がWEBにない(気がしました)。ということで、今回は社内でハンズオンでもやろうかと思って細かく書いてみました。

こんな感じのシナリオをやってみたいと思います。

  1. Dockerのイメージを用意する
  2. ECSの使い方の基本
  3. コンテナのリリース
  4. Blue/Green Deployment
  5. AutoScaling/ScaleIn

前準備:Dockerのイメージを用意する

FROM uzresk/docker-oracle-jdk
MAINTAINER uzresk

ADD demo-1.0.jar /root/demo-1.0.jar
CMD java -jar /root/demo-1.0.jar
  • Docker build
[root@centos7 build_demo_ver1.0]# docker build -t uzresk/demo:ver1.0 /vagrant/build_demo_ver1.0
Sending build context to Docker daemon 33.11 MB
Step 1 : FROM uzresk/docker-oracle-jdk
 ---> df2f575c2a0d
Step 2 : MAINTAINER uzresk
 ---> Using cache
 ---> 1995a4e99748
Step 3 : ADD demo-1.0.jar /root/demo-1.0.jar
 ---> 705df0209779
Removing intermediate container cd9ef33d8812
Step 4 : CMD java -jar /root/demo-1.0.jar
 ---> Running in b7bd939a8b5a
 ---> add0783a851f
Removing intermediate container b7bd939a8b5a
Successfully built add0783a851f
  • 起動します

    • アプリケーションは8080で起動しているのでポートフォワードしておきます。
[root@centos7 build_demo_ver1.0]# docker run -itd -p 80:8080 --name demo uzresk/demo:ver1.0
92bda2419bf7285d78f12be5877ae3242b5b13ac14409b3c47d38e2d74a06464
  • ブラウザでこんな画面がでれば成功です。

image

  • Dockerhubにコミットしてpushしておきます。
[root@centos7 build_demo_ver1.0]# docker commit -m "update ver1.0" demo uzresk/demo:ver1.0
[root@centos7 build_demo_ver1.0]# docker push uzresk/demo:ver1.0

ECSの使い方の基本

AWS ECSとはなんなのか?

  • 今回は利用手順について書こうと思うので割愛しますが、AWS Black Belt ECSを読むのがよろしいかと思います。

構成する順番を抑えよう

  • こんな感じの順番で構成していきます。大事なので押さえておきましょう。
  1. クラスタの作成

    • クラスタを動かすためのEC2インスタンスの設定を行います。具体的にはインスタンスタイプ、インスタンス数、VPC、サブネットの設定になります。
  2. タスク定義

    • クラスタ上で動かすコンテナの情報を登録します。コンテナイメージのURLやCPU、メモリのハード/ソフト制限、アプリケーションで利用する環境変数の定義などを行います。
  3. ロードバランサの作成

    • クラスタの上位に位置するロードバランサの設定を行います。スケールアウトやスケールインしてもロードバランサはサービスを見つけ出し配下に組み込むことができます。
  4. サービスの作成

    • クラスタとサービスを結びつけるのがサービスの役割です。タスクの最少数やAutoScalingの設定を行ったりできます。
    • 1つのクラスタに複数サービスを登録することももちろん可能です。

それではさっそくクラスタの作成からやってみましょう。

クラスタの作成

image

image

  • 正常に作成されると「クラスターの表示」ボタンが押せるようになります。

image

タスク定義

  • 次はタスクの定義です。タスクでは

image

  • タスク定義名を入力し、「コンテナの追加」をクリックします。

image

image

  • 作成を押せばタスク定義の作成が完了します。

ELBの作成

  • ELBは以下の設定で作っておきましょう

    • ELB名:app-demo-lb
    • 種類:アプリケーションロードバランサ
    • 2つのAZそれぞれのSubnetを指定
    • セキュリティグループで80/HTTPを通すように設定
  • ターゲットグループは以下のようにクラスタで設定したインスタンスIDをそれぞれ登録してください。

image

サービスの作成

  • クラスターのTOPからdemo-clusterを選択し、サービスタブで「作成」

image

  • タスク定義とクラスタ名は自動で埋まりますので、サービス名とタスクの数を設定します。
  • 今回はAZにそれぞれコンテナを作りたいので2としました。

image

  • 画面の下の方にあるELBの追加を選択します。

image

  • ELB名は作成したもの、リスナーポートは80、ターゲットグループ名は作成したものを選択します。

image

image

  • 「作成」を押して、サービスの画面をみるとPENDINGになっています。

image

  • 少し経つとRUNNINGになっている事が確認できると思います。

image

  • ELBのエンドポイント/app/をブラウザで叩くと画面が表示されるはずです。

image

コンテナを落としてみるとどうなるのか

  • タスクの一覧から、タスクを一つ消してみましょう。

image

  • 数十秒後に見てみると別のタスクIDのインスタンスが表示されているはずです。

image

  • コンテナが起動する数十秒間の間はアプリケーションロードバランサが生きているタスクの方にうまくルーティングしてくれるのかな?と思ったら「502BadGateway」というエラーが画面に返ってきました。
  • ここはALBのヘルスチェックの閾値を短くすることである程度は短くできそうです。
  • ここをさらに短くするには、コンテナ自体を軽くすることと、すぐに起動できるアプリケーションを利用するしかなさそうですね。

コンテナのリリース

  • 新しいコンテナをリリースするには、タスク定義に新しいリビジョンを登録し、サービスを更新することで実現可能です。さっそくやってみましょう。

image

  • コンテナのバージョンを2.0にして、新しいリビジョンを登録します。

image

  • 追加されたリビジョンを選択し、アクション→サービスの更新を押します。

image

  • タスク定義に新しいリビジョンが指定されていることを確認して、「サービスの更新」

image

  • サービスの「デプロイ」タブを覗くと、今はVer1.0が2つ動いていることが確認できます。

image

  • コンテナを一つ落としてみましょう

image

image

  • 実行中の数がそれぞれ1になり、タスクの一覧からもそれぞれが動いていることがわかりますね。
    image

image


Blue/Green Deployment

  • Blue/GreenDeploymentでは新しいリビジョンのアプリ用に、新しいインスタンスを構築して入れ替える必要があります。
  • この為のパラメータがサービスのデプロイメントオプションにある最大率(maximumPercent)です。2台の時にこの値を200%にしておくと、4台まで同時に動かしておくことができることを意味します。
  • 4台のインスタンス上で動かすにはECSのインスタンス台数を事前に追加しておくか、AutoScalingさせておく必要があります。もしECSインスタンスが2台の状態で4つのコンテナを動かそうとすると以下のようなメッセージがでてしまいます。(ポートかぶってるから上がらないよ。ってことですね)

  • さっそくやってみます

service demo-service was unable to place a task because no container instance met all of its requirements. The closest matching container-instance xxxxxxxxxxxxxxxxxxxx is already using a port required by your task. For more information, see the Troubleshooting section.

image

image

  • この状態でサービスの更新画面でタスク定義を新しいリビジョンに指定して「サービスの更新」を押してみます。
  • おお。4台分のコンテナが起動しましたね。

image

  • ちょっと経つと(3分ほど?)、古いタスクから削除されていきます・・・・

image

  • 最期は新しいタスク定義しか残らなくなりました。自動ですよ。自動。便利ですねー。

image


AutoScaling/ScaleIn

  • 次はオートスケールとスケールインを試してみます。
  • 通常のオートスケールではインスタンスだけでしたが、インスタンス上で動くコンテナもスケールする必要があります。
  • 今回は2つのインスタンスで2つのコンテナで動いていたものを、負荷をかけることにより4つのインスタンス上に4つのコンテナにスケールアウトさせて、スケールインさせたいと思います。

サービスのAutoScaling設定

  • タスクの最大数を4にして、スケーリングポリシーの追加を押します。

image

  • スケールアウトポリシーの設定を行います。
  • CPU使用率の1分間の平均が20%超えた場合2タスクスケールアウトする設定にしました。

image

  • スケールインポリシーの設定を行います。

image

  • ポリシーが追加できたら「保存」を押しましょう

image

  • ポリシーが追加されていることを確認して、「サービスの更新」を押します。

image

  • これでサービスの設定はおしまいです。

ClusterのAutoScaling/ScaleInの設定

  • ECSインスタンスのオートスケールのポリシーは、EC2インスタンスのAutoScalingGroupの設定で行います。
  • 最大数を4にします。

image

  • Scaleout/ScaleInのポリシーを設定します。
  • サービスの設定と同じく、クラスタのCPU使用率が20%以上だと2台スケールアウトするように設定しました。

image

うごかしてみる

  • ECSインスタンス上でCPU使用率を強引に(openssl speed -multi 1)あげてみたのですがうまく動きませんでした。
  • ありがちですけどabで負荷をかけてみます。
  • abをインストール
sudo yum install -y httpd24-tools
  • 負荷をかける
ab -n 100000 -c 100 http://localhost/app/loginForm
  • CloudWatch Alerm(CPUが20%以上)があがる

image

  • サービスの必要数が4に変更される

image

  • インスタンスがオートスケールする

image

  • タスクが起動する

image

  • 負荷を解除する

  • CloudWatch Alerm(CPUが20%より小さい)があがる

image

  • 必要数が2に変更される

image

  • コンテナとインスタンスが2ずつに変わる

  • ここまでやって思ったんですが、インスタンス→コンテナの順に起動されたんですからコンテナ→インスタンスの順に落としていった方がよさそうですね。それはスケーリングポリシーのクールダウン時間で調整ができそうです。

ECSインスタンスの起動を待つのか?

  • ECSのインスタンスの起動を行った後にコンテナが起動されるので結局時間が掛かってしまいます。負荷の時間が予測されるのであればECSインスタンスを事前に起動しておいた方がECSのスケールアウトが高速にできそうです。
  • Dockerのメリットの一つである起動の高速化のメリットを享受するにはこのスケジューリングがキーになりそうですね。

どのインスタンスがスケールインするのか?


さいごに

ここまでコンテナ管理のハードルが下がると、今後はアプリケーションをコンテナにして配布するのが普通になってくると思います。
そうなるときのためにDockerについてしっかりと理解し、良い設計を心がけたいものですね

続きを読む

AWSでLinuxしか触ったことない人が、AWSでWindowsServerを利用するときに知っておかないといけないことまとめ

はじめに

  • AWSでLinuxばかりやってたんですがWindowsServerを触らないといけない機会が凄く増えててビビってます。
  • WindowsServer利用するときも、まぁ大体Linuxと一緒なんでしょ!?と思ってたら火傷しますのでしっかりと抑えておきましょう。
  • 他にもWindowsだと気をつけないといけない!なんてことがあればご指摘ください。

ライセンスはどうなってるのか?押さえておこう。

  • WindowsServerのライセンス

    • EC2の費用に含まれている。
    • OSにCALの料金が含まれているのでCALの購入は不要
  • WindowsServerのライセンス持ち込みについて
  • 以下の既存のマイクロソフトライセンスはAWS上に持ち込み可能。
    • 1サーバ1ライセンス、1プロセッサライセンス4コアまでの1インスタンスに対応
    • Exchange Server
    • SharePoint Server
    • SQLServer Enterpriseなど
  • Officeのライセンスについて
    • ハードウェア占有インスタンス、占有ホストで利用可能
  • その他ライセンスについて不明な点があればAWS と Microsoft に関するよくある質問 – ライセンシングを読んでおく。

サポート&トラブル

どのイメージを利用すればよいのか?

  • EC2の画面から「パブリックイメージ」「所有者:Amazonイメージ」「search:Windows_Server-2012-R2_RTM-」で検索するとたくさん出てくる。
  • 「search:Windows_Server-2012-R2_RTM-Japanese」で検索するとLocaleがJapaneseで設定済のものもあるのでこれを選んでおくと楽ですね。

EC2 Management Console 2016-10-07 14-33-05.png

  • 最新のパッチが当たったAMIを公開してくれており、10月5日現在だと6月以前のAMIは無くなっていました。どうしても元のAMIをとっておきたい場合はプライベートイメージとして保管しておく必要がありそう。(が、、、そういうケースはあるんだろうか)

AWS は、Microsoft の火曜パッチ(毎月第 2 火曜日)の 5 営業日以内に、更新されパッチが全面的に適用された Windows AMI を提供します。

  • 新しいAMIがリリースされた時や以前のAMIが非公開になった時に通知をAmazonSNSで受けることができるようです。Subscriptionの設定で以下のARNを設定すればよいようです。
arn:aws:sns:us-east-1:801119661308:ec2-windows-ami-update
arn:aws:sns:us-east-1:801119661308:ec2-windows-ami-private

インストールメディアは使えるのか?

  • 使える。
  • マネジメントコンソールでスナップショットを開いて以下の条件で検索
    • パブリックスナップショットを選択
    • 所有者:Amazonイメージ
    • 説明:Windows 2012 R2
  • あとはボリュームの作成してWindowsServerにAttachすれば利用できる

どうやってWindowsServerに接続するのか?

  • RDPで接続する。パスワードはManagementConsoleからパスワードの取得を行うことで取得できる。
  • インスタンス起動後すぐに取得できるわけではなく、「あとN分後に取得できます。」のメッセージが出てくる。
  • これは後述するEC2Configがパスワードの初期化を行っているから。

拡張ネットワーキングは有効にしておこう

インスタンスの自動復旧設定をしておこう

  • Windowsに限った話ではないが、AutoRecoveryは設定しておく。やっといて損しない。
  • AutoRecoveryはシステムステータスチェックが失敗した場合(ネットワークとか電源とかホスト側の問題でこちらではどうしようもない問題)に自動で復旧してくれる機能で無料で利用できる。
  • 利用条件
    • インスタンスタイプはC3、C4、M3、M4、R3、T2、および X1
    • VPC内で動作しEBS-Backedとなっていること
    • 占有インスタンスではないこと
  • 参考

AutoHealingの設定

  • これもWindowsに限った話ではないが1台構成でもAutoHealingの設定をしておくことを検討しておく。
  • AutoHealingとはAutoScalingGroupの起動数をmin:N,max:Nにしておくことで常にN台起動する状態を作ることを言います。
  • 詳しくは別記事にしますが簡単に触れておく。
  • AutoScalingGroupを利用する場合
    • トリガーはStateがRunningじゃなくなったとき。
    • PrivateIPが変わってしまうので上位にELBを挟むなどの考慮が必要。
    • CloudWatch→SNS→Lambda→AutoScalingGroupをUnHealthyにすることで細かい障害の検知などが可能になる。
  • OptsWorksを利用する場合
    • トリガーはOptsWorksAgentがOptsWorksに通信できなくなったとき。
    • PrivateIPを変更することなくAutoHealingが動かせるが、AutoScalingGroupのような細かい制御は無理

EC2Configの役割について知っておく

  • EC2ConfigはWindows版Cloud-initみたいなものです。EC2Configがやってくれる役割については認識しておこう。
  • AWSが提供するWindowsServerイメージを利用すると既にインストール済になっています。
    C:\Program Files\Amazon\Ec2ConfigService¥Ec2ConfigServiceSettings.exe
  • サービスも自動で起動しているので特に何かしておく必要はありません。
  • こんなことをやってくれます。
* 初回起動時のタスクには以下のものがあります。
    * 管理者アカウントに、ランダムに生成した暗号化パスワードを設定する
    * リモートデスクトップに使用されるホスト証明書を生成しインストールする
    * オペレーティングシステムパーティションを動的に拡張して、未使用の領域が含まれるようにします。
    * 指定されたユーザーデータ(および、インストールされていれば Cloud-Init)を実行します。
* EC2Config は、インスタンスが起動するたびに次のタスクを実行します。
    * 16 進数表記のプライベート IP アドレスと一致するようにコンピュータのホスト名を変更する(このタスクはデフォルトでは無効になっているので、このタスクを有効にしてインスタンスの起動時に実行する必要があります)。
    * key management server (KMS)を構成し、Windows アクティベーションのステータスを確認して、必要に応じて Windows のアクティベーションを行う。
    * すべての Amazon EBS ボリュームおよびインスタンスストアボリュームをマウントし、ボリューム名をドライブ文字にマップします。
    * イベントログエントリをコンソールに出力し、トラブルシューティングに役立てる(このタスクはデフォルトでは無効になっているので、このタスクを有効にしてインスタンスの起動時に実行する必要があります)。
    * コンソールに Windows の準備が完了した旨の通知を出力する
    * 複数の NIC がアタッチされているとき、プライマリネットワークアダプタにカスタムルートを追加して、IP アドレス 169.254.169.250、169.254.169.251、および 169.254.169.254 を有効にする。これらのアドレスは Windows ライセンス認証が使用し、またユーザーがインスタンスのメタデータにアクセスする際にも使用します。
* EC2Config は、ユーザーがログインするたびに以下のタスクを実行します。
    * デスクトップ背景に壁紙情報を表示する
  • 他の用途については以降で説明します。

AMIの作成方法は2パターンあることを知っておく

  1. マネージメントコンソールやCLIからAMIの作成を行う
  2. EC2ConfigからAMIを作成する
  • 所謂システムバックアップを取得する場合は1を利用すれば良い。
  • EC2ConfigからAMIを作成する理由は、展開用のイメージを作るときです。実行するとセキュリティ識別子(SID)、コンピュータ名、イベントログなど固有の情報が削除され、インスタンスが停止します。停止した状態でコンソールやCLIからイメージを作成すればインスタンス固有の情報が排除されたAMIの作成ができます。
  • 作成の方法についてはSysprep を使って標準の Amazon マシンイメージを作成します。を参考にしてください。

  • 参考

AWS Diagnostics for Microsoft Windows Serverは入れとけ

  • このツールを使うとWindowsServer上から様々な情報を収集し、AWSテクニカルサポートに問い合わせるときに情報を集めるのが非常に楽になるということと、既知の問題に引っかかっていないかを検査してくれるらしいです。素晴らしい。
  • いざサポートに問い合わせる必要が出た時にも慌てないようにダウンロードしておいておき、動くことも確認しておくこと!
  • 集められる情報
IP アドレスとルートテーブルなどのネットワーク情報
ドメインとコンピュータ名
ライセンスの状態、Key Management Server (KMS) の構成などのアクティベーション設定
現在の時刻と時間帯などの時間設定
インスタンス上にインストールされたドライバ
セキュリティグループのルールに沿った Windows ファイアウォールの設定
インストールされた更新
Windows が 1 週間以内にクラッシュした場合のミニダンプファイル
  • 分析ルール
アクティベーションステータスと KMS 設定のチェック
メタデータと KMS アクセスに対する適切なルートテーブルエントリのチェック
セキュリティグループルールと Windows ファイアウォールルールの比較
PV ドライバのバージョン確認(Redhat または Citrix)
RealTimesUniversal レジストリキーが設定されているかの確認
複数の NIC を使用している場合のデフォルトゲートウェイ設定
ミニダンプファイルのコードのバグチェック
  • 動かすのは非常に簡単で、こちらからダウンロードして、exeをクリックするだけです。credentialの入力を求められるますが、予めEC2にReadonlyのRoleを設定しておき利用すると良いでしょう。

10.0.0.117  2016-10-07 15-08-35.png

  • 「OpenReport」をクリックするとテキストでレポートが出力されます。Windowsがライセンスされてるか。SecurityGroupの設定とFirewallの設定が合致しているかなどです。
  • 収集されたデータは実行ディレクトリと同じディレクトリに出力されていました。
  • 10.0.0.117  2016-10-07 15-14-48.png

  • 参考

監視はどうやる?(Cloudwatch)

  • プロセス、パフォーマンス

    • パフォーマンスカウンタで取得したデータをCloudWatchにメトリクスとして登録することが出来ます。パフォーマンスカウンタを利用すると大体のデータは取れるのでpowershellでcloudwatchにput-metricsする必要は無いです。
    • ただし、すべてカスタムメトリクスになるのでガンガン登録するとそれだけコストがかかります。監視するものはカスタムメトリクスとして登録、後々みれれば良いものはパフォーマンスカウンタとして取得しておくよう選別しておこう。
  • ログ
    • イベントログ含め、任意のログデータをEC2Configを利用することでCloudWatchLogsに取り込むことが出来ます。
  • 監視

    • CloudWatchのカスタムメトリクス、CloudWatchLogsに取り込めればこちらのものですね。Cloudwatchの標準機能を使って通知まで実現出来そうですね。
  • パフォーマンスカウンタのデータや、ログをCloudWatch,CloudWatchLogsに取り込む手順は以下の通りです。

共通の設定(CloudWatch Logs の認証情報、リージョン、ロググループ、ログストリームを設定)

  • EC2インスタンスにCloudwatch,CloudwatchLogsにアクセスするためのロールを付与します。
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "cloudwatch:*",
        "logs:*"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
  • EC2Configの設定を開きます。

C:¥Program Files¥Amazon¥Ec2ConfigService¥Ec2ConfigServiceSettings.exe

  • [Cloudwatch Logs] – [Enable CloudWatchLogs Integration]にチェックを入れます。

10.0.0.117  2016-10-07 15-27-36.png

  • 下記の設定ファイル内のリージョンを変更しておきます。今回は東京(ap-northeast-1)にしてあります。
  • ロールの設定が行われている場合は、AccessKey,SecretKeyは無視されるので空のままで良いです。

C:\Program Files\Amazon\Ec2ConfigService\Settings\AWS.EC2.Windows.CloudWatch.json

AWS.EC2.Windows.CloudWatch.json
            {
                "Id": "CloudWatchLogs",
                "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatchLogsOutput,AWS.EC2.Windows.CloudWatch",
                "Parameters": {
                    "AccessKey": "",
                    "SecretKey": "",
                    "Region": "ap-northeast-1",
                    "LogGroup": "Default-Log-Group",
                    "LogStream": "{instance_id}"
                }
            },
            {
                "Id": "CloudWatch",
                "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatch.CloudWatchOutputComponent,AWS.EC2.Windows.CloudWatch",
                "Parameters": 
                {
                    "AccessKey": "",
                    "SecretKey": "",
                    "Region": "ap-northeast-1",
                    "NameSpace": "Windows/Default"
                }
            }
  • ここまでで事前の設定はおしまいです。

イベントログをCloudWatchLogsでみえるようにしてみます

  • このあたりがイベントログの設定になります。
AWS.EC2.Windows.CloudWatch.json
{
    "EngineConfiguration": {
        "PollInterval": "00:00:15",
        "Components": [
            {
                "Id": "ApplicationEventLog",
                "FullName": "AWS.EC2.Windows.CloudWatch.EventLog.EventLogInputComponent,AWS.EC2.Windows.CloudWatch",
                "Parameters": {
                    "LogName": "Application",
                    "Levels": "1"
                }
            },
            {
                "Id": "SystemEventLog",
                "FullName": "AWS.EC2.Windows.CloudWatch.EventLog.EventLogInputComponent,AWS.EC2.Windows.CloudWatch",
                "Parameters": {
                    "LogName": "System",
                    "Levels": "7"
                }
            },
            {
                "Id": "SecurityEventLog",
                "FullName": "AWS.EC2.Windows.CloudWatch.EventLog.EventLogInputComponent,AWS.EC2.Windows.CloudWatch",
                "Parameters": {
                "LogName": "Security",
                "Levels": "7"
                }
            },
  • イベントログをCloudWatchLogsに出力するには、IdをFlows加えてあげれば良いです。今回はSecurityEventLogを出力するように追記してみました。
AWS.EC2.Windows.CloudWatch.json
        "Flows": {
            "Flows": 
            [
                "(ApplicationEventLog,SecurityEventLog,SystemEventLog),CloudWatchLogs"
            ]
        }
  • EC2Configを再起動して少し待つとCloudWatchLogsにログが出力されました。

CloudWatch Management Console 2016-10-07 16-52-29.png

パフォーマンスカウンタのデータをCloudWatchカスタムメトリクスに表示してみよう

  • この設定はAvailable MBytesをパフォーマンスカウンタから抽出してCloudWatchのカスタムメトリクスに名前空間Windows/Defaultの中にMemoryというメトリクスを追加しています。
AWS.EC2.Windows.CloudWatch.抜粋.json
            {
                "Id": "PerformanceCounter",
                "FullName": "AWS.EC2.Windows.CloudWatch.PerformanceCounterComponent.PerformanceCounterInputComponent,AWS.EC2.Windows.CloudWatch",
                "Parameters": {
                    "CategoryName": "Memory",
                    "CounterName": "Available MBytes",
                    "InstanceName": "",
                    "MetricName": "Memory",
                    "Unit": "Megabytes",
                    "DimensionName": "",
                    "DimensionValue": ""
                }
            },
・・・
            {
                "Id": "CloudWatch",
                "FullName": "AWS.EC2.Windows.CloudWatch.CloudWatch.CloudWatchOutputComponent,AWS.EC2.Windows.CloudWatch",
                "Parameters": 
                {
                    "AccessKey": "",
                    "SecretKey": "",
                    "Region": "ap-northeast-1",
                    "NameSpace": "Windows/Default"
                }
            }
・・・
        "Flows": {
            "Flows": 
            [
                "(ApplicationEventLog,SecurityEventLog,SystemEventLog),CloudWatchLogs",
                "(PerformanceCounter),CloudWatch"
            ]
        }
  • これも設定後再起動すると、このようにメモリがカスタムメトリクスに表示できます。

CloudWatch Management Console 2016-10-07 17-00-16.png

  • いやー便利ですね。

CloudWatchのメトリクスデータの保管

  • CloudWatchのメトリクスは2週間経つと自動で消えてしまいます。
  • 2週間より大きい期間のデータの保管が必要な場合は、定期的にAPIを使ってローカルに落としておくなどの工夫が必要。

CloudWatchLogsの保管期間を決めておこう

  • CloudWatchLogsも勿論お金が掛かります。
  • CloudWatchLogsのログの保管期間はデフォルトで無制限なので変更しておきましょう。
  • 参考

RunCommandの活用検討及び利用準備はしておく。

  • RunCommandはWindows,Linux共にEC2にログインせずともコマンドが実行できる機能
  • Windowsの場合はEc2Configが入っているのでOS側にエージェントのインストールは不要。
  • Javaのアプリケーションを運用していた場合、事前に準備さえしておけばJavaのThreadDumpもOSにログインしないで実行することができるわけです。
デフォルトで利用できるRunCommand
AWS-JoinDirectoryServiceDomain to join an AWS Directory
AWS-RunPowerShellScript to run PowerShell commands or scripts
AWS-UpdateEC2Config to update the EC2Config service
AWS-ConfigureWindowsUpdate to configure Windows Update settings
AWS-InstallApplication to install, repair, or uninstall software using an MSI package
AWS-InstallPowerShellModule to install PowerShell modules
AWS-ConfigureCloudWatch to configure Amazon CloudWatch Logs to monitor applications and systems
AWS-ListWindowsInventory to collect information about an EC2 instance running in Windows.
AWS-FindWindowsUpdates to scan an instance and determines which updates are missing.
AWS-InstallMissingWindowsUpdates to install missing updates on your EC2 instance.
AWS-InstallSpecificWindowsUpdates to install one or more specific updates.
  • 事前に利用できないかは検討しておこう。利用しない場合でも動かせるように準備はしておいた方が良いと思う。
  • RunCommandが利用できる条件は「RunCommandの前提条件」を参照。

おわりに

  • どうでしょうか。結構色々ありますね。何かあったときに慌てないようにNATやロールの設定は予め考えておきたいですね。

続きを読む

AWSアカウント取得後、はやる気持ちをグッと堪えてまずやっておくこと

はじめに

  • 認証に必要な情報は不正利用されてしまうと、大事故(ものすごい請求額)に繋がります。
  • 事故がおきないようにどうするべきか。予兆をどう検知するか。おきてしまった時にどう追跡するのか。を考えておく必要があります。
  • AWSのサービスを早速バリバリ使ってみるぜ!という気持ちをぐっとこらえてやっておきたい設定をリストアップしました。
  • 新しいAWSアカウントを利用する機会があったので、この記事を書きながらやってみましたが長めにみても30分あれば設定は終わります。

ルートアカウントのMFAの有効化

  • rootアカウントは超強力なので絶対にMFAを有効にすること。
  • ハードウェアデバイスで実施し、金庫に保管するくらいの勢いが良いと思います。
  • ハードウェアデバイスは$20くらいで購入が可能です。参考:Multi-Factor Authentication
  • 最低でも仮想MFAを設定しておきましょう。私がいつも使っているのはIIJのSmartKeyです。他にもGoogleAuthenticatorなどもあります。

IAMパスワードポリシーの有効化

  • 所属する組織に合わせてパスワードポリシーを必ず設定すること。
  • ポリシーでは設定できませんが、アカウント作成時にMFAを必須にすることを運用ルールとしました。

cloudtrailの有効化

  • 証跡を残すために行う。全リージョンで必ず設定すること。
  • S3に保管されたログが改竄されていないことも保証できるので合わせて有効化しておくこと。
  1. s3にバケットを作成する(trailxxxx)
  2. プロパティからライフサイクルの設定を行う(底冗長化、Glacier,完全に削除どれにするかはお好みで。とりあえず90日で削除のポリシーとした)
  3. CloudTrailの設定
  4. 「すべてのリージョンに適用」「ログファイルの検証を有効化」
  5. S3のバケットを確認し、証跡が取得できていること。

IAMユーザの作成

  • コンソール用、API用は別に分けて作成する。
  • APIでアクセスキー・シークレットアクセスキーを利用する場合、本当に必要か?代替できないか?を確認すること(ロールを使ってSTSで認証情報を取得できないかなど。)
  • 付与するロールを最小限にしたグループの作成
  • ユーザの作成、およびグループへの所属
  • CloudTrailでの証跡取得が無意味になるのでユーザは最低必ず1人1アカウント発行すること。
  • パスワードの設定(次回ログイン時に再設定してもらうようにしてます)
  • MFAの設定

請求関連

設定

*「請求とコスト管理」から「電子メールでPDF版請求書を受け取る」「請求アラートを受け取る」にチェックして「設定の保存」

電子メールでPDF版請求書を受け取る

  • rootアカウントに紐づくメールアドレスにしか飛ばせないので、必要であれば関係者が受け取るメーリングリストに変えておく。

請求アラート(Billing Alert)を設定する

  • 今回はt2.small×2,Lambda,SWF,RDB,ELB,S3程度なので$100を下回るはず
  • 80$でアラートを設定しておきました。

1.「バージニア北部」のリージョンを選択し、CloudWatch – 請求を選択
2. アラームを作成する
3. 超過金額と通知先メールアドレスを設定すると、メールでのSubscriptionを求められるのでConfirmすることでアラートが設定できる。


TrustedAdvisorの通知設定

  • ビジネスサポート以上じゃないとすべてのチェックは利用できない。
  • ただし、TrustedAdvisorの指摘は守るべきことばかりだし、定期的に自力でチェックするのは大変なものが多くこれだけでもサポートにお金を払う価値がある。
  • どうしても守れないルールなどがあれば、必要に応じて除外設定を行い、常にすべてクリアにしておく状態に保つこと。知っていて無視することと知らないということは別物。
  • 通知先のアドレスはアカウントに紐付くメールアドレスのみ。

続きを読む

AWS SimpleWorkflowでLambdaを使って、Activityの運用から解放されたい!

はじめに

  • AWS SWFご存知でしょうか。大体の人が名前は知ってるけど触ったことがないという反応が返ってきます。(SWF使いどころたくさんあるんだけど、やっぱり流行らないのかなー(涙))
  • SWFとFlowFramework(Java or Ruby)というライブラリを利用することで簡単に(?)ワークフローを実現することができる凄いサービスなんです。
  • この記事はSWFのActivityにLambdaを使って幸せになろうぜという記事です。

  • Lambdaは人気があって記事もたくさんあるのですが、SWFは始めのとっつきにくさからか、周りに使ってる人が見つけられず、ネット上でも日本語の情報源が非常に少ないのです。なので少し普及に貢献してみようと思います。(普及に貢献したい人、一緒に勉強会でもしましょう)

SWFの基礎的な話

  • SWFの概要を理解するにはまずはこちらの資料をご覧ください。
  • この資料を見てわかるようにAWS SWFでは大きく4人の登場人物が出てきます。

Cacoo - SWF 2016-04-01 10-12-44.png

  • Client(Executor) ・・・ workflowをキックする人です。オンプレミス側からSWFのEndpointに接続してワークフローを起動します。
  • SWF・・・SWFはクライアントからの実行の要求を受付けワークフローのキューの管理をしてくれます。
  • Desider・・・SWFのキュー(ドメイン・タスクリスト)を監視しながらワークフローを進める人です。ただタスクを管理するだけで実際の処理は行いません。SWFのエンドポイントからつながるのであればEC2でもよいですし、オンプレミスのサーバを使っても構いません。
  • Activity・・・Desiderから振られた処理を実行する人です。ステートレスに実行します。ActivityもSWFのエンドポイントからつながるのであればEC2でもよいですし、オンプレミスのサーバを使っても構いません。
  • Activityにはステートレスで、処理時間がかかり負荷がかかるものが実装されるため、実際に運用していくとなるとActivityをスケールアウトしていく運用になると思います。

さて本題

  • SWFを中心とした疎結合なアーキテクチャなので、Activityをスケールアウトしていくことで負荷に対応していくことができます。
  • 自動スケールアウトするにはActivityのインスタンスをAutoScalingGroupに登録させればよいでしょう。それすら面倒ならElasticBeansTalkにお任せしましょう。それすらも面倒だ、もっと安く運用したいんだったらLamdaなんじゃないかなと思うわけです。
  • Lambdaを使ったアーキテクチャは以下のようになります。
  • Cacoo - SWF 2016-04-01 10-24-20.png
  • Activityの部分がLambdaになっただけですが、Activityの運用から解き放たれると思うとこんなに嬉しいことはありません。
  • 早速実装方法を見ていきます。(LambdaFunctionの登録は通常Lambdaを利用するときと変わらないので割愛します。)

シンプルに呼び出す

DesiderからLambdaを呼び出す方法

  • SWFに付属しているサンプルではLambdaFunctionへ呼びっぱなしですが、ここではLambdaを実行した結果を待つ形にしてみました。
    @Override
    public void hello(String name) throws Exception {

        task = new TryCatchFinally() {

            @Override
            protected void doTry() throws Throwable {
                ConfigHelper configHelper = ConfigHelper.createConfig();
                DecisionContextProvider decisionProvider =
                        new DecisionContextProviderImpl();

                DecisionContext decisionContext = decisionProvider.getDecisionContext();
                LambdaFunctionClient lambdaClient =
                        decisionContext.getLambdaFunctionClient();

                // lambdaの引数はjson
                Promise<String> val = lambdaClient.scheduleLambdaFunction(
                        configHelper.getSwfLambdaFunction(), """ + name + """, 30);
                // lambda functionの呼び出しが終わるまで待つ
                processResult(val);

            }

            @Override
            protected void doCatch(Throwable e) throws Throwable {
                logger.error("catch exception", e);
                // 例外処理
                throw e;
            }

            @Override
            protected void doFinally() throws Throwable {
                // noop
            }
        };
    }

    @Asynchronous
    private void processResult(Promise<String> lambdaClientResult) {
        System.out.println("ready[" + LocalTime.now() + "] lambda return value["
                + lambdaClientResult.get() + "]");
    }
}
  • scheduleLambdaFunctionの第一引数はLambdaFunction名、第二引数はLambdaFunctionへの引数(jsonのみ)、第三引数はtimeoutの時間になります。
  • LambdaFunctionを実行した結果がPromiseで取れますので、これをAsynchronousメソッドに渡すことでLambdaFunctionの実行を待って結果を出力することができます。

リトライ処理

自前のActivityの場合

  • 通常のActivityであればリトライするには以下のようにアノテーションをActivityに付与すれば簡単に実現できるわけです。
  • ちなみに以下の設定は5秒,10秒,20秒とリトライしてくれます。
@ExponentialRetry(initialRetryIntervalSeconds = 5, maximumAttempts = 3)
public String hello(String str);

LambdaFunctionをActivityにした場合

  • LambdaFunction側にアノテーションが使えないのでDesider側でなんとかする必要がありそうです。
  • ここで登場するのがExponentialRetryPolicyとRetryDecoratorです。
  • ExponentialRetryPolicyでポリシーを決めて、RetryDecorator経由LambdaFunctionClientのインスタンスを入手することで実現できます。
                long initialRetryIntervalSeconds = 5;
                int maximumAttempts = 5;
                List<Class<? extends Throwable>> exceptionsToRetry = new ArrayList<>();
                exceptionsToRetry.add(RuntimeException.class);
                ExponentialRetryPolicy retryPolicy =
                        new ExponentialRetryPolicy(initialRetryIntervalSeconds)
                                .withMaximumAttempts(maximumAttempts)
                                .withExceptionsToRetry(exceptionsToRetry);
                Decorator retryDecorator = new RetryDecorator(retryPolicy);
                LambdaFunctionClient decoratedLambdaClient =
                        retryDecorator.decorate(LambdaFunctionClient.class, lambdaClient);
  • わかれば簡単ですけど気づけないですよねー

300秒の壁

  • AWS Lambda の制限
  • ちょっと前に300秒までLambdaの実行時間が延びましたが300秒を超える処理はどうやって実現したらよいでしょうか。(いや、そのまえに300秒超える処理どうなの?は一旦置いておきましょう)
  • そういう場合は、処理を投げた後に結果をポーリングさせるようなアーキテクチャにすると幸せになります。
  • Desider側ではDecisionContextからWorkflowClockというのが取れまして、WorkflowClockからcreateTimerして得られたPromiseをdesiderのメソッドの引数に上げてあげれば良いです。
  • 以下の例はRdsのSnapshot取得のAPIを叩いた後、snapshotがavairableになるのを待って処理を動かすサンプルです。
  • Functorの引数にPromiseを渡すことでそこまで処理を待たせることができるのと、pargeRdsSnapshotAfterPoolingにtimerを渡している部分がポイントですね。
    @Asynchronous
    private Promise<String> pargeRdsSnapshotAfterPooling(Promise<String> createRdsSnapshotResult,
            Promise<?>... waitForPromises) {

        // 中略

        LambdaFunctionClient lambdaClient = decisionContext.getLambdaFunctionClient();
        Promise<String> getRdsSnapshotStatusResult =
                lambdaClient.scheduleLambdaFunction("getRdsSnapshotStatus", parameter, 60);

        return new Functor<String>(getRdsSnapshotStatusResult) {
            @Override
            protected Promise<String> doExecute() throws Throwable {
                String rdsSnapshotStatus =
                        CmpWorkflowUtils.getActivityResult(getRdsSnapshotStatusResult.get());
                if ("available".equals(rdsSnapshotStatus)) {
                    return pargeRdsSnapshot();
                }
                int retryPeriod = 10;
                Promise<Void> timer = clock.createTimer(retryPeriod);
                return pargeRdsSnapshotAfterPooling(createRdsSnapshotResult, timer);
            }
        };
    }

まとめ

  • ということでSWFのLambdaを使うとActivityの運用から解放されて幸せになれるかもね。という記事でした。
  • サンプルは以下に置いてあります。上記の他、LambdaをCronで実行するサンプルも作って見ました。
    https://github.com/uzresk/aws-swf-lambda-samples

続きを読む

毎回5分かけてたAWS Lambdaへのデプロイを20秒にしよう

AWS LambdaのデプロイをJenkinsで自動化しようぜ。という記事です。

はじめに

  • 今回も小ネタ。
  • はじめはHelloWorldで遊んでいても、複雑なものを作り始めると繰り返しFunctionの再登録をしたくなるわけですが、AWSのマネジメントコンソールからjarをアップロードしてFuctionの再登録する手間が面倒になってくるわけです。
  • また、気付いたら依存ライブラリが多くなってしまい5MBくらいのjarになったあたりからアップロードするまでの時間がかかりすぎて段々イライラしてきます。
  • ということでJenkinsを使ってLambdaFunctionを自動登録する方法をご紹介します。Jenkinsになれた人なら30分くらいあればできると思います。

処理の流れ

  1. BitBucketへのコミット
  2. BitBucketのweb hookでJenkinsのビルド起動
  3. ビルド(Jenkins)
  4. S3へのjarのアップロード(Jenkins)
  5. S3からLambdaFunctionの登録(Jenkins)

私の環境では上記のような感じで稼働していますが、webhookとかそんなに目新しい話でもないので4と5についてご紹介します。

前準備

  • S3へのファイルアップロードもS3からLambdaへのFunction登録もAWS上のJenkinsから行います。
  • S3とLambdaへのアクセスするときにアクセスキーとシークレットアクセスキーは使いません。
  • 代わりにInstanceProfileを利用しますので事前にJenkinsが稼働するEC2のインスタンスに対してS3とLambdaにアクセスできる権限をIAM Roleで付与しておいてください。

S3へのjarのアップロード

  • S3プラグインを使うことでビルド後にできたjarファイルをS3にアップロードしてくれます。
  • [Jenkinsの管理] – [システムの設定] – [Amazon S3 profile]に以下のように設定します。

システムの設定 [Jenkins] 2016-03-14 15-00-27.png

  • Jenkinsのビルド設定画面で[ビルド後の処理の追加] – [Publish artifacts to S3 bucket]をクリックして以下にならって設定します。

2.cmp-activity Config [Jenkins] 2016-03-14 15-21-11.png

  • これで設定は完了です。超簡単ですね。

S3からLambdaFunctionの登録

  • AWS Lambda Pluginを使用します。
  • S3に登録されたモジュールを取得してLambdaFunctionに登録してくれるプラグインです。
  • Jenkinsのビルド設置画面で[ビルド後の処理の追加] – [AWS Lambda Deployment]をクリックします。
  • 設定の内容はAWSのマネジメントコンソールでの設定と変わりませんが注意点はロール名でして、ARNで記載する必要があります。また、LambdaのVPN対応も行われていまして、[高度な設定]をクリックするとVPCとSecurityGroupを登録することができます。

2.cmp-activity Config [Jenkins] 2016-03-14 15-14-05.png

Lambda Functionが更新されているのか?

  • 実はマネジメントコンソールからだと更新されているかどうかがよくわかりません。
  • そういう場合はaws cliを使ってfunctionのLast Modifiedを見てあげるとか、Descriptionにビルド時間を入れてあげると良いと思います。
  • ちなみにLastModifiedは以下のようなコマンドでみることができます。
[ec2-user@ip-10-0-1-26 target]$ aws lambda get-function --function-name Ec2InstanceState --region ap-northeast-1 | jq
{
  "Code": {
    "RepositoryType": "S3",
    "Location": "https://xxxxxx"
  },
  "Configuration": {
    "FunctionName": "Ec2InstanceState",
    "MemorySize": 512,
    "CodeSize": 8802205,
    "FunctionArn": "arn:aws:lambda:ap-northeast-1:194851312534:function:Ec2InstanceState",
    "Handler": "jp.gr.java_conf.uzresk.cmp.activity.aws.ec2.Ec2InstanceActivity::xxxx",
    "Role": "arn:aws:iam::123456789012:role/LambdaFunction",
    "Timeout": 300,
    "LastModified": "2016-03-14T06:09:37.885+0000",
    "Runtime": "java8",
    "Description": "getting ec2 instance status"
  }
}

まとめ

  • 1 Function入れ替えるのに5分くらいかかっていたのが20秒で済むようになりました。
  • 私が使っているLambdaFunctionはせいぜい10個〜20個程度なのでいちいち設定すれば良いのですが、たくさんになった場合は再考が必要ですね。ということで小ネタでした。

続きを読む

AWS SES(送信)でトラブルを起こす前に気をつけておきたいこと

はじめに

  • AWS SES(simple email service)を使うときに監視したい項目と監視手段についてまとめてみました。
  • CloudWatchのカスタムメトリクスに登録するときのツールを用意しましたので参考にどうぞ – github/uzresk/cloudwatch-scripts
  • SESを使い始めるのは簡単ですが、1日の送信数、1秒あたりの送信数に制限があることと、信頼性の低いメールを送信し続けると利用停止になる可能性があります。そうなっては手遅れですのでCloudWatchなどを使って定期的に監視&アラートを設定しておきましょう。

SESとは?

  • SESとはSimple Email Serviceの略で、メールを送受信できるようにするためのマネージドサービスです。
  • 送信の場合、SMTPサーバとして使うこともできますし、aws cli/sdkを使ってメール送信することもできます。
  • 特に申請しなければ認証されたメールアドレスにしかメールを送信することはできません。(Sandbox状態)、不特定多数にメールを送信する場合はRequestProductionAccessにする必要があります。

認証

SESの制限

  • SESを使ってのメール送信では送信クォータと最大送信レートという二つの制限があります。この制限を超えてしまうとメールが送れなくなってしまいますので、送信制限を解除したり制限を超えていないかを監視しておく必要があります。
  • 送信クォータ・・・24時間当たりに送信できるEメールの最大数
  • 最大送信レート・・・Amazon SES が 1 秒あたりにアカウントから受け付けるEメールの最大数
  • 不足する場合は、制限の解除を行うことができます。→こちら
  • SESの制限についてはこちらにまとまっています。

送信クォータと最大送信レートをCloudwatchで監視する

[root@ip-10-0-10-184 cloudwatch_scripts]# crontab -l
*/5 * * * * /bin/bash /home/ec2-user/cloudwatch_scripts/ses_sending_limits.sh
  • メトリクスがうまく取得できていれば/var/log/messagesに以下のメッセージが表示されます。
Feb 22 02:00:03 ip-10-0-10-184 root: cloudwatch put-metrics-data SES SentLast24hours:29 MaxSendRate:14
  • 問題なく動けばCloudwatchカスタムメトリクスに登録されるのでダッシュボードへ保存とアラートの設定を行います。

バウンス

  • バウンス率とは簡単にいうとメールが届かなかった割合のことです。このバウンス率が多いとAWSから配信停止のお知らせ。なんてものが届いた結果メールが送れなくなる可能性があるので十分注意が必要です。
  • バウンス率は5%以下になっていることが望ましいとのことです。
  • バウンス率を計算する範囲というのは決まっておらず、get-send-statisticsで取得される値より大きい範囲が指定されることもあるとのことです。
  • また一時的なエラー(例えばメールボックスが一杯)や検証済みドメインに対してはバウンスとしてカウントされないとのことです。
  • ということでバウンス率も定期的にCloudWatchで監視し、送信数の3%くらいバウンスが溜まってきたらアラートを上げるような仕組みを入れておいたほうがよさそうです。

苦情

  • 苦情とは受取人がEメールの受け取りを希望していない場合に発生するもので、Eメールクライアントで “これはスパムです” などのボタンをクリックした、E メールプロバイダーに苦情を報告した、Amazon SES ディレクトリに通知した、またはその他の方法を使用した可能性のことを指します。
  • 苦情率とは送信数に対する割合で、1%以下となることが望まれるようです。
  • こちらも定期的な監視が必要になる事項です。

バウンス数、苦情数の取得とCloudWatchへの取り込み

  • aws cliのget-send-statisticsを使えば取得することができます。
  • CloudWatchのカスタムメトリクスとして定期的に取得するshを作りました。
  • cloudwatch-scripts/ses_statistics.shをcronに登録します。
  • get-send-statisticsは15分おきにデータを取得し2週間保持しますのでcronの間隔は15分間隔でよいでしょう。
[root@ip-10-0-10-184 cloudwatch_scripts]# crontab -l
*/15 * * * * /bin/bash /home/ec2-user/cloudwatch_scripts/ses_statistics.sh
[root@ip-10-0-10-184 cloudwatch_scripts]# 
  • メトリクスがうまく取得できていれば/var/log/messagesに以下のメッセージが表示されます。
Feb 22 02:00:04 ip-10-0-10-184 root: cloudwatch put-metrics-data SES Bounces:0 Complaints:0
  • 問題なく動けばCloudwatchカスタムメトリクスに登録されるのでダッシュボードへ保存とアラートの設定を行います。

バウンス、苦情数増加への対策

  • バウンスに関しては、バウンスが発生したメールアドレスには二度と送信しないように定期的なクリーニングを行うとよいでしょう。
  • バウンスの通知についてはこちら。バウンスが発生したときにSNS通知することなんかもできますね。
  • 苦情数の増加に関しての対策は難しいのですが、質の良いコンテンツを提供し続けることがベストな対策だと思われます。

参考

続きを読む

AWS DataPipelineって何ができるの?

はじめに

  • AWS Datapipelineについて思ったよりWeb上に記事がないので、試してみた結果をまとめてみました。
  • 細かいパラメータについてはおいおいまとめていこうと思います。

情報源

んで、結局何ができるのか?

  • BlackBeltの資料内ではETLと書かれていますが、AsteriaやDataspiderのようなデータのマッピングツールを兼ね備えているわけではありません。S3からRedshiftにデータをロードしたり、RDSからデータを抽出してS3にエクスポートするなどができます。SQLレベルでの変換は可能ですが、細かい変換や集計に関しては、EMRを使ったりShellを起動してそのなかで呼ばれるプログラム内で実装する必要があります。
  • pipelineはそれぞれスケジュール起動することができます(スケジュール起動のタイミングは最短で15分間隔)pipelineではshellの起動ができるので、cronの代わりとして利用する人もいるようです。
  • DirectConnectと合わせて使うことで、オンプレミスのデータからデータを抽出しS3に保管したり、Redshiftにインポートすることができます。
  • pipeline内の各アクティビティはリランしたり、キャンセルしたりすることができます。

料金

  • 料金表 – Amazon Data Pipeilne
  • 東京リージョンを例にとると、1日に1回AWS内で流れるアクティビティだと月額$0.5715。これにActivityに紐付いてタスクを動かすEC2インスタンスの起動料金がかかるイメージですね。やっぱり安いですね。。

基本的な流れと要素の説明

  • 下記はRDSにあるデータを抽出してS3にエクスポートするPipelineです。

スクリーンショット 2015-11-12 14.34.58.png

  • 左右にあるドラム缶はDataNodeと言われ、データソースを表します。
  • 真ん中にある歯車はActivityと言われ処理を行います。処理はEC2やEMRで動かす必要がありますので、ActivityにはEC2やEMRのリソースを紐付ける必要があります。

Activityに紐付くサーバについて

Activityに処理が移ったタイミングでサーバに処理を行わせます。利用するサーバのタイプは大きく3種類あるようです。

1.インスタンスタイプやSubnet、AMI IDを指定して新しくEC2インスタンスを起動する
2.別のアクティビティで起動されたEC2インスタンスを再利用する。
3.オンプレミス(または、任意のEC2インスタンス)

1はPipelineがオンデマンドで起動するので起動するまでの時間が掛かります。
2,3に関しては起動時間が無いのですぐに処理に移ります。
3に関しては後述しますがjdkのバージョン6以上がインストールされている必要があることとDatapipelineのendpointに対して通信を行える必要があります。

DataNodeの種類

  • DynamoDBDataNode
  • MySqlDataNode
  • RedshiftDataNode
  • S3DataNode
  • SqlDataNode

上の4つはわかりやすいと思いますが、SqlDataNodeだけ2つの活用方法があります。

SqlDataNode – RDSに接続する

  • RDSに関してはインスタンスIDを設定するだけでRDSのインスタンスが特定されます。

スクリーンショット 2015-11-12 16.43.57.png

SqlDataNode – RDS以外のDBに接続する

  • オンプレミスにあるデータベースや、EC2上に構築されたデータベースは以下のように接続先やjdbcドライバを格納先(S3)を設定することで接続することができます。

スクリーンショット 2015-11-12 16.46.37.png

Activityの種類

  • 以下の操作を行うことができます。

  • CopyActivity

  • EmrActivity

  • HadoopActivity

  • HiveActivity

  • HiveCopyActivity

  • PigActivity

  • RedshiftCopyActivity

  • ShellCommandActivity

  • SqlActivity

  • 操作の内容についてはアクティビティを参照してください。


設定方法

ここからは何個かピックアップして操作を見てみようと思います。
EC2やRDSのリソースの設定については省略しています。

RDS → S3

  • RDSのデータをS3にコピーしようと思います。
  • inputのDataNodeにはRDSを指定して抽出するSQLを設定しています。#{table}と記載することでTableに設定された値をSQLに埋め込むことができます。
  • ここでは単一テーブルに対するSelectですが、複数テーブルでも勿論問題ありません。

スクリーンショット 2015-11-12 16.55.52.png

  • output先のS3の定義を行います。

スクリーンショット 2015-11-12 16.56.12.png

  • activityの定義を行います。

スクリーンショット 2015-11-12 16.54.39.png


RDS -> RDS

  • RDSのあるテーブルのデータを別のテーブルにコピーしてみます。
  • ここでは同一のRDS内でコピーしています。
  • inputにはRDSを指定します。

スクリーンショット 2015-11-12 17.08.39.png

  • outputにはinsert文を設定します。vaulesには?を入れておくことでinputのリソースで取得できた順にバインドされるようです。

スクリーンショット 2015-11-12 17.08.58.png

  • 最後にActivityです。ここはinputとoutputを指定するだけです。

スクリーンショット 2015-11-12 17.09.17.png


shellを起動

  • ここでは既に起動してあるEC2インスタンスでechoコマンドを打っている例です。

スクリーンショット 2015-11-12 19.05.25.png

  • スケジュールでshellを起動することができるのでcronの代わりに利用する人もいるようですね。

RDS -> S3 -> Redshift

  • outputをinputとして複数のActivityを繋ぐことができます。
  • RDS -> S3に関しは同様なので省略します。

スクリーンショット 2015-11-12 18.40.58.png

  • S3からRedshiftにデータを入れるときのAcitivityは以下のように定義します。

スクリーンショット 2015-11-12 18.43.10.png

  • outputのRedshiftの定義は以下のようにします。ここではaccountテーブルにデータを入れるように設定しています。

スクリーンショット 2015-11-12 18.44.02.png

  • RedshiftDatabaseの設定(ClusterのIDだけ入れれば繋がります)

スクリーンショット 2015-11-12 18.45.00.png


通知について

  • SNSのEndpointを設定しておくことで成功時・失敗時にメールを送ることが出来ます。
  • 成功時にメールを送るにはActivityのFieldにOn Successを追加し、sendMailを選択します。

スクリーンショット 2015-11-12 18.43.10.png

  • SNSのTopicの設定を行った後、OthersタブでsendMailの設定を行います。

スクリーンショット 2015-11-12 18.49.30.png


既に存在するサーバでActivityを動かす方法(オンプレミスで動作させる)

  • Java6以上をインストールします。
  • TaskRunnerをダウンロードしてサーバに配置します。
  • datapipelineに繋げるための情報を作成します。access-idとprivate-keyはIAMの画面からアクセスキーとシークレットアクセスキーを発行して記載してください。
credentials.json
{
  "access-id":"xxxxx",
  "private-key":"xxxxx",
  "endpoint":"https://datapipeline.ap-northeast-1.amazonaws.com",
  "region":"ap-northeast-1",
  "log-uri":"s3://bucket_name/logs/"
}
  • 起動してみます。
  • workerGroupに設定されたIDでDatapipeline上のタスクをポーリングします。workerGroupは好きな文字列で結構です。
[ec2-user@ip-10-0-0-48 ~]$ java -jar TaskRunner-1.0.jar --config ./credentials.json --workerGroup=wg-20151112 
log4j:WARN No appenders could be found for logger (amazonaws.datapipeline.objects.PluginModule).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Starting log pusher...
Log Pusher Started. Region: ap-northeast-1, LogUri: s3://uzresk-datapipeline/logs/
Initializing drivers...
Starting task runner...
  • Activityの設定で上記のworkerGroupを設定してあげます。

スクリーンショット 2015-11-12 18.59.07.png

  • 上記のように設定することでpipelineは、workerGroupで設定されたIDで動き、TaskRunnerはWorkGroupで設定されたタスクが存在すれば処理を行うようになります。

最後に

  • 単純ですが、単純だからこそ組み合わせて効果でそうなサービスだなぁという感じ。導入のハードルも比較的低いんじゃないかなーと思うんですがあまり実績ないんですかね。。

続きを読む