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
Deploy Rails apps in 2021
Search
Takumi Shotoku
May 28, 2021
Technology
7
9.4k
Deploy Rails apps in 2021
事業成長を加速させたエンジニアリングのウラ側
https://medpeer.connpass.com/event/211745/
Takumi Shotoku
May 28, 2021
Tweet
Share
More Decks by Takumi Shotoku
See All by Takumi Shotoku
Automatically generating types by running tests
sinsoku
3
11k
滅・サービスクラス🔥 / Destruction Service Class
sinsoku
8
2.5k
テストを書かないためのテスト/ Tests for not writing tests
sinsoku
1
260
ドメインの本質を掴む / Get the essence of the domain
sinsoku
2
310
"型"のあるRailsアプリケーション開発 / Typed Rails application development
sinsoku
10
2.8k
Let's get started with Ruby && Rails Tips
sinsoku
0
450
LTの敷居を下げる / Lower the threshold for LT
sinsoku
1
380
CircleCIの高速化🚀 / CircleCI faster
sinsoku
3
1.4k
Railsアプリと型検査 / Rails app and type checking
sinsoku
5
1.6k
Other Decks in Technology
See All in Technology
【NoMapsTECH 2025】AI Edge Computing Workshop
akit37
0
220
react-callを使ってダイヤログをいろんなとこで再利用しよう!
shinaps
2
260
AWSで始める実践Dagster入門
kitagawaz
1
680
開発者を支える Internal Developer Portal のイマとコレカラ / To-day and To-morrow of Internal Developer Portals: Supporting Developers
aoto
PRO
1
470
💡Ruby 川辺で灯すPicoRubyからの光
bash0c7
0
120
Webアプリケーションにオブザーバビリティを実装するRust入門ガイド
nwiizo
7
860
La gouvernance territoriale des données grâce à la plateforme Terreze
bluehats
0
190
「どこから読む?」コードとカルチャーに最速で馴染むための実践ガイド
zozotech
PRO
0
540
250905 大吉祥寺.pm 2025 前夜祭 「プログラミングに出会って20年、『今』が1番楽しい」
msykd
PRO
1
980
品質視点から考える組織デザイン/Organizational Design from Quality
mii3king
0
210
Codeful Serverless / 一人運用でもやり抜く力
_kensh
7
450
2025年夏 コーディングエージェントを統べる者
nwiizo
0
180
Featured
See All Featured
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
113
20k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
30
9.7k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.9k
What's in a price? How to price your products and services
michaelherold
246
12k
Rails Girls Zürich Keynote
gr2m
95
14k
Building Adaptive Systems
keathley
43
2.7k
The Invisible Side of Design
smashingmag
301
51k
Building a Modern Day E-commerce SEO Strategy
aleyda
43
7.6k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
BBQ
matthewcrist
89
9.8k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
46
7.6k
Transcript
Deploy Rails apps in 2021 事業成長を加速させたエンジニアリングのウラ側 2021/05/28 1
自己紹介 • 名前: 正徳 巧 • 会社: メドピア株式会社 • 所属:
CTO室SRE • GitHub: @sinsoku (画像右上) • Twitter: @sinsoku_listy (画像右下) よろしくお願いします。 2
最近の業務 • AWSインフラの改善 • デプロイの改善 • Railsアプリのコードの改善 • セキュリティ関連 3
ソフトウェアのデリバリ https://blogs.vmware.com/management/2020/03/vi-admin-to-devops.html 4
LeanとDevOpsの科学 • デプロイの頻度 • 変更のリードタイム • MTTR(平均修復時間) • 変更失敗率 5
どのくらいのデプロイ頻度を目指す? 6
7
8
9
10
CircleCIのレポート 20171 • メインラインブランチの安定性 • デプロイ時間 • デプロイ頻度 1 https://circleci.com/landing-pages/assets/2017-VelocityReport-
Updated-070219_JA.pdf 11
デプロイ時間 デプロイ時間は概ねコントロールされており、80.2%の組織が15 分以内にデプロイを行っています。特にデプロイ時間の短い組織 (95パーセンタイル) では2.7分、中央値は7.6分です。それ以降 はロングテールの分布が続き、下位5パーセンタイルの組織のデ プロイ時間は30分です。 https://circleci.com/landing-pages/assets/2017-VelocityReport-Updated-070219_JA.pdf 12
デプロイ頻度 全組織の75%が、最も活発なプロジェクトにおいて週に12回以下 の頻度でデプロイを行っていました。上位の組織 (95パーセンタ イル) では、メインラインブランチを週に32回デプロイしていま す。これは中央値の5倍以上、下位5パーセンタイルの約24倍で す。 https://circleci.com/landing-pages/assets/2017-VelocityReport-Updated-070219_JA.pdf 13
更にデプロイ頻度の多い会社の事例 14
GitHubにおける継続的デリバリー2 2 https://speakerdeck.com/yuichielectric/how-github-builds-and-deploy-software 15
GitHub Flow3 3 https://guides.github.com/introduction/flow/ 16
GitHub Flow3 Deploy With GitHub, you can deploy from a
branch for final testing in production before merging to main. つまりmainブランチは常に安定版になっており、問題が起きたら mainブランチをデプロイすることでロールバックできる。 3 https://guides.github.com/introduction/flow/ 17
GitHubの週辺りのデプロイ数(2015年) https://speakerdeck.com/yuichielectric/how-github-builds-and-deploy-software 18
GitHubのデプロイの変化 • 社員数の増加(588人 => 1248人) • デプロイロック、デプロイキューの混雑 • リリーストレインの導入 •
複数のPRを1つのデプロイにまとめる 19
GitHubの週辺りのデプロイ数(2019年) https://speakerdeck.com/yuichielectric/how-github-builds-and-deploy-software 20
デプロイまとめ 上位の組織 • 時間: 3分程度 • 頻度: 週に30回程度 すごい会社(GitHub) •
時間: ? • 頻度: 週に300回以上 21
少ないデプロイでは競合に勝てない時代 22
デプロイ頻度を増やすために • デプロイの改善 • 半年前のMedPeerのデプロイは15〜17分 • デプロイ頻度は月20〜25回程度 • カナリアデプロイ 23
MedPeerのブランチ戦略 24
デプロイパイプライン GitHub 1. リリースPRのマージ CodePipeline 1. CodeBuildで ! のビルド 2.
CodeBuildで db:migrate 3. デプロイ 25
デプロイパイプライン GitHub 1. Actionsで ! のビルド4 2. リリースPRのマージ CodePipeline 1.
CodeBuildで db:migrate 2. デプロイ 4 ビルドの高速化についてはテックブログ参照。https://tech.medpeer.co.jp/entry/2021/05/28/180408 26
リリースPRの自動作成 • git-pr-release を利用5 • 毎日10:30, 14:30に実行 • 手動で実行も可能 5
https://github.com/x-motemen/git-pr-release 27
Web上から実行できる 28
デプロイ頻度の計測 $ git log --merges \ --first-parent \ --since='2019-1-1' \
--format='%cd' \ --date='format:%Y-%m' origin/master \ | uniq -c masterへのマージ == デプロイ回数 29
30
デプロイ頻度を増やすには • ✅ デプロイの改善 • 15〜17分 " => 約7分 #
• 月20〜25回 => 月45〜50回 • カナリアデプロイ • 死活監視 31
MedPeerのRails appを動かすAWS構成 32
AWS CodeDeploy ECSの線形デプロイ、カナリアデプロイをサポートしている。6 • カナリア: 最初の増分で10%、残り90%を5分後にシフト • カナリア: 最初の増分で10%、残り90%を15分後にシフト •
線形デプロイ: トラフィックの10%を毎分シフト • 線形デプロイ: トラフィックの10%を3分ごとにシフト 6 太字部分のカスタマイズが可能。 33
カナリアデプロイの概要 34
CodePipeline vs GitHub Actions 35
36
GitHub Actionsの利点 • AWS for GitHub Actionsが便利 • Railsエンジニアが触りやすい •
! YAML • " HCL(Terraform) • 1つのサービス(GitHub)で完結すると楽 37
新しい開発フローの設計 1. リリースPRを作る 2. デプロイ承認後、canary環境にデプロイして動作確認 3. 問題がなければ5分後にproduction環境にもデプロイ • mainブランチに自動マージ(=mainは安定版) 4.
問題が起きたらワークフローをキャンセル • CodeDeployでロールバック 38
社内サービスで動作検証 39
実際に作ったワークフロー 40
db:migrate の実行 • db/migrate/* のdiffで要否を判定する • ecs:RunTask でECS上でワンショットのタスクを実行する • sinsoku/amazon-ecs-run-task-definition
のactionを作成7 7 https://github.com/sinsoku/amazon-ecs-run-task-definition 41
db:migrate の実行 steps: - uses: actions/checkout@v2 with: fetch-depth: 2 #
db:migrate Λ͢Δඞཁ͕͋Δ͔அ͢ΔͨΊɺલճͷmasterϒϥϯνͱͷdiffΛऔಘ͢Δɻ - name: Diff files in db/migrate id: migrate run: | MIGRATE_SIZE=$(git diff --name-only @^ -- db/migrate | wc -l) echo "::set-output name=size::$MIGRATE_SIZE" # ్தུ - name: Run a task on Amazon ECS if: steps.migrate.outputs.size != '0' uses: sinsoku/amazon-ecs-run-task-definition@v1 with: task-definition: ${{ steps.update-task-def-cmd.outputs.task-definition-arn }} container: ${{ env.ECS_CONTAINER }} command: '["bin/rails", "db:migrate"]' service: ${{ env.ECS_SERVICE }} cluster: ${{ env.ECS_CLUSTER }} 42
デプロイ(canary) steps: - name: Deploy to Amazon ECS id: code-deploy
uses: aws-actions/amazon-ecs-deploy-task-definition@v1 with: task-definition: ${{ steps.task-def-web.outputs.task-definition }} service: ${{ env.ECS_SERVICE }} cluster: ${{ env.ECS_CLUSTER }} codedeploy-appspec: appspec.yaml codedeploy-application: example-app codedeploy-deployment-group: example-app-dg wait-for-service-stability: false - name: Wait for the canary environment to deploy run: | names=$(aws deploy get-deployment --deployment-id ${{ steps.code-deploy.outputs.codedeploy-deployment-id }} \ --query 'deploymentInfo.loadBalancerInfo.targetGroupPairInfoList[].targetGroups[].name' \ --output text) arns=$(aws elbv2 describe-target-groups --names $names \ --query 'TargetGroups[].TargetGroupArn' \ --output text) for arn in $arns; do aws elbv2 wait target-in-service --target-group-arn $arn done 43
デプロイ(production) production: needs: canary runs-on: ubuntu-latest timeout-minutes: 15 environment: name:
production url: https://example.com concurrency: deployment steps: - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-1 - name: Wait a deployment run: aws deploy wait deployment-successful --deployment-id ${{ needs.canary.outputs.deployment-id }} 44
ロールバック rollback: needs: [canary, production] if: cancelled() && needs.canary.outputs.deployment-id runs-on:
ubuntu-latest timeout-minutes: 10 steps: - name: Stop a deployment run: aws deploy stop-deployment --deployment-id ${{ needs.canary.outputs.deployment-id }} --auto-rollback-enabled - name: Run a task on Amazon ECS if: needs.canary.outputs.migrate-size != '0' uses: sinsoku/amazon-ecs-run-task-definition@v1 with: task-definition: ${{ needs.canary.outputs.task-definition-arn }} container: ${{ env.ECS_CONTAINER }} command: '["bin/rails", "db:rollback", "STEP=${{ needs.canary.outputs.migrate-size }}"]' service: ${{ env.ECS_SERVICE }} cluster: ${{ env.ECS_CLUSTER }} 45
リリースPRのマージ merge: needs: production runs-on: ubuntu-latest timeout-minutes: 5 steps: -
name: Merge a release PR env: GITHUB_TOKEN: ${{ secrets.MEDPEER_GITHUB_TOKEN }} run: gh pr merge ${{ github.event.number }} --merge --repo ${{ github.repository }} 46
デプロイ頻度を増やすには • ✅ デプロイの改善 • 15〜17分 " => 約7分 #
• 月20〜25回 => 月45〜50回 • $ カナリアデプロイ • 死活監視 47
次はMedPeerに導入して、 もっとデプロイ頻度を増やすぞ! 48
この環境を体験したい人、一緒に作りたい人 https://medpeer.co.jp/recruit/ 49