構成管理101:シェフのレシピを書く
簡単に言うと、サーバー構成管理(一般にITオートメーションとも呼ばれます)は、インフラストラクチャ管理をコードベースに変換するソリューションであり、バージョン管理して簡単に再利用できる一連のプロビジョニングスクリプトでサーバーを展開するために必要なすべてのプロセスを記述します。 時間の経過とともに、サーバーインフラストラクチャの整合性を大幅に向上させることができます。
以前のガイドでは、サーバーインフラストラクチャに構成管理戦略を実装する主な利点、構成管理ツールの仕組み、およびこれらのツールに通常共通するものについて説明しました。
シリーズのこのパートでは、Rubyプログラミング言語を活用してインフラストラクチャの管理とプロビジョニングを自動化する強力な構成管理ツールであるChefを使用してサーバープロビジョニングを自動化するプロセスについて説明します。 Apacheを使用してUbuntu18.04Webサーバーのデプロイメントを完全に自動化するための簡略化された例を作成するために必要な言語の用語、構文、および機能に焦点を当てます。
これは、目標を達成するために自動化する必要がある手順のリストです。
apt
キャッシュを更新します- Apacheをインストールします
- カスタムドキュメントルートディレクトリを作成します
index.html
ファイルをカスタムドキュメントルートに配置します- テンプレートを適用して、カスタム仮想ホストを設定します
- Apacheを再起動します
まず、Chefが使用する用語を見てから、レシピの作成に使用できる主な言語機能の概要を説明します。 このガイドの最後に、完全な例を共有して、自分で試してみることができるようにします。
注:このガイドは、Chef言語と、サーバープロビジョニングを自動化するためのレシピの作成方法を紹介することを目的としています。 このツールのインストールと開始に必要な手順など、Chefの概要については、Chefの公式ドキュメントを参照してください。
##はじめにChefのより実践的なビューに移る前に、このツールによって導入された重要な用語と概念を理解することが重要です。 ###シェフ用語
- Chef Server :情報を保存し、ノードのプロビジョニングを管理する中央サーバー
- Chefノード:Chefサーバーによって管理される個々のサーバー
- Chef Workstation :プロビジョニングが作成されてChefServerにアップロードされるコントローラーマシン
- レシピ:実行する一連の命令(リソース)を含むファイル。 レシピはクックブック内に含まれている必要があります
- Resource :システムの要素と実行するアクションを宣言するコードの一部。 たとえば、パッケージをインストールするには、アクションinstallを使用してpackageリソースを宣言します。
- クックブック:プロビジョニングの一部の共有と再利用を容易にするために事前定義された方法で編成されたレシピとその他の関連ファイルのコレクション
- 属性:特定のノードに関する詳細。 属性は自動にすることができ(次の定義を参照)、レシピ内で定義することもできます
- 自動属性:ネットワークインターフェイスやオペレーティングシステムなどのシステムに関する情報を含むグローバル変数(他のツールでは facts と呼ばれます)。 これらの自動属性は、Ohaiと呼ばれるツールによって収集されます。
- サービス:サービスの再開や停止など、サービスステータスの変更をトリガーするために使用されます
###レシピ形式ChefレシピはRubyを使用して作成されています。 レシピは基本的に、ノードによって実行される命令のステップバイステップのセットを作成するリソース定義のコレクションです。 これらのリソース定義をRubyコードと組み合わせて、柔軟性とモジュール性を高めることができます。
以下に、apt-get update
を実行し、後でvim
をインストールするレシピの簡単な例を示します。
execute "apt-get update" do
command "apt-get update"
end
apt_package "vim" do
action :install
end
##レシピの記述###変数の操作ローカル変数は、レシピ内で通常のRubyローカル変数として定義できます。 以下の例は、後でリソース定義内で使用されるローカル変数を作成する方法を示しています。
package = "vim"
apt_package package do
action :install
end
ただし、これらの変数のスコープは制限されており、定義されたファイル内でのみ有効です。 変数を作成してグローバルに利用できるようにし、クックブックやレシピから使用できるようにする場合は、カスタム属性を定義する必要があります。
####属性の使用属性は、ノードに関する詳細を表します。 Chefには自動属性があります。これは、Ohaiと呼ばれるツールによって収集され、システムに関する情報(プラットフォーム、ホスト名、デフォルトのIPアドレスなど)を含む属性ですが、独自のカスタム属性を定義することもできます。
属性には、作成する属性のタイプによって定義されるさまざまな優先順位レベルがあります。 default
属性は、必要に応じて他の属性タイプで上書きできるため、最も一般的な選択肢です。
次の例は、ローカル変数の代わりにdefault
ノード属性を使用した場合の前の例の外観を示しています。
node.default['main']['package'] = "vim"
apt_package node['main']['package'] do
action :install
end
この例で観察する2つの詳細があります。
ノード変数を定義するときに推奨される方法は、使用中の現在のクックブックをキーとして使用して、ノード変数をハッシュとして編成することです。 この場合、同じ名前のクックブックがあるため、main
を使用しました。 これにより、類似した名前の属性を持つ可能性のある複数のクックブックを操作している場合の混乱を回避できます。 属性を定義するときにnode.default
を使用しましたが、後でその値にアクセスするときに、node
を直接使用したことに注意してください。 node.default
の使用法は、タイプdefaultの属性を作成することを定義します。 この属性は、normalまたはoverride属性など、優先順位の高い別のタイプによって値が上書きされる可能性があります。
属性の優先順位は、最初は少し混乱する可能性がありますが、ある程度練習すると慣れます。 動作を説明するために、次の例を検討してください。
node.normal['main']['package'] = "vim"
node.override['main']['package'] = "git"
node.default['main']['package'] = "curl"
apt_package node['main']['package'] do
action :install
end
この場合、どのパッケージがインストールされるか知っていますか? git
を推測した場合、正しく推測しました。 属性が定義された順序に関係なく、タイプoverride
の優先順位が高いほど、node['main']['package'] be evaluated to
git`になります。 ###ループの使用ループは通常、異なる入力値を使用してタスクを繰り返すために使用されます。 たとえば、10個の異なるパッケージをインストールするために10個のタスクを作成する代わりに、単一のタスクを作成し、ループを使用して、インストールするすべての異なるパッケージでタスクを繰り返すことができます。
Chefは、レシピ内にループを作成するためのすべてのRubyループ構造をサポートしています。 簡単な使用法では、each
が一般的な選択です。
['vim', 'git', 'curl'].each do |package|
apt_package package do
action :install
end
end
インライン配列を使用する代わりに、ループ内で使用するパラメーターを定義するための変数または属性を作成することもできます。 これにより、物事がより整理され、読みやすくなります。 以下に、インストールする必要のあるパッケージを定義するためにローカル変数を使用している同じ例を示します。
packages = ['vim', 'git', 'curl']
packages.each do |package|
apt_package package do
action :install
end
end
###条件付きの使用条件付きを使用すると、たとえば、変数やコマンドからの出力に基づいて、コードのブロックを実行するかどうかを動的に決定できます。
Chefは、レシピ内に条件ステートメントを作成するためのすべてのRuby条件をサポートしています。 さらに、すべてのリソースタイプは、タスクを実行するかどうかを決定する前に式を評価する2つの特別なプロパティif_only
とnot_if
をサポートします。
以下の例では、拡張機能php-pear
をインストールする前に、php
の存在を確認します。 コマンドwhich
を使用して、このシステムに現在php
実行可能ファイルがインストールされているかどうかを確認します。 コマンドwhich php
がfalseを返す場合、このタスクは実行されません。
apt_package "php-pear" do
action :install
only_if "which php"
end
逆に、条件がtrueと評価されたときにを除いて常にコマンドを実行する場合は、代わりにnot_if
を使用します。 この例では、システムがCentOSでない限り、php5
をインストールします。
apt_package "php5" do
action :install
not_if { node['platform'] == 'centos' }
end
より複雑な評価を実行する場合、特定の条件下で複数のタスクを実行する場合は、標準のRuby条件のいずれかを使用できます。 次の例では、システムがDebianまたはUbuntuの場合にのみapt-get update
を実行します。
if node['platform'] == 'debian' || node['platform'] == 'ubuntu'
execute "apt-get update" do
command "apt-get update"
end
end
属性node['platform']
は、Chefからの自動属性です。 最後の例は、より複雑な条件付き構造を示すことだけでしたが、自動属性を使用した単純なテストに置き換えることができます。node['platform_family']
、DebianシステムとUbuntuシステムの両方で「debian」を返します。<###テンプレートの操作テンプレートは通常、構成ファイルを設定するために使用され、これらのファイルをより用途が広く再利用可能にすることを目的とした変数やその他の機能を使用できます。
Chefは、Puppetで使用されているのと同じ形式であるEmbedded Ruby(ERB)テンプレートを使用します。 これらは、条件、ループ、およびその他のRuby機能をサポートします。
以下は、変数を使用してこのホストのドキュメントルートを定義するApache仮想ホストを設定するためのERBテンプレートの例です。
<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot <%= @doc_root %>
<Directory <%= @doc_root %>>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
テンプレートを適用するには、template
リソースを作成する必要があります。 これは、このテンプレートを適用してデフォルトのApache仮想ホストを置き換える方法です。
template "/etc/apache2/sites-available/000-default.conf" do
source "vhost.erb"
variables({ :doc_root => node['main']['doc_root'] })
action :create
end
Chefは、編成とモジュール性を強化するために、ローカルファイルを処理するときにいくつかの仮定を行います。 この場合、Chefは、このレシピが配置されているのと同じクックブックにあるはずのtemplatesフォルダー内のvhost.erb
テンプレートファイルを探します。
これまで見てきた他の構成管理ツールとは異なり、Chefは変数に対してより厳密なスコープを持っています。 つまり、template
リソースを定義するときに、テンプレート内で使用する予定の変数を明示的に指定する必要があります。 この例では、variables
メソッドを使用して、仮想ホストテンプレートで必要なdoc_root
属性を渡しました。 ###サービスの定義とトリガーサービスリソースは、サービスが初期化されて有効になっていることを確認するために使用されます。 また、サービスの再起動をトリガーするためにも使用されます。
Chefでは、通知を試みる前にサービスリソースを宣言する必要があります。そうしないと、エラーが発生します。
Apache仮想ホストをセットアップした以前のテンプレートの使用例を考慮に入れましょう。 仮想ホストの変更後にApacheが確実に再起動されるようにする場合は、最初にApacheサービスのserviceリソースを作成する必要があります。 このようなリソースがChefで定義される方法は次のとおりです。
service "apache2" do
action [ :enable, :start ]
end
ここで、 template リソースを定義するときに、再起動をトリガーするためにnotify
オプションを含める必要があります。
template "/etc/apache2/sites-available/000-default.conf" do
source "vhost.erb"
variables({ :doc_root => node['main']['doc_root'] })
action :create
notifies :restart, resources(:service => "apache2")
end
##レシピの例次に、このガイドの概要で説明されているように、Ubuntu14.04システム内でのApacheWebサーバーのインストールを自動化するレシピを見てみましょう。
Apacheを設定するためのテンプレートファイルとWebサーバーによって提供されるHTMLファイルを含む完全な例は、Githubのにあります。 このフォルダーには、 Vagrant によって管理される仮想マシンを使用して、簡単なセットアップでレシピをテストできるVagrantfileも含まれています。
以下に完全なレシピを見つけることができます:
- node.default['main']['doc_root'] = "/vagrant/web"
-
- execute "apt-get update" do
- command "apt-get update"
- end
-
- apt_package "apache2" do
- action :install
- end
-
- service "apache2" do
- action [ :enable, :start ]
- end
-
- directory node['main']['doc_root'] do
- owner 'www-data'
- group 'www-data'
- mode '0644'
- action :create
- end
-
- cookbook_file "#{node['main']['doc_root']}/index.html" do
- source 'index.html'
- owner 'www-data'
- group 'www-data'
- action :create
- end
-
- template "/etc/apache2/sites-available/000-default.conf" do
- source "vhost.erb"
- variables({ :doc_root => node['main']['doc_root'] })
- action :create
- notifies :restart, resources(:service => "apache2")
- end
-
###レシピの説明
####行1レシピは、属性の定義node['main']['doc_root']
で始まります。 ここでは単純なローカル変数を使用することもできますが、ほとんどのユースケースシナリオでは、レシピは、含まれているレシピまたは他のファイルから使用されるグローバル変数を定義する必要があります。 このような状況では、ローカル変数のスコープが制限されているため、ローカル変数の代わりに属性を作成する必要があります。
####3-5行目このexecuteリソースはapt-get update
を実行します。
####行7-10このapt_packageリソースは、パッケージapache2
をインストールします。
#### 12〜15行目この service リソースは、サービスapache2
を有効にして開始します。 後で、サービスを再開するためにこのリソースに通知する必要があります。 サービス定義は、サービスに通知しようとするリソースの前に配置することが重要です。そうしないと、エラーが発生します。
####行17-22このディレクトリリソースは、カスタム属性node['main']['doc_root']
で定義された値を使用して、ドキュメントルートとして機能するディレクトリを作成します。
####行24〜29 cockbook_file リソースは、ローカルファイルをリモートサーバーにコピーするために使用されます。 このリソースは、index.html
ファイルをコピーし、前のタスクで作成したドキュメントルート内に配置します。
####行31-36最後に、この template リソースは、Apache仮想ホストテンプレートを適用し、サービスapache2
に再起動を通知します。
##結論Chefは、Ruby言語を活用してサーバーのプロビジョニングとデプロイメントを自動化する、強力な構成管理ツールです。 標準言語機能を自由に使用して最大限の柔軟性を実現すると同時に、一部のリソースにカスタムDSLを提供します。