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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Takumi Shotoku
May 28, 2021
Technology
9.6k
7
Share
Deploy Rails apps in 2021
事業成長を加速させたエンジニアリングのウラ側
https://medpeer.connpass.com/event/211745/
Takumi Shotoku
May 28, 2021
More Decks by Takumi Shotoku
See All by Takumi Shotoku
TypeProf 開発レポート 2026-05 / TypeProf Dev Report 2026-05
sinsoku
1
94
Automatically generating types by running tests
sinsoku
4
18k
滅・サービスクラス🔥 / Destruction Service Class
sinsoku
8
2.8k
テストを書かないためのテスト/ Tests for not writing tests
sinsoku
1
300
ドメインの本質を掴む / Get the essence of the domain
sinsoku
2
340
"型"のあるRailsアプリケーション開発 / Typed Rails application development
sinsoku
10
3k
Let's get started with Ruby && Rails Tips
sinsoku
0
500
LTの敷居を下げる / Lower the threshold for LT
sinsoku
2
430
CircleCIの高速化🚀 / CircleCI faster
sinsoku
3
1.5k
Other Decks in Technology
See All in Technology
Generative UI × A2UI で AI エージェントを作った話 AI-DLC も使ってみた!
kmiya84377
1
160
シンデレラなんかになりたくない!ガラスの靴が割れた時代にどう歩く?
nomizone
0
190
ラズパイ & Picoで入門:Zephyr(RTOS)の環境構築からビルドまでの紹介
iotengineer22
0
240
自称宇宙最速で不合格となったAIP-C01にリベンジを果たすべくAIで問題集アプリを作ってみた。
yama3133
0
140
AI時代に求められる思考のパラダイムシフト
nrinetcom
PRO
1
150
AIAgentと取り組むKaggle
508shuto
2
560
The Making of AI Chips
pfn
PRO
0
770
脅威をエンジニアリングの糧にして:恐怖を乗り越えた先にあったもの / Turn threats into fuel for engineering: what lay beyond overcoming fear
nrslib
1
280
TypeScriptエンジニアのためのWASMランタイム入門:AssemblyScriptから理解するメモリの実態(ayano)
ayanoyuki
0
140
TSKaigi 2026 - Auth.jsからBetter Authへの 移行に見る「型とランタイム」の 設計思想の変化
teamlab
PRO
1
260
ルール・ロール・ツールを創る / Creating Rules, Roles and Tools
ks91
PRO
0
160
AI時代に改めて考える、ドメイン駆動設計 - モデリングが「AIへの共通言語」になる
littlehands
7
2.4k
Featured
See All Featured
Rebuilding a faster, lazier Slack
samanthasiow
85
9.5k
Building an army of robots
kneath
306
46k
It's Worth the Effort
3n
188
29k
Avoiding the “Bad Training, Faster” Trap in the Age of AI
tmiket
0
150
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.4k
Practical Orchestrator
shlominoach
191
11k
The Art of Programming - Codeland 2020
erikaheidi
57
14k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.9k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
700
Un-Boring Meetings
codingconduct
0
300
Designing for humans not robots
tammielis
254
26k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
340
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