Tôi đã định cấu hình môi trường đầu bếp và tôi có thể triển khai ứng dụng của mình bằng cách sử dụng capistrano. Bây giờ tôi muốn đầu bếp để xử lý capistrano để triển khai ứng dụng của tôi. Nó được hoàn thiện bằng cách nào ?Cách liên kết đầu bếp với capistrano để triển khai
Trả lời
Bạn có thể xem Foodfightshow Episode về Application Deployment.
Bạn có thể, ví dụ: đặt các tệp cấu hình (ví dụ: thông tin đăng nhập cơ sở dữ liệu) vào máy chủ bằng Đầu bếp, đồng thời đẩy mã nguồn bằng Capistrano.
Bạn không thể. Hoặc ít nhất nó sẽ không đơn giản.
Đầu bếp là hệ thống kéo - khách hàng lấy thông tin từ máy chủ Đầu bếp và thực hiện hành động theo đó.
Capistrano là hệ thống đẩy - bạn yêu cầu nó đăng nhập vào máy chủ và thực hiện các tác vụ ở đó.
Cách duy nhất tôi thấy để bạn tích hợp chúng là chạy Capistrano cục bộ trên mỗi máy, nhưng tôi không thấy lý do cho điều đó.
Tài nguyên triển khai của đầu bếp có thể làm mọi thứ bạn cần mà không cần tích hợp Capistrano. Nếu bạn vẫn muốn đẩy triển khai của bạn đến các máy chủ độc lập từ đầu bếp-khách hàng chạy, bạn tốt hơn không triển khai thông qua đầu bếp và giữ hệ thống hiện tại của bạn.
Nếu bạn muốn phân phối liên tục, hãy treo các tập lệnh Capistrano của bạn lên máy chủ CI và chạy chúng ở cuối đường ống.
podcast được giới thiệu bởi @StephenKing là nguồn thông tin tuyệt vời về vấn đề này.
Tôi làm ngược lại, ví dụ: triển khai công thức nấu ăn Chef của tôi thông qua Capistrano. Tôi khuyến khích điều đó.
#config/deploy.rb
...
before 'bundle:install', "provision:default", "deploy:config_db_yml_symlink"
...
Điều này sẽ thực hiện cấu hình đầu bếp cho máy chủ sau khi cài đặt gói, điều quan trọng vì rất nhiều đá quý dựa vào các gói đang được cài đặt cho hệ điều hành.
#config/deploy/provision.rb
Capistrano::Configuration.instance(:must_exist).load do
namespace :provision do
task :default do
provision.setup
provision.web
provision.db
provision.db_slave
end
task :setup, once: true do
provision.get_environment_variables
provision.update_cookbooks
end
task :db, :roles => :db do
next if find_servers_for_task(current_task).empty?
if rails_env == 'staging'
run %{cd #{release_path}/provision; sudo chef-solo -c solo.rb -j db.json -l debug}
else
run %{cd #{release_path}/provision; sudo chef-solo -c solo.rb -j db_master.json -l debug}
end
end
task :db_slave, :roles => :db_slave do
next if find_servers_for_task(current_task).empty?
run %{cd #{release_path}/provision; sudo chef-solo -c solo.rb -j db_slave.json -l debug}
end
task :web, :roles => :web do
next if find_servers_for_task(current_task).empty?
run %{cd #{release_path}/provision; sudo chef-solo -c solo.rb -j web.json -l debug}
end
task :get_environment_variables do
run "if [ -d ~/.config ]; then " +
"cd ~/.config && git fetch && git reset origin/master --hard; " +
"else git clone [email protected]:mycompany/config.git .config; fi"
run "sudo cp ~/.config/secureshare/#{rails_env}/environment /etc/environment"
end
task :update_cookbooks do
run "if [ -d /u/chef ]; then " +
"cd /u/chef && git fetch && git reset origin/master --hard; " +
"else git clone [email protected]:mycompany/chef.git /u/chef; fi"
end
end
namespace :deploy do
task :setup, :except => { :no_release => true } do
dirs = [deploy_to, releases_path, shared_path]
dirs += shared_children.map { |d| File.join(shared_path, d.split('/').last) }
dirs += [File.join(shared_path, 'sockets')]
run "#{try_sudo} mkdir -p #{dirs.join(' ')}"
run "#{try_sudo} chmod g+w #{dirs.join(' ')}" if fetch(:group_writable, true)
run "#{try_sudo} chown -R ubuntu:ubuntu #{dirs.join(' ')}" if fetch(:group_writable, true)
end
task :config_db_yml_symlink do
run "ln -s #{shared_path}/database.yml #{release_path}/config/database.yml"
end
end
end
Tôi có một thư mục trong dự án có tên là provision, để xử lý định nghĩa của vai trò đầu bếp, mặc dù công thức nấu ăn nằm trong một kho lưu trữ khác.
#provision/solo.rb
root = File.absolute_path(File.dirname(__FILE__))
cookbook_path '/u/chef'
role_path root + "/roles"
log_level :debug
log_location STDOUT
Nodes được định nghĩa trong dự án
#provision/db_slave.json
{
"run_list": ["role[db_slave]"]
}
Và vai trò
#provision/roles/db_slave.rb
name "db_slave"
description 'A postgresql slave.'
run_list(["recipe[base]", "recipe[postgresql::slave]", "recipe[rails]","recipe[papertrail]", "recipe[fail2ban]"])
override_attributes(
'kernel' => {
'shmmax' => ENV['KERNEL_SHMMAX'],
'shmall' => ENV['KERNEL_SHMALL'],
'msgmax' => ENV['KERNEL_MSGMAX'],
'msgmnb' => ENV['KERNEL_MSGMNB']
},
'postgresql' => {
'user' => ENV['PG_USER'],
'password' => ENV['PG_PASSWORD'],
'database' => ENV['PG_DATABASE'],
'master_host' => ENV['PG_HOST']
},
'app_dir' => ENV['APP_DIR'],
'papertrail' => {
'port' => ENV['PAPERTRAIL_PORT'],
'log_files' => [
"#{ENV['APP_DIR']}/shared/log/*.log",
"/var/log/*.log",
"/var/log/syslog",
"/var/log/upstart/*.log",
"/var/log/postgresql/*.log"
]
},
'new_relic' => {
'key' => ENV['NEW_RELIC_LICENSE_KEY']
})
Tất cả mà không giữ bất kỳ thông tin nhạy cảm trong ứng dụng. Tôi cũng sử dụng capistrano-ec2group để ánh xạ các máy chủ đến các vai trò sử dụng các nhóm bảo mật EC2.
group :myapp_web, :web
group :myapp_web, :app
group :myapp_db, :db, :primary=>true
group :myapp_db_slave, :db_slave
Vì vậy, về cơ bản bạn giữ công thức nấu ăn của bạn đầu bếp trong một repo, các biến môi trường của bạn trong repo khác, và ứng dụng của bạn trong repo khác - và sử dụng Capistrano để cả hai máy chủ cung cấp và triển khai ứng dụng của bạn.
Bạn cũng có thể giữ công thức nấu ăn đầu bếp trong kho ứng dụng của mình, nhưng điều đó ngăn cản việc tái sử dụng giữa dự án. Điều quan trọng là đặt mọi thứ thay đổi thành biến môi trường và lưu trữ chúng riêng biệt với ứng dụng và công thức nấu ăn.
Khi điều này được cấu hình đúng, để thêm các máy chủ mới, bạn chỉ cần quay một trong EC2, áp dụng các nhóm an ninh cần thiết rồi
cap deploy