プライベートサブネット配下にあるEC2のmysqlへの疎通確認で沼った話

# 経緯
プライベートサブネット配下にあるEC2にmysqlをインストールし
パブリックサブネット配下にあるEC2からDB接続する必要があった。
その際に中々うまく繋がらなかったので振り返りがてらメモを残します。

# 構成情報
AWS、mysql8、EC2、OS ubuntu

## 想定している経路
* パブリックサブネットEC2←→プライベートサブネットEC2(mysql)
(※長いので以後、フロントサーバーとDBサーバーとする)

# その1.プライベートサブネットにmysqlインストールできない問題
当たり前ですがDBサーバーはプライベートサブネットにあるため
パッケージをインストールしようにもネットが繋がっていない
なので一時的にネットに繋がる状態にする必要がある。

## ルートテーブル変更
EIPを一時的につける方法もあるが、今回はルートテーブル変更で対応した。
プライベートサブネットを一時的にigwがついているルートテーブルへ変更した。
その後はお決まりのpingで疎通確認、googleさんいつもありがとうございます。

```bash
$ ping google.com

--- google.com ping statistics ---
8 packets transmitted, 8 received, 0% packet loss, time 7009ms
rtt min/avg/max/mdev = 2.099/2.228/2.346/0.063 ms
```

戻すのを忘れずに。(この辺りは影響確認して上の方と相談した方がいいです)

# その2.フロントサーバーからDBサーバーへmysql接続できない問題
フロントサーバーからDBサーバーへmysql接続するためには
いくつかポイントがあり今回まんまとハマってしまったので復習がてら記載する。

## セキュリティグループでIPとポート番号を許可する
今回はmysqlでポート3306を使用したので、インバウンドルールにDBサーバーのIPとポート番号を登録した。
なお当然返ってくる時もポートを開ける必要があるのでフロントサーバーに向けてのIPとポート番号も必要となる

## mysqlでの権限確認
DBにアクセスする際にアクセスできるユーザーを作る必要がある、
インストール直後は当たり前ですがlocalhostしかない。

```
mysql> select user, host from mysql.user;
+------------------+--------------+
| user             | host         |
+------------------+--------------+
| debian-sys-maint | localhost    |
| tiikawa          | localhost    |
| mysql.infoschema | localhost    |
| mysql.session    | localhost    |
| mysql.sys        | localhost    |
| root             | localhost    |
+------------------+--------------+
```

またこの際hostにipの指定が必要なのでここに接続を許可するhostipを入れておく。

```
CREATE USER 'ユーザー名'@'許可するIP' IDENTIFIED BY 'パスワード';
```

そして忘れてはいけないのがテーブルの設定。
自分はこの設定を忘れていてmysqlに入ることはできるのに`テーブルにアクセスできないという珍現象を引き起こしていた。`

```
GRANT ALL PRIVILEGES ON tiikawaDB . * TO 'ユーザー名'@'許可するIP';

mysql> show grants for 'ユーザー名'@'許可するIP';
+---------------------------------------------------------------+
| Grants for ユーザー名@許可するIP                                 |
+---------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON tiikawaDB.* TO 'ユーザー名'@'許可するIP' |
+---------------------------------------------------------------+
1 row in set (0.00 sec)

```

しっかりテーブルにも権限があることを確認する。
この辺りは公式リファレンスで適切な権限設定を見たほうがいいかも。

## mysqld.cnfのバインドIPアドレス

上記の設定を行ったあたりで、フロントサーバーからDBサーバーへmysql接続をしたところ、以下のエラーが発生した。

```
$ mysql -h DBサーバープライベートIP -P 3306 -u ユーザー名 -p
Enter password: 
ERROR 2003 (HY000): Can't connect to MySQL server on 'プライベートIP:3306' (111)
```

こういう時はDBサーバーへ一旦pingしてみる
※ICMPをセキュリティグループ入れて許可するのを忘れずに。(1敗)

```
$ ping DBサーバープライベートIP

--- DBサーバープライベートIP ping statistics ---
70 packets transmitted, 70 received, 0% packet loss, time 70677ms
rtt min/avg/max/mdev = 0.188/0.322/0.493/0.065 ms
```

問題はなさそうだけど原因がわからず。
DBサーバーで作成したユーザーでログインを試してみるもののログインはできた。
mysqlの設定ファイルをのぞいてみる。

```
/etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
#
# * Basic Settings
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address		= 127.0.0.1
mysqlx-bind-address	= 127.0.0.1
```

どうやらデフォルトの設定では`bind-address`がローカルホストを指定していて
それ以外の接続を拒否してるらしい。

と同時に当たり前ですが`ssコマンドやnetstatを使って通信相手のIPアドレスやポートやローカルのIPアドレスとポートを見ることが重要だと分かりました。`

bind-addressは`0.0.0.0`にすると全て許可になります。
追加で接続したいIPを追加すると起動失敗するので、大元を変えるしかなさそう


以下、わかりやすかったので引用する。

https://oji-cloud.net/2024/02/22/post-8180/
https://dev.mysql.com/doc/refman/8.0/ja/problems-connecting.html

## DBサーバーのファイアウォール変更
こちらはやらなくても動きましたが、OSによって有効化してる場合は適宜調べて許可しましょう(投げやり)


# 感想

以上が詰まったポイントです、プライベートサブネット配下で色々検索しても
RDSがメインで出てきてあまり見つからなかったので大変でした。
「そもそもAWS使ってるのにRDS使わずなんでEC2にDB入れて構築してるねん」という本末転倒感はありますが‥
原因の切り分けと何をしたらいいかをもっと瞬時に判断できるようになりたいと思いました。