Puppetが開発した新たな構成管理ツール「Bolt」を使ってみる
あらかじめファイルなどで定義しておいた内容に従ってサーバーの設定やソフトウェアのインストールなどを自動実行する「構成管理自動化ツール」分野ではAnsibleやPuppet、Chefといったツールが有名だが、そんな中昨年10月に新たな自動化ツール「Puppet Bolt」がリリースされた。Puppet BoltはSSHなどのリモートログイン機能を使って対象とするマシンを操作するのが特徴で、管理対象のマシンにエージェントをインストールすることなく利用できる点がアピールされている。本記事ではこのPuppet Boltの機能、導入方法、使用例を紹介する。
目次
シンプルな構成管理ツールをうたう新ツール「Bolt」
ソフトウェアのインストールや構成管理を自動化する構成管理ツールとしては、PuppetやChef、Ansibleといったものが存在する。かつてはPuppetやChefが人気だったが、最近ではAnsibleの人気が高まっているようだ。TechRepublicの調査結果によると、2019年の調査で最も利用者が多かった構成管理ツールはAnsibleだったそうだ。
PuppetやChefでは管理対象のマシンに「エージェント」などと呼ばれる管理用のソフトウェアをインストールする必要があったが、Ansibleではエージェントのインストールが不要で、設定ファイルがシンプルで簡潔に記述できるなど、利用するための準備や手間が小さい点が評価されている。こうした状況を受けてか、Puppetを提供するPuppet社は2018年10月、新たな構成管理ツール「Puppet Bolt」(以下、Bolt)をリリースした。BoltのWebサイトでは、その特徴としてシンプルさが挙げられている(図1)。
これによると、BoltはPuppetに関する知識が無くても利用でき、また管理対象マシンへのエージェントの事前インストールも不要とされている。LinuxだけでなくWindowsやmacOSにも対応しているのも特徴だ。
そこで本記事では、この新しいツールであるBoltについて、Linux環境でのインストールや各種設定、基本的な使い方の紹介や、使い勝手についての検証を行っていく。
Boltのインストール
BoltはRuby言語で実装されており、そのソースコードはオープンソースで公開されている(GitHubで公開されているBoltのリポジトリ)。前述のとおり対応プラットフォームはLinuxおよびmacOS、Windowsで、Rubyはバージョン2.3以上が必須となっている。
Boltのドキュメントでは、RubyおよびBoltを個別にインストールするのではなく、Bolt本体に加えて使用するRubyや各種ライブラリなどがすべて含まれているパッケージを利用してインストールすることが推奨されている。現時点ではDebian 8/9、Ubuntu 14.04/16.04/18.04、Red Hat Enterprise Linux(RHEL) 6/7/8およびその互換環境、Fedora 28/29/30などに対応したパッケージがDebおよびYumリポジトリで提供されており、使用するディストリビューションに応じたリポジトリを登録することでapt/apt-getコマンドやyum/dnfコマンドでパッケージをインストールできる。
Debian系ディストリビューションへのインストール
Debian系ディストリビューション向けには、https://apt.puppet.com/というリポジトリが用意されている。このリポジトリで公開されている「puppet6-release-<リリース>.deb」(「<リリース>」部分には使用するディストリビューションのリリース名が入る)というパッケージをインストールすることでリポジトリが利用可能になる。
たとえばUbuntu 18.04.2 LTS(Bionic Beaver)の場合、「puppet6-release-bionic.deb」パッケージをインストールすれば、aptコマンドで「puppet-bolt」パッケージがインストールできるようになる。
$ wget https://apt.puppet.com/puppet6-release-bionic.deb # dpkg -i puppet6-release-bionic.deb # apt update # apt install puppet-bolt
Red Hat系ディストリビューションへのインストール
Red Hat系ディストリビューション向けには、https://yum.puppet.com/というリポジトリが用意されている。このリポジトリで公開されている「puppet6-release-<ディストリビューション名>-<バージョン>.noarch.rpm」というパッケージをインストールすることでリポジトリが利用可能になる。
たとえばRed Hat Enterprise 7系やその互換環境であるCentOS 7系の場合は「puppet6-release-el-7.noarch.rpm」を、Fedora 30の場合は「puppet6-release-fedora-30.noarch.rpm」をインストールすれば良い。
# rpm -ivh https://yum.puppet.com/puppet6-release-el-7.noarch.rpm # yun install puppet-bilt
いずれの場合も、インストールされたBoltのバージョンは「bolt --version」コマンドで確認できる。
$ bolt --version 1.25.0
環境情報収集のオプトアウト設定
Boltでは、デフォルト設定ではユーザーによる利用状況といったデータをPuppetに送信するようになっている。このデータ送信を止めるには、次のようにしてユーザのホームディレクトリ以下に「.puppetlabs/bolt/analytics.yaml」というファイルを作成し、そこに「disabled: true」と記述しておけば良い。
$ mkdir -p ~/.puppetlabs/bolt $ echo "disabled: true" > ~/.puppetlabs/bolt/analytics.yaml
なお、このファイルが存在しない場合、Boltの実行時にディレクトリおよびファイルが自動的に作成され、ここにユーザー固有のIDが保存される。
$ cat .puppetlabs/bolt/analytics.yaml --- user-id: 6e52cd2b-90ba-4ffa-97bb-7910b06cbcf5
各種操作を行うboltコマンド
Boltでは、「bolt」というコマンドを使って各種操作を実行する。boltコマンドは次のように2つ以上の引数を取り、これらで処理対象および処理内容を指定する。
bolt <サブコマンド> <アクション> <オプション>...」
サポートされているサブコマンドやアクションは「-h」オプションで確認できる。
$ bolt -h Usage: bolt <subcommand> <action> Available subcommands: bolt command run <command> Run a command remotely bolt file upload <src> <dest> Upload a local file or directory bolt script run <script> Upload a local script and run it remotely bolt task show Show list of available tasks bolt task show <task> Show documentation for task bolt task run <task> [params] Run a Puppet task bolt plan convert <plan_path> Convert a YAML plan to a Puppet plan bolt plan show Show list of available plans bolt plan show <plan> Show details for plan bolt plan run <plan> [params] Run a Puppet task plan bolt apply <manifest> Apply Puppet manifest code bolt puppetfile install Install modules from a Puppetfile into a Boltdir bolt puppetfile show-modules List modules available to Bolt bolt secret createkeys Create new encryption keys bolt secret encrypt <plaintext> Encrypt a value bolt secret decrypt <encrypted> Decrypt a value Run `bolt <subcommand> --help` to view specific examples. : :
サブコマンドの詳細や指定できるアクションについては、「bolt <サブコマンド> -h」のようにサブコマンドと一緒に「-h」オプションを指定することで確認できる。
$ bolt command -h Usage: bolt command <action> <command> Available actions are: run Run a command remotely : :
利用できるサブコマンドやアクションの一覧については公式ドキュメントのコマンドリファレンスも参照すると良いだろう。
SSHの設定
Boltではリモートログイン機能を使って操作対象のマシンにログインして各種処理を実行する仕組みになっている。そのため、操作対象のマシンに対しリモートログインできるよう事前に設定を行っておく必要がある。
また、Linuxの場合は主としてSSHを利用してリモートログインを行うが、このとき特に設定を行わない限りコマンドの実行時に毎回パスワードやパスフレーズの入力が必要となってしまう。さらに、筆者が検証した限りではboltコマンドの実行時にパスフレーズを入力できないという不具合も存在するようだ。
そのため、操作対象とするサーバーに公開鍵認証でログインできるように設定するとともに、パスフレーズの入力を省略できる「ssh-agent」というツールを利用することをおすすめする。
ssh-agentは、SSHで利用するパスフレーズを記録しておくことでパスフレーズ入力を省略できるようにするツールだ。たとえばシェルとしてbashを使用している場合、次のようにしてssh-agentを起動する。
$ ssh-agent bash
ssh-agentの起動後、ssh-addコマンドを実行するとパスフレーズの入力が求められ、以降はここで入力したパスフレーズがSSHの利用時に自動入力されるようになる。
$ ssh-add Enter passphrase for /home/hylom/.ssh/id_rsa: Identity added: /home/hylom/.ssh/id_rsa (/home/hylom/.ssh/id_rsa)
なお、ssh-agentの引数として指定したプログラムが終了すると保持されたパスフレーズはその時点で破棄される。
以下の実行例では、特に言及のない限りこのssh-agentを利用してパスフレーズの入力を省略できるようにした状態でboltコマンドを実行している。
リモートホスト上でコマンドを実行
Boltでは、「command」サブコマンドおよび「run」アクションを使ってリモートホスト上で任意のコマンドを実行できる。
$ bolt command run <実行するコマンド> -n <対象ホスト>
このとき、実行するリモートホストは「-n」(もしくは「--nodes」)オプションで指定する。たとえば、「192.0.2.100」というホストで「echo hoge」というコマンドを実行する場合、次のようになる。
$ bolt command run "echo hoge" -n 192.0.2.100 Started on 192.0.2.100... Finished on 192.0.2.100: STDOUT: hoge Successful on 1 node: 192.0.2.100 Ran on 1 node in 0.33 seconds
このとき、コマンドの実行結果は「STDOUT:」以下に表示される。また、指定したコマンドはリモートログインに使用したユーザーの権限(通常はローカルユーザーと同名のユーザー)で実行される。
$ bolt command run id -n 192.0.2.100 Started on 192.0.2.100... Finished on 192.0.2.100: STDOUT: uid=1000(hylom) gid=1000(hylom) groups=1000(hylom) Successful on 1 node: 192.0.2.100 Ran on 1 node in 0.33 seconds
リモートログインに使用するユーザーを指定したい場合は、ホスト名もしくはIPアドレスの前に「@」を付けて「<ユーザー名>@<ホスト名もしくはIPアドレス」のように指定すれば良い。
なお、Boltではデフォルトでリモートホストのホスト鍵の検証も行うようになっており、一度もリモートログインしていないリモートホストを対象にboltコマンドを実行すると、次のようにホスト鍵認証に失敗してしまう。
$ bolt command run "echo hoge" -n 192.0.2.100 Started on 192.0.2.100... Failed on 192.0.2.100: Host key verification failed for 192.0.2.100: fingerprint SHA256:RWWCsRzzOAZ61TWVqbzPxPUS1UiU0pNH41Dg+TlwGi8 is unknown for "192.0.2.100" Failed on 1 node: 192.0.2.100 Ran on 1 node in 0.09 seconds
この場合、次のようにsshコマンドで一度対象のリモートホストにログインしてホスト鍵を許可するか、もしくは「--no-host-key-check」オプション付きでboltコマンドを実行すれば良い。
$ ssh 192.0.2.100 The authenticity of host '192.0.2.100 (192.0.2.100)' can't be established. ECDSA key fingerprint is SHA256:u49rtoHeIz5ixnnmD4BysYcPpXolg2j3glKL8vuTY4s. Are you sure you want to continue connecting (yes/no)? yes ←そのままEnterキーを押す Warning: Permanently added '192.0.2.100' (ECDSA) to the list of known hosts.
リモートログインに使用したユーザーとは異なるユーザーでコマンドを実行したい場合は、「--run-as <ユーザー>」オプションを使用する。この場合、リモートホスト上でsudoコマンドが実行され、指定したユーザー権限でコマンドが実行される。sudoコマンドの実行時に必要なパスワードは「--sudo-password」を指定することで入力できる。次の例では、「--run-as root」と指定することでrootユーザーでコマンドを実行している。
$ bolt command run id -n 192.0.2.100 --run-as root --sudo-password Please enter your privilege escalation password: ←sudoコマンドで使用するパスワードを入力する Started on 192.0.2.100... Finished on 192.0.2.100: STDOUT: uid=0(root) gid=0(root) groups=0(root) Successful on 1 node: 192.0.2.100 Ran on 1 node in 0.36 seconds
複数のホストを対象にコマンドを実行する
-nオプションではカンマ区切りで複数のノードを同時に指定できる。次の例では、「192.0.2.100」と「192.0.2.110」という2つのリモートホストで「echo hoge」コマンドを実行している。
$ bolt command run "echo hoge" -n 192.0.2.100,192.0.2.110 Started on 192.0.2.100... Started on 192.0.2.110... Finished on 192.0.2.100: STDOUT: hoge Finished on 192.0.2.110: STDOUT: hoge Successful on 2 nodes: 192.0.2.100,192.0.2.110 Ran on 2 nodes in 0.40 seconds
また、ホスト名やIPアドレスの代わりに「@<ファイル名>」と指定することで、指定したファイルに記載されているIPアドレスやホスト名を対象にできる。次の例では、「192.0.2.100」および「192.0.2.110」と記述した「nodes.txt」というファイルを指定して実行している。
$ cat nodes.txt 192.0.2.100 192.0.2.110 $ bolt command run "echo hoge" -n @nodes.txt Started on 192.0.2.100... Started on 192.0.2.110... Finished on 192.0.2.110: STDOUT: hoge Finished on 192.0.2.100: STDOUT: hoge Successful on 2 nodes: 192.0.2.110,192.0.2.100 Ran on 2 nodes in 0.39 seconds
「-n -」と指定すれば、標準入力経由でリモートホストを指定できる。
$ cat nodes.txt | bolt command run "echo hoge" -n - Started on 192.0.2.100... Started on 192.0.2.110... Finished on 192.0.2.110: STDOUT: hoge Finished on 192.0.2.100: STDOUT: hoge Successful on 2 nodes: 192.0.2.110,192.0.2.100 Ran on 2 nodes in 0.36 seconds
スクリプトを実行する
boltコマンドでは、「script」サブコマンドで任意のスクリプトをリモートホスト上で実行できる。
$ bolt script run <実行するスクリプト> -n <対象ホスト>
次の例は、echoコマンドを実行するだけのスクリプト(hello.sh)を実行したものだ。
$ cat hello.sh #!/bin/bash echo "hello, world!" $ bolt script run hello.sh -n 192.0.2.100 Started on 192.0.2.100... Finished on 192.0.2.100: STDOUT: hello, world! Successful on 1 node: 192.0.2.100 Ran on 1 node in 0.62 seconds
ここではシェルスクリプトを実行させているが、リモートホスト上で実行できるものであれば任意のスクリプトやプログラムが実行可能だ。
ファイルのアップロード
「file」サブコマンドでは、指定したファイルを指定したホストにアップロードできる。
$ bolt file upload <対象のファイル> <アップロード先のパス> -n <対象ホスト>
たとえば「sample.txt」というファイルを、リモートホストのホームディレクトリ(~/)にアップロードするには次のように実行する。
$ bolt file upload sample.txt ~/ -n 192.0.2.100 Started on 192.0.2.100... Finished on 192.0.2.100: Uploaded 'sample.txt' to '192.0.2.100:/home/hylom/' Successful on 1 node: 192.0.2.100 Ran on 1 node in 0.52 seconds
実行する処理を定義した「Task」と「Plan」
Boltでは、リモートホストで実行する処理を「Task」や「Plan」という形で定義するようになっている。実行する単一の処理を定義したものがTaskで、1つ以上のTaskを組み合わせて実行できるようにしたものがPlanだ。
TaskやPlanは再利用できる形で定義できるようになっており、デフォルトでもいくつかのTaskやPlanがインストールされている。
Taskの一覧と実行
Taskに関する処理は「task」サブコマンドで実行でき、たとえば利用できるTaskの一覧は「bolt task show」コマンドで一覧表示できる。
$ bolt task show facts Gather system facts package Manage and inspect the state of packages puppet_agent::install Install the Puppet agent package puppet_agent::version Get the version of the Puppet agent package installed. Returns nothing if none present. puppet_conf Inspect puppet agent configuration settings reboot Reboots a machine reboot::last_boot_time Gets the last boot time of a Linux or Windows system service Manage and inspect the state of services MODULEPATH: /home/hylom/.puppetlabs/bolt/modules:/home/hylom/.puppetlabs/bolt/site-modules:/home/hylom/.puppetlabs/bolt/site Use `bolt task show <task-name>` to view details and parameters for a specific task.
個々のTaskの詳細は、「bolt task show <Task名>」コマンドで確認できる。たとえば「facts」というTaskについての詳細は次のようになっている。
$ bolt task show facts facts - Gather system facts USAGE: bolt task run --nodes <node-name> facts MODULE: built-in module
このTaskは「Gather system facts」と説明されているとおり、指定したノードの基本的な情報を取得するものだ。Taskを実行するには、「bolt task run <Task名>」コマンドを使用する。次の例は、前述のfactsというTaskを実行するものだ。
$ bolt task run facts -n 192.0.2.110 Started on 192.0.2.110... Finished on 192.0.2.110: { "os": { "name": "CentOS", "release": { "full": "7.6", "major": "7", "minor": "6" }, "family": "RedHat" } } Successful on 1 node: 192.0.2.110 Ran on 1 node in 0.71 seconds
Taskによっては、追加のパラメータ指定が必要となるものもある。たとえば「package」というTaskはパッケージのインストールやアップデート、アンインストールといった処理を行うもので、実行する処理を「action」、対象とするパッケージ名を「name」パラメータで指定する。
$ bolt task show package package - Manage and inspect the state of packages USAGE: bolt task run --nodes <node-name> package action=<value> name=<value> version=<value> provider=<value> PARAMETERS: - action: Enum[install, status, uninstall, upgrade] The operation (install, status, uninstall and upgrade) to perform on the package. - name: String[1] The name of the package to be manipulated. - version: Optional[String[1]] Version numbers must match the full version to install, including release if the provider uses a release moniker. Ranges or semver patterns are not accepted except for the gem package provider. For example, to install the bash package from the rpm bash-4.1.2-29.el6.x86_64.rpm, use the string '4.1.2-29.el6'. - provider: Optional[String[1]] The provider to use to manage or inspect the package, defaults to the system package manager. Only used when the 'puppet-agent' feature is available on the target so we can leverage Puppet. MODULE: built-in module
次の例は、このTaskを使って「httpd」パッケージをインストールするものだ。パッケージのインストールにはroot権限が必要であるため、ここでは「--run-as root」オプションを指定して実行している。
$ bolt task run package action=install name=httpd --run-as root --sudo-password -n 192.0.2.110 Please enter your privilege escalation password: Started on 192.0.2.110... Finished on 192.0.2.110: { "status": "installed", "version": "2.4.6-89.el7.centos" } Successful on 1 node: 192.0.2.110 Ran on 1 node in 13.01 seconds
また、「service」というTaskはサービスの起動/停止、再起動、有効化/無効化などを行うものだ。こちらも「action」で実行する処理、「name」で対象となるサービスを指定するようになっている。
$ bolt task show service service - Manage and inspect the state of services USAGE: bolt task run --nodes <node-name> service action=<value> name=<value> provider=<value> PARAMETERS: - action: Enum[start, stop, restart, enable, disable, status] The operation (start, stop, restart, enable, disable, status) to perform on the service. - name: String[1] The name of the service to operate on. - provider: Optional[String[1]] The provider to use to manage or inspect the service, defaults to the system service manager. Only used when the 'puppet-agent' feature is available on the target so we can leverage Puppet. MODULE: built-in module
次の例は、このTaskを使って「httpd」サービスをリスタートさせるものだ。
$ bolt task run service action=restart name=httpd --run-as root --sudo-password -n 192.0.2.110 Please enter your privilege escalation password: Started on 192.0.2.110... Finished on 192.0.2.110: { "status": "MainPID=29066,LoadState=loaded,ActiveState=active" } Successful on 1 node: 192.0.2.110 Ran on 1 node in 1.19 seconds
Planの一覧と実行
Planは複数のTaskを組み合わせて目的の処理を達成できるようにしたもので、「plan」サブコマンドでPlanに関する処理を実行できる。たとえば利用できるPlanの一覧は「bolt plan show」コマンドで確認できる。
$ bolt plan show aggregate::count aggregate::nodes canary facts facts::info puppetdb_fact reboot MODULEPATH: /home/hylom/.puppetlabs/bolt/modules:/home/hylom/.puppetlabs/bolt/site-modules:/home/hylom/.puppetlabs/bolt/site Use `bolt plan show <plan-name>` to view details and parameters for a specific plan.
また、Planの詳細は「bolt plan show <Plan名>」コマンドで確認できる。次の例は「facts」というPlanについての詳細を表示したものだ。
$ bolt plan show facts facts USAGE: bolt plan run facts nodes=<value> PARAMETERS: - nodes: TargetSpec MODULE: built-in module
Planを実行するには、「bolt plan run <Plan名>」コマンドを実行すれば良い。たとえば「nodes.txt」に記述されているリモートホストに対しfactsというTaskを実行する場合、次のようになる。
$ bolt plan run facts -n @nodes.txt Starting: plan facts Starting: task facts on 192.0.2.110, 192.0.2.100 Finished: task facts with 0 failures in 0.6 sec Finished: plan facts in 0.62 sec Finished on 192.0.2.110: { "os": { "name": "CentOS", "release": { "full": "7.6", "major": "7", "minor": "6" }, "family": "RedHat" } } Finished on 192.0.2.100: { "os": { "name": "CentOS", "release": { "full": "7.6", "major": "7", "minor": "6" }, "family": "RedHat" } } Successful on 2 nodes: 192.0.2.110,192.0.2.100 Ran on 2 nodes
TaskやPlanのインストール
TaskやPlanはモジュール化されており、容易に追加できる構造になっている。たとえば、Puppetが提供するPuppet ForgeというサイトでもBoltで利用できるTaskが公開されている(図2)。
Puppet Forgeで公開されているモジュールは、boltコマンドを使って簡単にインストールできる。たとえばリモートホスト上でMySQLサーバーに接続してSQLを実行したり、データベースをローカルストレージにバックアップしたりするといったTaskを提供する「mysql」モジュールをインストールしたい場合、次のような手順になる。
まず、モジュールをインストールする適当なディレクトリを用意し、そこに「bolt.yaml」というファイルと「Puppetfile」というファイルを作成する。
↓空のbolt.yamlファイルを作成する $ touch bolt.yaml ↓Puppetfileファイルを作成する $ echo "mod 'puppetlabs-mysql', '10.0.0'" > Puppetfile $ ls Puppetfile bolt.yaml
bolt.yamlはboltコマンドの挙動を定義するファイルだが、空のファイルでも問題ない。また、Puppetfileは使用するモジュールを指定するファイルで、次のようなフォーマットでインストールするモジュールを列挙する。
mod '<モジュール名>', '<バージョン>'
モジュール名やバージョンはPuppet Forgeのモジュールページで確認できる。今回インストールする「mysql」モジュールの場合、モジュール名は「puppetlabs-mysql」、バージョンは「10.0.0」となっているので、次のように指定する。
mod 'puppetlabs-mysql', '10.0.0'"
bolt.yamlおよびPuppetfileの2つのファイルを用意したら、これらファイルが格納されているディレクトリで「bolt puppetfile install」コマンドを実行すると、そのディレクトリ以下に「modules」というディレクトリが作成され、そこに指定したモジュールがインストールされる。
$ bolt puppetfile install Successfully synced modules from /home/hylom/bolt/test03/Puppetfile to /home/hylom/bolt/test03/modules $ ls Puppetfile bolt.yaml modules $ ls modules mysql
この状態で「bolt task show」コマンドを実行すると、「mysql::export」および「mysql::sql」という2つのTaskが利用できるようになっていることが確認できる。
$ bolt task show facts Gather system facts mysql::export Allows you to backup your database to local file. mysql::sql Allows you to execute arbitary SQL package Manage and inspect the state of packages puppet_agent::install Install the Puppet agent package puppet_agent::version Get the version of the Puppet agent package installed. Returns nothing if none present. puppet_conf Inspect puppet agent configuration settings reboot Reboots a machine reboot::last_boot_time Gets the last boot time of a Linux or Windows system service Manage and inspect the state of services MODULEPATH: /home/hylom/bolt/test03/modules:/home/hylom/bolt/test03/site-modules:/home/hylom/bolt/test03/site Use `bolt task show <task-name>` to view details and parameters for a specific task.
mysql::sqlは指定したホストでSQLを実行するTaskで、「sql」というパラメータで実行するSQLを指定する。オプションで対象のデータベース名や使用するユーザー名およびパスワードを指定することも可能だ。
$ bolt task show mysql::sql mysql::sql - Allows you to execute arbitary SQL USAGE: bolt task run --nodes <node-name> mysql::sql database=<value> user=<value> password=<value> sql=<value> PARAMETERS: - database: Optional[String[1]] Database to connect to - user: Optional[String[1]] The user - password: Optional[String[1]] The password - sql: String[1] The SQL you want to execute MODULE: /home/hylom/bolt/test03/modules/mysql
また、mysql::exportはデータベースに格納されているデータをファイルに出力するTaskで、「file」パラメータで保存先ファイルを指定する。
$ bolt task show mysql::export mysql::export - Allows you to backup your database to local file. USAGE: bolt task run --nodes <node-name> mysql::export database=<value> user=<value> password=<value> file=<value> PARAMETERS: - database: Optional[String[1]] Database to connect to - user: Optional[String[1]] The user - password: Optional[String[1]] The password - file: String[1] Path to file you want backup to MODULE: /home/hylom/bolt/test03/modules/mysql
なお、Taskによっては操作対象のリモートホストにPuppetのエージェントがインストールされていることが前提となっている場合がある。ここでインストールしたmysqlモジュールもそうなっており、Puppetのエージェントがインストールされていない場合はエラーとなってしまう。
たとえば次の実行例は、指定したリモートホスト上で「show databases」というSQL文を実行するものだが、Puppetエージェントがインストールされていない場合次のようにランライムがない旨が表示されてエラーとなる。
$ bolt task run mysql::sql sql="show databases" -n 192.0.2.100 Started on 192.0.2.100... Failed on 192.0.2.100: The task failed with exit code 126: bash: /tmp/832e77d6-1aeb-4399-aed1-e6b9f3ece522/sql.rb: /opt/puppetlabs/puppet/bin/ruby: 誤ったインタプリタです: そのようなファイルやディレクトリはありません { } Failed on 1 node: 192.0.2.100 Ran on 1 node in 0.71 seconds
この場合、次のように「puppet_agent::install」というTaskを実行することで対象ホストにPuppetのエージェントをインストールできる。
$ bolt task run puppet_agent::install --run-as root --sudo-password -n 192.0.2.100
エージェントのインストール後に同じコマンドを実行すると、次のようにSQL文の実行結果が表示される。
$ bolt task run mysql::sql sql="show databases" -n 192.0.2.100 Started on 192.0.2.100... Finished on 192.0.2.100: { "status": "Database\ninformation_schema\ntest" } Successful on 1 node: 192.0.2.100 Ran on 1 node in 1.70 seconds
なお、Puppet Forgeは現状ではPuppet向けのモジュールの公開が主となっており、Boltで利用できるのはその一部のみだ。検索時に「With Tasks?」で「Yes」を指定するとBoltで利用できる(Taskが提供されている)モジュールのみを対象に検索できるのだが、記事執筆時点でTaskを提供しているモジュールは211個で、うち一定の品質を保証する「approved」もしくは「supported」タグが付けられているのは37個に留まっている(図3)。
独自にPlanやTaskを作成する
Boltで標準で提供されているTaskは、パッケージのインストール、サービスの管理などを行うものなどに限られている。スクリプトを実行する機能も用意されているため、これらだけでもある程度のシステム管理は可能ではあるものの、構成管理ツールの利点である、宣言的に設定作業を記述できる点を活かそうとするのであれば、現状では独自にPlanやTaskを作成していく必要がある。そこで以下では、独自のPlanやTaskを作成する方法を説明していく。
Boltが利用する「プロジェクト」ディレクトリ構造
Boltにおいては、使用する設定ファイルやTask、Planといったモジュールは「プロジェクト」と呼ばれる特定のディレクトリ構造下に配置しなければならない。boltコマンドの実行時には、まずこのプロジェクトディレクトリの探索が行われ、次のようにしてプロジェクトディレクトリとして認識する。
- 「--boltdir」オプションが指定された場合、このオプションで指定されたディレクトリがプロジェクトディレクトリとなる
- カレントディレクトリに「bolt.yaml」ファイルが存在する場合、カレントディレクトリがプロジェクトディレクトリとなる
- カレントディレクトリに「Boltdir」という名前のディレクトリが存在する場合、そのディレクトリがプロジェクトディレクトリとなる
- bolt.yamlファイルやBoltdirディレクトリが見つからなかった場合、親ディレクトリを順に辿って探索してbolt.yamlファイルが存在するディレクトリもしくはBoltdirという名前のディレクトリを探し、そのディレクトリをプロジェクトディレクトリとする
- ルートディレクトリまで辿ってもbolt.yamlファイルやBoltdirディレクトリが見つからなかった場合、ホームディレクトリ以下の.puppetlabs/boltディレクトリがプロジェクトディレクトリとなる
なお、bolt.yamlはboltコマンドの挙動を指定するファイルだ。指定できる内容についてはドキュメントを参照してほしいが、boltコマンドの実行時に指定できるオプションのほとんどがこの設定ファイル内に記述できるようになっている。
また、プロジェクトディレクトリには「inventory.yaml」というファイルを置くこともできる。このファイルでは、管理対象とするリモートホストにエイリアス(別名)を付けたり、複数のリモートホストをグループとして管理したりする設定を記述できる。詳しくはドキュメントを参照して欲しいが、たとえば次の例は、「192.0.2.110」と「192.0.2.100」の2つのホストを「servers」というエイリアスで参照できるように設定したものだ。
$ cat inventory.yaml groups: - name: servers nodes: - 192.0.2.110 - 192.0.2.100
設定したエイリアスは、boltコマンドの「-n」オプションなどでリモートホストを指定する際に利用できる。
$ bolt command run "echo hoge" -n servers Started on 192.0.2.100... Started on 192.0.2.110... Finished on 192.0.2.100: STDOUT: hoge Finished on 192.0.2.110: STDOUT: hoge Successful on 2 nodes: 192.0.2.110,192.0.2.100 Ran on 2 nodes in 0.37 seconds
モジュールのインストールに使用するPuppetfileファイルも、このプロジェクトディレクトリ内に配置するようになっている。さらに、「bolt task」コマンドや「bolt plan」コマンドの実行時、Boltはプロジェクトディレクトリ下の「modules」ディレクトリ内からモジュールを探索する。各モジュールディレクトリ内では、「tasks」ディレクトリ内にTaskを定義したファイルを、「plans」ディレクトリ内にPlanを定義したファイルを格納する。
Taskの作成
それでは、実際にTaskを作成してみよう。ここではTaskの例として、メモリやI/Oの使用状況を表示する「vmstat」コマンドと、デバイス毎のI/O状況を表示する「iostat」コマンドを実行してその結果を表示するというTaskを「stats」という名前で作成してみる。
まず、前述したプロジェクトディレクトリ構造に則ってTaskを格納するディレクトリを作成する。今回は「stats」という名称なので、プロジェクトディレクトリの「modules」ディレクトリ以下に「stats」というディレクトリを作成し、さらにその下に「tasks」ディレクトリを作成する。
$ mkdir -p Boltdir/modules/stats/tasks
続いて、このディレクトリ内に「init.json」と「init.sh」というファイルを作成する。
$ vi Boltdir/modules/stats/tasks/init.json $ vi Boltdir/modules/stats/tasks/init.sh
init.jsonはTaskのメタデータをJSON形式で記述するものだ。たとえばTaskの説明は「description」プロパティで指定できる。今回は次のような内容とした。
{ "description": "run vmstat and iostat" }
また、init.shはTaskの実行時に実行されるスクリプトとなる。今回は次のような内容とした。
#!/bin/sh vmstat echo "----" iostat
これらのファイルを作成後「bolt task show」コマンドを実行すると、「stats」というTaskが認識されていることが分かる。
$ bolt task show facts Gather system facts package Manage and inspect the state of packages puppet_agent::install Install the Puppet agent package puppet_agent::version Get the version of the Puppet agent package installed. Returns nothing if none present. puppet_conf Inspect puppet agent configuration settings reboot Reboots a machine reboot::last_boot_time Gets the last boot time of a Linux or Windows system service Manage and inspect the state of services stats run vmstat and iostat : :
「bolt task run」コマンドでこのTaskを実行すると、次のように指定したリモートホストでinit.shファイルが実行され、その結果が出力される。
$ bolt task run stats -n 192.0.2.110 Started on 192.0.2.110... Finished on 192.0.2.110: procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 2 0 264 340396 26648 533508 0 0 1 1 53 72 0 0 100 0 0 ---- Linux 3.10.0-957.5.1.el7.x86_64 (centos10) 2019年07月10日 _x86_64_ (1 CPU) avg-cpu: %user %nice %system %iowait %steal %idle 0.05 0.00 0.03 0.00 0.03 99.89 Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn vda 0.11 0.81 0.96 423707 502896 { } Successful on 1 node: 192.0.2.110 Ran on 1 node in 0.66 seconds
なお、ここではシェルスクリプトでTaskを実装しているが、Taskの実装には任意の言語が利用可能だ。その場合、ファイルの拡張子は任意のものに変更できる。たとえばPythonでTaskを実装した場合、ファイル名は「init.py」とすれば良い。
また、1つのモジュールに複数のTaskを定義することもできる。その場合、スクリプトファイル名には任意のものが使用可能だ。そのファイル名の拡張子を除いたものがTask名となり、それに拡張子「.json」を付けたものがそのTaskのメタデータを記載するファイルとなる。また、boltコマンドでそのTaskを指定する場合は「<モジュール名>::<Task名>」という形で指定する。
たとえば、「vmstat.sh」という名前でTaskを実装した場合、メタデータは「vmstat.json」というファイルで指定し、このTaskを実行する場合は次のように指定する。
$ bolt task run stats::vmstat -n 192.0.2.110
Planの作成
Planは、実行する1つ以上のTaskをまとめて定義したものだ。これを利用することで、複数のTaskを1回のコマンドでまとめて実行できる。
PlanはRuby言語をベースとしたDSL(ドメイン特化言語)である「Puppet言語」、もしくはYAML形式で記述する。ただし、YAMLによる記述はベータ機能で今後仕様が変更される可能性があるとのことなので、今回はDSLによる記述についてのみ説明しておく。YAMLでの記述についてはドキュメントを参照してほしい。
Puppet言語でPlanを記述する場合、ファイル名は「init.pp」もしくは「<Plan名>.pp」となり、モジュールディレクトリ下の「plans」ディレクトリ以下に配置する。Planの基本的なフォーマットは次のようになる。
plan <モジュール名>::<Plan名>( TargetSpec $<パラメータ1>, TargetSpec $<パラメータ2>, : : ) { run_task('<Task名>', <対象ノード>, <パラメータ>) : : }
Taskの場合と同様、boltコマンドではファイル名が「init.pp」だった場合はモジュール名、「<Plan名>.pp」だった場合は「<モジュール名>::<Plan名>」でPlanを指定する。
たとえば次の例は、「update_package」というモジュールで提供されるPlanを作成するものだ。このPlanでは「package」Taskと「service」Taskを使ってパッケージのアップデートとサービスの再起動を実行するという書類を実行する。
まず、モジュールを格納する「update_package」ディレクトリを作成する。
$ mkdir -p Boltdir/modules/update_package
続いてこのディレクトリ下にPlanの設定ファイルを格納する「plans」ディレクトリを作成する。
$ mkdir Boltdir/modules/update_package/plans
今回はモジュール内に1つのPlanのみを作成するので、「init.pp」というファイルでPlanを定義する。
$ vi Boltdir/modules/update_package/plans/init.pp
init.ppファイルの内容は次のようになる。
↓「update_package」というPlan名でPlanを定義する plan update_package ( ↓「nodes」、「package_name」、「service_name」という3つのパラメータを受け取ることを宣言する TargetSpec $nodes, TargetSpec $package_name, TargetSpec $service_name, ) { ↓「nodes」パラメータで指定されたノードに対し、「package」Taskを実行する。 このTaskの「action」パラメータには「upgrade」を、「name」パラメータには「package_name」パラメータで指定された値を与える run_task('package', $nodes, { 'action' => 'upgrade', 'name' => $package_name }) ↓「nodes」パラメータで指定されたノードに対し、「service」Taskを実行する。 このTaskの「action」パラメータには「restart」を、「name」パラメータには「service_name」パラメータで指定された値を与える run_task('service', $nodes, { 'action' => 'restart', 'name' => $service_name }) }
ここでは、「update_package」という名前のPlanを定義している。このPlanは「nodes」および「package_name」、「service_name」の3つのパラメータを取り、これらで指定された値を使ってパッケージのアップグレードとサービスのリスタートを実行するようになっている。
以上でPlanの作成は完了だ。「bolt plan show」コマンドを実行すると、このPlanが認識されていることが確認できる。
$ bolt plan show aggregate::count aggregate::nodes canary facts facts::info puppetdb_fact reboot update_package MODULEPATH: /home/hylom/bolt/test02/Boltdir/modules:/home/hylom/bolt/test02/Boltdir/site-modules:/home/hylom/bolt/test02/Boltdir/site Use `bolt plan show <plan-name>` to view details and parameters for a specific plan.
$ bolt plan show update_package update_package USAGE: bolt plan run update_package nodes=<value> package_name=<value> service_name=<value> PARAMETERS: - nodes: TargetSpec - package_name: TargetSpec - service_name: TargetSpec MODULE: /home/hylom/bolt/test02/Boltdir/modules/update_package
また、「bolt plan run」コマンドでこのPlanを実行できる。
$ bolt plan run update_package -n 192.0.2.110 package_name=httpd service_name=httpd --run-as root --sudo-password Please enter your privilege escalation password: Starting: plan update_package Starting: task package on 192.0.2.110 Finished: task package with 0 failures in 7.48 sec Starting: task service on 192.0.2.110 Finished: task service with 0 failures in 1.89 sec Finished: plan update_package in 9.4 sec Plan completed successfully with no result
今後の周辺環境の発展に期待
前述のとおり、構成管理自動化ツール分野でAnsibleが人気なのは設定がシンプルで、簡潔に設定を記述できるという点が大きい。Puppetはそれと比較すると事前準備や設定の記述に手間がかかるということで、それを解消するためにBoltが開発されたと思われる。実際、単にコマンドやスクリプトをリモートホスト上で実行したり、パッケージのインストールやサービスの管理を行ったりするだけであれば、Boltは簡単に利用できる。
一方で、それ以上のことをやろうとすると現時点ではやや手間がかかってしまうというのが現状だ。公開されているTaskはまだ少なく、またTaskやPlanの記述を作成する場合、ディレクトリ構造やファイル名などのルールに従わなければならない。また、一部のTaskの利用にはPuppetのエージェントが必要な点もマイナスポイントだろう。
ただ、すでにPuppetを利用した構成管理を利用しているのであれば、Boltはそれと組み合わせて利用するツールとして有用だ。boltコマンド経由でPuppetエージェントをインストールすることもできるし、ディレクトリ構造などのルールはPuppetのものと同じだ。
また、今後Puppetのエージェントが不要なTaskが多く公開されるようになれば、簡単に使えて強力な構成管理自動化ツールとなる可能性もある。今後の発展に期待したい。