Memo/Vagrant

https://dexlab.net:443/pukiwiki/index.php?Memo/Vagrant
 

Vagrant

  • http://www.vagrantup.com/
    • 仮想マシンの VirtualBox, Amazon EC2 + VPC, VMware Fusion, Rackspace Cloud のCUIフロントエンドに相当する、rubyで書かれたツール。プログラミングでサーバ起動/終了/設定ができる
    • Vagrantfile は Ruby スクリプト。rubyの構文、関数が使える

S3にboxを置いて使う

「vagrant provision example」には非常に時間がかかる場合がある。
作成済みboxをs3 privateに置く事で、複数人の利用者が使う場合、boxのダウンロードだけという短時間で済む。

  • v1.3.2 はSTSに非対応。AssumeRoleが出来ない。
    • AWS STS credentials not supported · Issue #33 · WhoopInc/vagrant-s3auth
    • 例: ~/.aws/credentials
      [account1]
      aws_access_key_id = ****
      aws_secret_access_key = ****
      
      [account2]
      role_arn = arn:aws:iam::<account2 id>:role/<role name>
      source_profile = account1
    • 環境変数にSTSに必要な情報を設定すれば動作した
        ENV['AWS_PROFILE'] = 'example'
        ENV['AWS_REGION']  = 'ap-northeast-1'
        ENV['AWS_ACCESS_KEY_ID'] = 'AS***'
        ENV['AWS_SECRET_ACCESS_KEY'] = '***'
        ENV['AWS_SESSION_TOKEN'] = '***'
    • VMが複数ある場合、その個数分だけ呼ばれるので、1回だけセットする。AWS S3にアクセスするコマンド時のみ設定して、その他コマンド時に遅くならないように。
      def aws_credentials(aws_profile, aws_region)
        ENV.delete_if { |name| name.start_with?('AWS_') }  # Filter out rogue env vars.
        ENV['AWS_PROFILE'] = aws_profile
        ENV['AWS_REGION']  = aws_region
      
        unless ENV.has_key?('AWS_ACCESS_KEY_ID')
          sts_client = Aws::STS::Client.new(profile:  ENV['AWS_PROFILE'])
          caller_identity = sts_client.get_caller_identity()
      
          # https://docs.aws.amazon.com/sdkforruby/api/Aws/STS/Client.html#assume_role-instance_method
          role_arn = sprintf("arn:aws:iam::%s:role/%s", caller_identity.account, caller_identity.arn.split('/')[1])
          sts_creds = sts_client.assume_role({
            role_arn: role_arn,
            role_session_name: "vagrant",
          })
      
          ENV['AWS_ACCESS_KEY_ID'] = sts_creds.credentials.access_key_id
          ENV['AWS_SECRET_ACCESS_KEY'] = sts_creds.credentials.secret_access_key
          ENV['AWS_SESSION_TOKEN'] = sts_creds.credentials.session_token
        end
      end
      
      if vgconfig.has_key?("aws_profile") and ( ARGV[0].downcase == 'up' or ARGV[0].downcase == 'box' )
        aws_credentials(vgconfig["aws_profile"], vgconfig["aws_region"])
      end
    • s3のread権限があれば良さそうだが、何故かreadonly権限(ReadOnlyAccess)のprofileだと失敗した。
      Message: Aws::STS::Errors::AccessDenied: User: arn:aws:sts::***:assumed-role/***readonly/default_session is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::***:role/***readonly
    • awscliではReadOnlyAccessのprofileを指定しても問題なく、STSは取得できた。ruby sdkの使い方が間違ってそう。

Vagrantfile内

  • Vagrantfile内でrubyの関数が使える。
  • 「exit」で終了できる。
  • 関数が定義できる。

引数の取得

  • ARGV[0]: sub command
  • ARGV[1]: option1
  • Vagrantfile
    p ARGV
  • 実行
    vagrant box update
    ["box", "update"]

デバッグ

  • コマンド実行時に「--debug」オプションを付ける
  • Vagrantfile内でprintf()等のrubyの関数が使える。
    # 環境変数の表示
    p ENV
    printf("env: USER: %s\n", ENV["USER"])
  • ppを使って変数を見やすくダンプ
    require 'pp'
    pp ENV

boxファイルの圧縮

  • CentOS 6/7の場合。
    # yumのキャッシュを削除
    yum clean all
    # 圧縮が効きやすいように0で埋めて、消す。rmを2行に分割すると、 「/home/vagrant/.ansible/tmp/ansible-tmp-XXXX」で失敗するので、1行にした。
    dd if=/dev/zero of=/EMPTY bs=1M || echo "dd exit code $? is suppressed" && rm -f /EMPTY

環境:

  • VirtualBox 6.0.14
  • vagrant 2.2.6
  • box: centos/7 1910

サイズ:

  • centos/7: 415MB
  • centos/7 + vbguest: 900MB
  • centos/7 + vbguest + yum clean all + dd /EMPTY: 705MB

vboxmanageを使った圧縮:

  • VMのUUIDをメモ
    vboxmanage list hdds
    ...
    UUID:           xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    ...
  • vboxmanageの圧縮(--compact)が対応しているのが、.vdi形式のみ。.vmdk(VMware形式)は.vdiへ変換する
    vboxmanage clonehd <name>.vmdk <name>.vdi --format vdi
    vboxmanage modifyhd <name>.vdi --compact
    rm <name>.vmdk
    vboxmanage clonehd <name>.vdi <name>.vmdk --format vmdk

pluginの自動インストール

  • vagrant.yml
    vagrant_plugins:
    - vagrant-vbguest
    - vagrant-s3auth
  • Vagrantfile
    # -*- mode: ruby -*-
    # vi: set ft=ruby :
    
    require 'yaml'
    vgconfig = YAML.load_file 'vagrant.yml'
    
    def vagrant_plugins(plugins)
       plugins.each do |plugin|
        unless Vagrant.has_plugin?(plugin)
          # Attempt to install ourself. Bail out on failure so we don't get stuck in an
          # infinite loop.
          system('vagrant plugin install ' + plugin) || exit!
    
          # Relaunch Vagrant so the plugin is detected. Exit with the same status code.
          exit system('vagrant', *ARGV)
        end
       end
    end
    
    vagrant_plugins(vgconfig["vagrant_plugins"])

KVM用仮想マシンの作成

Linux上ではVirtualBoxよりKVMを使った方が起動等が早い。


構築済み環境のコピー

初期構築に時間がかかる場合、初期構築済みのboxを保存する事で時間を短縮できる。


cloud-initを使う


local-exec: ホストOSで実行

  • Vagrantfile: example/example をホストOSにclone
    config.push.define "local-exec" do |push|
      push.inline = <<-SCRIPT
        [ -d example ] || git clone git@github.com:example/example.git
      SCRIPT
    end
  • 実行
    vagrant push

loopで複数VMの構築

  • Loop Over VM Definitions
  • 変数が大きくなってくると辛いので yamlやansibleを検討する
    • ループに使う変数を間違える(正: vmconfig , 誤: config)と、ansibleが複数回実行されるので注意。
    • private_network_ip: は省略すると起動する場合があった
  • vagrant.yml
    hosts:
      - hostname: "centos6"
        box: "centos/6"
        private_network_ip: "192.168.56.10"
        forwarded_port:
          - guest: 80
            host: 18080
        memory: 512
        provision:
          ansible_playbook: playbook.vagrant.provision.centos.yml
      - hostname: "centos7"
        box: "centos/7"
        private_network_ip: "192.168.56.11"
        forwarded_port:
          - guest: 80
            host: 28080
        memory: 512
        provision:
          ansible_playbook: playbook.vagrant.provision.centos.yml
  • Vagrantfile
    # -*- mode: ruby -*-
    # vi: set ft=ruby :
    
    require 'yaml'
    vgconfig = YAML.load_file 'vagrant.yml'
    
    Vagrant.configure("2") do |config|
      config.vm.box_check_update = true
      config.ssh.forward_agent = true
      vgconfig["hosts"].each do |host|
        config.vm.define host["hostname"] do |vmconfig|
          vmconfig.vm.hostname = host["hostname"]
          vmconfig.vm.box = host["box"]
          host["forwarded_port"].each do |fwd_port|
            vmconfig.vm.network "forwarded_port", guest: fwd_port["guest"], host: fwd_port["host"]
          end
          if  host["private_network_ip"] != ""
            vmconfig.vm.network "private_network", ip: host["private_network_ip"]
          end
          vmconfig.vm.provider "virtualbox" do |vb|
            vb.memory = host["memory"]
            vb.customize ["modifyvm", :id].concat(host["customize"])
          end
          vmconfig.vm.synced_folder ".", "/vagrant", type: 'virtualbox'
          vmconfig.vm.provision :ansible do |ansible|
            ansible.playbook = host["provision"]["ansible_playbook"]
          end
        end
      end
    end

プラグイン


sshでの接続

  • 通常
    vagrant ssh [default]
  • 複数のvmがあると、portがvm起動順によって毎回変わるので注意。port固定したほうが良いかもしれない。
  • ansible等、他のツールを使いたい場合。
    vagrant ssh-config [default] > ssh-config
    
    # ssh
    ssh -F ssh-config default
    
    # scpでファイルコピー
    scp -F ssh-config dummy.txt default:/tmp/

Ansibleを使う

shellより楽に設定できる。

  • Ansible - Provisioning - Vagrant by HashiCorp
    • ansible: ホストOSにansibleがインストール済みの事が前提
    • ansible_local: ゲストOSにansibleをインストールして実行する。ホストOS側にansibleが不用になる。
  • ディレクトリ構造
    |-- Vagrantfile
    |-- /provisioning
    |   |-- /group_vars
    |           |-- all.yml
    |   |-- /roles
    |           |-- /bar
    |           |-- /foo
    |   |-- playbook.yml
  • inventory file
    • デフォルトは以下が使われた。 portはvmの起動順で変わる。
      .vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory
    • 固定で指定もできる。portを固定したほうが良い。
  • group
    • group_vars/ はデフォルトでは読み込まれない。「group_vars/all.yml」または「group_vars/all/*.yml」はansibleの仕様で必ず読み込まれる。
    • group nameを指定する場合
          ansible.groups = {
            "group1" => ["web"]
            "group2" => ["db"]
          }
  • ansible側で変数を定義して、Vagrantfile内で使う。
    require 'yaml'
    group_vars = YAML.load_file 'group_vars/all.yml'

box: 構築済みイメージの使用


Windows10を使う

  • 環境
    • Host OS: Win10 pro 1903
    • WSL1
      • OS: Ubuntu 18.04 LTS
      • vagrant 2.2.6
    • VirtualBox 6.0.14
  • Vagrantfile
      config.vm.hostname = "win10"
      config.vm.box = "Microsoft/EdgeOnWindows10"
      config.vm.guest = :windows
      config.vm.communicator = "winrm"
      config.winrm.username = "IEUser"
      config.winrm.password = "Passw0rd!"
      config.vm.synced_folder ".", "/vagrant", type: "nfs", disabled: true
  • ゲストOSのWin10上で、PowerShellを管理者権限で実行
    Get-NetConnectionProfile | Set-NetConnectionProfile -NetworkCategory Private
    winrm quickconfig
  • ゲストOSを再起動
    vagrant reload win10

/vagrantディレクトリが空の場合

Vagrant box centos/7 - Vagrant Cloud を使った場合、ホストOSから見た「/vagrant」が空の場合がある。

  • 共有フォルダは ゲストOSにインストールされた Guest Additions が担当している。ホストOSのVirtualBoxのバージョンと不一致や、古いと発生する。
  • 「Guest Additions」を更新してくれる「vagrant-vbguest」プラグインを追加
    vagrant plugin install vagrant-vbguest
    
    # up済みvmのバージョンをチェック
    vagrant vbguest [vmname] --status
    
    # 更新
    vagrant vbguest [vmname]
    
    # vm再起動
    vagrant reload [vmname]

コマンドラインオプション

  • vm名を省略すると「default」が指定された事になる。
# ヘルプ
vagrant -h

# Vagrantfileの検証
vagrant validate

# vagrantの状態
vagrant status

# 起動
vagrant up

# 一時停止、スリープ
vagrant suspend

# suspend状態からの復帰
vagrant resume

# Vagrantfileの変更反映(halt -> up)
vagrant reload

# provision部分の再実行(shell, ansible部分だけの実行)
vagrant provision

# 電源off
# 裏でVMが動いていると重いので、使い終わったら停止したほうが良い
vagrant halt

# vmの削除. boxのイメージは残ったまま
vagrant destroy
  • boxの操作
    # help
    vagrant box
    
    # インストール済みboxの一覧
    vagrant box list
    centos/7 (virtualbox, 1902.01)

インストール

  • CIDRは「192.168.56.1/24」
    • VirtualBoxのファイル > ホストネットワークマネージャ > アダプタを手動で設定のIPv4を確認。
    • 任意の値が指定できるが、NICが増えるので注意。増えすぎると分かりにくい。
  • 共有フォルダ。ホストOS上の任意のフォルダを、ゲストOS上の「/vagrant」へマウントできる。
    config.vm.synced_folder ".", "/vagrant"

macOS

brew cask install virtualbox
brew cask install vagrant

WSL環境

  • Win10 Pro 1803
    • VirtualBox 6.0.8
  • WSL
    • Ubuntu 18.04.2 LTS
    • vagrant 2.2.6
  1. Memo/Windows/PackageManagement#y905b7e1 でWindowsアプリとして、VirtualBoxのインストール
  2. WSLのUbuntu上でvagrantのインストール。Download - Vagrant by HashiCorp で最新バージョンを確認
    VAGRANT_VER=2.2.6
    wget https://releases.hashicorp.com/vagrant/${VAGRANT_VER}/vagrant_${VAGRANT_VER}_x86_64.deb
    sudo apt install ./vagrant_${VAGRANT_VER}_x86_64.deb
    
    vagrant -v
    Vagrant 2.2.6
  1. bash用の環境設定
    cat ~/.bash.d/vagrant.sh
    export VAGRANT_WSL_ENABLE_WINDOWS_ACCESS="1"
    export VAGRANT_WSL_WINDOWS_ACCESS_USER_HOME_PATH="/mnt/c/local/home/${USER}/vagrant"
    export PATH="$PATH:/mnt/c/Program Files/Oracle/VirtualBox"
    
    chmod +x ~/.bash.d/vagrant.sh
    source ~/.bash.d/vagrant.sh
  2. ruby warningを抑えるために、/etc/wsl.confの設定。Memo/Windows/10/WSL#bef978d4
  3. pluginの追加
    vagrant plugin install vagrant-vbguest

centos/7

mkdir ~/vagrant
cd vagrant
vagrant init centos/7

vim Vagrantfile
--
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "centos/7"
  config.vm.network "private_network", ip: "192.168.56.101"
  config.vm.synced_folder ".", "/vagrant"
  config.vm.provider "virtualbox" do |vb|
    vb.gui = false
    vb.memory = "512"
  end
end
--

vagrant up
vagrant status

vagrant ssh

[vagrant@localhost ~]$ cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
exit

vagrant halt

centos/7 + nginx

  1. 例: CentOS 7のboxを追加して、nginxをインストール
    # Vagrantfileを作成。テンプレートを作成してくれる。1ディレクトリに1ファイル。
    vagrant init centos/7
    
    # 適当にカスタマイズ
    cat Vagrantfile
    # -*- mode: ruby -*-
    # vi: set ft=ruby :
    
    Vagrant.configure("2") do |config|
      config.vm.box = "centos/7"
      config.vm.network "forwarded_port", guest: 80, host: 18080
      config.vm.network "private_network", ip: "192.168.56.101"
      config.vm.provider "virtualbox" do |vb|
         vb.gui = false
         vb.memory = "512"
      end
      config.vm.synced_folder ".", "/vagrant"
      config.vm.provision "shell", inline: <<-SHELL
        yum install -y vim epel-release
        yum install -y vim nginx
        service nginx restart
        chkconfig nginx on
      SHELL
    end
    
    # Vagrantfileの検証
    vagrant validate
    Vagrantfile validated successfully.
    
    # 起動。初回は時間がかかる。「.vagrant/」「.vagrant.d/」ディレクトリができる 
    vagrant up
    
    # ステータスの確認
    vagrant status
    ...
    default                   running (virtualbox)
    
    # sshでのログイン
    vagrant ssh [default]
    [vagrant@localhost ~]$ pwd
    /home/vagrant
    
    [vagrant@localhost ~]$ exit
  2. http://192.168.56.101/ を開いてnginxのデフォルトページが表示されるはず

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-11-29 (金) 22:16:20 (9d)