ライトウェルブログ

2019/06/12Windows Server 2016の構築手順を自動化する その3

こんにちは!

前回はAnsibleをインストールして
簡単なPlaybookを作成してみました。
今回は、もう少し発展させてみようと思います。

前回のPlaybook

前回は、PlaybookとInventoryの作成を行いました。

そして、前回作成したPlaybookはこんな感じでした。

#playbook.yml
---
- hosts: windows
  tasks:
    - win_user:
        name: ansible_admin
        password: hogehoge123!
        state: present
        groups:
          - Administrators
          - Users

このPlaybookを実行すると、対象のWindows上に「ansible_admin」というユーザが作成されました。

言い方を変えると、このplaybookでは「ansible_admin」というユーザしか作れません。

他にもやることを増やすとなるとこの続きに追記をしていく必要があります。でも、やることが増えていくとPlaybookが複雑化してしまいます。

 

Roleにしよう

ここで、Playbookの中身について少し説明します。

  • Playbookの中身

前回書いたPlaybookでは、hosts: と書いてある部分とtasks: と書いてある部分があります。

Ansible で行わせたい処理は、tasks: で定義します。

hosts: の後ろには、このPlaybookを適用するホストやグループを指定しています。
指定は、Inventoryファイルに書いたグループ名またはホスト名を書いています。

tasks: より下の記述でモジュールを呼び出しモジュールに必要なパラメータを与えていきます。

この、Playbookの場合win_userというモジュールを呼び、次の行からはwin_userモジュールに与えるパラメータを指定しています。
win_userというモジュールは、操作対象のWindowsのローカルユーザを管理する為のモジュールです。
モジュールのパラメータについては、ここでは詳細を省きますが恐らくWindowsのユーザ管理したことがある方であればなんとなくでわかると思います。

#playbook.yml
---
- hosts: windows
  tasks:
    - win_user:
        name: ansible_admin
        password: hogehoge123!
        state: present
        groups:
          - Administrators
          - Users

※参考:モジュールについては、Ansibleの公式ドキュメントに説明があります。
win_user

  • Roleを使う

このtasksから下の部分は、Roleを利用することでファイルを分けることができます。
PlaybookやInventoryファイルと同じ場所に、rolesというディレクトリを作成します。
さらにその下には、roleの名前を冠したディレクトリとtasksというディレクトリを作り、その中にmain.ymlというファイルを作ります。

[root@Ansible01 ansible]# mkdir -p roles/win_user_add/tasks/
[root@Ansible01 ansible]# vi main.yml

main.ymlには、上のPlaybookのtasksより下の内容を記載します。

#main.yml
---
- win_user:
    name: ansible_admin
    password: hogehoge123!
    state: present
    groups:
      - Administrators
      - Users

また、playbook.ymlも以下のように書き換えます。
roles: の下に、rolesディレクトリ直下のディレクトリ名を指定します。(ディレクトリ名がそのままロールの呼び出し時の名前となります。)

前回のPlaybookでやっていたユーザを作成する部分はroleに外だしされます。Playbookからは外だししたroleを呼び出すような感じになります。

#playbook.yml
---
- hosts: windows
  roles:
    - win_user_add

ここまでで、ファイルの構成は以下のようになっていると思います。

[root@Ansible01 ansible]# tree
.
|-- inventory
|-- playbook.yml
`-- roles
    `-- win_user_add
        `-- tasks
            `-- main.yml

3 directories, 3 files
[root@Ansible01 ansible]#

このように、roleを利用することで処理を部品化できます。やることが1つ、2つならPlaybookにすべてを書いてしまうのもありでしょう。しかし、やることが増えたり、管理対象が増えたり、管理対象ごとに異なる状態にしたいときは、すべてをPlaybookに書いてしまうと長大で複雑怪奇なPlaybookなってしまいますね。

さて、「管理対象ごとに異なる状態にしたいとき」と言いました。
これは、例えばServerAで作るユーザは「taro」という名前にしたいが、ServerBでは「jiro」という名前にしたいといったようなカスタマイズをしていきたくなると思います。

vars(変数シート)を使おう

さて、ここで前回の予告で登場したvars、つまり変数が出てきます。
モジュールに渡すパラメータを変数であつかえれば、Playbookやrolesに汎用性が出てきます。

  • varsの基本的な使い方

varsの使い方は、単純に以下のように使えます。

#playbook.yml
---
- hosts: windows
  vars:
    username: ansible_admin
  tasks:
    - win_user:
        name: '{{ username }}'
        password: hogehoge123!
        state: present
        groups:
          - Administrators
          - Users

前回作成したPlaybookにvars:で始まる部分を追加しています。ここでは、usernameという変数を定義し値をセットしています。(4-5行目)

例の通り変数は以下の形式で定義します。

変数名: 値

変数を使うときは、8行目のようになります。上記の例ではwin_userのモジュールにあたえるパラメータ name: に変数を参照するように指定しています。
定義した変数を使うときは、{{ }}で変数名を囲んで使用します。(追々出てきますが、囲まない場合もあります。)

さて、この例だとまだ先ほどのたとえのようにServerAで作るユーザは「taro」という名前にしたいが、ServerBでは「jiro」という名前にしたいという使い方はできません。

  • host_varsとgroup_vars

Ansibleには、host_varsとgroup_varsという変数があります。
読んで字のごとくですというか、そのままです。

host_vars ・・・ ホスト毎に適用される変数
group_vars ・・・グループ毎に適用される変数

ここでいうホスト、グループとは?、
極々単純です。前回作成したInventoryファイルを見てみます。
グループはインベントリファイルの”操作対象グループ”となっているもの、
ホストはインベントリファイルの”操作対象ホストx”となっているものです。
以下の例では、操作対象ホスト1と2は「windows」というグループにまとめています。

2#Inventory
[windows]                                      #  操作対象グループ
192.168.123.123                                #  操作対象ホスト1
192.168.123.124                                #  操作対象ホスト2

[windows:vars]                                 #  操作対象グループの変数
ansible_user=Administrator                     #  接続する管理者ユーザー名
ansible_password=Password123                   #  接続する管理者パスワード
ansible_connection=winrm                       #  接続プロトコル
ansible_port=5986                              #  winrmで使用するポート
ansible_winrm_server_cert_validation=ignore    #  HTTPSの証明書の検証しない

※インベントリファイルでは、#の右のコメントは実際には入れないで下さい。ここでわわかりやすくするために記載しています。
コメントを入れる場合は、前後の行に入れてください。

  • host_varsとgroup_vars を使ってみる準備

host_varsとgroup_varsを使ってみます。ここまで、順にやっていれば、現在のファイル構成は以下のようになっていると思います。

[root@Ansible01 ansible]# tree 
.
|-- inventory
|-- playbook.yml
`-- roles
    `-- win_user_add
        `-- tasks
            `-- main.yml

3 directories, 3 files
[root@Ansible01 ansible]#

inventoryとplaybookがあるのと同じ場所に、host_vars、group_vars というディレクトリを作ります。

[root@Ansible01 ansible]# mkdir host_vars group_vars

それぞれのディレクトリに、inventoryファイルの内容と一致する名前でファイルを作ります。

このinventoryファイルの例で行けば、
host_varsの配下に”192.168.123.123″と”192.168.123.124”いうファイルを作ります。
group_varsの配下は、”windows”というファイルを作ります。

  • host_varsとgroup_varsを定義

では、以下のような想定でユーザを作成することを考えます。
・ユーザ名

1台目のサーバ(192.168.123.123) : taro
2台目のサーバ(192.168.123.124) : jiro

・パスワード
2台とも共通で、”P@ssword123″
また、パスワードを無期限に設定

この想定であれば、ユーザー名はホスト毎の設定となるのでhost_varsに、パスワード関連は共通なのでgroup_varsに定義します。

・host_vars/192.168.123.123

local_username: taro

・host_vars/192.168.123.124

local_username: jiro

・group_vars/windows

user_password: P@ssword123
pw_never_expire: yes

・roles/win_user_add/tasks/main.yml
roleのファイルを以下のように書き換えます。
name: と  password:、 password_never_expires: のパラメータはそれぞれ変数から参照するようにします。

#main.yml
---
- name: ユーザの作成
  win_user:
    name: '{{ local_username }}'
    password: '{{ user_password }}'
    password_never_expires: '{{ pw_never_expire }}'
    state: present
    groups:
      - Administrators
      - Users

・Playbook
Playbookの中は、roleの説明のところと同じように以下の内容になっていることを確認します。

#playbook.yml
---
- hosts: windows
  roles:
    - win_user_add

 

ここまでで、以下のようなファイル構成になると思います。

[root@Ansible01 ansible]# tree 
.
|-- group_vars
|   `-- windows
|-- host_vars
|   |-- 192.168.123.123
|   `-- 192.168.123.124
|-- inventory
|-- playbook.yml
`-- roles
    `-- win_user_add
        `-- tasks
            `-- main.yml

5 directories, 6 files
[root@Ansible01 ansible]#

では実行してみましょう。

  • Playbookを実行

Playbook実行前はこんな感じです。

 

Playbook を実行します。

[root@Ansible01 ansible]# ansible-playbook -i inventory playbook.yml

PLAY [windows] *******************************************************

TASK [Gathering Facts] ***********************************************
ok: [192.168.123.124]
ok: [192.168.123.123]

TASK [win_user_add : ユーザの作成] *************************************
changed: [192.168.123.124]
changed: [192.168.123.123]

PLAY RECAP **********************************************************
192.168.123.123  : ok=2   changed=1  unreachable=0  failed=0
192.168.123.124  : ok=2   changed=1  unreachable=0  failed=0

[root@Ansible01 ansible]#

ユーザの作成TASKが、changedになりました。

PLAY RECAPのところでも、各対象への結果が表示されていますが、OKやchangedがカウントされています。
ここまできてなんですが、OKとchangedの違いは次回説明します。

ひとまず、今は結果を見てみましょう。
ということで、実際に対象となったWindows上も確認してみます。

それぞれのWindows上に異なるユーザが作られていることがわかります。

各ユーザのパスワードが無期限に設定されています。

 

このように、host_varsやgroup_varsを使用することで、Playbookやroleは共通のものを使いつつ管理対象ごとに異なる設定ができるようになります。

まとめ

今回は、roleとvarsについて扱いました。

前回作成したPlaybookは手順書そのものです。
簡単なこと1つだけであれば、Playbook1つ、いわば1枚の手順書ですべてでもよいかもしれません。

でも、10も20もやることが増えてくると、1枚の手順書収まらなくなるし、無理に1枚に収めるのもしんどいですよね。
そうなってくると手順書を分割したり、一覧や目次をつくったりすると思います。

今回は、Playbookが手順書一覧、roleが分割した具体的な操作手順書という形に変えてみました。

さらに、varsをつかうことで同じ手順書を他でも使うことができるようになりました。
いままで特定のシステム向けの手順書だったものが、汎用的に使える手順書に生まれ変わりました。

roleを使いファイルを別にすることで処理(手順)の部品化、さらにvarsを使うことで部品化したroleの汎用性が増したわけです。

さて、おそらくこんなことを思う方もいたのではないでしょうか?

  • Playbookもう一回実行したらどうなるの?
  • まだ、ユーザが1つしか作れないではないか!これじゃ、まだ実用的とは言えないよ!!
  • group_varsとhost_varsに同じ変数を作ったらどうなるの?

次回は、Ansibleの利点の1つ 冪等性とvarsの掘り下げにスポットを当ててみようと思います。

 

トップページに戻る