2019年6月19日水曜日

Ruby で Dynamic Inventory 入門

概要

DynamicInventory は Ansible がスクリプトを実行しその実行結果のインベントリ情報を使って playbook を流すことができる機能です
スクリプトは出力結果が決められたフォーマットになっていればどんな言語で書いても OK です
今回は Ruby でやってみました

環境

  • macOS 10.14.5
  • ansible 2.5.5
  • Vagrant 2.1.1
  • Ruby 2.6.2p47

テストマシン

今回は Vagrant で構築していますが SSH で接続できれば何でも OK です

  • vim Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/xenial64"
  config.vm.network "private_network", type: "dhcp"
  config.vm.network "private_network", ip: "192.168.99.200"
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "4096"
  end
end
  • vagrant up

SSH できるようにするがめ ssh-config を書き出します

  • vagrant ssh-config >> ~/.ssh/config

playbook

とりあえずテストマシンに playbook が流せる環境を作ります

  • vim example.yml
---
- hosts: role_web1
  tasks:
    - name: Install nginx
      shell: "amazon-linux-extras install nginx1.12"
      become: yes
    - name: Start nginx
      systemd:
        name: nginx.service
        state: started
      become: yes

インベントリファイルもとりあえずベタ書きします

  • vim inventory
[web1]
default

nginx をインストールして起動する playbook です
これでとりあえず実行できることを確認しましょう

  • ansible-playbook -i inventory example.yml -e 'ansible_python_interpreter=/usr/bin/python3'

Dynamic Inventory

さてここから Ruby を使った Dynamic Inventory を作成していきます
今回は特に動的に生成してる感じはないですが結果として「こんな感じの JSON が出力されれば良い」ということが理解できることを目的にしています

まずは単純なインベントリ情報を出力するスクリプトを書いてみます

  • vim inventory.rb
#! /usr/local/opt/ruby/bin/ruby
require 'json'

i = {
  :web1 => {
    :hosts => [
      'default'
    ]
  }
}
puts i.to_json
  • chmod +x inventory.rb

ファイルを指定するだけで実行できるようにシェバングを指定しています
シェバングのパスは環境によって異なると思うので適宜変更してください

このスクリプトを実行するとわかりますが単純な JSON が返ってきます

  • ./inventory.rb

=> {"web1":{"hosts":["default"]}}

このスクリプトを使って ansible-playbook を実行することができます

  • ansible-playbook -i ./inventory.rb example2.yml -e 'ansible_python_interpreter=/usr/bin/python3'

_meta

インベントリファイルには host_varsgroup_vars を書くことができます
Dynamic Inventory を使っても書くことができるので試してみました
スクリプトを以下のように書き換えましょう

  • vim inventory.rb
#! /usr/local/opt/ruby/bin/ruby
require 'json'

i = {
  :web1 => {
    :hosts => [
      'default'
    ],
    :vars => {
      :gvar => "gvalue"
    }
  },
  :_meta => {
    :hostvars => {
      :default => {
        :hvar => "hvalue"
      },
    }
  }
}
puts i.to_json

group_vars はホストグループの定義配下に vars を使って定義します
host_vars_meta を使って定義します
_meta 配下に hostvars を定義しその配下に key/value を定義することで参照することができるようになります

確認のための playbook も書き換えます

  • vim example.yml
---
- hosts: web1
  tasks:
    - name: Install nginx
      apt:
        name: nginx
        state: present
      become: yes
    - name: Start nginx
      systemd:
        name: nginx.service
        state: started
      become: yes
    - name: Debug host_vars
      debug:
        msg: _meta host_vars is {{hvar}}
    - name: Debug group_vars
      debug:
        msg: _meta group_vars is {{gvar}}

debug を使って変数の内容を表示しているだけです
これで先程同様に実行すると変数が問題なく参照できるのが確認できると思います

  • ansible-playbook -i ./inventory.rb example2.yml -e 'ansible_python_interpreter=/usr/bin/python3'

最後に

Dynamic Inventory を Ruby で試してみました
当然ですが ansible-playbook コマンドを実行するマシンに ruby がインストールされている必要があります
少し調べた感じだと --list--host オプションを実装したほうが良さそうだったのですが実装しないでも動作しました
スクリプトがインベントリファイルの形式で出力できたほうが良い場合などは実装すると良いかなと思います

実際は API や Terraform の .tfstate ファイルなどをパースしてインベントリ情報の JSON を生成することになると思います

参考サイト

0 件のコメント:

コメントを投稿