AWS SUMMIT TOKYO 2019 参加レポート (I2-05)コンテナ移行ってこんなに大変？ ～「家族アルバム みてね」を支えるインフラの裏側～

株式会社いい生活 [.NET アプリケーションチーム ](https://jobs.qiita.com/employers/e-seikatsu/development_teams/112) の中村です。
普段の業務は.NET＋Windowsサーバの環境でバッチ処理系のシステムの開発、運用を行っています。
今年の初めに、担当しているシステムの一つをAWS環境に移設し、AWSのドキュメントやブログなどを参考にしながら日々格闘しています。

システム概要については、弊社セッション資料(スライド18-19)がありますので、ご興味があれば、ぜひご覧ください。
[(L2-06)AWSを最大限活用した不動産業向けB2Bサービスのクラウドシフト事例](https://speakerdeck.com/akipom/awswozui-da-xian-huo-yong-sitabu-dong-chan-ye-xiang-keb2bsabisufalsekuraudosihutoshi-li?slide=18)

今日は 2019/6/12(水)～14(金) の期間で開催された「AWS Summit Tokyo 2019」の2日目
「コンテナ移行ってこんなに大変？ ～「家族アルバム みてね」を支えるインフラの裏側～」
に参加した内容をメモ書きで記載します。

## 概要
スピーカー(敬称略)：株式会社ミクシィ　みてね事業部 開発グループ　SRE　清水 勲

> ミクシィが提供する家族向け写真・動画共有アプリ「家族アルバム みてね」は、2019年初めに利用者数400万人を突破し、世界中の家族に快適にご利用いただけるよう、アプリケーションやインフラの改善を続けています。サービスのリリース当初からAWS OpsWorksを活用してきましたが、よりスケールしやすく、イミュータブルなコンテナ環境へ移行するためにAmazon EKSを採用し、移行作業を進めてきました。SREチームが中心となって移行を進める際に工夫した点や、様々な苦労、得た知見を共有いたします。

https://aws.summitregist.jp/public/session/view/247

## 参加理由
2019年1月に長くオンプレミスの環境で運用していたシステムをAWS環境へ移設し、
半年ほどクラウド環境での開発、運用を試行錯誤していますが、現在は以前のシステムをほぼそのままAWSへ移設した状態で、
これからコンテナやサーバレスなアーキテクチャをもっと活用してクラウド環境に適したシステムへシフトして行きたいと考えているため、
実際に取り組んでいる他社の事例を聞いてポイントや移行のヒントを得たいと思い参加しました。

## 以下 参加メモ
## サービス紹介
### 家族アルバム みてね
https://mitene.us

* 子供の写真や動画を無料・容量無制限で高速アップロード
* 日々の成長の様子をリアルタイムに共有
* 2015年リリース
* 国内外の利⽤者数 500万⼈以上
  * App Store レビュー 4.7
  * Google Play ストア レビュー 4.7
* 海外での受賞歴もあり
  * 2019 THE WEBBY AWARDS 受賞
  * 2019 NATIONAL Parenting Product(NAPPA) AWARDS 受賞

### みてねプレミアム
https://mitene.us/premium

* 2019年4月リリース
* 月額課金型の有料プラン
* ブラウザから写真、動画のアップロード可能
* 1秒動画を毎月配信（通常は3ヶ月毎）
* 動画アップロードの時間制限を延長（3分⇒10分）

## システム構成
### クライアント
* iOS
* Android
* Webブラウザ

### サーバー
* Ruby on Rails
  * API
  * Web UI
  * Sidekiq（ジョブキュー）
  * Whenever（Cron）

## 利用しているサービス
* 構成管理
  * [OpsWorks](https://aws.amazon.com/jp/opsworks/) （Chef や Puppet のマネージド型インスタンスを利用できる）
* 画像、動画配信
  * CloudFront
  * S3
* データストア
  * Aurora
  * ElastiCache
* ログ転送、解析
  * Kinesis Data Firehose
  * Athena
  * EMR
  * AWS Batch
* モニタリング
  * NewRelic
  * CloudWatch
  * Grafana

## いままでの課題
### コンテナ環境へ移行することで解決できるか？
* オートスケールに時間がかかる
* 問題が起きたときにデバッグしづらい
* Chefのバージョンアップが難しい
  * 仕様上OpsWorksのスタックごと入れ替え
* EC2リソースを使い切るための調整が難しい
* スポットインスタンスの活用が出来ていない⇒コスト削減したい
* SSH前提のオペレーション
  * オペレーションコストが高い、セキュリティ面で考慮が必要

## コンテナ移行によって解決すること
### 技術面
* OSに依存しないポータビリティ性
  * どこの環境でも簡単にイメージを配置できる
* ディスポーザブルなインフラの実現
  * 高速なデプロイ
  * SSHの機会を減らす
* 従来のVMより効率的なハードウェアリソースの活用
  * 空きリソースを活用できる
* さまざまなサービスがコンテナ前提
  * AWS CodeBuild、AWS Batch、SageMakerなど
* 新技術の習得、トレンドへの追従、新技術に興味があるエンジニアの採用

### ビジネス面
* ユーザーにより快適に使ってもらう
  * オートスケール速度向上
  * 耐障害性向上
* コスト削減
  * コンピュートリソースの効率化
  * スポットインスタンスの活用（コンテナに向いている）
* 新機能開発、不具合修正速度の向上
  * より事業にフォーカスできる
  * デプロイが速い
  * 環境構築しやすい

## OpsWorksからコンテナ環境へ
* OpsWorksはECSと連携できるらしい
  * あえてAWS OpsWorksを使う必要もない
* Chefからの脱却
* デプロイ速度向上
* コスト削減（スポットインスタンスの活用）
* 新しい技術の導⼊促進
* ECS or EKS

## ECS vs EKS
### ECS
* Fargateが使える
* シンプル（学習コスト低い）
* タスク単位のIAMロール
* AWS独自サービス

### EKS
* Fargateはまだ使えない
* 機能が豊富だが学習コストは高い
* 世の中のKubernetesのノウハウやツールをそのまま導入できる
* Kubernetesへの準拠性が認証されている

### Kubernetes
* 今最も注目されているコンテナ技術
* 2014年 GoogleがOSSとして公開
* CNCFプロジェクトの1つ
* 「KubeCon」の参加者は年々増加

## EKSの利点
* マネージドなコントロールプレーン
  * 自前でKubernetesを構築して運用するのは大変なことが多い
  * AWSが管理してくれるので運用の時間を減らしてアプリに注力
* Kubernetesのエコシステム
  * ノウハウやツールが豊富
  * コミュニティの既存のプラグインやツールが使える
  * プラグインやツールの独自開発で課題解決も可能
* IAMとの連携
  * 安全にAWSのリソースを扱うことができる
* Amazon CloudWatch Container Insights
  * [2019年５月プレビュー開始](https://aws.amazon.com/jp/about-aws/whats-new/2019/05/cloudwatch-container-insights-for-eks-and-kubernetes-preview/)
* スポットインスタンスとの組み合わせ
  * コスト最適化
* [SIG AWS](https://github.com/kubernetes/community/blob/master/sig-aws/)
* 以上を踏まえてEKSを選択

## コンテナ環境全体のデザイン
### AWSアカウント
* いままでは1つのAWSアカウントで運用してきたが、本番環境、ステージング環境、開発環境でAWSアカウントを分ける
* [「AWSにおけるマルチアカウント管理の手法とベストプラクティス」](https://d0.awsstatic.com/events/jp/2017/summit/slide/D4T2-2.pdf)
  * 完全なセキュリティとリソースの分離
  * アカウント毎に行える課金管理
  * 問題発発生の影響範囲の縮小化
* マルチアカウントは必須ではないが複雑なIAMポリシーからの脱却、Terraform利用による構築の効率性向上を求めて採用

### EKSクラスター
* 機能（サービス）ごとに分ける

## Chef Cookbookの資産からDockerfileへ
* Dockerfileを書く
* CodeBuildでイメージをビルド
  * GitHubと連携して自動ビルド
* ECRへプッシュ

## Ruby on Railsプロジェクトのコンテナ化
* Ruby（rbenv/ruby-build）のイメージ作成
* Rubyイメージをベースに必要パッケージや、RubyGemsをインストールしたイメージの作成
* ソースコードを入れたイメージの作成

### Point
* ビルドに時間がかかる部分を分離
* BuildKitを利用したビルドの高速化
  * 並列化、キャッシュ利用など
  * CodeBuildでDocker 18.09以降の環境を使う
* デプロイをより早くするために、コンテナイメージを小さくしていく工夫が必要（依存ライブラリが多いと大変）

## ローカル開発環境でイメージの動作検証
### ローカルでの開発環境の構築
* macOSやLinux環境でコンテナイメージを動作させる
* すべての開発者に使ってもらう
  * 構成や手順の理解をチーム内で深める⇒属人化を防ぐ

### コンテナイメージの動作確認
* Docker Composeを使って複数のイメージとの連携
* 環境変数の検証
* ユニットテスト（RSpec）
* macOSでのDocker利⽤はIO処理が遅い問題があるので注意

## AWSアカウントをマルチアカウントに
### AWS Organizationsを使う！

## Terraformによる適用環境の構築
* Infrastructure as a Codeの実現
* Terraformを使う
  * 利用実績が豊富、OSSで開発が活発
  * 他プロジェクトで利用経験があった
* GitHub + CodeBuildの連携
  * TerraformのCLIを手動実行しない環境を作る
  * CodeBuildプロジェクトの作成
  * GitHubと連携（Webhook）
    * Pull Request作成時に terraform plan
    * レビューの実施
    * Pull Requestマージで terraform apply
 
各AWSアカウントで必要なリソースの作成は全てTerraformで構築

## EKSクラスターの作成
* AWS CLIで作成
* [eksctl](https://eksctl.io/)でも作ることができる
  * CloudFormationとの連携を前提としていて、Terraformとの相性が悪そうだったため使っていない（実際はそうじゃないかも？）

* EKSクラスターを作る上でのハマりポイント
  * 作成するときに使われた IAM エンティティ (ユーザーまたはロール) が管理者としてKubernetes RBAC認証テーブルに追加される
  * そのIAMエンティティだけがkubectlを使用してKubernetes APIサーバーにアクセスできる

## EKSワーカーノードの作成
* Auto Scaling Groupを使う
* Terraformで作る
* [AWS EKS Introduction](https://learn.hashicorp.com/terraform/aws/eks-intro) を参考にすると良い
* Podのスケジューリングの制約の設定が可能
  * EKS最適化AMIのbootstrap.shのオプション指定がわかりづらいので、 https://github.com/awslabs/amazon-eks-ami/blob/master/files/bootstrap.sh を読むのがオススメ

## マニフェストの適用
* kubectlコマンドの実行環境をどうするか
  * 手元のPCではやりたくない（セキュリティ上）
* 最初はAWS Cloud9を試した
  * IAMを使った権限の制御ができる
  * 無操作によるサスペンド機能でのコスト削減
  * ブラウザのショートカットと競合して操作しにくい問題があった
  * 当時、東京リージョンではまだ使えなかったため、シンガポールリージョンで利用していたがレイテンシの問題があった
* セッションマネージャーの利用に変更
  * EC2にSSHレスでCLIコンソールが利用できる
  * IAMを使った権限の制御ができる
  * AWS CLIから簡単にアクセス可能

## いまできていること
* 複数AWSアカウントによる環境の分離
* Terraformによる構築のコード化、自動化
* セッションマネージャーを使ったkubectl実行環境
* EKSを使った開発環境の構築

## 現在進行中
* 本番環境の構築
  * 開発環境のTerraformのコードをほぼそのまま利用できる
* 本番環境の移行
  * デプロイ手順や運用
  * チーム内のノウハウ共有、ドキュメント化
  * 障害時のオペレーション
  * EKSクラスタのアップデート手順（利用する上で避けられない）
  * 属人化しないようにノウハウの共有、手順化が大事

## まとめ
* なぜコンテナが必要か、正しい理解が必要
  * コンテナ移⾏で課題解決ができるかどうかをよく考える
* コンテナに関する技術領域は広く、習得は簡単ではない
  * ノウハウの横展開が大事
* コンテナ移⾏によって得られたもの
  * ポータビリティ性の高いディスポーザブルなインフラ
  * 新たな技術、ノウハウ
  * １から構築する手順の再確認ができた、インフラに関する情報の整理ができた
* コンテナ移行によってこれから期待できること
  * 高速にスケーラブルなインフラ
  * コスト削減
  * 開発速度の向上（事業の成長のスピードアップにつながる）
* Dockerfileの書き方の工夫
  * 世の中にあるDockerfileを参考にするのがオススメ
  * ビルド時間の短縮につながる
* 複数のAWSアカウント運用
  * AWS Organizationsは便利
  * ただし管理対象が増えるのでInfrastructure as a Codeが大前提
* EKSの進化に追従すること
  * クラスターはアップデートし続ける必要がある
  * 最新から3つ古いバージョンでのクラスタ作成ができなくなる
  * 検証環境でアップデートの検証を十分に行う

## 所感
* コンテナ移行で解決されること、難しいところ、工夫するポイントなど、実際に今取り組んでいる話が聞けて、コンテナ移行に対してイメージが持てたのは良かった。
* 特に下記の点が参考になりました。
  * 現在のシステムの課題整理
  * 何を解決したくてコンテナ移行したのか
  * 採用したサービスのどこにメリットを感じたか
* 他のセッションでも同じようなニュアンスの話がありましたが「（自分たちに）なぜコンテナが必要か」について正しい理解を持つことが必要だなと思いました。
  * インフラ、ミドルウェアのコスト下げたい
  * オペレーションコストを下げたい
  * スケーラビリティを高めたい
  * デプロイを自動化したい
  * オフショア開発を効率化するために実行環境のポータビリティ性を得たい
  * ・・・など、まだあまり考えは纏まっていませんが変化出来る環境を手に入れるためにもコンテナ化が必要かなと感じています。
* コンテナ移行にあたってAWS Organizationsでマルチアカウント運用することを結構押していたのが個人的に印象に残りました。
  * 弊社のAWS環境が[サーバープラットフォームチーム ](https://jobs.qiita.com/employers/e-seikatsu/development_teams/24)の苦労のおかげで最初からマルチアカウント運用出来ている幸せに感謝すべきだなと思っています。
  * 弊社セッション資料(スライド16)に概要があります。 [(L2-06)AWSを最大限活用した不動産業向けB2Bサービスのクラウドシフト事例](https://speakerdeck.com/akipom/awswozui-da-xian-huo-yong-sitabu-dong-chan-ye-xiang-keb2bsabisufalsekuraudosihutoshi-li?slide=16)

## 最後に
株式会社いい生活では一緒に働く仲間を募集しています。