AnsibleからItamaeへ移行しようとしたけどやっぱやめた
webshというWebアプリを自前で運用している
当初はAnsibleというプロビジョニングツールでインフラの構成管理を行っていた
色々と辛みがでてきてitamaeという別のプロビジョニングツールに移行しようとしたけれどやっぱやめた
Ansibleのつらみ
ロールをまたがるvarsが別のロールの設定で上書きされる
先に定義されてるロールの設定値で上書きされてしまう
ロール配下でvarsを定義するときは変数名のコンフリクトが起きないようにロール名をプレフィックスにするのがベターらしい
当初それを知らなくてロールが増えてきたタイミングでプロビジョニングをした時に差分が出始めて異常に気づいた
結果的にこうなる
code:yml
fluentd_work_dir: "/opt/fluentd"
fluentd_service_name: "fluentd"
fluentd_config_file_fullpath: "{{ fluentd_work_dir }}/fluent.conf"
ええ・・・
jinja2で展開される文字列が意図どおりにならない
数値型として展開されない
例えばgrafana lokiの設定ファイルのYAMLだとserver.http_listen_portの値は数値型でないといけない
が、Ansibleで変数の値を展開しようとすると勝手に文字列型として展開される
'1234'的な感じ
これを回避するには {{ port | int }}と書く必要がある
trueをtrueとして展開できない
supervisorの設定で変数に定義したtrueをそのまま展開しようとしてもできない
code:yml
redirect_stderr: true
code:app.conf
redirect_stderr = {{ redirect_stderr }}
これはTrueとして展開される
pythonのtrue/falseはTrue/Falseとして表現されていることに起因すると思う
こう書く必要がある
code:yml
redirect_stderr: "true"
変数展開記法内で{{が出現する時
こう書く
クオートでくくる
code:yml
tag: "{{ 'log.{{.Name}}' }}"
YAMLの仕様とPythonの仕様とjinja2の仕様が入り乱れてわけが解らなくなる
差分が見づらい
サービスごとの設定値をハッシュマップの配列にもたせてループしたくなる
code:vars.yml
services:
- name: app1
log_dir: /var/log/app1
- name: app2
log_dir: /var/log/app2
code:main.yml
- file:
path: "{{ item.log_dir }}"
state: directory
with_items: "{{ services }}"
コレをやるとハッシュマップ全体が差分にでてきて、ログが巨大で見づらくなる
でもループしたいよお
書き方がブレる
変数をset_factモジュールで定義するのか
varsで定義するのか
defaultsで定義するのか
YAML自体もいろんな書き方をサポートしている
alias / anchor
ハッシュマップ
code:yml
# これと
- { name: "hello", age: 2 }
# これは
- name: "hello"
age: 2
# 同じ
yesもtrueと同じ扱いになってtrueに変換されてしまう
taskからhandlersにnotifyしたときに、同名のhandlersが複数存在すると別ロールのhandlersが起動される場合がある
変数上書き問題と同じ
nginxロール配下なんだからhandlersの名前にnginx入れなくていいや~と思って記述していたら、いつの間にか別ロールのがキックされるようになってnginxの再起動が走らなくなっていた
別ロールのが参照されるとかそんなんある?
バージョン問題
結構バージョンによって大きく挙動が変わる
固定すれば良いんだろうけれど、breaking changesも頻繁に入ってる
Webの記事とかもいつのバージョンの情報なのかでだいぶ変わってくる
モジュール多すぎ
あらゆる処理をモジュールで表現しようという気概が伺える
数千モジュール存在する
正直使いこなせないというか、存在すらしらずにシェルで書いていた場合もある
冪等性担保してくれるのは嬉しいんだけど、Ansibleでプロビジョニングするための挙動理解のためにドキュメント読み倒す必要があって、つらい
ミドルウェアの理解と、Ansibleのモジュールの理解という2重苦
正直シェルでよくね?みたいなシーンも多い
遅い
1ロール実行するのも遅い
プロビジョニングするときに全部のロール実行するのだとめちゃくちゃ待たされる
結果的に各ロールにタグを割り振って、特定のタグだけ実行するという運用になりがち
これをやると前述のvarsやhandlersがいつの間にか上書きされていたことに気づけなくなって、かなり後になって差分ができていることに気づく
Ansible自体のコード規模巨大すぎ
リポジトリみたらコード量が尋常じゃない
モジュールの多さに起因してると思う
YAMLでプログラム書くのしんどすぎる
条件分岐とループが書きづらい
変数定義もめんどくさい
role/ロール名/tasks内で変数定義をするにはset_factモジュールを呼ぶ必要がある
set_factをするのが面倒ならrole/ロール名/varsディレクトリを切ってmain.ymlを定義する必要がある
どっちも面倒
Ansibleに疲れた
気にしないといけないことが多すぎる
仕事でもAnsible使うけれど、正直Ansibleは属人化しやすいと思う
コード化されることの意義は大きいが、属人化という新たな課題が生まれてしまう
ロールをまたがって設定が上書きされるのだけは耐えられない
エージェントレスで使えるプロビジョニングツールとしてitamaeが存在することを知っていたので、移行を検討しはじめた
itamaeに試してみた感想
標準モジュールはかなり少ない
プラグインもあんまり多くない
シェルで頑張らないといけないシーンは多い
読みやすい
書きやすい
個人的にはプロビジョニングをYAMLで頑張るよりもスクリプトで頑張った方が楽だと思う
ループしやすい
設定がロールをまたがらない
これだけでも嬉しい
別のロールの設定の影響を受けるのは正直バグでは、と思ってるがずっと前から残ってるので今後も変わらないだろうな
テンプレート記法のerbはあんまり他の設定ファイルのテンプレート構文とあんまりコンフリクトしないかも
これは使ってるミドルウェアにもよるとは思う
Goのテンプレート記法とはコンフリクトしない
見たまま変数が展開されてくれる
いちいち型変換しなくてよい
こういうのでいいんだよ
ansibleよりは早い
ansibleモジュール多すぎて速度遅くなってるのでは疑惑
正直ansibleコード規模が巨大すぎる
保守してる人たち辛くないのかな...
ちょっとだけコード読んだことあるけれど、正直あれを保守したくない
itamae generate cookbookでテンプレートを作ってくれる
結構これ嬉しい
が・・・やめた
itamaeを試している期間中にもAnsibleのメリットを考えていた
Webの情報量的にはAnsibleが圧倒的に多い
Ansibleの問題
ハンドラや変数がロールをまたがる
命名規則で予防するしかない
差分出力が見づらい
ハッシュマップで頑張るのをなるべく無くす
ansible.cfgの設定でスキップのログや、changedのログだけを出力するようにできた
書き方が属人化する
itamaeのitamae pluginと同様にAnsibleにもAnsibleGalaxyがある
AnsibleGalaxyの数はitamae pluginに比べるとかなり多い印象
自分で頑張ってインストールしないといけないものだけroleを自分で書いて、それ以外はなるべくAnsibleGalaxyを使うようにすれば書き方のブレは多少改善しそう
AnsibleGalaxyならテストされてるものも多いので、自分で実装するよりは信頼できそう
速度面
Ansibleを最大で25倍高速化するMitogenについて調べてみた - Qiita
これを導入したら本当に爆速になった
バージョン問題
dockerでPython環境を閉じるようにしたら解決した
Ansibleの実行環境をDockerで構築する
結果
Ansibleと上手に付き合っていきます