サーバーレス&コンテナ&サービスメッシュ AWS Summit Tokyo 2019 re:Cap Day1

2019.07.01

AWS Summitの人気セッションのハイライトイベント「re:Cap」

2019年6月12日/13日/14日に幕張メッセで開催されたAWS Summit Tokyo 2019の人気セッションの内容の再演イベントがAWS Loft Tokyoで今日7月1日から5日間連続で行われる。

本日はその初日である「サーバーレス&コンテナ」回に参加。

オープニングはLoftマーケティングマネージャーのゆっきーさん。

recapday1

サーバーレス編

サーバーレスとは

  • サーバー管理が不要
  • 柔軟なスケーリング
  • アイドル時のリソース確保が不要
  • 組み込まれた高可用性
  • REST APIならAPI Gateway

    • 認証も組み込まれている
    • 独自の認証を作りたかったらLambdaを利用することができる
    • WAFやX-Rayを使って拡張することができる

開発・テスト・フレームワーク

  • 開発環境

    • Cloud9
    • CodeStarを使うとCloud9も一緒にセットアップされる
    • PyCharm
    • IntelliJ
    • Eclipse
    • Visual Studio
    • VS Code(Preview)
  • マイクロサービス化して疎結合にしていくとリソースがどんどん増えていく

AWS SAM(Serverless Application Model)

  • AWSでサーバーレスアプリケーションを表現するスタンダードモデル
  • 関数、API、イベントソースとデータストア
  • サーバーレスアプリケーションのデプロイと管理を簡素化
  • CloudFormationの拡張

    • SAMはpackageとdeployの2つのコマンドを追加している
  • SAMのテンプレート

    • YAMLまたはJSONで記述
    • AWS::Serverless::Function をタイプに指定するとLambda関数が構築できる
    • PropertiesEvent セクションを指定するとAPI Gatewayを構築することができる
    • AWS::Serverless::SimpleTable をタイプに指定するとDynamoDBテーブルが構築できる
    • これらのテンプレートを0から書き始めるのは大変なので、 https://github.com/awslabs にあるサンプルコードをたたき台にすると便利
  • SAM CLI

    • サーバーレスアプリのためのローカルテストツール
    • ローカルマシンでレスポンスやログの確認ができる
    • Lambdaの実行環境をシミュレートしたDockerイメージ
    • $ sam init コマンドも提供されていて、雛形をすぐ作れる
    • 関数ペイロードを生成
    • $ sam local generate-event s3 --bucket hogebucket --key hogekey > s3event.json
    • Lambda関数を実行
    • $ sam local invoke hogeFunction -e s3event.json
    • APIエンドポイントを立ち上げ
    • $ sam local start-api

複数環境・CI/CD

  • 複数環境の必要性

    • リソースの重複使用を避けたい
    • ユーザーに影響を与えずに安全に新しいコードをテストしたい
    • インフラストラクチャの変更を安全にテストしたい
  • アカウント戦略

    • AWSアカウントを分ける
  • 同じアカウントでスタックを分ける

    • ○ リソース管理が簡単
    • ○ 管理や監視ツールを見やすい
    • × 許可やアクセスの分離が難しい
  • アカウントを分ける

    • ○ 許可やアクセスを確実に分離できる
    • ○ アカウントごとのリソース制限を管理しやすい
    • × 複数アカウントとそれらの間のコントロールを管理するのが難しい
  • 環境変数:それぞれの環境に固有の変数を利用する

    • AWS Lambdaの環境変数
    • 関数に動的に渡すことができるキーと値のペア
    • Node.jsの process.env 、Pythonの os.environ のような標準的な環境変数から利用できる
    • KMSも使える
    • AWS Lambdaのバージョニング・エイリアス
    • エイリアス:Lambda関数の特定のバージョンに対するポインタ
    • API Gatewayのステージ
    • 環境変数のように利用できる
    • $ context オブジェクトで利用できる
  • SAM

    • 1つのテンプレートから複数の環境を構築
    • テンプレートをGit等で管理する

CI/CD:アプリケーションのテストを自動化

  • AWS Codeサービスと組み合わせてCI/CD

  • X-Rayを使ってモニタリングまで対応できる

  • CI/CDパイプラインの構成例

    • プッシュするとCodeCommitのリポジトリにプッシュ
    • CodePipelineが検知してCodeBuildがビルド
    • CloudFormation&SAMがデプロイ
  • CodeStar

    • テンプレートを検索してデプロイするとパイプラインがサクッと出来上がる
    • Cloud9も合わせてセットアップできる
  • AWS CodeDeploy

    • 段階的なデプロイメント
    • DeploymentPreference > TypeCanary10Percent10Minutes 等の用意された値をセットすることで段階的にデプロイできる
    • Alarm
    • デプロイ中に発生したエラーをハンドリングする
    • Hook
    • PreTrafficPostTraffic を使うと、あるタイミングでLambda関数を実行できる
    • 戻り値に応じてCodeDeployの動作を変えることができる
    • 連携テストや検証アクションをこのフックの中で実現することができる
  • API Gatewayのカナリアリリース

    • 新しいステージにデプロイに進むトラフィックの割合を設定し、ステージの設定や変数をテストする
    • ロールバックするには、デプロイを削除するかトラフィックの割合を0にする
    • 問題なければカナリアリリースを本番稼働に昇格させる
    • ABテストとかにも使える
  • AWS Serverless Application Repository

    • SAMやCloudFormationとして再利用する
    • Serverless Application Repository経由で再利用する
    • AWS CodePipeline SAR Auto-Publishというawslabsのツール

      • CodePipelineの一連の処理に合わせてPublishまで自動でやってしまう

監視

  • CloudWatchメトリックス

    • デフォルトメトリックス
    • Invocations
    • Duration
    • Throttles
    • Errors,Availability
    • IteratorAge
    • DeadLetterErrors
    • カスタムメトリックス
  • AWS X-Ray

    • サービスマップ
    • 各ノードの呼び出し結果を色で分類し、割合を円グラフにする
    • 平均レイテンシ(ms)
    • トレース数(trace/min)
    • サービス名
    • サービスの分類
    • ボトルネックを簡単に特定することができる

サーバーレスデザインパターン

  • 動的Webアプリ/モバイルバックエンド

    • API Gateway
    • Lambda
    • DynamoDB
  • インタラクティブモバイル/モバイルオフライン処理

    • AppSync
    • Lambda
    • DyunamoDB
  • 画像処理/シンプルなデータ加工

    • S3
    • Lambda(S3のPutをトリガーに動作する)
  • アプリケーション/フロー処理

    • StepFunction
    • 一連の処理フローを可視化・管理
  • 流入データの連続処理

    • Kinesis
    • Lambda
    • S3
    • ストリーミングデータを受け付けるようなアプリケーション
    • Kinesisでバッファリング
  • データ変更トリガー(変更に起因する処理の実行)

    • DynamoDB Streams
    • Lambda
    • DynamoDBに実行されたデータ変更処理に反応したイベント処理
  • 機械学習/ETL/データパイプライン

    • StepFunction
  • データレイクからのデータ加工

    • S3
    • Glue
    • Athena
    • Redshift

Kubernetes on AWS(Amazon EKS実践入門)

コンテナの復習

  • ソフトウェアをOS内の独立した環境で実行する技術
  • 代表的な実装:Docker

    • Build, share and run any application, anywhere
    • 依存関係をパッケージング
    • どこでも動くポータビリティ
    • どこでも作れて、いつでも捨てられる
    • コードで定義
    • バージョン管理やCI/CDに向いている
  • Dockerコンテナの3フェーズ

    • Build
    • Dockerfileを使ってイメージを作っていく
    • コンテナに入ってコマンドを叩くことも可能だが、何が入っているか不明瞭なコンテナの作成は思想に反する
    • よくベースにするOSは apline
    • Share
    • イメージレジストリにコンテナイメージをアップロードする

      • Gitで言う $ git push と同じような操作
    • DockerHubやECR
    • Run
    • Dockerエンジンが起動しているコンテナホストで $ docer run コマンドを実行

      • レジストリからイメージをダウンロードしてきて実行してくれる
  • コンテナのユースケース

    • マイクロサービスのアプリケーション
    • ジョブ実行
    • ジョブ実行時のみ起動してくれればいい、という状況
    • CI/CDの実行
    • CodeBuildでもビルドの環境はDockerで実現されている
    • 機械学習
    • 非常に多くの依存関係があるので、そのセットアップに使われる
  • コンテナ実行時の課題

    • コンテナが起動するホストが増えていくと管理が大変になってくる
    • 耐障害性
    • コンテナのホストが停止したらコンテナ全滅、機能停止
    • 運用性
    • コンテナはどのホストで動かす?リソースは空いてる?
    • 通信したいコンテナはどこにいる?(IPは?名前は?)
    • リソース制限を一括でかけたい
    • スケール
    • 負荷に応じて、コンテナをスケールしたい
    • 同種のコンテナ間でロードバランシングしたい

Kubernates(通称K8s)

  • オープンソースのコンテナオーケストレーションツール
  • Cloud Native Computing Foudationが開発プロジェクトをホスト

    • Prometheus
    • Envoy
    • CoreDNS
    • Fluentd
    • containerd
  • 人気の理由

    • 成長を続けるユーザー数とコミュニティ
    • Runs Anywhere - クラウドでもオンプレでも動く
    • 「オンプレの資産もまだまだ残っているので、クラウドとオンプレで管理方法が異なるのは困る」というケースも多い
    • 拡張可能なAPIとエコシステム
  • 主要機能

    • ノードにコンテナを自動はいち
    • 失敗したコンテナの自動復旧
    • 手動スケール/オートスケール
    • 通信相手を特定/ロードバランス
    • 自動ローリングアップデート/ロールバック
    • 機密情報や設定の管理
    • S3等ストレージのマウント
    • バッチ実行
  • コントロールプレーン
  • データプレーン

    • コンテナを実行する基盤
  • Kubernetesオブジェクト

    • Pod(ポッド)
    • デプロイの最小単位
    • 1つ以上のコンテナから構成される
    • Service
    • Podを名前解決により発見(サービスディスカバリ)
    • ロードバランス(L3/L4)
    • Deployment
    • Podを維持、コントロールするReplicasetの管理
  • Podを手動で操作することは少なく、Deploymentを操作することが多い
  • マニフェストと宣言的設定

    • YAMLファイルで設定を書く
    • 「あるべき状態」を記述する
    • ex:どのコンテナが何台起動してほしいか
    • Kubernetesがどうマニフェストを扱うか
    • APIサーバーが受け取る
    • コントロールプレーンがポーリングする
    • データプレーンを操作してPodの起動・停止を行う

KubernetesとAWS

  • 51%のKubernetesユーザーがAWS上で動かしている
  • EC2を何台か起動して、コントロールプレーンとデータプレーンを展開する

Kubernetes運用の悩み

  • Kubernetesコントロールプレーンの運用は重労働

    • コントロールプレーンの冗長化は必須
    • 運用中のKubernetesのバージョンアップは大変
    • 運用責任はお客さま
  • もっとアプリケーションを実行する部分に集中したい!

Amazon EKS(Elastic Kubanetes Service)

  • Kubernetesコントロールプレーンをマネージドで提供
  • Kubernetesリリースを改変なく利用

    • CNCFによるKubernetes準拠の認定
    • 既存のエコシステムがそのまま動作
  • AWSサービスとシームレスな連携
  • "Undifferentiated Heavy Lifting(=付加価値のない重労働)"を削減し、ビジネス価値の創出に集中できる
  • Kubernetesマニフェストを書いてAWSのマネージドサービスをデプロイ/コントロール可能

Amazon EKSを使う理由

  • 堅牢なコントロールプレーンをマネージドで提供
  • Kubernetesの運用を支援する機能

    • Kubernetesのバージョンアップ、コントロールプレーンログの集約等
  • AWSマネージドサービスとスムーズな連携が可能
  • 選択可能なデータプレーン(ノード)

    • ワークロードに合わせたインスタンスタイプやEC2 AMIを利用できる
    • リザーブドインスタンスやスポットインスタンスも利用できる

導入事例

  • Snapchat
  • APP CARD
  • サイバーエージェント

EKSをデプロイする方法

  • AWSマネジメントコンソール
  • AWS CLI
  • CloudFormation
  • オープンソースツール

    • eksctl
    • terraform

eksctlを使ってEKSをデプロイする

  • EKS構築に必要な権限を割り当て(IAM)
  • 必要なコマンドをインストール

    • eksctl
    • kubectl
  • eksctlコマンドで作成実行

    • $ eksctl create cluster -f 設定ファイル
  • デプロイした後は慣れ親しんだkubectlコマンドで操作することができる

    • ex:$ kubectl get pods

ユースケースとAWS連携

  • HTTP/HTTPS対応のロードバランサーを使いたい

    • SSLオフロード、パスルーティング、複数ドメイン対応
    • Ingressオブジェクトによるロードバランサ機能
    • ALB Ingress Controller
    • AWSのサービスチームがメンテナンスに参加
    • Application Load Balancerを自動デプロイ、設定
    • その他マネージドサービスと連携

      • Amazon Route53 / AWS Certificate Manager
  • ログを集約したい

    • FluentdのDaemonsetを利用してログを集約
    • CloudWatch Container Insights(プレビュー)
    • コンテナログと、メトリクスをCloudWatchに集約
    • 数個のマニフェストを適用するだけの、簡単なセットアップ
  • オートスケールしたい

    • 2種類の水平オートスケール
    • Podレベル:水平オートスケーリング
    • ノードレベル:クラスターオートスケーリング
  • デプロイを効率化したい

    • Codeシリーズを利用してパイプラインを構築
    • CodeCommitへプッシュ
    • 変更を検知、パイプラインを開始
    • コンテナをビルドしてECRへプッシュ
    • Lambdaをトリガー
    • Golang SDKを利用してDeploymentを更新
    • コンテナイメージを取得してローリングアップデートを実行

その他

  • Amazon ECR

    • フルマネージドのコンテナレジストリ
  • データベース

    • Kubernetesとコンテナを使ってMySQLを立ち上げることは可能だが、スケーラビリティやバックアップの設定を行うのは非常に大変
    • AWSの他のサービスを使ってオフロードするのがオススメ

サービスメッシュは本当に必要なのか、何を解決するのか

"Monolith"という呼称に込められるニュアンス

  • 関係者間調整のオーバーヘッド

    • ステークホルダーが増えてくると開発のロードマップにも影響を及ぼしてくる
  • 変更による影響範囲の広さ
  • モジュール構造維持の難しさ
  • 非効率なスケーリング

    • リクエストが多い部分だけスケーリングしたいのに、単一のアプリケーションだとリクエストが少ない部分も含めてスケーリングするしかない
    • ちょっとした部分を変更したときにありとあらゆるユニットテストを実行する必要があり、デベロッパーのデプロイに対するモチベーションを下げる
    • まとめて一個のリリースにしようとして、障害が起きる可能性が上がる

マイクロサービス化に期待される効果

  • 変更による影響範囲の局所化

  • モジュール境界の維持しやすさ

  • 独立したデプロイとスケーリング

  • 自律的なチームによる開発・運用

    • 小さい単位にサービスが分割されるので、各サービスを担当チームが開発できる
  • Polyglot(-able)

    • 個々のサービスごとに開発言語を変える(ことができる)
    • 社内での知識がサイロ化する
  • AWS X-Ray

    • 分散アプリケーションの分析と調査のための分散トレーシングサービス
    • X-Ray SDKを入れる

マイクロサービスの課題

  • サービスの適切な分割

    • 正解がない
    • モノリスで作る場合も、新規でマイクロサービスで作る場合も発生する課題
  • テストの難しさ

    • 依存先サービス、依存先サービスの依存先サービス...など全てを準備する必要がある
  • 影響範囲を自サービス内に収める難しさ

    • 異常なまでに後方互換性に執着する必要がある
    • 他のサービスがアクセスしてくるからダウンタイムを作れない
  • サービス間通信の信頼性 - Reliability

    • マイクロサービスは一種の分散システム
    • ネットワーク経由通信 = 失敗が前提
    • 一時的なネットワーク状況による失敗
    • 対向サービスの不具合・停止による失敗
    • 防御的実装の必要性
    • 呼び出し先サービスの位置は一定ではない

      • サービスディスカバリ
    • 一時的な呼び出しの失敗

      • リトライ(w/Exponential back-off)
    • 継続した呼び出しの失敗

      • サーキットブレーカー
      • リトライし続けるとユーザーにはレスポンスが返らない
      • 対向サービスの復旧作業の妨害になってしまう可能性
    • 呼び出しサービスのパフォーマンス悪化

      • タイムアウト
    • 呼び出し元システムの不具合

      • スロットリング

サービス間通信の可観測性 - Observability

  • マイクロサービス群 = 1つのサービス
  • 外形的には「システム」の恣意杯
  • 失敗はどこで、なぜ起きたのか
  • システムを観測できる実装の必要性

    • ログ/メトリクス/トレース情報出力
    • 各サービスの既存実装の出力フォーマットが不揃いだとコンテキストが見えない
    • Ruby/Go...言語ごとに色々ある
    • 「システム」全体の観測には不向き
    • 全サービスで出力フォーマットを統一
    • 現実的...?

      • 各サービスへの個別実装
      • 複数の言語やフレームワーク
      • 実装担当者と品質担保方法
      • 統一フォーマットの変更
    • 一貫性がある方法が必要
    • 「共通ライブラリ」という解決策
    • Microservice = アプリケーションコード + 共通ライブラリ
    • 課題が...

      • パフォーマンス悪化
      • 言語の最新verの対応まだ?
    • マイクロサービスは
    • 疎結合な実装、自律的チーム関係の維持が成功の秘訣
    • サービス間通信の信頼性担保やシステム全体を観測できる仕組みが必要
    • プロキシへのオフロードというアイデア
    • 全てのサービスはプロキシを通して通信する = サービスメッシュ

Envoy Proxy

  • OSSプロジェクト

  • CNCFメンテナンス

  • サービスメッシュとアプリケーションの密結合

    • 本質的にネットワークトポロジの定義やトラフィックコントロールポリシーはアプリケーションが知る必要のない話

AWS AppMesh

  • Envoy proxyの動的設定変更を可能にする

  • App Meshはサービスメッシュのコントロールプレーン

    • メッシュ全体構造の定義
    • メッシュを構成するプロキシに対し動的に設定を配信
  • アプリケーションレベルのネットワーク

    • ログ・メトリクス・トレース情報の容易な出力
    • クライアントサイドのトラフィック・ルーティングポリシー
  • クラスタやサービスにまたがるメッシュの構築

    • ECS
    • Fargate
    • EKS
    • Kubernetes on EC2
    • EC2
  • マネージドコントロールプレーン

    • 容易なオペレーション
    • 高いスケーラビリティ
  • トラフィックコントロール

    • トラフィックコントロール
    • ルーティング
  • Observability

    • ロギング
    • HTTP access log
    • Amazon CloudWatch Logs
    • メトリクス
    • CloudWatch
    • StatsD
    • Prometheus
    • 分散トレーシング
    • X-Ray
    • Envoyがサポートするその他のトレーシングドライバ
  • サービスメッシュはそもそもコンテナだけのものではない

  • AWS App Meshパブリックロードマップ

  • その他

    • App Mesh自体に料金はかからない
    • 東京リージョンで利用可能

サービスメッシュは本当に必要なのか?

  • あなたのシステムにサービスメッシュは必要か
  • サービスメッシュ

    • サービス間通信の信頼性と可観測性を確保する一貫性のある手段の一つ
  • AWS App Mesh

    • サービスメッシュを実現するサービス
  • そもそもサービスメッシュは必要か?

    • X-Rayでの分散トレーシング、ALBでのトラフィックコントロール
    • OSSライブラリの利用で十分低コストなケース
  • 動的なサービスメッシュが必要か

    • Envoyに静的設定ファイルを利用する

感想

サーバーレスセッションについて

2019年に入ってからAppSyncやCognitoやDynamoDBを使ったサーバーレスアプリケーションを構築していてそのあたりは多少知見があったものの、そのフレームワークであるAWS SAMについては初めて知ることが大半だった。

AWSでのバックエンドの構築にはAmplify CLIやAWS CDKをよく使っていて、AWS SAMは軽く触る程度しか使ったことがなかったので、これを機会にもう少し深掘りして調査してみたい。

AWS CDKでの現状のLambda関数の開発は、

  • ローカルで開発
  • $ webpack -w でビルド
  • $ cdk deploy でデプロイ
  • AWS上で動作検証

という流れで行なっており、ビルドとデプロイに若干時間がかかっていてなんとかしたいところ。(改善策としてTypeScriptを諦めつつ関数本体はCloud9で開発してみたり...)

AWS SAMを使うことでこれがスムーズになるなら、LambdaはSAMで、それ以外のリソースはCDKでという組み合わせ方もできるかもしれない。

コンテナセッションについて

Ruby on Railsでモバイルアプリのバックエンドを構築していたとき、依存関係の管理の簡略化やデプロイのワークフローの整備のためにコンテナ化を考えたことがあった。

そのときのデプロイ先はホストマシンを意識せずにコンテナを走らせることができるAWS Fargateだった。

Kubernetesという単語は耳することは多かったが、なんのために使うのか、どのような経緯でECSとEKSがあるかなどが全然わかっていなかった。

今回のセッションのおかげでコンテナの基本からKubernetesの基本、EKSでできることが一通り理解できたので、技術選定のタイミングで漁る引き出しの一つとして持っておけたらと思う。

サービスメッシュセッションについて

「マイクロサービス」「サービスメッシュ」「えんゔぉい」という単語をTwitterのタイムラインやAWS Summitの会場で見聞きすることがあったが、こちらもEKS/Kubernetes同様全然概要を知らなかった。

知らなかったし、「大規模なプロジェクトで使うから当分関係なさそう」と考えていたのが正直なところ。

今回、マイクロサービスとは何かという基本の話から、マイクロサービスを考える上で発生する課題、そしてその解決策の選択肢とさらった上で一つの確立された解決策である「システムの観測性を確保するための仕組みのプロキシへのオフロード」という今回のメイントピックまで聞くことができた。

一通り聞いて理解した上でも、やっぱりまだ当分使う機会はないんじゃないかという感想は変わらなかったが、システムの規模が大きくなってくるとどのような課題が発生するのか、それにどうエンジニアたちが立ち向かっていったのかを知ることができてこちらも今後の引き出しの一つにできたと思う。

何よりトリさんの話しがうますぎて、マイクロサービス・サービスメッシュど素人の僕でも引き込まれました...!

その他

19:00スタートで休憩なしで21:15までの2時間15分のセミナーだったが、非常に濃い内容でとても充実感があった。

知らないことだらけだったのでまずはひたすらメモ。

メモの行数を数えたら500行を超えていた。

興味ある分野で、最高のスピーカーが話してくれて、PCを使って全力でメモしてという理想的な学び方ができたが、例えばこれを一日に4セットやるとなると体が持たない気がする。

大学をイメージすると90分が一日4コマくらいが最大でしかもそれが週5日。

学んだことを持ち帰って、自分で考えて復習して、さらに次回の予習までして...となるととても回らないんじゃないだろうか。

社会に出てようやく「本当の学び方」ができていると実感する機会が日常的に得られるようになった分、大学までの学びをもっと良くしたいなぁと思うことも増えた。

こんな風に学びを楽しめる人を増やしたい。

今日でまだre:Cap 1日目。まだまだre:Capは始まったばかりなので全力でインプット&アウトプットしよう。