構成管理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
直接。 The 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
拡張機能をインストールする前に php-pear
. コマンドを使用します which
あるかどうかを確認するため php
このシステムに現在インストールされている実行可能ファイル。 コマンドの場合 which php
falseを返します。このタスクは実行されません:
apt_package "php-pear" do
action :install
only_if "which php"
end
逆のことをしたい場合は、条件が真と評価されたときにを除いて常にコマンドを実行します。 not_if
代わりは。 この例はインストールします php5
システムがCentOSでない限り:
apt_package "php5" do
action :install
not_if { node['platform'] == 'centos' }
end
より複雑な評価を実行する場合、特定の条件下で複数のタスクを実行する場合は、標準のRuby条件のいずれかを使用できます。 次の例は実行するだけです apt-get update
システムがDebianまたはUbuntuの場合:
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は、編成とモジュール性を強化するために、ローカルファイルを処理するときにいくつかの仮定を行います。 この場合、シェフは vhost.erb
このレシピが配置されているのと同じクックブックにある必要があるtemplatesフォルダー内のテンプレートファイル。
これまで見てきた他の構成管理ツールとは異なり、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を提供します。