Ubuntu OpenStack Installerは、Canonical社が開発しているOpenStackのインストーラーです。私はUbuntuユーザーなのでこれをよく使っているのですが、構築が完了するまでに非常に時間がかかるのが難点でした(数時間とか)。これを改善したワークアラウンドを紹介します。
ちなみに、他のOpenStackインストーラーは
とかがあります。
なぜ遅いのか
このインストーラーは内部でlxcやjujuを利用していて、それらがlxcのコンテナイメージやkvmのマシンイメージを cloud-images.ubuntu.com からダウンロードします。このサーバーはイギリスにあるようで、日本から非常に遠いです。ひどいと100KB/secくらいしか出ません。イメージファイルは数百MBあるので、ダウンロードだけでかなり時間がかかります。
こういうときはミラーサーバを使うべきです。Ubuntuは非常に多くのミラーがあるのですが、ほとんどがaptとISOイメージで、コンテナイメージのミラーは非常に少ないです。日本では唯一、富山大学がミラーです。
日本国内のダウンロードサイト
(UEC iamgeのところ)
そしてUbuntu OpenStack Installerには、ミラーを設定する項目はありません。また、内部で呼び出しいているlxcやjujuなども、ミラーの設定はあるもののインストーラーが隠蔽してしまうので、残念ながら設定ができませんでした。
仕方ないのでミラーを設定するのでは無く、あらかじめミラーからダウンロードして置いてキャッシュを作成しておき、インストーラーはキャッシュを利用するようなアプローチを取りました。
- インストーラーが最初に作成するlxcコンテナのイメージ(ダウンロードサイズ150MBくらい)を、ミラーサイトからダウンロードしてキャッシュを作成する。
- lxcコンテナ内でjujuが起動する仮想マシンイメージ(ダウンロードサイズ250MBくらい)を、ホスト側であらかじめダウンロードしておいてディレクトリ共有でコンテナ内で利用する。
手順
ではやってみます。ここではシングルノードへのインストールが前提です。オフィシャルのドキュメントも合わせて見て下さい。
動作確認はVMware上のUbuntu14.04LTSで行っています。
hiro@ubuntu14:~$ uname -a
Linux ubuntu14 4.2.0-27-generic #32~14.04.1-Ubuntu SMP Fri Jan 22 15:32:26 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
hiro@ubuntu14:~$ openstack-install --version
openstack-install 0.99.28
以下、色々解説も書きましたが、やること自体は少ないです。
1. 準備
openstack-installを実行する直前(Start the installationの前)までオフィシャルドキュメントの通りに進めます。
2. lxcのコンテナイメージのキャッシュを作成する
lxcはコンテナを起動する際にコンテナイメージを必要とし、イメージのダウンロードの際には内部で /usr/share/lxc/templates/lxc-ubuntu-cloud が呼ばれます。中身はシェルスクリプトです。
そして、lxc-ubuntu-cloudはさらに内部でubuntu-cloudimg-queryを実行します。このコマンドはcloud-utilsパッケージに含まれるコマンドで、ホストのアーキテクチャーやUbuntuのリリース名を元にイメージのダウンロードとrootfsの展開を行います。これもシェルスクリプトです。
ubuntu-cloudimg-queryは環境変数 UBUNTU_CLOUDIMG_QUERY_BASEURL でミラーを指定することができます。しかし、日本のミラーにはコンテナイメージファイルはミラーされているものの、ubuntu-cloudimg-queryが利用するクエリファイルだけミラーされていません(なぜなのか...)
そこで、一度ミラーなしでubuntu-cloudimg-queryを実行しローカルにクエリのキャッシュを作り、次にlxc-ubuntu-cloudを実行してミラーからイメージをダウンロードするという段階を踏みます。
まず、ubuntu-cloudimg-queryを実行します。第一引数はUbuntuのリリース名(/etc/lsb-releaseに書いてあります)、第二引数はreleasedで固定、第三引数はホストのアーキテクチャです。
hiro@ubuntu14:~$ ubuntu-cloudimg-query trusty released amd64 > /dev/null
次にlxc-ubuntu-cloudでコンテナイメージをダウンロードします。環境変数UBUNTU_CLOUDIMG_QUERY_BASEURLを指定することで、ミラーからコンテナイメージがダウンロードされます。pathパラメータは必須のパラメータで、指定したディレクトリにrootfsが展開されますが、これは不要なので適当なディレクトリを指定しておきます。
UBUNTU_CLOUDIMG_QUERY_BASEURL=http://ubuntutym2.u-toyama.ac.jp/cloud-images/releases sudo -E /usr/share/lxc/templates/lxc-ubuntu-cloud --path=/tmp/hoge
そしてコンテナイメージが/var/cache/lxc/cloud-(リリース名)にキャッシュされていることを確認します。
hiro@ubuntu14:~$ sudo ls -l /var/cache/lxc/cloud-trusty
合計 122104
drwxr-xr-x 22 root root 4096 7月 26 11:59 rootfs
drwxr-xr-x 3 root root 4096 7月 26 12:04 tmp
-rw-r--r-- 1 root root 125023208 7月 15 06:03 ubuntu-14.04-server-cloudimg-amd64-root.tar.xz
3. 仮想マシンイメージをあらかじめダウンロードしておく
次に、jujuがlxc内部で使用する仮想マシンイメージを、あらかじめミラーからダウンロードしておきます。juju内部ではuvtoolが使われており、イメージの管理にはuvt-simplestreams-libvirtコマンドを使います。このコマンドもcloud-images.ubuntu.comからイメージをダウンロードするのでボトルネックになります。ミラーの指定は--sourceオプションで行います。
結論として、残念ながらjujuを使う場合において--sourceオプションを指定する方法はありません。このあたりです。
https://github.com/juju/juju/blob/69d8569f1da7a360851dc79d8b76549562e1b326/container/kvm/libvirt.go#L59
https://github.com/juju/juju/blob/69d8569f1da7a360851dc79d8b76549562e1b326/container/kvm/kvm.go#L146
なので方法論として、ホスト側であらかじめイメージをミラーからダウンロードしておいて、そのキャッシュディレクトリ(/var/lib/uvtool)をlxcコンテナ内のjujuと共有するようにします。
uvtoolをインストールする
hiro@ubuntu14:~$ sudo apt-get install uvtool
仮想マシンイメージをミラーからダウンロードする(オプションのreleaseとarchは使っているバージョンに合わせて下さい。)
hiro@ubuntu14:~$ uvt-simplestreams-libvirt sync --source=http://ubuntutym2.u-toyama.ac.jp/cloud-images/releases arch=amd64 release=trusty
何も出力されませんが、/var/lib/uvtool/ 配下にキャッシュファイルが作成されています。
hiro@ubuntu14:~$ ls -l /var/lib/uvtool/libvirt/images/
合計 845196
drwxr-xr-x 2 root root 4096 7月 26 19:24 ./
drwxr-xr-x 4 root root 4096 7月 26 12:48 ../
-rw------- 1 pollinate libvirtd 865468416 7月 26 16:40 x-uvt-b64-Y29tLnVidW50dS5jbG91ZDpzZXJ2ZXI6MTQuMDQ6YW1kNjQgMjAxNjA3MTQ=
4. cloud-initのテンプレートを修正する
インストーラーが使うcloud-initのuser-dataを修正します。 インストーラーがホストのuvtoolのディレクトリをホームディレクトリにマウントするので、/var/lib/にシンボリックリンクを作る必要があるからです。
sudo vi /usr/share/openstack/templates/userdata.yaml
最下行に以下の一行を追加します。YAMLなのでインデントに注意です。
{%- if https_proxy %}
- echo "export https_proxy={{ https_proxy }}" >> /home/ubuntu/.bashrc
- echo "export HTTPS_PROXY={{ https_proxy }}" >> /home/ubuntu/.bashrc
{%- endif %}
- "chown ubuntu:ubuntu /home/ubuntu /home/ubuntu/.bashrc"
- "ln -s /home/ubuntu/uvtool /var/lib/uvtool" ← この行
5. openstack-installを実行する
ようやくOpenStackのインストール開始です! openstack-installを実行する際に、環境変数を2つ指定します。
EXTRA_BIND_DIRS=/var/lib/uvtool USE_LXC_IMAGE_CACHE=1 sudo -E openstack-install
sudoに-Eオプションを付けることが必須です。これによりsudoから起動したコマンドに環境変数が引き継がれます。
EXTRA_BIND_DIRSは、インストーラーが作成するlxcコンテナが、ホストのディレクトリをマウントするよう指定するオプションです。ホストのuvtoolのキャッシュディレクトリをコンテナ内から使用するために指定しています。これはヘルプには書いてなくコード内にあります。
USE_LXC_IMAGE_CACHEはインストーラーがlxcイメージを起動する際に、キャッシュされたイメージファイルを使うことを強制するものです。挙動としては、インストーラーが内部で起動するlxc-createから-Fオプションが除外されます。これを指定しないと、openstack-installを実行する度にイメージのダウンロードが行われてしまいます。これはオフィシャルドキュメントに記述があります(Additional Tipsのところ)
あとは通常通りインストールを進めるだけです! インストール時間がかなり短くなってるはずです(数十分で終わる)