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

Rails App Deployment with CodeDeploy

tannai
August 30, 2016

Rails App Deployment with CodeDeploy

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 } } };