Abstract
Ubuntu 16.04 LTS (Xenial) をサポートした Conjure-up 2.0.1 が先日リリースされました。新しい Conjure-up を使ってUbuntuマシン一台で OpenStack Mitaka を構築してみたのでその手順をご紹介します。
Conjure-up とは
Conjure-up は、KubernetesやDeepLearningのフレームワークといった、導入に手間のかかる大規模なソフトウェアを、 Juju や LXD を使ってできるだけ簡単に導入するツールです。GitHub上にリポジトリがあり、バージョン2.0のベータ版公開から長らく開発が進められていましたが、先日ようやく2.0.1リリース版が公開されました。
ソフトウェアの導入をどのように簡単化するか、全体像を理解するためにも、Conjure-up が用いている Juju と LXD について説明をしたいと思います。
Juju: デプロイツール
Juju は Apache や MySQL といったクラウドアプリケーションのデプロイ、設定、管理を行うことができる Ubuntu 用のツールです。デプロイツールというと Chef や Puppet がありますが、 Juju はそれらの Ubuntu に特化したものという位置づけでしょうか[2]。詳しい説明は公式のドキュメントが参考になりますが、 Juju では各クラウドアプリケーションを Charm という単位で扱い、設定ファイルを元に Charm に書かれたスクリプトを実行することで Docker や LXD でコンテナを作り、その上にアプリケーションのデプロイを行います。
複雜なミドルウェアの設定や管理を行うこのようなツールはサービスオーケストレーションツールと呼ばれているみたいです。
LXD: コンテナハイパーバイザ
LXD (Linux Container Daemon) は LXC (Linux Container) を使って一つのマシン上で複数のLinuxシステムを走らせるコンテナ仮想化ツールです。
似たようなツールとして Docker がありますが、 Docker はアプリケーション単位での隔離を目的としているのに対し、 LXD ではシステム単位での隔離を目的としており REST API をサポートするなどの違いがあります[1]。
Conjure-up は何をするか
では Conjure-up は Juju や LXD を使ってどのように大規模ソフトウェアの導入を支援するか、と言う話ですが、 OpenStack を例にとって説明したいと思います。
OpenStack はクラウドコンピューティングを実現するためのソフトウェアプラットフォームですが、単体ではなく以下に上げたような複数の構成要素から成っています。
- Nova: 仮想インスタンスを動作させる
- Neutron: 仮想ネットワークの構成と管理を担う
- Cinder: ストレージを提供する
- Keystone: 認証情報を管理する
- Glance: 仮想インスタンスの起動イメージを管理する
- Swift: オブジェクトストレージを提供する
- Horizon: ダッシュボード(Web UI)を提供する
- ...
理想的にはこれらのアプリケーションは別々の物理マシンで立ち上げたいところですが、本格的に運用するわけでなければ1台のマシンだけで完結したい訳です。
そこで考えられたのが LXD を使って各アプリケーションをそれぞれのコンテナで動かし、1台の物理マシン上で動く複数台の仮想マシンで OpenStack を構成する方法。
さらに、各コンテナのセットアップを Juju で自動化してしまえば、コマンド一発でLXD コンテナの作成からアプリケーションのデプロイ、設定までを行えるのではと。これをやったのが conjure-up です。
同様に、conjure-up を使えば複数の構成要素からなる大規模なソフトウェアやプラットフォームを Juju やら LXD やらを使って簡単にデプロイできるわけですね。
作業環境
前置きが長くなってしまいましたが、ここからは実際に conjure-up を使って OpenStack Mitaka を構築していきます。
今回は Ubuntu Server をクリーンインストールした物理マシン1台を使って構築します。
項目 | 値 |
---|---|
ホスト名 | curiosity |
OS | Ubuntu 16.04 LTS |
CPU | Intel Core i7-3820 |
メモリ | 64GB |
ストレージ | /dev/sda: 512 GB SSD x 1 /dev/sdb: 3TB HDD x 1 |
NIC | 1000-base ethernet x 1 |
注意点として、OpenStack を構成する LXD コンテナ自体、および OpenStack 上で動く nova 仮想マシンの両方のデータを ホスト側OSとは隔離して /dev/sdb 上に配置します。なお、この構成はマストでは無く、ホスト側OSと同じパーティションを使っても構築できます。詳しくは「01. 事前準備: ZFS と LXD の構築」で説明します。
また、執筆時点での各種依存パッケージのバージョンは次の通りです。
- lxd: 2.0.4-0ubuntu1~ubuntu16.04.1
- juju-2.0: 2.0-rc3-0ubuntu1~16.04.1~juju1
- conjure-up: 2.0.1-0~201610061938~ubuntu16.04.1
バージョンの違いによって conjure-up の過程でエラーが起きたり上手く行かなかったりするかもしれません。
01. 事前準備1: ZFS と LXD の構築
LXD 2.0 ではデータの保存先として Linux 上のディレクトリに加え Ubuntu 16.04 からサポートされた ZFS ファイルシステムを選択できるようになりました。
次世代ファイルシステムとされている ZFS を使うメリットは沢山あるみたい[4]なので、今回は ZFS を使いたいと思います。
ZFS と LXD パッケージのインストール
$ sudo apt install lxd zfs
LXD 初期化
※ [注意] **以下のコマンドは SSH 経由で無くマシン上で直接実行してください。**でないとネットワークブリッジの設定の項目で SSH が切断され操作できなくなります。
$ sudo lxd init
Name of the storage backend to use (dir or zfs): zfs
Create a new ZFS pool (yes/no)? yes
Name of the new ZFS pool: openstack
Would you like to use an existing block device (yes/no)? yes
Path to the existing block device: /dev/sdb
Would you like LXD to be available over the network (yes/no)? no
Do you want to configure the LXD bridge (yes/no)? yes
LXD has been successfully configured.
※ ZFS を別ストレージで作らない場合はこんな感じになります
$ sudo lxd init
Name of the storage backend to use (dir or zfs): zfs
Create a new ZFS pool (yes/no)? yes
Name of the new ZFS pool: openstack
Would you like to use an existing block device (yes/no)? no
Size in GB of the new loop device (1GB minimum): 100
Would you like LXD to be available over the network (yes/no)? no
Do you want to configure the LXD bridge (yes/no)? yes
LXD has been successfully configured.
02. 事前準備2: Nested VT-x の有効化
LXD上でのLXDの実行をサポートするために Nested VT-x を有効化します。
Nested VT-x が有効かどうか確認します。
$ cat /sys/module/kvm_intel/parameters/nested
N
N なら無効なので、以下のコマンドを実行して有効化します。
$ sudo rmmod kvm-intel
$ sudo sh -c "echo 'options kvm-intel nested=y' >> /etc/modprobe.d/dist.conf"
$ sudo modprobe kvm-intel
$ cat /sys/module/kvm_intel/parameters/nested
Y
03. Conjure-up のインストール
apt へのリポジトリの登録をします。
$ sudo apt-add-repository ppa:conjure-up/next
$ sudo apt-add-repository ppa:juju/devel
$ sudo apt update
その後 conjure-up を導入します。
$ sudo apt install conjure-up
04. OpenStack 構築
1. conjure-up
conjure-up コマンドで OpenStack を構築します。
$ conjure-up openstack
2. アプリケーションのデプロイ
スクリーンが立ち上がるので OpenStack with NovaLXD を選択.
その後デプロイするアプリケーション一覧と設定項目の画面が出るので、そのまま Deploy all 15 Remaining Applications を押します。
といきたいところなのですが、筆者の環境では15個のアプリケーションすべてを同時にデプロイしたところ、 rabbitmq-server のデプロイに失敗して途中でコケてしまいました。
解決策として rabbitmq-server だけを最初にデプロイし、後述する Troubleshooting にある通り rabbitmq-server の設定ファイルの修正と反映を行った後に残りのアプリケーションをすべてデプロイすると上手くいきました。 (詳しくはGithub の issue #489に書かれています。)
進捗が気になる人は、別のコンソールを開いて
$ watch juju status
や
$ juju debug-log
としてみると状況がわかると思います。
3. 指示に従って後処理
すべてのアプリケーションのデプロイが終わると、 ソフトウェアの設定を行う画面に遷移します。
エンターを押してステップを進めていきます。
Step 1. Glance への Ubuntu Trusty (14.04) と Ubuntu Xenial (16.04) 起動イメージのインポート
以上で構築完了です。
05. ダッシュボードへのアクセス
openstack-dashboard/0
ユニットの IP アドレスをメモしておきます。
$ juju status
...
openstack-dashboard/0 active idle 14 10.19.198.23 80/tcp,443/tcp Unit is ready
...
ホスト側から openstack-dashboard/0
へのリバースプロキシを作るため、 apache2 を入れて設定します。
$ sudo apt install apache2
$ sudo a2enmod proxy
$ sudo vim /etc/apache2/sites-enabled/000-default.conf
--> 以下、<VirtualHost />内に追記
---
<IfModule mod_proxy.c>
ProxyPass / http://10.19.198.23/
ProxyPassReverse / http://10.19.198.23/
</IfModule>
---
以上で完了。
http://ホストのIPアドレス/horizon
をブラウザで開き、ユーザ名 admin
, パスワード openstack
でログインできます。
Troubleshooting
1. rabbitmq-server の立ち上げに失敗する
conjure-up openstack
としても一発でデプロイ出来ないことが多々あります。筆者の場合は、次のエラーが出て rabbitmq-server/0
ユニットが立ち上がりませんでした。
hook failed: "amqp-relation-changed" for nova-compute:amqp
ユニットの立ち上げに失敗した場合、juju ssh ユニット名
として仮想マシンのコンソールを開き、ログを参照すると原因がわかりやすいです。
$ juju ssh rabbitmq-server/0
--- (以下、仮想マシン上での操作) ---
ubuntu@juju-84f95a-15$ sudo less +F /var/log/juju/unit-rabbitmq-server-0.log
...
2016-10-11 01:29:59 DEBUG juju-log amqp:27: Hardening function 'install'
2016-10-11 01:29:59 DEBUG juju-log amqp:27: Hardening function 'upgrade_charm'
2016-10-11 01:29:59 DEBUG juju-log amqp:27: Hardening function 'config_changed'
2016-10-11 01:29:59 DEBUG juju-log amqp:27: Hardening function 'update_status'
2016-10-11 01:30:00 INFO amqp-relation-changed Error: unable to connect to node rabbit@ubuntu: nodedown
2016-10-11 01:30:00 INFO amqp-relation-changed
2016-10-11 01:30:00 INFO amqp-relation-changed DIAGNOSTICS
2016-10-11 01:30:00 INFO amqp-relation-changed ===========
2016-10-11 01:30:00 INFO amqp-relation-changed
2016-10-11 01:30:00 INFO amqp-relation-changed attempted to contact: [rabbit@ubuntu]
2016-10-11 01:30:00 INFO amqp-relation-changed
2016-10-11 01:30:00 INFO amqp-relation-changed rabbit@ubuntu:
2016-10-11 01:30:00 INFO amqp-relation-changed * unable to connect to epmd (port 4369) on ubuntu: nxdomain (non-existing domain)
2016-10-11 01:30:00 INFO amqp-relation-changed
2016-10-11 01:30:00 INFO amqp-relation-changed
2016-10-11 01:30:00 INFO amqp-relation-changed current node details:
2016-10-11 01:30:00 INFO amqp-relation-changed - node name: 'rabbitmq-cli-20529@juju-84f95a-15'
2016-10-11 01:30:00 INFO amqp-relation-changed - home dir: /var/lib/rabbitmq
2016-10-11 01:30:00 INFO amqp-relation-changed - cookie hash: Grmb/HfpexA0abUh5/acVQ==
2016-10-11 01:30:00 INFO amqp-relation-changed
2016-10-11 01:30:00 DEBUG juju-log amqp:27: Command '['/usr/sbin/rabbitmqctl', 'list_vhosts']' returned non-zero exit status 2
2016-10-11 01:30:00 DEBUG juju-log amqp:27: Running ['/usr/sbin/rabbitmqctl', 'add_vhost', u'openstack']
2016-10-11 01:30:00 INFO amqp-relation-changed Error: unable to connect to node rabbit@ubuntu: nodedown
2016-10-11 01:30:00 INFO amqp-relation-changed
2016-10-11 01:30:00 INFO amqp-relation-changed DIAGNOSTICS
2016-10-11 01:30:00 INFO amqp-relation-changed ===========
2016-10-11 01:30:00 INFO amqp-relation-changed
2016-10-11 01:30:00 INFO amqp-relation-changed attempted to contact: [rabbit@ubuntu]
2016-10-11 01:30:00 INFO amqp-relation-changed
2016-10-11 01:30:00 INFO amqp-relation-changed rabbit@ubuntu:
2016-10-11 01:30:00 INFO amqp-relation-changed * unable to connect to epmd (port 4369) on ubuntu: nxdomain (non-existing domain)
2016-10-11 01:30:00 INFO amqp-relation-changed
2016-10-11 01:30:00 INFO amqp-relation-changed
2016-10-11 01:30:00 INFO amqp-relation-changed current node details:
2016-10-11 01:30:00 INFO amqp-relation-changed - node name: 'rabbitmq-cli-20656@juju-84f95a-15'
2016-10-11 01:30:00 INFO amqp-relation-changed - home dir: /var/lib/rabbitmq
2016-10-11 01:30:00 INFO amqp-relation-changed - cookie hash: Grmb/HfpexA0abUh5/acVQ==
2016-10-11 01:30:00 INFO amqp-relation-changed
2016-10-11 01:30:01 INFO amqp-relation-changed Segmentation fault (core dumped)
2016-10-11 01:30:01 INFO amqp-relation-changed Traceback (most recent call last):
2016-10-11 01:30:01 INFO amqp-relation-changed File "/var/lib/juju/agents/unit-rabbitmq-server-0/charm/hooks/amqp-relation-changed", line 765, in <module>
2016-10-11 01:30:01 INFO amqp-relation-changed hooks.execute(sys.argv)
2016-10-11 01:30:01 INFO amqp-relation-changed File "/var/lib/juju/agents/unit-rabbitmq-server-0/charm/hooks/charmhelpers/core/hookenv.py", line 715, in execute
2016-10-11 01:30:01 INFO amqp-relation-changed self._hooks[hook_name]()
2016-10-11 01:30:01 INFO amqp-relation-changed File "/var/lib/juju/agents/unit-rabbitmq-server-0/charm/hooks/amqp-relation-changed", line 212, in amqp_changed
2016-10-11 01:30:01 INFO amqp-relation-changed admin=settings.get('admin', False))
2016-10-11 01:30:01 INFO amqp-relation-changed File "/var/lib/juju/agents/unit-rabbitmq-server-0/charm/hooks/amqp-relation-changed", line 153, in configure_amqp
2016-10-11 01:30:01 INFO amqp-relation-changed rabbit.create_vhost(vhost)
2016-10-11 01:30:01 INFO amqp-relation-changed File "/var/lib/juju/agents/unit-rabbitmq-server-0/charm/hooks/rabbit_utils.py", line 177, in create_vhost
2016-10-11 01:30:01 INFO amqp-relation-changed rabbitmqctl('add_vhost', vhost)
2016-10-11 01:30:01 INFO amqp-relation-changed File "/var/lib/juju/agents/unit-rabbitmq-server-0/charm/hooks/rabbit_utils.py", line 321, in rabbitmqctl
2016-10-11 01:30:01 INFO amqp-relation-changed subprocess.check_call(cmd)
2016-10-11 01:30:01 INFO amqp-relation-changed File "/usr/lib/python2.7/subprocess.py", line 541, in check_call
2016-10-11 01:30:01 INFO amqp-relation-changed raise CalledProcessError(retcode, cmd)
2016-10-11 01:30:01 INFO amqp-relation-changed subprocess.CalledProcessError: Command '['/usr/sbin/rabbitmqctl', 'add_vhost', u'openstack']' returned non-zero exit sta
tus 139
2016-10-11 01:30:01 ERROR juju.worker.uniter.operation runhook.go:107 hook "amqp-relation-changed" failed: exit status 1
今回のエラーでは、 rabbitmq の管理コマンド rabbitmqctl
を実行する際に使われる、接続先ホスト名の解決に失敗していました。 rabbit@ubuntu
ではなく rabbit@juju-84f95a-15
に接続してほしい訳です。
調べたところ RabbitMQ の設定ファイルを書き変えれば解決できました。
$ juju ssh rabbitmq-server/0
--- (以下、仮想マシン上での操作) ---
ubuntu@juju-84f95a-15$ hostname
juju-84f95a-15
ubuntu@juju-84f95a-15$ sudo vim /etc/rabbitmq/rabbitmq-env.conf
—-> 最終行を書き換え
---
#RABBITMQ_NODENAME=rabbit@ubuntu
RABBITMQ_NODENAME=rabbit@juju-84f95a-15
---
ubuntu@juju-84f95a-15$ sudo service rabbitmq-server restart
設定ファイルの反映後、5分毎に juju からコマンドが呼ばれるのを待ちます。
ホスト側で
$ watch juju status
などとしておけば状況が掴みやすいでしょう。
※ なお、 /etc/hosts
にホスト名 ubuntu
を追加しただけでは、上記問題は解決しませんでした。
2. conjure-up が途中でエラーになって終了したとき
rabbitmq-server の立ち上げに失敗するなどエラーが出てしまうと conjure-up は終了してしまいます。
本当は全ユニットが立ち上がった後にSSHキーファイルをコピーしたり dashboard へのアクセスを可能にしたりと、複数のステップがあるのですが、そこに行き着く前に終了する場合もあります。
そんなときは仕方が無いので手動で各ステップを実行していきます。
$ cd ~/.cache/conjure-up/openstack-novalxd/steps
$ ./step-03_keypair
Connection to 10.19.198.100 closed.
{"message": "SSH Keypair is now imported and accessible when creating compute nodes.", "returnCode": 0, "isComplete": true}Connection to 10.19.198.100 closed.
$ ./step-04_neutron
{"message": "Neutron networking is now configured and is available to you during instance creation.", "returnCode": 0, "isComplete": true}Connection to 10.19.198.100 closed.
$ ./step-05_horizon
{"message": "Login to Horizon: http://10.19.198.23/horizon l: admin p: openstack", "returnCode": 0, "isComplete": true}
3. OpenStack を最初からデプロイし直したいとき
conjure-up は一度デプロイすると ~/.cache/conjure-up
下に設定ファイルとログを保管します。
2度目の実行からは設定ファイルを元にデプロイし直せますが、デプロイの途中でエラーが起きて中断しても、はじめからやり直しになります。(この辺なんとかして欲しいですが)
真っさらな状態に戻すなら、 Juju をモデルごと消せばよさそうです。
モデル一覧を確認します。
$ juju models
CONTROLLER: bobcat
MODEL OWNER STATUS MACHINES CORES ACCESS LAST CONNECTION
controller admin@local available 1 - admin just now
mite* admin@local available 16 - admin 2 minutes ago
選択されている mite モデルを消します。
$ juju destroy-model mite
WARNING! This command will destroy the "mite" model.
This includes all machines, applications, data and other resources.
Continue [y/N]? y
$ juju models
CONTROLLER: bobcat
MODEL OWNER STATUS MACHINES CORES ACCESS LAST CONNECTION
controller admin@local available 1 - admin just now
mite admin@local destroying 16 - admin 1 minute ago
conjure-up の設定ファイルを消します。
$ rm -rf ~/.cache/conjure-up
これでいいはず。
4. 一度作成した ZFS のファイルシステムを削除したいとき
openstack
という名前の zfs プールは以下のコマンドで削除できます。
$ sudo zfs destroy -r openstack
$ sudo zpool destroy openstack
参考文献
- LXD 2.0: LXDについて [1/12] - Qiita
- DockerだけじゃないContainersの世界 - Qiita
- 第288回 デプロイツール「Juju」を使って大魔術師を目指そう : Ubuntu Weekly Recipe
- ZFS on Linuxで高信頼なストレージを作る(Ubuntu 14.04) - Qiita
- Removing services, units and environments | Documentation | Juju
- openstack lxd | Juju
- Openstack on LXD - OpenStack Charms Guide 0.0.1.dev11 documentation