Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rails App Deployment with CodeDeploy

Avatar for tannai tannai
August 30, 2016

Rails App Deployment with CodeDeploy

Avatar for tannai

tannai

August 30, 2016
Tweet

More Decks by tannai

Other Decks in Programming

Transcript

  1. େ·͔ͳྲྀΕ • Ansible Playbookͷ࡞੒ • CodeDeployઃఆͷ࡞੒ • Cloud Formation Templateͷ࡞੒

    • σϓϩΠͯ͠ΈΔ • ௥Ճཁ݅Λ࣮૷͢Δ • ࣦഊ࣌ͷ௨஌ • Blue Green Deployment
  2. webservers.yml - hosts: all remote_user: ec2-user vars: rails_env: "{{ lookup('env',

    'RAILS_ENV') }}" roles: - common - nginx - fluentd - logrotate - ruby - node - rails - ssh
  3. 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
  4. 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
  5. 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
  6. 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
  7. 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"
  8. 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"
  9. 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
  10. 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
  11. 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
  12. 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
  13. 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
  14. ΍ͬͯΔ͜ͱ • ELBͷ࡞੒ • Launch Configͷ࡞੒ • User DataͰCodeDeploy AgentͷΠϯε

    τʔϧ • Auto Scaling Groupͷ࡞੒ • Route53Ϩίʔυͷ࡞੒ ※CodeDeployϦιʔε͸࡞੒ͯ͠ͳ͍
  15. 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" ] ] } },
  16. εΫϦϓτͰσϓϩΠ༻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()); });
  17. 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 } } };