Ansibleが使えるようになったきっかけ

Red Hatでコンサルタントをしている id:nanodayo です。 赤帽エンジニアAdvent Calendar 2018 の9日目の記事となります。

本日はAnsibleを始めてみたいけどまだ手が出せないという方向けの記事になります。

本記事の対象になる人

  • Ansibleを使ってみたいけど、どんな事(やりたい事)ができるか解らない
  • 試しに使ってみるにも何をすればいいかわからない
  • 概要はなんとなくわかったけど、凝ったことをする方法がわからない

私は長らく上記の状態で、中々手が出せずにいましたが、 ある程度自分で調べて使えるようになるきっかけは、以下の2つを覚えたからでした。

  • ホストごとに変数を定義する
  • roleの利用方法と変数の上書き方法

本記事で取り上げるので、同じような状態の方の助けになれば幸いです。

サンプルplaybook

説明のため、ここでは以下の作業のplaybook化を題材にします。(apache)

  • サーバへのパッケージのインストール
  • 設定ファイルの作成
  • インストールしたサービスの起動

例えば、こんな感じのplaybookになります。

---
- name: deploy apache
  become: true
  hosts: web
  tasks:
  - name: install apache
    yum:
      name: httpd
      state: latest

  - name: create config file
    template:
      src: vhosts.conf.j2
      dest: /etc/httpd/conf.d/vhosts.conf

  - name: enable apache service
    service:
      name: httpd
      enabled: yes
      state: started

この時点で出てきた疑問

え?yumなの?Ansibleを使えばOSの違いを吸収できるんじゃなかったの?

OS非依存かどうかはモジュールの実装によりますので、OSごとに固有の処理が必要になる場合は以下のような実装が必要になります。

  • ansibleの変数を見てOSのタイプを識別する
  • 条件文(when)を入れて、RedHatだったらyum、Ubuntuだったらapt…というような分岐処理にする

このようにOS非依存な形で記述するにはplaybook側で違いを吸収する記述が必要になる場合があります。 ただし、こういった処理は既に誰かが作っていることが多いのでroleの使用をおすすめします。(詳細は後述)

※パッケージに関しては packageモジュールというOS非依存のモジュールがあるので、上記はあくまで説明のための例になります。パッケージ以外の例だと、設定ファイルの場所がディストリビューションによって異なるといったケースがあります。

対象ホストごとに違う値を設定したいんだけど…

例えばlistenするIPなど、設定ファイルに自身のIPアドレスを記述したい場合が該当します。 私がansibleを始めようとして調べたときは 「ansible_default_ipv4.addressという値を使って取得できるので、それをtemplateの適用したい場所に入れて…」といった具合の情報が出てきました。

<VirtualHost {{ ansible_default_ipv4.address }}:{{ listen_port }}>
    ServerName {{ vhost_servername }}
    DocumentRoot {{ vhost_docroot }}
</VirtualHost>

ただそうなると今度は

  • ansibleで取得できる変数があるのはわかったけど何があるかわからない
  • 欲しい値に対応してない可能性がある

という疑問が出てきます。

ホストごとに固有の変数なのでhostvars と呼ばれていますが factsとして取得する以外にも、単純に変数として宣言もできます。 (ちなみに、factsをカスタマイズして取得する変数を追加することもできます。) 下記はinventoryに定義する方法をとっています。

---
[web]
web00.test listen_ip=192.168.0.100
web01.test listen_ip=192.168.0.101

これでホストごとに違う値をもたせられるだけでも、大分柔軟に設定ファイルを作れるのではないでしょうか。 変数の定義の仕方はいくつかあり、なおかつ変数の優先度などもありますが詳しくは参考リンクを御覧ください。

roleを使ってみる

ここまでで冪等性をもたせたり、OS非依存に作ろうとするとやっぱり作るのが面倒という印象を持った方もいると思います。

誰かが既に作っていそうなものは、再利用したい…そこでroleの出番です。

試しにapacheのroleを入れてみよう

Ansible Galaxyからapacheを検索すると geerlingguy.apache というroleが見つかるのでこちらを使用します。

以下のコマンドでインストールします。(-p オプションはインストール先の指定。)

$ ansible-galaxy install geerlingguy.apache -p role

roleを使う場合のplaybookの記述は以下のようになります。

---
- name: deploy apache
  become: true
  hosts: web
  roles:
    - geerlingguy.apache

これでroleを適用してapacheがインストールされます。 templateなども、role内にあれば適用されます。

自分の環境用にカスタマイズする

以下の手順で、カスタマイズができます。

カスタマイズに必要な変数を調べる

galaxyでroleを見つけた際に、readmeを読むと、 どんな変数があって、どう変えれば良いかといった情報も書かれています。 変数のデフォルト値は defaults/main.yml で定義されているので、そちらと templates や tasks を見るとよいでしょう。

例えば、geerlingguy.apache では vhost の listen ip は以下のように apache_listen_ip として定義されてる事がわかります。( templates/vhosts.conf.j2 )

....
<VirtualHost {{ apache_listen_ip }}:{{ apache_listen_port }}>
  ServerName {{ vhost.servername }}
....

また defaults/main.yml を見ると以下のようにデフォルト値が定義されています。

...
apache_listen_ip: "*"
apache_listen_port: 80
...

お目当ての変数をオーバーライドする

listen ipを、* ではなく、ホストごとに特定のIPアドレスに固定するのであれば、以下のように記述します。

---
[web]
web00.test apache_listen_ip=192.168.0.100
web01.test apache_listen_ip=192.168.0.101

変数には優先順位があり、role/xxxx/defaults/ 配下よりも、inventoryの値が優先されるので、 自分の環境に合わせてinventoryに定義し、適用する環境を変えたいときはinventoryファイルを別途用意する… というような運用が考えられます。

その他

ここでは取り上げませんが、他にも以下のような機能があります。

  • dry-runオプション
  • 適用するホストを限定する( -l オプション)
  • 変数をvarsファイルに記述する
  • 変数を元にしたループ(with_items)
  • 特定の条件を満たしたときだけ実行(when)
  • templateの中にif文を入れる

おすすめの学習方法

最後に、おすすめの学習方法を紹介します。

  • 簡単なものから少しづつやってみる

いきなり複雑なことをやろうとすると躓きやすいので、まずは簡単なところから慣らしていくのが良いと思います。

  • ansible-galaxyにある role を使ってみる

本日紹介した内容で、既にあるroleを使いつつ、必要な変数だけ上書きする…という雰囲気は伝わったかと思います。要件に合致するものがあればになりますが、あまり自分で実装せずとも始められるのでこちらも取っ掛かりとしておすすめです。

  • 勉強会に出てみる

これから始めようという方だと「勉強会に出ても、話がわかるだけの知識がないし…」と尻込みしてしまうかもしれませんが、もくもく会であれば、自習の場なのでセルフペースの学習でも問題ないですし、 Ansible Lightbulbなど、教材も用意されているので詰まったときに質問もしやすいかと思います。

参考リンク

Ansible Getting Start https://docs.ansible.com/ansible/latest/user_guide/intro_getting_started.html

Ansible Module Index https://docs.ansible.com/ansible/latest/modules/modules_by_category.html

Ansible変数の優先度 https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable

Ansible Galaxy https://galaxy.ansible.com/

Ansibleユーザ会 https://ansible-users.connpass.com/

Ansible Lightbulb https://github.com/ansible/lightbulb

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。