apatheia.info

構成管理ツール Ansible について

2013.04.06 cm

Ansible というサーバーの設定を管理するツールの説明。いわゆる構成管理 (CM: Configuration Management) にカテゴライズされるもので、Puppet や Chef の親戚みたいなものと考えてもらえればだいたいあってる。

概要

リード開発者は Michael DeHaan で、現職の AnsibleWorks の前は Redhat で CobblerFunc に携わっていたり、Puppet labs でプロダクトマネージャーしたりしているという経歴の持ち主。

Ansible は Python で書かれている。同じジャンルで Python 製というと Salt が有名。Chef の場合、レシピを書くためには Ruby の知識が必要となってくるけど、Ansible はどんな言語でもモジュールが書けるようになっているので、運用にあたって Python の知識は必要無い。

動作の点でも Puppet や Chef などのツールとまったく異なるアプローチをしている。Puppet や Chef は、サーバーとクライアントで構成され、クライアントとなるマシンはサーバーに設定を問い合わせながら、自分自身を「あるべき状態」に収束するよう変更を加えていく。Ansible の場合、サーバー側からクライアントとなるサーバー(群)に対して直接命令を送り込み結果を得る。これは FuncCapistranoFabric などに似ているが、これらのデプロイを目的としたツールにはない「何回やっても結果が同じ」(idempotence) という CM ツールらしさはちゃんと備えている。

ドキュメントは12ページしかなく(ちなみに、さっき数えてみたらChefのドキュメントは2834ファイルあった) 非常に習得は簡単。サーバーを立てる必要もなく、クライアントマシンもエージェントレス、加えて短期間で学習できるので手軽感は非常に高いが、モジュール機構が強力なのできわめて実用的になっている。

基本的な概念

Ansible を理解する上で重要となる、モジュールとプレーブックについて説明する。

モジュール

クライアント内での動きはモジュールという形で定義する。

パッケージのインストール、サービスの起動、ユーザーやグループの作成などの基本的なモジュールはあるが、実際には環境に合わせて不足分は自分でモジュールを作っていくことになる。

モジュールは簡単に作れる。モジュールが役割を端的に言うと、以下を行うだけである。

  • 標準入力でオプションを受け取る

  • 標準出力で実行結果を返す

    • 出力形式は key=value を空白でつなげたものか JSON

これができる言語であれば、シェルスクリプトでも Perl でも問題ない。

プレーブック

実際の処理では単発のモジュールでサーバーの設定が終わることはないので、モジュールの使い方をまとめたものが必要になる。Ansible では、YAML で処理をまとめたものを プレーブック (Playbook)と呼んでいる。

例: Apache と PHP をインストールする (webapp.yml)

- hosts: webserver
  user: vagrant
  sudo: yes
  tasks:
    - name: install apache
      action: yum pkg=httpd state=installed
    - name: install php
      action: yum pkg=php state=installed

例: 実行

# ansible-playbook プレーブック名
$ ansible-playbook webapp.yml

以上は簡単な例だが、設定ファイルを配置したり、それに併せてサービスを再起動させたりといったことも記述可能。

プレーブックには以下のような内容が含まれる:

  • hosts: 対象のホスト
  • user: 実行ユーザー
  • vars: 変数
  • tasks: タスク

vars の変数は、テンプレート内で展開される。設定ファイル配置時にパラメータを変更、といった場合に利用する。

インストール

以下では、インストールから簡単なコマンドの実行までの例を挙げる。サーバー、クライアント双方で CentOS 6.4 を利用した。

Ansible を動かすためには、Python 2.6 以上と Ansible のソースコードとごくわずかな Python パッケージだけあればよい。CentOS 6 であれば Python の条件は満たせているし、EPEL で Ansible のパッケージが提供されているので、yum でインストール可能。

# EPEL 有効化
$ sudo rpm -ivh http://ftp.riken.jp/Linux/fedora/epel/6/i386/epel-release-6-8.noarch.rpm

# Ansible インストール
$ sudo yum install ansible

他の Unix 系OSであれば、pip install ansible でいい。

$ sudo pip install ansible

次に、サーバーからクライアントに SSH でログインできるように調整しておく。

# 以下のマシンを用意した。
# それぞれホスト名でアクセスできる
#    Ansible 実行側 ... server
#    変更対象 ... client1, client2

# server側で公開鍵認証用の鍵を作成
$ $ ssh-keygen -t rsa

# client に公開鍵を配置する
$ ssh-copy-id client1
$ ssh-copy-id client2

# 試しにログインしてみる
# 頻繁に実行することになるので、公開鍵にパスフレーズを
# 設定している場合は、ssh-agent を使ってパスフレーズの
# 入力を省略できるようにしておく。
$ ssh client1
$ ssh client2

今度は、対象のサーバーを設定してみよう。環境変数 ANSIBLE_HOSTS にあるファイルでサーバーの指定が可能。

$ cat <EOD >~/target
> [webserver]
> client1
> 
> [dbserver]
> client2
> EOD
$ export ANSIBLE_HOSTS=~/target

設定の中で、[ ] によりグループを作っている。つまり「webserver グループに client1、dbserver グループに client2 が所属している」ということを表している。グループはオプションなので、単純にホスト名を羅列するだけでもいい。試しに、対象のホストを調べてみよう。

# ansible ホストパターン --list-hosts

# ホスト名を直接指定
$ ansible client1 --list-hosts
client1

# グループ名を指定
$ ansible webserver --list-hosts
client1
$ ansible dbserver --list-hosts
client2

# all を指定した場合、全サーバーを列挙
$ ansible all --list-hosts
client1
client2

これだけで準備は完了。実行してみる。

# コマンドの書式
ansible 対象 -m モジュール名 -a オプション

# 例 ping モジュール
$ ansible all -m ping
client2 | success >> {
    "changed": false,
    "ping": "pong"
}

client1 | success >> {
    "changed": false,
    "ping": "pong"
}

-m をつけないで、直接コマンドを実行することも可能。

# すべてのマシンでカーネルのバージョンを取得
$ ansible all -a 'uname -r'
client2 | success | rc=0 >>
2.6.32-358.el6.x86_64

client1 | success | rc=0 >>
2.6.32-358.el6.x86_64

プレーブックを実行したときは以下のようになる。

# 対象は webserver というグループ(client1 が所属)に対して、
# Apache と PHP をインストールするプレーブック、webapp.yml を実行
# Apache はすでにインストールされていたので、
# PHP のみインストールされることとなった

$ ansible-playbook webapp.yml

PLAY [webserver] *********************

GATHERING FACTS *********************
ok: [client1]

TASK: [install apache] *********************
ok: [client1]

TASK: [install php] *********************
changed: [client1]

PLAY RECAP *********************
client1                        : ok=3    changed=1    unreachable=0    failed=0

その他

まとめ

ロゴのセンスは悪いけど、アプリケーション自体の仕組みはすごくセンスがいい。

他の構成管理ツールと比べると、DSL を覚えるといった「ツールを使うまでののコスト」、ツールのためのサーバー構築・運用といった「ツールを使ってからのコスト」が軽微なので、よりやりたいことに目が向けられるのもうれしい。

最近日本国内でも Chef の話題を聞くことが多いんだけど、Chef Server の運用とかオートスケールとのコンビネーションとかの情報はあまり聞かないので、たぶん割と小規模な環境でリモートサーバーの Chef-solo をキックみたいなケースが多いのかと思う。そういったところだと、Ansible のほうがふさわしいっていうことが多いんじゃないかな。