LoginSignup
12
11

More than 5 years have passed since last update.

requirettyが有効なイメージを使用する

Posted at

基本的にVagrantはプロビジョニングを行う際sudoをつけてコマンドを実行しますが、Boxでrequirettyが有効になっていると作成した仮想マシン上でsudoをつけてコマンドが実行できずエラーが発生してしまいます。

クラウド系のプラグインはサービスプロバイダが提供しているイメージ・テンプレートをボックスとして使用するものが多いので、そのままではrequirettyが有効になっている場合があります。自分でrequirettyを無効化したイメージを作成し直すこともできますが、
既存のイメージを使用することができればサービスプロバイダが提供している様々なイメージが利用しやすくなります。

そこで今回はrequirettyが有効なイメージを使用する方法を調べてみます。

今回調べた方法はあくまで一時的にrequirettyを回避する方法です。何度も使用するイメージについてはrequirettyを無効化しておいた方が後で問題がでないと思います。

TL;DR

  • requirettyが有効なテンプレートでもconfig.ssh.pty=trueとすることでsudoをすることができる。
  • ログインユーザーがrootであればconfig.ssh.sudo_commandを使ってsudo無しでコマンドを実行するように設定できる
  • Rsync Synced Folderを使う場合rsync__rsync_pathでsudo無しでrsyncを実行するよう設定できる

環境

動作の確認は以下の環境で行いました。

  • Vagrant (1.7.4)
  • vagrnt-cloudstack (1.1.0)
  • IDCFクラウド

Vagrantfile

以下のVagrntfileをテスト用に使用します。

vagrant-cloudstackを使用してIDCFクラウド上にVMを作成しています。IDCFクラウドにはrequirettyが無効化されたVagrant用のテンプレートが用意されているのですが、ここではあえてVagrant用でないrequirettyが有効なテンプレートを使用します。

IDCFクラウドのテンプレートの仕様でデフォルトのログインユーザーがrootのためoverride.ssh.username = "root"でログインユーザーをrootとしてあります。また、後述するようにrequirettyが有効な場合Rsync Synced Folderにも影響があるのでいったん無効化しておきます。

Vagrantfile
Vagrant.configure("2") do |config|                                                 
  config.vm.provider :cloudstack do |cloudstack, override|                         
    override.vm.box = "dummy"                                                      
    override.vm.box_url = "https://github.com/schubergphilis/vagrant-cloudstack/raw/master/dummy.box"

    cloudstack.host    = "compute.jp-east.idcfcloud.com"                           
    cloudstack.path    = "/client/api"                                             
    cloudstack.port    = "443"                                                     
    cloudstack.scheme  = "https"                                                   

    cloudstack.api_key    = "#{ENV['CLOUDSTACK_API_KEY']}"                         
    cloudstack.secret_key = "#{ENV['CLOUDSTACK_SECRET_KEY']}"                      

    cloudstack.zone_name             = "pascal"                                    
    cloudstack.template_name         = "CentOS 6.6 64-bit"                         
    cloudstack.service_offering_name = "light.S1"                                  

    cloudstack.pf_ip_address   = "#{ENV['PUBLIC_IP_ADDRESS']}"                     
    cloudstack.pf_public_port  = 2222                                              
    cloudstack.pf_private_port = 22                                                

    cloudstack.keypair            = "#{ENV['CLOUDSTACK_SSH_KEYPAIR']}"             

    override.ssh.username         = "root"                                         
    override.ssh.host             = "#{ENV['PUBLIC_IP_ADDRESS']}"                  
    override.ssh.private_key_path = "#{ENV['VAGRANT_SSH_PRIVATE_KEY']}"                                         
  end                                                                                                                            

  # Synced Folderを無効化                                                                                 
  config.vm.synced_folder ".", "/vagrant", disabled: true

  # Shell Provisionerの実行                                                                                 
  config.vm.provision "shell",                                  
        inline: "echo Hello, World"                                                
end                                                                              

Shell Provisionerを使う

requiretty有効時のShell Provisionerのエラー

環境変数をセットしてvagrant upvagrant provision)を実行すると次のエラーが発生します。これはShell Provisionerがsudoでコマンドを実行しようした際にttyがないため発生しているエラーです。

==> default: Running provisioner: shell...
    default: Running: inline script
==> default: sudo
==> default: : 
==> default: sudo を実行するには tty がなければいけません。すみません
The SSH command responded with a non-zero exit status. Vagrant
assumes that this means the command failed. The output for this command
should be in the log above. Please read the output to determine what
went wrong.

config.ssh.ptyをtrueにしてptyを使用してエラーを回避する

このエラーの回避方法の一つは、config.ssh.ptytrueとして、ptyを使用するようにすることです。

config.ssh - Vagrantfile - Vagrant Documentation

Vagrantfile
Vagrant.configure("2") do |config|                                                 
  config.vm.provider :cloudstack do |cloudstack, override|                         
    override.vm.box = "dummy"                                                      
    override.vm.box_url = "https://github.com/schubergphilis/vagrant-cloudstack/raw/master/dummy.box"

    cloudstack.host    = "compute.jp-east.idcfcloud.com"                           
    cloudstack.path    = "/client/api"                                             
    cloudstack.port    = "443"                                                     
    cloudstack.scheme  = "https"                                                   

    cloudstack.api_key    = "#{ENV['CLOUDSTACK_API_KEY']}"                         
    cloudstack.secret_key = "#{ENV['CLOUDSTACK_SECRET_KEY']}"                      

    cloudstack.zone_name             = "pascal"                                    
    cloudstack.template_name         = "CentOS 6.6 64-bit"                         
    cloudstack.service_offering_name = "light.S1"                                  

    cloudstack.pf_ip_address   = "#{ENV['PUBLIC_IP_ADDRESS']}"                     
    cloudstack.pf_public_port  = 2222                                              
    cloudstack.pf_private_port = 22                                                

    cloudstack.keypair            = "#{ENV['CLOUDSTACK_SSH_KEYPAIR']}"             

    override.ssh.username         = "root"                                         
    override.ssh.host             = "#{ENV['PUBLIC_IP_ADDRESS']}"                  
    override.ssh.private_key_path = "#{ENV['VAGRANT_SSH_PRIVATE_KEY']}" 
    override.ssh.pty              = true                                        
  end                                                                                                                            

  # Synced Folderを無効化                                                                                 
  config.vm.synced_folder ".", "/vagrant", disabled: true

  # Shell Provisionerの実行                                                                                 
  config.vm.provision "shell",                                  
        inline: "echo Hello, World"                                                
end                                                                              
==> default: Running provisioner: shell...
    default: Running: inline script
==> default: Hello, World

config.ssh.sudo_commandでsudoを無効化する

今回の例ではrootでログインしているのでコマンドにsudoをつける必要がありません。
したがって、config.ssh.sudo_commandを上書きしてsudo無しでコマンドを実行するように設定することでエラーを回避することもできます。

config.ssh - Vagrantfile - Vagrant Documentation

Vagrantfile
Vagrant.configure("2") do |config|                                                 
  config.vm.provider :cloudstack do |cloudstack, override|                         
    override.vm.box = "dummy"                                                      
    override.vm.box_url = "https://github.com/schubergphilis/vagrant-cloudstack/raw/master/dummy.box"

    cloudstack.host    = "compute.jp-east.idcfcloud.com"                           
    cloudstack.path    = "/client/api"                                             
    cloudstack.port    = "443"                                                     
    cloudstack.scheme  = "https"                                                   

    cloudstack.api_key    = "#{ENV['CLOUDSTACK_API_KEY']}"                         
    cloudstack.secret_key = "#{ENV['CLOUDSTACK_SECRET_KEY']}"                      

    cloudstack.zone_name             = "pascal"                                    
    cloudstack.template_name         = "CentOS 6.6 64-bit"                         
    cloudstack.service_offering_name = "light.S1"                                  

    cloudstack.pf_ip_address   = "#{ENV['PUBLIC_IP_ADDRESS']}"                     
    cloudstack.pf_public_port  = 2222                                              
    cloudstack.pf_private_port = 22                                                

    cloudstack.keypair            = "#{ENV['CLOUDSTACK_SSH_KEYPAIR']}"             

    override.ssh.username         = "root"                                         
    override.ssh.host             = "#{ENV['PUBLIC_IP_ADDRESS']}"                  
    override.ssh.private_key_path = "#{ENV['VAGRANT_SSH_PRIVATE_KEY']}"
    override.ssh.sudo_command     = "%c"                                      
  end                                                                                                                            

  # Synced Folderを無効化                                                                                 
  config.vm.synced_folder ".", "/vagrant", disabled: true

  # Shell Provisionerの実行                                                                                 
  config.vm.provision "shell",                             
        inline: "echo Hello, World"                                                
end 

privilegedオプションをfalseにしてコマンドをsudo無しで実行する

sudo無しでコマンドを実行するように設定することは、Shell Provisionerのprivilegedオプションをfalseにすることによっても可能です。この方法でもエラーを回避することができます。

この設定はShell Provisionerのみに影響します。他のVagrantコマンドがsudoを使用している場合にはこの方法で対応することはできません。

Vagrantfile
Vagrant.configure("2") do |config|                                                 
  config.vm.provider :cloudstack do |cloudstack, override|                         
    override.vm.box = "dummy"                                                      
    override.vm.box_url = "https://github.com/schubergphilis/vagrant-cloudstack/raw/master/dummy.box"

    cloudstack.host    = "compute.jp-east.idcfcloud.com"                           
    cloudstack.path    = "/client/api"                                             
    cloudstack.port    = "443"                                                     
    cloudstack.scheme  = "https"                                                   

    cloudstack.api_key    = "#{ENV['CLOUDSTACK_API_KEY']}"                         
    cloudstack.secret_key = "#{ENV['CLOUDSTACK_SECRET_KEY']}"                      

    cloudstack.zone_name             = "pascal"                                    
    cloudstack.template_name         = "CentOS 6.6 64-bit"                         
    cloudstack.service_offering_name = "light.S1"                                  

    cloudstack.pf_ip_address   = "#{ENV['PUBLIC_IP_ADDRESS']}"                     
    cloudstack.pf_public_port  = 2222                                              
    cloudstack.pf_private_port = 22                                                

    cloudstack.keypair            = "#{ENV['CLOUDSTACK_SSH_KEYPAIR']}"             

    override.ssh.username         = "root"                                         
    override.ssh.host             = "#{ENV['PUBLIC_IP_ADDRESS']}"                  
    override.ssh.private_key_path = "#{ENV['VAGRANT_SSH_PRIVATE_KEY']}"                                        
  end                                                                                                                            

  # Synced Folderを無効化                                                                                 
  config.vm.synced_folder ".", "/vagrant", disabled: true

  # Shell Provisionerの実行                                                                                 
  config.vm.provision "shell", privileged: false,                              
        inline: "echo Hello, World"                                                
end                                                                              

Rsync Synced Folderを使う

Rsync Synced Folderを使うためには作成した仮想マシンにディレクトリを作成し、ローカルのデータをコピーできるようにする必要があります。

vagrantユーザーで/vagrantを作成する等、一般ユーザーでは権限が不足している場合があるためディレクトリの作成等のコマンドはsudoを付けて実行されます。したがって、Shell Provisionerの場合と同様config.ssh.ptyconfig.ssh.sudo_commandを設定しrequiretty有効時でもコマンドを実行できるようにしておく必要があります。(Shell ProvisionernのprivilegedオプションはShell Provisionerの動作にのみ影響するのでSynced Folderを使うためには使用できません。)

例えば、config.ssh.pty=trueとした状態でSynced Folderを有効化してみます。

Vagrantfile
Vagrant.configure("2") do |config|                                                 
  config.vm.provider :cloudstack do |cloudstack, override|                         
    override.vm.box = "dummy"                                                      
    override.vm.box_url = "https://github.com/schubergphilis/vagrant-cloudstack/raw/master/dummy.box"

    cloudstack.host    = "compute.jp-east.idcfcloud.com"                           
    cloudstack.path    = "/client/api"                                             
    cloudstack.port    = "443"                                                     
    cloudstack.scheme  = "https"                                                   

    cloudstack.api_key    = "#{ENV['CLOUDSTACK_API_KEY']}"                         
    cloudstack.secret_key = "#{ENV['CLOUDSTACK_SECRET_KEY']}"                      

    cloudstack.zone_name             = "pascal"                                    
    cloudstack.template_name         = "CentOS 6.6 64-bit"                         
    cloudstack.service_offering_name = "light.S1"                                  

    cloudstack.pf_ip_address   = "#{ENV['PUBLIC_IP_ADDRESS']}"                     
    cloudstack.pf_public_port  = 2222                                              
    cloudstack.pf_private_port = 22                                                

    cloudstack.keypair            = "#{ENV['CLOUDSTACK_SSH_KEYPAIR']}"             

    override.ssh.username         = "root"                                         
    override.ssh.host             = "#{ENV['PUBLIC_IP_ADDRESS']}"                  
    override.ssh.private_key_path = "#{ENV['VAGRANT_SSH_PRIVATE_KEY']}" 
    override.ssh.pty              = true                                        
  end                                                                                                                            

  # Shell Provisionerの実行                                                                                 
  config.vm.provision "shell",                                  
        inline: "echo Hello, World"                                                
end                                                                              

しかし、これを実行すると次のようなエラーとなります。

==> default: Rsyncing folder: /Users/atsaki/gitrepos/vagrant-examples/centos/ => /vagrant
There was an error when attempting to rsync a synced folder.
Please inspect the error message below for more info.

Host path: /Users/atsaki/gitrepos/vagrant-examples/centos/
Guest path: /vagrant
Command: rsync --verbose --archive --delete -z --copy-links --no-owner --no-group --rsync-path sudo rsync -e ssh -p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i '/Users/atsaki/.ssh/id_rsa_idcfcloud' --exclude .vagrant/ /Users/atsaki/gitrepos/vagrant-examples/centos/ root@xxx.xxx.xxx.xxx:/vagrant
Error: Warning: Permanently added '[xxx.xxx.xxx.xxx]:2222' (RSA) to the list of known hosts.
sudo: sudo を実行するには tty がなければいけません。すみません
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at /SourceCache/rsync/rsync-42/rsync/io.c(452) [sender=2.6.9]

このエラーはrsyncコマンドの--rsync-path "sudo rsync"のsudoがttyなしで実行されるため発生しています。

rsync__rsync_pathで--rsync-pathからsudoを除く

ログインユーザがrootの場合、--rsync-pathのsudoは不要なのでrsync__rsync_pathオプションで--rsync-pathからsudoを除くことでエラーを回避することができます。

ログインユーザーがrootでない場合でも権限があるディレクトリをSynced Folderにする場合には同様の方法で対応できると思います。

Vagrantfile
Vagrant.configure("2") do |config|                                                 
  config.vm.provider :cloudstack do |cloudstack, override|                         
    override.vm.box = "dummy"                                                      
    override.vm.box_url = "https://github.com/schubergphilis/vagrant-cloudstack/raw/master/dummy.box"

    cloudstack.host    = "compute.jp-east.idcfcloud.com"                           
    cloudstack.path    = "/client/api"                                             
    cloudstack.port    = "443"                                                     
    cloudstack.scheme  = "https"                                                   

    cloudstack.api_key    = "#{ENV['CLOUDSTACK_API_KEY']}"                         
    cloudstack.secret_key = "#{ENV['CLOUDSTACK_SECRET_KEY']}"                      

    cloudstack.zone_name             = "pascal"                                    
    cloudstack.template_name         = "CentOS 6.6 64-bit"                         
    cloudstack.service_offering_name = "light.S1"                                  

    cloudstack.pf_ip_address   = "#{ENV['PUBLIC_IP_ADDRESS']}"                     
    cloudstack.pf_public_port  = 2222                                              
    cloudstack.pf_private_port = 22                                                

    cloudstack.keypair            = "#{ENV['CLOUDSTACK_SSH_KEYPAIR']}"             

    override.ssh.username         = "root"                                         
    override.ssh.host             = "#{ENV['PUBLIC_IP_ADDRESS']}"                  
    override.ssh.private_key_path = "#{ENV['VAGRANT_SSH_PRIVATE_KEY']}"            
    override.ssh.pty              = true                                           
  end                                                                              

  # rsync__rsync_pathで--rsync-pathからsudoを除く                                                  
  config.vm.synced_folder ".", "/vagrant", type: "rsync",                          
    rsync__rsync_path: "rsync"                                                     

  # Shell Provisionerの実行                                                        
  config.vm.provision "shell",                                                     
        inline: "echo Hello, World"                                                
end                           

参考資料

12
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
11