Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Rails App Deployment with CodeDeploy
Search
tannai
August 30, 2016
Programming
1.6k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Rails App Deployment with CodeDeploy
http://classmethod.connpass.com/event/38180/
tannai
August 30, 2016
More Decks by tannai
See All by tannai
redash patche at dmm
yuukigoodman
0
770
akibago-2018-10-30
yuukigoodman
0
96
serverless-design-and-streaming-date-processing-service
yuukigoodman
0
1.1k
alexa-changes-development-process
yuukigoodman
0
1.7k
VUIとAlexaによるちょっと未来の体験の話2
yuukigoodman
0
950
regrowth2016alexa
yuukigoodman
0
1.4k
cognito-userpools-in-production
yuukigoodman
4
8.9k
aws-lambda-in-practice
yuukigoodman
2
2.1k
serverless-from-today
yuukigoodman
2
2.3k
Other Decks in Programming
See All in Programming
【加筆修正版】Laravel のアプリケーションをどこにデプロイするか #phpcon_ehime
akase244
0
150
Agents on Rails - Rails at Scale 2026
irinanazarova
0
540
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
2
410
sbt 2.0: takeoff
eed3si9n
0
150
動作中のプログラムの中身をリアルタイムに覗く / Realtime Debugger for CSharp with Roslyn
prota
1
1.9k
現場と育てるRailsモデリング 〜Spreadsheetから始めたモデル設計〜
siroemk
2
520
CodeRabbitの効果検証と過ごしてみた3ヶ月
armondando
0
230
コードレビューのボトルネックを"する側"と"される側"の両面から解消する
yub0n
2
1.6k
コードで差別化できない時代の ソフトウェアエンジニアリング / Software Engineering in an Era Where Code Doesn’t Differentiate
kishida
2
170
SREの越境 / SRE Collaboration
y0hgi
2
310
[ハンズオン]AIへの指示だけで「五目並べ」を作ってみよう
satoshi256kbyte
1
370
PumaからFalconに移行したRailsアプリケーションでの実践
falcon8823
0
150
Featured
See All Featured
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
2
2.2k
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Balancing Empowerment & Direction
lara
6
1.3k
Become a Pro
speakerdeck
PRO
31
6.3k
Thoughts on Productivity
jonyablonski
76
5.4k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Fantastic passwords and where to find them - at NoRuKo
philnash
53
4k
The Curious Case for Waylosing
cassininazir
1
570
How STYLIGHT went responsive
nonsquared
100
6.3k
KATA
mclloyd
PRO
35
16k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
1
450
Transcript
RailsΞϓϦΛ σϓϩΠ͢Δ CodeDeploy Classmethod, Inc. Yuki Tannai ࣮ફAWSϓϩάϥϛϯά
ࣗݾհ • ୮༏ل • @yuukigoodman • αʔόͰಈ͘ϓϩάϥϜͱ͔AWS
Agenda • σϓϩΠͱ • σϓϩΠΛࢧ͑ΔAWS • CodeDeployͰRailsΛσϓϩΠ
σϓϩΠͱ
γεςϜΛ ར༻Մೳʹ͢Δ ׆ಈશൠͰ͋Δ — ja.wikipedia.org1 1 https://ja.wikipedia.org/wiki/ιϑτΣΞσϓϩΠϝϯτ
• ͨͩίʔυΛμϯϩʔυͯ͠ىಈ͢Εྑ͍ ͱ͍͏ͷͰͳ͍ • σϓϩΠʹΑͬͯղܾ͍͕ͨ͋͠Γɺ ͦΕϓϩδΣΫτͷਐߦͱڞʹมԽ͢Δ • σϓϩΠαʔϏεఏڙऀͷΛղܾ͢Δ • ఏڙऀͷղܾར༻ऀͷՁʹͳΓಘΔ
• σϓϩΠ࣭ͷͻͱͭ(QCD) • Quality/Cost/Delivery
σϓϩΠࣗಈԽͷಈػ • ස͕ଟ͍ • ϛε͕Ͱ͖ͳ͍ • ϧʔνϯϫʔΫ • ͰʑมΘΔ ࣗಈԽ͠ͳ͍ͱͬͯΒΜͶʔʂʂ
σϓϩΠࣗಈԽͷ؍ • Ͳ͔͜ΒͲ͜ʹσϓϩΠ͢Δ͔ • ࣗಈσϓϩΠͷ࣮ߦτϦΨʔ • ͍ͭ୭͕σϓϩΠ͢Δ͔ • ࣦഊΛͲ͏ݕग़͠ɺͲ͜ʹ௨͢Δ͔ •
Ͳͷ͘Β͍มߋ͕ೖΔ͔
σϓϩΠϓϩδΣΫτͷਐߦͱͱʹมԽ͢Δ • Ϗδωε: ༷มߋೲظॖ • ৫: ϝϯόʔͷೖΕସ͑૿ݮɺख़ͷෆ ۉҰ͞ • ٕज़:
όʔδϣϯΞοϓύϑΥʔϚϯε ͜ΕΒͷཧ༝ʹΑΓσϓϩΠมߋ͞ΕΔ
มߋʹ͑͏Δ σϓϩΠࣗಈԽͷ ϓϩάϥϜΛॻ͘
ͦͷͨΊͷඪઃఆͱઃܭ͕େࣄ
σϓϩΠΛࢧ͑Δ AWS
None
EC2 • ΦʔιυοΫεͳσϓϩΠλʔήοτ • େͷ߹EC2ʹσϓϩΠ͢Δ • Πϯελϯε࡞ͱϓϩϏδϣχϯά͕ඞཁ
None
Elastic Beanstalk • HerokuΈ͍ͨͳαʔϏε • EC2/RDS/ELBϦιʔεΛ؆୯ʹཧ͢Δ • ࣮ମCFn • ઐ༻ͷίϚϯυ(eb-cli)͕͋Δ
• eb deploy
None
Cloud Formation • AWSϦιʔεͷߏཧ • ϒϥβCLIͰ͍ͬͯΔ͜ͱΛJSONͰهड़ ͢Δͱ࣮ߦͯ͘͠ΕΔ • AWSެࣜఏڙπʔϧͳͷͰ҆৺ •
࠶ݱੑ͕ٻΊΒΕΔ߹ඇৗʹ༗ޮ
None
EC2 Container Service • EC2Ϋϥελ্Ͱͷίϯςφ࣮ߦΛཧ • Dockerӡ༻ʹৄ͍͠ਓɺ ͥͻ࠙ձͰڭ͍͑ͯͩ͘͞ >< •
Container Registry౦ژʹདྷͨ
None
Code Deploy • EC2ͷίʔυͷஔͱىಈΛཧ͢ΔαʔϏε • ຊͷओਓެ • EC2ʹAgentΛΠϯετʔϧ͓ͯ͘͠
CodeDeployͰ RailsΛσϓϩΠ
େ·͔ͳྲྀΕ • Ansible Playbookͷ࡞ • CodeDeployઃఆͷ࡞ • Cloud Formation Templateͷ࡞
• σϓϩΠͯ͠ΈΔ • Ճཁ݅Λ࣮͢Δ • ࣦഊ࣌ͷ௨ • Blue Green Deployment
Ansible Playbookͷ࡞
webservers.yml - hosts: all remote_user: ec2-user vars: rails_env: "{{ lookup('env',
'RAILS_ENV') }}" roles: - common - nginx - fluentd - logrotate - ruby - node - rails - ssh
roles/common/tasks/main.yml - name: install yum security plugin yum: pkg=yum-plugin-security state=latest
sudo: yes - name: update yum security shell: yum -y --security update-minimal sudo: yes
roles/common/tasks/main.yml - name: install yum packages yum: name={{ item }}
state=present sudo: yes with_items: - gcc-c++ - glibc-headers - openssl-devel - readline - readline-devel - libyaml-devel - libffi-devel - libxml2 - libxslt - libxml2-devel - libxslt-devel - zlib - zlib-devel - mysql-devel - git - ruby-devel
roles/node/tasks/main.yml - name: install nodejs yum: name=nodejs enablerepo=epel sudo: yes
roles/ruby/tasks/main.yml - name: check rbenv presence command: which rbenv ignore_errors:
true register: rbenv_path - name: Install rbenv sudo: yes git: repo=https://github.com/sstephenson/rbenv.git dest={{ rbenv_root }} when: rbenv_path.rc != 0 - name: Install ruby-build sudo: yes git: repo=https://github.com/sstephenson/ruby-build.git dest={{ rbenv_root }}/plugins/ruby-build when: rbenv_path.rc != 0
roles/ruby/tasks/main.yml - name: create shims dir sudo: yes file: path={{
rbenv_root }}/shims state=directory when: rbenv_path.rc != 0 - name: create versions dir sudo: yes file: path={{ rbenv_root }}/versions state=directory when: rbenv_path.rc != 0 - name: change owner of install dir sudo: yes command: chgrp -R {{ app_user }} {{ rbenv_root }} when: rbenv_path.rc != 0 - name: change mode of install dir sudo: yes command: chmod -R g+rwxXs {{ rbenv_root }} when: rbenv_path.rc != 0
roles/ruby/tasks/main.yml - name: Set rbenv env file sudo: yes copy:
src=rbenv.sh dest=/etc/profile.d mode=0775 when: rbenv_path.rc != 0 - name: check ruby version shell: rbenv versions | grep {{ ruby_version }} > /dev/null ; echo $? ignore_errors: true register: ruby_is_installed changed_when: ruby_is_installed.stdout != '0' - name: Install ruby with rbenv shell: bash -lc "rbenv install {{ ruby_version }}" args: creates: "{{ rbenv_root }}/versions/{{ ruby_version }}/bin/ruby"
roles/ruby/tasks/main.yml - name: check ruby version shell: ruby -v |
grep {{ ruby_version }} > /dev/null ; echo $? register: is_correct_version changed_when: is_correct_version.stdout != '0' - name: Switch Ruby version shell: bash -lc "rbenv global {{ ruby_version }} && rbenv rehash" when: is_correct_version.stdout != '0' - name: update rubygems shell: bash -lc "rbenv exec gem update --system" - name: install common gems shell: bash -lc "rbenv exec gem install bundler io-console --no-ri --no-rdoc" args: creates: "{{ rbenv_root }}/shims/bundle"
CodeDeployઃఆͷ࡞
RAILS_ROOT/appspec.yml version: 0.0 os: linux files: - source: / destination:
/home/ec2-user/app permissions: - object: /home/ec2-user pattern: "**" owner: ec2-user group: ec2-user mode: 755
RAILS_ROOT/appspec.yml hooks: ApplicationStop: - location: script/codedeploy/deregister_from_elb.sh - location: script/codedeploy/application_stop.sh timeout:
300 runas: ec2-user BeforeInstall: - location: script/codedeploy/before_install.sh timeout: 300 runas: root
RAILS_ROOT/appspec.yml AfterInstall: - location: script/codedeploy/after_install.sh timeout: 3600 runas: ec2-user ApplicationStart:
- location: script/codedeploy/application_start.sh timeout: 3600 runas: ec2-user ValidateService: - location: script/codedeploy/verify_service.sh timeout: 3600 runas: ec2-user - location: script/codedeploy/register_with_elb.sh
ApplicationStop • σϓϩΠલʹΞϓϦΛఀࢭ͢Δ • ELBԼͷ߹ొղআ͢Δ • EC2ࣗΛstand byʹ͢Δ • deregister_from_elb.sh
awslabsϦϙͰ
ApplicationStop • application_stop.shͰదٓRailsΛఀࢭ͢ Δ • ͜ͷ࣌ͰELB͔Βִ͞Ε͍ͯΔͷͰࢭΊ ͳͯ͘ྑ͍
BeforeInstall • ιʔείʔυΛEC2ʹίϐʔ͢Δ • ओʹAnsible(ͱCapistrano)ͷ४උ • appspec.ymlͰrunas: rootΛΕͳ͍
BeforeInstall #!/bin/bash yum list installed python-pip &> /dev/null if [
$? != 0 ]; then yum install -y python-pip fi pip list | grep -q ansible if [ $? != 0 ]; then pip install ansible fi mkdir -p /data/app chown -R ec2-user:ec2-user /data/app
AfterInstall • ίϐʔͱunzipͷ࣍ʹ࣮ߦ͞ΕΔ • ࣗͷEC2λάΛಡΜͰઃఆϑΝΠϧΛμϯ ϩʔυͯ͠ධՁ
AfterInstall #!/bin/bash set -u METADATA=`ec2-describe-instances $(ec2-metadata -i | cut -d"
" -f 2) --region ap-northeast-1` BUCKET_NAME=`echo "$METADATA" | grep VariablesBucket | cut -f 5` KEY_NAME=`echo "$METADATA" | grep VariablesKey | cut -f 5` sudo aws s3api get-object --bucket $BUCKET_NAME \ --key $KEY_NAME $APPLICATION_VARIABLES_PATH \ --region ap-northeast-1 . $APPLICATION_VARIABLES_PATH /usr/local/bin/ansible-playbook $DESTINATION_PATH/ansible/site.yml \ -i $DESTINATION_PATH/ansible/codedeployhosts --connection=local
ApplicationStart • Railsͷىಈ४උͱىಈΛߦͳ͏ • ࠓճcapistranoͰٵऩ͍ͯ͠Δ
ApplicationStart #!/bin/bash set -u . /etc/profile.d/rbenv.sh . $APPLICATION_VARIABLES_PATH cd $DESTINATION_PATH
rbenv exec bundle exec cap local deploy
ValidateService • ΞϓϦέʔγϣϯͷىಈͱELBొΛߦͳ͏ • ҎԼͷεΫϦϓτ͕exit code 0ͳΒ࣍ͷ registerwithelb.sh͕Δ • registerwithelb.shAWSLabsͰެ։͞
Ε͍ͯΔ #!/bin/bash curl -s http://localhost/health_check
Cloud Formation Templateͷ࡞
ͦΕΛه͢ʹ ༨ന͕Γͳ͍
ͬͯΔ͜ͱ • ELBͷ࡞ • Launch Configͷ࡞ • User DataͰCodeDeploy AgentͷΠϯε
τʔϧ • Auto Scaling Groupͷ࡞ • Route53Ϩίʔυͷ࡞ ※CodeDeployϦιʔε࡞ͯ͠ͳ͍
Launch Config "UserData": { "Fn::Base64": { "Fn::Join": [ "", [
"#!/bin/bash -xe\n", "yum update -y aws-cfn-bootstrap; yum install -y aws-cli\n", "sed -i 's/Defaults requiretty/Defaults:root !requiretty/g' /etc/sudoers\n", "cd /home/ec2-user/\n", "aws s3 cp 's3://aws-codedeploy-us-east-1/latest/codedeploy-agent.noarch.rpm' . ", "|| error_exit 'Failed to download AWS CodeDeploy Agent.'\n", "yum -y install codedeploy-agent.noarch.rpm || error_exit 'Failed to install AWS CodeDeploy Agent.' \n" ] ] } },
CFn Create Stack
CodeDeployϦιʔεΛखಈͰ࡞ • ڥมshΛS3ʹஔ͘ • CFnͰͰ͖ͨASGΛࢦఆͯ͠Aplication/ DeploymentGroup࡞
σϓϩΠͯ͠ΈΔ
Ճཁ݅: ΑΓҰͷࣗಈԽ
ྲྀΕ • εΫϦϓτͰσϓϩΠ༻zipΛ࡞ • S3ʹஔ • LambdaͰCodeDeploy
εΫϦϓτͰσϓϩΠ༻zipΛ࡞ gulp.task('clean', function() { return del(['./tmp/dest']); }); gulp.task('zip', function() {
return gulp.src('**') .pipe(excludeGitignore()) .pipe(zip(bundleName + '.zip')) .pipe(gulp.dest('./tmp/dest')); }); gulp.task('upload', function(){ var publisher = awspublish.create({ params: { Bucket: BUCKET } }); return gulp.src('./tmp/dest/' + bundleName + '.zip') .pipe(publisher.publish()) .pipe(awspublish.reporter()); });
S3ʹzipΛஔ͘ͱಈ͘Lambda exports.handler = (event, context, callback) => { const message
= JSON.parse(event.Records[0].Sns.Message); const params = { applicationName: `my-application`, deploymentGroupName: `my-deployment-group`, revision: { revisionType: 'S3', s3Location: { bucket: message.bucketName, bundleType: 'zip', key: message.keyName } } };
S3ʹzipΛஔ͘ͱಈ͘Lambda codedeploy.createDeployment(params, (err, data) => { if (err) { console.log(err);
callback(err); } else { callback(null, data); } });
Ճཁ݅: ىಈΛૣ͘͢Δ
AMIΛͱΔ • σϓϩΠঢ়ଶͷAMI࡞ • CFnमਖ਼
Ճཁ݅: B-G σϓϩΠ
• ELB+ASGΛDeploymentGroupΛ2ͭ࡞ • CodeDeloyޭ࣌ʹSNSܦ༝ͰLambdaΛىಈ • LambdaͰRoute53 ALIASϨίʔυͷ͖ઌΛ ม͑Δ
·ͱΊ
CodeDeployͰҎԼΛୡՄೳ • AnsibleγΣϧεΫϦϓτͷφϨοδΛస༻ Ͱ͖Δ • χʔζʹ߹ΘͤͨσϓϩΠγεςϜΛ࡞ΕΔ