ランサーズ等のサービスを開発・運用する中で得た知識やノウハウを紹介しています。

Labels:  AWS, CircleCI, Docker, ECS/Fargate 投稿者:adachin

グループ会社のインフラをECS/Fargateに移行して振り返る

皆さん元気ですか!?SREチームの@adachin0817です。去年から行っていた移行プロジェクトで、グループ会社である、シクロマーケティング株式会社の「ミギウデ」をさくらVPSからAWSへ移行しました。今回、移行背景やECS/Fargateでのコンテナ運用について簡単にご紹介と振り返りを行ってみたいと思います。


なぜAWSへ移行するのか

AWSへ移行すると冗長性の担保などが挙げられますが、一番は開発環境やインフラなど、すべてランサーズに統一させるということが第一の目的です。それに伴い、ミギウデ自体のサービスがシンプルなインフラ構成ということもあり、インフラ運用の手間をなくしたいということから、ECS/Fargateで初の外部サービスとしてコンテナ運用にチャレンジしてみようとなりました。

目的とコンテナ化にするメリット

・内部統制対応
・S3、RDSを利用したバックアップ
・CloudWatchLogs+αを利用したログの保存
・冗長化による稼働率の向上
・開発効率のアップ
・共通開発環境の構築
・リリースの属人化の排除
・GitHubと連動してリリース(人件費削減)
・運用効率のアップ
・Immutableなサーバーの運用
・タスク単位で自由に割当のリソースが変更できる
・スケールアウトのしやすさ

まずは開発環境から紹介していきましょう。


開発環境

・構成

$ tree dev
dev
├── README.md
├── cyclo-app
│    ├── Dockerfile
│    ├── gemrc
│    ├── nginx
│    │   ├── app.conf
│    │   └── nginx.conf
│    └── supervisor
│         ├── app.conf
│         └── delayed_job.sh
├── docker-compose.yml
├── elb
│   ├── Dockerfile
│   ├── h2o
│   │   ├── conf.d
│   │   └── dev.cyclo-creativecloud.com.conf
│   │   └── h2o.conf
│   └── service.sh
└── mysql
    ├── Dockerfile
    ├── mysql_init.sh
    ├── mysqld.cnf
    └── service.sh

・docker-compose.yml

version: '2'

services:
  elb:
    build: ./elb
    image: cyclo-elb
    hostname: elb
    networks:
      lancers:
        ipv4_address: xx.xxx.xx.xx
    extra_hosts:
      - "dev.cyclo-creativecloud.com:xx.xxx.xx.xx"
    container_name: cyclo-elb-xx-xx
    ports:
      - 80:80
      - 443:443
  app:
    build: ./cyclo-app
    image: cyclo-app
    hostname: cyclo-app
    networks:
      lancers:
        ipv4_address: xx.xxx.xx.xx
    extra_hosts:
      - "dev.cyclo-creativecloud.com:xx.xxx.xx.xx"
    container_name: cyclo-app-xx-xx
    volumes:
      - ~/www/app:/var/www/app/
  mysql:
    build: ./mysql
    image: cyclo-mysql
    hostname: mysql
    networks:
      lancers:
      ipv4_address: xx.xxx.xx.xx
    container_name: cyclo-mysql-xx-xx
    ports:
      - 3306:3306

networks:
  lancers:
  external: true

・ランサーズ開発環境

 

開発環境ですが、リバースプロキシとして使うELB(H2O)コンテナ、App(Rails)、MySQLコンテナの3つで動作しています。これにより、AWSやランサーズの開発環境(上記図)と同じ構成に仕上がることができました。

このサービスはRailsでできているということもあり、bundle install はコンテナにログインしてから実行しています。また各アプリケーションの起動はSupervisorで管理しました。また、Dockerはプロセスがフォアグラウンドで動いてないと、コンテナが終了するため、フォアグラウンドで実行するように注意しましょう。


・cyclo-app/supervisor/app.conf


[supervisord]
nodaemon=true

[program:app]
command=bundle exec unicorn_rails -c config/dev_unicorn.rb -E development
autostart=true
autorestart=true
stopsignal=TERM
user=root
directory=/var/www/app/
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:delayed_job]
command=sh /etc/supervisor/conf.d/delayed_job.sh
autostart=true
stopsignal=TERM
user=root
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0

[program:nginx]
command=/usr/sbin/nginx -g "daemon off;"
autostart=true
autorestart=true
stopsignal=TERM
user=root
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:sshd]
command=/usr/sbin/sshd -D
autostart=true
autorestart=true
stopsignal=TERM
user=root


Stg/本番環境

・Stg

・本番環境

・Docker(Stg/Prd)

$ tree
├── prd
│   └── cyclo-app
│       ├── Dockerfile
│       ├── README.md
│       ├── common
│       │   └── prompt.sh
│       ├── gemrc
│       ├── nginx
│       │   ├── app.conf
│       │   └── nginx.conf
│       └── supervisor
│           ├── app.conf
│           └── delayed_job.sh
└── stg
    └── cyclo-app
        ├── Dockerfile
        ├── README.md
        ├── common
        │   └── prompt.sh
        ├── gemrc
        ├── nginx
        │   ├── app.conf
        │   └── nginx.conf
        └── supervisor
            ├── app.conf
            └── delayed_job.sh

Stgと本番環境はすべてTerraformでインフラコード化をしています。これによりStg環境で一度作ってしまえば、本番環境構築に工数がかかることなく、設定変更時のミスが減ります。RDSAuroraを使い、コンテナのログはすべて標準出力をしてCloudWatch logに出力しています。各ログは今までLambdaを利用してS3に保存していましたが、Pythonのバージョンアップ対応でメンテをしたくないことから、今回はAmazon Kinesisを利用しました。他にもAppコンテナ以外にコマンドでRDSへ接続、aws cliの利用や開発者がrails consoleを使いたいため、Appコンテナとまったく同じコンテナであるdevopsコンテナを作成しました。このコンテナはランサーズの踏み台サーバーからSSHでログインできるようにVPC Peeringしています(下記図より)。SSMのセッションマネージャーもありますが、手軽に踏み台からSSHしたいということから、今回はこのような構成にしました。ちなみにECSのタスク定義ですが、AppコンテナはSupervisorで起動し、devopsコンテナはフォアグラウンドでSSHが起動するように制御しています。バッチは元々Railsのwheneverを入れて、schedule.rbファイルで管理していましたが、 ECS Scheduled Tasksを使って実装しました。監視はDatadogを使って、コンテナ内のCPU,メモリーなどのリソースと外形監視を行っています。

・VPC Peering

・コンテナデプロイの流れ

コンテナのデプロイはCircleCIで実装しました。GitHubdevelopブランチにマージするとStgが反映され、masterブランチにマージすると本番が反映されます。CIrspecCDCircleCIのOrbsを利用しており、Orbsがなかった頃はecs-deployを使ってシェルスクリプトを使っていましたが、簡単にDockerfileのbuild、ECRへpushECSリビジョンの更新、サービスタスク定義の更新、DBマイグレーションまで可能になりました。今までCapistranoによってサービスのリリースを行っていましたが、CircleCIによってリリースフローを確立できました。

移行プロジェクトと振り返り

今回3社合同で行われた移行プロジェクトですが、SREチームでコンテナの設計、デプロイなどを実装し、チームの皆様にフォローして頂きつつ、開発チームと連携してサーバーサイドの動きなどをヒアリングしながら進めていきました。また、リモートワークが当たり前になってきた頃には、とにかく通話してコミュニケーションを取るように心がけました。最後にチームで良かったところ、悪かったところを振り返ってみます。

Keep

・モダン技術へのチャレンジをやりきれた
・初めて外部サービスとしてコンテナ運用を行うことができた
・RailsでのECS/Fargateでの知見が高まった
・メンテナンス時にトラブルなく移行できた
・CircleCIのOrbsを使ったCI/CDの知見
・今後他サービスでのCI/CDの検証となった
・Datadogをサイドカーコンテナとして動かした際の知見
・コンテナの監視検証となった
・バッチ置き換えの検証となった
・内部統制対応

・ログの取得
・冗長性の確保
・データベースのバックアップが取れている
・リリースフローを確率できた

Problem

・当初の移行スケジュールが伸びてしまった
・開発環境が不十分なできになっていた
・コンテナの設計とやり直しに時間かかりすぎていた
・突発的なエラーにも時間かかりすぎていた
・デプロイの実装に時間かかりすぎていた

Try

・ECSの他サービスへの適用
・移行スケジュールとタスクを最初から明確にする


まとめ

今回外部サービスとしてコンテナ運用は初めてのチャレンジということもあり、やりきれて非常にいい経験となりました!今後はこの知見を活かしてランサーズもFargate化を計画をしていますので、その時はまたブログします。

※余談
今回の移行プロジェクトで会社で表彰頂きました!ありがとうございました!!

ランサーズではサービスを成長させてくれるエンジニア、デザイナーを募集しています!
ご興味がある方は、以下URLよりご応募ください。


【中途採用】
サービスリードエンジニア
テックリード(アーキテクト)
フロントエンドエンジニア
サーバーサイドエンジニア
業務エンジニア(社内システム基盤・基幹システム)

【インターン・学生バイト】
19新卒対象サマーインターン
エンジニアインターン

その他採用情報

関連記事

PHPカンファレンス福岡 2017に登壇しました

インフラエンジニアの金澤です。 2017/06/10(土)に、PHPカンファレンス福岡に登壇させていただきました。 今回、30分枠とLT枠(5分)の2枠を採択していただきました。 登壇内容 CakePHP 1.3 + PHP 5.3 → CakePHP 3 + …

PHP, CakePHPバージョンアップに向けてCIで品質を担保・向上していく

こんにちは、エンジニアの上野です。 今回はソース例や実際のサンプルソースを交えながら 「PHPバージョンアップに向けてCIで品質を担保・向上していく」と題してlancers.jp本体に導入しているCircleCIでの取り組みについてご紹介します。 導入背景 P …

thumbnail
AWSのEC2 API Toolsをインストールなしで利用する方法

こんにちは、ランサーズ インフラ担当のkeiです。 本日は、EC2 API Toolsをインストール作業をすることなく利用する方法をご紹介します。 ランサーズでは、試験環境から本番環境までAWS上でサーバ運用をしており、 先日、Amazon様の事例紹介ページに …