赤ドクロ Presents 『AWSでアプリ開発するなら 知っておくべこと』
アーキテクチャのベストプラクティス
- Design for failure
- 単一障害点をなくす、すべてが失敗し得るという前提で考える
- 最初に1ホストを複数に分割する⇒Webとデータベース(RDS)
- 複数のWebインスタンスを異なるAZで
- RDSはMulti-AZ
- ELBを利用して負荷分散
- 単一障害点をなくす、すべてが失敗し得るという前提で考える
- Build Security Every Layer
- 通信経路および保存されたデータの暗号化、IAM/セキュリティグループ
- Leverage Many Storage Options
- 万能なデータストアは存在しない、特性に応じて使い分ける
- Storage
- Object Storage: S3, Glacier
- File/Block Storage: EFS(NFS、共有ディスク), EBS - Database
- NoSQL: ElastiCache, DynamoDB
- SQL: RDS(トランザクション処理), Redshift(DWH) - 例
- 静的コンテンツはS3に
- セッションやステートはDynamoDB
- DBのキャッシュはElastiCache
- Implement Elasticity
- IPアドレスで参照しない(名前ベースで)、分散させる
- Think Prallel
- EMRを用いて並列のMapReduceジョブを実行、ELB、1つのKinesis Streamと複数のKCLアプリケーション、バックエンドとしてのLambda
- 1インスタンスでN時間 = N台を1時間 ⇒ コストは同じ
- Loose Coupling
- コンポーネント間の結合度が緩やかになるほど、スケーラビリティは高まる
- すべてのコンポーネントはブラックボックスとしてデザイン(APIアクセス、DNS名でアクセスなど)
- Queueを使って疎結合に(部分的なretryがしやすくなる、重たい処理だけをスケールする)
- Service Discovery
- 各サービスで増えたリソース、減ったリソースに対して透過的にアクセス
- Auto Scalingを使ったELB自動登録、Consulなど - Asynchronous Integration
- 同期処理である必要がなければ非同期にする(その処理、本当にレスポンス必要ですか?)
- アプリケーションがブロックされない
- スケーラビリティ&高可用性
- Frontendを停止することになくBackendを容易にメンテナンス可能
- リクエストの処理順序やリトライ等の制御が容易に(一方、数珠つなぎで全体の見通しは悪くなる)
- Don't Fear Constraints
- より多くのメモリが必要?⇒負荷分散、キャッシュ
- データベースのIOPSが必要?⇒リードレプリカ、シャーディング、データベースのキャッシング
- 問題のあるインスタンスを破棄し、置き換える
The Twelve-Factor App
- Dockerによるアプリケーション開発やLambdaのようなサーバレスコンピュートの普及に伴い、改めて重要性が増しつつある
- Codebase
- デプロイされているアプリとコードベースは常に1:1であるべき
- Dependencies
- 依存関係を明示的に宣言し分離する
- 特定の環境に暗黙的にインストールされているパッケージやツールに依存せず、アプリに同梱する
- 例:gemとbundler
- Config
- OSレベルの環境変数によって注入されるべき
- 設定ファイルは言語/フレームワークの環境依存になる
- Backing Service
- ネットワーク越しに使うものはすべてリソースとして扱い(URLのように)、データベースはアタッチされたリソースとして扱う
- リソースの切替はリソースハンドルの切替(URLの切替)とする
- Build
- build、リリース、実行の3つのステージを厳密に分離する
- すべてのリリースは一意のIDを持つべき(どの環境にどのIDがdeployされているか)
- Process
- アプリケーションをStatelessなプロセスの組み合わせとして実行!
- スケールアウトの単位としてプロセスモデルは分かりやすい(スレッドはメモリ共有するなどで管理が複雑)
- 永続化する必要のあるデータ(次のリクエストでも利用するデータ)はDBなどstatefullな外部サービスを利用
- ローカルディスクのファイル、メモリ上のデータはあくまでもキャッシュとして扱う
- Dsiposability
- グレースフルシャットダウン
- Dev/prod parity
- 開発・ステージング・本番環境をできるだけ一致させ、CI/CDの効果を発揮する
- Log
- 出力ストリームの保存先やルーティングにアプリは関与しない(標準出力に吐き出すだけにする)
- 収集、保存、インデックス化し分析する環境をアプリの外に用意する
- Stateless
- ステートフルにになる要素を水平スケールするリソースの外部に配置
- Session情報(スケールアウトすると新しいインスタンスから見えない)⇒DynamoDBに見にいってローカルにキャッシュ
DevOps
- 無駄やボトルネックを取り除くことで、ライフサイクル(フィードバックループ)を効率化し、高速化する
- Cluture:End to EndでOne teamであること、主体的なオーナーシップ、行われた作業の結果に対する可視性を高める
- Practice:Automate Everything、Test Everything, CI/CD/Infrastructure as a code, etc...
- 自動化と構成管理:プロビジョニング、設定、オーケストレーション、レポーティング
- ApplicationとInfrastructureをいずれも、バージョン管理し、build&testし、成果物を登録し、デプロイする
- 繰り返し継続的に行う
- Tool
DevOps tool on AWS
- ほとんどのサービスにAPIが用意されている⇒プログラミングの文脈でインフラを制御する
- 各言語のSDKが用意されている(IDE向けのプラグインも用意されている)
- Cloud formation
- Jenkinsを使ったデプロイ
ベストプラクティス
- 自動ロールバック:まずはロールバックし、その後ログ/グラフなどを用いてデバッグする
- ダッシュボードで通常時と異常時を把握する
AWS SECURITY DEATH \m/ ~セキュ鮫様からのお告げ~ by Security-JAWS
ネットワーク
- public subnet / private subnet
- public subnet: インターネットに直接接続可能なサブネット(公開サーバを置く、EIPとの紐づけもできる)
- private subnet: NATゲートウェイを経由して内⇒外のインターネット通信は可能
- statefull / stateless
- NAT配下のクライアントのSource Portはハイポート(1024-65535)からランダムに設定される
- Statefull: 戻りの通信もよろしくしてくれる
- Stateless:内⇒外も書かないといけない(1024-65535/tcp)
- Security GroupはStatefull⇔Network ACL(subnet単位で通信を制御)はStateless
- VPN
- ユースケース
- Webサーバ/DBサーバのメンテナンスはプライベートネットワーク経由で行いたい(平文でインターネットを通さない)
- 社内システムで事業所とAWSの間(Direct Connectは品質を高めることもできる)
- AWSを既存システムの拡張リソースとして使用するような場合(繁忙期など) - VPNの場合、AWS側には2つのVPNエンドポイントが用意される(Customer Gateway側で2つのトンネルを張る必要がある)
- static routingもしくは、BGPによるダイナミックルーティング(対応機種のFAQ参照)
- ユースケース
- Direct Connect(専用線接続)
- 宅内~接続ポイント⇒一般的には通信キャリア
- 接続ポイント~AWS⇒AWSが提供
- VLAN分けをできるキャリアと、できないサービスがある
- TOKAIコミュニケーションズ、Colt(旧KVH)
WAF/DDoS
- 全脳アーキテクチャ若手の会
DDoS
- DDoS対策(コストがかかる)、DDoSをあえて受ける(落ちてもいいサイトであれば、放置するのも一つ)
- L3/L4:Infrastructure
- L7: Application
- AWS Shield
- CloudFrontを使って、Shieldオプションを有効化
- Shieldの後ろはAWSでも、オンプレでも対策可能
- 防御対象:CloudFront, ELB, ALB, Route53
- 監視:常にモニタリングしてベースラインの作成、異常検出
- Basicは無料で利用可能、AdvancedはDRT付き
- Billing Protection
- DRT:WAFのチューニングやルール作成もやる
- CloudFrontさえ入っているなら、導入しておかない手はない!
WAF
- FWやIDS/IPSでは防ぐことができない不正な攻撃を遮断(アプリケーション脆弱性など)
- PCI-DSS 6.6にもWAF導入について明記されている
- AWS WAF
- カスタムルール(IPアドレス制限/文字列制限)、SQLI/XSSといった基本的な対策が可能
- 構成:CloudFront, ELB, ALBに仕込めるマネージドWAF
- ルールを正規表現で書けない、WAF検知ログは100件まで
- AWS WAF / WAF on AWS / SaaS WAF / Cloud WAFの比較
- SaaS WAF / Cloud WAF: 正常な通信の確認、DNSの向き先変更程度で導入できる
- WAF on AWSはオートスケールに対応している製品が多い
- AWS WAFはセキュリティ面では物足りない
- 「セキュリティ開発」はなぜ浸透しないのか
AWS Config
ごちゃごちゃしやすいAWSリソースを簡単に「見える化」できる
- 構成管理、変更管理のためのサービス(よく使うサービスは対応済)
- 構成情報のスナップショットの取得
- 変更内容を追うことができる、SNSを使った通知も可能
- AWSリソース間の関係性の確認(EC2とVPC/Security Group/ALBとの関係)
- EC2 Systems Manager: エージェントを入れると、OSの中の情報を取れる、コンソールからコマンドを発行⇒OS上の変更管理が可能になった
- IAMの構成管理
- ユースケース
- AWSリソースの一覧でAWSリソースを確認できる、削除されたリソースについても追跡可能
- いつ、どのように変更されたかを記録するので証跡として利用可能
- 関連するAWSリソースも辿れるのでトラブルシュートしやすい
- AWS Confing Rules
- AWS Configで記録した設定が正しいかを判定するルールを定義できる
- 例
- セキュリティグループがフルオープン
- MFA設定していない
- ACMの証明書の有効期限があと少し
- マネージドルール
- Instanceにtagをつけているか?(billingのために、作った人/プロジェクト名をつける)
- SecurityGroupがフルオープンになっているか?
- カスタムルール
- 判定機構はLambdaで実装⇒極論、修正することもできる
- awslabsにカスタムルールが公開されている(現在34)
- AWS Configを有効化して可視化
- Auto Scalliingで、頻繁にインスタンスの起動/削除をしていなければ、課金額は大きくない
Chat bots with Amazon Lex
- Amazon Lex:音声/テキスト処理
- Alexaと同じ技術で提供されている
- 音声認識+自然言語処理
- コンポーネント
- ユーザ入力⇒出力
- Intents:意図(Utterance/Slots)
- Fulfillment:処理
- Utterance
- Intent(例:RegisteruserForEvent)に対してユーザ入力を紐づける
- Sample utteranceを複数事前に定義する
- 反復して学習することによってユーザ入力の言い回しの揺れを吸収(徐々に改善していく)
- Slot
- SLOT NAME: eventDate, SLOT TYPE: AMAZON.DATE
- 12 March 2017 / tomorrowみたいな揺れを吸収できる
- Fulfilment
- AWS Lambdaとの統合⇒クライアントにレスポンスを返す
- 複数のintentをflowにすることで、より自然な対話が可能になる
- もう少し知りたいですか? ⇒ yes ⇒ 次のintentに繋げる
- 曖昧な答えの場合は、プロンプトを出す(「"yes"か"no"で答えてください」)
- Lambdaとの統合
- Lexがユーザ入力をparseし、intent/slotsを渡してlambdaを起動、lambdaからレスポンスを返す
- dialogAction:会話の流れをつかさどる(例:ConfirmIntent)
- facebookの場合、Response cardを返すこともできる(ユーザに選択肢リストを提示)
- Lambda Functionの実装例
- switchでintentごとの処理を定義して、1 functionで複数intentを処理
- LexResponseBuilderでレスポンスをbuild
- English Onlyでlaunchするが、複数言語をサポートするロードマップ
- 開発者からAWS Japanへプレッシャーを!
- 最初はよくテストして、エラーが多いようであればintentを細かく設定するなどの工夫が必要
サーバレスの今と未来
サーバレス
- パラダイムシフト
- サーバが要らないということではなく、開発者はサーバについて「考えなくてもよくなる」
- 2014年末のre:InventにてLambdaの発表
- 最大の特徴は、課金は使った分だけ(メモリ×時間×実行回数)
- Function as a Service
- アーキテクチャにおける責務
- Stateful >> Stateless
- 永続データ >> 揮発性
- バッチ >> イベントドリブン
- アーキテクチャにおける責務
- Lambda goes everywhere
- コンテナベースの実行環境はportabilityが高いので、いろいろなところにデプロイできる
- Athenaの基盤もLambda
- Greengrass(AWS IoT)
- CloudFrontのEdgeの上
代表的なサーバレスアーキテクチャ
- UIドリブンアプリケーション
- 認証ロジックをBaaS、DynamoDBにクライアントから直接アクセス、SPA+API Gateway
- メッセージドリブンアプリケーション
- オンライン広告システム
- コンテンツのサムネイル作成(image magicを載せたlambda)
- ログのストリームプロセッシング(kinesis/kafkaから取って、加工して、S3やDynamoに入れる)
エコシステム
- プラットフォーム事業者、フレームワークやツール、アプリケーション開発者
- アプリケーション開発者のノウハウ発信が足りない
- cloud packの毎日放送事例
- Serverless framework, Apex, Lamvery, Swagger, AWS Serverless Application Model(SAM), Postman...
- SAM
- CloudFormationテンプレートで管理できる
- lambda, API Gateway, DynamoDBがサポートされている
- app-spec.yaml -> CloudFormation(codeはS3経由でデプロイされる)
サーバレスだからこそできることをやる
- 10X Product Development
- TypeScriptしか書かず、あとは外部のサービスを使っている
- firebase(auth), Netlify(static site hosting), Cloudinary(画像管理), Algolia(検索)
- Serverless, NoOpes and the Tooth Fairy
- 来るサーバーレスな未来では、アプリケーション開発者が運用に責任を持つ
- プロバイダの技術情報や、内部技術が何に依存しているか理解する
- 可視性が下がる、自分自身で問題をfixできないし新機能を実装することもできない
- 売れていないサービスはシャットダウンされるかも
- 日経新聞事例(紙面ビューアー)
- 最大18,000回/1分間のinvocation
- システムをリアクティブに設計する
- イベントの発火やwebhookなどに対応している周辺のマネージドサービスとうまくつないでいる
- シンプルなマイクロサービスとして
- 一度トライアルしておき、いざ活用する前にはまりどころなど判断
SPAの開発の流れ
- ビュー/アプリ(js)開発
- ビューの作成
- テスト駆動でアプリコードを追加(テストがないと、統合時に問題が起こったときの切り分けが困難)
- 例:jQuery+Jasmine
- ローカルで開発可能、チーム開発がはじまったらS3で
- テスト時のブラウザキャッシュに注意(chromeの開発者ツールでdisable cacheするとか)
- AWSに繋ぐ前に、1行書いたら1行テスト
- Cognitoを使った認証+フェデレーション
- 例:Google+
- Googleで認証してIDが払い出される
- ブラウザがCognitoにJSでアクセス、CognitoがGoogleに検証、OKであればDynamoDB書き込み権限を払い出す
- DynamoDBを使ったデータの管理
- Lambdaでシステム強化
- DynamoDB直接読み書きでは仕組みとしてできてしまう、「不正なクエリからの保護」(lambdaでvalidationするなど)
- 「ユーザ全員分の集計」などの情報提供のため
- Serverless Single Page Apps
- Ben Rady著、Step by Stepガイド(日本語版が間もなく出る予定)
参考(ところどころで言及されていた別発表)
- サーバーレスでシステムを開発する時に大切な事
[AWSワークショップ] Amazon Kinesis Analyticsを触ってみよう
- https://jaws-days.doorkeeper.jp/events/57980
- https://github.com/bdjaws/share/tree/master/20170311
- http://qiita.com/takada_tf/items/f03c36eed9e22eb74744
kinesis
- モチベーション
- 処理した結果を複数システムに送る必要がある
- kafka or Kinesis Streams - しかも機械学習を行なう
- Spark Streaming or Storm
- 処理した結果を複数システムに送る必要がある
- Kinesis
- Streams
- マネージドkafkaのイメージ:入出力に制限はある(入力:秒間1MBまたは1,000put) - Firehose:S3, Redshiftへ簡単に配信
- Analytics:SQLクエリー
- Streams
- Stream Source/Destination(StreamかFirehose)
- 入力側を決定する(Strems or firehouse)
- 入力データの型定義をおこなう
- SQL分を作成、デプロイ
- 出力先を決定する(Strems or firehouse)
- kinesis demo stremasは良く停止するので注意・・・
- データ定義は大文字で定義(もしくはselect句をダブルクォーテーションで挟む)
Windowの概念
- Tumbling Window(例:1分ごとに出力)
- FLOOR(("SOURCE_SQL_STREAM_001".ROWTIME - TIMESTAMP '1970-01-01 00:00:00') SECOND / 10 TO SECOND)
- 10 TO SECOND⇒10秒間隔
- Sliding Window(データが流れてきたら出力を開始する)
- Time(60sec:レコード受信をトリガーに直近60sec分を集計)
- Row(2rows:自分+直近2レコード)
- 1つのdestinationに対して、TimeとRowを両方設定できる
Reference Dataの追加
- AWS CLIでのみ追加が可能
- 例:S3のファイルを見る
- 現状、Reference Dataを追加すると動作しない(サポート確認中)
まとめ
- Firehose -> Elastic Search -> KibanaとすべてAWSコンソールで設定可能
- 構築は非常に楽、標準SQL、Firehoseで接続が簡単
- バグが多い、性能評価がしにくい
- kinesis streamsはzookeeperの管理が不要、KPLと併用すれば非常に安い
- Analyticsは簡単な集計処理ならよいが、複雑な処理はSpark Streaming等を利用したほうがよい