このエントリーをはてなブックマークに追加

Ansibleでの連番ホスト名をつけるなど

クックパッドの新オフィスでitamaeによる寿司の無限プロビジョニングを体験して、Ansibleのお悩み相談してきた #infra_sushi

という記事を拝見しました。

お悩みの詳細はスライドを見てもらうとして、一つのツールですべて賄おう
として頑張ってしまうと、構成に矛盾が出てしまうので、
適材適所で組み合わせて使わないといけないというのは、完全に正論。

というのはぼくも完全に同意します。

ですが、実はこの2つの悩みはたぶんansibleでも解決できます。(LTを聞いていたわけではないので、意図とずれていたらごめんなさい)

1. EC2インスタンス作成の時の変数設定

[webservers]
prod-web01
prod-web02
prod-web03

[webservers:vars]
ami=ami-785bae10
group_tag=web

というinventoryファイルがすでにあるときに

---
- hosts: webservers
  gather_facts: no  # noにしておくと捗る
  tasks:
    - local_action:
        module: ec2
        (パラメータは一部略しています)
        instance_type: t2.micro
        image: "{{ ami }}"  # inventory
        exact_count: 3
        instance_tags:
          role: "{{group_tag }}" # ここちゃんと使えます
        region: us-east-1
      run_once: true  # 1.7以降で使えます
      register: ec2

local_actionはansible-playbookコマンドを実行するホストですので、hostsになにが書いてあろうとも、localhostで実行されます。

ただ、複数のホストが含まれているグループを指定した場合、local_actionで指定したモジュールもその数だけ実行されてしまいます。

このため、1.7から導入されたrun_onceを使います。run_onceは、グループ内の先頭で定義されたホストでのみ実行されるようにするためのパラメーターです。今回はlocal_actionですから、ローカルホストで一回だけ実行されることに鳴ります。

ホスト名自動採番

自動採番とありますが、ここでは連続の番号を振る、と解釈します。

採番はwith_indexed_itemsを使うと、{{ item.0 }}にインデックス番号が、{{ item.1 }}にリストの中身が入ります。

- debug: msg="{{ item.1 }} at {{ item.0 }}"
  with_indexed_items: some_list

これを利用します。

最初こうしてみたのですが、

- hostname: name="{{ host_prefix }}-{{ item.0 }}"
  with_indexed_items: play_hosts

これだと、例えば3台あれば、その3台に対して3回、合計9回実行されてしまいます。

というわけで、前述のrun_onceと組み合わせます。ただし、単にrun_onceだと、一台でしか設定できないことになってしまいます。ここでdelegate_toを使います。

- hostname: name="{{ host_prefix }}-{{ item.0 }}"
  run_once: yes
  delegate_to: "{{ item.1 }}"
  with_indexed_items: play_hosts

ちなみにplay_hostsは今回のplayで対象となるホストのリストが入っている、最初から定義済みの変数です。

余談

0から始まるのがいやだ?贅沢だねぇ。

- hostname: name="{{ host_prefix }}-{{ item.0 + 1}}"

まとめ

ということで、2つの問題に対してansibleでも解決できることを示しました。

ただ、見て分かる通り結構トリッキーですので、適材適所で組み合わせて使ったほうがいい、というのは合意します。

宣伝

ツキノワでは、 ansibleの有償セミナー(ハンズオン付き)を計画しています。

興味のある方はwebページからお問い合わせください。