Vagrant + Ansible で 自分専用のDNSサーバーを立ち上げる方法

開発や検証作業を行っている時に、自分の環境だけで利用できるプライベートなDNSが欲しいという時がある。そこで、コマンド git, cd, vagrant ３つ実行するだけで、簡単に起動できるDNSサーバーのVagrantfile と Ansible playbook を作った。

詳細な利用方法は、https://github.com/takara9/vagrant-dns の書いてあるので、参照してもらいたい。ここでは、Vagrant と Ansible の連携について、ポイントを挙げて紹介する。


## Vagrantfile から Ansible を起動する方法

起動した仮想マシンの中で、vagrant upの実行中に、ansibleを実行する為のポイントは以下である。

* /vagrant を仮想マシンにマウントして、Playbookなどがゲストマシンからアクセスできるようにする。
* ansibleのPlaybookとインベントリ(hosts)を指定する以下の記述を作成する。
* 必要なAnsible playbookを配置する。

~~~file:Vagrantfile抜粋
    machine.vm.synced_folder ".", "/vagrant", owner: "vagrant",
      group: "vagrant", mount_options: ["dmode=700", "fmode=700"]
    
    machine.vm.provision "ansible_local" do |ansible|
      ansible.playbook       = "playbook/install_bind.yml"
      ansible.version        = "2.8.5"
      ansible.verbose        = false
      ansible.install        = true
      ansible.limit          = "server1"
      ansible.inventory_path = "playbook/bind/hosts"
~~~


## Varantfile と Ansible playbook のディレクトリ構造

Vagrantfileのディレクトリに、Ansible playbook用にディレクトリ playbookを作成して、[Creating Reusable Playbooks » Roles](https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html)と参考URLのリンクを参照してディレクトリ構造を作成した。
また、[Ansible Playbook のベストプラクティス](https://docs.ansible.com/ansible/latest/user_guide/playbooks_best_practices.html)を参考にできる。

ここでは、bind が 役割(roles)に相当して、install_bind.yaml の中から呼び出す。

~~~
.
├── README.md
├── Vagrantfile
├── ansible.cfg
└── playbook
    ├── bind
    │   ├── defaults
    │   │   └── main.yml
    │   ├── handlers
    │   │   └── main.yml
    │   ├── hosts
    │   ├── tasks
    │   │   └── main.yml
    │   ├── templates
    │   │   ├── db.forward.j2
    │   │   ├── db.reverse.j2
    │   │   ├── named.conf.j2
    │   │   ├── named.conf.local.j2
    │   │   └── resolv.j2
    │   └── vars
    │       └── main.yml
    └── install_bind.yml
~~~


このファイル install_bind.yml の `roles:` にディレクトリ名`- bind`を設定することで、`bind/tasks/main.yml` が実行される。 

~~~file:install_bind.yml
---
- name: Set up Bind DNS
  hosts: server1
  gather_facts: true
  become: true

  roles:
    - bind
~~~

サーバーに設定を増やして役割を増やすには、配列変数として、以下のように追加すれば良い。

~~~
  roles:
    - bind
    - ca
~~~


## CentOS 8 を起動する為のVagrantfile

本題からズレるが、今回、RHEL8 の互換である CentOS8 を利用した。
CentOS８を利用するには、以下の vm.box 指定で良い。

~~~file:Vagrantfile抜粋
# coding: utf-8
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.define 'server1' do |machine|
    machine.vm.box = "generic/centos8"
  end
end
~~~

## SELinuxのモード変更

SELinuxが有効になっていると、nsupdateでゾーンファイルの変更はファイルのパーミションに関係なく、禁止される。その為、nsupdateなどで動的に更新ができない。そこで、目的とするモードをpermissive（寛容）に変更することで、ダイナミックDNSとして利用できる。

~~~
- name: change selinux
  selinux:
    policy: targeted
    state: permissive
~~~

## Ansible playbook だけの実行

途中でplaybookがエラーになった場合、毎回 vagrant up から実行するのは時間を要する。
そこで、playbookの開発の場合は、仮想サーバーに入って、ansible-playbookコマンドを直接実行する。

その際に、前述のように、/vagrant ディレクトリに Vagratfileのディレクトリがマウントされている必要がある。

~~~console:
# ansible-playbook -i /vagrant/playbook/bind/hosts /vagrant/playbook/install_bind.yml
~~~


## まとめ

Ansible の playbook の資産は、いろいろの事を達成するために、開発者にとって、とても力になる。
繰り返し利用できて、その上に、積み上げる事ができる。当たり前だけど、これを活用しない手はない。

クラウドでも、オンプレでも、開発者自身のラップトップ環境でも、どこでも利用できるから、マルチクラウドやハイブリッドクラウドの利用に踏み出す際に、とても大切なスキルだと考える。