皆さまこんにちは。インテージテクノスフィアのアイダです。2回目はリサーチテクノロジー本部の SさんによるAWSを使った事例紹介です。当社は2010年頃からAWSを業務適用し始め、今では全社で積極的に利用しております。Sさんも長年AWS利用されている方ですが最近初めてサーバレスアーキテクチャを使ったそうで、今回その知見を書いていただきました。ではSさんお願いします!
- はじめに
- 1. Redshiftは集計系関数があまりサポートされてない!(Athena -> Redshift Spectrum)
- 2. 30秒以上のAPI GatewayはStep Functionsをかますべし
- 3. API Gatewayのアクセス制限設定の罠に注意
- 4. Cognitoのいけてないところ
- 5. serverless frameworkでLambdaのデプロイを簡単に
はじめに
とある業務で手掛けたAWSでのサーバーレスアーキテクチャの事例のご紹介です。
私もサーバレスが初めてだったこともあり、いろいろと苦戦しました。
API開発これからやるという方、AWSのサーバレスアーキテクチャよく知らないという方、なんとなく興味ある方にちょっとでも参考になればと思います。
まずお話の前提として要求時点でのこれ(A)が、最終的にこれ(B)になりました。
(A)
(B)
上記過程でいろいろ工夫したり、ハマった点をお話したいとおもいます。
1. Redshiftは集計系関数があまりサポートされてない!(Athena -> Redshift Spectrum)
今回、データ分析業務における人的作業の負荷が上がってきたことから、API化(処理化)し、人的作業を減らすことが目的の1つでした。
かつ要件として各自が分析で利用していたAthenaをDB化する前提があり、運用やパフォーマンス検討の結果Redshift Spectrumを採用して開発を進めました。
Redshift Spectrumをご存じない方向けに簡単に言うと、S3にあるファイルをインポートせずにそのままRedshiftの外部テーブル化する仕組みです。
(Athenaとの違いは省略します)
で、Athenaで使っていたクエリをRedshift Spectrumへ移行したのですが、
Redshift(Spectrum含む)は集計や分析用途のクセに集計系関数があまりサポートされてない
ということに途中で気づきました。
具体的に言うと、Athenaでは集計時に小計を算出するためのGroup by句にROLLUPオプションを使っていたのですが、Redshiftではこれがないと。もちろん全部の組み合わせの小計を出すCUBEオプションもない。
Redshift
https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/c_Aggregate_Functions.html
→RedshiftはオープンソースのPostgreSQLがベース。
新しめのPostgreSQLにはROLLUPはあるのだが、Redshiftのベースとなっているバージョンには入ってない。
Athena
https://docs.aws.amazon.com/ja_jp/athena/latest/ug/select.html
→AthenaはFacebookがオープンソース化したPrestoがベース
まあ、移行あるあるっちゃあその通りなんですが。
で、どうしたかって?
SQLを改修しサブクエリで小計を計算してUNION句でつなぎました。
え?処理性能悪くなるって??だってしょうがないじゃないですか・・・
ちなみにAthenaは多重度には弱いのですが、ビッグデータ系の単発クエリ処理性能だけならノーチューンでRedshiftより『断然』速いです。
こういった分析業務の処理化は結構、事例として頻度は高いのではないでしょうか。その場合、もしアプリケーション的にリクエストの多重性を制御できる、もしくはサービスのSLA(Service Level Agreemen))を鑑みて処理失敗してもクリティカルな影響が少ない状況であれば、分析用に使っていたAthenaのままAPI化したほうが開発コストも処理時間も削減できる可能性があります。是非あたまの片隅にでも置いといてください。
2. 30秒以上のAPI GatewayはStep Functionsをかますべし
同期処理と非同期処理の違い、みなさんご存じですか?
Webアプリケーションの場合、いろいろなところのタイムアウトを気にする必要がでてくるのですが、AWSでよくやる
API Gateway + Lambda
の構成で、時間的に最もネックになるのはAPI Gatewayの タイムアウト(リファレンスでは「統合のタイムアウト」という制限値)です。
現時点で、この値が最大29秒までしかサポートされていません。
https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/limits.html
リソースまたはオペレーション | デフォルトの制限 | 引き上げることができる |
---|---|---|
統合のタイムアウト | Lambda、Lambda プロキシ、HTTP、HTTP プロキシ、AWS 統合など、すべての統合タイプで 50 ミリ秒~29 秒 | 下限または上限には適用外 |
もちろん設計段階で同期にすべきか非同期にすべきかは悩んではいました。しかし、依頼側よりできれば同期にしたいとのことで作りながら考えようという形で進めたのですが、結果的に処理時間が読めない案件であった時点で非同期構成にすべきだった(少し遠回りした)ということですね。
したがって、『応答の完了が確実に30秒未満に終わる』と断言できるものではない限り、非同期処理として
API Gateway + Step Functions + Lambda
の構成を意識すべきです。
事例はすぐ探せます(みんな大好きクラスメソッドさんの事例)
https://dev.classmethod.jp/cloud/aws/apigateway-stepfunctions-asynchronous/
Step Functionsを使う分リクエスト用とレスポンス用の2つのメソッドを用意することにはなるのですが。
あと応答の完了で次に問題になるのは、Lambdaのタイムアウト900秒(15分)という制限あたりです。
3. API Gatewayのアクセス制限設定の罠に注意
API GatewayでAPIを作る場合、セキュリティを考慮してアクセス経路を適切に設定しますよね。みなさん、この設定でハマりませんでしたか?なかなかうまく制限ができない・・・みたいな。
通常アクセス制限はリソースポリシーで設定するかとおもいますが、アクセス許可させる対象となるAPI Gatewayのメソッドやプロパティのリソースを指すARNがマネジメントコンソール上のどこからも取得できないという・・・
ひどい!
設定を行いたい方は、この辺のドキュメントを見ながら設定をすることになります。
意外とネット上にこの辺のアクセス制限の事例も少ないので、ハマった方はいるのではとおもいます。とりあえずあらかじめ注意してください。
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/list_amazonapigateway.html
4. Cognitoのいけてないところ
Cognito、使ったことある人少ないと思いますが、ユーザー認証用のディレクトリサービスです。
https://aws.amazon.com/jp/cognito/
簡単に言うなら、社内のActive Directory(通称:AD)と同じような仕組みと考えてください。
この仕組みと社内のADを連携させれば(注:システム管理者に要相談!)社内のログインアカウントを利用してシングルサインオン認証ができるはずです。
で、このCognito。
もちろん任意のユーザーを登録することができるので、アプリケーション等でユーザーを個別、グループ単位で認証認可をさせたい場合は重宝します。
ただ、登録したユーザーを有効化するためにはマネジメントコンソールではできず、boto3等の純正ライブラリもしくはAWS CLI等のコマンドを使わなければいけないんです。つまりこちらもめんどくさいから気を付けてください。
5. serverless frameworkでLambdaのデプロイを簡単に
今回の記事で一番伝えたかったことです。
皆さん、Lambdaってどうやってデプロイしてますか?
そりゃーライブラリをなにも使わないような簡単な処理であればマネジメントコンソールに直接ゴリゴリ書いてもいいでしょうが、かなり複雑な処理を組み込んだLambda関数をまさかライブラリも含めて自分でzipに固めてアップロードしてませんよね?今後も維持保守していくんですよ、誰がそれ引き継いでやるんですか??
というわけで、そのあたり改修⇔デプロイの多いアジャイル的な開発をPythonで行うのであれば、こちらのフレームワーク+プラグインの導入をお勧めします。
serverless framework + serverless-python-requirementsプラグイン
純正のPythonコードだけであればプラグインは不要だけど、だいたいはpipで外部モジュールいれるとおもうので、その場合にはこのプラグインを入れて設定ファイルに記載しておくとデプロイ時同梱してくれます。
インストールの前提条件 はこんな感じです。
- python3.7がインストールされている
- node.jsのv4以上がインストールされている
- AWS CLIがインストールされている
- docker がインストールされている
ymlにデプロイ先の環境情報を記載して、外部モジュールリストを置くだけ。
一度設定できてしまえば、
$ sls deploy
だけでデプロイしてくれちゃいます。
いやー、システムテストで数十回もバグ改修(泣)。これなかったら超めんどくさかった。いくつかこういったフレームワークはあるみたいなのですが、
何がいいってインストールも設定もシンプルだし動きが軽い、そしてなんかかっこいい。
この仕組み、裏でうごいているのはCloudFormationなので、CloudFormationでできることはおそらくほぼできるはすです。
私は「にわか」使いだったのですが、もっと便利な使い方がいっぱいあるようで、なんならすでにあるある構成のymlテンプレが用意されているので、これを使うと楽ちんぽい。下記あたりが参考になるでしょうか。
できることざっくり: Serverless Frameworkの使い方まとめ - Qiita
実装例: Serverless FrameworkのExampleを見て、サーバーレスの様々な実装を学ぼう | Developers.IO
こんなことまで: Serverless FrameworkでVPC作るところからHello Worldまで全部自動化してみた! - Qiita
気になるとこ: LambdaのデプロイをシェルスクリプトからServerless Frameworkに切り替えた時に苦労した点 | Developers.IO
本家サイト: https://serverless.com/examples/https://github.com/serverless/examples
ちなみにAWS謹製の似たようなデプロイ用のフレームワークであるAWS SAMというものもありカバー範囲は広そうですが、すべてをこのフレームワークでのデプロイに任せる必要はないし、そもそもカジュアルではなさそうなので
今のところserverless framework一択でよかろう。
これからAPIを開発しようとしている方、ぜひとも何かのきっかけになれば幸いです。