はのちゃ爆発

はのちゃが技術ネタとか日常のこととかを書いてます。

Knife-ZeroでVagrant仮想マシンのプロビジョニングをしてみた話

はじめに

以前からChefを使いたい欲は高かったのですが、 Chefってなかなか最初の導入までのハードルが高いと思うのは私だけでしょうか。

本来はChef ServerとChef Clientを用意してあげなきゃいけない、とか、
Chef-soloとかもあるけど今後は使わないでねって公式ブログ で言われてたりとか、
chef-clientが流行ってるみたいだけど、リモートノードの管理ができなかったりとか。

そこで便利なものがあります。Knife-Zeroです。

knife-zero とは

Knife-ZeroはChefのプラグインです。特徴はだいたい次のとおり。

  • SSHポートフォワードでChef-Zeroに接続して、必要なCookbookだけ転送します。

  • Nodeオブジェクトをローカル保存します。

  • Chef-Server/Client環境の機能をつかえます。

  • ただしenterprise addonは除きます。

Chef-Zeroというものもありますが、別物らしいです。私は最初混同してました。

ざっくり言うと、手軽にリモートのマシンに対してChef使えるようにするツール、といったところでしょうか。
実際、とても手軽にリモートマシンに対してChefを使えるようになります。

Knife-Zero を使ってみる

では早速 Knife-Zero を使ってみましょう。

Chef-DKを導入する

Knife-ZeroはChefのプラグインなので、Chefをまず用意する必要があります。 今回はChef-DKを入れることでChefのインストールを行います。

環境に応じてインストール方法は異なりますが、どの環境でも標準的なソフトウェアのインストール方法で入れられると思います。 Windowsなら通常のインストーラMacインストーラもしくはbrew caskでも可。RHEPはrpm

導入が終わったらターミナルでchef -vなどと打ってインストールできているのか確認しておきましょう。

Knife-Zeroを導入する

Knife-Zeroはgemとして作られているので、gem install...でインストールできます。

Rubyが(比較的)簡単に扱えるMac(Unix)/Linux環境であれば直接インストールでもいいですが、 今回はWindows環境と操作方法を合わせたいことや、Knife-ZeroがChefに依存したツールであることなどから、 Chef内部にインストールするようにします。

以下の様なコマンドでインストールできます。

$ chef gem install knife-zero

Knife-Zero でリモートマシンにChefを入れる

今回はVagrant仮想マシンに対してKnife-Zeroを使いますが、Vagrantについての説明はここでは行いません。 以下の手順では、以下の要件を満たしたVagrant仮想マシンを作成し、起動しているものとして進めます。

  • 192.168.33.10 を仮想マシンに割り当てている
    • config.vm.network "private_network", ip: "192.168.33.10"
  • boxとしてcentos/7を使用する
    • config.vm.box = "centos/7"

まず、適当な作業ディレクトリを作成します。server-hogeのようなディレクトリでいいでしょう。 次に、Knife-Zeroの設定ファイルであるknife.rbを作業ディレクトリ直下に作成します。

local_mode true
chef_repo_path File.expand_path('../', __FILE__)

knife[:use_sudo] = true

knife[:automatic_attribute_whitelist] = %w[
  os
  os_version
  hostname
  ipaddress
  roles
  recipes
  ipaddress
  platform
  platform_version
  cloud
  cloud_v2
  chef_packages
]

なんとなく意味はわかると思いますが、とりあえず書いておくと便利、と思っていただければいいかと思います。

knife.rbを作成したら、いよいよKnife-Zeroにいきます。

が、その前に、Vagrantマシンにssh接続できるよう、~/.ssh/configVagrant仮想マシンsshで接続するための設定を追加します。 設定は人によって若干異なるかもしれませんが、以下の様なHostを追加すればいいかと思います。

Host test-server
  HostName  192.168.33.10
  Port  22
  IdentityFile  {vagrantのprivate_keyの場所}
  User vagrant

ちなみにこの設定はなくてもなんとかなったりします。 が、Vagrant以外の、他のVPSなどに対してChef-Zeroを使う時と同じ方法で進めていきたいので、このような方法をとっています。

準備ができたら、以下のコマンドを実行します。

$ chef exec knife zero bootstrap test-server --node-name {好きなノード名}

このコマンドで、~/.ssh/configにtest-serverとして登録されている設定を使って仮想マシンssh接続し、 仮想マシン上にChef-Clientをインストールするなどの初期設定が行われます。

--node-nameオプションは無くても大丈夫ですが、 ノードに名前を付けておいたほうが後々の作業等がやりやすいので、付けておきましょう。 (オプションがないとlocalhostというノード名になる…?はず。)

Knife-Zeroで管理しているノードを確認する

上記のbootstrapを行うと、bootstrapを行った対象マシン(ノード)の情報が生成されます。 この情報はnodes/{ノード名}.jsonというファイルに格納されます。

また、現在管理下にあるnodeの一覧は以下のコマンドで見ることが出来ます。

$ chef exec knife node list

ノードの詳細情報を見る場合は以下のコマンドを使います。

$ chef exec knife node show {ノード名}

Node Name:   {ノード名}
Environment: _default
FQDN:
IP:          10.0.2.15
Run List:
Roles:
Recipes:
Platform:    centos 7.2.1511
Tags:

Knife-Zeroを使って仮想マシンでChef-Clientを動かす

管理対象ノードが追加されていることを確認したら、Chef(Chef-Client)を仮想マシン上で動かしてみます。 以下のコマンドを叩いてみます。

$ chef exec knife zero converge 'name:*'

chef knife zero converge QUERYというコマンドで、QUERYで指定されたノードのChef-Clientを実行できます。

QUERYが急に出てきますが、これはChef-Clientを実行したい対象ノードを検索、絞り込むために使う検索クエリです。

対象Nodeはクエリ結果で絞込みます。クエリの書式はknife searchのSEARCH_QUERYと同一です。

(Knife-Zero公式サイトより引用)

複数ノードを管理するときに便利ですが、単一、少数のノードを扱っている時はあまり意識しません。

とりあえず管理対象ノード全てでChefしたい場合は'name:*'などと指定しておけばいいと思います。 もっと厳密に指定したいなら'name:{ノード名}などが適切かもしれません。

さて、実行してみましたが、Vagrant仮想マシンのノードに対して初期状態のままconvergeすると失敗します。

FATAL: 1 node found, but does not have the required attribute to establish the connection. Try setting another attribute to open the connection using --attribute.

knife.rbの設定で、fqdnknife[:automatic_attribute_whitelist]から外しているので、 接続に必要な情報が足りない、と怒られます。

本来はfqdnknife.rbに含めたいのですが、Vagrant仮想マシンだと上手く行かなくなる原因になります。 (少なくとも初期状態の仮想マシンでは。) Knife-ZeroはVagrantとの相性があまりよくないとのことで、ノード設定ファイルに修正が必要です。

自動生成されたファイルは以下のようなものになっています。

{
  "name": "test-server",
  "normal": {
    "knife_zero": {
      "host": "{ホスト名}"
    },
    "tags": [

    ]
  },
  "automatic": {
    "os": "linux",
    "os_version": "3.10.0-327.18.2.el7.x86_64",
    "hostname": "localhost",
    "ipaddress": "10.0.2.15",
    "roles": [

    ],
    "recipes": [

    ],
    "platform": "centos",
    "platform_version": "7.2.1511",
    "cloud_v2": null,
    "chef_packages": {
      "ohai": {
        "version": "8.17.0",
        "ohai_root": "/opt/chef/embedded/lib/ruby/gems/2.1.0/gems/ohai-8.17.0/lib/ohai"
      },
      "chef": {
        "version": "12.12.13",
        "chef_root": "/opt/chef/embedded/lib/ruby/gems/2.1.0/gems/chef-12.12.13/lib"
      }
    }
  }
}

この中にfqdnの値を入れてあげる必要があります。 今回は"normal"以下に"fqdn"キーを作り、値を.ssh/configにあるHost名に書き換えます。今回の例ならtest-serverです。 これで正常にconvergeできるようになります。

書き換えて、再度convergeしてみます。

test-server Starting Chef Client, version 12.12.13
test-server resolving cookbooks for run list: []
test-server Synchronizing Cookbooks:
test-server Installing Cookbook Gems:
test-server Compiling Cookbooks...
test-server [2016-07-07T09:03:45-04:00] WARN: Node test-server has an empty run list.
test-server Converging 0 resources
test-server [2016-07-07T09:03:45-04:00] WARN: Could not find whitelist attribute cloud.
test-server
test-server Running handlers:
test-server Running handlers complete
test-server Chef Client finished, 0/0 resources updated in 04 seconds

このようなログが出力され、Chef-Clientが実行されました。 まだ何もChefのcookbookがないので、特に何も実行されずに終了します。

※ バグなのか何なのかは分かりませんが、run_listがない状態でconvergeすると、 なぜかノードのfqdnの値がもとのlocalhostに戻ってしまいます。

Cookbookを追加してChef-Clientを実行してみる

ここまでで、Knife-Zeroを使ってVagrant仮想マシン上でChef-Clientを実行することができるようになりました。

しかし、Chefを使っているのになんのCookbookも適用していないのではあんまりなので、試しにVimでも入れてみましょう。

レシピをどこかから持ってきてもいいのですが、簡単なレシピなのでさくっと作ってしまいましょう。 今回はknifeでレシピを作ります。

$ chef exec knife cookbook create vim

色々とファイルができますが、メインとなるのはcookbooks/vim/recipes/default.rbです。 ここにVimをインストールする設定を書きます。

#
# Cookbook Name:: vim
# Recipe:: default
#
# Copyright 2016, YOUR_COMPANY_NAME
#
# All rights reserved - Do Not Redistribute
#

package 'vim'

レシピを作ったら、レシピを実行対象として追加します。

$ chef exec knife node run_list add ノード名 vim

これでVim cookbookがランリストに追加されたので、再度convergeします。

$ chef exec knife zero converge 'name:*'

以下の様なログが出て、Vim仮想マシンにインストールされたら成功です!

test-server Starting Chef Client, version 12.12.13
test-server resolving cookbooks for run list: ["vim"]
test-server Synchronizing Cookbooks:
test-server   - vim (0.1.0)
test-server Installing Cookbook Gems:
test-server Compiling Cookbooks...
test-server Converging 1 resources
test-server Recipe: vim::default
test-server   * yum_package[vim] action install
test-server     - install version 7.4.160-1.el7 of package vim-enhanced
test-server [2016-07-08T00:15:53-04:00] WARN: Could not find whitelist attribute cloud.
test-server
test-server Running handlers:
test-server Running handlers complete
test-server Chef Client finished, 1/1 resources updated in 57 seconds

おわりに

Knife-Zeroを使ってVagrant仮想マシンにリモートでChef-Clientをインストール、実行することができました。 また、実行させたいcookbookを追加して、仮想マシンVimをインストールすることもできました。

このように、Knife-Zeroを使うことで、とても簡単にChefを扱うことができるようになりました。 今回はVagrant仮想マシンでしたが、AWSやその他のVPSなどに対しても、 ほぼ同様の手順でKnife-Zeroを使うことができると思います。素敵ですね。

今後はAWS、Azureなどに立ち上げた仮想マシンにKnife-Zeroを使ってみようと思います。