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
8.8k
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
Let's get started with Ruby && Rails Tips
sinsoku
0
310
LTの敷居を下げる / Lower the threshold for LT
sinsoku
1
280
CircleCIの高速化🚀 / CircleCI faster
sinsoku
3
1.1k
Railsアプリと型検査 / Rails app and type checking
sinsoku
5
1.2k
💎のつくりかた 2023 / How to make gems 2023
sinsoku
2
290
Make tests run faster
sinsoku
2
590
YARD with RBS Syntax
sinsoku
1
410
Get started with OSS contributions
sinsoku
2
1.1k
Advice for Ruby beginners
sinsoku
2
450
Other Decks in Technology
See All in Technology
初中級者用如何使用backlog -VALE TUDOEDITION-
in0u
0
140
Github Actions 로 Android 팀의 효율성 극대화
hadonghyun
0
160
Azure Pipelinesを使用したCICDベースラインアーキテクチャ実践
yuriemori
0
190
AWSサービスメニュー開発をしていてAWSを好きだ!と感じた瞬間
toru_kubota
0
130
コンテナ・K8s研修 - 前半 コンテナ基礎・ハンズオン【MIXI 24新卒技術研修】
mixi_engineers
PRO
0
170
Docker互換のセキュアなコンテナ実行環境「Podman」超入門
devops_vtj
6
3.2k
データ分析を支える技術 生成AI再入門
ishikawa_satoru
0
380
エンジニアリングマネージャーはどう学んでいくのか #devsumi / How Do Engineering Managers Continue to Learn and Grow?
expajp
4
1.3k
技術負債による事業の失敗はなぜ起こるのか / Why do business failures due to technical debt occur?
i35_267
0
190
AWSで”最小権限の原則”を実現するための考え方 /20240722-ssmjp-aws-least-privilege
opelab
10
4.3k
「単なる OAuth 2.0 を認証に使うと、車が通れるほどのどでかいセキュリティー・ホールができる」のか検証してみた
terara
0
380
年間一億円削減した時系列データベースのアーキテクチャ改善~不確実性の高いプロジェクトへの挑戦~
lycorptech_jp
PRO
3
2.9k
Featured
See All Featured
StorybookのUI Testing Handbookを読んだ
zakiyama
15
4.9k
Infographics Made Easy
chrislema
238
18k
Product Roadmaps are Hard
iamctodd
PRO
48
10k
Happy Clients
brianwarren
94
6.5k
Debugging Ruby Performance
tmm1
71
11k
Making the Leap to Tech Lead
cromwellryan
127
8.7k
What the flash - Photography Introduction
edds
65
11k
Building an army of robots
kneath
301
42k
Rebuilding a faster, lazier Slack
samanthasiow
78
8.5k
The Power of CSS Pseudo Elements
geoffreycrofte
64
5.2k
A Philosophy of Restraint
colly
200
16k
Bootstrapping a Software Product
garrettdimon
PRO
304
110k
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