VIPなどで使用するOCI ComputeのセカンダリIPを考える

# 1. はじめに

以前セカンダリVNICのことを書いて、次はセカンダリIPと思っていたら、@NSO-KCさんに先を越されてしまった。と思ったら、さらに@mmarukawさんのエントリも登場。下書きしていたので、ほかと重複している部分もあるけど、自分なりに書いてみました。

ちなみにセカンダリVNICとセカンダリIPでは、まったく用途が違います。キリッ。

* @NSO-KCさん[[Oracle Cloud] ComputeのセカンダリIPのフェールオーバを試してみる](https://qiita.com/NSO-KC/items/4c06d78109ba5a8e0034)
* @mmarukawさん [[Oracle Cloud Infrastructure] Pacemakerを使って仮想IPを別ADのインスタンスに自動フェイルオーバーする](https://qiita.com/mmarukaw/items/66fac6c8e0843df6b7c0)
* [OCI ComputeにセカンダリVNICを追加する Part 1](https://qiita.com/yamada-hakase/items/a6d4d846e4cf4afb9453), [Part 2](https://qiita.com/yamada-hakase/items/6b0c49a0b2b3c5e4c4dd), [Part 3](https://qiita.com/yamada-hakase/items/abe8114d327c19c98acd)

### 1-1. 参考資料

* [プライベートIPアドレス](https://docs.oracle.com/cd/E97706_01/Content/Network/Tasks/managingIPaddresses.htm)
* [Private IP Addresses](https://docs.cloud.oracle.com/iaas/Content/Network/Tasks/managingIPaddresses.htm)
* [OracleCloudで考える高可用性アーキテクチャ](https://speakerdeck.com/mmarukaw/oracleclouddekao-erugao-ke-yong-xing-akitekutiya?slide=40)

# 2. セカンダリIPの用途は？

### 2-1. セカンダリIPとは

セカンダリIPとは、1つのVNIC割り当てた、2つ目以降のIPアドレスのこと。セカンダリIPを利用すると、1つのVNICに最大31個のIPアドレスを割り当てできる。

なお、インスタンス作成時に割り当てたプライベートIPを「プライマリIP」もしくは「プライベート・プライマリIP」と呼ぶ。

### 2-2. おもな用途
マニュアルにも書かれているように、この2つがおもな利用目的だ。

* インスタンスのフェイルオーバー
* 1つのインスタンスで、複数のサービスまたはエンドポイントの実行

この中でもセカンダリIPを仮想IPとして利用し、インスタンスのフェイルオーバーに使うのがもっとも一般的は利用方法だ。

外部アクセスのフェイルオーバー目的の場合、ReservedパブリックIPも利用できる。ただし手順が異なるので今回は紹介しない。

###2-3. 留意事項
[マニュアル](https://docs.oracle.com/cd/E97706_01/Content/Network/Tasks/managingIPaddresses.htm#Linux:)に書かれている制限事項から重要なものをピックアップすると以下のとおり。

* 一つのVNICに最大31個のセカンダリ・プライベートIPを割り当てられる
* VNICからセカンダリIPを削除すると、サブネットの利用可能なアドレス・プールに返される
* インスタンスもしくはVNICを削除すると、セカンダリIPも自動的に削除される。
* ネットワークの帯域幅はシェイプに依存している。セカンダリIPを増やしてもインスタンス帯域幅は変わらない
* セカンダリIPにReservedパブリックIPを割り当てられる

# 3. セカンダリIPを割り当てる

インスタンスにセカンダリIPを割り当ててみよう。セカンダリIPの割り当ては、OCI側の設定と、OS内部の設定が必要だ。この2つを設定して、はじめてセカンダリIPを利用できるようになる。

### 3-1. 管理コンソールでセカンダリIPを割り当てる

以下、管理コンソールの手順である。

1. 管理コンソールでComputeインスタンス詳細を表示する。
2. 「アタッチされたVNIC（Attached VNICs）」をクリックすると、インスタンスにアタッチしているVNICが表示される。
![2ndaryip01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/6421a785-e80a-89ed-8968-3a7b89572b94.png)
3. 左のリソースから「IPアドレス（IP Addresses）」を選択すると、VNICプライマリ・プライベートIPが表示される。
![2ndaryip02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/fb6cca4e-f8e3-e815-46f7-e1ca743cd462.png)
4. 「プライベートIPアドレスの割当て（Assign Private IP Address）」をクリックする。必要項目を入力し「割当て（Assign）」をクリックすればOCI側の作業は終了だ。
![2ndaryip03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/7d97a6d5-714f-5229-0dc8-99046ebde10c.png)

**プライベートIPアドレス（Private IP Adress）：**セカンダリIPとして設定するIPアドレス。インスタンスが属するサブネットCIDRレンジ内にする必要がある。
**別のVNICに割り当て済みの場合は割り当て解除（Unassign if already assigned to another VNIC）：**ここで入力したIPアドレスが、他のVNICに割り当てられていたときは強制解除する。
**ホスト名（Hostname）：**セカンダリIPのホスト名。VCN内でFQDNの名前解決が可能。

5.割り当てに成功すると以下のように表示される。
![2ndaryip04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/f04adc43-7f50-341c-1dfa-725504ebbb37.png)

### 3-2. Linux OSでセカンダリIPを割り当てる

ここではOracle Linux 7でセカンダリIPを割り当てる。Windowsの方法はマニュアルを見てほしい。

1. sshでログインしてIPアドレスを確認する。VNICのens3割り当てられているのはプライマリIPだけだ。

```shell-session
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc mq state UP group default qlen 1000
    link/ether 02:00:17:00:08:22 brd ff:ff:ff:ff:ff:ff
    inet 10.5.1.5/24 brd 10.5.1.255 scope global dynamic ens3
       valid_lft 54595sec preferred_lft 54595sec
```

2.ipコマンドでipアドレスを割り当てる。

```shell-session:シンタックス
ip addr add <address>/<subnet_prefix_len> dev <phys_dev> label <phys_dev>:<addr_seq_num>
```
ens3にセカンダリIP`10.5.1.30/24`を割り当てる。最後のaddr_seq_numは、重複しないゼロ以上の数値だ。

```shell-session
# ip addr add 10.5.1.30/24 dev ens3 label ens3:0
```

**参考：[ipコマンド チートシート](https://access.redhat.com/sites/default/files/attachments/rh_ip_command_cheatsheet_1214_jcs_print_ja4.pdf)**

3.確認すると、セカンダリIPが割り当てられている。

```shell-session
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc mq state UP group default qlen 1000
    link/ether 02:00:17:00:08:22 brd ff:ff:ff:ff:ff:ff
    inet 10.5.1.5/24 brd 10.5.1.255 scope global dynamic ens3
       valid_lft 64759sec preferred_lft 64759sec
    inet 10.5.1.30/24 scope global secondary ens3:0 ★この行
       valid_lft forever preferred_lft forever
```

4.正常に動作しているかは外部からping、もしくは以下のコマンドで確認できる。sshの場合は、セカンダリIPを設定したホスト名が返ってくれば、意図したインスタンスに接続できている。

```shell-session
$ ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i <秘密鍵> <割り当てたセカンダリIP> hostname
```

5.OSのセカンダリIP設定は以下のコマンドで削除できる。デバイス番号に追加した`:0`は不要である。

```shell-session
# ip addr del 10.5.1.30/24 dev ens3
```

6.`ip addr add`で追加した設定はインスタンスをリブートすると消えてしまう。永続的に指定するときは以下のようなファイルを追加する。ただしフェイルオーバー目的で使用するときは、動的に設定した方がいいだろう。

```shell-session:/etc/sysconfig/network-scripts/ifcfg-ens3:0
DEVICE="ens3:0"
BOOTPROTO=static
IPADDR=10.5.1.30
NETMASK=255.255.255.0
ONBOOT=yes
```

# 4. セカンダリIPでフェイルオーバーする

基礎知識がわかったので、手動でフェイルオーバーしてみよう。以下のような環境を想定している。
![2ndaryip05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/9d415e12-ce64-1789-5b64-fc028aa2e90f.png)

**フェイルオーバー実施手順**

1. Active側でセカンダリIP割り当て（OCI管理コンソール）
2. Active側でセカンダリIP割り当て（OSのipコマンド）
3. <font color="red">ここからフェイルオーバー実施</font>
4. Standby側でセカンダリIP割り当て。強制割り当て解除をチェック（OCI管理コンソール）
5. Standby側でセカンダリIP割り当て（OSのipコマンド）

<font color="blue">上記手順で実行すると、5が終わったところで、実際にフェイルオーバーが完了する。</font>

理想的には、3のあとに**「Active側でセカンダリIP割り当て解除（OSのipコマンド）」**すべきだが、手順に含めなくてもエラーにならなかった。

このことから「ipコマンドを実行するのが面倒」と思い、好奇心でActive/Standbyの両ノードに`/etc/sysconfig/network-scripts/ifcfg-ens3:0`を設定してみると、変わらずフェイルオーバーできた！

<font color="blue">オンプレミスの場合、同一サブネットでIPアドレスが重複しているとエラーが出るのにOCIはエラーにならない。クラウドレイヤでうまくルーティングしているのだろう。</font>

# 5. おわりに
きっかけとなった記事「[[Oracle Cloud] ComputeのセカンダリIPのフェールオーバを試してみる](https://qiita.com/NSO-KC/items/4c06d78109ba5a8e0034)」ではスクリプトを使ってフェイルオーバーしていたが、実際には自動化が必要だろう。まあ、監視ツールからスクリプトをキックしてもいいけどね。

自動化については、このあたりの記事を参考にしてほしい。

* [Automatic Virtual IP Failover on Oracle Cloud Infrastructure](https://community.oracle.com/blogs/gmelo/2017/10/02/automatic-virtual-ip-failover-on-oracle-cloud-infrastructure)→Pacemakerを利用したHAクラスタ
* [[Oracle Cloud Infrastructure] Pacemakerを使って仮想IPを別ADのインスタンスに自動フェイルオーバーする](https://qiita.com/mmarukaw/items/66fac6c8e0843df6b7c0)→Pacemakerを利用したHAクラスタ
* [NAT Instance Configuration](https://docs.cloud.oracle.com/iaas/Content/Resources/Assets/whitepapers/nat-instance-configuration.pdf)→keepalivedを利用したVRRPクラスタ

**Pacemakerに関する余談**
Pacemakerは使いこなせれば無料でうれしいけれど、本番運用できるレベルまで完成度を高めるにはかなりのノウハウが必要だ。その昔ドハマった経験あり。徹夜に近い作業を何日したっけ（遠い目）。結局そのときは構築・運用マニュアルで50ページ近く書いたような。

この件に関しては言いたいことがあって、2010年くらいにIPAが公開したHadoopに関する報告書「高信頼クラウド実現用ソフトウェア開発（分散制御処理技術等に係るデータセンターの高信頼化に向けた実証事業）」。HadoopのNameNodeを保護するため、heatbeat（Pacemakerの前身）+DRBDでHAクラスタを組んでいたのだけれど、これが地雷。

Hadoopが主目的だったこともあり、クラスタまわりの詳細な記述は書かれていなかった。

当時注目度が高かったドキュメントということもあり、これをマネしてハマル人が続出。構築が大変なだけで無く、トラブル発生時のリカバリも難易度が高かった。DRBDの難易度が高いことも原因だけど。

高可用性を目指してクラスタを導入したけれど、逆にその複雑さで可用性が下がるってのはありがちな話。

悩みたくないならば、[LINBITのサポートありバージョン](https://sios.jp/products/linbit/)や[Lifekeeper](https://sios.jp/products/lkdk/product/lifekeeper.html)、[NEC CLUSTERPRO](https://jpn.nec.com/clusterpro/)などを使うのがオススメ。

* [RHEL High Availability Add-On（HAアドオン）についてのFAQ](https://rheb.hatenablog.com/entry/201812-rhel-ha-addon)
* [ClusterLabs](https://clusterlabs.org)
* [LINUX-HA JAPAN](http://linux-ha.osdn.jp/wp/)