ConoHaでFloating IPを使う

# Floating IP

ConoHaのプライベートネットワークではFloating IPと言う機能が使えます。これは仮想サーバーのネットワークインターフェイスに、IPアドレスを自由に割り当てることができる機能です。特定のIPアドレスを割り当てたり、サーバーAに割り当てられたアドレスをサーバーBに付け替えたりすることができます。その間約数秒でほとんど通信断もありません。

「ConoHaのプライベートネットワークはIPアドレスが固定」と思っている方も多いと思いますが、実はもっと柔軟に構築できるんです。ただ、残念ながらコントロールパネルからこの操作は行えないので、API経由で行う必要があります。

## 準備

今回は、特定IPアドレスの割り当てとIPアドレスの付け替えを試してみます。以下のように仮想サーバー2台を用意して、プライベートネットワークに接続しておいて下さい。ネットワークセグメントは「192.168.1.0/24」にしておきます。やり方はオフィシャルのドキュメントを見て下さい。

* [プライベートネットワークを使う](https://www.conoha.jp/conoben/archives/9132)

<img width="892" alt="floating2.png" src="https://qiita-image-store.s3.amazonaws.com/0/44152/a070645c-0c0a-1e5f-b700-f9fc3bb69c88.png">

## 構成

Server-AとServer-Bには192.168.1.1と192.168.1.2というIPアドレスが割り当てられています。これはコントロールパネルからプライベートネットワークを作ると、デフォルトで割り当てられるアドレスです。今回はこの構成で、

1. Server-AのIPアドレスを192.168.1.10に変更する
2. Server-AのIPアドレス(192.168.1.10)をServer-Bに付け替える

と言うことをやってみます。

### OpenStack CLIツールのインストール

ConoHaのAPIはOpenStackに準拠しています(APIについては[こちらのスライド](http://www.slideshare.net/hironobusaitoh/conohaopenstack-api)もご覧下さい)。curlなどから叩いても良いのですが、もう少し楽をしたいので、OpenStackのコマンドラインツールをServer-Cにインストールします。Server-Cにログインして以下のコマンドを実行します。Ubuntuなのでaptですが、CentOSの場合はyumを使います。

```shell-session
# Python関連パッケージのインストール
apt-get install python python-dev python-pip

# OpenStackツールのインストール(今回はこの3つを使います)
pip install python-keystoneclient python-novaclient python-neutronclient
```

### 認証情報のセット

ConoHa APIに接続するための認証情報を環境変数でセットします。以下のコマンド群をServer-Cのシェル上で実行してください。情報はConoHaのコントロールパネルの「API」メニューにあります。

```shell-session
export OS_USERNAME=[APIユーザー名]
export OS_TENANT_NAME=[APIテナント名]
export OS_PASSWORD=[APIパスワード]
export OS_AUTH_URL=[Identity Serviceエンドポイント]
```

## プライベート側に自由にIPアドレスを割り当てる

ConoHaのコントロールパネルから仮想サーバーにプライベートネットワークを割り当てると、IPアドレスが自動的に決められてしまいます。これをNetwork APIを使って自由に決めてみましょう。ConoHaのAPIはOpenStackに準拠していて、OpenStackのネットワークを管理するコンポーネントは「Neutron」という名前です。

先ほどOpenStackツールをインストールしましたが、その名もずばり"neutron"と言うコマンドがインストールされています。まずサブネットの一覧を取得してみます。

サブネット一覧を取得する

```shell-session
$ neutron subnet-list
```

なにやらずらずらと一覧が出力されます。これを理解するために、サブネットとポートと言う概念について簡単に説明します。

OpenStackにおいて「サブネット」というのは、特定のネットワークセグメントを管理する単位です。今回作成したプライベートネットは「192.168.1.0/24」で、ちゃんとsubnet-listの実行結果にも含まれています。

```shell-session
neutron subnet-list
+--------------------------------------+---------------------------+-------------------------+--------------------------------------------------------------------------------------+
| id                                   | name                      | cidr                    | allocation_pools                                                                     |
+--------------------------------------+---------------------------+-------------------------+--------------------------------------------------------------------------------------+
(中略)
| e135c0a5-9a6a-4660-a710-a3b0ddc1482f | local-192-168-1-0-24      | 192.168.1.0/24          | {"start": "192.168.1.1", "end": "192.168.1.254"}                                    
```

一方で「ポート」というのは、サブネットから特定のIPアドレスレンジを切り出した単位です。そして、ポートは仮想マシンの仮想インターフェイスに対してアタッチされます。つまり、コントロールパネルからプライベートネットワークを作ると192.168.1.1が割り当てられますが、これは「192.168.1.0/24と言うサブネットから」「192.168.1.1が割り当てられたポートが作成され」「それが仮想マシンの仮想ネットワークインターフェイスにアタッチされている」ということです。

では、port-listサブコマンドで一覧を取得してみましょう。

ポート一覧を取得する

```shell-session
$ neutron port-list
```

実行結果

```shell-session
+--------------------------------------+----------------------------+-------------------+-----------------------------------------------------------------------------------------------------------+
| id                                   | name                       | mac_address       | fixed_ips                                                                                                 |
+--------------------------------------+----------------------------+-------------------+-----------------------------------------------------------------------------------------------------------+
| (中略)
| 4dabccf7-2ff4-4a55-862f-45b53d2c734a | local-gnct47070904         | fa:16:3e:7a:5b:3d | {"subnet_id": "e135c0a5-9a6a-4660-a710-a3b0ddc1482f", "ip_address": "192.168.1.1"}
```

IPアドレスは192.168.1.1や192.168.1.2などが出てきたはずです。これらのポートは仮想マシンにアタッチされています。

> ちなみに、仮想マシンにどのポートがアタッチされているかを調べるには、OpenStackツールのnovaと言うコマンドを使います。「pip install openstack-novaclient」でインストールして「nova interface-list」サブコマンドを調べてみて下さい。

さて、仮想マシンに好みのIPアドレスを割り当てるには、このポートに割り当てたIPアドレスを変更します。
これにはport-updateサブコマンドを使います。このサブコマンドは機能が多く、書式が少し複雑になるので注意です。

port-updateコマンドの書式(今回使うオプションのみ)

```shell-session
neutron port-update --fixed-ip subnet=[サブネットのUUID],ip_address=[割り当てるIPアドレス][ポートのUUID]
```

subnet=にはport-listサブコマンドの結果にある"subnet_id"を指定し、ip_address=には割り当てるIPアドレスを指定します。たとえば192.168.1.10を指定して実行してみます。

```shell-session
$ neutron port-update \
--fixed-ip subnet=e135c0a5-9a6a-4660-a710-a3b0ddc1482f,ip_address=192.168.1.10 \
4dabccf7-2ff4-4a55-862f-45b53d2c734a
Updated port: 4dabccf7-2ff4-4a55-862f-45b53d2c734a
```
「Updated port: 」と返ってくれば成功です。

実行後にUpdated portと出れば成功です。port-listを再実行してIPアドレスが変わっていることを確認してみて下さい。また、ConoHaのコントロールパネル上でもIPアドレスが変わっていることがわかります。
あとは、OS側でネットワークの設定を変更すればOKです。

<img width="635" alt="floating3.png" src="https://qiita-image-store.s3.amazonaws.com/0/44152/7128bb78-fe64-e74b-952b-d965167a0ce9.png">

ポートには複数のIPアドレスを割り当てることも可能です。その場合は--fixed-ipオプションを繰り返して指定します。

```shell-session
neutron port-update \
--fixed-ip subnet=e135c0a5-9a6a-4660-a710-a3b0ddc1482f,ip_address=192.168.1.1 \
--fixed-ip subnet=e135c0a5-9a6a-4660-a710-a3b0ddc1482f,ip_address=192.168.1.10 \
4dabccf7-2ff4-4a55-862f-45b53d2c734a
```

上記を実行することで、最初から割り当てられていた192.168.1.1と、新規に割り当てた192.168.1.10両方を使うことができます。

## IPアドレスの付け替えを行う

IPアドレスの付け替えといっても簡単です。port-updateコマンドを複数回実行して、Server-Aに割り当てていたIPアドレスをServer-Bに付け替えてあげれば良いのです。

```shell-session
# Server-Aから192.168.1.10の割り当てを外す(≈192.168.1.1のみにする)
neutron port-update \
--fixed-ip subnet=e135c0a5-9a6a-4660-a710-a3b0ddc1482f,ip_address=192.168.1.1 \
4dabccf7-2ff4-4a55-862f-45b53d2c734a

# Server-Bに192.168.1.10を割り当てる
neutron port-update \
--fixed-ip subnet=e135c0a5-9a6a-4660-a710-a3b0ddc1482f,ip_address=192.168.1.2 \
--fixed-ip subnet=e135c0a5-9a6a-4660-a710-a3b0ddc1482f,ip_address=192.168.1.10 \
56783624-8b18-438a-bcf8-860e6a33cdc1
```

仮想ネットワーク側はこれでよいのですが、MACアドレスが変わるので、このIPアドレスを使う仮想マシンはARPキャッシュをクリアする必要があります。以下のコマンドです。

```shell-session
arp -d 192.168.1.10
```
## 参考情報

今回はOpenStackのCLIツールを使いましたが、APIを直接叩いても同じことができます。参考までに関連するConoHaのAPIリファレンスを載せておきます。

### Compute Service

* [VM一覧取得](https://www.conoha.jp/docs/compute-get_vms_list.html)
* [アタッチ済みポート一覧取得](https://www.conoha.jp/docs/compute-get_attached_ports_list.html)
* [ポートアタッチ(VMに追加IPv4アドレスを割り当て)](https://www.conoha.jp/docs/compute-attach_port.html)
* [ポートデタッチ(VMに割り当てた追加IPv4アドレスを削除)](https://www.conoha.jp/docs/compute-attach_port.html)

### Network Service

* [サブネット一覧取得](https://www.conoha.jp/docs/neutron-get_subnets_list.html)
* [サブネットの払い出し(ローカルネット用)](https://www.conoha.jp/docs/neutron-add_subnet.html)
* [サブネットの削除](https://www.conoha.jp/docs/neutron-remove_subnet.html)
* [ポート一覧取得](https://www.conoha.jp/docs/neutron-get_ports_list.html)
* [ポート追加](https://www.conoha.jp/docs/neutron-add_port.html)
* [ポート更新/セキュリティグループ割り当て](https://www.conoha.jp/docs/neutron-update_port.html)
* [ポート削除](https://www.conoha.jp/docs/neutron-remove_port.html)

## おわりに

今回は単純にIPアドレスを更新しただけでしたが、Floating IPを使うと柔軟にネットワークを作ることができることがわかります。実際、サブネットやポートは複数作成できますし、ポートをVMにアタッチするのはオンライン(仮想マシンの停止なし)でできたりもします。Blue/Greenデプロイみたいなこともできそうですし、夢が広がりますね。