Туторіал з налаштування 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]"
],
...

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

На цьому етапі налаштуємо процес моніторингу за станом процесів такого програмного забезпечення:

Для моніторингу стану цих процесів будемо використовувати 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(
 версія: 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

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

# 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"

Вам також потрібно додати рецепт, який вже був доданий у 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/pid/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/pid/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-deploycookbook, де буде описів 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 '\
\
' > 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, ви побачите, що вони тепер зашифровані.

Замініть значення, встановлені у пунктах 5.2 та 5.5, за допомогою тих, що були встановлені під час 5.2 Database setup та 5.5 Monit setup.

Ви можете редагувати дані із зашифрованих 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', 'pid', 'puma.state')
sidekiq_state_file = File.join(shared_path, 'tmp', 'pid', 'sidekiq.pid')
maintenance_file = File.join(shared_path, 'tmp', 'maintenance')

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

Використання ключів 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
/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/pid 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/pid/puma.pid'
state_path '<%= @project_root %>/shared/tmp/pid/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/pid/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/pid і public/systemза замовчуванням). Після цього вам потрібно створити будь-які необхідні каталоги (tmp, public і configза замовчуванням), якщо їх не існує. Наприкінці цього кроку ви посилаєтеся на спільні каталоги в поточний release, public/system, tmp/pidта logкаталоги, а потім — на releaseу current.
  4. Restart перезапустіть додаток, використовуючи команду restart у recipe.

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

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

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

timestamped_deploy node['domain'] 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/pid' => 'tmp/pid',
 'tmp/sockets' => 'tmp/sockets'
)

 # Map files in a shared directory to release the current 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 за допомогу у підготовці матеріалу.

Опубліковано: 02/11/18 @ 11:00
Розділ Різне

Рекомендуємо:

Як валідувати продуктові гіпотези. Досвід Google, MacPaw і SendPulse
Финстрип за Жовтень 2018, інфо-сайти. Вперше 100К+
Чому Java все ще не торт. Yet
DOU Hobby: Мотоподорожі — незамінний інструмент для звільнення мозку від зайвого
Скільки можна підняти на пуш підписки? І потім зрости на 50% ;)