Vagrantfileでの複数サーバ構築（VirtualBox+Vagrant）

#背景
[前回の記事](https://qiita.com/mizuya_37/items/3ea0e8cca95fe75d17f4)にて、VirtualBox+Vagrantを用いた（単純な）サーバの自動構築が出来たので、今回はvagrantfileにもう少し細かい設定を行い、複数台のサーバ構築ができるようにする。

# 今回の範囲
以下のような環境を構築する。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626355/4ad4f442-900b-bb89-5afa-f3432ee31942.png" width="500">

# 環境
- windows 10
- VirtualBox 6.0.20
- Vagrant 2.2.7

# vagrantfileについて
vagrantfileは以下のセクション内に記載していく。
各サーバの設定は、
　config.vm.define "定義名" do |変数名|　～　end
のセクションに記載する。
また、パイプラインで囲まれた箇所に記載されている変数名は、そのセクション内で設定する項目名の先頭に記載をする形式となる。※ユニーク名で有る必要はない

```vim:vagrantfile
Vagrant.configure("2") do |config|
  # 各サーバ共有設定

  config.vm.define "centos74Web" do |server1|
    # 各サーバ別設定
    server1.vm.network "private_network", ip: "192.168.100.10"
    ...
    ...
  end
  config.vm.define "centos74AP" do |server2|
    ...
  end
  config.vm.define "centos74DB" do |server3|
    ...
  end
end
```
今回、vagrantfileで設定しているのは、下記の項目の通りとなる。

1. OS指定（vagrantboxのイメージファイル指定）※共通設定に記載
1. ネットワーク設定
1. ホストOSとの共有ディレクトリ
1. ホスト名設定
1. サーバスペック
1. VMの設定変更、SWインストール（shellコマンド実行）

## OS指定（vagrantboxのイメージファイル指定）
今回構築するVMのOSはCentOS7.4で合わせているため、共通設定のセクションに記載する。

```vim:vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "centos7.4.1708"
  config.vm.box_version = "0"
  config.vm.box_url = "https://vagrantcloud.com/centos/boxes/7/versions/1803.01/providers/virtualbox.box"
end
```
ローカルのvagrantに、box名「centos7.4.1708」、バージョン「0」が登録されている場合は、そのboxイメージを使用して構築する。
無い場合はconfig.vm.box_urlの指定先からダウンロード、登録後にそのboxイメージを使用して構築を行う。
URLの指定については、[こちら](https://qiita.com/mizuya_37/items/3ea0e8cca95fe75d17f4#vagrantbox%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E5%8F%96%E5%BE%97)を参照ください。

## ネットワーク設定
virtualBoxでは、下記のネットワーク設定ができる。

- NAT
- ホストオンリーアダプター
- 内部ネットワーク
- ブリッジアダプター
- ポートフォワーディング

この設定については、下記のQiita記事が分かりやすい出の、そちらを参照ください。
　[Vagrant 事始め 04 - Vagrant のネットワーク設定](https://qiita.com/centipede/items/64e8f7360d2086f4764f)

今回、「ホストオンリーアダプター」と「内部ネットワーク」を使用しており、以下の通り記載している。

```vim:vagrantfile
Vagrant.configure("2") do |config|
  config.vm.define "centos74Web" do |server1|
    # NW設定
    # ホストオンリーアダプター
    server1.vm.network "private_network", ip: "192.168.100.10"
    # 内部ネットワーク
    server1.vm.network "private_network", ip: "192.168.101.10", virtualbox__intnet: "Front1-NW"
  end
end
```

## ホストOSとの共有ディレクトリ
### 共有ディレクトリ設定時のエラー
ホストOSとの共有ディレクトリを使用する場合、VMのOS上に「Virtualbox Guest Additions」をインストール必要があり、インストールしていない場合、下記のエラーが発生してしまう。

```cmd:コマンドプロンプト　エラー内容
mount -t vboxsf -o uid=1000,gid=1000 ******* ********
The error output from the command was:
mount: unknown filesystem type 'vboxsf'
```
#### 解決策
ホストOSのvagrantにPlugin「vagrant-vbguest」をインストールする案が挙げられる。
Pluginを入れておくことで「vagrant up」時に、VMのOS上に「Virtualbox Guest Additions」をインストールしてくれる。

#### 事前手順
以下コマンドをホストOSのコマンドプロンプトで実行し、vagrantに「vagrant-vbguest」をインストールしておく。

```cmd:コマンドプロンプト
vagrant plugin install vagrant-vbguest
```
上記コマンドにてインストールしておくことで、VM作成時に「Virtualbox Guest Additions」を自動でインストールしてくれる。

## ホスト名設定
VMのホスト名については、下記の通り設定（server1.vm.hostname）を行っている。

```vim:vagrantfile
Vagrant.configure("2") do |config|
  config.vm.define "centos74Web" do |server1|
    # ホスト名設定
    server1.vm.hostname = 'centosWeb'
  end
```


## サーバスペック
各サーバの設定は下記セクションにて記載する。
今回の設定では、GUI無効、VM名、メモリ、CPUの設定を行っている。

```vim:vagrantfile
Vagrant.configure("2") do |config|
  config.vm.define "centos74Web" do |server1|
    server1.vm.provider "virtualbox" do |vb|
      # GUI無効
      vb.gui = false
      # VM名（VertualBox表示名）
      vb.name = "centos74-Web"
      # メモリ
      vb.memory = "1024"
      # CPU
      vb.cpus = 1
    end    
  end
```


## VMの設定変更、SWインストール（shellコマンド実行）
VMの設定として、下記のセクションにてOS構築後のOS設定やSWインストールをroot権限にて行うことができる。
なお、下記の記載では、初回構築時の「vagrant up」実行時に実施されるのみであり、OS停止後に再度「vagrant up」を行っても、コマンドは実施されない。
もし、「vagrant up」実行時に毎回コマンドを実行したい場合は、alwaysオプションを使用することで、実行されるようになる。
※詳しくは、[こちら](https://qiita.com/mizuya_37/items/18ebcd4e0677d1e53a5d#%E6%B3%A8%E6%84%8F%E7%82%B9)を参照ください。

```vim:vagrantfile
Vagrant.configure("2") do |config|
  config.vm.define "centos74Web" do |server1|
    server1.vm.provision "shell", inline: <<-SHELL
    ...
    ...
    SHELL
  end
end
```

今回、OS設定・SWのインストールであるが、下記の内容を行っている。
なお、SW設定は行っていないため、APサーバとDBサーバのSWインストールについては説明を省略する。

- 共通設定
 - ssh接続（アカウント:vagrant）
 - FW無効
- Webサーバ
 - nginxインストール
- APサーバ
 - JAVAインストール
- DBサーバ
 - postgresqlインストール


### 共通設定
#### ssh接続（アカウント:vagrant）
vagrantでは、VMに対して「vagrant ssh」コマンドで接続することが出来る。
しかし、初期ではssh接続でのパスワード認証がOFFになっているため、TeraTermなどのクライアントソフトで接続する際は、設定を変更する必要がある。
そのため、下記コマンドを実行して、sshd_configの設定を変更し、接続できるようにしている。

```vim:vagrantfile
Vagrant.configure("2") do |config|
  config.vm.define "centos74Web" do |server1|
    server1.vm.provision "shell", inline: <<-SHELL
      sed -i -e 's/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
      systemctl restart sshd
    SHELL
  end
end
```

#### FW無効
OSのFWは無効にしておきたいため、下記コマンドを実行するようにしている。

```vim:vagrantfile
Vagrant.configure("2") do |config|
  config.vm.define "centos74Web" do |server1|
    server1.vm.provision "shell", inline: <<-SHELL
      systemctl stop firewalld
      systemctl disable firewalld
    SHELL
  end
end
```

#### Webサーバ：nginxインストール
nginxをインストールする際にリポジトリ設定が必要のため、「yum install」コマンドを実行する前に、OS設定を行う必要がある。

今回、ホストOS側で作成したrepoファイルを転送する形で、設定変更を行った。

##### ホストOSからのファイル転送について
ホストOSからファイル転送を行う場合は、下記の通り
　XXXX.vm.provision "file", source: 転送元パス, destination: 送信先パス
にて、送信することが可能である。
転送元パスは、vagrantfileがあるディレクトリを参照するため、同じディレクトリに転送ファイルを置く場合は、ファイル名のみで問題ない。
なお、この転送では一般ユーザ：vagrantで転送を行うため、vagrantで書込み権限がない場合は転送に失敗する。

今回のnginxリポジトリ設定ファイルの転送先ディレクトリはvagrantユーザでの権限がないため、一旦、vagrantのhomeディレクトリに転送を行っている。

その後、shellコマンドのセクションにおいては、root権限にて実行されるため、ファイル転送にて転送したファイルを、shellコマンド実行のセクションにて移動（mvコマンド）することで、所定のディレクトリに格納している。
その後に、nginxのインストールを実行している。

vagrantfileの記載は下記のとおりである。

```vim:vagrantfile
Vagrant.configure("2") do |config|
  config.vm.define "centos74Web" do |server1|    
    # nginxのリポジトリ設定ファイルをホストOSから転送
    server1.vm.provision "file", source: "nginx.repo", destination: "/home/vagrant/nginx.repo"
    
    server1.vm.provision "shell", inline: <<-SHELL
      # 転送されたファイルを、リポジトリ設定の所定のディレクトリに移動
      mv /home/vagrant/nginx.repo /etc/yum.repos.d/nginx.repo

      # nginxのインストール・自動起動設定・起動
      yum install -y nginx
      systemctl enable nginx
      systemctl start nginx
    SHELL
  end
```


## まとめ（vagrantfileの記載例）
ここまでの設定をまとめたvagrantfileは下記のとおりであり、この設定を実行することで、VM3台を構築する。
※nginxのリポジトリ設定ファイルがホストOS側に別途必要

```vim:vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "centos7.4.1708"
  config.vm.box_version = "0"
  config.vm.box_url = "https://vagrantcloud.com/centos/boxes/7/versions/1803.01/providers/virtualbox.box"

  config.vm.define "centos74Web" do |server1|
    server1.vm.network "private_network", ip: "192.168.100.10"
    server1.vm.network "private_network", ip: "192.168.101.10", virtualbox__intnet: "Front1-NW"
    server1.vm.synced_folder "./Web", "/home/vagrant/host-common"
    server1.vm.hostname = 'centosWeb'
    
    server1.vm.provider "virtualbox" do |vb|
      vb.gui = false
      vb.name = "centos74-Web"
      vb.memory = "1024"
      vb.cpus = 1
    end
    
    server1.vm.provision "file", source: "nginx.repo", destination: "/home/vagrant/nginx.repo"
    
    server1.vm.provision "shell", inline: <<-SHELL
      sed -i -e 's/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
      systemctl restart sshd

      systemctl stop firewalld
      systemctl disable firewalld

      mv /home/vagrant/nginx.repo /etc/yum.repos.d/nginx.repo

      yum install -y nginx
      systemctl enable nginx
      systemctl start nginx
    SHELL
  end
  
  config.vm.define "centos74AP" do |server2|
    server2.vm.network "private_network", ip: "192.168.100.11"
    server2.vm.network "private_network", ip: "192.168.101.11", virtualbox__intnet: "Front1-NW"
    server2.vm.network "private_network", ip: "192.168.102.11", virtualbox__intnet: "Front2-NW"
    # server2.vm.synced_folder "./", "/var/www/common"
    server2.vm.hostname = 'centosAP'
    
    server2.vm.provider "virtualbox" do |vb|
      vb.gui = false
      vb.name = "centos74-AP"
      vb.memory = "1024"
      vb.cpus = 1
    end
    
    server2.vm.provision "shell", inline: <<-SHELL
      sed -i -e 's/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
      systemctl restart sshd
      
      yum intall -y java
      
      systemctl stop firewalld
      systemctl disable firewalld
    SHELL
  end
  
  
  config.vm.define "centos74DB" do |server3|
    server3.vm.network "private_network", ip: "192.168.100.12"
    server3.vm.network "private_network", ip: "192.168.102.12", virtualbox__intnet: "Front2-NW"

    # server3.vm.synced_folder "./", "/var/www/common"
    server3.vm.hostname = 'centosDB'
    
    server3.vm.provider "virtualbox" do |vb|
      vb.gui = false
      vb.name = "centos74-DB"
      vb.memory = "2048"
      vb.cpus = 2
    end

    server3.vm.provision "shell", inline: <<-SHELL
      sed -i -e 's/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
      systemctl restart sshd

      yum install -y postgresql-server
      postgresql-setup initdb
      systemctl enable postgresql.service
      systemctl start postgresql.service
      
      systemctl stop firewalld
      systemctl disable firewalld
    SHELL
  end
end
```

# vagrantの実行
vagrantfileを作成したら、そのディレクトリにてコマンドプロンプトから下記コマンドを実行

```cmd:コマンドプロンプト
vagrant up
```

なお、3台のうち、例えばWebサーバのみ構築・起動したい場合は、下記の通りコマンドを実行することで、特定のサーバのみ構築・起動が可能である。

```cmd:コマンドプロンプト
vagrant up 定義名

例）centos74Webの場合
vagrant up centos74Web
```

# 終わりに
vagrantについては、これまでの投稿記事で自分なりには整理が出来たので、次はこれを使って、他のMW等の検証していこうかと思います。