構成管理101:Puppetマニフェストの作成

前書き

簡単に言えば、サーバー構成管理(一般的にITオートメーションとも呼ばれます)は、インフラストラクチャ管理をコードベースに変換するソリューションであり、バージョン管理および再利用が容易なプロビジョニングスクリプトのセットでサーバーを展開するために必要なすべてのプロセスを記述します。 サーバーインフラストラクチャの整合性を長期にわたって大幅に改善できます。

https://www.digitalocean.com/community/tutorials/an-introduction-to-configuration-management [前のガイド]で、サーバーインフラストラクチャの構成管理戦略を実装する主な利点、構成管理の方法について説明しましたツールが機能し、これらのツールに通常共通するもの。

シリーズのこのパートでは、マスターサーバーを使用してノードの構成を調整し、複雑なインフラストラクチャを透過的に管理できる一般的な構成管理ツールであるPuppetを使用してサーバープロビジョニングを自動化するプロセスについて説明します。 Apacheを使用したUbuntu 18.04 Webサーバーの展開を完全に自動化するための簡単な例を作成するために必要な言語用語、構文、および機能に焦点を当てます。

これは、目標を達成するために自動化する必要がある手順のリストです。

  1. `+ apt +`キャッシュを更新する

  2. Apacheをインストールする

  3. カスタムドキュメントルートディレクトリを作成する

  4. カスタムドキュメントルートに `+ index.html`ファイルを配置します

  5. テンプレートを適用して、カスタム仮想ホストをセットアップします

  6. Apacheを再起動します

まず、Puppetで使用される用語を見てから、マニフェストの作成に使用できる主要な言語機能の概要を説明します。 このガイドの最後で、完全な例を共有するので、自分で試してみることができます。

入門

Puppetのより実践的なビューに移る前に、このツールで導入された重要な用語と概念を理解することが重要です。

パペット規約

  • * Puppetマスター*:ノードの構成を制御するマスターサーバー

  • * Puppet Agentノード*:Puppetマスターによって制御されるノード

  • マニフェスト:実行される命令セットを含むファイル

  • リソース:システムの要素とその状態の変更方法を宣言するコードの一部。 たとえば、パッケージをインストールするには、_package_リソースを定義し、その状態が「インストール済み」に設定されていることを確認する必要があります

  • モジュール:プロビジョニングの一部の共有と再利用を促進するために、事前に定義された方法で編成されたマニフェストと他の関連ファイルのコレクション

  • クラス:通常のプログラミング言語と同様に、クラスはPuppetで使用され、プロビジョニングをより適切に編成し、コードの一部を再利用しやすくします

  • 事実:ネットワークインターフェイスやオペレーティングシステムなど、システムに関する情報を含むグローバル変数

  • サービス:サービスの再起動や停止など、サービスのステータスの変更をトリガーするために使用されます

Puppetプロビジョニングは、Rubyに基づくカスタムDSL(ドメイン固有言語)を使用して記述されています。

リソース

Puppetでは、タスクまたはステップは* resources *を宣言することにより定義されます。 リソースは、パッケージ、ファイル、サービス、ユーザー、およびコマンドを表すことができます。 それらは、宣言されたリソースの状態が現在システム上にあるものと異なる場合にシステムの変更をトリガーする状態を持っているかもしれません。 たとえば、マニフェストで「+ installed +」に設定された_package_リソースは、パッケージが以前にインストールされていなかった場合、システム上でパッケージのインストールをトリガーします。

これが_package_リソースの外観です:

package { 'nginx':
   ensure  => 'installed'
}

次のように、 `+ exec +`リソースを宣言することにより、任意のコマンドを実行できます。

exec { 'apt-get update':
   command => '/usr/bin/apt-get update'
}

最初の行の「+ apt-get update」部分は実際のコマンド宣言ではなく、この一意のリソースの識別子であることに注意してください。 多くの場合、リソース内から他のリソースを参照する必要があり、そのためにそれらの識別子を使用します。 この場合、識別子は「+ apt-get update」ですが、他の文字列でもかまいません。

リソース依存

マニフェストを作成する場合、Puppetは定義された順序でリソースを評価しないことに注意してください。 これは、Puppetを使い始めた人にとって一般的な混乱の原因です。 リソースは相互の依存関係を明示的に定義する必要があります。そうしないと、どのリソースが最初に評価され、結果として実行されるかが保証されません。

簡単な例として、コマンドを実行したいが、最初に依存関係がインストールされていることを確認する必要があるとしましょう:

package { 'python-software-properties':
   ensure => 'installed'
}

exec { 'add-repository':
   command => '/usr/bin/add-apt-repository ppa:ondrej/php5 -y'
   require => Package['python-software-properties']
}

+ require +`オプションは、パラメーターとして別のリソースへの参照を受け取ります。 この場合、 `+ python-software-properties`として識別されるpackageリソースを参照しています。 +リソースを宣言するために(小文字で) `+ exec ++ package +`などを使用する一方で、以前に定義されたリソースを参照するときは、 `+ Exec +、 `+ Package +`などを使用することに注意することが重要です。 on(大文字)。

次に、タスクが別のタスクの前に実行されることを確認する必要があるとしましょう。 このような場合、代わりに `+ before +`オプションを使用できます:

package { 'curl':
   ensure => 'installed'
   before => Exec['install script']
}

exec { 'install script':
   command => '/usr/bin/curl http://example.com/some-script.sh'

マニフェスト形式

マニフェストは基本的に、リソース宣言のコレクションであり、拡張子「+ .pp 」を使用します。 以下に、2つのタスクを実行する簡単なプレイブックの例を示します。「 apt 」キャッシュを更新し、後で「 vim +」をインストールします。

exec { 'apt-get update':
   command => '/usr/bin/apt-get update'
}

package { 'vim':
   ensure => 'installed'
   require => Exec['apt-get update']
}

このガイドが終了する前に、マニフェストのより実際の例を詳細に説明します。 次のセクションでは、Puppetマニフェストの作成に使用できる最も重要な要素と機能の概要を説明します。

マニフェストの作成

変数の使用

変数は、マニフェストの任意の時点で定義できます。 変数の最も一般的なタイプは文字列と文字列の配列ですが、ブール値やハッシュなどの他のタイプもサポートされています。

次の例では、後でリソース内で使用される文字列変数を定義しています。

$package = "vim"

package { $package:
  ensure => "installed"
}

ループを使用する

ループは通常、異なる入力値を使用してタスクを繰り返すために使用されます。 たとえば、10個の異なるパッケージをインストールするための10個のタスクを作成する代わりに、単一のタスクを作成し、ループを使用して、インストールするすべての異なるパッケージでタスクを繰り返すことができます。

Puppetで異なる値を使用してタスクを繰り返す最も簡単な方法は、次の例のように配列を使用することです。

$packages = ['vim', 'git', 'curl']

package { $packages:
  ensure => "installed"
}

バージョン4以降、Puppetはタスクを反復処理するための追加の方法をサポートしています。 以下の例は前の例と同じことをしますが、今回は `+ each +`イテレータを使用します。 このオプションは、リソース定義をループするための柔軟性を提供します。

$packages.each |String $package| {
 package { $package:
   ensure => "installed"
 }
}

条件を使用する

条件を使用して、たとえば変数またはコマンドからの出力に基づいて、コードのブロックを実行するかどうかを動的に決定できます。

Puppetは、 `+ if / else `や ` case `ステートメントなど、従来のプログラミング言語で見つけることができるほとんどの条件構造をサポートしています。 さらに、 ` exec +`などの一部のリソースは、条件付きのように機能する属性をサポートしますが、条件としてコマンド出力のみを受け入れます。

_fact_に基づいてコマンドを実行するとします。 この場合、変数の値をテストするには、 `+ if / else +`のようなサポートされている条件構造のいずれかを使用する必要があります。

if $osfamily != 'Debian' {
warning('This manifest is not supported on this OS.')
}
else {
notify { 'Good to go!': }
}

別の一般的な状況は、別のコマンドからの出力に基づいてコマンドの実行を条件付ける場合です。 このような場合、以下の例のように、「+ onlyif 」または「 unless 」を使用できます。 このコマンドは、 ` / bin / which php +`からの出力が成功した場合にのみ実行されます。つまり、コマンドはステータス* 0 *で終了します。

exec { "Test":
command => "/bin/echo PHP is installed here > /tmp/test.txt",
onlyif => "/bin/which php"
}

同様に、「+ unless 」の下のコマンドが正常に終了する場合を除き、「 unless +」は常にコマンドを実行します。

exec { "Test":
command => "/bin/echo PHP is NOT installed here > /tmp/test.txt",
unless => "/bin/which php"
}

テンプレートの使用

テンプレートは通常、構成ファイルをセットアップするために使用され、変数やその他の機能を使用して、これらのファイルをより汎用的で再利用可能にすることを目的としています。 Puppetは、テンプレート用に2つの異なる形式をサポートしています:Embedded Puppet(EPP)およびEmbedded Ruby(ERB)。 ただし、EPP形式は、Puppetの最新バージョン(バージョン4.0以降)でのみ機能します。

以下は、このホストのドキュメントルートを設定する変数を使用して、Apache仮想ホストを設定するためのERBテンプレートの例です。

<VirtualHost *:80>
   ServerAdmin [email protected]
   DocumentRoot <%= @doc_root %>

   <Directory <%= @doc_root %>>
       AllowOverride All
       Require all granted
   </Directory>
</VirtualHost>

テンプレートを適用するには、 + template a`メソッドでテンプレートコンテンツをレンダリングする + file`リソースを作成する必要があります。 これは、このテンプレートを適用してデフォルトのApache仮想ホストを置き換える方法です。

file { "/etc/apache2/sites-available/000-default.conf":
   ensure => "present",
   content => template("apache/vhost.erb")
}

Puppetは、組織とモジュール性を強化するために、ローカルファイルを扱う際にいくつかの仮定を行います。 この場合、Puppetはモジュールディレクトリ内のフォルダー `+ apache / templates `内で ` vhost.erb +`テンプレートファイルを探します。

サービスの定義とトリガー

サービスリソースは、サービスが初期化および有効化されていることを確認するために使用されます。 また、サービスの再起動をトリガーするためにも使用されます。

Apache仮想ホストを設定する以前のテンプレートの使用例を考慮してみましょう。 仮想ホストの変更後にApacheが再起動されるようにするには、最初にApacheサービス用の_service_リソースを作成する必要があります。 これは、Puppetでそのようなリソースがどのように定義されるかです:

service { 'apache2':
   ensure => running,
   enable => true
}

さて、リソースを定義するとき、再起動をトリガーするために `+ notify +`オプションを含める必要があります:

file { "/etc/apache2/sites-available/000-default.conf":
   ensure => "present",
   content => template("vhost.erb"),
   notify => Service['apache2']
}

マニフェストの例

このガイドの概要で説明したように、Ubuntu 14.04システム内でのApache Webサーバーのインストールを自動化するマニフェストを見てみましょう。

Apacheを設定するためのテンプレートファイルとWebサーバーが提供するHTMLファイルを含む完全な例は、https://github.com/erikaheidi/cfmgmt/tree/master/puppet [on Github]にあります。 このフォルダーには、https://vagrantup.com [Vagrant]によって管理される仮想マシンを使用して、簡素化されたセットアップでマニフェストをテストできるVagrantfileも含まれています。

以下に完全なマニフェストがあります。

default.pp

$doc_root = "/var/www/example"

exec { 'apt-get update':
command => '/usr/bin/apt-get update'
}

package { 'apache2':
ensure  => "installed",
require => Exec['apt-get update']
}

file { $doc_root:
ensure => "directory",
owner => "www-data",
group => "www-data",
mode => 644
}

file { "$doc_root/index.html":
  ensure => "present",
  source => "puppet:///modules/main/index.html",
  require => File[$doc_root]
}

file { "/etc/apache2/sites-available/000-default.conf":
  ensure => "present",
  content => template("main/vhost.erb"),
  notify => Service['apache2'],
  require => Package['apache2']
}

service { 'apache2':
  ensure => running,
  enable => true
}

マニフェストの説明

ライン1

マニフェストは変数定義 `+ $ doc_root +`で始まります。 この変数は、後でリソース宣言で使用されます。

行3〜5

この* exec *リソースは `+ apt-get update +`コマンドを実行します。

7〜10行目

この* package *リソースはパッケージ `+ apache2 `をインストールし、 ` apt-get update +`リソースが要件であることを定義します。つまり、必要なリソースが評価された後にのみ実行されます。

12〜17行目

ここで* file *リソースを使用して、ドキュメントルートとして機能する新しいディレクトリを作成します。 `+ file `リソースはディレクトリとファイルの作成に使用でき、テンプレートの適用とローカルファイルのリモートサーバーへのコピーにも使用されます。 このタスクはプロビジョニングのどの時点でも実行できるため、ここで「 require +」を設定する必要はありませんでした。

19〜23行目

ここでは別の* file リソースを使用します。今回はローカルの index.html *ファイルをサーバー内のドキュメントルートにコピーします。 `+ source `パラメーターを使用して、元のファイルの場所をPuppetに知らせます。 この命名法は、Puppetがローカルファイルを処理する方法に基づいています。 https://github.com/erikaheidi/cfmgmt/tree/master/puppet/environments/vagrant/modules/main/files[Githubリポジトリの例]を見ると、ディレクトリ構造の作成方法がわかりますPuppetにこのリソースを見つけさせるため。 このリソースを実行する前にドキュメントのルートディレクトリを作成する必要があります。そのため、以前のリソースを参照する ` require +`オプションを含めます。

25〜30行目

新しい* file リソースを使用して、Apacheテンプレートを適用し、サービスに再起動を通知します。 この例では、プロビジョニングは main というモジュールで構成されているため、テンプレートソースは main / vhost.erb *です。 `+ require `ステートメントを使用して、パッケージ ` apache2 +`のインストール後にのみテンプレートリソースが実行されるようにします。そうしないと、Apacheが使用するディレクトリ構造がまだ存在しない可能性があります。

行32〜35

最後に、* service *リソースは `+ apache2 +`サービスを宣言し、仮想ホストテンプレートを適用するリソースからの再起動を通知します。

結論

Puppetは、表現力豊かなカスタムDSLを使用してサーバーリソースを管理し、タスクを自動化する強力な構成管理ツールです。 その言語は高度なリソースを提供し、プロビジョニングのセットアップに柔軟性を与えます。リソースは定義された順序と同じ順序で評価されないことを覚えておくことが重要です。そのため、適切な実行チェーンを確立するためにリソース間の依存関係を定義する際には注意が必要です。

https://www.digitalocean.com/community/tutorials/configuration-management-101-writing-chef-recipes [このシリーズの次のガイド]では、Chefをご覧ください。これは、インフラストラクチャの管理とプロビジョニングを自動化するRubyプログラミング言語。