話題の記事

Ansibleチュートリアル 2017

2017.03.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

渡辺です。

2015年11月にRole を使ったAnsibleのチュートリアル書きました。 それから1年以上経ち、ノウハウも溜まってきたので、新しく書き直してみます。

セットアップ

Ansibleのインストールと、EC2インスタンスを2台起動しておきます。

ssh_configの作成

はじめにホスト情報をssh_configに定義します。 ansible.cnfでssh_configを設定するでも書いたようにSSHで接続する時のユーザ名や秘密鍵の場所はssh_configを作成してまとめておくと便利です。

プロジェクトディレクトリにssh_configを作成しましょう。

Host *
  StrictHostKeyChecking no
  UserKnownHostsFile /dev/null

Host test1a
  HostName xx.xxx.xx.xxx
  User ec2-user
  IdentityFile ~/.ssh/dev.pem

Host test1c
  HostName xx.xxx.xx.xxx
  User ec2-user
  IdentityFile ~/.ssh/dev.pem

ssh_configを作成したならば、SSH接続できることを確認してください。

$ ssh -F ssh_config test1a
Warning: Permanently added 'xx.xxx.xx.xxx' (ECDSA) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2016.09-release-notes/
4 package(s) needed for security, out of 8 available
Run "sudo yum update" to apply all updates.

作成したssh_configはAnsible以外でも利用できるので、一緒にバージョン管理システムに登録しましょう。

inventoryの作成

inventoryファイルには、Ansibleでホストとホストのグループを定義します。 ホストグループを使えば複数のサーバを対象として、Ansibleを流すことができるので便利です。

プロジェクトディレクトリにhostsという名前でファイルを作成します。

[test]
test1a
test1c

ここではホストグループtestに、ホストtest1aとtest1cを追加しました。 ホスト名はssh_configで定義したホスト名を使用します。

ansible.cfgを配置する

Ansibleでプロジェクトディレクトリのssh_configを利用するため、ansible.cfgを作成します。

[defaults]
inventory = hosts
retry_files_enabled = False

[privilege_escalation]
become = True

[ssh_connection]
control_path = %(directory)s/%%h-%%r
ssh_args = -o ControlPersist=15m -F ssh_config -q
scp_if_ssh = True

合わせてオススメのオプションを設定しておきます。

Playbookを実行する

Playbook test.ymlを作成します。

- hosts: test
  roles: []

現時点ではrolesは空配列で良いでしょう。

動作確認します。

$ ansible-playbook test.yml 

PLAY [test] ********************************************************************

TASK [setup] *******************************************************************
ok: [test1a]
ok: [test1c]

PLAY RECAP *********************************************************************
test1a                     : ok=1    changed=0    unreachable=0    failed=0   
test1c                     : ok=1    changed=0    unreachable=0    failed=0

ansible.cfgでデフォルト値を設定しているため、実行時にinventoryの指定は不要です。

Roleの作成と実行

rolesディレクトリを作成し、Roleを作成します。

Role system/lang を作成します。 Roleで実行するタスクは roles/[Role名]/tasks/main.ymlに記述してください。

# roles/system/lang/tasks/main.yml
---
- name: set LANG=ja_JP.UTF-8 in /etc/sysconfig/i18n
  lineinfile:
    dest: /etc/sysconfig/i18n
    regexp: "^LANG="
    line: "LANG=ja_JP.UTF-8"
    backup: yes

このRoleでは、/etc/sysconfig/i18nを編集し、言語設定を変更します。

test.ymlを編集し、system/langをrolesに追加します。

- hosts: test
  roles:
    - system/lang

実行します。

$ ansible-playbook test.yml 

PLAY [test] ********************************************************************

TASK [setup] *******************************************************************
ok: [test1c]
ok: [test1a]

TASK [system/lang : set LANG=ja_JP.UTF-8 in /etc/sysconfig/i18n] ***************
changed: [test1a]
changed: [test1c]

PLAY RECAP *********************************************************************
test1a                     : ok=2    changed=1    unreachable=0    failed=0   
test1c                     : ok=2    changed=1    unreachable=0    failed=0

社内で共有しているRoleなどがあれば、コピーして使えます。 プロジェクト固有のRoleはそれぞれ作成してください。

グループ変数の追加

再利用可能なRoleは汎用化し、グループ変数で値を指定できるようにします。

まず、Roleで埋め込み変数を参照するように修正しましょう。

# roles/system/lang/tasks/main.yml
---
- name: "set LANG={{ system_lang }} in /etc/sysconfig/i18n"
  lineinfile:
    dest: /etc/sysconfig/i18n
    regexp: "^LANG="
    line: "LANG={{ system_lang }}"
    backup: yes

system_langが埋め込み変数の変数名です。

変数名はグローバルスコープなので注意して名前をつけてください。 また、原則としてダブルクォーテーションで囲った中で利用しないと変数展開が行われないので注意します。

変数はグループ変数に定義すれば良いのですが、Roleで使う場合はデフォルト値があると便利です。 Roleのdefaultsディレクトリにmain.ymlを作成し、デフォルト変数を定義しましょう。

# roles/system/lang/defaults/main.yml
---
system_lang: ja_JP.UTF-8

なお、varsディレクトリに作成した場合、グループ変数よりも優先されてしまいます。 非情に使い勝手悪いRoleになるので注意しましょう。

Playbookを実行してみます。

$ ansible-playbook test.yml 

PLAY [test] ********************************************************************

TASK [setup] *******************************************************************
ok: [test1a]
ok: [test1c]

TASK [system/lang : set LANG=ja_JP.UTF-8 in /etc/sysconfig/i18n] ***************
ok: [test1a]
ok: [test1c]

PLAY RECAP *********************************************************************
test1a                     : ok=2    changed=0    unreachable=0    failed=0   
test1c                     : ok=2    changed=0    unreachable=0    failed=0

デフォルト変数が適用されているため、サーバの状態は変わりません。

最後にグループ変数を作成します。 group_varsディレクトリを作成し、グループ名.ymlを作成します。

# group_vars/test.yml
---
system_lang: en_US.UTF-8

グループ変数はRoleのデフォルト変数よりも強いため、グループ変数の値が優先されます。

実行確認です。

$ ansible-playbook test.yml 

PLAY [test] ********************************************************************

TASK [setup] *******************************************************************
ok: [test1a]
ok: [test1c]

TASK [system/lang : set LANG=en_US.UTF-8 in /etc/sysconfig/i18n] ***************
changed: [test1a]
changed: [test1c]

PLAY RECAP *********************************************************************
test1a                     : ok=2    changed=1    unreachable=0    failed=0   
test1c                     : ok=2    changed=1    unreachable=0    failed=0

グループ変数が反映され、サーバの状態が更新されました。

なお、全ホストに有効な変数を定義する場合は、all.ymlに定義してください。

まとめ

ssh_configansible.cfgを設定することで、パラメータも最小限にRoleをサーバに適用可能です。 再利用できる形にRoleを作成し、効率良いサーバ管理を行いましょう。