Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Rails App Deployment with CodeDeploy
tannai
August 30, 2016
Programming
0
1.1k
Rails App Deployment with CodeDeploy
http://classmethod.connpass.com/event/38180/
tannai
August 30, 2016
Tweet
Share
More Decks by tannai
See All by tannai
redash patche at dmm
yuukigoodman
0
530
akibago-2018-10-30
yuukigoodman
0
56
serverless-design-and-streaming-date-processing-service
yuukigoodman
0
630
alexa-changes-development-process
yuukigoodman
0
1.1k
VUIとAlexaによるちょっと未来の体験の話2
yuukigoodman
0
590
regrowth2016alexa
yuukigoodman
0
1k
cognito-userpools-in-production
yuukigoodman
4
7.5k
aws-lambda-in-practice
yuukigoodman
2
1.5k
serverless-from-today
yuukigoodman
2
1.7k
Other Decks in Programming
See All in Programming
jq at the Shortcuts
cockscomb
1
430
domain層のモジュール化 / MoT TechTalk #15
mot_techtalk
0
120
Makuakeの認証基盤とRe-Architectureチーム
bmf_san
0
600
花き業界のサプライチェーンを繋げるプロダクト開発の進め方
userlike1
0
170
PHPDocにおける配列の型定義を少し知る
shimabox
1
140
Writing Greener Java Applications
hollycummins
0
340
エンジニア向け会社紹介資料/engineer-recruiting-pitch
xmile
PRO
0
100
コンピュータビジョンセミナー2 / computer_vision_seminar_libSGM
fixstars
0
320
爆速の日経電子版開発の今
shinyaigeek
2
630
AWSとCPUのムフフな関係
cmdemura
0
480
子育てとEMと転職と
_atsushisakai
1
410
An Advanced Introduction to R
nicetak
0
1.8k
Featured
See All Featured
Designing Dashboards & Data Visualisations in Web Apps
destraynor
224
50k
JazzCon 2018 Closing Keynote - Leadership for the Reluctant Leader
reverentgeek
175
9.1k
Six Lessons from altMBA
skipperchong
15
2.3k
Designing Experiences People Love
moore
130
22k
Art, The Web, and Tiny UX
lynnandtonic
284
18k
Into the Great Unknown - MozCon
thekraken
2
300
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
227
16k
A Philosophy of Restraint
colly
193
15k
For a Future-Friendly Web
brad_frost
166
7.8k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
6
840
Gamification - CAS2011
davidbonilla
75
4.1k
VelocityConf: Rendering Performance Case Studies
addyosmani
317
22k
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γΣϧεΫϦϓτͷφϨοδΛస༻ Ͱ͖Δ • χʔζʹ߹ΘͤͨσϓϩΠγεςϜΛ࡞ΕΔ