お前のパソコンを構成管理してやろうか

この記事は GMOペパボ Advent Calendar 2018 の14日目の記事です。

qiita.com

 さっむいですね。。
前回の記事が「あっついですね」で始まっていたのにもう寒くなってしまいました。寒暖差が体に堪えても、普通に会社に出て普通に仕事しています。

 最近ですね、お仕事してる時にこう言われることが多くなってきたんです。

  • 開発環境が壊れて開発すべきページが見れなくて困っている
  • テンプレートのデザインしたので、コミットしておいてもらえませんか

 あれ?何かが違う気がする。。。

気がついたら、そのたびに小一時間、下手したら丸一日かかりっきりでパソコンを直してました。

  • Ruby のバージョンが違う
  • コンテナが buzy で止まってる
  • pid ファイルがあるのにサーバが止まってる
  • Python3 にしないと動かないはずなのに動かない
  • Composer がエラー吐く
  • PuppetLabs の VM イメージが古すぎて GnuPG の署名が通らなくなってた
  • rbenv の git リポジトリが変わってるみたいで Puppet が止まる
  • 会社でホストしてた yum リポジトリがなくなってた

 などなど、そもそも構築方法を見直さなければならないものから、手順自体を見直さなければならないものまで、多種多様の「動かなくなった」案件が舞い降りました。
 僕はわりと壊れたものを直すのが好きなので、時間がかかっても最終的に直してしまっていたのですが、ちょっと時間取られすぎかなって思ったり、いやいや、そもそもちゃんとした開発環境もないのにちゃんと開発できてるんか?生産性とか開発のテンポってみんなどう感じてる?みたいな思いが頭の中でグールグルしていました。
 そんな家でビールを飲んでテレビを見てうとうとしていた時に、なぜかデーモン閣下が僕にこうささやいていました。

「お前のパソコンを構成管理してやろうか!」

 というのは嘘なんですが、これは結構大事なんじゃあなかろうかと思いました。
 確かに僕たちが開発してるものは、維持しなければならない技術スタックが多くなってきてまして、それらを維持するための解決案もあってケアされていると思っていましたが、それをブラッシュアップしきれていない状況でした。
このことについては、我らが偉大なるリーダーも課題感を持っており、会社ブログで書いてました。

tech.pepabo.com

 ただ、僕としては DB を除く全てのロールをコンテナ化したいと思っていて、そのコンテナから社内 OpenStack のイメージを作成してサンドボックス環境化して行きたかったんですね。
で、環境作るときはとりあえず docker-compose up しといて!って言ったら終わる感じにしておきたかったんですが、今の puppet どうする? capistrano どうする?みたいなよくある構成管理はどのツールに請け負わす?みたいな解決案を持っていませんでした。
 docker-compose.ymldockerfile に全部書けるぐらいなら管理も楽だしそれがいいんですが、ちょっとそんなに単純でもないしな。かと言って本番の Terraform からキックされるクックブックとは違う開発環境のクックブックをブラッシュアップしていくことにどれほどの意味があるのか。 mitamae か確かに便利そうだなぁ、割と Ruby っぽいレシピ書くっぽいけどこれ自体を維持していけるかな。あでもなんか mruby 使ってるだけあって速いらしいけど、今のやつは Fabric と混ざってる??
 うーんうーん、と悩んでたんですが、結局、まずまずは目の前の環境が壊れている子を助けることが主眼なんだから、今手元でずっと温め続けてきた ansible-playbook をもうちょっとブラッシュアップして使ってもらったほうが早いのでは?と思い直し、とりあえずみんなの環境ができて、お隣に行ってガチャガチャ直す時間が減ってからベストプラクティスを定義しても遅くはないのではなかろうか?どうせコンテナ化したらまたバックグラウンドが変わるだろうし。と思って社内で公開しました。

 構成はベストプラクティスに寄せたつもりです。

$ tree -L 2
.
├── ansible.cfg
├── dev.yml
├── hosts
├── log
│   ├── debug.log
│   roles
│   ├── composer
│   ├── docker
│   ├── homebrew
│   ├── hosts
│   ├── migration
│   ├── node
│   ├── pip
│   ├── ruby
│   ├── sidekiq
│   ├── styleguide
│   ├── vagrant
│   ├── vagrant.puppet
│   └── workspace
└── workspace
    ├── repository A
    ├── repository B
    └── repository C

 抽象化した作業をロールで分解して、使いたいタスクを dev.yml のコメントを外して使ってもらって好きな playbook を使ってもらえるように意識したつもりで、例えば好きなロールのサーバの起動だけしたいとか、 homebrew でインストールしたアプリのアップデートだけしたいとか、ユースケースに併せて使えるように意識しました。今後、使ってもらっていって、固定化されたユースケースが浮き上がってきたらそれ用の playbook を作ったらいいんだし、再利用性を考慮したつもりなんですけど、こういう設計って答えがなくて無限に悩めますね。
(ちなみに、これが全てではなくて、ロール固有の処理とかビジネスロジックに依存するタスクは割愛しております。

 Ansible 自体は前職のゲーム作っていた時に本番のサーバプロビジョニングで使っていたので、記法や勘所はすぐに思い出せたのですが、個人のパソコンをプロビジョニングする時にとっても悩んだ点を紹介します。
サーバのプロビジョニングはベースとなる構成が同じなので、各個人の macOS でベースが違うプロビジョニングはかなりハードルが高いと思いました。例えば

  • 使っているシェルが zsh や fish 、 bash など異なる
  • ndenv 、 nodebrew など、言語のバージョン管理ツールが各個人で異なる
  • sudo する時のパスワード入力
  • python の実行パスが各個人で異なる
  • インストールパスに各個人の趣向が異なる
  • 既にインストール済みのモジュールのエラー回避
  • ロールの設計

 また、普通にハマったことはこんなもの

  • 変数にハイフン( - )を使ったら見つからなくなった
TASK [test : debug] ***************************************************************
Tuesday 11 December 2018  17:00:54 +0900 (0:00:01.294)       0:00:01.437 ******
ok: [localhost] => {
    "ps-test": "VARIABLE IS NOT DEFINED!"
}

 こんな感じで、 VARIABLE IS NOT DEFINED! になってあれ?って思ったんですけど、ハイフン使わなかったら出ました
( yml かなこれは

[local]
localhost ansible_python_interpreter=/usr/local/bin/python3

hosts に ansible_python_interpreter を指定して Python3 のインタプリタをフルパス指定したら動きました

 個人 mac なんで、 NOPASSWD とか指定してませんから、 sudo が必要なタスクで --ask-become-pass を指定しておかないと権限がなくてエラーになります。
パスワードの入力自体はいいんですけど、NOPASSWD を記述してる VM 内の操作にそぐわなかったので、まぁ、playbook を分けるか mac に NOPASSWD を記述します。
 でも、セキュリティ上、良くないので、 vault で解決できたらそれがいいんですが、ちょっとそこまで行きませんでした。。

  • rbenv はバージョンが切り替わるけど、 ndenv は切り替わらなかった

 これは、今でもよくわかっていないのですが、 shell モジュールの実行時、 .node_version での node バージョンの切り替えがうまくいきませんでした。
rbenv の場合、 .ruby_version に記載のバージョンに切り替わるので、 chdir を指定したらバージョンが切り替わったのですが、なぜか ndenv の場合、 .node_version のバージョンに切り替わりませんでした。
 lookup を使って .node_version を参照して node global xxx で切り替わったのでそうしましたが、もうちょっと上手いことやれる気がしてます。、

感想など

 やっぱり自動化は面白い!って思いました。
Ansible は、エラーが実行したコマンドのエラーそのまま出ますので、えー、これ使ってるんや!とか、なんでこのファイルのここをコメントアウトしてるんだ・・・とか発見が多かったです。
 多分、普通にアプリ実行環境(本番とかステージング環境)の構築に Ansible を使っているだけではぶつからないエラーに引っかかるので、ちょっと Ansible 力が上がった気がします。

 ということで、明日の GMOペパボ Advent Calendar 2018@litencatt さんです。