vagrant+ansibleでdocker、docker-compose、kubectlが使える環境を作成する

# はじめに
vagrantとansibleを用いてdockerやkubectlが使える環境を簡単に構築できるようにしました。
今回はVMに入れるOSとしてcentosを選んでいます。

なおvirtualboxとvagrantはインストールされていることを前提とします。

# 実装
最終的にフォルダ構造は次のようになります。

```bash
├── Vagrantfile
├── ansible.cfg
├── hosts
└── playbook.yml
```

## Vagrantfile
まずはVagrantfileから見ていきます。

```bash:Vagrantfile
Vagrant.configure(2) do |config|
  config.vm.define "target" do |node|
    node.vm.box = "centos7.2"
    node.vm.hostname = "target"
    node.vm.network :private_network, ip: "192.168.10.20"
    node.vm.network :forwarded_port, id: "ssh", guest: 22, host: 2220
  end
  
  config.vm.define "controller" do |node|
    node.vm.box = "centos7.2"
    node.vm.hostname = "controller"
    node.vm.network :private_network, ip: "192.168.10.10"
    node.vm.network :forwarded_port, id: "ssh", guest: 22, host: 2210

    node.vm.provision "ansible_local" do |ansible|
      ansible.limit = "all"
      ansible.inventory_path = "hosts"
      ansible.playbook = "playbook.yml"
    end
  end
end
```

vagrantで作成するVMは、controllerとその操作対象となるtargetの2つです。
controllerにはansible_localをプロビジョニングとして加えています。

controllerはtargetの構成を管理するためのものです。
実際にSSHして操作を行うのはtargetになります。

プロビジョニングの設定として以下3つを定義しています。

|設定対象  |  説明   |
|:-----------------|:------------------|
| limit             |対象のリモートホスト|
| inventory_path          |対象のリモートホストの情報 | 
| playbook             |対象のリモートホストの状態| 


## hosts
ansibleの対象のリモートホストの情報をここで定義します。

```text:hosts
[vagrant]
target ansible_ssh_host=192.168.10.20 ansible_ssh_private_key_file=/vagrant/.vagrant/machines/target/virtualbox/private_key
```

vagrantというグループのtargetを定義していることになります。
IPアドレスとSSHキーの場所を記述します。

## ansible.cfg
ansibleのconfigファイルです。
SSHホストキーのチェックを無効化させないといけません。

```text:ansible.cfg
[defaults]
host_key_checking = no

[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes
```

## playbook.yml
targetにインストールしたいものをここで記述しておきます。
具体的にはdocker、docker-compose、kubectlをインストールします。

```yaml:playbook.yml
---
- hosts: vagrant
  become: yes
  tasks:
    - name: install yum-utils
      yum: name=yum-utils state=present

    - name: add docker repo
      shell: "yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo"
      args:
        chdir: "/etc/yum.repos.d"
        creates: docker-ce.repo

    - name: install docker-ce
      yum: name=docker-ce state=present

    - name: add group
      user: name=vagrant groups=docker append=yes
      tags: dockerhost
      become: True

    - name: restart docker
      systemd:
        name: docker.service
        state: restarted
        daemon_reload: yes
        enabled: yes

    - name: ensure docker-compose is installed and available
      get_url: 
        url : https://github.com/docker/compose/releases/download/1.24.0/docker-compose-{{ansible_system}}-{{ansible_machine}}
        dest: /usr/local/bin/docker-compose
        owner: vagrant
        group: vagrant
        mode: 'u+x,g+x'
    
    - name: ensure kubectl is installed and available
      get_url: 
        url : https://storage.googleapis.com/kubernetes-release/release/v1.14.1/bin/linux/amd64/kubectl
        dest: /usr/local/bin/kubectl
        owner: vagrant
        group: vagrant
        mode: 'u+x,g+x'
```

docker-composeとkubectlに関しては作成時における最新バージョンを選びました。

# 実行
centosのboxを追加して初期化を行います。

```bash
$ vagrant box add centos7.2 https://github.com/CommanderK5/packer-centos-template/releases/download/0.7.2/vagrant-centos-7.2.box
$ vagrant init
```

<p>
あとはVMを立ち上げるだけです。

```bash
$ vagrant up
...
...
    controller: Running ansible-playbook...

PLAY [vagrant] *****************************************************************

TASK [Gathering Facts] *********************************************************
ok: [target]

TASK [install yum-utils] *******************************************************
ok: [target]

TASK [add docker repo] *********************************************************
changed: [target]

TASK [install docker-ce] *******************************************************
changed: [target]

TASK [add group] ***************************************************************
changed: [target]

TASK [restart docker] **********************************************************
changed: [target]

TASK [ensure docker-compose is installed and available] ************************
changed: [target]

TASK [ensure kubectl is installed and available] *******************************
changed: [target]

PLAY RECAP *********************************************************************
target                     : ok=8    changed=6    unreachable=0    failed=0
```

<p>
targetにSSHしてdocker、docker-compose、kubectlのコマンドを試してみます。

```bash
$ vagrant ssh target
Last login: Sat May  4 18:02:30 2019 from 10.0.2.2

[vagrant@target ~]$ docker version
Client:
 Version:           18.09.5
 API version:       1.39
 Go version:        go1.10.8
 Git commit:        e8ff056
 Built:             Thu Apr 11 04:43:34 2019
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          18.09.5
  API version:      1.39 (minimum version 1.12)
  Go version:       go1.10.8
  Git commit:       e8ff056
  Built:            Thu Apr 11 04:13:40 2019
  OS/Arch:          linux/amd64
  Experimental:     false

[vagrant@target ~]$ docker-compose version
docker-compose version 1.24.0, build 0aa59064
docker-py version: 3.7.2
CPython version: 3.6.8
OpenSSL version: OpenSSL 1.1.0j  20 Nov 2018

[vagrant@target ~]$ kubectl version
Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.1", GitCommit:"b7394102d6ef778017f2ca4046abbaa23b88c290", GitTreeState:"clean", BuildDate:"2019-04-08T17:11:31Z", GoVersion:"go1.12.1", Compiler:"gc", Platform:"linux/amd64"}
The connection to the server localhost:8080 was refused - did you specify the right host or port?
```

<p>
それぞれがインストールされていることが分かります。
なお、まだkubeconfigを設定していないのでkubectlでサーバ情報は得られていません。


# まとめ
vagrantとansibleを用いてdocker、docker-compose、kubectlが使える環境を構築しました。
何かの研修で全員に同じ環境を提供したいときとかで役に立ちそうです。