Oracle Cloud Infrastructureの名前解決の仕組み&ホスト名の変更方法

# 1. はじめに

Oracle Cloud Infrastructureに限らず、パブリック・クラウドのIaaSは、オンプレミスの常識とは異なる部分がある。今回紹介する「参照するDNSサーバーの指定」や「ホスト名の変更」もその一つだ。

このあたりのことはマニュアルの[「DHCPオプション」](https://docs.cloud.oracle.com/ja-jp/iaas/Content/Network/Tasks/managingDHCP.htm)に書かれているが、わかりづらいので取り上げる。なお今回の対象は、サーバー側のDNSサービスではなく、クライアント側の仕組みの話である。

### 1-1. TL;DR

* マニュアルのDHCPオプションの説明がわかりづらい
* 参照するDNSサーバーを/etc/resolv.confに記述してもリセットされる
* ホスト名の変更は意外に面倒

### 1-2. 前提条件

* Oracle Cloud Infrastructure Compute
* Oracle Cloud Infrastructure Database(DBaaS)

### 1-3. 参考資料
**OCI日本語マニュアル**

* [仮想クラウド・ネットワーク内の DNS](https://docs.cloud.oracle.com/ja-jp/iaas/Content/Network/Concepts/dns.htm)
* [DHCPオプション](https://docs.cloud.oracle.com/ja-jp/iaas/Content/Network/Tasks/managingDHCP.htm)

**OCI英語マニュアル**

* [DNS in Your Virtual Cloud Network](https://docs.cloud.oracle.com/en-us/iaas/Content/Network/Concepts/dns.htm)
* [DHCP Options](https://docs.cloud.oracle.com/en-us/iaas/Content/Network/Tasks/managingDHCP.htm)

# 2. 基本用語とオンプレミスにおける仕組み

本題に入る前に、基本用語とオンプレミスにおける仕組みを振り返る。

### 2-1. 用語の確認

<dl>
  <dt>DNS</dt>
    <dd>ドメイン名（ホスト名）とIPアドレスを対応づける仕組み</dd>
  <dt>DNSサーバー</dt>
    <dd>DNSを提供しているサーバー</dd>
  <dt>リゾルバ</dt>
    <dd>DNSサーバーにアクセスして、ドメイン名に対応したIPアドレスを取得するクライアント側の仕組み（プログラム）</dd>
  <dt>名前解決</dt>
    <dd>ホスト名をIPアドレスに変換する処理</dd>
  <dt>ホスト名／ドメイン名／FQDN</dt>
    <dd>https://www.sample.comというURLがあった場合、ホスト名は「www」であり、ドメイン名は「sample.com」である。また「www.sample.com」全部をFQDN（Fully Qualified Domain Name）という。ただし、文脈上それぞれを区別しないで使うこともある。</dd>
  <dt>レジストラ</dt>
    <dd>foo.comのようなドメイン名を登録する業者。利用者はレジストラやレジストラの代理店を通じてドメイン名を登録（取得）する。</dd>
</dl>

### 2-2. オンプレミスにおけるDNSリゾルバの設定方法

クラウドの前に、オンプレミスでの設定方法を振り返る。Linux OSでは、参照するDNSサーバーを`/etc/resolv.conf`や`/etc/sysconfig/network-scripts/ifcfg-*`で指定する。

```:/etc/resolv.conf
nameserver DNSサーバーのIPアドレス
search     検索リスト1 検索リスト2 検索リスト3 ...
```

```:/etc/sysconfig/network-scripts/ifcfg-*
DNS1=DNSサーバーのIPアドレス
DOMAIN=検索リスト1 検索リスト2 検索リスト3 ...
```

次のように/etc/resolv.confを設定した環境で`ping foo`というコマンドを実行する。DNSサーバー「172.16.0.10」に対して`foo.sample.com`のIPアドレスを問い合わせ、登録されていたときは取得できる。

```:/etc/resolv.conf
nameserver 172.16.0.10
search     sample.com
```

<font color="red">**注意**
RHEL系ディストリビューションでNetworkManagerが有効になっているとき、/etc/resolv.confの設定内容は、/etc/sysconfig/network-scripts/ifcfg-*の設定内容で上書きされる。</font>

<font color="red">そのため/etc/resolv.confを直接書き換えてよいのは、NetworkManagerが無効になっているときか、NetworkManagerが上書きしないようにパラメーターを設定しているときである。</font>

* [CentOS 7のネットワーク管理基礎（前編）](https://thinkit.co.jp/story/2014/12/25/5412?page=0%2C1)
* [How can I prevent NetworkManager from modifying the /etc/resolv.conf file in RHEL7? ](https://access.redhat.com/solutions/894753)※要RHNアカウント

話がオンプレミスで長くなった。次にOracle Cloud Infrastructureにおける指定方法や機能を説明する。

# 3. Oracle Cloud InfrastructureにおけるDNSリゾルバの仕組み

オンプレミスでは`/etc/resolv.conf`や/`etc/sysconfig/network-scripts/ifcfg-*`で、参照するDNSサーバーを指定していた。しかしOracle Cloud Infrastructureではサブネットの「DHCPオプション」で指定する。

仕組みはあとで説明するとして、ここではOracle Cloud Infrastructureでの指定方法を説明する。

### 3-1. Oracle Cloud Infrastructureにおけるリゾルバの種類

Oracle Cloud Infrastructureでリゾルバを指定する方法が **「DHCPオプション」** だ。なぜDHCPという名前なのか疑問に思うかもしれないが、気にしないで進むことにする。

次の2種類の設定があり、サブネット単位で設定する。他にサーチドメインもあるが、オンプレミスと同じなので省略する。

* <font color="blue">**Internet and VCN Resolver**</font>
* <font color="blue">**Custom Resolver**</font>

それぞれの違いは次のとおり。

**Internet and VCN Resolver**：
デフォルト設定であり、下記2つの目的で使用する。

* インターネットに一般公開されているwww.oracle.comなどの名前解決（Internet Resolver）
* 同じVCNで稼働するインスタンスの名前解決（VCN Resolver）

**Custom Resolver**：
以下のように特定のDNSサーバーを参照するときに使用する。

* インターネットで提供されている特定のDNSサーバー
* Oracle Cloud Infrastructure内に自分で立てたDNSサーバー
* VPNやFastConnectで接続しているオンプレミス・ネットワークにあるDNSサーバー

<font color="blue">**両者の違いを一言で表すならば、特定のDNSサーバーを指定するか、しないかである。**</font>

<font color="red">**重要：** プライベートDNSのリリースに伴い、Internet and VCN Resolverでも固有のDNSサーバーを参照できるようになった。特定のDNSで集中管理するという目的以外では、Custom Resolverの必要性は減少している。プライベートDNSの詳細は以下の記事を参照のこと。</font>

* [Oracle CloudのプライベートDNSを理解する](https://qiita.com/yamada-hakase/items/1b37b2aaacca525e571d)

下図はInternet and VCN Resolverの概念図だ。Oracle Cloud Infrastructureの内部ネットワークにあるDNSサーバーを参照するので、Internet GatewayやNAT Gatewayは不要である。
![dhcpoption02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/a1ba9efd-a7c2-dc15-7ca2-4fa199a45967.png)

※ DBaaSの2ノードRACでは、Custom Resolverは使用できない

### 3-2. DHCPオプションの使い分け

次にDHCPオプションの使い分けや応用について考えてみる。「Internet and VCN Resolverができること」という視点で考えるとわかりやすい。

**できること**

* 同じVCNで稼働するインスタンスの名前解決
* インターネットに一般公開されているサーバーの名前解決

**できないこと**

* 他のVCNで稼働するインスタンスの名前解決
* パブリックIPを持つOracle Cloud Infrastructure Computeインスタンス（サービス）に対する名前解決

これらの特性を理解したうえで考えた「できないこと」の対応策は以下のとおり。

**<font color="blue">課題1: 他のVCNで稼働するインスタンスの名前解決（プライベートIP）</font>**
　→/etc/hostsファイルを利用する。
　→Oracle Cloud Infrastructure内もしくはVPN/FastConnectで接続したオンプレミスネットワークに立てたDNSサーバーをCustom Resolverで指定する。

**<font color="blue">課題2: パブリックIPを持つOracle Cloud Infrastructure Computeインスタンスに対する名前解決</font>**
　→一般公開するサービスならば、レジストラからドメイン名を取得したうえで、Oracle Cloud Infrastructureの[DNSサービス](https://docs.oracle.com/ja-jp/iaas/Content/DNS/Concepts/dnszonemanagement.htm)、もしくは他のDNSサービスを利用する。

下記リンクには、いろいろな構成方法が紹介されているので参照してほしい。

* [仮想クラウド・ネットワーク内のDNS](https://docs.oracle.com/ja-jp/iaas/Content/Network/Concepts/dns.htm)のシナリオ1から3
* [Hybrid DNS Configuration](https://github.com/terraform-providers/terraform-provider-oci/blob/255817f83956f1f9a3ab903e11465e8b4dde1957/docs/examples/networking/hybrid_dns/Hybrid-DNS-configuration-using-DNS-VM-in-VCN.md)

### 3-3. VCN Resolver使用する条件

「Internet and VCN Resolver」と「Custom Resolver」は、VCNに複数定義でき、サブネット作成後でも切り替えられる。ただしVCN Resolverは、以下の3条件をクリアする必要がある。

1. VCN作成時に **[USE DNS HOSTNAMES IN THIS VCN]** を有効にしていること
2. 上記に加えて、サブネット作成時に **[USE DNS HOSTNAMES IN THIS SUBNET]** を有効していること
3. 上記に加えて、DHCPオプションが **[Internet and VCN Resolver]** であること

1と2は、あとで変更できず、VCNやサブネットを再作成する必要がある。いずれもインスタンス再作成につながるので、VCN Resolverを使うときには、必ずチェックすること。

**VCN/サブネットとVCN Resolverの関係**
![dhcp01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/5b7d431d-b771-c827-0f0e-0129e8cb84cc.png)

VCN Resolverが利用できると、次のFQDNで名前解決できる。

<font color="blue">**＜hostname＞.＜subnet DNS label＞.＜VCN DNS label＞.oraclevcn.com**</font>

インスタンスのFQDNは、管理コンソール以外にも/etc/hostsや以下のコマンドで確認できる。

```shell-session
$ hostname
foo

$ hostname -f
foo.＜subnet DNS label＞.＜VCN DNS label＞.oraclevcn.com
```

<font color="red">**注意**
DHCPオプションの設定を変更したときは、サブネットのインスタンスを再起動すること。再起動しないと、次のDHCPリースが更新されるまで反映されない（最大24時間）。
</font>

### 3-4. おまけ：DNSサービスとは違います

DNSの話をすると、Amazon Route 53やAzure DNS、各プロバイダーなどが提供するDNSサービスを連想する人もいるだろう。Oracle Cloud Infrastructureでも同様のDNSサービスを提供している。

* [Oracle Cloud Infrastructure DNS](https://www.oracle.com/cloud/networking/dns.html)
* [マニュアル：DNSおよびトラフィック管理](https://docs.oracle.com/ja-jp/iaas/Content/EdgeServices/overview.htm)

しかし今回はクライアントの話なので、上記DNSサービスのことではない。なおOracle社は、2016年に世界的マネージドDNSプロバイダーDyn社を買収している。

# 4. DHCPオプションの仕組みを掘り下げる

DHCPオプションが、どのような仕組みになっているか調べることにする。

### 4-1. なぜDHCPオプションなのか

「DHCPオプション」と聞いて不思議に思う人もいるだろう。わたし自身も最初はそうだった。理由は簡単で

**プライベートIPなどを割り当てる仕組みにDHCPを使っているからだ。**

ただし一般的なDHCPとは異なり、OCI Compute/Databaseではインスタンスが削除（Terminate）されるまで、同じプライベートIPが割り当てられる。

### 4-2. ネットワーク設定ファイルを確認する

OCI Compute/Databaseのネットワーク設定ファイルを確認してみよう。いずれもDHCPになっている。

**Oracle Linux 9**

```shell:/etc/sysconfig/network-scripts/ifcfg-ens3
# Created by cloud-init on instance boot automatically, do not edit.
#
AUTOCONNECT_PRIORITY=999
BOOTPROTO=dhcp　★
DEVICE=ens3
HWADDR=02:00:17:02:81:53
ONBOOT=yes
TYPE=Ethernet
USERCTL=no
```

**Oracle Linux 7 / 8**

```shell:/etc/sysconfig/network-scripts/ifcfg-ens3
# Generated by dracut initrd
NAME="ens3"
DEVICE="ens3"
ONBOOT=yes
NETBOOT=yes
UUID="e9c190bf-e0aa-435e-98ed-1a543f356906"
BOOTPROTO=dhcp　★
TYPE=Ethernet
NM_CONTROLLED=no
```

**Oracle Linux 6**

```shell:/etc/sysconfig/network-scripts/ifcfg-eth0
# Generated by OCI dhcp-helper
DEVICE=eth0
ONBOOT=yes
NETBOOT=yes
BOOTPROTO=dhcp　　★
TYPE=Ethernet
NM_CONTROLLED=no
UUID="f60739e2-feff-422f-871c-7329832af225"
```

/var/log/messagesをdhclientでgrepすると、毎回10時間前後で更新されているのが分かる。

```
Oct  7 03:34:35 ol7srv dhclient[2134]: DHCPREQUEST on ens3 to 169.254.169.254 port 67 (xid=0x4d4c8a54)
Oct  7 03:34:35 ol7srv dhclient[2134]: DHCPACK from 169.254.169.254 (xid=0x4d4c8a54)
Oct  7 03:34:37 ol7srv dhclient[2134]: bound to 10.0.0.5 -- renewal in 38491 seconds.
Oct  7 14:16:08 ol7srv dhclient[2134]: DHCPREQUEST on ens3 to 169.254.169.254 port 67 (xid=0x4d4c8a54)
Oct  7 14:16:08 ol7srv dhclient[2134]: DHCPACK from 169.254.169.254 (xid=0x4d4c8a54)
Oct  7 14:16:10 ol7srv dhclient[2134]: bound to 10.0.0.5 -- renewal in 38021 seconds.
Oct  8 00:49:51 ol7srv dhclient[2134]: DHCPREQUEST on ens3 to 169.254.169.254 port 67 (xid=0x4d4c8a54)
Oct  8 00:49:51 ol7srv dhclient[2134]: DHCPACK from 169.254.169.254 (xid=0x4d4c8a54)
Oct  8 00:49:53 ol7srv dhclient[2134]: bound to 10.0.0.5 -- renewal in 33417 seconds.
```

「DHCP Options」ページの「[Important Notes about Your Instances and DHCP Options](https://docs.cloud.oracle.com/en-us/iaas/Content/Network/Tasks/managingDHCP.htm)」には重要なことが書かれている。

> Whenever you change the value of one of the DHCP options, you must do one of the following for the change to take effect on existing instances in the subnets associated with that set of DHCP options: either restart the DHCP client on the instance, or reboot the instance.

**DHCPクライアントを停止、または停止につながる操作をしてはいけない。**

> Any changes you make to the /etc/hosts and /etc/resolv.conf files will be overwritten whenever the DHCP lease is renewed or the instance is rebooted. 

**/etc/hostsと/etc/resolv.confは定期的に上書きされる。そして自分調べでは、/etc/hostsに追加したエントリは上書きされない。**

### 4-3. /etc/resolv.confと/etc/hostsを確認する

/etc/resolv.confを確認してみよう。冒頭のコメントには以下のことが書いてある。

* DHCPリースの更新ごとに上書きされる
* 上書きを防止するには/etc/oci-hostname.confを変更すべし

```shell:/etc/resolv.conf
; Any changes made to this file will be overwritten whenever the
; DHCP lease is renewed. To persist changes you must update the
; /etc/oci-hostname.conf file. For more information see
;[https://docs.cloud.oracle.com/en-us/iaas/Content/Network/Tasks/managingDHCP.htm#notes]
;
; generated by /usr/sbin/dhclient-script
search <VCN DNS label>.oraclevcn.com <subnet DNS label>.<VCN DNS label>.oraclevcn.com
nameserver 169.254.169.254
```

続いて/etc/hostsを確認してみよう。ComputeとDatabaseでは異なるが、以下のようになっている（プライベートIPが`10.0.0.5`のとき）。

```shell:Computeの/etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.5 <hostname>.<subnet DNS label>.<VCN DNS label>.oraclevcn.com <hostname>
```

```shell:DBaaSの/etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.5  <hostname>.<subnet DNS label>.<VCN DNS label>.oraclevcn.com  <hostname>
192.168.16.18  <hostname>-priv.<subnet DNS label>.<VCN DNS label>.oraclevcn.com  <hostname>-priv
10.0.0.5  <hostname>-vip.<subnet DNS label>.<VCN DNS label>.oraclevcn.com  <hostname>-vip
10.0.0.5  <hostname>-scan.<subnet DNS label>.<VCN DNS label>.com  <hostname>-scan
```

DBaaSの`192.168.16.18`が気になる人がいるかもしれない。これはClusterwareがインターコネクトに使用するアドレスだ。[DBaaSのマニュアル](https://docs.oracle.com/ja-jp/iaas/Content/Database/Tasks/creatingDBsystem.htm)には、DBaaSインスタンスは、`192.168.16.16/28`とオーバーラップするサブネットには作成できないと書いてある。

DBaaSのNIC情報を確認すると、ens4がインターコネクト用のNICになっていることがわかる。

```shell-session
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group defaul              t
    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 defa              ult qlen 1000
    link/ether 02:00:17:03:0a:bd brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.5/24 brd 10.0.2.255 scope global dynamic ens3
       valid_lft 81235sec preferred_lft 81235sec
3: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc mq state UP group defa              ult qlen 1000
    link/ether 02:00:17:03:35:98 brd ff:ff:ff:ff:ff:ff
    inet 192.168.16.18/24 brd 192.168.16.255 scope global ens4
       valid_lft forever preferred_lft forever
```


### 4-4. /etc/oci-hostname.confを調べる

/etc/oci-hostname.confは、Computeだけに存在するファイルで、DBaaSには存在しない。

```shell:/etc/oci-hostname.conf
# This configuration file controls the hostname persistence behavior for Oracle Linux
# compute instance on Oracle Cloud Infrastructure (formerly Baremetal Cloud Services)
# Set PRESERVE_HOSTINFO to one of the following values
#   0 -- default behavior to update hostname, /etc/hosts and /etc/resolv.conf to
#        reflect the hostname set during instance creation from the metadata service
#   1 -- preserve user configured hostname across reboots; update /etc/hosts and
#           /etc/resolv.conf from the metadata service
#   2 -- preserve user configured hostname across instance reboots; no custom
#        changes to /etc/hosts and /etc/resolv.conf from the metadata service,
#        but dhclient will still overwrite /etc/resolv.conf
#   3 -- preserve hostname and /etc/hosts entries across instance reboots;
#        update /etc/resolv.conf from instance metadata service
PRESERVE_HOSTINFO=0
```

違いをまとめたのが次の表だ。

| 値 | ホスト名 | hosts | resolv.conf |
|:-:|:-:|:-:|:-:|
| 0  | 更新される | 更新される | 更新される |
| 1  | 更新されない | 更新される | 更新される |
| 2  | 更新されない | 更新されない | 更新されない(*1) |
| 3  | 更新されない | 更新されない | 更新される |

*1:リブートでは更新されないが、DHCPクライアントによって更新される

# 5. ホスト名を変更する

DHCPオプションの仕組みによって、従来の方法でホスト名を変更してもリセットされてしまう。そのため、Oracle Cloud Infrastructure固有の方法で変更する必要がある。

### 5-1. インスタンスのホスト名

管理コンソールで表示される名前が「ホスト名」だと思っている人もいるだろう。実はコンソールに表示されるのは表示名（display name）で、実際のホスト名と異なる可能性がある。

Computeでは次の仕組みでホスト名を生成している。

1. 表示名をホスト名として利用できるか検証（RFC等への適合）
1. 利用できるときは、表示名をホスト名として利用
1. 利用できないときは、自動生成したホスト名を利用

またComputeインスタンス作成時に、明示的にホスト名を指定することもできる。管理コンソールで **「拡張オプションの表示（Show Advanced Option）」** をクリックするとホスト名の入力エリアが表示される。ここに入力すれば、表示名と異なるホスト名を使用できる。
![hostname01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/b3407eed-e931-cecc-e412-99e9e178ea6c.png)


### 5-2. Computeのホスト名を変更する

Computeのホスト名を変更するには、いくつかの方法がある。この中で1の方法を説明する。

1. /etc/oci-hostname.confを使ってホスト名を変更する
2. ブート・ボリュームをクローンしてインスタンスを作成する
3. カスタム・イメージを作成してインスタンスを作成する

変更手順は、はじめにOS上で変更し、次に管理コンソールで変更する。

1. OSでホスト名を変更する。

**Oracle Linux 7 / 8 / 9のとき**

```shell-session
# hostnamectl set-hostname ＜新しいホスト名＞
```

**Oracle Linux 6のとき**

```shell-session:/etc/sysconfig/network
NETWORKING=yes
HOSTNAME=＜新しいホスト名＞
```

2.PRESERVE_HOSTINFOの値を0から2に変更する。

```shell-session:/etc/oci-hostname.conf
PRESERVE_HOSTINFO=2
```

3.管理コンソールで該当インスタンスの詳細を表示。左下の **「アタッチされたVNIC（Attached VNIC）」** をクリックする。次に **「VNICの編集（Edit VNIC）」** をクリックすると以下のダイアログが表示される。ここで表示名（名前）とホスト名を変更できる。
![dhcp04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266049/049d6f40-73b1-2734-5276-051cc5112dfc.png)

4.最後にインスタンスをリブートしたら完了だ。

なおDBaaSの手順は複雑なのでMy Oracle Supportを見てほしい。

* [MOS Note 1552810.1 How to change Hostname / IP for a Grid Infrastructure Oracle Restart Standalone Configuration (SIHA) 11.2 and Later](https://support.oracle.com/epmos/faces/DocumentDisplay?id=1552810.1)

# 6. まとめ

**DNSリゾルバ**

* 参照するDNSサーバーはDHCPオプションで指定する
* DHCPオプションの仕組みのため、ホスト名や/etc/hosts、/etc/resolv.confは自動更新される。手動では変更できない
* デフォルトのInternet and VCN Resolverでは、インターネットに公開されているサーバーとVCN内インスタンスの名前解決ができる。VCN外の名前解決はできない
* 特定のDNSサーバーを参照するときはCustom Resolverを使用する
* インスタンスに割り当てたプライベートIPはインスタンスを削除するまで変わらない
* 本文では説明していないが、インスタンスに割り当てたパブリックIPはインスタンスを削除するまで変わらない。同じパブリックIPを再利用するにはReserved IPを使用する必要がある

**ホスト名**

* 管理コンソールに表示されるのは、ホスト名ではなく表示名。そのため表示名とホスト名が異なることがある
* ホスト名を変更するにはOracle Cloud Infrastructure固有の方法で変更する