Puppetを手元の端末からSSHごしにApplyするPeroを開発した

はじめに

GMOペパボではPuppetをサーバのミドルウェアインストールやセットアップに利用しているサービスが多くあり、ユースケースとしてはサーバ・クライアント構成でサーバにPuppetの資産をCapistranoなどでデプロイして、クライアント側で puppet apply コマンドを利用して開発しています。

一方で、僕が開発しているサーバは基本的にはChefないし、Itamae(mitamae)を利用して開発しており、特にいま一緒に仕事させていただいる @sawanoboly さんが開発しているKnife Zeroを1日に549858回くらい実行しています。

そんな僕がPuppetを利用する場合に非常に手間に感じるのが、開発サーバなどでレシピを開発しているときに、変更のたびにマニフェストをPuppetサーバにデプロイしないといけなくて、それが非常に手間に感じており、僕はあまりやらないのですが本番サーバに直接手で変更を加えて、Puppetに書き戻すというようなオペレーションも散見されていました。これはスノーフレークサーバを作ってしまう習慣となり得るので、システムを開発運用する上で望ましいこととは思えませんでした。

DockerとSSHポートフォワードを利用して、Puppet Apply

これらの課題を解決するために、開発においていちいち資産をデプロイしなくてもPuppetをApply出来る、Peroというgemを開発しました。この名前はあんちぽさんがのりでPeroとどっかに書いたのをそのまま採用したのですが、ソフトウェア自体が前述のKnife Zeroに影響をうけているので、Puppet Zeroの略なのかもしれません。

作りとしては非常にシンプルです。

  1. laptop上でDockerを利用して、任意のバージョンのPuppetサーバを起動し、マニフェストをボリュームマウント
  2. laptopからTargetサーバにSSH接続し、Targetサーバの localhost:8140 を laptopのPuppet Serverプロセスにポート転送。
  3. PuppetはSSL証明書を利用した通信を行うので、Targetサーバが既存のPuppetサーバと接続性を失うのを避けるために、Targetサーバでマウントネームスペースを分離し、PuppetのSSLディレクトリを一時ディレクトリでバインドマウントします。 こうすることで、このSSHセッションで起動されたbashだけが、一時的なSSLディレクトリを参照するので、もともとTargetサーバが利用してたPuppetサーバとの接続性には影響を及ぼさずに利用することが出来ます。
  4. Targetサーバで localhost:8140 をPuppetサーバとしてApply.

実行例

まずpuppetをクライアントにインストールするとともに、Peroが利用する構成情報を作成します。

$ pero install --agent-version 6.17.0 example.com

あとはこれらの情報を基に、マニフェストをApplyすることが出来ます。

$ pero apply --noop example.com
$ pero apply example.com

便利な使い方

手元からデプロイ無しでマニフェストをApply出来るだけでもハチャメチャ便利なのですが、いくつか便利な使い方があります。

並列で手元からマニフェストをApply

puppet apply -C5 example.* のように登録されたノードを正規表現で指定できるようにしてあり、合致したノードに並列してマニフェストをApplyすることが出来ます。

またinstallコマンドも複数の引数を受け付けることが出来るので、下記のように一気にインストールすることが出来ます。

$ pero install --agent-version 6.17.0 10.1.1.1 20.1.1.1

バージョンアップの支援

これが最大のメリットだと思うのですが、サーバ・クライアント構成をとっている場合に、双方を一気にあげてしまうか、何かしらの環境を作り込まないとバージョンアップしづらいのがPuppetのサーバ・クライアント構成運用の大変なところだと思います。しかし、PeroはPuppetサーバをDockerで起動するので、例えばPuppet5ブランチと、Puppet6ブランチを共存して運用することが用意になります。これまですべてのロールを一気にバージョンアップするのが辛くて、バージョンアップが進んでいないようなリポジトリやサービスも、Peroを利用すると既存の環境に影響を与えることなく、安心してバージョンアップすることが出来ます。

最後に

もともとは最近色々な商材のPuppetを触る機会があって、ぼくがふわっと立てたIssueがきっかけだった。

ちょうど一ヶ月くらい前だったんだけど、そこからなんとなく頭の片隅にありながらも証明書の扱いどうすっかなぁと考えていたりして、最初はsshfsでmasterの証明書ディレクトリをマウントしてしまうかとかも考えたのだけど、何かの拍子にunshareが振ってきて、今の実装を思いついて、合計3〜4日くらいで出来たと思う。

僕は仕事でたまたまコンテナの基礎技術を @udzura の影響で扱うことがあったから着想出来たけど、まあこれも普段からLinuxプログラミングインターフェースを読んだり、そういうコミュニティで活躍してたから思いつけたなぁと思っていて、こういう発想を得て、課題を解決出来うるためには日々精進だなぁと改めて思った。