Ansible って結構ツラいんじゃないかと思った話

blog システム開発

Webアプリケーション EC2 にデプロイする。
本番環境・ステージング環境・開発環境の3つを作る必要があるので、Ansible で構成ファイル作っとけば、1つの構成ファイルを全部に適用して全ての AWSの環境が整うのでは?
と思い、3年ぶりぐらいに Ansible を触ってみた。

以前、CentOS に適用する playbook を中途半端に書いていたので、それをちょっと弄ったらどうにかなりそう。
PHP7->PHP8、Apache->Nginx といった変更点はあるが、まぁそんなにややこしい事は起こらないだろう思って進めてみるも、想像していたよりも全然上手く行かず、結局 Ansible を使わない方向に落ち着きました。

というか、前回作成した時も、ちゃんと作ると凄い大変だったので、何だか中途半端な状態になって一部は手作業が入ることになっていたのをすっかり忘れていました。

以下、何で Ansible 使うのやめといたかの記録。

構成

ローカルでは Docker を使用。
ベースイメージは php:8.0-fpm, nginx, node:16-slim など。

開発時はこれらは個別のコンテナとして分かれているけど、AWS環境では EC2 にデプロイし、EC2 の中に PHP、Nginx、Node.js といったアプリケーションの動作に必要なツールやライブラリを入れていく。

EC2 は2台立ててロードバランサで負荷を分散。
ストレージは RDS と S3。メモリキャッシュには ElastiCache。

別に、これといった特徴のない、ごく普通の構成。

リポジトリを指定するのが面倒

環境構築時、パッケージマネージャをこねくり回さないといけない状況になると結構面倒くさい。

remi やら epel やら pecl やら色々種類があってカオス化してるし、やってるうちに混乱してきて何が何だか分からなくなってくる事は1度や2度じゃないと思う。

Ansible を使う事で、その辺を抽象化して yaml ファイルに最低限のことを書くだけでいい感じに環境が準備できるのかと思いきや、リポジトリの参照先を示さないと yaml でインストール命令書いていてもそこで失敗してしまう。

結局、どこのリポジトリから拾ってくるか、という事はユーザ自身が把握し、わざわざ yaml に記述しておく必要があるので、それだと苦労が全然軽減されないじゃーん。と感じてしまう。

物によっては wget や curl で拾ってくる必要があったりして、「もう、構成管理ツール使ってインストールする意味なくね?」と思う場面もしばしば。

マニュアルが使いづらい

公式マニュアル、こんな感じ。
https://docs.ansible.com/ansible/2.9/index.html

何だか充実していそうに見えるが、実際にプレイブックを書く場面では、意外と使いづらかったりする。

例えば、以下の命令で Apache がインストールできる。

  yum:
    name: apache

「なるほど。name の部分にインストールするアプリケーション名を入れればいいのな。じゃ、Node.js を入れるときはどう書くの? “node”? それとも “nodejs”?」

といった状況になった時、「name に何が指定できるのか」という事が非常に分かりづらい。
いくら探しても一覧のようなものが見つからないし、yum list みたいにリストアップするコマンドも無いみたい。

検索ウィンドウがあるが、何を優先してそんな情報を引っ張ってきているのか、かなり謎なものが多い。

例えば、”nginx” とかは一意性が高そうなので必要な情報が拾いやすいかと思いきや、「community.general.nginx_status_info」みたいな情報ばかりがバンバン出てきて、肝心の「nginx をインストールするにはどうするか、nginx のコンフィグはどう書くか」という探し出す事が極めて難しい。というか僕には見つけきれませんでした。

公式ドキュメントから情報が拾えないので、仕方なく「試しに “node” でやってみるか。あ、ダメなのね。じゃ次は “nodejs” でやってみるか。」といった変なトライアンドエラーに頼るか、ググってそれっぽい参考情報を探すことになる。

そしてググって情報を探すのも、色々とカオスで必要な情報をピックアップしづらい。(詳細は後述)

「name に何が指定できるのか分からない」という点については、自分が Ansible に使いこなせていないのが理由の1つかもしれないが、このくらいの情報は、ドキュメントを少し読んだだけですぐに分かる構造になっていて欲しいと思ってる。

Ansible の不採用を決めるまで3日ぐらいかけて検証したけど、未だに見つけきれてないし。

参考にする playbook が情報過多

そんな感じで公式ドキュメントが頼りないので、公式以外の情報を参照するべく Google 検索に頼るも、出てくる情報はかなりヘビーなものも多い。

今回適用したいのは Amazon Linux なので、それ以外のディストリの情報は特にいらないんだけど、出てくる参考プレイブックは「Ubuntu ならこの動き、CentOS ならこの動き」と、結構な数のディストリの分岐があったりして、必要な情報を拾い上げるのが結構面倒だったりする。

そして、パッケージマネージャーに何を使うか(≒ディストリを何を使うか)という事を意識して playbook を書く必要があり、探し当てた情報が apt だったりすると、また探し直しになってしまう。

検索時に “-apt” オプションをつけて、Debian 系のディストリを対象とした情報を検索対象から外す事ができはするんだけど、その場合、全部のディストリに対応して記述した記事がヒットしなくなってしまい、検索ワードの絞り込みが非常に悩ましい。

それに加え、現時点(2022年4月)において、Linux に実装されている Python のメジャーバージョンが上がり始めてる事が関係しているのか何なのか(Ansible は Python で実装されている)、Ansible の方もドラスティックに変わっているようで、せっかく見つけた情報も過去のものとなってしまっていて、役に立たなくなっている事も多い。

公式マニュアルが頼りないので他のサイトを色々と参考にする必要があるのに、ネット上も新旧の情報が入り乱れて腐海化してしまっているというのが Ansible を使う事の難易度を格段に上げている。

ディストリごとの記述の差異もあり、「この記述は Debian系の時のみ有効」「この記述は RedHat系のみ有効」みたいな表現があったり、探し当てた情報を自分が必要な情報用にコンバートするための知識が必要となる場面も出てきたりと、記述には非常に苦労をさせられる。

構文が変わってる

3年前くらいに書いたプレイブックを元に書き直していたんだけど、いくつかのシンタックスが構文が古いと warning が出た。
2.9 あたりから、ガラッと構文が変わったみたい。
別に構文が変わるのは悪い事じゃ無いとは思うけど、変更内容について、全くポリシーが感じられない。

例えば、PHP で、「in_array と array_map は、第一引数を配列にします」という変更があったとする。(あくまで例です)
なかなかヘヴィな変更だが、理由は分からなくは無い。PHPの配列操作系のメソッドは、第一引数に操作対象の配列を要求していたり、第二引数に要求していたりと、かなりバラバラで統一感がまるで無い。
その状況を良しとせず、「第一引数に操作対象の配列を持ってくるように統一するんかな。移行期間中は大変だけど、遠い未来のことを考えたら、そっちの方がいい事もあるよな」と、変更理由を使い手側が理解する事はできる。

が、少なくとも自分が触った範囲では、「単にシンタックスの文字が変わっただけ」といった印象しか感じないものばかりで、「何でこう変える必要があったの?」とまるで背景が想像できなかった。

特に「become: yes」とか意味が分からん。「sudo: yes」のままでいいじゃん。

冪等性は結局書き手が担保する必要がある?

Ansible のメリットに、「冪等性(何度実行しても、同じ結果になる)」というのがあるが、どうも「Ansible を使えば、冪等性が担保できる」ということではないみたいだ。

書き方次第では、1回目の実行と2回目の実行で、結果が変わるプレイブックなどいくらでも作れてしまうし、自然にそうなってしまう事は十分にある気がする。

多分、
「何度実行しても同じ結果になる」
ではなく、
「何度実行しても同じ結果になるような記述を表現できる」
という認識が正しい気がする。

どういうことかと言うと、冪等性を担保するには書き手の技量が求められ、それを担保する事を考えると記述がえらい難しくなり、Ansible のみならず、インストールするライブラリやコンフィグについてもちゃんと知っておかなければいけないのでは? という感覚があった。

というか、EC2 に適用する事を前提とするなら、そんな事に気を回すよりもインスタンスを一旦破棄して、もっかい最初から流した方がよいのでは? と思っている。

何十台、何百台といったマシンが動いている状況だと、ローリングデプロイしていく感じになるだろうから、1つや2つ壊して作り直しても別に影響なさそうだし。

何だかんだ言って、直接触れないと不安

例えば、nginx のサービスをスタートする時、こんな感じで記述できる。

  service:
    name: nginx
    enabled: yes

全てを Ansible で表現できるなら、nginx のコマンドを一切知らなくても、yaml だけで表現する事も可能だと思う。

が、全てをプレイブックで表現すると異常に難易度が上がるうえ、nginx で出来る事が全てプレイブックで表現できるとは限らないので、結局 Ansible の命令と通常のコマンドが混在する形になってしまう。(そして、「何が Ansible で表現できて、何が Ansible で表現できないか」という事を知っておく必要があり、それを調べるのに結構時間がかかる)

そんな中途半端な記述になってしまうぐらいなら、もう一切 Ansible の命令を使わず、全部コマンドで書けばよくね? と思って進めていると、ある事に気づく。

シェルスクリプトで書いた方が早い…

結論

Ansible 結構しんどいので、シェルスクリプトを使った方がいいんじゃないかな。(よっぽど巨大な構成でなければ)

結構クセが強くて学習コストが高く、インフラ専属でないエンジニアが片手間に触るのは、なかなか厳しいんじゃないかと思います。※個人の感想です

「そこまで Ansible の機能を使い倒さず、必要最小限の内容をシンプルに書く」という使い方もあるかもしれませんが、それだと「この程度なら、シェルスクリプトでよくね?」という内容になりがちなので、結局 Ansible の出番が無い気がします。

というか、元々、冒頭で書いたような小さい構成のアプリに適用するような代物ではないのかもしれません。
そう言う意味では、Ansible がどうこうと言うより、自分の技術選定がミスってたと言う事になります。

ただ、安易に導入すると後で余計な苦労を背負い込む事は分かったので、「Ansible 使うといいよ!」というアドバイスを無条件に受け入れてはいけない、という知識くらいは得られました。

今後、自分が Ansible とどう向き合っていくかは決めていないが、インフラしか触らない人の「Ansible いいよ!」は、ちょっと疑いの目を向けて聞く事にしようと思います。(インフラの構築のみを請け負う会社の人なら、警戒心さらに高めに設定。この手の仕事って、一度作って納品してしまえば、納品先が運用苦しい内容になってても、基本知ったこっちゃないだろうし。インフラ構築を外部に委託した時、運用フェーズ時の苦労を一切考えてないような完成品が納品された事とかあるんで。)

ただ、「バックエンドが専門だけど、インフラも触る」という人の「Ansible いいよ!」という意見なら、真剣に耳を傾けたいと思います。

どんな場面で Ansible を使うか(ブログ主の場合)

何百台のサーバを管理するようなガチのインフラの仕事を請けているわけじゃないし、当分その予定も特に無いので、使うとしたら別の用途となりそう。

例えば、オープンソースのアプリケーションを公開して、ディストリごとの環境構築ファイルを playbook で用意する、という用途だろうか。

でも、よく考えたらそういう事したいならコンテナを使う事を前提とした作りにするし、デプロイもコンテナを前提とするな。

使うとしたら、ガチのインフラエンジニアに転向する時だろうか。(今のところ、特に予定無いけど。)
どう考えても、バックエンドとプロマネやりながら出来る仕事のスコープに無さそう。

コメント

タイトルとURLをコピーしました