Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
メドピア AWS勉強会 ECS編 / MedPeer AWS Seminar ECS
Search
reireias
October 12, 2020
Technology
15
11k
メドピア AWS勉強会 ECS編 / MedPeer AWS Seminar ECS
メドピア社内で定期的に開催しているAWSに関する勉強会を開催しています。本資料はそのうちのECSに関する回のものです。
reireias
October 12, 2020
Tweet
Share
More Decks by reireias
See All by reireias
MedPeer SREチームによるAWSアカウント運用効率化 / Improving efficiency of AWS account operations by MedPeer SRE team
reireias
7
1.5k
複雑なサービスの開発環境 / Complex Service Development
reireias
0
850
[開発合宿] Firebase + Nuxt.js + RaspberryPiによる猫監視システム / Cat Watcher
reireias
0
260
Other Decks in Technology
See All in Technology
Oracle Base Database Service 技術詳細
oracle4engineer
PRO
5
49k
ガチ勢によるPipeCD運用大全〜滑らかなCI/CDを添えて〜 / ai-pipecd-encyclopedia
cyberagentdevelopers
PRO
3
200
事業者間調整の行間を読む 調整の具体事例
sugiim
0
1.3k
新卒1年目が向き合う生成AI事業の開発を加速させる技術選定 / ai-web-launcher
cyberagentdevelopers
PRO
7
1.5k
Apple/Google/Amazonの決済システムの違いを踏まえた定期購読課金システムの構築 / abema-billing-system
cyberagentdevelopers
PRO
1
210
カメラを用いた店内計測におけるオプトインの仕組みの実現 / ai-optin-camera
cyberagentdevelopers
PRO
1
120
新卒1年目が挑む!生成AI × マルチエージェントで実現する次世代オンボーディング / operation-ai-onboarding
cyberagentdevelopers
PRO
1
160
CyberAgent 生成AI Deep Dive with Amazon Web Services / genai-aws
cyberagentdevelopers
PRO
1
480
visionOSでの空間表現実装とImmersive Video表示について / ai-immersive-visionos
cyberagentdevelopers
PRO
1
110
GitHub Universe: Evaluating RAG apps in GitHub Actions
pamelafox
0
170
IaC運用を楽にするためにCDK Pipelinesを導入したけど、思い通りにいかなかった話
smt7174
1
110
生成AIと知識グラフの相互利用に基づく文書解析
koujikozaki
1
140
Featured
See All Featured
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
167
49k
Intergalactic Javascript Robots from Outer Space
tanoku
268
27k
The Pragmatic Product Professional
lauravandoore
31
6.3k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
A Tale of Four Properties
chriscoyier
156
23k
How GitHub (no longer) Works
holman
311
140k
Why You Should Never Use an ORM
jnunemaker
PRO
53
9k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
43
6.6k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
27
4.2k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
25
1.8k
Building a Scalable Design System with Sketch
lauravandoore
459
33k
Transcript
AWS勉強会 ECS編 メドピア株式会社 CTO室 SRE 侘美 怜
注意 本資料はメドピア社内で実施した勉強会の資料を外部公開向けに一部修正したものに なります。 講師の説明が無いと理解しづらい図などがありますのでご注意ください。
目的 ECSの仕組み・概念を理解する Fargateとは何かを理解する ECSのスケーリングについて理解する ECSのデプロイ時の挙動を理解する ECSのログの閲覧方法を理解する
目次 1. AWSの基本 ◦ Region ◦ Availability Zone ◦ VPC/Subent
2. ECS ◦ ECSの概念 ◦ Fargate ◦ スペックとスケール ◦ ログ ◦ デプロイ
1. AWSの基本
概念 Region Availability Zone VPC(Virtual Private Cloud) Subnet
Region AWSが展開する世界各地のロケーションのこと AWSの各種リソースは指定したRegionの中に作られる(例外あり) メドピアでは東京リージョン(ap-northeast-1)を使っている
Availability Zone リージョン内に複数あるデータセンターのこと 東京リージョンには3つのAZがある(ap-northeast-1a, 1c, 1d) 同時に複数のAZが落ちることはほぼないため、サービスを複数AZにまたがって構築す ることで、高い可用性を実現する Region (ap-northeast-1)
AZ-A AZ-C AZ-D
一般的なMulti-AZ構成 Region (ap-northeast-1) AZ-C AZ-A Aurora(Writer) Aurora(Replica) ECS ALB ECS
簡略化のためにAZ2つで説明 どっちかのAZが落ちてもサービ スは稼働する構成 ただし、Region全体のネット ワーク障害などの場合は死ぬ AZ間通信の場合、AZ内通信に くらべて、10ms程度レイテンシ が発生する
AZ間通信のレイテンシがネックになる例(実話) 1回のSQL実行が5msのクエリがあったと仮定する。 このクエリを1000回実行するようなN+1の実装をしてしまった。 5ms * 1000回なので、5000msで応答する計算になる。 ローカルで計測してもその程度だった。 まあまあ重いページなので、5秒は許容範囲としリリースした。 リリース後、「2回に1回くらいの頻度で、エラーになる」という問い合わせが入ってしまっ た。
AZ間通信の場合、1回の通信ごとに10ms程度のレイテンシが発生する。 →1000回の通信では、10秒のレイテンシが発生する。 →レスポンスに15秒かかってしまい、タイムアウト。
VPC(Virtual Private Cloud) 仮想的なネットワーク空間 複数のAZをまたぐように作成できる production環境とstaging環境は別のVPCとすることで、ネットワーク的に分離する設計 が一般的 Region (ap-northeast-1) AZ-A
AZ-C AZ-D VPC 10.0.0.0/16
Subnet VPCの中に作るサブ的なネットワーク空間 VPC内にEC2やRDSを作成する際に指定が必須になる Subnet単位でアクセスを制限したりする Availability Zone 1a Availability Zone 1c
Availability Zone 1d VPC Private subnet 10.0.130.0/24 Public subnet 10.0.30.0/24 Private subnet 10.0.120.0/24 Public subnet 10.0.20.0/24 Private subnet 10.0.110.0/24 Public subnet 10.0.10.0/24
2. ECS
目次 1. AWSの基本 ◦ Region ◦ Availability Zone ◦ VPC/Subent
2. ECS ◦ ECSの概念 ◦ Fargate ◦ スペックとスケール ◦ ログ ◦ デプロイ
2.1. ECSの概念
ECSとは Elastic Container Service Dockerコンテナの実行や管理を行うことができるサービス メドピア社内のサービスは一部の古いサービスを除き、ほぼこれで運用されている Kubernetesとは別物 Kubernetesはもっと複雑で、ロードバランサーやストレージ等様々なリソースを管理でき る
ECSの概念 ECSクラスター ECSサービス ECSタスク定義 ECSタスク Dockerコンテナ
クラスター/サービス/タスク/コンテナの関係 Cluster Service A Task A Container A Container B
Service B Task A Container A Container B Task B Container C Task B Container C
AWSマネジメントコンソールで確認 ECSクラスター ECSサービス ECSタスク
タスク定義 ECSサービスがECSタスクを起動する 際の設定が書かれたリソース 「どんなコンテナをどんな設定で起動す るか」が書かれている デプロイする度に新しいリビジョンが作ら れる(新しいイメージが指定されている)
タスク定義を確認する AWSマネジメントコンソール上で現在作成されたタスク定義を確認できる 作成元のコードは社内のサービスによって管理されている場所が異なる • 比較的最近のプロジェクト等はterraformのリポジトリに入っている • ecs-cliを使ってプロジェクトは、docker-compose.yml形式に変換されたものがrails のリポジトリ内に入っている 例をマネジメントコンソールと実装で見てみる 参考:https://github.com/aws/amazon-ecs-cli
マネジメントコンソールで紹介
タスク定義と他リソースの関係 ECSサービスは属性として以下を持つ • 使用するタスク定義とそのリビジョン • 希望するタスク数 Task Definition Revision 10
Service Task Revision 1 ... Task Task Task Revision 10のタスク定義で4タスク起動する設定にした例
タスク定義とデプロイ ECSのデプロイは通常以下の方式で行う 1. 新しいDockerイメージをビルドする 2. 新しいDockerイメージを利用するタスク定義のリビジョンを作成する 3. ECSサービスで使用するタスク定義を最新のリビジョンに更新する 4. ECSサービスがコンテナを置き換える
タスク定義とデプロイ ① Dockerイメージをビルド ② タスク定義の新リビジョンの作成 ③ ECSサービスのタスク定義指定を更新 ④ ECSサービスがタスクを置き換える Task
Definition Revision 10 Service Task(10) Image Image Revision 11 Task(10) Task(11) Task(11) Task Definition Revision 10 Service Task(10) Image Image Revision 11 Task(10) Task Definition Revision 10 Service Task(10) Image Image Revision 11 Task(10) Task Definition Revision 10 Service Task(10) Image Image Task(10)
実際の構成の例 ECSクラスター ECSサービス 起動タイプ ECSタスク (数) Dockerコンテナ prd-app prd-app Fargate
prd-app (4) - nginx - rails - datadog prd-api prd-api Fargate prd-api (4) - nginx - rails - datadog prd-admin prd-admin EC2 prd-admin (1) - nginx - rails - datadog prd-worker prd-worker Fargate prd-worker (2) - worker(sidekiq) - datadog ※ 実際に運用しているサービスの名前とは微妙に異なります
2.2. Fargate
Fargateとは? Fargateとは、ECSサービスに指定する起動タイプの1種 起動タイプにはFargateとEC2がある
起動タイプEC2 ECSサービスの起動タイプをEC2に設定するとタスクはECSクラスターに登録された EC2インスタンスのDockerデーモン上で実行される このEC2インスタンスは自前で用意しなければならない 1つのEC2インスタンス上でCPUやメモリが足りていれば複数のタスクを実行することが できる EC2インスタンス Task A Container
A Container B Task B Container C
起動タイプFargate Fargateはマネージドなコンテナ実行環境 起動タイプにFargateを指定した場合、タスクはFargate上で実行される FargateのスペックはCPUとメモリを指定でき、サイズに比例して料金がかかる Fargate Task A Container A Container
B Task B Container C Fargate
比較 Fargate EC2 スケーリング速度 速い EC2の起動の分遅い 管理コスト 低 高 EC2の管理も自前
コスト 低 デプロイ時のキャパシティ的に メモリの料金に無駄が出る ssh可能 (基本的に)不可能 可能
スケーリング速度 Fargateのほうが倍程度速い EC2の場合は インスタンスの起動→クラスターへ登録→イメージのpull→コンテナ起動という流れ Fargateの場合は ENIの設定→イメージのpull→コンテナ起動という流れ インスタンス起動はインスタンスタイプにもよるが、2分程度かかるが、FargateのENIの 設定は10秒程度で終わる
管理コスト EC2の方が管理対象が増える SRE的には令和の時代にEC2インスタンスの管理はやりたくない(個人の感想) EC2インスタンスのインスタンスタイプ設定、OS、スケーリング管理等がFargateに比べ ると余計に必要になる ECSタスクで利用するCPU、メモリとタスク数からEC2のインスタンスタイプを決定する 等の設計のコストも高い EC2にどのようにタスクを配置するか等も設計しなければならない (先日これをミスって503エラーを出してしまった) 一方でFargateはタスク1つ1つのCPU、メモリサイズを決めるだけで良い
コスト CPUやメモリサイズで見ると、EC2とFargateにそこまで大きなコスト差はない ただし、デプロイ設定によってはEC2が大きな損をすることになる デフォルト設定である、デプロイ時のコンテナが2倍起動する設定にした場合、通常起動 するタスクのCPUとメモリの2倍が収まるサイズのEC2インスタンスを用意する必要があ る これは、現在のCPU/メモリ使用量ではなく、タスクの最大のCPU/メモリ使用量がEC2上 に空いていなければタスクを起動しないというECSの特性に起因する この問題はデプロイ時に一時的にタスクの数が少なくなることを許容すれば回避可能
コスト Fargate EC2 Fargate Task A cpu: 256 mem: 512
EC2 cpu 512, mem: 1024 Task A cpu: 256 mem: 512 デプロイ中 デプロイ後 Fargate Task A cpu: 256 mem: 512 Fargate newTask A cpu: 256 mem: 512 Fargate newTask A cpu: 256 mem: 512 EC2 cpu 512, mem: 1024 Task A cpu: 256 mem: 512 newTask A cpu: 256 mem: 512 EC2 cpu 512, mem: 1024 newTask A cpu: 256 mem: 512 平常時にタスクの倍のスペックの EC2を用 意する必要があり、無駄コストとなる
ssh可能か 起動タイプEC2の場合は、EC2へssh→ `docker exec` でコンテナへ接続できる Fargateの場合は、マネージドサービスなのでssh接続ができない sshをSessionManagerに置き換えても同じ Twitterでこんな意見も見た
sshする運用を廃止して Fargateを使おう
とはいえ、現実は... 社内でよくある例 adminクラスターは起動タイプEC2でssh(SessionManager)接続できるようにしておき、 appクラスターはFargateにする adminのタスクはCPU/メモリ共に小さいし、タスク数も少ないのでEC2に余計にコストが かかる点も微々たるもの ただし、社内の最新のイケてるプロジェクトは完全Fargateのみである
余談:stgはEC2、prdはFargate→ダメゼッタイ 社内でよくある構成でした 理由は、昔Fargateにリザーブドプラン(料金を前払いして割り引きする仕組み)が無かっ たため(今はある) ここ半年で2件ほど、Fargateでしか発生しない不具合を踏んだケースが発生 1件はsassc-rubyのバグ 1件はEC2とFargateの構成差によるRole関連の見落とし 本番環境とステージング環境は最大限努力して同一の環境にしましょう
2.3. スペックとスケール
ECSのスペック ECSでスペックを指定できる箇所を起動タイプ別に以下に示す Fargate EC2 Task Fargate Container Container 必須 -
CPU - メモリ FargateはTaskのCPUとメモリ のスペックで確保される 任意 - CPU/メモリ - 予約メモリ EC2 Instance 必須 - インスタンスタイプ Task Container Container Task Container 任意 - CPU/メモリ - 予約メモリ 必須 - メモリ 任意 - CPU
注意点 • メモリ使用量100%になると、コンテナが落ちる ◦ dockerのOOM Killerが発動し、コンテナが落ちる ◦ 基本的にどのコンテナも必須なので、 1つのコンテが落ちたらタスク全体が落ちる設定が多い •
起動タイプEC2の場合、空きがないとタスクは起動しない ◦ タスクサイズ分のCPU/メモリの空きがEC2に無いと起動しない ◦ この空きは現在の使用量ではなく、タスクサイズで計算される ◦ 例:メモリ4GBのEC2上では、メモリ1.5GBのタスクは起動直後のメモリ消費が 100MBであっても、2 つまでしか起動できない
ECSのスケーリング 起動タイプFargateのオートスケーリングを設定できる箇所 タスクの数をスケール可能 スケーリングのトリガーはCPUとかメモリとか、CloudWatchで取得できる値ならなんでも Fargate Container Container Task Fargate Container
Container Task
ECSのスケーリング 起動タイプEC2のオートスケーリングを設定できる箇所 タスクの数とEC2インスタンスの数の両方をスケール可能 Container Container Task Container Container Task EC2
注意点:よくある失敗 元々の状態 EC2メモリ4GB + メモリ1.5GBのタスク1つ スケールアウトして下記の状態となった EC2メモリ4GB + メモリ1.5GBのタスク2つ この状態だと、空きメモリは
`4GB - 1.5GB * 2 = 1GB` しかない デプロイ時のmaxを200%にしていると、デプロイ時に新規にタスクが起動できないた め、デプロイがエラーになって終了する →起動タイプEC2の場合、EC2とタスクの両方のスケーリングを正しく設定する必要が ある(無駄コストを払わないようにこれを実現するのはかなり複雑なのでFargateを使お う)
2.4. ログ
ECSのログ ECSではDockerコンテナの標準出力がCloudWatch LogsというAWSのサービスへ送 信される 起動タイプEC2の場合、ssh接続しdockerコマンドを実行できるが、docker logsコマンド でコンテナのログを見ることはできないので注意
ログの見方① 直接CloudWatch Logsへ移動し確認する方法
ログの見方① 同じECSサービス→同じロググループへ出 力 コンテナ名がログストリームのprefixに設定さ れている
ログの見方② ECSの画面からコンテナを指定して、CloudWatch Logsを開くことも可能 クラスター→サービス→タスク→コンテナ→CloudWatchのログを表示
ログの見方③ ECSの画面上でもログを確認することができる クラスター→サービス→タスク→Logsタブ→コンテナを指定 ここだけログが降順で並ぶので注意
ECSにおけるログ出力設定の注意 標準出力と標準エラー出力の使い分けができない jsonにすると検索性がよくなる(らしい) CloudWatch Logsはログの量で課金されるので、ログレベルは `:info` にすることを徹 底していきたい
2.5. デプロイ
ECSのデプロイ デプロイの仕組みというよりは、デプロイ時に発生する有名な問題の話を紹介 デプロイ自体はタスク定義の項で紹介したように以下の流れで行われる • 最新のソースコードでDockerイメージを作成 • ECRにimageをpush • タスク定義に上記イメージを使用する新しいリビジョンを追加 •
ECSサービスで利用するタスク定義のリビジョンを最新に更新 • あとはECSが設定に基づき新しいタスクを起動し、古いタスクを停止 余談:上記処理はどこから実行しても良いので、GitHub Actionsからデプロイする仕組 みも実験中
問題:ECSデプロイ時にassetsの参照で404エラー デプロイしている最中にサービスにアクセスすると、jsやcss等のassets系のGETリクエ ストが一定確率で404エラーになる問題 何も対策せずに、デフォルトのECSのデプロイ設定でRailsをデプロイすると発生する
仕組み Task Container V1 Task Container V2 ① htmlを新バージョンのアプリか ら取得(1/2の確率で発生)
デプロイ中に新旧両方のバージョンが ロードバランサーに紐づくタイミングで発 生する ② htmlに記載されたcssを旧バー ジョンのアプリに取りに行く ③ 新バージョンのアプリの asset pipelineで作成されたcssは存在し ないので404を返す assets pipelineを使っているRailsが複数バージョン混 在するとエラーになるという当たり前の話 ELB
対策 メジャーな対策を2つ紹介する 現在社内ではどちらのパターンも存在しているが、今後は対策2の方を採用していく見 込み 対策1. assetsファイルをCloudFrontで配信 対策2. CodeDeployで一括でトラフィック切り替え
対策1. assetsファイルをCloudFrontで配信 Task Container V1 Task Container V2 /assets 等のパスはS3から取得す
るように設定 新バージョンをデプロイする直前 にassets系ファイルをアップロード する デプロイ中は、CloudFrontから新旧両方の バージョンのassetsファイルを取得できるよう にする方法 S3に無限にassetsが溜まっていかないよう に、デプロイの最後、旧バージョンのコンテナ が停止した後で、古い assetsファイルを消す CloudFront S3 Bucket
対策1. assetsファイルをCloudFrontで配信 Task Container V1 Task Container V2 ドメインを別にしている亜種パターンもある assets.example.com
example.com
対策1. のデメリット ロールバックができない ECSはタスク定義のリビジョンが残るため、本来であれば簡単な操作で1つ前のリビジョ ンにロールバックできる しかし、S3に前のバージョンのassetsファイルが無いため、ロールバックするとassets系 ファイルの取得がすべて404エラーになってしまう S3上に古いバージョンのassetsを残すようにすればよいが、コストが増えたり定期的に 消す仕組みの管理など複雑になりがち
対策2. CodeDeployで一括でトラフィック切り替え Task Container V1 Task Container V2 ELB Task
Container V1 Task Container V2 ELB CodeDeployというAWSサービスと連携してECSへデプロイすることで、新旧バージョン が混在する瞬間を発生させずに、トラフィックを一括で切り替える タスクがいくつあっても一括で新旧 のバージョンへの トラフィックが切り替わる
対策案2. のメリット ロールバックができる デプロイがCodeDeployに管理されるため、ECSサービスのタスク定義のリビジョン指定 ではなく、CodeDeployからロールバックを指示することになる とはいえ、CodeDeployのロールバックもシンプルなのでワンボタンでロールバックでき る 案1よりコストに優れる 案1はCloudFrontが必須だが、こちらは任意なので管理画面とかにも気軽に使える
備考:カナリアデプロイに関して カナリアデプロイを行う場合は、新旧両方のassetsファイルを配信する必要があります。 CodeDeployに備わっているカナリアデプロイの機能を利用する場合は、案1、案2とは 異なる構成を検討する必要があります。
Fin.