Knife-ZeroでOpenStack Kiloデプロイ(複数台編)

こんにちは。@jedipunkz です。

前回 OpenStack Kilo のオールインワン構成を Chef-Zero を使ってデプロイする方法 を書きましたが、複数台構成についても調べたので結果をまとめていきます。

使うのは openstack/openstack-chef-repo です。下記の URL にあります。

https://github.com/openstack/openstack-chef-repo

この中に Vagrant を使ったファイルが存在しますが、実機でのデプロイには全く役に 立ちません。自分で Environment ファイルを作成する必要があります。今回は前提の 構成を作って、それに合わせた Environment ファイルを記します。ほぼスタンダード な構成にしましたので、自分の環境に合わせて修正するのも比較的簡単だと想います。 参考にしてください。

今回は knife-zero を使ってデプロイします。Chef サーバが必要なく、knife-zero を 使うホスト上のオンメモリで Chef サーバが稼働するので準備がほとんど必要ありません。

早速ですが、構成と準備・そしてデプロイ作業を記していきます。

前提の構成

   +------------+
   | GW Router  |
+--+------------+
|  |
|  +--------------+--------------+---------------------------- public network
|  | eth0         | eth0
|  +------------+ +------------+ +------------+ +------------+
|  | Controller | |  Network   | |  Compute   | | Knife-Zero | 
|  +------------+ +-------+----+ +------+-----+ +------------+
|  | eth1         | eth1  |      | eth1 |       | eth1 
+--+--------------+-------)------+------)-------+------------- api/management network
                          | eth2        | eth2
                          +-------------+--------------------- guest network

特徴としては…

  • public, api/management, guest の3つのネットワークに接続された OpenStack ホスト
  • Controller, Network, Compute の最小複数台構成
  • knife-zero を実行する ‘Knife-Zero’ ホスト
  • Knife-zero ホストは api/management network のみに接続で可
  • デプロイは api/management network を介して行う
  • public, api/management network はインターネットへの疎通が必須
  • OS は Ubuntu 14.04 amd64

とくに api/management network がインターネットへの疎通が必要なところに注意して ください。デプロイは knife-zero ホストで実行しますが、各ノードへログインしデプ ロイする際にインターネット上からパッケージの取得を試みます。

また api/management network を2つに分離するのも一般的ですが、ここでは一本にま とめています。

IP アドレス

IP アドレスは下記を前提にします。

interface IP addr
Controller eth0 10.0.1.10
Controller eth1 10.0.2.10
Network eth0 10.0.1.11
Network eth1 10.0.2.11
Network eth2 10.0.3.11
Compute eth1 10.0.2.12
Compute eth2 10.0.3.12
Knife-Zero eth1 10.0.2.13

ネットワークインターフェース設定

それぞれのホストで下記のようにネットワークインターフェースを設定します。

  • Controller ホスト

eth0, 1 を使用します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
auto eth0
iface eth0 inet static
    address 10.0.1.10
    netmask 255.255.255.0
    gateway 10.0.1.254
    dns-nameservers 8.8.8.8
    dns-search jedihub.com

auto eth1
iface eth1 inet static
    address 10.0.2.10
    netmask 255.255.255.0

auto eth2
iface eth2 inet manual
  • Network ホスト

eth0, 1, 2 全てを使用します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
auto eth0
iface eth0 inet static
        up ifconfig $IFACE 0.0.0.0 up
        up ip link set $IFACE promisc on
        down ip link set $IFACE promisc off
        down ifconfig $IFACE down
        address 10.0.1.11
        netmask 255.255.255.0

auto eth1
iface eth1 inet static
        address 10.0.2.11
        netmask 255.255.255.0
        gateway 10.0.2.248
        dns-nameservers 8.8.8.8
        dns-search jedihub.com

auto eth2
iface eth2 inet static
        address 10.0.3.11
        netmask 255.255.255.0
  • Compute ホスト

eth1, 2 を使用します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
auto eth0
iface eth0 inet manual

auto eth1
iface eth1 inet static
        address 10.0.2.12
        netmask 255.255.255.0
        gateway 10.0.2.248
        dns-nameservers 8.8.8.8
        dns-search jedihub.com

auto eth2
iface eth2 inet static
        address 10.0.3.12
        netmask 255.255.255.0

これらの作業は knife-zero からログインし eth1 を介して行ってください。でないと 接続が切断される可能性があります。

準備

knife-zero ホストに chef, knife-zero, berkshelf が入っている必要があるので、こ こでインストールしていきます。

knife-zero ホストに chef をインストールします。Omnibus パッケージを使って手っ 取り早く環境を整えます。

1
2
sudo -i
curl -L https://www.opscode.com/chef/install.sh | bash

Berkshelf をインストールするのに必要なソフトウェアをインストールします。

1
apt-get -y install build-essential zlib1g-dev libssl-dev libreadline-dev ruby-dev libxml2-dev libxslt-dev g++

Berkshelf をインストールします。

1
/opt/chef/embedded/bin/gem install berkshelf --no-ri --no-rdoc

最後に knife-zero をインストールします。

1
/opt/chef/embedded/bin/gem install knife-zero --no-ri --no-rdoc

デプロイ作業

それでは openstack-chef-repo を取得してデプロイの準備を行います。 ブランチの指定は行わず master ブランチを取得します。Kilo は master ブランチで 管理されています。次のバージョンの開発が始まるタイミングで ‘stable/kilo’ ブラ ンチに管理が移されます。

1
2
3
sudo -i
cd ~/
git clone https://github.com/openstack/openstack-chef-repo.git

次に Berkshelf を使って必要な Cookbooks をダウンロードします。

1
2
cd ~/openstack-chef-repo
/opt/chef/embedded/bin/berks vendor ./cookbooks

Environment を作成します。これは各環境に合わせた設定ファイルのようなもので、各 Cookbooks の Attributes を上書きする仕組みになっています。下記の内容を

1
openstack-chef-repo/environments/multi-neutron-kilo.json

というファイル名で保存してください。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
{
  "name": "multi-neutron-kilo",
  "description": "test",
  "cookbook_versions": {
  },
  "json_class": "Chef::Environment",
  "chef_type": "environment",
  "default_attributes": {
  },
  "override_attributes": {
    "mysql": {
      "bind_address": "0.0.0.0",
      "server_root_password": "mysqlroot",
      "server_debian_password": "mysqlroot",
      "server_repl_password": "mysqlroot",
      "allow_remote_root": true,
      "root_network_acl": ["10.0.0.0/8"]
    },
    "rabbitmq": {
      "address": "0.0.0.0",
      "port": "5672",
      "loopback_users": []
    },
    "openstack": {
      "auth": {
        "validate_certs": false
      },
      "dashboard": {
        "session_backend": "file"
      },
      "block-storage": {
        "syslog": {
          "use": false
        },
        "api": {
          "ratelimit": "False"
        },
        "debug": true,
        "image_api_chef_role": "os-image",
        "identity_service_chef_role": "os-identity",
        "rabbit_server_chef_role": "os-ops-messaging"
      },
      "compute": {
        "rabbit": {
          "host": "10.0.2.10"
        },
        "novnc_proxy": {
          "bind_interface": "eth1"
        },
        "libvirt": {
          "virt_type": "qemu",
          "bind_interface": "eth1"
        },
        "novnc_proxy": {
          "bind_interface": "eth1"
        },
        "xvpvnc_proxy": {
          "bind_interface": "eth1"
        },
        "image_api_chef_role": "os-image",
        "identity_service_chef_role": "os-identity",
        "nova_setup_chef_role": "os-compute-api",
        "rabbit_server_chef_role": "os-ops-messaging",
        "network": {
          "public_interface": "eth1",
          "service_type": "neutron"
        }
      },
      "network": {
        "debug": "True",
        "dhcp": {
          "enable_isolated_metadata": "True"
        },
        "metadata": {
          "nova_metadata_ip": "10.0.2.10"
        },
        "openvswitch": {
          "tunnel_id_ranges": "1:1000",
          "enable_tunneling": "True",
          "tenant_network_type": "gre",
          "tunnel_types": "gre",
          "tunnel_type": "gre",
          "bridge_mappings": "physnet1:br-eth2",
          "bridge_mapping_interface": "br-eth2:eth2"
        },
        "ml2": {
          "tenant_network_types": "gre",
          "mechanism_drivers": "openvswitch",
          "tunnel_id_ranges": "1:1000",
          "enable_security_group": "True"
        },
        "api": {
          "bind_interface": "eth1"
        },
        "l3": {
          "external_network_bridge_interface": "eth0"
        },
        "service_plugins": ["neutron.services.l3_router.l3_router_plugin.L3RouterPlugin"]
      },
      "db": {
        "bind_interface": "eth1",
        "compute": {
          "host": "10.0.2.10"
        },
        "identity": {
          "host": "10.0.2.10"
        },
        "image": {
          "host": "10.0.2.10"
        },
        "network": {
          "host": "10.0.2.10"
        },
        "volume": {
          "host": "10.0.2.10"
        },
        "dashboard": {
          "host": "10.0.2.10"
        },
        "telemetry": {
          "host": "10.0.2.10"
        },
        "orchestration": {
          "host": "10.0.2.10"
        }
      },
      "developer_mode": true,
      "endpoints": {
        "network-openvswitch": {
          "bind_interface": "eth1"
        },
        "compute-api-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8774"
        },
        "compute-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8774"
        },
        "compute-ec2-admin-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8773"
        },
        "compute-ec2-admin": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8773"
        },
       "compute-ec2-api-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8773"
        },
        "compute-ec2-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8773"
        },
        "compute-xvpvnc": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "6081"
        },
        "compute-novnc-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "6080"
        },
        "compute-novnc": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "6080"
        },
        "compute-vnc": {
          "host": "0.0.0.0",
          "scheme": "http",
          "port": "6080"
        },
        "image-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "9292"
        },
        "image-api-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "9292"
        },
        "image-registry": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "9191"
        },
        "image-registry-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "9191"
        },
        "identity-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "5000"
        },
        "identity-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "5000"
        },
        "identity-admin": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "35357"
        },
        "identity-internal": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "35357"
        },
        "volume-api-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8776"
        },
        "volume-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8776"
        },
        "telemetry-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8777"
        },
        "network-api-bind": {
          "host": "10.0.2.11",
          "scheme": "http",
          "port": "9696"
        },
        "network-api": {
          "host": "10.0.2.11,
          "scheme": "http",
          "port": "9696"
        },
        "block-storage-api-bind": {
          "host": "10.0.2.10",
          "port": "8776",
          "bind_interface": "eth1"
        },
        "block-storage-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8776"
        },
        "orchestration-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8004"
        },
        "orchestration-api-cfn": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8000"
        },
        "db": {
          "host": "0.0.0.0",
          "port": "3306"
        },
        "bind-host": "0.0.0.0"
      },
      "identity": {
        "admin_user": "admin",
        "bind_interface": "eth1",
        "debug": true
      },
      "image": {
        "api": {
          "bind_interface": "eth1"
        },
        "debug": true,
        "identity_service_chef_role": "os-identity",
        "rabbit_server_chef_role": "os-ops-messaging",
        "registry": {
          "bind_interface": "eth1"
        },
        "syslog": {
          "use": false
        }
      },
      "mq": {
        "bind_interface": "eth1",
        "host": "10.0.2.10",
        "user": "guest",
        "vhost": "/nova",
        "network": {
          "rabbit": {
             "host": "10.0.2.10",
             "port": "5672"
          }
        },
        "compute": {
           "service_type": "rabbitmq",
          "rabbit": {
            "host": "10.0.2.10",
            "port": "5672"
          }
        },
        "block-storage": {
          "service_type": "rabbitmq",
          "rabbit": {
            "host": "10.0.2.10",
            "port": "5672"
          }
        }
      }
    },
    "queue": {
      "host": "10.0.2.10",
      "user": "guest",
      "vhost": "/nova"
    }
  }
}

上記ファイルでは virt_type : qemu に設定していますが、KVM リソースを利用出来る 環境であればここを削除してください。デフォルトの ‘kvm’ が適用されます。また気 をつけることは IP アドレスとネットワークインターフェース名です。環境に合わせて 設定していきましょう。今回は前提構成に合わせて environemnt ファイルを作ってい ます。

次に openstack-chef-repo/.chef/encrypted_data_bag_secret というファイルが knife-zero ホストにあるはずです。これをデプロイ対象の3ノードに事前に転送してお く必要があります。

1
2
3
scp openstack-chef-repo/.chef/encrypted_data_bag_secret 10.0.2.10:/tmp/
scp openstack-chef-repo/.chef/encrypted_data_bag_secret 10.0.2.11:/tmp/
scp openstack-chef-repo/.chef/encrypted_data_bag_secret 10.0.2.12:/tmp/

対象ホストにて

1
2
mkdir /etc/chef
mv /tmp/encrypted_data_bag_secret /etc/chef/openstack_data_bag_secret

ではいよいよデプロイです。

Controller ホストへのデプロイ

1
knife zero bootstrap 10.0.2.10 -N kilo01 -r 'role[os-compute-single-controller-no-network]' -E multi-neutron-kilo -x <USERNAME> --sudo

Network ホストへのデプロイ

1
knife zero bootstrap 10.0.2.11 -N kilo02 -r 'role[os-client]','role[os-network]' -E multi-neutron-kilo -x <USERNAME> --sudo

Compute ノードへのデプロイ

1
knife zero bootstrap 10.0.2.12 -N kilo03 -r 'role[os-compute-worker]' -E multi-neutron-kilo -x <USERNAME> --sudo

これで完了です。admin/mypass というユーザ・パスワードでログインが可能です。

まとめ

openstack-chef-repo を使って OpenStack Kilo の複数台構成をデプロイ出来ました。重要なのは Environment をどうやって作るか?ですが、 私は 作成 -> デプロイ -> 修正 -> デプロイ ->…. を繰り返して作成しています。何度実行しても不具合は発生しない設計なクックブックに なっていますので、このような作業が可能になります。また、「ここの設定を追加したい」という時は…

  • 該当の template を探す
  • 該当のパラメータを確認する
  • recipe 内で template にどうパラメータを渡しているか確認する
  • attribute なり、変数なりを修正するための方法を探す

と行います。比較的難しい作業になるのですが、自らの環境に合わせた Environment を作成するにはこれらの作業が必須となってきます。

以上、複数台構成のデプロイ方法についてでした。

Chef-ZeroでOpenStack Kiloデプロイ(オールインワン編)

こんにちは。@jedipunkz です。

久々に openstack-chef-repo を覗いてみたら ‘openstack/openstack-chef-repo’ とし て公開されていました。今まで stackforge 側で管理されていましたが ‘openstack’ の方に移動したようです。

https://github.com/openstack/openstack-chef-repo

結構安定してきているのかな?と想い、ちらっと試したのですが案の定、簡単に動作さ せることが出来ました。

今回はこのレポジトリを使ってオールインワン構成の OpenStack Kilo を作る方法をま とめていきます。

前提の構成

このレポジトリは Vagrant で OpenStack を作るための環境一式が最初から用意されて いますが、Vagrant では本番環境を作ることは出来ないため、Ubuntu ホストを前提と した記述に差し替えて説明していきます。前提にする構成は下記のとおりです。

  • Uuntu Linux 14.04 x 1 台
  • ネットワークインターフェース x 3 つ
  • eth0 : External ネットワーク用
  • eth1 : Internal (API, Manage) ネットワーク用
  • eth2 : Guest ネットワーク用

特徴としては上記なのですが、eth2 に関してはオールインワンなので必ずしも必要と いうわけではありません。複数台構成を考慮した設定になっています。

前提のIP アドレス

この記事では下記の IP アドレスを前提にします。お手持ちの環境の IP アドレスが違 い場合はそれに合わせて後に示す json ファイルを変更してください。

  • 10.0.1.10 (eth0) : external ネットワーク
  • 10.0.2.10 (eth1) : api/management ネットワーク
  • 10.0.3.10 (eth2) : Guest ネットワーク

事前の準備

事前に対象ホスト (OpenStack ホスト) に chef, berkshelf をインストールします。

1
2
sudo -i
curl -L https://www.opscode.com/chef/install.sh | bash

Berkshelf をインストールするのに必要なソフトウェアをインストールします。

1
apt-get -y install build-essential zlib1g-dev libssl-dev libreadline-dev ruby-dev libxml2-dev libxslt-dev g++

Berkshelf をインストールします。

1
/opt/chef/embedded/bin/gem install berkshelf --no-ri --no-rdoc

デプロイ作業

それでは openstack-chef-repo を取得してデプロイの準備を行います。 ブランチの指定は行わず master ブランチを取得します。Kilo は master ブランチで 管理されています。次のバージョンの開発が始まるタイミングで ‘stable/kilo’ ブラ ンチに管理が移されます。

1
2
3
sudo -i
cd ~/
git clone https://github.com/openstack/openstack-chef-repo.git

次に Berkshelf を使って必要な Cookbooks をダウンロードします。

1
2
cd ~/openstack-chef-repo
/opt/chef/embedded/bin/berks vendor ./cookbooks

Environment を作成します。これは各環境に合わせた設定ファイルのようなもので、各 Cookbooks の Attributes を上書きする仕組みになっています。下記の内容を

1
openstack-chef-repo/environments/aio-neutron-kilo.json

というファイル名で保存してください。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
{
  "name": "aio-neutron-kilo",
  "description": "test",
  "cookbook_versions": {
  },
  "json_class": "Chef::Environment",
  "chef_type": "environment",
  "default_attributes": {
  },
  "override_attributes": {
    "mysql": {
      "bind_address": "0.0.0.0",
      "server_root_password": "mysqlroot",
      "server_debian_password": "mysqlroot",
      "server_repl_password": "mysqlroot",
      "allow_remote_root": true,
      "root_network_acl": ["10.0.0.0/8"]
    },
    "rabbitmq": {
      "address": "0.0.0.0",
      "port": "5672",
      "loopback_users": []
    },
    "openstack": {
      "auth": {
        "validate_certs": false
      },
      "dashboard": {
        "session_backend": "file"
      },
      "block-storage": {
        "syslog": {
          "use": false
        },
        "api": {
          "ratelimit": "False"
        },
        "debug": true,
        "image_api_chef_role": "os-image",
        "identity_service_chef_role": "os-identity",
        "rabbit_server_chef_role": "os-ops-messaging"
      },
      "compute": {
        "rabbit": {
          "host": "10.0.2.10"
        },
        "novnc_proxy": {
          "bind_interface": "eth1"
        },
        "libvirt": {
          "virt_type": "qemu",
          "bind_interface": "eth1"
        },
        "novnc_proxy": {
          "bind_interface": "eth1"
        },
        "xvpvnc_proxy": {
          "bind_interface": "eth1"
        },
        "image_api_chef_role": "os-image",
        "identity_service_chef_role": "os-identity",
        "nova_setup_chef_role": "os-compute-api",
        "rabbit_server_chef_role": "os-ops-messaging",
        "network": {
          "public_interface": "eth1",
          "service_type": "neutron"
        }
      },
      "network": {
        "debug": "True",
        "dhcp": {
          "enable_isolated_metadata": "True"
        },
        "metadata": {
          "nova_metadata_ip": "10.0.2.10"
        },
        "openvswitch": {
          "tunnel_id_ranges": "1:1000",
          "enable_tunneling": "True",
          "tenant_network_type": "gre",
          "local_ip_interface": "eth2"
        },
        "api": {
          "bind_interface": "eth1"
        },
        "l3": {
          "external_network_bridge_interface": "eth0"
        },
        "service_plugins": ["neutron.services.l3_router.l3_router_plugin.L3RouterPlugin"]
      },
      "db": {
        "bind_interface": "eth1",
        "compute": {
          "host": "10.0.2.10"
        },
        "identity": {
          "host": "10.0.2.10"
        },
        "image": {
          "host": "10.0.2.10"
        },
        "network": {
          "host": "10.0.2.10"
        },
        "volume": {
          "host": "10.0.2.10"
        },
        "dashboard": {
          "host": "10.0.2.10"
        },
        "telemetry": {
          "host": "10.0.2.10"
        },
        "orchestration": {
          "host": "10.0.2.10"
        }
      },
      "developer_mode": true,
      "endpoints": {
        "compute-api-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8774"
        },
        "compute-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8774"
        },
        "compute-ec2-admin-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8773"
        },
        "compute-ec2-admin": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8773"
        },
       "compute-ec2-api-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8773"
        },
        "compute-ec2-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8773"
        },
        "compute-xvpvnc": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "6081"
        },
        "compute-novnc-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "6080"
        },
        "compute-novnc": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "6080"
        },
        "compute-vnc": {
          "host": "0.0.0.0",
          "scheme": "http",
          "port": "6080"
        },
        "image-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "9292"
        },
        "image-api-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "9292"
        },
        "image-registry": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "9191"
        },
        "image-registry-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "9191"
        },
        "identity-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "5000"
        },
        "identity-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "5000"
        },
        "identity-admin": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "35357"
        },
        "identity-internal": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "35357"
        },
        "volume-api-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8776"
        },
        "volume-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8776"
        },
        "telemetry-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8777"
        },
        "network-api-bind": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "9696"
        },
        "network-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "9696"
        },
        "orchestration-api": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8004"
        },
        "orchestration-api-cfn": {
          "host": "10.0.2.10",
          "scheme": "http",
          "port": "8000"
        },
        "db": {
          "host": "0.0.0.0",
          "port": "3306"
        },
        "bind-host": "0.0.0.0"
      },
      "identity": {
        "admin_user": "admin",
        "bind_interface": "eth1",
        "debug": true
      },
      "image": {
        "api": {
          "bind_interface": "eth1"
        },
        "debug": true,
        "identity_service_chef_role": "os-identity",
        "rabbit_server_chef_role": "os-ops-messaging",
        "registry": {
          "bind_interface": "eth1"
        },
        "syslog": {
          "use": false
        }
      },
      "mq": {
        "bind_interface": "eth1",
        "host": "10.0.2.10",
        "user": "guest",
        "vhost": "/nova",
        "network": {
          "rabbit": {
             "host": "10.0.2.10",
             "port": "5672"
          }
        },
        "compute": {
           "service_type": "rabbitmq",
          "rabbit": {
            "host": "10.0.2.10",
            "port": "5672"
          }
        },
        "block-storage": {
          "service_type": "rabbitmq",
          "rabbit": {
            "host": "10.0.2.10",
            "port": "5672"
          }
        }
      }
    },
    "queue": {
      "host": "10.0.2.10",
      "user": "guest",
      "vhost": "/nova"
    }
  }
}

上記ファイルは KVM が使えない環境用に virt_type : qemu にしていますが、KVM が 利用できる環境をご利用であれば該当行を削除してください。デフォルト値の ‘kvm’ が入るはずです。

次にデプロイ前に databag 関連の事前操作を行います。Vagrant 用に作成されたファ イルを除くと…

1
2
3
4
5
6
7
8
9
machine 'controller' do
  add_machine_options vagrant_config: controller_config
  role 'allinone-compute'
  role 'os-image-upload'
  chef_environment env
  file('/etc/chef/openstack_data_bag_secret',
       "#{File.dirname(__FILE__)}/.chef/encrypted_data_bag_secret")
  converge true
end

となっていて /etc/chef/openstack_data_bag_secret というファイルを事前にコピー する必要がありそうです。下記のように操作します。

1
cp .chef/encrypted_data_bag_secret /etc/chef/openstack_data_bag_secret

デプロイを実行します。

この openstack-chef-repo には .chef ディレクトリが存在していてノード名が記され ています。’nodienode’ というノード名です。これを利用してそのままデプロイを実行 します。

1
2
3
chef-client -z
knife node -z run_list add nodienode 'role[allinone-compute]'
chef-client -z -E aio-neutron-kilo

上記の説明を行います。 1行目 chef-client -z で Chef-Zero サーバをメモリ上に起動し、2行目で自ノードへ run_list を追加しています。最後、3行目でデプロイ実行、となります。

数分待つと OpenStack Kilo が構成されているはずです。

まとめ

Chef-Zero を用いることで Chef サーバを利用せずに楽に構築が行えました。ですが、 OpenStack の複数台構成となるとそれぞれのノードのパラメータを連携させる必要が出 てくるので Chef サーバを用いたほうが良さそうです。今度、時間を見つけて Kilo の 複数台構成についても調べておきます。

また、master ブランチを使用していますので、まだ openstack-chef-repo 自体が流動 的な状態とも言えます。が launchpad で管理されている Bug リストを見ると、ステー タス Critical, High の Bug が見つからなかったので Kilo に関しては、大きな問題 無く安定してきている感があります。

https://bugs.launchpad.net/openstack-chef

オブジェクトストレージ Minio を使ってみる

こんにちは、@jedipunkz です。

久々にブログ更新になりましたが、ウォーミングアップで minio というオブジェクト ストレージを使ってみたメモを記事にしたいと想います。

minio は Minimal Object Storage の名の通り、最小限の小さなオブジェクトストレー ジになります。公式サイトは下記のとおりです。

http://minio.io/

Golang で記述されていて Apache License v2 の元に公開されています。

最近、資金調達の話も挙がっていたので、これから一般的になってくるのかもしれません。

早速ですが、minio を動かしてみます。

Minio を起動する

方法は mithub.com/minio/minio の README に書かれていますが、バイナリを持ってき て実行権限を与えるだけのシンプルな手順になります。

Linux でも Mac でも動作しますが、今回私は Mac 上で動作させました。

1
2
3
4
5
% wget https://dl.minio.io:9000/updates/2015/Jun/darwin-amd64/minio
% chmod +x minio
% ./minio mode memory limit 512MB
Starting minio server on: http://127.0.0.1:9000
Starting minio server on: http://192.168.1.123:9000

起動すると Listening Port と共に EndPoint の URL が表示されます。

次に mc という minio client を使って動作確認します。

Mc を使ってアクセスする

mc は下記の URL にあります。

https://github.com/minio/mc

こちらもダウンロードして実行権限を付与するのみです。mc は minio だけではなく、 Amazon S3 とも互換性がありアクセス出来ますが、せっかくなので上記で起動した minio にアクセスします。

1
2
3
4
5
% wget https://dl.minio.io:9000/updates/2015/Jun/darwin-amd64/mc
% chmod +x mc
% ./mc config generate
/mc ls  http://127.0.0.1:9000/bucket01
[2015-06-25 16:21:37 JST]     0B testfile

上記では予め作っておいた bucket01 という名前のバケットの中身を表示しています。 作り方はこれから minio の Golang ライブラリである minio-go を使って作りました。 これから説明します。

また ls コマンドの他にも Usage を確認すると幾つかのサブコマンドが見つかります。

Minio の Golang ライブラリ minio-go を使ってアクセスする

さて、せっかくのオブジェクトストレージも手作業でファイルやバケットのアクセスを 行うのはもったいないです。ソフトウェアを使って操作してす。

minio のサンプルのコードを参考にして、下記のコードを作成してみました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package main

import (
    "log"
    "os"

    "github.com/minio/minio-go"
)

func main() {
    config := minio.Config{
        // AccessKeyID:     "YOUR-ACCESS-KEY-HERE",
        // SecretAccessKey: "YOUR-PASSWORD-HERE",
        Endpoint:        "http://127.0.0.1:9000",
    }

    s3Client, err := minio.New(config)
    if err != nil {
        log.Fatalln(err)
    }

    err = s3Client.MakeBucket("bucket01", minio.BucketACL("public-read-write"))
    if err != nil {
        log.Fatalln(err)
    }
    log.Println("Success: I made a bucket.")

    object, err := os.Open("testfile")
    if err != nil {
        log.Fatalln(err)
    }
    defer object.Close()
    objectInfo, err := object.Stat()
    if err != nil {
        object.Close()
        log.Fatalln(err)
    }

    err = s3Client.PutObject("bucket01", "testfile", "application/octet-stream", objectInfo.Size(), object)
    if err != nil {
        log.Fatalln(err)
    }

    for bucket := range s3Client.ListBuckets() {
        if bucket.Err != nil {
            log.Fatalln(bucket.Err)
        }
        log.Println(bucket.Stat)
    }

    for object := range s3Client.ListObjects("bucket01", "", true) {
        if object.Err != nil {
            log.Fatalln(object.Err)
        }
        log.Println(object.Stat)
    }

}

簡単ですがコードの説明をします。

  • 11行目で config の上書きをします。先ほど起動した minio の EndPoint を記します。
  • 17行目で minio にセッションを張り接続を行っています。
  • 22行目で ‘bucket01’ というバケットを生成しています。その際にACLも設定
  • 28行目から42行目で ‘testfile’ というローカルファイルをストレージにPUTしています。
  • 44行目でバケット一覧を表示しています。
  • 51行目で上記で作成したバケットの中のオブジェクト一覧を表示しています。

実行結果は下記のとおりです。

1
2
3
4
2015/06/25 16:56:21 Success: I made a bucket.
2015/06/25 16:56:21 {bucket01 2015-06-25 07:56:21.155 +0000 UTC}
2015/06/25 16:56:21 {"d41d8cd98f00b204e9800998ecf8427e" testfile 2015-06-25
07:56:21.158 +0000 UTC 0 {minio minio} STANDARD}

バケットの作成とオブジェクトの PUT が正常に行えたことをログから確認できます。

まとめ

上記の通り、今現在出来ることは少ないですが冒頭にも記したとおり資金調達の話も挙 がってきていますので、これからどのような方向に向かうか楽しみでもあります。また 最初から Golang, Python 等のライブラリが用意されているところが今どきだなぁと想 いました。オブジェクトストレージを手作業で操作するケースは現場では殆ど無いと想 いますので、その辺は現在では当たり前になりつつあるかもしれません。ちなみに Python のライブラリは下記の URL にあります。

https://github.com/minio/minio-py

以上です。

VyOS で VXLAN を使ってみる

こんにちは。@jedipunkz です。

VyOS に VXLAN が実装されたと聞いて少し触ってみました。この情報を知ったきっかけ は @upaa さんの下記の資料です。

参考資料 : http://www.slideshare.net/upaa/vyos-users-meeting-2-vyosvxlan

VyOS は御存知の通り実体は Debian Gnu/Linux 系の OS でその上に OSS なミドル ウェアが搭載されていて CLI でミドルウェアのコンフィギュレーション等が行えるモ ノになっています。Linux で VXLAN といえば OVS を使ったモノがよく知られています が VyOS の VXLAN 機能は Linux Kernel の実装を使っているようです。

要件

  • トンネルを張るためのセグメントを用意
  • VyOS 1.1.1 (現在最新ステーブルバージョン) が必要
  • Ubuntu Server 14.04 LTS (同じく Linux VXLAN 搭載バージョン)

構成

特徴

  • マネージメント用セグメント 10.0.1.0/24 を用意
  • GRE と同じくトンネル終端が必要なのでそのためのセグメント 10.0.2.0/24 を用意
  • 各 eth1 は IP reachable である必要があるので予め IP アドレスの設定と疎通を確認
  • VXLAN を喋れる Ubuntu 14.04 LTS x 1 台と VyOS 1.1.1 x 2 台で相互に疎通確認
1
2
3
4
5
6
7
8
9
10
11
12
+-------------+-------------+------------ Management 10.0.1.0/24
|10.0.0.254   |10.0.0.253   |10.0.0.1
|eth0         |eth0         |eth0
+----------+  +----------+  +----------+ 
|  vyos01  |  |  vyos02  |  |  ubuntu  |
+-+--------+  +----------+  +----------+ 
| |eth1       | |eth1       | |eth1
| |10.0.2.254 | |10.0.2.253 | |10.0.2.1
| +-----------)-+-----------)-+---------- Tunneling 10.0.2.0/24
|             |             |
+-------------+-------------+------------ VXLAN(eth1にlink) 10.0.1.0/24
10.0.1.254     10.0.1.253    10.0.1.1

設定を投入

vyos01 の設定を行う。VXLAN の設定に必要なものは…

  • VNI (VXLAN Network Ideintity)という識別子
  • Multicast Group Address
  • 互いに IP reachable なトンネルを張るためのインターフェース

です。これらを意識して下記の設定を vyos01 に投入します。

1
2
3
4
5
6
$ configure
% set interfaces vxlan vxlan0
% set interfaces vxlan vxlan0 group 239.1.1.1
% set interfaces vxlan vxlan0 vni 42
% set interfaces vxlan vxlan0 address '10.0.1.254/24'
% set interfaces vxlan vxlan0 link eth1

設定を確認します

1
2
3
4
5
6
7
8
9
% exit
$ show int
...<省略>...
    vxlan vxlan0 {
     address 10.0.1.254/24
     group 239.1.1.1
     link eth1
     vni 42
}

VyOS の CLI を介さず直 Linux の設定を iproute2 で確認してみましょう。 VNI, Multicast Group Address と共に ‘link eth1’ で設定したトンネルを終端するための物理 NIC が確認できます。

1
2
3
4
vyos@vyos01# ip -d link show vxlan0
5: vxlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default
    link/ether 86:24:26:b2:11:5c brd ff:ff:ff:ff:ff:ff promiscuity 0
    vxlan id 42 group 239.1.1.1 dev eth1 port 32768 61000 ttl 16 ageing 300

vyos02 の設定を同様に行います。

1
2
3
4
5
$ congigure
% set interfaces vxlan vxlan0 address '10.0.1.253/24'
% set interfaces vxlan vxlan0 vni 42
% set interfaces vxlan vxlan0 group 239.1.1.1
% set interfaces vxlan vxlan0 link eth1

設定の確認を行います。

1
2
3
4
5
6
7
... 省略 ...
vxlan vxlan0 {
     address 10.0.1.254/24
     group 239.1.1.1
     link eth1
     vni 42
}

同じく Linux の iproute2 で確認します。

1
2
3
4
vyos@vyos01# ip -d link show vxlan0
5: vxlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default
    link/ether 86:24:26:b2:11:5c brd ff:ff:ff:ff:ff:ff promiscuity 0
    vxlan id 42 group 239.1.1.1 dev eth1 port 32768 61000 ttl 16 ageing 300

ubuntu ホストの設定を行っていきます。

Ubuntu Server 14.04 LTS であればパッチを当てること無く Linux Kernel の VXLAN 機能を使うことができます。 設定内容は VyOS と同等です。VyOS がこの Linux の実装を使っているのがよく分かります。

1
2
3
4
sudo modprobe vxlan
sudo ip link add vxlan0 type vxlan id 42 group 239.1.1.1 dev eth1
sudo ip link set up vxlan0
sudo ip a add 10.0.1.1/24 dev vxlan0

同じく Linux iproute2 で確認を行います。

1
2
3
4
 ip -d link show vxlan0
5: vxlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default
    link/ether d6:ff:c1:27:69:a0 brd ff:ff:ff:ff:ff:ff promiscuity 0
    vxlan id 42 group 239.1.1.1 dev eth1 port 32768 61000 ageing 300

疎通確認

疎通確認を行います。

ubuntu -> vyos01 の疎通確認です。ICMP で疎通が取れることを確認できます。

1
2
3
4
5
6
7
8
9
thirai@ubuntu:~$ ping 10.0.1.254 -c 3
PING 10.0.1.254 (10.0.1.254) 56(84) bytes of data.
64 bytes from 10.0.1.254: icmp_seq=1 ttl=64 time=0.272 ms
64 bytes from 10.0.1.254: icmp_seq=2 ttl=64 time=0.336 ms
64 bytes from 10.0.1.254: icmp_seq=3 ttl=64 time=0.490 ms

--- 10.0.1.254 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.272/0.366/0.490/0.091 ms

次に ubuntu -> vyos02 の疎通確認です。

1
2
3
4
5
6
7
8
9
thirai@ubuntu:~$ ping 10.0.1.253 -c 3
PING 10.0.1.253 (10.0.1.253) 56(84) bytes of data.
64 bytes from 10.0.1.253: icmp_seq=1 ttl=64 time=0.272 ms
64 bytes from 10.0.1.253: icmp_seq=2 ttl=64 time=0.418 ms
64 bytes from 10.0.1.253: icmp_seq=3 ttl=64 time=0.451 ms

--- 10.0.1.253 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1998ms
rtt min/avg/max/mdev = 0.272/0.380/0.451/0.079 ms

この時点で ubuntu ホストの fdb (forwarding db) の内容を確認します。

1
2
3
4
$ bridge fdb show dev vxlan0
00:00:00:00:00:00 dst 239.1.1.1 via eth1 self permanent
4e:69:a4:a7:ef:1c dst 10.0.2.253 self
86:24:26:b2:11:5c dst 10.0.2.254 self

vyos01, vyos02 のトンネル終端 IP アドレスと Mac アドレスが確認できます。ubuntu ホストから見ると 送信先は vyos0[12] の VXLAN インターフェースではなく、あくまでもトンネル終端を行っているインターフェース になることがわかります。

まとめ

VyOS ver 1.1.0 には VXLAN を物理インターフェースに link する機能に不具合がありそうなので今ら ver 1.1.1 を使うしか なさそう。とは言え、ver 1.1.1 なら普通に動作しました。

VyOS は仮想ルータという位置付けなので今回紹介したようにインターフェースを VXLAN ネットワークに所属させる 機能があるのみです。VXLAN Trunk を行うような設定はありません。これはハイパーバイザ上で動作させることを前提 に設計されているので仕方ないです..というかスイッチで行うべき機能ですよね..。VM を接続して云々するには OVS のようなソフトウェアスイッチを使えばできます。

また fdb は時間が経つと情報が消えます。これは VXLAN のメッシュ構造なトンネルがその都度張られているのかどうか 気になるところです。ICMP の送信で一発目のみマルチキャストでその後ユニキャストになることを確認しましたが、その 一発目のマルチキャストでトンネリングがされるものなのでしょうか…。あとで調べてみます。OVS のように CLI で トンネルがどのように張られているか確認する手段があれば良いのですが。

以上です。

Aviator でモダンに OpenStack を操作する

こんにちは。@jedipunkz です。

自分は Ruby を普段使うのでいつも Fog というライブラリを使って OpenStack, AWS を操作していました。Fog を使うとクラウドの操作が Ruby のネイティブコードで行え るのでシステムコマンド打つよりミス無く済みます。

Fog より後発で Aviator というライブラリが登場してきたので少し使ってみたのです がまだ未完成なところがあるものの便利な点もあって今後に期待だったので紹介します。

認証情報を yaml ファイルに記す

接続に必要な認証情報を yaml ファイルで記述します。名前を ‘aviator.yml’ として 保存。この時に下記のように環境毎に認証情報を別けて書くことができます。こうする ことでコードの中で開発用・サービス用等と使い分けられます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
production:
  provider: openstack
  auth_service:
    name: identity
    host_uri: <Auth URL>
    request: create_token
    validator: list_tenants
  auth_credentials:
    username: <User Name>
    password: <Password>
    tenant_name: <Tenant Name>

development:
  provider: openstack
  auth_service:
    name: identity
    host_uri: <Auth URL>
    request: create_token
    validator: list_tenants
  auth_credentials:
    username: <User Name>
    password: <Password>
    tenant_name: <Tenant Name>

シンタックス確認

次に aviator のシンタックスを確認します。Fog に無い機能で、コマンドラインでシ ンタックスを確認できてしかも指定可能はパラメータと必須なパラメータと共にサンプ ルコードまで提供してくれます。公式サイトに’サーバ作成’のメソッドが掲載されてい るので、ここでは仮想ディスクを作るシンタックスを確認してみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
% gem install aviator
% aviator describe openstack volume # <-- 利用可能な機能を確認
Available requests for openstack volume_service:
v1 public list_volume_types
v1 public list_volumes
v1 public delete_volume
v1 public create_volume
v1 public get_volume
v1 public update_volume
  v1 public root
% aviator describe openstack volume v1 public create_volume # <-- シンタックスを確認
:Request => create_volume

Parameters:
 +---------------------+-----------+
 | NAME                | REQUIRED? |
 +---------------------+-----------+
 | availability_zone   |     N     |
 | display_description |     Y     |
 | display_name        |     Y     |
 | metadata            |     N     |
 | size                |     Y     |
 | snapshot_id         |     N     |
 | volume_type         |     N     |
 +---------------------+-----------+

Sample Code:
  session.volume_service.request(:create_volume) do |params|
    params.volume_type = value
    params.availability_zone = value
    params.snapshot_id = value
    params.metadata = value
    params.display_name = value
    params.display_description = value
    params.size = value
  end

このように create_volume というメソッドが用意されていて、指定出来るパラメータ・ 必須なパラメータが確認できます。必須なモノには “Y” が REQUIRED に付いています。 またサンプルコードが出力されるので、めちゃ便利です。

では create_volume のシンタックスがわかったので、コードを書いてみましょう。

コードを書いてみる

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env ruby

require 'aviator'
require 'json'

volume_session = Aviator::Session.new(
              :config_file => '/home/thirai/aviator/aviator.yml',
              :environment => :production,
              :log_file    => '/home/thirai/aviator/aviator.log'
            )

volume_session.authenticate

volume_session.volume_service.request(:create_volume) do |params|
  params.display_description = 'testvol'
  params.display_name = 'testvol01'
  params.size = 1
end
puts volume_session.volume_service.request(:list_volumes).body

6行目で先ほど作成した認証情報ファイル aviator.yml とログ出力ファイル aviator.log を指定します。12行目で実際に OpenStack にログインしています。

14-18行目はサンプルコードそのままです。必須パラメータの display_description, display_name, size のみを指定し仮想ディスクを作成しました。最後の puts … は 実際に作成した仮想ディスク一覧を出力しています。

結果は下記のとおりです。

1
2
3
4
5
{ volumes: [{ status: 'available', display_name: 'testvol01', attachments: [],
availability_zone: 'az3', bootable: 'false', created_at:
'2014-12-13T00:41:53.000000', display_description: 'testvol', volume_type:
'standard', snapshot_id: nil, source_volid: nil, metadata:  }, id:
'3a5f616e-a732-4442-a419-10369111bd4c', size: 1 }] }

まとめ

サンプルコードやパラメータ一覧等がひと目でわかる aviator はとても便利です。ま だ利用できるクラウドプラットフォームが OpenStack しかないのと、Neutron の機能 がスッポリ抜けているので、まだ利用するには早いかもです…。逆に言えばコントリ ビューションするチャンスなので、もし気になった方がいたら開発に参加してみるのも いいかもしれません。

Chef-Zero でお手軽に OpenStack Icehouse を作る

こんにちは。@jedipunkz です。

OpenStack Juno がリリースされましたが、今日は Icehouse ネタです。

icehouse 以降、自分の中で OpenStack を自動で作る仕組みが無くなりつつあり、気軽 に OpenStack を作って色々試したい!ッていう時に手段が無く困っていました。例え ば仕事でちょっと OpenStack 弄りたい!って時に DevStack, RDO しかなく。DevStack は御存知の通り動かない可能性が結構あるし RDO は Ubuntu/Debian Gnu Linux ベース じゃないし。

ってことで、以前にも紹介した stackforge 管理の openstack-chef-repo と Chef-Zero を使って OpenStack Icehouse (Neutron) のオールインワン構成を作る方法 を書きます。ちなみに最近 Chef-Solo が Chef-Zero に置き換わりつつあるらしいです。 Chef-Zero はオンメモリで Chef サーバを起動する仕組みです。Chef-Solo と違って Chef サーバを扱う時と何も変更無く操作が出来るのでとても楽です。また、Chef サーバを 別途構、構築・管理しなくて良いので、気軽に OpenStack が作れます。

ちなみに stackforge/openstack-chef-repo の README.md に Chef-Zero での構築方法 が書いてありますが、沢山の問題があります。

  • nova-network 構成
  • API の Endpoint が全て localhost に向いてしまうため外部から操作不可能
  • 各コンポーネントの bind_address が localhost を向いてしまう
  • berkshelf がそのままでは入らない

よって、今回はこれらの問題を解決しつつ “オールインワンな Neutron 構成の Icehouse OpenStack を作る方法” を書いていきます。

構成

+----------------- 10.0.0.0/24 (api/management network)
|
+----------------+
| OpenStack Node |
|   Controller   |
|    Compute     |
+----------------+
|  |
+--(-------------- 10.0.1.0/24 (external network)
   |
   +-------------- 10.0.2.0/24 (guest vm network)

IP address 達

  • 10.0.0.10 (api/manageent network) : eth0
  • 10.0.1.10 (external network) : eth1
  • 10.0.2.10 (guest vm network) : eth2

注意 : 操作は全て eth0 経由で行う

前提の環境

stackforge/openstack-chef-repo の依存している Cookbooks の関係上、upstart 周り がうまく制御できていないので Ubuntu Server 12.04.x を使います。

インストール方法

上記のように3つのネットワークインターフェースが付いたサーバを1台用意します。 KVM が利用出来たほうがいいですが使えないくても構いません。KVM リソースが使えな い場合の修正方法を後に記します。

サーバにログインし root ユーザになります。その後 Chef をオムニバスインストーラ でインストールします。

1
2
% sudo -i
# curl -L https://www.opscode.com/chef/install.sh | bash

次に stable/icehose ブランチを指定して openstack-chef-repo をクローンします。

1
2
3
# cd ~
# git clone -b stable/icehouse https://github.com/stackforge/openstack-chef-repo
# 

berkshelf をインストールするのですが依存パッケージが足らないのでここでインストー ルします。

1
2
# apt-get -y install build-essential zlib1g-dev libssl-dev libreadline-dev \
  ruby-dev libxml2-dev libxslt-dev g++

berkshelf をインストールします。

1
# /opt/chef/embedded/bin/gem install berkshelf --no-ri --no-rdoc

次に openstack-chef-repo に依存する Cookbooks を取得します。

1
2
# cd ~/openstack-chef-repo
# /opt/chef/embedded/bin/berks vendor ./cookbooks

~/openstack-chef-repo/environments ディレクトリ配下に neutron-allinone.json と いうファイル名で作成します。内容は下記の通りです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
{                                                                                                                                                      [0/215]
  "name": "neutron-allinone",
  "description": "test",
  "cookbook_versions": {
  },
  "json_class": "Chef::Environment",
  "chef_type": "environment",
  "default_attributes": {
  },
  "override_attributes": {
    "mysql": {
      "bind_address": "0.0.0.0",
      "server_root_password": "root",
      "server_debian_password": "root",
      "server_repl_password": "root",
      "allow_remote_root": true,
      "root_network_acl": ["10.0.0.0/8"]
    },
    "rabbitmq": {
      "address": "10.0.1.10",
      "port": "5672"
    },
    "openstack": {
      "auth": {
        "validate_certs": false
      },
      "dashboard": {
        "session_backend": "file"
      },
      "block-storage": {
        "syslog": {
          "use": false
        },
        "api": {
          "ratelimit": "False"
        },
        "debug": true,
        "image_api_chef_role": "os-image",
        "identity_service_chef_role": "os-identity",
        "rabbit_server_chef_role": "os-ops-messaging"
      },
      "compute": {
        "rabbit": {
          "host": "10.0.1.10"
        },
        "novnc_proxy": {
          "bind_interface": "eth0"
        },
        "libvirt": {
          "bind_interface": "eth0",
        },
        "novnc_proxy": {
          "bind_interface": "eth0"
        },
        "xvpvnc_proxy": {
          "bind_interface": "eth0"
        },
        "image_api_chef_role": "os-image",
        "identity_service_chef_role": "os-identity",
        "nova_setup_chef_role": "os-compute-api",
        "rabbit_server_chef_role": "os-ops-messaging",
        "network": {
          "public_interface": "eth0",
          "service_type": "neutron"
        }
      },
      "network": {
        "debug": "True",
        "dhcp": {
          "enable_isolated_metadata": "True"
        },
        "metadata": {
          "nova_metadata_ip": "10.0.1.10"
        },
        "openvswitch": {
          "tunnel_id_ranges": "1:1000",
          "enable_tunneling": "True",
          "tenant_network_type": "gre",
          "local_ip_interface": "eth2"
        },
        "api": {
          "bind_interface": "eth0"
        },
        "l3": {
          "external_network_bridge_interface": "eth1"
        },
        "service_plugins": ["neutron.services.l3_router.l3_router_plugin.L3RouterPlugin"]
      },
      "db": {
        "bind_interface": "eth0",
        "compute": {
          "host": "10.0.1.10"
        },
        "identity": {
          "host": "10.0.1.10"
        },
        "image": {
          "host": "10.0.1.10"
        },
        "network": {
          "host": "10.0.1.10"
        },
        "volume": {
          "host": "10.0.1.10"
        },
        "dashboard": {
          "host": "10.0.1.10"
        },
        "telemetry": {
          "host": "10.0.1.10"
        },
        "orchestration": {
          "host": "10.0.1.10"
        }
      },
      "developer_mode": true,
      "endpoints": {
        "compute-api-bind": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "8774"
        },
        "compute-api": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "8774"
        },
        "compute-ec2-admin-bind": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "8773"
        },
        "compute-ec2-admin": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "8773"
        },
       "compute-ec2-api-bind": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "8773"
        },
        "compute-ec2-api": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "8773"
        },
        "compute-xvpvnc": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "6081"
        },
        "compute-novnc-bind": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "6080"
        },
        "compute-novnc": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "6080"
        },
        "compute-vnc": {
          "host": "0.0.0.0",
          "scheme": "http",
          "port": "6080"
        },
        "image-api": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "9292"
        },
        "image-api-bind": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "9292"
        },
        "image-registry": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "9191"
        },
        "image-registry-bind": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "9191"
        },
        "identity-api": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "5000"
        },
        "identity-bind": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "5000"
        },
        "identity-admin": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "35357"
        },
        "volume-api-bind": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "8776"
        },
        "volume-api": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "8776"
        },
        "telemetry-api": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "8777"
        },
        "network-api-bind": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "9696"
        },
        "network-api": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "9696"
        },
        "orchestration-api": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "8004"
        },
        "orchestration-api-cfn": {
          "host": "10.0.1.10",
          "scheme": "http",
          "port": "8000"
        }
      },
      "identity": {
        "admin_user": "admin",
        "bind_interface": "eth0",
        "debug": true
      },
      "image": {
        "api": {
          "bind_interface": "eth0"
        },
        "debug": true,
        "identity_service_chef_role": "os-identity",
        "rabbit_server_chef_role": "os-ops-messaging",
        "registry": {
          "bind_interface": "eth0"
        },
        "syslog": {
          "use": false
        },
        "upload_images": [
          "precise"
        ]
      },
      "mq": {
        "bind_interface": "eth0",
        "host": "10.0.1.10",
        "user": "guest",
        "vhost": "/nova",
        "network": {
          "rabbit": {
             "host": "10.0.1.10",
             "port": "5672"
          }
        },
        "compute": {
           "service_type": "rabbitmq",
          "rabbit": {
            "host": "10.0.1.10",
            "port": "5672"
          }
        },
        "block-storage": {
          "service_type": "rabbitmq",
          "rabbit": {
            "host": "10.0.1.10",
            "port": "5672"
          }
        }
      }
    },
    "queue": {
      "host": "10.0.1.10",
      "user": "guest",
      "vhost": "/nova"
    }
  }
}

内容について全て説明するのは難しいですが、このファイルを作成するのが今回一番苦 労した点です。と言うのは、構成を作りつつそれぞれのコンポーネントのコンフィギュ レーション、エンドポイントのアドレス、バインドアドレス、リスンポート等など、全 てが正常な値になるように Cookbooks を読みつつ作業するからです。この json ファ イルが完成してしまえば、あとは簡単なのですが。

前述しましたが KVM リソースが使えない環境の場合 Qemu で仮想マシンを稼働するこ とができます。その場合、下記のように “libvirt” の項目に “virt_type” を追記して ください。

1
2
3
4
    "libvirt": {
      "bind_interface": "eth0",
      "virt_type": "qemu" # <------ 追記
    },

それではデプロイしていきます。

ここで ‘allinone’ はホスト名、’allinone-compute’ は Role 名、neutron-allinone は先ほど作成した json で指定している environment 名です。

1
2
3
# chef-client -z
# knife node -z run_list add allinone 'role[allinone-compute]'
# chef-client -z -E neutron-allinone

環境にもよりますが、数分でオールインワンな OpenStack Icehouse が完成します。

まとめ

Chef サーバを使わなくて良いのでお手軽に OpenStack が構築出来ました。この json ファイルは実は他にも応用出来ると思っています。複数台構成の OpenStack も指定 Role を工夫すれば構築出来るでしょう。が、その場合は chef-zero は使えません。 Chef サーバ構成にする必要が出てきます。

ちなみに OpenStack Paris Summit 2014 で「OpenStack のデプロイに何を使っている か?」という調査結果が下記になります。Chef が2位ですが Pueppet に大きく離され ている感があります。Juno 版の openstack-chef-repo も開発が進んでいますので、頑 張って広めていきたいです。

  • 1位 Puppet
  • 2位 Chef
  • 3位 Ansible
  • 4位 DevStack
  • 5位 PackStack
  • 6位 Salt
  • 7位 Juju
  • 8位 Crowbar
  • 9位 CFEngine

参考 URL : http://superuser.openstack.org/articles/openstack-user-survey-insights-november-2014

ちなみに、Puppet を使った OpenStack デプロイも個人的に色々試しています。

MidoStack を動かしてみる

こんにちは。@jedipunkz です。

昨晩 Midokura さんが Midonet を OSS 化したとニュースになりました。公式サイトは 下記の URL になっています。Midonet は OpenStack Neutron のプラグインとして動作 するソフトウェアです。

http://www.midonet.org

下記のGithub 上でソースを公開しています。

https://github.com/midonet

本体の midonet と共に midostack というレポジトリがあってどうやら公式サイトの QuickStart を見ても devstack を交えての簡単な midonet の動作が確認できそう。

https://github.com/midonet/midostack

早速使ってみる

早速 midostack を使って midonet を体験してみましょう。QuickStart には Vagrant + VirtualBox を用いた使い方が改定ありますが手元の PC 端末だとリソース が足らなくて CirrOS VM 一個すら立ち上がりませんでした。よって普通にリソースの 沢山あるサーバで稼働してみます。Vagrantfile 見ても

1
config.vm.synced_folder "./", "/midostack"

としているだけなので、Vagrant ではなくても大丈夫でしょう。

Ubuntu Server 14.04 をインストールしたマシンを用意して midostack を取得します。

1
% git clone https://github.com/midonet/midostack.git

midonet_stack.sh を実行します。

1
2
% cd midostack
% ./midonet_stack.sh

暫く待つと Neutron Middonet Plugin が有効になった OpenStack が立ち上がります。 Horizon にアクセスしましょう。ユーザ名 : admin, パスワード : gogomid0 (デフォ ルト) です。

VM も普通に立ち上がりますし VM 同士の通信も良好です。

Neutron プロセスを確認する

Neutron-Server は下記のように立ち上がっています。

1
16229 pts/13   S+     0:06 python /usr/local/bin/neutron-server --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/midonet/midonet.ini

/etc/neutron/neutron.conf の midonet の指定はこんな感じ。

1
2
core_plugin = midonet.neutron.plugin.MidonetPluginV2
api_extensions_path = /opt/stack/midonet/python-neutron-plugin-midonet/midonet/neutron/extensions

次に /etc/neutron/plugins/midonet/midonet.ini を確認してみましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[midonet]
# MidoNet API server URI
# midonet_uri = http://localhost:8080/midonet-api

# MidoNet admin username
# username = admin

# MidoNet admin password
# password = passw0rd

# ID of the project that MidoNet admin user belongs to
# project_id = 77777777-7777-7777-7777-777777777777

# Virtual provider router ID
# provider_router_id = 00112233-0011-0011-0011-001122334455

# Path to midonet host uuid file
# midonet_host_uuid_path = /etc/midolman/host_uuid.properties

[MIDONET]
project_id = admin
password = gogomid0
username = admin
midonet_uri = http://localhost:8081/midonet-api

Midonet API にアクセスする

Midonet API のリファレンスが下記の URL で公開されていました。

http://docs.midonet.org/docs/v1.8/rest-api/api/rest-api-specification.html

早速使ってみましょう。まず Token を得ます。

1
curl -i 'http://127.0.0.1:5000/v2.0/tokens' -X POST -H "Content-Type: application/json" -H "Accept: application/json"  -d '{"auth": {"tenantName": "admin", "passwordCredentials": {"username": "admin", "password": "gogomid0"}}}'

Token ID を取得したら “/” に対してアクセスしてみましょう。

1
% curl -i -X GET http://localhost:8081/midonet-api/ -H "User-Agent: python-keystoneclient" -H "X-Auth-Token: <TokenID>"

レスポンス

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
"routerTemplate": "http://localhost:8081/midonet-api/routers/{id}",
"portTemplate": "http://localhost:8081/midonet-api/ports/{id}",
"vipTemplate": "http://localhost:8081/midonet-api/vips/{id}",
"poolTemplate": "http://localhost:8081/midonet-api/pools/{id}",
"healthMonitorTemplate": "http://localhost:8081/midonet-api/health_monitors/{id}",
"healthMonitors": "http://localhost:8081/midonet-api/health_monitors",
"loadBalancers": "http://localhost:8081/midonet-api/load_balancers",
"ipAddrGroupTemplate": "http://localhost:8081/midonet-api/ip_addr_groups/{id}",
"tenants": "http://localhost:8081/midonet-api/tenants",
"tenantTemplate": "http://localhost:8081/midonet-api/tenants/{id}",
"portGroupTemplate": "http://localhost:8081/midonet-api/port_groups/{id}",
"loadBalancerTemplate": "http://localhost:8081/midonet-api/load_balancers/{id}",
"poolMemberTemplate": "http://localhost:8081/midonet-api/pool_members/{id}",
"hostVersions": "http://localhost:8081/midonet-api/versions",
"version": "v1.7",
"bridgeTemplate": "http://localhost:8081/midonet-api/bridges/{id}",
"hostTemplate": "http://localhost:8081/midonet-api/hosts/{id}",
"uri": "http://localhost:8081/midonet-api/",
"vteps": "http://localhost:8081/midonet-api/vteps",
"tunnelZoneTemplate": "http://localhost:8081/midonet-api/tunnel_zones/{id}",
"ipAddrGroups": "http://localhost:8081/midonet-api/ip_addr_groups",
"writeVersion": "http://localhost:8081/midonet-api/write_version",
"chainTemplate": "http://localhost:8081/midonet-api/chains/{id}",
"vtepTemplate": "http://localhost:8081/midonet-api/vteps/{ipAddr}",
"adRouteTemplate": "http://localhost:8081/midonet-api/ad_routes/{id}",
"bgpTemplate": "http://localhost:8081/midonet-api/bgps/{id}",
"hosts": "http://localhost:8081/midonet-api/hosts",
"routeTemplate": "http://localhost:8081/midonet-api/routes/{id}",
"ruleTemplate": "http://localhost:8081/midonet-api/rules/{id}",
"systemState": "http://localhost:8081/midonet-api/system_state",
"vips": "http://localhost:8081/midonet-api/vips",
"pools": "http://localhost:8081/midonet-api/pools",
"routers": "http://localhost:8081/midonet-api/routers",
"bridges": "http://localhost:8081/midonet-api/bridges",
"chains": "http://localhost:8081/midonet-api/chains",
"portGroups": "http://localhost:8081/midonet-api/port_groups",
"poolMembers": "http://localhost:8081/midonet-api/pool_members",
"tunnelZones": "http://localhost:8081/midonet-api/tunnel_zones"
}

なんとなく引数にこれらの文字列を渡せばいいのだなと分かります。

次に neutron の管理している subnets を確認してみましょう。

1
% curl -i -X GET http://localhost:8081/midonet-api/neutron/subnets -H "User-Agent: python-keystoneclient" -H "X-Auth-Token: <TokenID>"

レスポンス

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
[
  {
    "enable_dhcp": false,
    "tenant_id": "65f7012145d84ac5afc36572eabe5b09",
    "host_routes": [],
    "dns_nameservers": [],
    "id": "3dbe5cff-8a8c-4790-85b5-b789d8ede863",
    "name": "public-subnet",
    "cidr": "200.200.200.0/24",
    "shared": false,
    "ip_version": 4,
    "network_id": "45269fba-e32f-40b0-a542-f5cfe34ce1a1",
    "gateway_ip": "200.200.200.1",
    "allocation_pools": [
      {
        "last_ip": null,
        "first_ip": null
      }
    ]
  },
  {
    "enable_dhcp": true,
    "tenant_id": "f34b4398015546b8b84f50c731ed6c51",
    "host_routes": [],
    "dns_nameservers": [],
    "id": "3dbcf04a-9738-4b1f-b084-76f2a4b17cbc",
    "name": "private-subnet",
    "cidr": "10.0.0.0/24",
    "shared": false,
    "ip_version": 4,
    "network_id": "2edb78c3-0f23-4e29-a3e6-cc97f55baa6a",
    "gateway_ip": "10.0.0.1",
    "allocation_pools": [
      {
        "last_ip": null,
        "first_ip": null
      }
    ]
  }
]

2つのサブネットが確認出来ました。

まとめ

勉強不足でまだ全く midonet で出来る事がわからない..汗。でもとりあえず動かせた し、API も引っ張れるのでこれから色々試せそうですね。OSS 化されたことで、コミュ ニティの間でも使われていくことも想像出来ますし、自分たち技術者としてはとても有 り難いことでした。

Chef-Container Beta を使ってみる

こんにちは。@jedipunkz です。

昨晩 Chef が Chef-Container を発表しました。

まだ Beta リリースでバージョンは 0.2.0 です。(gem だと 0.1.1)

Docker を代表とするコンテナ周りの技術が最近、盛んにリリースされていますし、今 後クラウドプラットフォーム上でコンテナを使ってアプリを動かすケースも増えてくる のではないでしょうか。Dockerfile を使っても Chef-Solo を使ってソフトウェアをデ プロイ出来るのだけどそれだけだとしんどいので、コンテナに特化した Chef が出てき たってことだと思います。特徴として SSH でログインしてブートストラップするので はなくて Runit + Chef-init を用いてコンテナにデプロイすることが挙げられます。

では実際に使ってみたのでその時の手順をまとめてみます。

事前に用意する環境

下記のソフトウェアを予めインストールしておきましょう。

  • docker
  • chef
  • berkshelf

ここで注意なのですが後に knife コマンドを使って Docker イメージをビルドします。 つまり root 権限が必要です。rbenv 等を使って ruby, chef をインストールすると、 辛いかもしれませんので OS のパッケージを使ってインストールすると良いと思います。 この辺りは今後改善策が出てくるかも…。

尚、インストール方法はここでは割愛します。

Chef-Container のインストール

下記の2つの Gems をインストールします。

  • knife-container
  • chef-container
1
2
% sudo gem install knife-container
% sudo gem install chef-container

使用方法

まず knife コマンドを使って操作に必要なディレクトリとファイルを生成します。

1
% knife container docker init chef/ubuntu-12.04 -r 'recipe[apache2]' -z -b

ここで ‘chef/ubuntu-12.04’ は Docker のイメージ名です。chef-init 等の環境が予 め入っていました。このイメージ以外では今のところ動作を確認していません..。これは後にまとめで触れます。

上記のコマンドの結果で得られるディレクトリとファイル達です。

1
2
3
4
5
6
7
8
9
.
└── dockerfiles
    └── chef
        └── ubuntu-12.04
            ├── Berksfile
            ├── chef
            │   ├── first-boot.json
            │   └── zero.rb
            └── Dockerfile

また dockerfiles/chef/ubuntu-12.04/Dockerfile を確認すると…

1
2
3
4
5
6
7
# BASE chef/ubuntu-12.04:latest
FROM chef/ubuntu-12.04
ADD chef/ /etc/chef/
RUN chef-init --bootstrap
RUN rm -rf /etc/chef/secure/*
ENTRYPOINT ["chef-init"]
CMD ["--onboot"]

イメージを取得 -> ディレクトリ同期 -> chef-init 実行 -> /etc/chef/secure 配下削除、と 実行しているようです。

次に first-boot.json という名前のファイルを生成します。chef-init が解釈するファ イルです。

1
2
3
4
5
6
7
8
9
10
{
   "run_list": [
      "recipe[apache2]"
   ],
   "container_service": {
      "apache2": {
         "command": "/usr/sbin/apache2 -k start"
      }
   }
}

ではいよいよ knife コマンドで Docker イメージをビルドします。

1
% sudo knife container docker build chef/ubuntu-12.04 -z

すると、下記のように Docker イメージが出来上がります。

1
2
3
4
5
% sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
chef/ubuntu-12.04   11                  03fd2357596f        4 days ago          397.7 MB
chef/ubuntu-12.04   11.12               03fd2357596f        4 days ago          397.7 MB
chef/ubuntu-12.04   11.12.8             03fd2357596f        4 days ago          397.7 MB

出来上がったイメージを利用してコンテナを稼働します。

1
2
3
4
% sudo docker run chef/ubuntu-12.04
% sudo docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS               NAMES
191cfdaf0bdb        650a89f73ed8        chef-init --onboot   39 minutes ago      Up 39 minutes                           agitated_almeida

まとめ

コンテナと言っても今現在は Docker のみに対応しているようです。また init の際に指定する Docker イメージ の中に chef-init が入っている必要がありそうです。Build する前に予めイメージを作っておく必要があるという のはしんどいので、今後改善されるかもしれません。

そもそも Docker やコンテナ技術の登場で Puppet, Chef を代表とするツール類が不要になるのでは?という議論が 幾つかの場面であったように思います。つまりコンテナのイメージに予めソフトウェアを配布しそれを用いて稼働 することで、マシンが起動した後にデプロイすることが必要ないよね?という発想です。今回紹介したようにコンテナの イメージを生成するのに Chef を用いるということであれば、また別の議論になりそうです。また稼働したコンテナに ソフトウェアをデプロイすることも場合によっては必要なので、この辺りの技術の完成度が上がることを期待したいです。

参考 URL

JTF2014 で Ceph について話してきた!

こんにちは。@jedipunkz です。

今日、JTF2014 (July Tech Festa 2014) というイベントで Ceph のことを話してきま した。Ceph ユーザ会の会員として話してきたのですが Ceph ユーザ会は実は最近発足 したばかりのユーザ会で、まだまだ活動が活発ではありません。もし興味がある方いらっ しゃいましたら是非参加よろしくお願いしますー。下記の Google Groups になります。

https://groups.google.com/forum/#!forum/ceph-jp

ユーザ会としての勉強会として初になるのですが、今回このイベントで自分は Ceph-Deploy について話してきました。とりあえず皆さんに使ってもらいたかったので この話をしてきました。が、予定時間がメチャ短かったので超絶早口で頑張った分、皆 さんに理解してもらえなかった気がしてちょっと反省…。なので、このブログを利用 して少し細くさせてもらいます。

今日の発表資料はこちらです!

今日のテーマは 「Ceph-Deploy を使って Ceph を構築してみる」だったのですが、下 記のテーマを持って資料を作っています。

  • 単にミニマム構成ではなく運用を考慮した実用性のある構成
  • OSD, MON, MDS の各プロセスとノード・ディスクの数の関係を知ってもらう

特に「実用性のある..」は意識したつもりでした。そのために前提とした構成に下記の 特徴を持たせています。(資料 6 ページ目に構成図があります。確認してみてください。)

  • オブジェクト格納用ディスクは複数/ノードを前提
  • OSD レプリケーションのためのクラスタネットワークを用いる構成
  • OSD の扱うジャーナル格納用ディスクは高速な SSD を用いる
  • MDS は利用する HW リソースの特徴が異なるので別ノードへ配置

ストレージ全体を拡張したければ

  • 図中 ceph01-03 の様なノードを増設する
  • ceph01-03 にディスクとそれに対する OSD を増設する

ですが、前者がベストでしょう。ノード増設の場合 ceph-deploy を用いて

  • ceph-deploy mon create <新規ホスト名> で MON を稼働
  • ceph-dploy disk zap, osd create で OSD を稼働

で簡単に可能です。MDS の増設も負荷状況を見ながらするといいでしょう。自分はまだ Ceph を運用していないので、各プロセスがどのようなリソースの消費の仕方をするの か知りません。MDS がどのような数で運用していくべきなのか。早く運用から得たノウ ハウが共有されないかなぁと期待しています。

また今回話すのを忘れたのですが SSD をジャーナル格納用ディスクとして用いたのは ハードディスクに対して高速でアクセス出来ること・またメタデータはファイルオブジェ クトに対して小容量で済む、といった理由からです。メタデータを扱うのに適している と思います。また将来的には幾つかの KVS データベースソフトウェアをメタデータ管 理に使う実装がされるそうです。

以上です。皆さん、是非 Ceph を使ってみてください! また興味のある方はユーザ会 への加入をご検討くださいー。

Mesos + Marathon + Deimos + Docker を試してみた!

こんにちは。@jedipunkz です。

以前 Mesos, Docker について記事にしました。

http://jedipunkz.github.io/blog/2013/09/28/mesos-architecture-number-1/ http://jedipunkz.github.io/blog/2013/10/01/methos-architecture-number-2-docker-on-mesos/

Twitter で Docker 関連のオーケストレーションツールについて呟いていたら @everpeace さんから こんな情報をもらいました。

Deimos !!! 知らなかった。Mesos の Docker プラグインらしく下記の場所にありました。

https://github.com/mesosphere/deimos

色々調べいたら、こんな資料が見つかりました。どうやらまだ公開されて4日しか経っていないようです。

http://mesosphere.io/learn/run-docker-on-mesosphere/

Mesos + Marathon + Deimos + Docker をオールインワン構成で構築する手順が書かれています。

内容はほぼ同じですが、一応自分がやってみて理解したことをまとめたいので下記に記していきます。

構築してみる

手順をまとめてスクリプトにしました。パッケージは Ubuntu 13.10 用のようですが 14.04 のホスト で実行出来ました。14.04 のパッケージはまだ見つかっていません。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/bin/bash
# disable ipv6
echo 'net.ipv6.conf.all.disable_ipv6 = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.default.disable_ipv6 = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

# install related tools
sudo apt-get update
sudo apt-get -y install curl python-setuptools python-pip python-dev python-protobuf

# install zookeeper
sudo apt-get -y install zookeeperd
echo 1 | sudo dd of=/var/lib/zookeeper/myid

# install docker
sudo apt-get -y install docker.io
sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker
sudo sed -i '$acomplete -F _docker docker' /etc/bash_completion.d/docker.io
sudo docker pull libmesos/ubuntu

# install mesos
curl -fL http://downloads.mesosphere.io/master/ubuntu/13.10/mesos_0.19.0-xcon3_amd64.deb -o /tmp/mesos.deb
sudo dpkg -i /tmp/mesos.deb
sudo mkdir -p /etc/mesos-master
echo in_memory  | sudo dd of=/etc/mesos-master/registry
curl -fL http://downloads.mesosphere.io/master/ubuntu/13.10/mesos_0.19.0-xcon3_amd64.egg -o /tmp/mesos.egg
sudo easy_install /tmp/mesos.egg

# install marathon
curl -fL http://downloads.mesosphere.io/marathon/marathon_0.5.0-xcon2_noarch.deb -o /tmp/marathon.deb
sudo dpkg -i /tmp/marathon.deb

# restart each services
sudo service docker.io restart
sudo service zookeeper restart
sudo service mesos-master restart
sudo service mesos-slave restart

# install deimos
sudo pip install deimos
sudo mkdir -p /etc/mesos-slave

## Configure Deimos as a containerizer
echo /usr/bin/deimos  | sudo dd of=/etc/mesos-slave/containerizer_path
echo external     | sudo dd of=/etc/mesos-slave/isolation

プロセスの確認

実行が終わると各プロセスが確認出来ます。オプションでどのプロセスが何を見ているか大体 わかりますので見ていきます。

mesos-master

mesos-master は zookeeper を参照して 5050 番ポートで起動しているようです。

1
2
% ps ax | grep mesos-master
 1224 ?        Ssl    0:30 /usr/local/sbin/mesos-master --zk=zk://localhost:2181/mesos --port=5050 --log_dir=/var/log/mesos --registry=in_memory

mesos-slave

mesos-slave は同じく zookeeper を参照して containerizer を deimos として稼働していることが わかります。

1
2
% ps ax | grep mesos-slave
 1225 ?        Ssl    0:12 /usr/local/sbin/mesos-slave --master=zk://localhost:2181/mesos --log_dir=/var/log/mesos --containerizer_path=/usr/bin/deimos --isolation=external

zookeeper

zookeeper は OpenJDK7 で稼働している Java プロセスです。

1
2
% ps ax | grep zookeeper
 1073 ?        Ssl    1:07 /usr/bin/java -cp /etc/zookeeper/conf:/usr/share/java/jline.jar:/usr/share/java/log4j-1.2.jar:/usr/share/java/xercesImpl.jar:/usr/share/java/xmlParserAPIs.jar:/usr/share/java/netty.jar:/usr/share/java/slf4j-api.jar:/usr/share/java/slf4j-log4j12.jar:/usr/share/java/zookeeper.jar -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only=false -Dzookeeper.log.dir=/var/log/zookeeper -Dzookeeper.root.logger=INFO,ROLLINGFILE org.apache.zookeeper.server.quorum.QuorumPeerMain /etc/zookeeper/conf/zoo.cfg

docker

docker が起動していることも確認できます。設定は特にしていないです。

1
2
% ps axuw | grep docker
root       831  0.0  0.3 364776 14924 ?        Sl   01:30   0:01 /usr/bin/docker.io -d

Marathon の WebUI にアクセス

Marathon の WebUI にアクセスしてみましょう。

まだ何も Tasks が実行されていないので一覧には何も表示されないと思います。

Tasks の実行

Marathon API に対してクエリを発行することで Mesos の Tasks として Docker コンテナを稼働させることが出来ます。 下記のファイルを ubuntu.json として保存。

1
2
3
4
5
6
7
8
9
10
{
    "container": {
    "image": "docker:///libmesos/ubuntu"
  },
  "id": "ubuntu",
  "instances": "1",
  "cpus": ".5",
  "mem": "512",
  "uris": [ ]
}

下記の通り localhost:8080 が Marathon API の Endpoint になっているのでここに対して作成した JSON を POST します。

1
% curl -X POST -H "Content-Type: application/json" localhost:8080/v2/apps -d@ubuntu.json

Tasks の一覧を取得してみます。

1
2
% curl -X GET -H "Content-Type: application/json" localhost:8080/v2/apps
{"apps":[{"id":"ubuntu","cmd":"","env":{},"instances":1,"cpus":0.5,"mem":512.0,"executor":"","constraints":[],"uris":[],"ports":[13049],"taskRateLimit":1.0,"container":{"image":"docker:///libmesos/ubuntu","options":[]},"version":"2014-06-13T01:45:58.693Z","tasksStaged":1,"tasksRunning":0}]}

Tasks の一覧が JSON で返ってきます。id : ubuntu, インスタンス数 : 1, CPU 0.5, メモリー : 512MB で Task が稼働していることが確認出来ます。

ここで WebUI 側も見てみましょう。

一つ Task が稼働していることが確認出来ると思います。

その Task をクリックすると詳細が表示されます。

次に Tasks のスケーリングを行ってみましょう。 下記の通り ubuntu.json を修正し instances : 2 とする。これによってインスタンス数が2に増えます。

1
2
3
4
5
6
7
8
9
10
{
    "container": {
    "image": "docker:///libmesos/ubuntu"
  },
  "id": "ubuntu",
  "instances": "2",
  "cpus": ".5",
  "mem": "512",
  "uris": [ ]
}

修正した JSON を POST します。

1
% curl -X PUT -H "Content-Type: application/json" localhost:8080/v2/apps/ubuntu -d@ubuntu.json

Tasks の一覧を取得し containers が 2 になっていることが確認できます。

1
2
% curl -X GET -H "Content-Type: application/json" localhost:8080/v2/apps
{"apps":[{"id":"ubuntu","cmd":"","env":{},"instances":2,"cpus":0.5,"mem":512.0,"executor":"","constraints":[],"uris":[],"ports":[17543],"taskRateLimit":1.0,"container":{"image":"docker:///libmesos/ubuntu","options":[]},"version":"2014-06-13T02:40:04.536Z","tasksStaged":3,"tasksRunning":0}]}

最後に Tasks を削除してみましょう。

1
% curl -X DELETE -H "Content-Type: application/json" localhost:8080/v2/apps/ubuntu

Tasks が削除されたことを確認します。

1
2
% curl -X GET -H "Content-Type: application/json" localhost:8080/v2/apps
{"apps":[]}

Marathon API v2

Marathon API v2 について下記の URL に仕様が載っています。上記に記したクエリ以外にも色々載っているので 動作を確認してみるといいと思います。

https://github.com/mesosphere/marathon/blob/master/docs/api/http/REST_template.md

まとめ

オールインワン構成が出来ました。また動作確認も無事出来ています。 以前試した時よりも大分、手順が簡潔になった印象があります。また参考資料中に

“checkout our other multi-node tutorials on how to scale Docker in your data center.”

とありますが、まだ見つかっていません(´・ω・`)見つかった方教えてくださいー。

以前試した時は Mesos-Master の冗長化が出来なかったので今回こそ Multi Mesos-Masters, Multi Mesos-Slaves の構成を作ってみたいと思います。

また今月?になって続々と Docker のオーケストレーションツールを各社が公開しています。

centurion

New Relic が開発したオーケストレーションツール。 https://github.com/newrelic/centurion

helios

Spotify が開発したオーケストレーションツール。 https://github.com/spotify/helios

fleet

CoreOS 標準搭載。 https://github.com/coreos/fleet

geard

RedHat が Red Hat Enterprise Linux Atomic Host に搭載しているツール。 http://openshift.github.io/geard/

Kubernetes

Google が開発したオーケストレーションツール。 https://github.com/GoogleCloudPlatform/kubernetes

shipper

Python のコードで Docker をオーケストレーション出来るツール。 https://github.com/mailgun/shipper

幾つか試したのですが、まだまだ動く所までいかないツールがありました。github の README にも “絶賛開発中なのでプロダクトレディではない” と書かれています。これからでしょう。