自宅で執筆してますGMOアドマーケティング GMOSSP開発担当の@KazuakiMです。
コロナの影響で私の生活環境は大きく変わりましたが、私は元気です。
今日はGMOSSPの環境構築、リリースなどで活躍しているAnsibleに触れる機会がありましたので、
Ansible初心者の私がAnsibleのPlaybookを修正して本番環境に反映するまでをコードと共にご紹介します。
Ansibleの知識が全くないため、Ansible構築・運用ガイドブックを参考に既存のコードを読み解いていきました。
こちらの本は弊社のインフラチームに良本だとお墨付きをもらい、じっくり読み込んでなんとなく理解が深まりました。
ではさっそく、Ansible独自?の用語と合わせて、設定方法をご紹介します。
インベントリ
Ansible適用対象のホストを記載します。その際にホストグループを設定する事ができます。
書き方的には下記のような感じで書きます。
1 2 3 4 5 6 7 8 9 10 11 |
[web] web01 web02 [db] db01 db02 [cloud:children] web db |
順に説明します。こちらはwebホストグループに、web01、web02が属しています。
そのため、webホストグループを指定するとweb01、web02が適用対象となります。
1 2 3 |
[web] web01 web02 |
また、ホストグループはネスト構造が可能で、その場合にはchildrenと指定します。
1 2 3 4 5 6 7 8 9 |
[cloud:children] web db #構成イメージ # cloud ┳ web ┳ web01 # ┃ ┗ web02 # ┗ db ┳ db01 # ┗ db02 |
モジュール
Ansibleは多くのモジュールを提供しています。今回は比較的触れやすそうだろうと思い、
cronvar/cronモジュールの導入を私の方で実装させて頂きました。
最新ドキュメントは以下の2つとなります。
https://docs.ansible.com/ansible/latest/modules/cronvar_module.html
https://docs.ansible.com/ansible/latest/modules/cron_module.html
ではそれぞれのモジュールの設定を見ていきましょう。
cronvarはMAILTOなどcronに設定する環境変数となります。
下記は例となります。
1 2 3 4 5 6 |
#abcdユーザのcronにMAILTOを設定しています。 - name: Set "MAILTO=xxxx@xxxxx.xxx" at cron cronvar: name: MAILTO user: abcd value: xxxx@xxxxx.xxx |
続いて、cronを仕込んでみます。
1 2 3 4 5 6 7 8 9 10 11 12 |
#abcdユーザのcronにhello_world.phpを毎分実行する設定をしています。 - name: Set "* * * * * /bin/php $PRJ_DIR/bin/hello_world.php" at cron cron: name: Hello World user: abcd backup: yes month: "*" day: "*" hour: "*" minute: "*" weekday: "*" job: "/bin/php $PRJ_DIR/bin/hello_world.php" |
これでモジュールの設定は一段落です。
Role
1つのPlaybookに全てのタスクを記載すると膨大な量となる上、冗長なコードもでてきます。
Role機能を利用して、処理の細分化を適切に行ないます。
今回は先程作成したモジュールのコードをroles/cron/tasks配下に設置しています。
設置したモジュールのコードはmain.ymlからインポートします。
インポートする際に、先程設定したホストグループに対してタスクを実行するのか?
特定サーバに対してタスクを実行するのか?等の条件をあわせて設定します。
1 2 3 4 5 |
- import_tasks: web.yml when: "'web' in group_names" - import_tasks: db01.yml when: inventory_hostname == "db01" |
Roles
最後に実行するPlaybookのrolesに今回作成したcronを追加します。
あわせてtagsの設定を行う事で個別実行が出来るようにします。
1 2 3 4 5 |
- name: Sample hosts: web roles: - role: cron tags: cron |
Ansible-lint
実際にAnsibleのPlaybookで動作確認する前にここでコーヒーブレイク。
最近ではコードを書いたら、必ず構文チェックする文化が根づいているかと思いますが、
AnsibleにもLinter機能は提供されています。
作成したPlaybookはLinterにかけて構文チェックを行ないます。
まずはpipコマンドでansible-lintをインストールします。
1 |
$ pip install ansible-lint |
実行方法は下記のような感じで解析したいPlaybookを指定するだけとなります
1 |
$ ansible-lint playbook.yml |
DryRun
では実際に作成したPlaybookを実行してみます。
1 2 3 4 5 6 7 8 9 10 11 |
$ ansible-playbook -i hosts web.yml -l web01 -t cron -v --diff --check Using ~/ansible.cfg as config file TASK [cron : Set "MAILTO=xxxx@xxxxx.xxx" at cron] **************************** skipping: [web01] => {"changed": false, "msg": "remote module (cronvar) does not support check mode"} TASK [cron : Set "* * * * * /bin/php $PRJ_DIR/bin/hello_world.php" at cron] ** ok: [web01] => {"changed": false, "envs": ["MAILTO"], "jobs": ["Hello World"]} PLAY RECAP ******************************************************************* web01 : ok=1 changed=0 unreachable=0 failed=0 |
だいたいこんな感じになるのではないでしょうか。
cronvarはチェックモードを用意されていないため、DryRun結果はわかりませんでした。
Run
DryRunに問題ない事を確認しましたら、–checkを外して、適用という流れとなります。
1 |
$ ansible-playbook -i hosts web.yml -l web01 -t cron -v --diff |
まとめ
Ansibleは非常に優れたツールで利便性も高く、私のような初心者でも簡単な設定であればすぐに作ることができました。
今回はcronという事でわりと身近に感じる設定でしたが、より深い部分まで触れる事で、アプリエンジニアとしての視野を広げる機会になる事を実感しました。