サーバー構築の自動化で利用される技術、自動化ツールとして「Kickstart」「Puppet」を紹介し、構築から運用まで、システムライフサイクル全体にわたる運用管理の自動化についても解説する連載。今回は、自動化ツールを使う上で大切な3つのことを基に、Puppetの変数とテンプレート、条件分岐、クラス、モジュールの使い方などを解説します。
前回の「Puppetのインストールと動作確認、トラブル対処法」では、無事PuppetのインストールをクリアしたR子さん、今回はついに「マニフェスト」(Puppetにおける自動化の定義書)を作成するようです。
K男 お、ちゃんとPuppetのmasterとagentのセットアップができたね! 感心感心。
R子 もう私、いっぱいいっぱいですぅ。許してくださいよぉ(悲)。
K男 うちの会社ではWebサーバーのチューニングノウハウがあるんだけど、手順書を見てやらなくても自動構築できるようにしたいんだよね。
R子 あ、私も手順書のコピペミスとかで怒られたことあるので、自動化でできると楽ですね〜。
K男 では早速、PuppetでWebサーバーを自動構築してみて。あ、うちの部署では基本CentOSだけど、他の部署ではUbuntu使ってるので、CentOSとUbuntuの両方に対応できるようにしておいてね。
R子 え? 私Ubuntuとか使ったことないんですけど……(泣)。
前回はPuppetのインストールと、簡単なマニフェストを使った動作確認まで終わりました。今回はHTTPサーバーを自動構築するマニフェストをR子さんと一緒に作ってみましょう。
一般的なアプリケーションを作るときは、最初にアプリケーションが備えるべき要件を考えるように、マニフェストの作成でも、最初に自動構築するシステムの要件を考えてから設計します。
今回R子さんが作るように指示があったHTTPサーバーのマニフェストですが、K男さんが熱く語る完成形は以下のようなものでした。
実際のプロジェクトでは、もっとたくさんの設定項目があるのでしょうけど、今回はR子さんに対するK男さんの優しさ(?)で、指示はこれだけでした。さてR子さんは、どのように作業を進めたらよいのでしょう。
ここで、Puppetのような自動化ツールを使う上で大切なことである「依存関係」「抽象化」「冪等性」について紹介します。これらを踏まえて実際にマニフェストを作っていきましょう。
マニフェストをどう作るか考える前に、一般的なサーバー構築作業を思い出してみましょう。よくあるのは「作業手順書があって、手順書に従って作業していく」ものだと思います。「手順書」ですから当然、順番がありますね。
では「順番があるのは、どうしてなのか」を考えてみます。HTTPサーバーをインストールする手順を簡単に思い返してみましょう。おおよそ以下のような流れではないでしょうか。
この作業の流れですが、例えば1と2を入れ替えたらどうなるでしょう。2の設定をするためにはhttpd.confが必要ですが、HTTPサーバーのパッケージが入っていなければファイル自体がありません。「ファイルがない」ということは「2の設定ができない」ということになります。
つまり、これは「2の作業は1の作業が完了していることに依存している」といえます。同様に3と4の作業は2の作業が完了していないとできません。つまり、これも「2の作業が完了していることに依存している」といえます。
個々の作業に「依存関係」があるということは、「Puppetが使う作業手順書」ともいえるマニフェストにも、この「依存関係」を記述する必要があります。マニフェストを記述するPuppet言語には、その方法がもちろんあります。詳しくは後述します。
ここでちょっと視点を変えてみましょう。サーバー構築作業の手順書ですが、多くの場合サーバーごとに用意されていると思います。とあるシステムで以下のような作業手順書が用意されていたときを想像してみましょう。
ポイントはサーバーの使っているOSです。1のHTTPサーバーと2のアプリケーションサーバーはCentOSで同じですが、3のデータベースサーバーがSolarisでOSが違うものになっています。さらに4に全サーバー共通の作業手順があり、ユーザー作成とhostsファイルの設定をするようです。
CentOSのユーザー作成コマンドは「useradd」でSolarisでも同じです。ところが、hostsファイルはCentOSでは「/etc/hosts」ですが、Solarisでは「/etc/inet/hosts」になっています。
マニフェストを作るときに「CentOSのhostsファイルにエントリを追加」と「Solarisのhostsファイルにエントリを追加」が、Puppet言語で別々の命令だったらどうでしょう。これでは全く同じ作業なのに、OSが違うとマニフェストを別々にしなければなりません。
Puppetでは、このようなOSや環境ごとの差異を吸収し、全てのOSや環境で同じ作業なら同じ命令を使えるように抽象化するレイヤーがあります。これをPuppetでは「Resource Abstraction Layer(RAL)」と呼んでいます。この抽象化レイヤーのおかげで、コマンドを直接実行するような命令を例外とすれば、多くの作業で使う命令でOSや環境に依存性をなくしています。
先ほどK男さんから指示された内容を思い出してみましょう。その中に「設定変更はマニフェストの変更で対応とすること」という項目がありました。
マニフェストを変更した後はマニフェスト実行することになるのですが、変更してない箇所はどうなるのでしょうか。変更したところだけ抜き出して実行するのではありませんし(それでは手間や管理が大変な上に「修正だけで」という指示に沿っていませんね)、変更していない箇所まで再実行してしまいます。
仮にシェルスクリプトなどを使って同じような自動化をしていたとします。そうするとパッケージのインストールや設定などのコマンドも再実行することになってしまい、変更してはいけない部分を壊してしまいかねません。
Puppetは、そうした事態を避けるため、「現在の状態を確認し、必要があるか判断した上で実行する」機構を備えています。すでに“あるべき状態”になっているときは命令をスキップし、何もしません。
例えば、命令が「ユーザーabcを○○という内容で作成しろ」だった場合、ユーザーabcがすでに存在し、なおかつ○○という内容であるならばスキップするが、ユーザーabcが存在しない、もしくは存在はするが××という内容だったという場合は、ユーザー作成や変更の処理を実行するという具合です。この概念を「冪等性(べきとうせい)」と言います。
Copyright © ITmedia, Inc. All Rights Reserved.