はじめに Link to heading
「とりあえず動けばいい」
この思考が、2時間の無駄な試行錯誤を生み出しました。
GCP上でWordPress マルチテナント環境を構築していた際、Cloud SQLのSSL証明書エラーに遭遇しました。その時に取った「アプリケーション層での対症療法」というアプローチが、いかに間違っていたか。そして、なぜそのような判断をしてしまったのか。
この記事では、失敗の過程を包み隠さず共有し、同じミスを繰り返さないための教訓を整理します。
1. 問題の発生経緯 Link to heading
最初のエラーメッセージ Link to heading
WordPressのインストール中、こんなエラーに遭遇しました:
Error establishing a database connection
詳細を確認すると:
mysqli_real_connect(): SSL operation failed with code 1. OpenSSL Error messages:
error:0A000126:SSL routines::unexpected eof while reading
その時の私の思考:
- 「SSL証明書の問題だな」
- 「WordPressがCloud SQLのSSL証明書を読み込めていない」
- 「→ アプリケーション側で証明書を設定すれば解決するはず」
この判断が、すべての間違いの始まりでした。
2. 判断ミス1: カスタムdb.phpによる対症療法 Link to heading
取ったアプローチ(間違い) Link to heading
私は wp-content/db.php というカスタムMySQLドライバを作成しました:
1<?php
2// カスタムMySQLドライバ - SSL証明書を設定
3class wpdb extends wpdb {
4 public function db_connect($allow_bail = true) {
5 $this->dbh = new mysqli(
6 DB_HOST,
7 DB_USER,
8 DB_PASSWORD,
9 DB_NAME,
10 3306,
11 null
12 );
13
14 // SSL証明書設定
15 $this->dbh->ssl_set(
16 '/var/www/certs/client-key.pem',
17 '/var/www/certs/client-cert.pem',
18 '/var/www/certs/server-ca.pem',
19 null,
20 null
21 );
22
23 return $this->dbh->real_connect(
24 DB_HOST,
25 DB_USER,
26 DB_PASSWORD,
27 DB_NAME,
28 3306,
29 null,
30 MYSQLI_CLIENT_SSL
31 );
32 }
33}
この判断の何が問題だったのか Link to heading
問題1: アプリケーション層で解決しようとした Link to heading
- 根本原因: Cloud SQLのデフォルト設定が
require_ssl = true - 私の対応: アプリケーション側でSSL証明書を設定
- 正しい対応: Terraformで
require_ssl = falseに設定すべきだった
1# 正しいアプローチ(Terraform)
2resource "google_sql_database_instance" "wordpress" {
3 settings {
4 ip_configuration {
5 require_ssl = false # ← これだけで解決
6 }
7 }
8}
問題2: IaC原則違反 Link to heading
- カスタムファイル(db.php)を手動で配置
- Ansible管理外のファイル
- 他のサーバーへの展開時に再現性がない
- Git管理されていない
問題3: WordPressコアの動作を変更 Link to heading
wp-content/db.phpはWordPressの「ドロップインファイル」- WordPressのデータベース接続ロジック全体を上書き
- 将来のWordPressアップデートで互換性問題のリスク
3. 判断ミス2: Terraformでの根本対応を後回しにした Link to heading
なぜ後回しにしたのか Link to heading
私の思考プロセス:
- 「カスタムdb.phpで動いた!」
- 「とりあえずWordPressのインストールを進めよう」
- 「インフラ設定の変更は後でいいや」
この「とりあえず動けばいい」思考が致命的でした。
後回しにした結果 Link to heading
新しいインスタンスで同じエラー
- Terraform applyでインスタンスが再作成
- カスタムdb.phpが存在しない
- 再度同じエラーに遭遇
デバッグの混乱
- 「なぜ動いていたのに動かなくなった?」
- カスタムdb.phpの存在を忘れていた
- NFSマウントされたファイルの把握が困難
最終的にカスタムdb.phpを削除
- Terraformで
require_ssl = falseに変更 - カスタムdb.phpを削除
- あっさり解決
- Terraformで
4. 時系列でみる判断の分岐点 Link to heading
各ポイントでの「取るべきだった行動」 Link to heading
| 時点 | 実際の行動 | 取るべきだった行動 |
|---|---|---|
| エラー発生 | アプリ層で解決を試みる | インフラ設定を確認 |
| カスタムdb.php作成 | 「動いた!」と満足 | 根本原因を調査 |
| 一時的に動作 | 次のタスクに進む | Terraform修正を完了 |
| インスタンス再作成 | 「なぜ動かない?」と混乱 | - |
| 2時間後 | Terraform修正 | 最初からこうすべきだった |
5. 根本原因分析: なぜ判断を誤ったのか Link to heading
原因1: Cloud SQLのデフォルト設定への理解不足 Link to heading
知らなかったこと:
- Cloud SQLのデフォルトは
require_ssl = true - プライベートIP接続でもSSL要件は有効
- SSL証明書は手動で発行・配布する必要がある
学んだこと:
1# Cloud SQLの設定確認コマンド
2gcloud sql instances describe INSTANCE_NAME \
3 --format="value(settings.ipConfiguration.requireSsl)"
原因2: エラーメッセージの表面的な読み取り Link to heading
エラーメッセージ:
SSL operation failed
私の解釈: 「証明書が足りない」 正しい解釈: 「そもそもSSL接続が必要ない環境でSSLを要求されている」
原因3: アプリケーション層で解決しようとするバイアス Link to heading
私の背景:
- アプリケーションエンジニア出身
- インフラ設定よりコード修正に慣れている
- 「コードで解決できる」という思い込み
バイアスの罠:
- アプリ層で解決 = 「すぐできる」「簡単」
- インフラ層の変更 = 「面倒」「怖い」「影響範囲が大きい」
現実:
| 対応 | 実装時間 | デバッグ時間 | 保守性 |
|---|---|---|---|
| カスタムdb.php | 30分 | 2時間 | 低 |
| Terraform修正 | 5分 | 0分 | 高 |
原因4: IaC原則の理解不足 Link to heading
違反したIaC原則:
すべてをコードで管理
- 違反: カスタムdb.phpを手動配置
- 正: Terraformで設定変更
冪等性
- 違反: 手動ファイル配置は再現性がない
- 正: terraform applyは何度実行しても同じ結果
不変インフラ
- 違反: 既存サーバーにファイル追加
- 正: 設定変更後にインスタンス再作成
6. 再発防止策: 同様の事象が起きた時のチェックリスト Link to heading
エラー発生時の思考フロー Link to heading
□ Step 1: エラーの発生層を特定
- インフラ層(ネットワーク、DB設定、認証)
- ミドルウェア層(Nginx、PHP、MySQL)
- アプリケーション層(WordPress、プラグイン)
□ Step 2: デフォルト設定を確認
- 「デフォルトではどうなっているか?」
- 「設定を変更したか?」
- 「ドキュメントの推奨設定は?」
□ Step 3: 対応方法の検討
- 根本対応か対症療法か?
- IaC原則に従っているか?
- 将来の運用コストは?
□ Step 4: 実装前の自問自答
- 「この対応は再現可能か?」
- 「他のサーバーでも動くか?」
- 「1年後も保守できるか?」
Cloud SQL固有のチェックリスト Link to heading
□ プライベートIP接続かパブリックIP接続か?
- プライベートIPならSSL不要なケースが多い
□ require_ssl設定を確認
gcloud sql instances describe INSTANCE_NAME
□ アプリケーションから接続テスト
mysql -h DB_HOST -u DB_USER -p
□ SSL証明書の有効期限確認(SSL使う場合)
gcloud sql ssl-certs list --instance=INSTANCE_NAME
7. 学んだこと・読者へのメッセージ Link to heading
失敗から得た3つの教訓 Link to heading
教訓1: 「動けばいい」は技術的負債の始まり Link to heading
一時的に動作することと、正しく動作することは別物です。
- カスタムdb.phpは「動いた」
- しかし、保守不可能で再現性もない
- 結局、後で2時間かけて正しく直すことに
正しいアプローチ:
- エラーの根本原因を特定
- インフラ層の設定を修正
- 再現可能な形で実装
教訓2: IaC原則は「面倒な作業」ではなく「時間短縮」 Link to heading
「Terraform修正は面倒だから後で…」という思考が、結果的に時間を浪費しました。
比較: 最初からTerraform修正していた場合
| アプローチ | 実装 | デバッグ | 合計 |
|---|---|---|---|
| カスタムdb.php → Terraform | 30分 | 120分 | 150分 |
| 最初からTerraform | 5分 | 0分 | 5分 |
時間差: 145分(2時間25分)
教訓3: エラーメッセージは「何が足りないか」ではなく「何が間違っているか」を示す Link to heading
SSL operation failed
このメッセージを「証明書が足りない」と解釈したのが間違いでした。
正しい解釈:
- 「SSL接続を要求されているが、それは必要か?」
- 「プライベートIP接続でSSLは必須ではない」
- 「→ インフラ設定を見直すべき」
読者へのメッセージ Link to heading
失敗は避けられません。重要なのは、失敗から学び、同じミスを繰り返さないことです。
この記事で共有した判断ミスは、決して特殊なケースではありません。
- 「とりあえず動けばいい」
- 「後で直せばいい」
- 「アプリで解決できるはず」
これらの思考パターンは、誰にでも起こりうるものです。
大切なこと:
- 失敗を記録する
- なぜその判断をしたのか分析する
- 次回同じ状況でどう判断すべきか整理する
あなたが同じようなエラーに遭遇した時、この記事が判断の助けになれば幸いです。
参考リンク Link to heading
この記事のコード Link to heading
実際のTerraform設定:
1# terraform/modules/database/main.tf
2resource "google_sql_database_instance" "wordpress" {
3 name = "${var.env}-wordpress-db"
4 database_version = "MYSQL_8_0"
5 region = var.region
6
7 settings {
8 ip_configuration {
9 ipv4_enabled = false # パブリックIPは無効
10 private_network = var.network_id
11 require_ssl = false # ← これが重要!
12 }
13 }
14}
GitHub: infra-ai-agent
まとめ Link to heading
- ❌ カスタムdb.phpによる対症療法は間違い
- ✅ Terraformで
require_ssl = falseに設定するのが正解 - ⏱️ 正しいアプローチなら5分で解決(実際は2時間浪費)
- 📚 IaC原則を守ることが、結果的に時間短縮になる
- 🎯 エラーメッセージの真意を読み取る訓練が必要
次回予告: 「WordPress環境構築で遭遇した5つのハマりポイントと解決策」では、今回のSSL問題以外にも遭遇した具体的なトラブル事例を共有します。
著者について: インフラエンジニアリングを学びながらGCP上でマルチテナントWordPress環境を構築。失敗から学ぶことを大切にしています。
この記事が役に立ったら: GitHub Starをいただけると嬉しいです! infra-ai-agent