OpenStack MagnumでDockerクラスタを構築してみた(インストール編)

こんにちは！ bbrfkr(ビビリフクロウ)と申します。とあるSIerでインフラ構築・運用・保守の自動化適用推進をやっています。その一環でコンテナ基盤についても構築・運用・保守のナレッジを増やしていこうという動きがあり、今回は自身の興味でOpenStack Magnumを試しに使ってみようと思い至りました。せっかく試してみたのでOpenStack Magnumのインストール・使い方を2回に分けて共有させていただきます。つまずきポイントを共有出来たら幸いです。

# OpenStack Magnumとは
OpenStack Magnumとは何かについてを簡単に説明いたします。そもそもOpenStackとは AWSのようなクラウド基盤を構築するためのオープンソースソフトウェアです。

![openstack_img.png](https://qiita-image-store.s3.amazonaws.com/0/151015/9c74d56f-b539-67ad-2a69-decc4dd19703.png)

OpenStackはハイパバイザおよび仮想マシンを管理する機能、仮想ネットワークを管理する機能、ストレージを管理する機能など、様々な構成要素(コンポーネント)の集合体で成り立っています。代表的なコンポーネントには以下のようなものがあります。

|コンポーネント名|機能|AWS相当コンポーネント・機能|
|---|---|---|
|Keystone|ユーザ管理や認証を行う|IAM|
|Glance|仮想マシンイメージの管理を行う|AMI|
|Nova|ハイパバイザや仮想マシンの管理を行う|EC2|
|Neutron|仮想ネットワークの管理を行う|VPC|
|Horizon|Web UIを提供する|Management Console|
|Cinder|ブロックストレージを管理する|EBS|
|Swift|オブジェクトストレージを管理する|S3|
|Heat|クラウド環境のオーケストレーションを行う|CloudFormation|

Magnumもこれらのコンポーネントのうちの一つです。Magnumは**コンテナ実行基盤の管理**を行います。具体的にはKubernetes、Docker Swarm、Mesosといったコンテナオーケストレータをデプロイし、そのライフサイクルの管理を行います。AWSにおけるECS(Elastic Container Service)に相当するコンポーネントになります。

Magnumがコンテナ実行基盤をデプロイする仕組みを簡単に説明します。MagnumにはCluster driverという構成要素があります。これは特定のLinuxディストリビューションをプロビジョニングし、その上で特定のコンテナオーケストレータをデプロイするために必要なソフトウェアなのですが、この中にOpenStack Heatで利用できるHOTテンプレート - いわばコンテナ実行基盤の設計書 - が含まれています。MagnumはこのHOTテンプレートを用いてHeatにコンテナ実行基盤のデプロイ指示を出し、コンテナ実行基盤のデプロイを実現しています。

![magnum_deploy.png](https://qiita-image-store.s3.amazonaws.com/0/151015/27d8eaa9-d3b8-149c-0de5-f44089a4d7f7.png)

# OpenStack Magnumのインストール
では、Magnumをインストールする具体的な手順を説明します。本手順は私、bbrfkrが動作することを確認できた手順であり、[公式手順](https://docs.openstack.org/magnum/latest/install/install-guide-from-source.html)とは若干異なることをご了承ください。

## 前提条件
まず、Magnumをインストールする前に既存のOpenStack環境に以下の依存コンポーネントがインストールされているか確認してください。

* Keystone
* Glance
* Nova
* Neutron
* Horizon
* Cinder (コンテナのルートディスク用ストレージを切るのに必要)
* Heat
* Barbican (APIサーバ用の証明書作成に必要)

また、今回の手順はOSはCentOS7.4、OpenStackリリースはPikeに対するものになりますので、ご了承ください。

## インストール手順
以下、全てコントローラノードにて作業します。

### ボリュームタイプの作成

* Cinderに少なくとも一つのボリュームタイプを定義する (ボリュームタイプについては[ここ](http://blog.bit-isle.jp/bird/2013/10/26)が詳しいです) [^1] 

```
# cinder type-create VOLUME_TYPE
# cinder type-key VOLUME_TYPE set volume_backend_name=BACKEND_NAME
```

### データベースの作成

* DBMSにログイン

```
# mysql -u root -p
```

* `magnum`データベースの作成

```
CREATE DATABASE magnum;
```

* `magnum`データベースへのアクセス権限付与 (`MAGNUM_DBPASS`は適当な値に置き換えてください)

```
GRANT ALL PRIVILEGES ON magnum.* TO 'magnum'@'controller' IDENTIFIED BY 'MAGNUM_DBPASS';
GRANT ALL PRIVILEGES ON magnum.* TO 'magnum'@'%' IDENTIFIED BY 'MAGNUM_DBPASS';
```

* DBMSからログアウト

```
\q
```

### サービスとエンドポイントの作成

* `magnum`ユーザの作成

```
# openstack user create --domain default --password-prompt magnum
```

* `magnum`ユーザに`admin`ロールを付与

```
# openstack role add --project service --user magnum admin
```

* `magnum`サービスの作成

```
# openstack service create --name magnum \
  --description "OpenStack Container Infrastructure Management Service" \
  container-infra
```

* エンドポイントの作成 (`CONTROLLER_IP`はコントローラノードのIPに置き換えてください)

```
# openstack endpoint create --region RegionOne \
  container-infra public http://CONTROLLER_IP:9511/v1
# openstack endpoint create --region RegionOne \
  container-infra internal http://CONTROLLER_IP:9511/v1
# openstack endpoint create --region RegionOne \
  container-infra admin http://CONTROLLER_IP:9511/v1
```

### `magnum`ドメインの作成

* `magnum`ドメインの作成

```
# openstack domain create --description "Owns users and projects \
  created by magnum" magnum
```

* `magnum_domain_admin`ユーザを作成

```
# openstack user create --domain magnum --password-prompt \
  magnum_domain_admin
```

* `magnum_domain_admin`ユーザに`admin`ロールを付与

```
# openstack role add --domain magnum --user-domain magnum \
  --user magnum_domain_admin admin
```

### コア機能のインストールと設定

* 依存パッケージのインストール

```
# yum install python-devel openssl-devel mysql-devel \
              libxml2-devel libxslt-devel postgresql-devel git \
              libffi-devel gettext gcc
```

* OSユーザ`magnum`の作成

```
# groupadd --system magnum
# useradd --home-dir "/var/lib/magnum" \
      --create-home \
      --system \
      --shell /bin/false \
      -g magnum \
      magnum
```

* ログディレクトリと設定ファイル用ディレクトリの作成

```
# mkdir -p /var/log/magnum
# mkdir -p /etc/magnum
```

* ディレクトリの権限設定

```
# chown magnum:magnum /var/log/magnum
# chown magnum:magnum /var/lib/magnum
# chown magnum:magnum /etc/magnum
```

* virtualenvのインストールとMagnum用の仮想環境の作成

```
# easy_install -U virtualenv
# su -s /bin/sh -c "virtualenv /var/lib/magnum/env" magnum
```

* 依存pythonモジュールのインストール

```
# su -s /bin/sh -c "/var/lib/magnum/env/bin/pip install tox pymysql \
  python-memcached" magnum
```

* Magnumリポジトリのクローン

```
# cd /var/lib/magnum
# git clone https://git.openstack.org/openstack/magnum.git
# chown -R magnum:magnum magnum
# cd magnum
```

* リポジトリをある特定コミットに戻す [^2]

```
# git reset --hard d71f6c348a8ee591ebabcdb839812c20a3da805e
```

* Mesos用Hotテンプレートの修正 [^3]

```magnum/drivers/mesos_ubuntu_v1/templates/mesoscluster.yaml
  secgroup_master:
    type: OS::Neutron::SecurityGroup
    properties:
      rules:
        - protocol: icmp
        - protocol: tcp
          port_range_min: 22
          port_range_max: 22
        - protocol: tcp
          remote_mode: remote_group_id
        - protocol: tcp         # ここ追加
          port_range_min: 2181  # ここ追加
          port_range_max: 2181  # ここ追加
        - protocol: tcp
          port_range_min: 5050
          port_range_max: 5050
        - protocol: tcp
          port_range_min: 8080
          port_range_max: 8080
```

* `api-paste.ini`のコピー

```
# su -s /bin/sh -c "cp etc/magnum/api-paste.ini /etc/magnum" magnum
```

* サンプル設定ファイルの生成

```
# su -s /bin/sh -c "/var/lib/magnum/env/bin/tox -e genconfig" magnum
# su -s /bin/sh -c "cp etc/magnum/magnum.conf.sample /etc/magnum/magnum.conf" magnum
```

* `policy.yaml`の生成とコピー

```
# su -s /bin/sh -c "/var/lib/magnum/env/bin/tox -e genpolicy" magnum
# su -s /bin/sh -c "cp etc/magnum/policy.yaml.sample /etc/magnum/policy.yaml" magnum
```

* 設定ファイルの編集。各パラメータは以下の通り置き換えてください
    * RABBIT_PASS: RabbitMQのパスワード
    * CONTROLLER_IP: コントローラノードのIP
    * CONTROLLER_HOSTNAME: コントローラノードのホスト名
    * VOLUME_TYPE: 作成したCinderのボリュームタイプ
    * MAGNUM_PASS: `magnum`ユーザのパスワード
    * DOMAIN_ADMIN_PASS: `magnum_domain_admin`ユーザのパスワード

```/etc/magnum/magnum.conf
[DEFAULT]
transport_url = rabbit://openstack:RABBIT_PASS@CONTROLLER_HOSTNAME

[api]
host = CONTROLLER_IP

[certificates]
cert_manager_type = barbican

[cinder]
default_docker_volume_type = VOLUME_TYPE

[cinder_client]
region_name = RegionOne

[database]
connection = mysql+pymysql://magnum:MAGNUM_DBPASS@CONTROLLER_HOSTNAME/magnum

[keystone_authtoken]
memcached_servers = CONTROLLER_HOSTNAME:11211
auth_version = v3
auth_uri = http://CONTROLLER_HOSTNAME:5000/v3
project_domain_name = default
project_name = service
user_domain_name = default
password = MAGNUM_PASS
username = magnum
auth_url = http://CONTROLLER_HOSTNAME:35357
auth_type = password
admin_user = magnum
admin_password = MAGNUM_PASS
admin_tenant_name = service

[trust]
trustee_domain_name = magnum
trustee_domain_admin_name = magnum_domain_admin
trustee_domain_admin_password = DOMAIN_ADMIN_PASS

[oslo_concurrency]
lock_path = /var/lib/magnum/tmp

[oslo_messaging_notifications]
driver = messaging

[oslo_policy]
policy_file = /etc/magnum/policy.yaml
```

* データベースのマイグレーション

```
# su -s /bin/sh -c "/var/lib/magnum/env/bin/magnum-db-manage upgrade" magnum
```

* Magnum用のログローテーション設定

```
# cd /var/lib/magnum/magnum
# cp doc/examples/etc/logrotate.d/magnum.logrotate /etc/logrotate.d/magnum
```

### サービス登録と起動設定

* サービス登録

```
# cp doc/examples/etc/systemd/system/magnum-api.service \
  /etc/systemd/system/magnum-api.service
# cp doc/examples/etc/systemd/system/magnum-conductor.service \
  /etc/systemd/system/magnum-conductor.service
```

* サービス自動起動設定と起動

```
# systemctl enable magnum-api
# systemctl enable magnum-conductor
# systemctl start magnum-api
# systemctl start magnum-conductor
# systemctl status magnum-api
# systemctl status magnum-conductor
```

### Horizon拡張のインストール
デフォルトではHorizonにMagnumを操作する項目がないので、これを追加します。

* リポジトリのクローンとチェックアウト

```
# cd ~
# git clone https://github.com/openstack/magnum-ui
# cd magnum-ui
# git checkout -b pike remotes/origin/stable/pike
```

* インストール

```
# python setup.py install
# cp magnum_ui/enabled/_1370_project_container_infra_panel_group.py /usr/share/openstack-dashboard/openstack_dashboard/local/enabled
# cp magnum_ui/enabled/_1371_project_container_infra_clusters_panel.py /usr/share/openstack-dashboard/openstack_dashboard/local/enabled
# cp magnum_ui/enabled/_1372_project_container_infra_cluster_templates_panel.py /usr/share/openstack-dashboard/openstack_dashboard/local/enabled
```

* Apache、Memcachedの再起動

```
# systemctl restart httpd memcached
```

* `libgnome-keyring`のアンインストール [^4]

```
# yum remove libgnome-keyring
```

# 使い方編へ続く
以上で、OpenStack PikeリリースにMagnumをインストールすることができたかと思います。Horizonからの操作感については次回の使い方編でお伝えしたいと思います。

[^1]: もし一つもボリュームタイプが定義されていないと、Magnumがコンテナのルートディスク用ストレージを切るときに`None`という名前のボリュームタイプを探してしまい、そのようなボリュームタイプは存在しないと怒られるため。

[^2]: [https://github.com/openstack/magnumのf89cc4c98cd231b26e94e85526c59f7107ec7dd7のコミット](https://github.com/openstack/magnum/commit/f89cc4c98cd231b26e94e85526c59f7107ec7dd7)で、KubernetesをFedora Atomic Hostに作成する場合のAPIサーバの指定が`/etc/sysconfig/kubelet`から`/etc/kubernetes/kubeconfig.yaml`に変更になったのですが、私の環境ではこのコミットが原因でAPIサーバをkubeletが探せなくなったので、直前のコミットに戻しています。

[^3]: Magnumの持っているHOTテンプレートではzookeeperの通信用ポートの開いていないセキュリティグループを作ってしまい、MasterにSlaveを登録できなかったため、当該ポートの開いたセキュリティグループを作るよう、HOTテンプレートを修正しています。

[^4]: 私の環境だと、こちらをアンインストールしないとHorizonに全くアクセスできない状態になったため。