SlideShare a Scribd company logo
minaについて
そろそろ語っておくか

                   shibuya.rb
      SEO Naotoshi (@sonots)
                2013/04/17
自己紹介
describe Sonots do
 its(:last_name} { should == ”瀬尾” }
 its(:twitter) { should == ”@sonots” }
 its(:company) { should == :DeNA }
 its(:job_title) { should == ”Infra Engineer” }

 it_should_behave_like ”DeNA employee”
end

shared_examples_for ”DeNA employee” do
 it { should write(:perl) } #=> fail
end
最近やってること



 なにか画像が
 あった気がす
    る     Haikanko
Haikanko
 なにか画像があった気がする




-配管工-
Haikanko
• Fluentd クラスタ管理ツール
• sinatra / erb / mina
• 詳しくはブログで http://blog.livedoor.jp/
 sonots/archives/25694161.html
mina
(ミーナ?ミナ?)
Yet another

Capistrano
Mina works really fast because it’s a
deploy Bash script generator.

It generates an entire procedure as a
Bash script and runs it remotely in the
server.

    シェルスクリプトを生成して、
     リモートサーバで実行する
Compare this to the likes of Vlad or
Capistrano, Mina only creates one SSH
session per deploy, minimizing the
SSH connection overhead.


    Capistrano と違って、
  1度しかSSHセッションを開かない
            速い
サンプル
config/deploy.rb                          $   gem install mina
require 'mina/git'                       $   mina init
require 'mina/bundler'                   $   mina deploy
require 'mina/rails'                     $   mina restart

set :domain, 'your.server.com'
set :user,   'your_username'
set :repository, 'https://github.com/xxx/repo.git’

task :deploy do
  deploy do
    invoke :'git:clone'
    invoke :'deploy:link_shared_path'
    invoke :'bundle:install'
  end
end

task :restart do
  queue! %[sudo service restart nginx]
end
サンプル(2)
                                        $ mina setup #=>
config/deploy.rb
                                        !"" current
                                        !"" releases
require 'mina/rbenv'
                                        #"" shared
                                            !"" config
task :environment do
                                            $   #"" database.yml
  invoke :'rbenv:load'
                                            #"" log
  # invoke :'rvm:use'
end

task :setup => :environment do
  queue! %[mkdir -p "#{deploy_to}/shared/log"]
  queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/log"]

  queue! %[mkdir -p "#{deploy_to}/shared/config"]
  queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/config"]

  queue! %[touch "#{deploy_to}/shared/config/database.yml"]
  queue %[echo "-----> Be sure to edit 'shared/config/
database.yml'."]
end
シェルスクリプト臭
シェルスクリプト臭

   だがそれ
    がいい
  (なにか画像があ
   った気がする)
• queue or queue! でコマンドを enqueue
• task を実行すると :domain に指定したホ
  ストでシェルスクリプトを生成して実行

• mina {task_name} --simulate # dry-run
• mina {task_name} --verbose
 • queue! で指定したコマンドを echo
 • queue! だけでおk
ここから
(個人的に)
  本題
Haikanko で
    どのように
mina を使っているか
設定ファイル                                     Fluentdクラスタ
<source>
  type forward
  port <%= port %>
</source>

<% archivers.each do |archiver| %>
<match raw.<%= archiver.agent_tag %>.**>
  type copy

  <store>
    stdout
  </store>

  <store>                                        deploy
    type file_alternative
    path <%= archiver.path %>
    output_include_time false
    output_include_tag false
    output_data_type attr:message
    add_newline true
    compress gz
  </store>

  <%= erb :'_flowcounter' %>
</match>
<% end %>
ディレクトリ構造
                 require ‘boot.rb’のみ

config
`-- deploy.rb
pipework         通常ファイル
|-- boot.rb
|-- files/
|-- mina/                 mina レシピ
`-- templates/



                    erb ファイル
remote_file               拡張メソッド
def remote_file(target_path, source_path = nil)
  if block_given?
    contents = yield
    source_path = create_tempfile(contents)
  elsif source_path
    source_path = File.expand_path(source_path, files_dir)
  end
  queue! %[sudo mkdir -p $(dirname #{target_path})]
  queue! %[sudo rsync -a #{localhost}:#{source_path} #{target_path}]
end


template_file
def template_file(target_path, template_path, options = {})
  remote_file(target_path) do
    template_path = "#{template_path}.erb" unless File.extname(template_path) == ".erb"
    template_path = File.expand_path(template_path, templates_dir)
    Tilt.new(template_path).render(self, options[:locals])
  end
end

remote_directory
def remote_directory(target_path, source_path)
  source_path = File.expand_path(source_path, files_dir)
  queue! %[sudo mkdir -p $(dirname #{target_path})]
  queue! %[sudo rsync -a --delete #{localhost}:#{source_path}/ #{target_path}/]
end
chef
インスパイア
       :D
multistage 対応
capistrano/ext            config/haikanko.yml
multistage                defaults: &defaults
                            repository: ‘haikanko’
config                      branch: 'master'
|-- deploy.rb
`-- deploy                development:
    |-- staging.rb          <<: *defaults
    |-- sandbox.rb          host: localhost
    `-- production.rb
                          test:
                            <<: *defaults
                            host: localhost

                          staging:
                            <<: *defaults
                            host: xxxxxxx


       https://github.com/ngmoco/bootloader
コマンドオプション
• mina は rake ベース
 task :deploy, :host, :hoge do |t, args|
   set :domain, args[:host]
   puts args[:hoge]
 end                              \(^0^)/
 $ mina ”deploy[localhost,foobar]”




    環境変数で         ※なんとかしたいとは思っている

 task :deploy
   set :domain, ENV[‘HOST’]
   puts ENV[‘HOGE’]
 end

 $ HOST=localhost HOGE=foobar mina deploy
複数サーバ
multi_invoke
def multi_invoke(task, domains, args = [])
  isolate do
    domains.each do |domain|
      set :domain, domain
     yield if block_given?
     run! if commands.any?
     Rake::Task.tasks.each {|t| t.reenable }
    end
  end
end


            rake タスクは1度実行するとフラグが立って、実行できなくなる
            複数ホストに対して実行できるようなメソッドを用意
まとめ
良いところ
• SSHセッション1回
• シェルスクリプト脳(個人的な意見)
• シェルスクリプトノウハウ詰まってる
悪いところ
• rake のオプションキモい
• 途中に処理挟めない
  task :setup => :environment do
    queue! %[cd]
    a = Tempfile.new #=> 最初に実行
    queue! %[ls]
  end
Haikankoでは
• デプロイツールなのに、プロビジョニン
 グツール(chef)っぽく使っている

• こういうプロビジョニングツールあって
 もいいかもね

• なんか作りたい
お知らせ
• haikanko を github におきました
• テスト足りてない ^^;
   https://github.com/sonots/haikanko

• プルリク歓迎

More Related Content

Mina 20130417

  • 1. minaについて そろそろ語っておくか shibuya.rb SEO Naotoshi (@sonots) 2013/04/17
  • 2. 自己紹介 describe Sonots do its(:last_name} { should == ”瀬尾” } its(:twitter) { should == ”@sonots” } its(:company) { should == :DeNA } its(:job_title) { should == ”Infra Engineer” } it_should_behave_like ”DeNA employee” end shared_examples_for ”DeNA employee” do it { should write(:perl) } #=> fail end
  • 5. Haikanko • Fluentd クラスタ管理ツール • sinatra / erb / mina • 詳しくはブログで http://blog.livedoor.jp/ sonots/archives/25694161.html
  • 8. Mina works really fast because it’s a deploy Bash script generator. It generates an entire procedure as a Bash script and runs it remotely in the server. シェルスクリプトを生成して、 リモートサーバで実行する
  • 9. Compare this to the likes of Vlad or Capistrano, Mina only creates one SSH session per deploy, minimizing the SSH connection overhead. Capistrano と違って、 1度しかSSHセッションを開かない 速い
  • 10. サンプル config/deploy.rb $ gem install mina require 'mina/git' $ mina init require 'mina/bundler' $ mina deploy require 'mina/rails' $ mina restart set :domain, 'your.server.com' set :user, 'your_username' set :repository, 'https://github.com/xxx/repo.git’ task :deploy do deploy do invoke :'git:clone' invoke :'deploy:link_shared_path' invoke :'bundle:install' end end task :restart do queue! %[sudo service restart nginx] end
  • 11. サンプル(2) $ mina setup #=> config/deploy.rb !"" current !"" releases require 'mina/rbenv' #"" shared !"" config task :environment do $   #"" database.yml   invoke :'rbenv:load' #"" log # invoke :'rvm:use' end task :setup => :environment do   queue! %[mkdir -p "#{deploy_to}/shared/log"]   queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/log"]   queue! %[mkdir -p "#{deploy_to}/shared/config"]   queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/config"]   queue! %[touch "#{deploy_to}/shared/config/database.yml"]   queue %[echo "-----> Be sure to edit 'shared/config/ database.yml'."] end
  • 13. シェルスクリプト臭 だがそれ がいい (なにか画像があ った気がする)
  • 14. • queue or queue! でコマンドを enqueue • task を実行すると :domain に指定したホ ストでシェルスクリプトを生成して実行 • mina {task_name} --simulate # dry-run • mina {task_name} --verbose • queue! で指定したコマンドを echo • queue! だけでおk
  • 16. Haikanko で どのように mina を使っているか
  • 17. 設定ファイル Fluentdクラスタ <source>   type forward   port <%= port %> </source> <% archivers.each do |archiver| %> <match raw.<%= archiver.agent_tag %>.**>   type copy <store> stdout </store>   <store> deploy     type file_alternative     path <%= archiver.path %>     output_include_time false     output_include_tag false     output_data_type attr:message     add_newline true     compress gz   </store> <%= erb :'_flowcounter' %> </match> <% end %>
  • 18. ディレクトリ構造 require ‘boot.rb’のみ config `-- deploy.rb pipework 通常ファイル |-- boot.rb |-- files/ |-- mina/ mina レシピ `-- templates/ erb ファイル
  • 19. remote_file 拡張メソッド def remote_file(target_path, source_path = nil)   if block_given?     contents = yield     source_path = create_tempfile(contents)   elsif source_path     source_path = File.expand_path(source_path, files_dir)   end   queue! %[sudo mkdir -p $(dirname #{target_path})]   queue! %[sudo rsync -a #{localhost}:#{source_path} #{target_path}] end template_file def template_file(target_path, template_path, options = {})   remote_file(target_path) do     template_path = "#{template_path}.erb" unless File.extname(template_path) == ".erb"     template_path = File.expand_path(template_path, templates_dir)     Tilt.new(template_path).render(self, options[:locals])   end end remote_directory def remote_directory(target_path, source_path)   source_path = File.expand_path(source_path, files_dir)   queue! %[sudo mkdir -p $(dirname #{target_path})]   queue! %[sudo rsync -a --delete #{localhost}:#{source_path}/ #{target_path}/] end
  • 21. multistage 対応 capistrano/ext config/haikanko.yml multistage defaults: &defaults   repository: ‘haikanko’ config   branch: 'master' |-- deploy.rb `-- deploy development: |-- staging.rb   <<: *defaults |-- sandbox.rb   host: localhost `-- production.rb test:   <<: *defaults   host: localhost staging:   <<: *defaults   host: xxxxxxx https://github.com/ngmoco/bootloader
  • 22. コマンドオプション • mina は rake ベース task :deploy, :host, :hoge do |t, args| set :domain, args[:host] puts args[:hoge] end \(^0^)/ $ mina ”deploy[localhost,foobar]” 環境変数で ※なんとかしたいとは思っている task :deploy set :domain, ENV[‘HOST’] puts ENV[‘HOGE’] end $ HOST=localhost HOGE=foobar mina deploy
  • 23. 複数サーバ multi_invoke def multi_invoke(task, domains, args = [])   isolate do     domains.each do |domain|     set :domain, domain      yield if block_given?      run! if commands.any?      Rake::Task.tasks.each {|t| t.reenable } end end end rake タスクは1度実行するとフラグが立って、実行できなくなる 複数ホストに対して実行できるようなメソッドを用意
  • 26. 悪いところ • rake のオプションキモい • 途中に処理挟めない task :setup => :environment do   queue! %[cd] a = Tempfile.new #=> 最初に実行   queue! %[ls] end
  • 27. Haikankoでは • デプロイツールなのに、プロビジョニン グツール(chef)っぽく使っている • こういうプロビジョニングツールあって もいいかもね • なんか作りたい
  • 28. お知らせ • haikanko を github におきました • テスト足りてない ^^; https://github.com/sonots/haikanko • プルリク歓迎