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
9k
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
"型"のあるRailsアプリケーション開発 / Typed Rails application development
sinsoku
8
2.2k
Let's get started with Ruby && Rails Tips
sinsoku
0
340
LTの敷居を下げる / Lower the threshold for LT
sinsoku
1
310
CircleCIの高速化🚀 / CircleCI faster
sinsoku
3
1.2k
Railsアプリと型検査 / Rails app and type checking
sinsoku
5
1.3k
💎のつくりかた 2023 / How to make gems 2023
sinsoku
2
310
Make tests run faster
sinsoku
2
630
YARD with RBS Syntax
sinsoku
1
460
Get started with OSS contributions
sinsoku
2
1.2k
Other Decks in Technology
See All in Technology
【shownet.conf_】コンピューティング資源を統合した分散コンテナ基盤の進化
shownet
PRO
0
400
エムスリー全チーム紹介資料 / Introduction of M3 All Teams
m3_engineering
1
310
Efficient zero-copy networking using io_uring
ennael
PRO
0
350
トークナイザー入門
payanotty
2
950
All your memory are belong to… whom?
ennael
PRO
0
660
Develop to Survive - YAPC::Hakodate 2024 Keynote
moznion
8
2.3k
【shownet.conf_】多様化するネットワーク環境を柔軟に統合するルーティングテクノロジー
shownet
PRO
0
380
Oracle Database 23ai 新機能#4 Application Continuity
oracle4engineer
PRO
0
120
Oracle GoldenGate 23ai 導入Tips
oracle4engineer
PRO
1
270
第45回 MLOps 勉強会 - ML Test Score を用いた機械学習システムの定量的なアセスメント
masatakashiwagi
3
300
Azure Verified Moduleを触って分かった注目ポイント/azure-verified-module-begin
mhrtech
1
380
KubeVirt Networking ONIC 2024
orimanabu
3
300
Featured
See All Featured
Designing for humans not robots
tammielis
249
25k
Side Projects
sachag
452
42k
Designing with Data
zakiwarfel
98
5.1k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
249
21k
Docker and Python
trallard
40
3k
The Cost Of JavaScript in 2023
addyosmani
43
5.8k
What's in a price? How to price your products and services
michaelherold
243
11k
The Invisible Side of Design
smashingmag
297
50k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
327
21k
What the flash - Photography Introduction
edds
67
11k
Building an army of robots
kneath
302
42k
Producing Creativity
orderedlist
PRO
341
39k
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