Ansibleを使ってみました



Dockerを使って環境構築をしているのですが、構成管理ツールを使ったことがなかったので、どちらのほうが便利なのか確認するためにAnsibleを使ってみました。


*Ansibleとは

構成管理ツールの1つです。(似たツールとしては、PuppetやChefがあります)
playbookと呼ばれる設定管理スクリプトを実行することで、デプロイや新しいサーバーのプロビジョニングをすることができます。
playbookはYAMLとJinja2のテンプレート言語で書き、ansible-playbookコマンドで実行します。
また、ansible.cfgという名前のファイルを作成してデフォルト設定を記述しておくと、ssh鍵などの指定をする必要がなくなります。

<特徴>

  • プッシュベース
    デフォルトでプッシュベースになっているので、コマンドを実行するとすぐにリモートサーバーに接続して作業に取り掛かることができ、サーバーに変更がかかるタイミングをコントロールすることができます。(chafはプルベースなのでタイミングをコントロールできません)
  • スケールダウン
    playbookを1つ書くだけでスケールダウンすることができます。(スケールダウンとは、実利用に対してサーバスペックが過剰な場合に、仮想サーバのスペックを下げるアプローチです。)
  • モジュール
    モジュールを使うことでパッケージのインストールやサービスの再起動、設定ファイルのコピーといったタスクを実行することができます。


*参考

今回のコードは、ほぼ下記の記事を参考にさせて頂きました。


*環境

  • MacOS
  • Vagrant 2.1.1
  • Virtualbox 5.2.12


*VM環境の作成

作業用のディレクトリを作成し、VMテンプレートのBox(今回はCentOS)をダウンロードします。
$ mkdir ansible
$ cd ansible
$ vagrant box add centos6.7 https://github.com/CommanderK5/packer-centos-template/releases/download/0.6.7/vagrant-centos-6.7.box

vagrant initコマンドを実行して、Vagrantfileを作成します。
$ vagrant init
$ ls
Vagrantfile

VagrantfileはVM環境を作成するための設定ファイルです。
今回は下記内容に編集します。
Vagrant.configure(2) do |config|
  config.vm.define "controller" do |node|
      node.vm.box = "centos6.7"
      node.vm.hostname = "controller"
      node.vm.network :private_network, ip: "192.168.100.10"
      node.vm.network :forwarded_port, id: "ssh", guest: 22, host: 2210
  end
  config.vm.define "target" do |node|
      node.vm.box = "centos6.7"
      node.vm.hostname = "target"
      node.vm.network :private_network, ip: "192.168.100.20"
      node.vm.network :forwarded_port, id: "ssh", guest: 22, host: 2220
  end
end

vagrant upコマンドを実行してVM環境を構築します。
statusコマンドで状態を確認することができます。
$ vagrant up
...

$ vagrant status
Current machine states:

controller                running (virtualbox)
target                    running (virtualbox)

This environment represents multiple VMs. The VMs are all listed
above with their current state. For more information about a specific
VM, run `vagrant status NAME`.

controllerの環境にssh接続するための仮想環境の情報を調べます。
(★が付いているの項目が、ssh接続に必要な情報です。)
$ vagrant ssh-config
Host controller
  ★HostName 127.0.0.1
  ★User vagrant
  ★Port 2210
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  ★IdentityFile /Users/XXX/ansible/.vagrant/machines/controller/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL

Host target
  HostName 127.0.0.1
  User vagrant
  Port 2220
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /Users/
  XXX/ansible/.vagrant/machines/target/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL

仮想環境(controller)に接続します。
$ ssh vagrant@127.0.0.1 -p 2210 -i /Users/XXX/ansible/.vagrant/machines/controller/virtualbox/private_key

[vagrant@controller ~]$


*Ansibleの実行

仮想環境に接続したら、ansibleをインストールします。
[vagrant@controller ~]$ sudo yum install ansible
[vagrant@controller ~]$ ansible --version
ansible 2.5.3

ansibleはssh接続を使って処理を実行していくため、鍵の設定をしておきます。
パスワードが聞かれたらvagrantと入力します。
[vagrant@controller ~]$ ssh-keygen -t rsa
後続の質問はすべてEnter
[vagrant@controller ~]$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.100.20

作業用にansibleディレクトリを作成してhostsファイルを作成します。
  • inventory/hosts
[targets]
192.168.100.20

グループ変数を定義するファイルを作成します。
  • group_vars/targets.yml
message: "Hello Ansible!"

fruits:
  apples:
    amount: 10
  bananas:
    amount: 20
  oranges:
    amount: 30

ansibleディレクトリの直下にplaybookを作成します。
  • test.yml
- hosts: targets
  user: root
  tasks:
    - name: output message.
      debug: msg="{{ message }}"

    - name: output fruits
      debug: msg="We want {{ item.value.amount }} {{ item.key }} !" 
      with_dict: "{{ fruits }}"

playbookを実行します。
[vagrant@controller ansible]$ ansible-playbook -i inventory/hosts test.yml

PLAY [targets] ********************************************************************************************************************

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

TASK [output message.] ************************************************************************************************************
ok: [192.168.100.20] => {
    "msg": "Hello Ansible!"
}

TASK [output fruits] **************************************************************************************************************
ok: [192.168.100.20] => (item=None) => {
    "msg": "We want 10 apples!"
}
ok: [192.168.100.20] => (item=None) => {
    "msg": "We want 30 oranges!"
}
ok: [192.168.100.20] => (item=None) => {
    "msg": "We want 20 bananas!"
}

PLAY RECAP ************************************************************************************************************************
192.168.100.20             : ok=3    changed=0    unreachable=0    failed=0   

[vagrant@controller ansible]$ 

インストールやファイルの作成なども試してみます。
  • main.yml
- hosts: targets
  user: root
  tasks:
  - name: install packages from yum
    yum: name={{ item }} state=latest
    with_items:
      - jq
      - ruby
      - httpd

  - name: register cron job
    cron: name="check ping" day="*/2" hour="12" minute="0" job="ping -c 3 192.168.100.10"

  - name: create directories
    file: path={{ item.path }} owner={{ item.owner }} group={{ item.group }} mode={{ item.mode }} state=directory
    with_items:
      - { "path":"/opt/ansible", "owner":"root", "group":"root", "mode":"755" }
      - { "path":"/opt/vagrant", "owner":"vagrant", "group":"vagrant", "mode":"755" }

playbookを実行します。
$ ansible-playbook -i inventory/hosts main.yml

[vagrant@controller ansible]$ ansible-playbook -i inventory/hosts main.yml

PLAY [targets] ****************************************************************************************************************************

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

TASK [install packages from yum] **********************************************************************************************************
ok: [192.168.100.20] => (item=[u'jq', u'ruby', u'httpd'])

TASK [register cron job] ******************************************************************************************************************
ok: [192.168.100.20]

TASK [create directories] *****************************************************************************************************************
ok: [192.168.100.20] => (item={u'owner': u'root', u'path': u'/opt/ansible', u'group': u'root', u'mode': u'755'})
ok: [192.168.100.20] => (item={u'owner': u'vagrant', u'path': u'/opt/vagrant', u'group': u'vagrant', u'mode': u'755'})

PLAY RECAP ********************************************************************************************************************************
192.168.100.20             : ok=4    changed=4    unreachable=0    failed=0   


実行されたタスクの数が最後に出力されるので、結果が非常にわかりやすいです。playbookを再度実行するとchanged=0 になるので、変更ないことがわかる点も良いと感じました。
ファイルの書き方としては、Jinja2テンプレートを使って可変にできる点が便利そうでした。
最後にVMをシャットダウンしておきます。
$ vagrant halt


*所感

Dockerはコンテナを作って破棄したり作り直したりといったことができて、Ansibleは実際の環境に対しての設定を簡単にすることができるようです。
YAMLファイルなのでDockerと同じような書き方ができますし、私としてはDockerのほうが便利そうだと感じました。
状況によってはAnsibleのほうが適切な場合もあるかもしれないので、もう少し知見を集めて勉強しておきたいと思います。
Previous
Next Post »

人気の投稿