dnsmasq使用中にhostnameを変更したら外部との疎通が一切とれなくなった件の対処法

ここ数日ハマってた問題が解決したのでメモを残しておきます

自分がググった範囲では同様の事象はなかったと思います。

# tl;dr
dnsmasqを使っている場合、hostname変更後はnetwork再起動が必要

# 環境
* CentOS 7.1.1503
* NetworkManager 1.0.6-29.el7_2
* dnsmasq 2.66-12.el7

# dnsmasqって何よ？
一言で言えばDNSのキャッシュサーバです

[NetworkManager＋dnsmasqで名前解決の耐障害性を向上 | 外道父の匠](http://blog.father.gedow.net/2016/02/12/networkmanager-dnsmasq/) の説明が詳しいのでそちらをごらんください

# 事象
プロビジョニングのレシピでhostnameを変更すると `/var/run/NetworkManager/dnsmasq.conf` が空ファイルになって外部との疎通が一切できなくなる

# 手順
## 1. 実行前
```shell-session
$ curl -I http://www.drecom.co.jp/
HTTP/1.1 200 OK
Date: Thu, 12 May 2016 04:34:56 GMT
Server: Apache
Vary: Accept-Encoding
Content-Type: text/html

# NOTE: dnsmasqが有効になってるのでlocalhost:53をむいている
$ nslookup www.drecom.co.jp
Server:     127.0.0.1
Address:    127.0.0.1#53

Non-authoritative answer:
Name:   www.drecom.co.jp
Address: 210.148.6.26

$ cat /var/run/NetworkManager/dnsmasq.conf
server=xx.xx.xx.xx
```

## 2. hostnameを変更

実際はitamaeのレシピで実行してるのでやってることは厳密には違うけど、やってることはだいたいこんな感じ

```shell-session
sudo hostnamectl set-hostname "examplestaging-web-01"
```

## 3. 実行後
```shell-session
$ curl -I http://www.drecom.co.jp/
curl: (6) Could not resolve host: www.drecom.co.jp; 不明なエラー
$ nslookup www.drecom.co.jp
Server:     127.0.0.1
Address:    127.0.0.1#53

** server can't find www.drecom.co.jp: REFUSED

$ cat /var/run/NetworkManager/dnsmasq.conf
$ ls -l /var/run/NetworkManager/dnsmasq.conf
-rw-r--r-- 1 root root 0 5月 17 16:35 /var/run/NetworkManager/dnsmasq.conf
```

hostnameを変更したらなぜか `/var/run/NetworkManager/dnsmasq.conf` が0バイトに。。。

こうなると `yum install` もできない :cry:

# 調査時にやったこと
## どのレシピが原因か絞りこむ
itamaeの実行ログを見て変更がかかったレシピを1つずつ実行しつつ確認。今回はレシピの全適用ではなく差分適用時のみ起こる事象だったので調査自体は大変ではなかったです。（7ファイルくらい）

そんなこんなで冒頭で書いたようにhostname変更のレシピが犯人だと特定できました

## NetworkManagerのログを見る
`journalctl -u <ユニットファイル名>` でログが見れる。 （`-f` で `tail -f` みたいな挙動）

```shell-session
$ sudo journalctl -u NetworkManager.service -f
（略）
 5月 13 14:05:36 examplestaging-web-01 dnsmasq[25644]: started, version 2.66 cachesize 1024
 5月 13 14:05:36 examplestaging-web-01 dnsmasq[25644]: compile time options: IPv6 GNU-getopt DBus no-i18n IDN DHCP DHCPv6 no-Lua TFTP no-conntrack ipset auth
 5月 13 14:05:36 examplestaging-web-01 dnsmasq[25644]: warning: no upstream servers configured
 5月 13 14:05:36 examplestaging-web-01 dnsmasq[25644]: cleared cache
```

hostname変更と同タイミングでログが出てたのを確認。`/var/run/NetworkManager/dnsmasq.conf` が空ファイルになったのも同じ時間でした

上記warningが出てたので怪しいと思ったのですが特に関係なかったです

## ネットワークを疑う
VPNの関係でレシピ実行前に手で設定した箇所があったので [^vpn]、 そこが怪しいかもと思いチェック

`nmcli connection show` や `netstat -nr` を確認したけど特に問題ナッシングでした

[^vpn]: VM起動直後はクラウド管理画面のコンソールからしかログインできなかったため、レシピ実行前にVPNを設定して社内から接続できるようにしておく必要がありました。（この状態でベースイメージを作成してレシピ実行やCIで利用）

## NetworkManagerとdnsmasqを止めてみる
```shell-session
$ sudo systemctl stop NetworkManager
$ sudo systemctl stop dnsmasq
$ ps aux | grep dnsmasq
nobody     860  0.0  0.1  15520  1160 ?        S    18:54   0:00 /usr/sbin/dnsmasq --no-resolv --keep-in-foreground --no-hosts --bind-interfaces --pid-file=/var/run/NetworkManager/dnsmasq.pid --listen-address=127.0.0.1 --conf-file=/var/run/NetworkManager/dnsmasq.conf --cache-size=400 --proxy-dnssec --conf-dir=/etc/NetworkManager/dnsmasq.d
sueyosh+  1930  0.0  0.0 112656   968 pts/0    S+   18:58   0:00 grep --color=auto dnsmasq
```

serviceを止めたのになぜかdnsmasqのプロセスがががが。
この時点でdnsmasqの古いプロセスが残り続けてるのが原因だろうとおおよそ特定

## networkを再起動
```shell-session
$ sudo systemctl restart network

$ ll /var/run/NetworkManager/
合計 8
-rw-r--r--. 1 root root 63  5月 17 15:35 dnsmasq.conf
-rw-r--r--. 1 root root  6  5月 17 15:35 dnsmasq.pid
srwxrwxrwx. 1 root root  0  5月 17 15:35 private
srwxrwxrwx. 1 root root  0  5月 17 15:35 private-dhcp
```

`/var/run/NetworkManager/dnsmasq.conf` が復活して外部との疎通もとれるようになった ╭( ･ㅂ･)و ̑̑ 

# 副産物
調査段階で `systemctl` や `journalctl` を死ぬほど叩いたのでsystemdに慣れた気がする