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.1k
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
テストを書かないためのテスト/ Tests for not writing tests
sinsoku
1
170
ドメインの本質を掴む / Get the essence of the domain
sinsoku
2
230
"型"のあるRailsアプリケーション開発 / Typed Rails application development
sinsoku
9
2.5k
Let's get started with Ruby && Rails Tips
sinsoku
0
380
LTの敷居を下げる / Lower the threshold for LT
sinsoku
1
340
CircleCIの高速化🚀 / CircleCI faster
sinsoku
3
1.3k
Railsアプリと型検査 / Rails app and type checking
sinsoku
5
1.4k
💎のつくりかた 2023 / How to make gems 2023
sinsoku
2
350
Make tests run faster
sinsoku
2
670
Other Decks in Technology
See All in Technology
The future we create with our own MVV
matsukurou
0
2k
CDKのコードレビューを楽にするパッケージcdk-mentorを作ってみた/cdk-mentor
tomoki10
0
210
Formal Development of Operating Systems in Rust
riru
1
420
WantedlyでのKotlin Multiplatformの導入と課題 / Kotlin Multiplatform Implementation and Challenges at Wantedly
kubode
0
250
JAWS-UG20250116_iOSアプリエンジニアがAWSreInventに行ってきた(真面目編)
totokit4
0
140
データ基盤におけるIaCの重要性とその運用
mtpooh
4
500
When Windows Meets Kubernetes…
pichuang
0
300
Copilotの力を実感!3ヶ月間の生成AI研修の試行錯誤&成功事例をご紹介。果たして得たものとは・・?
ktc_shiori
0
350
.NET 最新アップデート ~ AI とクラウド時代のアプリモダナイゼーション
chack411
0
200
20250116_JAWS_Osaka
takuyay0ne
2
200
AWSサービスアップデート 2024/12 Part3
nrinetcom
PRO
0
140
ゼロからわかる!!AWSの構成図を書いてみようワークショップ 問題&解答解説 #デッカイギ #羽田デッカイギおつ
_mossann_t
0
1.5k
Featured
See All Featured
Making the Leap to Tech Lead
cromwellryan
133
9k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
3
240
GitHub's CSS Performance
jonrohan
1030
460k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Agile that works and the tools we love
rasmusluckow
328
21k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
7k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
28
2.2k
[RailsConf 2023] Rails as a piece of cake
palkan
53
5.1k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
49k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
30
2.1k
Fireside Chat
paigeccino
34
3.1k
Practical Orchestrator
shlominoach
186
10k
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