プログラマでありたい

おっさんになっても、プログラマでありつづけたい

Lambda PythonでAWS CLIコマンドを実行する方法

f:id:dkfj:20151027075740p:plain

 スケジュール機能の登場や最大稼働可能時間の延長で、バッチ的なタスクでLambdaを使いたいという要望が増えてきています。このバッチを新規で作る場合は良いのですが、既にAWS CLIで作りこんでいるという場合も多いでしょう。そうなるとPythonやNode.jsに移植するより、そのまま使いたいはずです。しかし、2015年10月現在ではLambdaではAWS CLIはサポートされていません
 しかし、非公式ですがAWS CLIについても使おうと思えば使えます。チラッと手順を紹介するので、興味がある人は自己責任で試してください。

AWSの設定



 AWS絡みでは、下記の設定が必要です。特にCLI特有という訳ではないので、サラッと紹介だけしておきます。

  • Lambdaプロジェクトの作成
  • IAM Roleの作成
  • SNS関係の設定

 Lambdaのエンジンは、Pythonを選択します。理由としては、AWS CLIの実体はbotocoreでエンジンがPythonの場合はデフォルトでインストールされている為です。IAMは、CLIから呼ぶ出すAWSのリソースの使用権限を付与します。SNSについては、サンプルとして実行するCLIコマンドから呼び出す為です。何でも良いです。

Lambdaモジュールの作成



 まず必要なPythonのモジュールを用意します。2015年10月29日時点では、下記のモジュールが必要でした。Lambda関数を作成するローカル環境で、モジュールのダウンロードをしてください。

pip install awscli -t ./
pip install colorama -t ./ 
pip install pyasn1 -t ./
pip install rsa

 次にPythonの実行ソースを作成します。本当に適当に書いています。

import commands

print('Loading function')

def lambda_handler(event, context):
    result = commands.getoutput("/var/task/topic.sh")
    print(result)
    return 0

 ソースの意味としては、OSのコマンドを実行するライブラリを呼び出し、OSコマンドでシェルスクリプトを実行するだけです。呼び出す対象のシェルは、下記の通りです。CLIコマンドでSNS通知を発行しています。

#!/bin/bash

export AWS_DEFAULT_REGION='ap-northeast-1'

SNS_TOPIC_ARN='arn:aws:sns:ap-northeast-1:XXXXXXXXXXXX:PushNotificationTest'


SNS_MSG_SUBJECT='test message'
SNS_MSG_BODY='Hello World!'

aws sns publish \
    --topic-arn ${SNS_TOPIC_ARN} \
    --message "${SNS_MSG_BODY}" \
    --subject "${SNS_MSG_SUBJECT}"

 準備が出来れば、対象のソース・モジュールをzipに固めます。

$ zip -r exec-cli.zip lambda_function.py topic.sh aws* colorama* pyasn1* rsa* 

 Lambdaのコンソール画面からzipファイルをアップロードして実行してください。上手くいけば、メールが届いているはずです。

技術的な背景



 Lambdaファンクションが実行される環境としては、たぶんECSのようなコンテナで管理されたAmazon Linux AMIのインスタンスです。ということで、適切な権限のIAM Roleを割り当てれば、そこで実行されるコマンドについてもIAM Roleの権限が継承されているはずです。じゃぁ、後は必要なモジュールを配置すればいいやんという推測です。実際に動いているので、予想通りなのでしょう。

感想



 この様にLambdaの実行環境は、実はかなり自由度が高く頑張ればかなりのことが出来ます。一方で、AWSが保証している言語の実行エンジン以外の部分については、どのように変更されるか全く解りません。その為、実戦配備にはリスキー過ぎます。ユーザとしては、リスクを承知の上で利用するか、AWS側の対応を待つ以外ありません。私の個人的な思いとしては、AWSさん早くCLIを使えるようにしてください。

※書いた後に気がついたのですが、ファイル操作系の処理をLambdaに持って行ってもあまり用途はなさそうですね。誰かLambda+CLIで素敵なシェル芸を生み出してくださいw

Amazon Web Services パターン別構築・運用ガイド  一番大切な知識と技術が身につく

Amazon Web Services パターン別構築・運用ガイド  一番大切な知識と技術が身につく

  • 作者: NRIネットコム株式会社,佐々木拓郎,林晋一郎,小西秀和,佐藤瞬
  • 出版社/メーカー: SBクリエイティブ
  • 発売日: 2015/03/25
  • メディア: Kindle版
  • この商品を含むブログを見る

See Also:
サーバレスアーキテクチャとは?
サーバレスアーキテクチャ(ServerLess Architecture)とBaaSの違い
仮想サーバ、コンテナサービス、ファンクション
クラウドファーストとクラウドネイティブ
AWS Mobile HubとAmazon API Gatewayからモバイル開発の今後を考える
JAWSUG千葉で、API Gatewayの話をしてきました。
5分で何となく解るAmazon Cognito

AWS書籍活用術 JAWS-UG初心者支部第一回に登壇してきました

 先日、JAWS-UG初心者支部の第一回に参加してきてAWS書籍活用術というタイトルで登壇してきました。

www.slideshare.net

JAWS-UG初心者支部と登壇の経緯



 JAWSUG大阪時代から何かとお世話になっている青木さんが、東京で初心者向きの支部を開設するという話を聞きました。AWSの本を執筆した関係や仕事でAWSの導入を行っていることもあり、初心者が疑問に思うことや求める事について興味がありました。そういった理由で、お手伝いしますよと伝えていたところ、第一回目から声を掛けて頂いた次第です。

発表内容について



 依頼されたテーマは、AWS書籍の活用術です。内容としては、AWS本の紹介とそれを使った勉強方法とのことです。AWS本については世の中に出ている本は大体おさえているので問題ないのですが、勉強方法は少し悩みました。私は、世間一般に比べるとかなり本を読むのが好きです。一方で、技術書を熟読して勉強するかというと、あまりしません。ざっと読んで、大体の内容を押さえておいて、必要なところだけゆっくり読んで試すというスタイルです。
 そのスタイルは良し悪しがあります。飛ばして読むので、体系的な理解が進まない恐れもあります。ただ、自分が実践していない一般論を話しても仕方がないので、ある程度誤解をうむ可能性がある自分のスタイルを紹介することにしました。なお、一般書を含まて読書論については何回も書いているので、下の方のリンクを参照してください。

感想



 一回目ながら予想以上の参加者に驚きました。また、Twitterやアンケートでのフィードバックが多く、登壇者としてもありがたかったです。感想の中には、読んでいる本の著者と会えて感激という言葉を頂きました。実体はただのおっさんですが、虚像でもイベントの盛り上がりに役立てて良かったです。
 また懇親会の参加率および雰囲気も良かったです。参加者の大半がJAWSUGに初参加ということもあり、懇親会でも初対面の人が多かったです。古参の勉強会の懇親会はメンバーが固定化しがちな側面があるので、なかなか新鮮でした。
 運営面でも、今回の立ち上げメンバーは運営初心者です。私は横で見ているだけでしたが、試行錯誤しながらもどういった支部にしたいかというビジョンが明確で、パッションもあふれていました。かなり大変だったと思いますが、まずは第一回目大成功だったと思います。ありがとうございました。


Amazon Web Services パターン別構築・運用ガイド  一番大切な知識と技術が身につく

Amazon Web Services パターン別構築・運用ガイド  一番大切な知識と技術が身につく

  • 作者: NRIネットコム株式会社,佐々木拓郎,林晋一郎,小西秀和,佐藤瞬
  • 出版社/メーカー: SBクリエイティブ
  • 発売日: 2015/03/25
  • メディア: Kindle版
  • この商品を含むブログを見る


See Also:
「Amazon Web Services パターン別構築・運用ガイド」の目次
『Amazon Web Services パターン別構築・運用ガイド』を書きました
今まで読んで良かった本 100冊
読書のコストの話。或いは電子書籍が本の頁数を変えるかもという予想
社会人向けに本の選び方について一言
「読書について」を読まずに本を読むべからず
本の読み方がもう少し上手くなるの5つのTips

参照:
JAWS-UG初心者支部を立ち上げました_2015年5月14日 - yuka_rin’s blog
AWS初心者に贈る〜AWS関連コンテンツを使い倒そう_20150514 #jawsug_bgnr #jawsug @applebear_a…
re:invent へ行こう ~ 仲間作りのワークショップ - JAWS-UG 初心者支部 第1回
https://niheitokyo.s3.amazonaws.com/Create_Account_SPL.pdf?AWSAccessKeyId=AKIAJ5HSIYX72QFVIYVA&Expires=1433634920&Signature=mlnAlVCzAzTxFSdm7EhWvAkidJg%3D
JAWS-UG初心者支部【第1回】 #jawsug_bgnr - Togetterまとめ

「Amazon Web Services パターン別構築・運用ガイド」の電子書籍化決定!!

Amazon Web Services パターン別構築・運用ガイド  一番大切な知識と技術が身につく

Amazon Web Services パターン別構築・運用ガイド  一番大切な知識と技術が身につく

  • 作者: NRIネットコム株式会社,佐々木拓郎,林晋一郎,小西秀和,佐藤瞬
  • 出版社/メーカー: SBクリエイティブ
  • 発売日: 2015/03/25
  • メディア: Kindle版
  • この商品を含むブログを見る


 いよいよ明日3/25発売のAmazon Web Services パターン別構築・運用ガイドですが、嬉しいニュースがあります。何と、電子書籍化が決定しました。紙の本と同時に電子書籍版も発売の予定です!!AWS流に表現すると、「We are excited to announce that Amazon Web Services Pattern Configuration and Operation Guide Book is decided to e-book.」ということでしょうか。

電子書籍の必要性



 著者としても、かなり嬉しいニュースです。今回の本は、大型本でかつ分厚いです。かばんに入れるとズシリと重く、持ち運びは少し大変です。電子書籍化することにより、いつでも持ち運べて見せることも可能になります。
 また、前作のRubyによるクローラー開発技法 巡回・解析機能の実装と21の運用例の時の経験から、紙の本を買わないという層はもう既に一定数いるということが解ってきています。そんな中で電子書籍を出さないというのは機会損失そのものです。出版社さんとしては、まだまだ紙の本を中心に考える必要がある中で、今回の判断を下して頂いてありがたいことです。まだAmazonの選択肢には出てきていませんが、明日3/25には出てくるのではないかと思います。どちらが必要か判断して購入して頂ければありがたいです。
※追記 選択肢として出るようになりました。ただ404のエラーが出るようです。中の人の対応待ち?直接リンクだと購入できます。
Amazon.co.jp: Amazon Web Services パターン別構築・運用ガイド 一番大切な知識と技術が身につく 電子書籍: NRIネットコム株式会社, 佐々木 拓郎, 林 晋一郎, 小西 秀和, 佐藤 瞬: Kindleストア

Amazon Web Services パターン別構築・運用ガイドの予約状況



 ちなみに予約状況ですが、次のグラフにある通り、かなり順調です。日平均でいうとずっと1,000位台で、しばしば3桁台に突入しています。

f:id:dkfj:20150324061717p:plain

 著者としては、あとは発売後のレビューを待つばかりです。どんな意見があるか、待ち遠しいです。(正直、厳しい意見が出るのは怖いですが、鋼のハートを用意しているので大丈夫です。)

Amazon Web Services パターン別構築・運用ガイド  一番大切な知識と技術が身につく

Amazon Web Services パターン別構築・運用ガイド  一番大切な知識と技術が身につく

  • 作者: NRIネットコム株式会社,佐々木拓郎,林晋一郎,小西秀和,佐藤瞬
  • 出版社/メーカー: SBクリエイティブ
  • 発売日: 2015/03/25
  • メディア: Kindle版
  • この商品を含むブログを見る

See Also:
「Amazon Web Services パターン別構築・運用ガイド」の執筆環境
「Amazon Web Services パターン別構築・運用ガイド」の目次
AWSパターン別本の狙い。例えばAutoScalingを使えるように。「Amazon Web Services パターン別構築・運用ガイド」の裏話
『Amazon Web Services パターン別構築・運用ガイド』を書きました
『Rubyによるクローラー開発技法』を書きました
本を書く前に準備したこと、執筆中にしていたこと

AWS コマンドラインインターフェイス(CLI)とAmazon EC2 API Toolsの違い

 慣れている方でもわりと混同されているものに、AWSのコマンドラインインターフェイス(CLI)とAmazon EC2 API Toolsがあります。元々あったのがEC2 API Toolsで、Javaベースで作られています。名前の通り、EC2を操作するコマンドを中心に展開されています。それに対してCLIは後発のツールで、Pythonベースで作られています。こちらは、EC2に限らず包括的にAWSを操作する為のツールとなっています。

CLIとEC2 API Toolsのコマンド

 言葉で説明するより、具体的なコマンドを見たらピンとくると思います。

 まずはCLIです。awsコマンドの後に対象のサービス(ec2等)、実行したいコマンドと続けます。下記の例は、インスタンス一覧を表示するコマンドです。実際には、この後に様々なオプションを付けます。

$ aws ec2 describe-instances

 次にEC2 API Toolsのコマンドです。ec2-から全てのコマンドが全て続いています。

$ ec2-describe-instances

 CLIはEC2 API Toolsのコマンド体系を引き継いでいるため、コマンドも非常に似ています。そのため、EC2 API Toolsに習熟していると、CLIもほぼ同様の操作で利用できます。反面、Googleで検索すると、検索結果が両者が混じりあうことが多いので、注意が必要です。

CLIとEC2 API Toolsの関係



 CLIとEC2 API Toolsの関係を、非常に大雑把に捉えると下記のような関係になります。

f:id:dkfj:20150321222250p:plain

 ポイントはCLIはEC2 API Toolsの大部分を包含するものの、完全に包含するものではないという点です。例えば、VM Importを行うec2-import-instanceコマンドは、EC2 API Toolsしかありません。

CLIとEC2 API Toolsのどちらを使うべきか?



 特別な事情がない限り、CLIを使うべきです。カバー範囲の広さや更新頻度など、CLIに分があります。また、見過ごせないのは、EC2 API ToolsはJavaベースということです。コマンドラインで実行するには、意外に負荷が大きいのです。CPUを結構使うので、microなどの小さなインスタンスの場合、高頻度で利用するとCPUが100%で張り付く場合もあります。

まとめ



 ということで、CLIがお勧めです。3/25に発売の「Amazon Web Services パターン別構築・運用ガイド」にも、結構CLIを取り上げています。Windows,Mac,Linuxそれぞれへのインストール方法や、基本的な使い方の解説の他に、随所にCLIを使った構築法も記載しています。

Amazon Web Services パターン別構築・運用ガイド

Amazon Web Services パターン別構築・運用ガイド

  • 作者: NRIネットコム株式会社,佐々木拓郎,林晋一郎,小西秀和,佐藤瞬
  • 出版社/メーカー: SBクリエイティブ
  • 発売日: 2015/03/25
  • メディア: 大型本
  • この商品を含むブログを見る

See Also:
「Amazon Web Services パターン別構築・運用ガイド」の執筆環境
「Amazon Web Services パターン別構築・運用ガイド」の目次
AWSパターン別本の狙い。例えばAutoScalingを使えるように。「Amazon Web Services パターン別構築・運用ガイド」の裏話
『Amazon Web Services パターン別構築・運用ガイド』を書きました
『Rubyによるクローラー開発技法』を書きました
本を書く前に準備したこと、執筆中にしていたこと

「Amazon Web Services パターン別構築・運用ガイド」の目次

Amazon Web Services パターン別構築・運用ガイド

Amazon Web Services パターン別構築・運用ガイド

  • 作者: NRIネットコム株式会社,佐々木拓郎,林晋一郎,小西秀和,佐藤瞬
  • 出版社/メーカー: SBクリエイティブ
  • 発売日: 2015/03/25
  • メディア: 大型本
  • この商品を含むブログを見る


 「Amazon Web Services パターン別構築・運用ガイド」ですが、いよいよ来週発売です。校正も終わり、あとは発売日を待つばかりとなりました。少し時間も余裕が出てきたので、この本の紹介をしていこうと思います。
 まずは、目次です。全部で5章構成となっています。1章が、AWSの概念的な説明。2章が、手を動かしながらAWSを触ってみるという章です。3章からが実践的な内容で、まずはパターン別の構築例。4章がセキュリティ、5章が運用となっています。

Chapter1 AWSの基本
1-1 AWSとは
 クラウドとは
 物理サーバ(オンプレミス)とAWSの違い
 レンタルサーバ(共有サーバ)とAWSの違い
 プライベートクラウドとAWS
 AWSのサービス全体像

1-2 AWSのネットワークサービス
 リージョンとアベイラビリティゾーン
 Virtual Private Cloud (VPC)
 Route53
 AWSネットワークとVPCネットワーク

1-3 コンピュータ基盤としてのAWS
 Amazon Elastic Compute Cloud(EC2)
 Amazon Elastic Block Store(EBS)
 EC2におけるバックアップ
 Amazon Simple Storage Service(Amazon S3)
 Amazon Glacier

1-4 アプリケーション基盤としてのAWS
 Relational Database Service(RDS)
 Elastic Beanstalk
 ElastiCache

1-5 サービスとしてのAWS
 AWSのアプリケーションサービスの概念
 SESとSQS
 SNSとCloudWatch

1-6 AWS利用のコスト
 AWSの料金体系
 AWSの料金計算の仕方

Chapter2 AWSを利用する

2-1 AWS利用の準備
 AWSアカウントの作成
 ユーザアカウントの作成(IAM)

2-2 AWS CLI
 AWS CLIのインストールと設定
 AWS CLIの基本的な使用方法

2-3 AWS SDK
 サポートされる言語とバージョン
 AWS SDKのインストールと設定
 AWS SDKの基本的な使用方法

2-4 VPCネットワークの作成
 Default-VPC
 Custom-VPCを作成する

2-5 仮想コンピュータ(Amazon EC2)の利用
 AWS操作用の公開鍵・秘密鍵の作成(KeyPair)
 Security Groupを作成する
 EC2を起動する
 AMIを作成する
 ElasticIP(EIP)の利用

2-6 ELB(Elastic Load Balancer)を使用する
 ELBのサービス詳細
 ELBの作成

Chapter3 パターン別構築例

3-1 EC2を利用した動的サイトの構築
 WordPressを使ったブログサイトの構築
 ロードバランシングとHTTPSサイトの構築
 Marketplacesを利用して、構築済みのインスタンスを利用する

3-2 Elastic Beanstalkによる動的サイトのサーバレス構築
 Elastic Beanstalkを利用した再構築
 Elastic Beanstalkを利用したロードバランシングとHTTPSサイトの構築

3-3 S3による静的サイトのサーバレス構築
 S3による静的サイトの構築
 Route53を利用してDNSを設定する
 Route53へドメインの移管
 CloudFrontとの連携

3-4 Auto Scalingによる自動スケーリングシステムの構築
 Auto Scalingの設定
 Auto Scalingを利用するためのアプリケーション構成
 Auto Scaling使用時のEC2インスタンスの初期化処理
 Immutable Infrastructure

3-5 Elastic BeanstalkとLambdaによるバッチサーバの構築
 Elastic Beanstalkによるバッチサーバの冗長化構成
 Lambdaによるサーバレスな処理システムの構築

3-6 CloudFormationによるテンプレートを利用した自動構築
 CloudFormationの概要
 CloudFormationによるネットワーク構築
 CloudFormationによるサーバ構築

3-7 SESによるメール送信システムの構築
 SESを使ってメールを送信する
 EC2インスタンスにメールサーバを構築する
 外部のメール送信サービスを利用する

3-8 AWS上に開発環境を構築する
 開発環境の構築と運用
 継続的インテグレーション(CI)を実施する

3-9 モバイルアプリからAWS上のリソースを利用する
 Cognitoによるユーザ認証と2-tierアーキテクチャ
 AWSのモバイル開発プラットフォーム
 SNSによるモバイルプッシュ通知

Chapter4 AWSのセキュリティ

4-1 AWSのセキュリティへの取り組み
 責任共有モデル
 第三者認証

4-2 IAM(AWS Identity and Access Management)
 AWSのアカウント種類
 IAMユーザとIAMグループ
 IAMロール

4-3 データ暗号化
 AWSが提供するデータ暗号化サービス・機能

4-4 WAF・IDS・IPSによる外部からの攻撃対策
 外部からの攻撃の種類と防御方法
 エージェント型とリバースプロキシ型のサービス導入例

4-5 VPCでネットワークセキュリティを高める
 VPCによるSubnet構成
 SecurityGroupとNetworkACL

4-6 AWSと脆弱性診断
 侵入(ペネトレーション)テスト
 侵入(ペネトレーション)テストツール

Chapter5 管理と運用

5-1 ジョブ管理
 ジョブ管理システムの概念
 サービス型のジョブ管理システム

5-2 システムを監視する
 AWSのなかから監視する
 AWSの外から監視する

5-3 アラートを通知する
 AWSの機能を利用した通知方法
 Twilioを利用した電話通知

5-4 データをバックアップする
 EBSのデータバックアップ
 S3とGlacierを使ったバックアップと管理
 AMIの運用方法

5-5 AWSにおけるログ管理
 AWSのサービスログ/操作履歴のログを収集保存する
 EC2インスタンスのログを収集保存する

5-6 AWSにおけるコスト管理
 AWSにおけるコスト管理
 AWSのコストを節約する

5-7 AWSの利用を支えるサポートの仕組み
 AWSサポート
 AWS Trusted Advisor

 各章のサブタイトルを見ていただくと解ると思いますが、AWSを普通に利用して運用するには必要不可欠なことを網羅していると思います。これ見て、物足りないぜという方は、直接ご相談ください。あまり一般的ではない事例や、かなり厳し目のセキュリティポリシーに基づくものなど、色々あります。
 ちなみに、4人による共著という形になっておりますが、章単位ではなく節単位で分担しております。3-9については誰の担当といった形ですね。このあたりも、ちょっと面白い形で次回紹介したいと思います。

See Also:
AWSパターン別本の狙い。例えばAutoScalingを使えるように。「Amazon Web Services パターン別構築・運用ガイド」の裏話
『Amazon Web Services パターン別構築・運用ガイド』を書きました
『Rubyによるクローラー開発技法』を書きました
本を書く前に準備したこと、執筆中にしていたこと

Amazon Web Services パターン別構築・運用ガイド

Amazon Web Services パターン別構築・運用ガイド

  • 作者: NRIネットコム株式会社,佐々木拓郎,林晋一郎,小西秀和,佐藤瞬
  • 出版社/メーカー: SBクリエイティブ
  • 発売日: 2015/03/25
  • メディア: 大型本
  • この商品を含むブログを見る

5分で何となく解るAmazon Cognito

 年末年始でじっくり調べてみようと思っていたのがCognitoです。先日ようやく時間が取れて、何となく解ってきたので簡単にまとめてみます。Cognitoは、モバイル向けに設計されたユーザーアイデンティティおよびデータ同期のサービスです。主な機能としては、以下の3点です。

  • FacebookやGoogleなどのOpenID ConnectベースのIdentity Providerを利用して認証できる
  • Cognito Syncで、同一ユーザの複数の端末のデータを同期できる
  • 認証/未認証のユーザにIAM Roleを利用して、AWSリソースのアクセス制御

 上記の説明を聞いても、Cognitoの良さはさっぱり解らないと思います。私もCognitoの説明を読んでも、Facebookで認証できるのかぁくらいにしか感じませんでした。Cognito Syncの同期機能も、ほーっと思ったけど必要とする場面はどれくらいあるのだろうなぁと思いました。

Cognitoの重要性



 しかし、Cognitoのユースケースが出始めることで、ようやくCognitoの重要性が解ってきました。Cognitoの重要な機能は、安全簡単にAWSリソースのアクセス制御ができることなのだと思います。モバイル・アプリの場合、サーバサイドのプログラムのようにアクセスキーとシークレットアクセスキーを埋め込むことはできません。配布するために、アプリ内からキーを取り出される可能性があるからです。かといって、インスタンスのようにIAM Roleを発行するということも出来ません。モバイルからAWSのリソースを利用しようとすると、従来であればSecurity Token Service(STS)とToken Vending Machine(TVM)を利用して一時的な認証と認可の仕組みを構築する必要がありました。
 これ非常に面倒くさいですよね。ということで、どういうアーキテクチャが主流だったかというと、下の図のような形だと思います。

f:id:dkfj:20150119232504p:plain

 いわゆる三層構造(3Tier Architecture)です。AWSのリソースの制御はEC2側でやってしまって、モバイル側には結果をJSON等で返すだけという形です。この構成だと、当然全てのリクエスト・レスポンスがEC2を通ることになるので、この部分の性能と可用性が重要になります。必然的に、ELBやAutoScalingを利用することになります。EC2は、直接的な利用料がAWSサービスの中でも比較的高いことや、構築運用監視に人手が必要なため、コストが高くつきます。

Cognitoがもたらすアーキテクチャの変化



 では、Cognitoを利用するとどう変わるのでしょうか?EC2を経由せず、モバイルから直接AWSのリソースにアクセスする構造を簡単に実現できます。2Tier構成です。

f:id:dkfj:20150119233617p:plain

 CognitoはIAM Roleを利用して、認証/未認証のユーザにそれぞれアクセス認可を与えることができます。この未認証ユーザにもというところが味噌で、これのお陰でモバイル・アプリに簡単安全にアクセス認可する仕組みとして利用できます。事実、CognitoのIdentity Poolを作成する時に、実はIdentity Providerの設定は必須ではありません。実装面では、Cognitoの設定をしておけば、後はSDKを取り込んで少しコードを書くだけで、簡単に利用可能です。従来のようにSTS+TVMを使って独自の認証認可の仕組みを実装する必要はありません。Cognitoのウリは、安全簡単に認可の仕組みを組み込めるので、アーキテクチャすら変える力があるということです。

まとめ



 ということで、ここ最近Cognitoについて考えてきたことをまとめてみました。Cognitoは、2Tierアーキテクチャの要になると思います。ただ、まだドキュメント読んだりサンプルコードを動かしているレベルなので、今後本格的にアプリを開発し運用してみると考え方は変わるかもしれません。しかし、Lambdaが出てきたこともあり、AWSはシステムのアーキテクチャ自体を変えるような何かを考えているのではと思います。今年はそこを見極めてみたいですね。たぶんそのうちに、Node.js向けのCognito SDKもでるでしょうし。ツッコミどころあれば、ご指摘頂ければ幸いです。

See Also:
Lambdaで作るクローラー/スクレイピング
S3のイベント通知機能(S3 Event Notifications)に対するユースケースを考える


Amazon Web Servicesクラウドデザインパターン設計ガイド

Amazon Web Servicesクラウドデザインパターン設計ガイド

Lambdaで作るクローラー/スクレイピング

 話題のAWS Lambda Advent Calendar 2014の14日目です。クロスポストで、クローラー/スクレイピング Advent Calendar 2014の14日目でもあります。

 re:Inventで発表されて以来、注目のLambdaです。サーバを用意しなくても、バッチを直接実行できるとあって、ユースケースを考えるだけで夢が広がります。今年はクローラー本を出したこともあって、Lambdaで作るクローラー/スクレイピングをテーマにします。

クローラー/スクレイピングとは?



 Webクローラーは、Webサイトを巡回してデータを取得するプログラムです。スクレイピングは、取得したデータから目的の情報を抜き出すことを指します。一般的には、クローラーの中に、スクレイピングの機能を包含していることが多いです。また、特定のページだけ取得してデータを抜き出すことを、スクレイピングと呼ぶことが多いです。

クローラーの機能



 クローラーの機能は、ざっくり分類すると下記の4つです。
今回は、2と3の部分をLambdaで実施します。

1. 巡回先を決定する
2. ダウンロード
3. 情報を抜き出す
4. (データを保存する)

Lambdaクローラーのモデル



 Lambdaクローラーのモデルとしては、次のような形になります。
f:id:dkfj:20141214045906p:plain

 LambdaCrowlerで、指定されたURLをNode.jsのhttpモジュールを使ってダウンロードします。ダウンロードをしたファイルをS3に保存します。保存先のS3にEventの設定をしておき、parseHtmlのLambdaファンクションを呼び出すようにします。呼び出されたparseHtmlは、イベント情報から呼び元のs3ファイルを取得します。ファイル取得後に、cheerioというスクレイピング用のモジュールを利用して所定の情報を抜き出します。今回は、Yahoo!Financeから株価情報を取得する例とします。

Lambdaクローラーの実装



 まずLambdaCrowlerの実装です。諸般の事情により、取得先のURLと保存するファイル名はリテラルで記述しています。

console.log('Loading event');
var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion: '2006-03-01'});
var http = require ('http');

exports.handler = function(event, context) {
    var bucket = 'lambda-crawler';
    var key = 'test';
    var body;
    http.get("http://stocks.finance.yahoo.co.jp/stocks/history/?code=9984.T", function(res) {
        console.log("Got response: " + res.statusCode);
        res.on("data", function(chunk) {
            console.log('chunk: ');
            body += chunk;
        });

        res.on('end', function(res) {
            console.log('end')
            putObject(context, bucket, key ,body);
        });
    }).on('error', function(e) {
        context.done('error', e);
    });

    function putObject(context, bucket, key ,body) {
        var params = {Bucket: bucket, Key: key, Body: body};
        console.log('s3 putObject' + params);

        s3.putObject(params, function(err, data) {
            if (err) {
                console.log('put error' + err);  
                context.done(null, err);
            } else {
                console.log("Successfully uploaded data to myBucket/myKey");
                context.done(null, "done");
            }
        });
    }
};

 注意点としては、http.requestがcallbackを利用している点です。リクエストの終了イベントを拾い、その後にS3に保存するように記述しています。実行すると次のようなログがでます。

START RequestId: 2b379992-8300-11e4-88d6-37d91d3def55
2014-12-13T19:42:26.841Z	2b379992-8300-11e4-88d6-37d91d3def55	Got response: 200
2014-12-13T19:42:26.842Z	2b379992-8300-11e4-88d6-37d91d3def55	chunk: 
2014-12-13T19:42:26.842Z	2b379992-8300-11e4-88d6-37d91d3def55	chunk: 
2014-12-13T19:42:27.022Z	2b379992-8300-11e4-88d6-37d91d3def55	chunk: 
2014-12-13T19:42:27.022Z	2b379992-8300-11e4-88d6-37d91d3def55	chunk: 
2014-12-13T19:42:27.203Z	2b379992-8300-11e4-88d6-37d91d3def55	chunk: 
2014-12-13T19:42:27.384Z	2b379992-8300-11e4-88d6-37d91d3def55	chunk: 
2014-12-13T19:42:27.384Z	2b379992-8300-11e4-88d6-37d91d3def55	end
2014-12-13T19:42:27.384Z	2b379992-8300-11e4-88d6-37d91d3def55	s3 putObject[object Object]
2014-12-13T19:42:27.574Z	2b379992-8300-11e4-88d6-37d91d3def55	Successfully uploaded data to myBucket/myKey
END RequestId: 2b379992-8300-11e4-88d6-37d91d3def55
REPORT RequestId: 2b379992-8300-11e4-88d6-37d91d3def55	Duration: 2558.28 ms	Billed Duration: 2600 ms 	Memory Size: 128 MB	Max Memory Used: 18 MB	

 次にparseHtmlの実装です。非標準のモジュールであるcheerioを利用しています。

console.log('Loading event');
var cheerio = require('cheerio');
var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion: '2006-03-01'});
var http = require ('http');

exports.handler = function(event, context) {
    var record = event.Records[0];
    var bucket = record.s3.bucket.name;
    var key = record.s3.object.key;
    console.log('record:' + record);
    console.log('bucket:' + bucket);
    console.log('key:' + key);
    getObject(context, bucket, key)
    function getObject(context, bucket, key) {
        console.log('s3 getObject');
        s3.getObject({Bucket:bucket, Key:key},
            function(err,data) {
                if (err) {
                    console.log('error getting object ' + key + ' from bucket ' + bucket +
                       '. Make sure they exist and your bucket is in the same region as this function.');
                    context.done('error','error getting file'+err);
                }
                else {
                    var contentEncoding = data.ContentEncoding;
                    var contentBody = data.Body.toString(contentEncoding);
                    parseHtml(context, contentBody); 
                }
            }
        );
    }
    function parseHtml(context, body) {
        console.log('parseHtml');
        var $ = cheerio.load(body);
        var title = $("title").text();
        var stockPrice = $('td[class=stoksPrice]').text();
        console.log('stockPrice:'+stockPrice);
    }	
};

 まずイベントからバケット名とファイル名を取得します。その情報を元に、S3からファイルを取得します。ファイルを取得したら、cheerioでスクレイピングです。cheerioの使い方は割愛しますが、タグ名+クラス名で、要素を指定しています。
 尚、非標準のモジュールを利用しているので、ソースと一緒にモジュールもzipで固めてアップロードする必要があります。

├── node_modules
│     ├── aws-sdk
│     └── cheerio
├parseHtml.js

 上記のような構造のディレクトリをまとめてzip化します。

zip -r code.zip parseHtml.js node_modules/

アップロードしたファイルの中で、どのファイルを実行するかは「File name」で指定します。
f:id:dkfj:20141214051542p:plain

実行すると、次のようなログが出てきます。stockPriceの部分が、今回取得しようとした情報です。

START RequestId: 1d834bf2-8300-11e4-800c-bd34141de807
2014-12-13T19:42:05.492Z	1d834bf2-8300-11e4-800c-bd34141de807	record:[object Object]
2014-12-13T19:42:05.492Z	1d834bf2-8300-11e4-800c-bd34141de807	bucket:lambda-crawler
2014-12-13T19:42:05.492Z	1d834bf2-8300-11e4-800c-bd34141de807	key:test
2014-12-13T19:42:05.493Z	1d834bf2-8300-11e4-800c-bd34141de807	s3 getObject
2014-12-13T19:42:06.174Z	1d834bf2-8300-11e4-800c-bd34141de807	parseHtml
2014-12-13T19:42:07.173Z	1d834bf2-8300-11e4-800c-bd34141de807	stockPrice:7,336
Process exited before completing request

END RequestId: 1d834bf2-8300-11e4-800c-bd34141de807
REPORT RequestId: 1d834bf2-8300-11e4-800c-bd34141de807	Duration: 1920.75 ms	Billed Duration: 2000 ms 	Memory Size: 128 MB	Max Memory Used: 27 MB	

ハマリポイント



 成果物としてのソースは非常に簡単ですが、かなりハマりました。ハマったポイントは、以下の通りです。

  1. そもそもNode.js知らん
  2. S3 Event Notificationのロール登録時に、ロール中にprincipalのserviceにs3.amazonaws.comが必要

課題



 一応完成しましたが、1つ課題があります。最初のLambdaファンクションを呼び出すのを誰にするかです。呼び出し方として、s3 event notification,Kinesis stream, DyanmoDB stream、もしくはプログラムから呼び出すなどの手段あります。そもそも今回Lambdaでクローラーを作ろうと思った目的は、サーバレスで作りたかったからです。どの呼び出し元を選んだとしても、イベント起こす為の起点が必要です。その辺りどうするかがポイントになりますね。
 クローラーという用途で考えると、何らかの方法で取得対象をDynamoDBに登録して、Lambdaを呼び出して結果を記載するという方法があっているかもしれません。もしくは、呼び元の小さなインスタンスを用意して、処理自体をLambdaの潤沢なリソースを使うというのも考えられます。いずれにせよ、Lambdaを使うには、信頼性の高いスケジュール・ジョブの実行主体が必要になります。この辺りもサービス化して貰えるとありがたいですね。

まとめ



 駆け足でしたが、やはりLambdaは魅力的なサービスです。クローラーを作ってると、IPアドレスとリソースの確保が大変です。もう少し色々考察してみたいと思います。ちなみに、Rubyによるクローラー開発技法という本を書いたのですが、リクエストの中で多いのがPython版とNode.js版を出してとのことです。Lambdaが出たことなので、誰かNode.js版書きませんか?

See Also:
KimonoLabsと今後のサービスのあり方のはなし
プログラミング・レスで5分でサックリWebスクレイピング「kimonolabs」
『Rubyによるクローラー開発技法』を書きました


参照:
AWS Lambda Advent Calendar 2014
クローラー/スクレイピング Advent Calendar 2014
全部俺Advent Calendar

Rubyによるクローラー開発技法 巡回・解析機能の実装と21の運用例

Rubyによるクローラー開発技法 巡回・解析機能の実装と21の運用例