目次
初めまして!
新人エンジニアのmoridyです。
今回は弊社でもIaCツールとして活用している、Ansibleについての記事です。
昨年の11月に入社するまではAnsibleのAの字も知らなかった私が、研修の中でつまずいたポイントをまとめました!
これからAnsibleを学習する方の助けになれればと思います。
検証は以下のバージョンで行っています。
- Ansible 6.7.0
- Ansible-core 2.13.13
Ansible-coreって何?
Ansibleはモジュールを利用して、さまざまな操作を実現します。Ansible 2.9までは各種のモジュールが入った状態で提供されていましたが、2.10からは従来通りのオールインワンパッケージであるAnsibleと、最小構成のAnsible-coreに分かれて提供されています。コミュニティが作成した多彩なロールやコレクション(Playbook、ロール、モジュール、およびプラグインが含まれる)がAnsible Galaxyで配布されており、そこから必要なものを選ぶ事ができます。
ちなみに「Ansible ドキュメント」で Google検索を行うと、2024年2月時点では2.9のドキュメントが一番上に表示されるので注意しましょう。現在は2.17が最新で、2.15まで日本語のドキュメントが公開されています。
まずはYAMLから
YAML(ヤメル、ヤムル)とは、構造化データやオブジェクトを文字列にシリアライズ(直列化)するためのデータ形式の一種。
https://ja.wikipedia.org/wiki/YAML
AnsibleはYAMLで記述されます。初心者はまずYAMLの文法をしっかりと理解することが大事です。
YAMLの初版は2001年とのことですが、前職で扱うことはなく初見でした・・・。他業界から転職した方はマークアップ言語的な書き方に戸惑うかも知れません。
IaC関連ではAnsible以外でもYAMLを活用する機会は多く(K8s、terraformなど)、足場を固めておいて損はありません。
Jinja2のテンプレートを使用するには・・・
AnsibleはJinja2のテンプレートエンジンを利用することで動的な処理を実現しています。
二重中括弧({{}})で囲うことでJinja2テンプレートである事を表現し、特に変数を利用するために多用することになります。
YAMLの仕様です
YAMLはブロックスタイルとフロースタイルで記述することができます。ブロックスタイルはインデントでマッピング(ディクショナリ、ハッシュ)を表現するのですが、フロースタイルでは中括弧({})を使用します。
#ブロックスタイル
sample:
foo: bar
hoge: fuga
#フロースタイル
sample: {foo: bar, hoge: fuga}
そのため、コロンの直後に中括弧があるとYAMLはマッピングと認識してしまい、Jinja2のテンプレートが使用できません。Ansibleでコロンの直後に変数を置きたい場合は、行全体を引用符(””)で囲む必要があります。
#これはNG
sample:
foo: {{bar}}
hoge: fuga
#これはOK
sample:
foo: "{{bar}}"
hoge: fuga
そのほかにもいくつか([] {} > | * & ! % # ` @ , など)の記号はYAMLの予約文字となっているので、気をつけましょう。この例外を知らないと、なぜここだけ引用符が必要なのか頭を悩ませることになります。
#エラーは丁寧に出してくれる
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
whenのJinja2は生
Ansibleでは条件分岐をwhenで行うことができます。(Jinja2のifなど他の方法も利用可能)
whenによる条件分岐は、ミドルウェアが既にインストールされていたらどうするか、外部ディスクがアタッチされていたらマウント、などなど頻繁に利用することになります。
ここだけの話
最初にwhenに触れる際には注意点があります。
見出しにも書いてあるようにwhenのJinja2は生です。
どういうことかというと、ここ以外ではJinja2のテンプレートを利用するために二重中括弧({{}})で囲んでいましたが、それが必要ありません。
#これは警告される
vars:
hoge: fuga
when: "{{hoge is defined}}"
debug:
msg: "{{hoge}}"
#これは大丈夫
vars:
hoge: fuga
when: hoge is defined
debug:
msg: "{{hoge}}"
他ではJinja2と二重中括弧({{}})がセットになっているので、whenを初めて使う際に生のJinja2を求められると戸惑います。whenではそれ自体が二重中括弧({{}})の役割だと理解すると良いでしょう。
#警告しつつも処理はしてくれる
[WARNING]: conditional statements should not include jinja2 templating
delimiters such as {{ }} or {% %}. Found: {{file is defined}}
whenの判定がブロック内で変わる
Ansibleのブロックはタスクをまとめてくれるものです。まとめたタスクにはブロックごとwhenなど(ループを除く)を記述できるので、記述を簡易にできます。
ブロック内の処理はそれぞれ
ブロックに対して記述したwhenなどはブロック内のタスクごとに適用されます。
ブロック自体は影響を受けません。
# 1つ目が実行されない
when: hoge is not defined
block:
- name: task1
vars:
hoge: test
debug:
var: hoge
- name: task2
debug:
var: hoge
# 全て実行される
when: hoge is not defined
block:
- name: task1
debug:
var: hoge
- name: task2
debug:
var: hoge
whenで言うとif文のつもりでブロックに適用することはできません。
ブロック内でwhenの判定に利用していた変数が変化すると、ブロック内のタスクに実行されるものとされないものが出てきてしまいます。
あとがき
今回はAnsibleを学習する上でつまずいたポイントの中でも、序盤に知っておきたかったことをピックアップしてご紹介しました。いかがだったでしょうか。Ansible初学者の助けとなれていれば幸いです。
私自身、現在進行形で学習を行っておりますので、今後つまずいたポイントがあればまた記事を書かせて頂きます!
最後までお読み頂きありがとうございました!