ChefでCentOS7+OpenStack(Kilo)を構築する


OpenStack Advent Calendar 2015　の12/7分の記事です。

## なぜChef?
CentOSならPackstackの方がお手軽だと思いますが、たまたま自分が使っていた構成管理ツールがChefであり、コミュニティのCookbookが既にあり導入の敷居が低いかなと思っただけです。AnsibleなどもコミュニティのPlaybookがあるのでこれから構築するという人は自分に適したツールを選択していただければと思います。

## 構成
今回作業したマシン構成は以下の通りです。
### 作業用マシン
* Mac OSX 10.10

### 構築対象マシン
* CentOS7.1 (Controller兼Network)
* CentOS7.1 (Compute)

## 構築準備
### ChefDKのインストール
構築対象のマシンとは別にChefのCookbookなどをダウンロードする作業用マシンにChefDK (https://downloads.chef.io/chef-dk/) をインストールします。ChefDKはChefDeveloperKitの略で、CookBookの開発に必要なツール類が含まれており、Rubyもバンドルされているので便利です。また、色んなプラットフォーム向けに用意されているのも嬉しいです。

### Cookbookの取得
OpenStackのCookbookを使います。ブランチでバージョンが分かれているので構築したいバージョンのブランチをクローンし、必要なCookbookも合わせてダウンロードします。

```
$ git clone -b stable/kilo https://github.com/openstack/openstack-chef-repo.git
$ cd openstack-chef-repo
$ chef exec rake berks_vendor
```

### chefのインストール
構築対象のマシンにchefをインストールしておきます。パッケージからインストールする場合は、公式( https://downloads.chef.io/chef-client/ )にパッケージファイルがあります。

## 構築手順

### ノード構成の決定
OpenStackのノード構成を決めます。今回は、Controller兼networkとcomputeの2台構成でいきます。上記のCookBookはVagrantで仮想マシンも準備しますが今回は事前に準備しているマシンに適用する方法でいきます。

### パラメータの編集
構築するOpenStackのパラメータを(必要があれば)編集します。
ChefにはEnvironmentというcookbookのattributeを上書きするための仕組みがあるため、そのファイルを編集します。environmentsフォルダ配下の既存ファイルを参考に新しい kilo-centos7.json というファイルを作成します。
修正したいパラメータのattributeは各cookbookを参照してください。
以下に今回使ったサンプルを記載します。

```~/openstack-chef-repo/environments/kilo-centos7.json
{
  "name": "kilo-centos7",
  "chef_type": "environment",
  "cookbook_versions": {},
  "json_class": "Chef::Environment",
  "override_attributes": {
    "openstack": {
      "yum": {
        "rdo_delorean_enabled": false
      },
      "endpoints": {
        "bind-host": "0.0.0.0",
        "host": "0.0.0.0",
        "identity-bind": {
          "host": "0.0.0.0"
        }   
      },
      "mq": {
        "user": "admin"
      },
      "network": {
        "service_plugins": [
          "neutron.services.l3_router.l3_router_plugin.L3RouterPlugin"],
        "dhcp": {
          "enable_isolated_metadata": True
        },
        "l3": {
          "external_network_bridge_interface": "enp0s8"
        }
      },
      "block-storage": {
        "volume": {
          "create_volume_group": true,
          "default_volume_type": "lvm"
        }
      },
      "image": {
        "image_upload": false
      },
      "compute": {
        "enabled_apis": "ec2,osapi_compute",
        "libvirt": {
          "virt_type": "qemu"
        },
        "network": {
          "public_interface": "enp0s10",
          "service_type": "neutron"
        }
      }
    }
  }
}
```


### Chef-provisionで利用するファイルを作成
今回はChef-ServerやChef-Soloではなく、chef-provisioningとchef-provisioning-sshを利用します。これはrubyのライブラリとして提供されており、定義ファイルにマシン構成を記述するとssh経由でcookbookが適用できるというものでお手軽にリモートのマシンに対してcookbookを試すことができます。リポジトリ直下に以下のような感じで作成します。

```~/openstack-chef-repo/kilo-centos7.rb
require 'chef/provisioning'
require 'chef/provisioning/ssh_driver'

with_driver 'ssh'

env = kilo_centos7

machine "controller" do
  machine_options :transport_options => {
    'ip_address' => '192.168.1.11',
    'username' => 'vagrant',
    'ssh_options' => {
      :keys => ['/home/stake/.ssh/key.pem']
      }
    }
  converge true
end

machine "compute" do
  machine_options :transport_options => {
    'ip_address' => '192.168.1.101',
    'username' => 'vagrant',
    'ssh_options' => {
      :keys => ['/home/stake/.ssh/key.pem']
    }
  }
  converge true
end

```

chef-provisioning-sshはChefDKに含まれないので個別にインストールが必要です。

```
$ chef gem install chef-provisioning-ssh
```


## Roleの適用
ノード構成が決まったら上記の定義ファイルに適用するレシピを記述していきます。
OpenStackのCookBookは個別にレシピを適用するのではなく、役割毎にロールが分かれていて、必要なレシピはそのRoleに含まれています。例えば、Keystoneをインストールしたければ、`role 'os-identity'`を適用するといった感じです。
詳しくはリポジトリ直下にあるRolesフォルダの各種jsonファイルを参照してください。
上記のファイルに今回の構成を考慮してRoleを追加すると以下のようになります。

```~/openstack-chef-repo/kilo-centos7.rb
require 'chef/provisioning'
require 'chef/provisioning/ssh_driver'

with_driver 'ssh'

env = 'kilo-centos7'

machine 'controller' do
  machine_options :transport_options => {
    :ip_address => '192.168.1.11',
    :username => 'vagrant',
    :ssh_options => {
      :keys => ['/home/stake/.ssh/key.pem']
    }
  }
  role 'os-base'
  role 'os-client'
  role 'os-ops-caching'
  role 'os-ops-database'
  recipe 'openstack-ops-database::openstack-db'
  role 'os-ops-messaging'
  role 'os-identity'
  role 'os-image'
  role 'os-network'
  role 'os-dashboard'
  role 'os-compute-setup'
  role 'os-compute-conductor'
  role 'os-compute-scheduler'
  role 'os-compute-api'
  role 'os-compute-cert'
  role 'os-compute-vncproxy'
  role 'os-block-storage'
  chef_environment env
  file('/etc/chef/openstack_data_bag_secret',
    "#{File.dirname(__FILE__)}/.chef/encrypted_data_bag_secret")
  converge true
end

machine 'compute' do
  machine_options :transport_options => {
    :ip_address => '192.168.1.101',
    :username => 'vagrant',
    :ssh_options => {
      :keys => ['/home/stake/.ssh/key.pem']
    }
  }
  role 'os-compute-worker'
  chef_environment env
  file('/etc/chef/openstack_data_bag_secret',
    "#{File.dirname(__FILE__)}/.chef/encrypted_data_bag_secret")
  converge true
end

```

個人的にこのファイルがvagrantfileっぽくて好きです。

### レシピ適用
上記のファイルの作成ができたら作業用マシンから以下のコマンドを実行してレシピを適用します。
ログが大量に流れて時間も結構かかりますが、これだけでOpenStack環境が構築できます。

```
$ chef-client -z kilo-centos7.rb --chef-zero-port 8899
```


## よく設定変更しそうなところ

### パスワード
openstack-chef-repoのREADMEに書いていますが、デフォルトは全て'mypass'になっています。
例えば新しくopenstackというユーザを利用したい場合は、以下のようにパスワードを設定してください。

```
$ export editor=vi
$ knife solo data bag create user_passwords openstack --secret-file .chef/encrypted_data_bag_secret
```

各コンポーネントのDB接続ユーザなども変更可能です。そのときは、user_passwordsとopenstackの部分を適宜変更してください。

### RabbitMQのadminアカウント
よくみる構築手順ではopenstackというユーザ名で構築することが多いですが、デフォルトではadminという名前で作成されます。変更したい場合は、`node['openstack']['mq']['user']`を変更してください。ただし、作成したユーザのパスワードは上記のようにdatabagsで作成してください。


### endpointの設定
複数のNICがあり、各コンポーネントのendpointを変更したいときはenvironmentで以下のように行います。
Firewall用のCookbookを作成するときもこのパラメータを参照すればいいので設定が集約されて便利です。

```
{
  "block-storage-api": {
    "host": "controller",
    "port": "8776"
  }
}
```



## その他注意点

### 参照先のRDOリポジトリ
デフォルトのリポジトリだとgpgkeyが見つからないエラーが出ます。`node['openstack']['yum']['gpgcheck']`をfalseに設定するか、適切な参照先を設定します。

### cinderのバックエンドをLVMで構築するとき
cinder-volumeを乗せるサーバにcinder-volumesという名前でVGを作っておいてください。