×Закрыть

Туторіал з налаштування Rails-додатків на Amazon EC2 з Chef. Частина 3

Усім привіт! Ця стаття завершує цикл туторіалів із розгортання Rails-додатків за допомогою платформи автоматизації Chef та Amazon EC2. Скориставшись знаннями, отриманими у попередніх частинах нашого циклу, ми закінчимо писати cookbooks і захистимо наш сервер. Ми також пройдемо весь цикл розгортання нашого Spree-додатка.

Попередні випуски циклу: частина 1, частина 2.

Налаштування безпеки

Щоб захистити додаток, вам необхідно встановити й налаштувати OpenSSH на цьому етапі.

OpenSSH

Щоб увімкнути автентифікацію за допомогою SSH, встановіть OpenSSH за допомогою openssh cookbook.

Додайте необхідні залежності в Berksfile.

cookbook 'openssh', '~> 2.6.1'

Створіть cookbook.

mkdir site-cookbooks/app-openssh

Встановіть метадані для cookbook.

touch site-cookbooks/app-openssh/metadata.rb
# site-cookbooks/app-openssh/metadata.rb
name    'app-openssh'
version '0.1.0'
depends 'openssh'

Створіть атрибути за стандартним cookbook налаштуванням.

mkdir site-cookbooks/app-openssh/attributes
touch site-cookbooks/app-openssh/attributes/default.rb

Скасуйте автентифікацію за допомогою пароля через атрибут password_authentication та відключіть print_motd, який визначить, чи потрібно логувати SSH daemon, коли користувач входить до сервера у файл /etc/motd.

# site-cookbooks/app-openssh/attributes/default.rb

default['openssh']['server']['password_authentication'] = 'no'
default['openssh']['server']['print_motd'] = 'no'

Створіть recipe для cookbook за стандартним налаштуванням.

mkdir site-cookbooks/app-openssh/recipes
touch site-cookbooks/app-openssh/recipes/default.rb

Потім вам потрібно підключити зовнішній cookbook для встановлення Redis.

# site-cookbooks/app-openssh/recipes/default.rb

include_recipe 'openssh'

І нарешті, додайте всі cookbooks до security role.

touch roles/security.rb

У roles/security.rb

name 'security'
description 'Security setup'

run_list 'recipe[app-openssh]'

Також додайте security role до списку запуску YOUR_IP_ADDRESS.json node.

...
  "run_list": [
    "role[setup]",
    "role[database]",
    "role[web]",
    "role[security]"
  ],
...

Управління та моніторинг системних процесів

На цьому етапі налаштуємо процес моніторингу за станом процесів такого програмного забезпечення:
  • PostgreSQL;
  • Redis;
  • Nginx;
  • Puma.

Для моніторингу стану цих процесів будемо використовувати Monit. Щоб установити й налаштувати Monit, будемо використовувати chef-monit.

Також додайте необхідні залежності в Berksfile.

cookbook 'monit', '~> 1.0.0'

Створіть cookbook.

mkdir site-cookbooks/app-monit

Встановіть метадані для cookbook.

touch site-cookbooks/app-monit/metadata.rb
# site-cookbooks/app-monit/metadata.rb
name    'app-monit'
version '0.1.0'
depends 'app-attributes'
depends 'app-postgresql'
depends 'app-deploy'
depends 'monit'

Щоб у майбутньому було зручно підтримувати атрибути додатка, перемістіть Monit атрибути username та password до app-atributes.

# site-cookbooks/app-attributes/attributes/default.rb

# Monit -----------------------------------------------------------

override['monit']['username'] = 'USERNAME'
override['monit']['password'] = 'PASSWORD'

Замініть USERNAME і PASSWORD своїми значеннями. Далі (у частині розгортання програми) ми покажемо вам, як більш надійно зберігати таку інформацію, використовуючи encrypted_data_bags.

Тепер створіть атрибути для cookbook за стандартним налаштуванням.

mkdir site-cookbooks/app-monit/attributes
touch site-cookbooks/app-monit/attributes/default.rb

Визначте наступні атрибути:

# site-cookbooks/app-monit/attributes/default.rb

default['monit']['poll_period'] = 5 # Interval in seconds to check all Monit services at
default['monit']['port'] = 2812 # Port to listen on for Monit's HTTPD interface
default['monit']['address'] = '0.0.0.0' # Local address to bind to for Monit's HTTPD interface
default['monit']['logfile'] = '/var/log/monit.log' # Path to log messages to

Тепер ви можете написати recipes і шаблони конфігурації Monit для зазначеного вище програмного забезпечення.

mkdir -p site-cookbooks/app-monit/{recipes,templates}

PostgreSQL

Створіть recipe для підключення Monit до PostgreSQL.
touch site-cookbooks/app-monit/recipes/postgresql.rb

З’єднайте зовнішній cookbook і шаблон PostgreSQL з конфігураціями.

include_recipe 'monit'

monit_config 'postgresql' do
  source 'postgresql.conf.erb'
  variables(
    version: node['postgresql']['defaults']['server']['version']
  )
end

Потім створіть сам шаблон.

touch site-cookbooks/app-monit/templates/postgresql.conf.erb

Напишіть конфигурацію для відстежування PostgreSQL-процесу:

# site-cookbooks/app-monit/templates/postgresql.conf.erb

check process postgresql with pidfile /var/run/postgresql/<%= @version %>-main.pid
  group database
  start program = "/etc/init.d/postgresql start"
  stop program  = "/etc/init.d/postgresql stop"

  if failed unixsocket /var/run/postgresql/.s.PGSQL.5432 protocol pgsql then restart
  if failed host 127.0.0.1 port 5432 protocol pgsql then restart

Потім оновіть перелік запусків для database role .

# roles/database.rb

run_list 'recipe[app-postgresql]',
         'recipe[app-monit::postgresql]'

Redis

Створіть recipe для підключення Monit до Redis.
touch site-cookbooks/app-monit/recipes/redis.rb

Вам потрібно підключити зовнішній cookbook і шаблон Redis до ваших конфігурацій.

# site-cookbooks/app-monit/recipes/redis.rb

include_recipe 'monit'

monit_config 'redis' do
  source 'redis.conf.erb'
end

Створіть шаблон.

touch site-cookbooks/app-monit/templates/redis.conf.erb

Напишіть конфігурацію для відстежування Redis-процесу:

# site-cookbooks/app-monit/templates/redis.conf.erb

check process redis with pidfile /var/run/redis/redis-server.pid
  start program = "/etc/init.d/redis-server start"
  stop program  = "/etc/init.d/redis-server stop"

Тепер додайте цей recipe до web role.

# roles/web.rb

run_list 'recipe[app-redis]',
         'recipe[app-ruby]',
         'recipe[app-nodejs]',
         'recipe[app-imagemagick]',
         'recipe[app-nginx]',
         'recipe[app-monit::redis]'

Nginx

Створіть recipe для інтеграції Monit з Nginx.

touch site-cookbooks/app-monit/recipes/nginx.rb

З’єднайте зовнішній cookbook та інтегруйте шаблон Nginx з конфігураціями.

# site-cookbooks/app-monit/recipes/nginx.rb

include_recipe 'monit'

monit_config 'nginx' do
  source 'nginx.conf.erb'
end

Тепер створіть шаблон.

touch site-cookbooks/app-monit/templates/nginx.conf.erb

Напишіть конфігурацію для відстежування Nginx-процесу:

# site-cookbooks/app-monit/templates/nginx.conf.erb

check process nginx with pidfile /var/run/nginx.pid
  start program = "/etc/init.d/nginx start"
  stop program  = "/etc/init.d/nginx stop"

Вам також потрібно додати recipe, який уже був доданий у web role.

# roles/web.rb

run_list 'recipe[app-redis]',
         'recipe[app-ruby]',
         'recipe[app-nodejs]',
         'recipe[app-imagemagick]',
         'recipe[app-nginx]',
         'recipe[app-monit::redis]',
         'recipe[app-monit::nginx]'

Puma

Створіть recipe для інтеграції Monit з Puma.
touch site-cookbooks/app-monit/recipes/puma.rb

Далі вам необхідно підключити зовнішній cookbook та інтегрувати шаблон Puma з конфігураціями.

# site-cookbooks/app-monit/recipes/puma.rb

include_recipe 'monit'

user = node['project']['user']
project_root = node['project']['root']
rvm = File.join('/', 'home', user, '.rvm', 'scripts', 'rvm')

monit_config 'puma' do
  source 'puma.conf.erb'
  variables(
    user: user,
    project_root: project_root,
    rvm: rvm
  )
end

Створіть шаблон.

touch site-cookbooks/app-monit/templates/puma.conf.erb

Напишіть конфігурацію для відстежування Puma-процесу:

# site-cookbooks/app-monit/templates/puma.conf.erb

check process puma with pidfile <%= @project_root %>/shared/tmp/pids/puma.pid
  start program = "/bin/su - <%= @user %> -s /bin/bash -c 'source <%= @rvm %> && cd <%= @project_root %>/current && bundle exec puma -C <%= @project_root %>/shared/puma.rb -e <%= node.environment %> --daemon'"
    with timeout 30 seconds
  stop program  = "/bin/su - <%= @user %> -s /bin/bash -c 'source <%= @rvm %> && cd <%= @project_root %>/current && bundle exec pumactl -P <%= @project_root %>/shared/tmp/pids/puma.pid stop'"
    with timeout 30 seconds

Нарешті, додайте цей recipe до web role.

# roles/web.rb

run_list 'recipe[app-redis]',
         'recipe[app-ruby]',
         'recipe[app-nodejs]',
         'recipe[app-imagemagick]',
         'recipe[app-nginx]',
         'recipe[app-monit::redis]',
         'recipe[app-monit::nginx]',
         'recipe[app-monit::puma]'

Розгортання додатка

Setup

У цьому розділі нашого туторіалу ми розглянемо, як можна розгорнути додаток, використовуючи Chef.

Основи

Почнемо зі створення app-deploy cookbook, де буде описаний recipe розгортання додатків.

Спочатку додайте залежності до метаданих.

# site-cookbooks/app-deploy/metadata.rb

name    'app-deploy'
version '0.1.0'

depends 'app-attributes'
depends 'app-users'

Використовуйте encrypted_data_bags для збереження конфіденційної інформації про проект: пароль бази даних або ключі від зовнішніх служб (AWS та ін.).

Чому ми використовуємо encrypted_data_bags

Головна причина — безпека. За допомогою encrypted_data_bags усі дані зберігаються у зашифрованому вигляді. Таким чином, навіть якщо зловмисник отримає доступ до сховища зі скриптами, він не зможе використати конфіденційну інформацію.

Щоб мати змогу використовувати зашифровані data bags, потрібно створити файл, у якому зберігатимуться ключі шифрування й дешифрування. Використовуйте OpenSSL для створення приватного ключа й помістіть його у файл encrypted_data_bag_secret.

Зауважте! Якщо ви перезапишете існуючий файл encrypted_data_bag_secret або видалите його, ви не зможете розшифрувати дані, зашифровані раніше.

Щоб створити ключ, запустіть у терміналі цю команду:

openssl rand -base64 512 | tr -d '\\r\\n' > encrypted_data_bag_secret

Зауважте! Варто не зберігати у репозиторії створений файл, а поділитися ним з членами вашої команди. Для цього потрібно додати його до .gitignore.

# .gitignore

encrypted_data_bag_secret

Далі вкажіть додатковий елемент encrypted_data_bag_secret для knife solo.

# .chef/knife.rb

...
encrypted_data_bag_secret 'encrypted_data_bag_secret'

Використовуючи knife solo, створіть файл конфігурації для середовища Dev за допомогою приватного ключа.

knife solo data bag create configs dev --secret-file encrypted_data_bag_secret

У текстовий редактор, відкритий у терміналі, введіть database credentials, секретні ключі додатка та Monit credentials.

# data_bags/configs/dev.json

{
  "id": "dev",
  "database": {
    "name": "NAME",
    "user": "USER",
    "password": "PASSWORD"
  },
  "application": {
    "AWS_ACCESS_KEY_ID": "AWS_ACCESS_KEY_ID",
    "AWS_SECRET_ACCESS_KEY": "AWS_SECRET_ACCESS_KEY",
    "S3_BUCKET_NAME": "S3_BUCKET_NAME",
    "S3_REGION": "S3_REGION",
    "S3_HOST_NAME": "S3_HOST_NAME",
    "DEVISE_SECRET_KEY": "DEVISE_SECRET_KEY",
    "SECRET_KEY_BASE": "SECRET_KEY_BASE"
  },
  "monit": {
    "username": "USER_NAME",
    "password": "PASSWORD"
  }
}

Після того, як ви збережете свої дані до /data_bags/configs/dev.json, ви побачите, що вони тепер зашифровані.

Ви можете редагувати дані із зашифрованих data bags за допомогою наступної команди:

knife solo data bag edit configs dev

Ви також можете читати ці дані за допомогою цієї команди:

knife solo data bag show configs dev

Оскільки ваші ключі та credentials тепер зберігаються в encrypted_data_bag, ви можете видалити явне визначення Monit credentials з app-attributes.

# site-cookbooks/app-attributes/attributes/default.rb

# Monit -----------------------------------------------------------

monit_configs = Chef::EncryptedDataBagItem.load('configs', node.environment)['monit']

override['monit']['username'] = monit_configs['username']
override['monit']['password'] = monit_configs['password']

Set up SSH

Додаток знаходиться у приватному репозиторії. Тому для стиснення проекту використовуйте обгортку SSH. Для цього вам потрібні ключі SSH, які ви додасте до cookbook.

Якщо у вас немає ключа SSH, ви можете створити його за допомогою наведеної нижче команди. Не потрібно встановлювати пароль private key, оскільки він блокує chef-client під час запуску сценаріїв розгортання. Вам також потрібно буде вказати свою адресу електронної пошти замість example@gmail.com.

ssh-keygen -t rsa -b 4096 -C "example@gmail.com"

Потім створіть каталог — site-cookbooks/app-deploy/files — де ви розмістите приватні та публічні ключі.

mkdir site-cookbooks/app-deploy/files
mkdir site-cookbooks/app-deploy/files/default
touch site-cookbooks/app-deploy/files/default/key
touch site-cookbooks/app-deploy/files/default/key.pub

Додайте ключі у створений файл.

cp ~/.ssh/id_rsa site-cookbooks/app-deploy/files/default/key
cp ~/.ssh/id_rsa.pub site-cookbooks/app-deploy/files/default/key.pub

Зауважте! Додайте site-cookbooks/app-deploy/files/default каталог до .gitignore, оскільки ніхто не повинен знати ваш приватний ключ.

# .gitignore

site-cookbooks/app-deploy/files/default

Далі створіть recipe за стандартним налаштуванням, де ви докладно розпишете процес розгортання.

mkdir site-cookbooks/app-deploy/recipes
touch site-cookbooks/app-deploy/recipes/default.rb

У верхній частині цього файлу визначте змінні, з якими ви будете працювати у recipe:

# site-cookbooks/app-deploy/recipes/default.rb

encrypted_data = Chef::EncryptedDataBagItem.load('configs', node.environment)

config = node['project']

deployer = config['user']
deployer_group = config['group']

root_path = config['root']
home_path = File.join('/', 'home', deployer)
shared_path = File.join(root_path, 'shared')
bundle_path = File.join(shared_path, 'vendor', 'bundle')
config_path = File.join(shared_path, 'config')
ssh_path = File.join(shared_path, '.ssh')

puma_state_file = File.join(shared_path, 'tmp', 'pids', 'puma.state')
sidekiq_state_file = File.join(shared_path, 'tmp', 'pids', 'sidekiq.pid')
maintenance_file = File.join(shared_path, 'tmp', 'maintenance')

Тепер ми можемо почати описувати recipe розгортання додатка. Recipe складається з декількох етапів:

  • Використання SSH ключів;
  • Створення спільних каталогів;
  • Створення бази даних і конфігурації Puma.

Використання SSH ключів

Перш за все, ми опишемо використання SSH ключів:
# site-cookbooks/app-deploy/recipes/default.rb

# SSH -------------------------------------------------------------------------------------------------

ssh_key_file = File.join(ssh_path, deployer)
ssh_wrapper_file = File.join(ssh_path, 'wrap-ssh4git.sh')

directory ssh_path do
  owner deployer
  group deployer_group
  recursive true
end

cookbook_file ssh_key_file do
  source 'key'
  owner deployer
  group deployer_group
  mode 0o600
end

file ssh_wrapper_file do
  content "#!/bin/bash\n/usr/bin/env ssh -o \"StrictHostKeyChecking=no\" -i \"#{ssh_key_file}\" $1 $2"
  owner deployer
  group deployer_group
  mode 0o755
end

Створення спільних каталогів

# site-cookbooks/app-deploy/recipes/default.rb

# DIRECTORIES ---------------------------------------------------------------------------------------------------------

%w[config log public/system public/uploads public/assets repo tmp/cache tmp/pids tmp/sockets].each do |dir|
  directory File.join(shared_path, dir) do
    owner deployer
    group deployer_group
    mode 0o755
    recursive true
  end
end

Створення бази даних і конфігурації Puma

1. Конфігурація бази даних

Опишемо використання шаблону з конфігурацією для доступу до бази даних.

# site-cookbooks/app-deploy/recipes/default.rb

template File.join(config_path, 'database.yml') do
  source File.join(node.environment, 'database.yml.erb')
  variables(
    environment: node.environment,
    database: encrypted_data['database']['name'],
    user: encrypted_data['database']['user'],
    password: encrypted_data['database']['password']
  )
  sensitive true
  owner deployer
  group deployer_group
  mode 0o644
end

Далі створимо шаблон:

# site-cookbooks/app-deploy/templates/dev/database.yml.erb

---
<%= @environment %>:
  adapter: postgresql
  encoding: unicode
  database: <%= @database %>
  user: <%= @user %>
  password: <%= @password %>
  pool: 20
mkdir site-cookbooks/app-deploy/templates
mkdir site-cookbooks/app-deploy/templates/dev
touch site-cookbooks/app-deploy/templates/dev/database.yml.erb

2. Конфігурація додатка

Тут ви маєте описати генерацію файлу application.yml, де ви будете зберігати змінні проекту.

# site-cookbooks/app-deploy/recipes/default.rb

file File.join(config_path, 'application.yml') do
  content Hash[node.environment, encrypted_data['application']].to_yaml
  sensitive true
  owner deployer
  group deployer_group
  mode 0o644
end

3. Puma

Тепер вам потрібно описати, як використовувати шаблон з конфігураціями:

# site-cookbooks/app-deploy/recipes/default.rb

template File.join(shared_path, 'puma.rb') do
  source File.join(node.environment, 'puma.rb.erb')
  variables(
    environment: node.environment,
    project_root: root_path
  )
  owner deployer
  group deployer_group
  mode 0o644
end

Вам також потрібно створити шаблон з конфігурацією:

touch site-cookbooks/app-deploy/templates/dev/puma.rb.erb
# site-cookbooks/app-deploy/templates/dev/puma.rb.erb

#!/usr/bin/env puma

directory '<%= @project_root %>/current'
rackup '<%= @project_root %>/current/config.ru'
environment '<%= @environment %>'
pidfile '<%= @project_root %>/shared/tmp/pids/puma.pid'
state_path '<%= @project_root %>/shared/tmp/pids/puma.state'
stdout_redirect '<%= @project_root %>/shared/log/puma.error.log', '<%= @project_root %>/shared/log/puma.access.log', true
threads 4, 16
bind 'unix://<%= @project_root %>/shared/tmp/sockets/puma.sock'
workers 0
preload_app!

on_restart do
  puts 'Refreshing Gemfile'
  ENV['BUNDLE_GEMFILE'] = '<%= @project_root %>/current/Gemfile'
end

on_worker_boot do
  ActiveSupport.on_load(:active_record) do
    ActiveRecord::Base.establish_connection
  end
end

4. Конфігурація Sidekiq

Спочатку опишіть, як створити шаблон з конфігурацією Sidekiq:

# site-cookbooks/app-deploy/recipes/default.rb

template File.join(config_path, 'sidekiq.yml') do
  source File.join(node.environment, 'sidekiq.yml.erb')
  variables(
    environment: node.environment
  )
  sensitive true
  owner deployer
  group deployer_group
  mode 0o644
end

Потім створіть шаблон з конфігурацією:

touch site-cookbooks/app-deploy/templates/dev/sidekiq.yml.erb

---
<%= @environment %>:
  :verbose: true
  :logfile: log/sidekiq.log
  :concurrency:  1
  :strict: false
  :pidfile: tmp/pids/sidekiq.pid
  :queues:
    - [default, 1]

Розгортання

Тепер перейдемо безпосередньо до розгортання додатка. Як правило, розгортання відбувається в чотири етапи:
  1. Checkout  chef-client використовує ресурс Source Code Management (SCM) для отримання вказаної ревізії додатка й розміщення clone або checkout в субкаталозі deploy каталогу з назвою cached-copy. Потім копія додатка розміщується в цьому субкаталозі.
  2. Migrate  якщо процес міграції буде запущено, chef-client символічно пов’язує файл конфігурації бази даних з checkout (config/database.yml за замовчуванням) і запускає команду міграції. Для Ruby on Rails додатка migration_command зазвичай встановлюється в rack db: migrate.
  3. Symlink — каталог для загальних і тимчасових файлів, які видаляються з checkout (log, tmp / pids і public / system за замовчуванням). Після цього вам потрібно створити будь-які необхідні каталоги (tmp, public і config за замовчуванням), якщо їх не існує. Наприкінці цього кроку ви посилаєтеся на спільні каталоги в поточний release, public / system, tmp / pids та log каталоги, а потім — на release у current.
  4. Restart  перезапустіть додаток, використовуючи команду restart у recipe.

Ось детальна інструкція розгортання додатків:

# site-cookbooks/app-deploy/recipes/default.rb

# DEPLOYMENT ----------------------------------------------------------------------------------------------------------

timestamped_deploy node[‘domain_name’] do
  ssh_wrapper ssh_wrapper_file
  repository config['repository']
  branch config['branch']
  repository_cache 'repo'
  deploy_to config['root']
  user deployer
  group deployer_group

  # Set global environments
  environment(
    'HOME' => home_path,
    'RAILS_ENV' => node.environment
  )

  # Before you start to run the migration, create tmp and public directories.
  create_dirs_before_symlink %w[tmp public]

  # Map files in a shared directory to their paths in the current release directory.
  symlinks(
    'config/application.yml' => 'config/application.yml',
    'config/database.yml' => 'config/database.yml',
    'config/newrelic.yml' => 'config/newrelic.yml',
    'config/sidekiq.yml' => 'config/sidekiq.yml',
    'log' => 'log',
    'public/system' => 'public/system',
    'public/uploads' => 'public/uploads',
    'public/assets' => 'public/assets',
    'tmp/cache' => 'tmp/cache',
    'tmp/pids' => 'tmp/pids',
    'tmp/sockets' => 'tmp/sockets'
  )

  # Map files in a shared directory to the current release directory.
  symlink_before_migrate(
    'config/application.yml' => 'config/application.yml',
    'config/database.yml' => 'config/database.yml'
  )

  # Run this code before the migration starts
  before_migrate do
    file maintenance_file do
      owner deployer
      group deployer_group
      action :create
    end

    # Install bundler gem
    execute 'install bundler' do
      command "/bin/bash -lc 'source $HOME/.rvm/scripts/rvm && gem install bundler'"
      cwd release_path
      user deployer
      group deployer_group
      environment(
        'HOME' => home_path
      )
    end

    # Install other gems
    execute 'bundle install' do
      command "/bin/bash -lc 'source $HOME/.rvm/scripts/rvm && bundle install --without development test --deployment --path #{bundle_path}'"
      cwd release_path
      user deployer
      group deployer_group
      environment(
        'HOME' => home_path
      )
    end
  end

  migration_command "/bin/bash -lc 'source $HOME/.rvm/scripts/rvm && bundle exec rails db:migrate --trace'"
  migrate true

  restart_command do
    # If PUMA is running ‒ restart it
    if File.exist? puma_state_file
      execute 'pumactl restart' do
        command "/bin/bash -lc 'source $HOME/.rvm/scripts/rvm && bundle exec pumactl -S #{puma_state_file} restart'"
        cwd release_path
        user deployer
        group deployer_group
        environment(
          'HOME' => home_path
        )
      end
    end

    # If Sidekiq is running ‒ restart it
    if File.exist? sidekiq_state_file
      execute 'sidekiqctl stop' do
        command "/bin/bash -lc 'source $HOME/.rvm/scripts/rvm && bundle exec sidekiqctl stop #{sidekiq_state_file}'"
        cwd release_path
        user deployer
        group deployer_group
        environment(
          'HOME' => home_path
        )
      end
    end
  end

  # Run the following tasks before app restart commands
  before_restart do
    execute 'db:seed' do
      command "/bin/bash -lc 'source $HOME/.rvm/scripts/rvm && bundle exec rake db:seed'"
      cwd release_path
      user 'root'
      group 'root'
      environment(
        'HOME' => home_path,
        'RAILS_ENV' => node.environment
      )
    end

    execute 'assets:precompile' do
      command "/bin/bash -lc 'source $HOME/.rvm/scripts/rvm && bundle exec rake assets:precompile'"
      cwd release_path
      user 'root'
      group 'root'
      environment(
        'HOME' => home_path,
        'RAILS_ENV' => node.environment
      )
    end
  end

  # Once you've restarted the app, remove the maintenance file
  after_restart do
    file maintenance_file do
      action :delete
    end
  end

  action :deploy
end

Застосування конфігурацій

Тепер вам потрібно додати app-deploy cookbook до deploy role, щоб використовувати цей cookbook далі в node.
touch roles/deploy.rb

Опишемо базову інформацію про цю role та її run list.

# roles/deploy.rb

name 'deploy'

description 'Deployment'

run_list 'recipe[app-deploy]'

Далі додайте цю role до загального списку nodes/ YOUR_IP_ADDRESS.json node.

// nodes/YOUR_IP_ADDRESS.json

 ...
 "run_list": [
   "role[setup]",
   "role[database]",
   "role[web]",
   "role[security]",
   "role[deploy]"
 ],
...

Тепер ви можете застосувати скрипти, які ви написали, щоб запустити додаток на сервері.

Встановіть Chef і застосуйте всі конфігурації за допомогою такої команди:

knife solo bootstrap ubuntu@YOUR_IP_ADDRESS -i spree_dev.pem

Після завершення розгортання Spree-додаток буде доступний через публічний DNS. У нашому прикладі — адреса ec2-18-221-230-71.us-east-2.compute.amazonaws.com.

Тепер ви можете увійти на сервер через SSH як deployer-користувач:

ssh deployer@YOUR_IP_ADDRESS

У майбутньому ви зможете розгорнути додаток на віддаленому комп’ютері за допомогою такої команди:

knife solo cook deployer@YOUR_IP_ADDRESS -o "'recipe[app-deploy]'"

Підбиваємо підсумки

Коли я створював цей туторіал, то мав на меті показати надзвичайну гнучкість Chef та його можливості розгортання проектів будь-якої складності. Також зауважу, що туторіал буде цікавий у першу чергу для новачків, адже в ньому детально розібрані компоненти, необхідні для коректної роботи Spree-додатка та показані всі етапи розгортання додатка.

Сподіваюсь, що туторіал був для вас корисним. Запрошую вас поділитися своїм досвідом використання Chef нижче у коментарях.

Дякую команді RubyGarage за допомогу у підготовці матеріалу.


Попередні частини туторіалу: частина 1, частина 2.

LinkedIn

1 комментарий

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.

Хорошая заметка, большое спасибо ! Очень приятно видеть такие материалы, именно технического характера

Подписаться на комментарии