【Ansible入門】Playbookで変数を使い効率化を図ってみましょう

記事タイトルとURLをコピーする

こんにちは、CI部の柿﨑です。
10/16(水)より、beatmania IIDX 27 HEROIC VERSE が稼働し始めました。
最近は1日1クレを日課にしておりまして、5年のブランクを経て皆伝取得を目指しております。(以前は中伝でした。)
どの分野にも限らず、資格の取得には日々の積み重ねが大事だと思っている今日この頃です。 今回は、前回のAnsible入門の続きを題材にしていこうと思います。
Playbook内で変数を使うことで可読性や保守性を高めていきましょうというのが、主題となります。

本記事の対象者

  • 前回のAWS環境を準備できる方
  • AWS環境にてサクッとAnsibleに触りたい方

本記事のコンセプト

  • なるべくシンプルに
  • 最低限使えるディレクトリ構成でAnsibleの動作を理解する

前提条件

  • 前回の前提条件を満たしつつ、前回同様の環境を準備する
    ※AnsibleサーバーでAnsibleを使えればおk!

目次

  1. 変数を使ってみよう
  2. Playbookのタスクを効率的に書いてみよう
  3. Playbookを暗号化してみよう
  4. さいごに

1.変数を使ってみよう

前回のPlaybookでは、tasks/main.ymlファイルを以下のように(一部抜粋)記載していました。

- name: create user
  user:
    name: hands-on-user01
    createhome: yes
    state: present
    password: "{{ 'hands-on' | password_hash('sha512') }}"

簡単に書くと各パラメーターをそのまま記載していますね。
Playbookの構文がこれだけならまだ良いですが、実案件で使っていくとコードが膨らんでいくものです。
こんなときにパラメーターを変数化しておくことで、コードを管理しやすくしてくれます。
※お急ぎの方用ですが、最終系は以下のコードになります。そうでない方はパスしてください。

git clone https://github.com/ikayarou/hands-on-02.git

では早速、変数を使えるようにPlaybookを修正していきましょう。
※今回、tasks/main.ymlファイル内のsshd_configは触りません。

  1. Ansibleサーバーにec2-userでSSH接続
  2. 前回のPlaybookがある場合はcd ~/hands-on-01を実行
    Playbookがない場合は、以下の手順を実行
cd
    git clone https://github.com/ikayarou/hands-on-01.git
    cd hands-on-01
  1. 変数格納用のdefaults/main.ymlファイルを作成
mkdir roles/hands-on/defaults
    vi roles/hands-on/defaults/main.yml

以下の内容で保存

---
    # hands-on user
    name: hands-on-user01
    home: yes
    state: present
    remove: no
    password: hands-on
  1. tasks/main.ymlを変数が使えるように修正
vi roles/hands-on/tasks/main.yml

以下の内容で保存

    - name: create users
      user:
        name: "{{ name }}"
        createhome: "{{ home }}"
        state: "{{ state }}"
        remove: "{{ remove }}"
        password: "{{ password | password_hash('sha512') }}"

    - name: change hostname
      hostname:
        name: "{{ inventory_hostname }}"

    - name: modify sshd_config
      lineinfile:
        dest: /etc/ssh/sshd_config
        state: present
        backrefs: yes
        regexp: '^PasswordAuthentication no'
        line: 'PasswordAuthentication yes'
      notify:
        - restart sshd
  1. Playbookを実行し、SSH接続
sudo ansible-playbook -i inventory/hosts site.yml
    ssh hands-on-user01@192.168.20.4
    ※パスワード、hands-on を入力しEnter

上記手順を実行した先で、以下の状態を確認できればおkです。
※ホスト名がClient01でなく、Clinet01だったらごめんなさい。このブログ更新前のhands-on-01が間違ってました。(Gitコード修正済み)

[hands-on-user01@Client01 ~]$ hostname
Client01
[hands-on-user01@Client01 ~]$

ひとつずつ説明いたします。

まず、tasks/main.ymlファイルですが、パラメーターを変数化するときは以下の形になります。
※passwordのところだけやや違いますが、そこは公式ドキュメントに記載があります。

"{{ 変数名 }}"

変数名をなるべく分かりやすい名称にして、各パラメーターを置き換えていけばおkです!
また、以下の項目を追加しました。

remove: "{{ remove }}"
※のちの手順で使うため追加
- name: change hostname
  hostname:
    name: "{{ inventory_hostname }}"
※対象サーバーのホスト名を変更するタスク

前者はのちの手順で説明します。
後者の変数に関しては次のdefaults/main.ymlファイルと一緒に説明します。 次にdefaults/main.ymlファイルですが、tasks/main.ymlファイルで指定されている変数と変数の値が記載されております。

# hands-on user
name: hands-on-user01
home: yes
state: present
remove: no
password: hands-on

このdefaultsディレクトリをhands-onロール配下に作成することで、当該ロールで使用される変数のデフォルト値を定義することができます。
これと似た機能を持つvarsディレクトリというものがあり、どちらも変数を定義することができます。
今回はガッツリAnsibleを触る段階ではありませんので、変数の上書きが容易にできて扱いやすいdefaultsディレクトリを使う方がベターだと考えておkです。 ここでお気づきの方もいるかもしれないですが、defaults/main.ymlファイルに"{{ inventory_hostname }}"のパラメーターが記載されていません。
しかし、Client01サーバーのホスト名がClient01に設定されていました。
これは何かといいますと、マジック変数と呼ばれる機能になります。
こちらに分かりやすく記載されています。
以下画像の赤丸部分の値を引っ張ってきたわけですね!ありがとうAnsible。わざわざ変数のパラメーターを書く必要がありませんので、とても楽ですね♪

2.Playbookのタスクを効率的に書いてみよう

ここまでで変数を使えるようになりました。
ただし、このままの状態でOSのユーザーをいくつも作ってくれえ!
と、頼まれたらどうするのでしょうか。
タスクをコピペして以下のようにしてみたりするかもしれません。

- name: create users_1
  user:
    name: "{{ name_1 }}"
    createhome: "{{ home_1 }}"
    state: "{{ state_1 }}"
    remove: "{{ remove_1 }}"
    password: "{{ password_1 | password_hash('sha512') }}"
- name: create users_2
  user:
    name: "{{ name_2 }}"
    createhome: "{{ home_2 }}"
    state: "{{ state_2 }}"
    remove: "{{ remove_2 }}"
    password: "{{ password_2 | password_hash('sha512') }}"

こうするとdefaults/main.ymlファイルも変数のパラメーターを記述していかないといけません。
想像するだけでもしんどいですよね。
そこでwith_itemsと呼ばれるものを使ってみます。 with_itemsをざっくり説明すると、リスト型や辞書型などのパラメーターの数だけタスク処理をループしてくれるものです。
つまり1つのタスクだけ準備して、パラメーターを複数設定すればおkです。
早速、作成するユーザーを3つに増やして書いてみましょう!

  1. tasks/main.ymlファイルにwith_itemsを追記
cd ~/hands-on-01
    vi roles/hands-on/tasks/main.yml

以下の内容で保存

---
    - name: create users
      user:
        name: "{{ item.name }}"
        createhome: "{{ item.home }}"
        state: "{{ item.state }}"
        remove: "{{ item.remove }}"
        password: "{{ item.password | password_hash('sha512') }}"
      with_items: "{{ users }}"

    - name: change hostname
      hostname:
        name: "{{ inventory_hostname }}"

    - name: modify sshd_config
      lineinfile:
        dest: /etc/ssh/sshd_config
        state: present
        backrefs: yes
        regexp: '^PasswordAuthentication no'
        line: 'PasswordAuthentication yes'
      notify:
        - restart sshd
  1. defaults/main.ymlファイルの変数の書き方を修正
vi roles/hands-on/defaults/main.yml

以下の内容で保存

---
    users:
      # hands-on
      - name: hands-on-user01
        home: yes
        state: present
        remove: no
        password: hands-on

      # ika
      - name: user-ika
        home: yes
        state: present
        remove: no
        password: ika

      # tako
      - name: user-tako
        home: yes
        state: present
        remove: no
        password: tako
  1. Playbookを実行し、SSH接続、ユーザー確認
sudo ansible-playbook -i inventory/hosts site.yml
    ssh user-ika@192.168.20.4
    ※パスワード、ika を入力しEnter

    cat /etc/passwd
    ※末尾に3つのユーザーが追加されていれば成功

こちらもひとつずつ説明していきます。 今回はwith_itemsのパラメーターを変数化していますので、その前提で説明します。
tasks/main.ymlファイルとdefaults/main.ymlファイルの関係は以下の画像のとおりです。
with_itemsuserモジュールと同じインデントになっていることに注意してください。
これはuserモジュールの機能でないことを意味しています。
もし共通の設定があるようでしたら、そこだけwith_itemsとは別の変数として定義すれば、defaults/main.ymlファイルのハッシュの数が減ります。 ではここで、user-ikaだけ削除してみましょう。

  1. defaults/main.ymlファイルを変更
※user-ikaユーザーでログインしている場合は、exit でAnsibleサーバーへ戻ってください。
    cd ~/hands-on-01
    vi roles/hands-on/defaults/main.yml

以下の内容で保存

---
    users:
      # hands-on
      - name: hands-on-user01
        home: yes
        state: present
        remove: no
        password: hands-on

      # ika
      - name: user-ika
        home: yes
        state: absent
        remove: yes
        password: ika

      # tako
      - name: user-tako
        home: yes
        state: present
        remove: no
        password: tako

# ikastate:remove:の値だけ変更しています。
※ここのために今回のハンズオンにてremove:を追加しました。
詳しくはこちらのremoveの説明を参照ください。

  1. Playbookを実行し、SSH接続確認、ユーザー確認
sudo ansible-playbook -i inventory/hosts site.yml
    ssh user-ika@192.168.20.4
    ※パスワード、ika を入力しEnter
    ※接続できないことを確認

    ssh user-tako@192.168.20.4
    ※パスワード、tako を入力しEnter

    cat /etc/passwd
    ※user-ika の表示が消えていれば成功

このようにして1つのタスクで複数のユーザーを同時に作成したり、特定のユーザーだけ削除したりということができました!

3.Playbookを暗号化してみよう

最後はPlaybookを暗号化してみましょう! ときに平文で載せたくない情報もあると思われます。
例えば、OSユーザーのパスワードですね。
主な暗号化のパターンとしては、Playbookのファイル内全てを暗号化するもの、
ファイル内の一部を暗号化するものの2パターンになります。
今回はファイル内の一部を暗号化するansible-vault encrypt_stringを使っていきます。

  1. パラメーターを暗号化する

※user-takoユーザーでログインしている場合は、exit でAnsibleサーバーへ戻ってください。

    cd ~/hands-on-01
    ansible-vault encrypt_string 'hands-on' --name 'password'

パスワードの入力とを求められるため、serverworks と入力、確認用にもう1回 以下の文字列が出力されるため、Encryption successfulの上の行までコピー

password: !vault |
              $ANSIBLE_VAULT;1.1;AES256
              63623934306536633137313638633733336134393731656239343334393461313834383137303439
              6231326361336363373730393964643064363632616637340a623163636466326231623164636334
              35313834613065316134616234396433303766313662306634653230396532623133626434663138
              3630636133306365650a633061323137313334633139366566656163616335396537323330373232
              6238
    Encryption successful
  1. defaults/main.ymlファイルを変更する
vi roles/hands-on/defaults/main.yml

以下のように前の手順でコピーした値で、# hands-onpassword:を上書きする

    users:
      # hands-on
      - name: hands-on-user01
        home: yes
        state: present
        remove: no
        password: !vault |
              $ANSIBLE_VAULT;1.1;AES256
              63623934306536633137313638633733336134393731656239343334393461313834383137303439
              6231326361336363373730393964643064363632616637340a623163636466326231623164636334
              35313834613065316134616234396433303766313662306634653230396532623133626434663138
              3630636133306365650a633061323137313334633139366566656163616335396537323330373232
              6238

      # ika
      - name: user-ika
        home: yes
        state: present
        remove: no
        password: ika

      # tako
      - name: user-tako
        home: yes
        state: present
        remove: no
        password: tako
  1. Playbookを実行
sudo ansible-playbook -i inventory/hosts site.yml --ask-vault-pass
    ※パスワードを聞かれるため、serverworks と入力しEnter

エラーがなければ完了

実行結果には以下のように暗号化されていたパラメーターが平文で出力されてしまいます。
ここからの情報流出には注意が必要ですね! ansible-vault encrypt_stringで暗号化するときは、以下のような構文となります。
ansible-vault encrypt_string '暗号化する値' --name '変数名'
このようにピンポイントで暗号化をしておくと、暗号化されたファイルをいちいち複合化して編集、という手間が減ります。
そして、Playbookが暗号化されている場合は、ansible-playbookコマンドに--ask-vault-passオプションを付与する必要があることにもご注意ください。
オプションなしで実行しますと、当然のようにエラーになるだけですので大きな問題はないです。 ほかにも方法はございますが、今回はおまけ程度ということでサラッと暗号化に触れてみました。

さいごに

今回の内容だけでも、それなりにAnsibleを触れるようになると思われます。
ここからは、複数台のサーバーを管理するイメージを持ちつつ、Playbookをどのように書けば効率的か、保守性が高いかを意識していくことで、
オレ流のベストプラクティスが生まれてくるものと思います。
私もまだまだ知らないことばかりですので、ここはこうした方がいいよ!などの情報がありましたら、教えていただけますとうれしいです。

本記事が、皆様のお役に立てれば幸いでございます。

柿﨑 拓人 (記事一覧)

クラウドインテグレーション部

AWS移行案件の要件定義~構築をメインに担当。
最近ボルダリングをはじめました。