Files
wordpress/CLAUDE.md
T
claude 8241812d84
Helm Chart Release / release-chart (push) Successful in 6s
docs: kube-vip環境での実IP喪失原因と共有Ingress Controller移行手順を追記
mikoto-wordpress-nginxの調査で、type: ClusterIP + kube-vipアノテーション
による手動VIP付与構成では、kube-vip自体がTCP接続をプロキシするため
externalTrafficPolicyを設定しても実クライアントIPが失われることが判明。
共有Ingress Controller(Cilium組み込み等)へ移行する場合の具体的な
values設定とhelm upgradeコマンド例をREADMEに追加。
クラスタ構成の調査結果をCLAUDE.mdに記録。
2026-08-09 16:20:40 +09:00

73 lines
8.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md — WordPress Helm Chart
## リポジトリ概要
Raspberry Pi などのベアメタルで稼働することを想定した、Kubernetes 上で動作する Alpine Nginx + WordPress (PHP-FPM) の Helm チャート。
- **Gitea リポジトリ**: `ssh://git@192.168.9.65/helmchart/wordpress`
- **Helm リポジトリ**: `https://git.cafepieters.com/api/packages/helmchart/helm`
## 実行環境について
WordPress本体はイメージ内蔵のもの(`docker.io/wordpress:<tag>-fpm-alpine`)をemptyDirにコピーして使い捨てで起動し、`wp-content`のみPVCで永続化する(bitnami方式)。PHPの実行環境はこのイメージに依存し、本リポジトリにPHPコードは含まれない。
## Git コミット情報
| 項目 | 値 |
|------|-----|
| 名前 | Claude |
| メール | claude@cafepieters.com |
| SSH キー | `P:\Claude\.ssh\id_claude` |
## 作業完了のルール(重要)
1. **機能を追加・変更した場合は、必ず README.md を更新すること。** 追加・変更した機能の説明を反映してから作業完了とする。
2. **変更は必ず Git Commit / Push まで行うこと。** 作業単位ごとにコミットし、origin(main) へ push するまでが作業完了。
3. **Commit メッセージに Claude クレジット(Co-Authored-By 等)を追記することは禁止。** `user.name = Claude` でコミットされるため、ユーザー名で判別可能。
4. `git pull` で取り込まれた変更は必ず尊重し、revert して push することは禁止(既存の共通ルールと同じ)。
## クラスタ構成メモ(実運用環境)
- ノード: `cpi11`(control-plane, 192.168.9.9/物理IF)、`wpi21`/`wpi22`/`wpi23`(worker)。全てRaspberry Pi(Ubuntu 25.04)。
- CNI: **Cilium**kube-proxyなし、eBPFベース)。`cilium-envoy` Podが動作しており、Cilium組み込みIngress ControllerEnvoyベース)が利用可能。
- Pod CIDR: `10.0.0.0/8`系、ノードごとに `/24` を割り当て(例: cpi11→`10.0.0.0/24`、wpi22→`10.0.1.0/24`、wpi21→`10.0.2.0/24`、wpi23→`10.0.3.0/24`)。
- 外部公開: **kube-vip**ARP方式、静的Pod `kube-vip-cpi11`)。物理ルーターのグローバルIP配下、`192.168.9.0/24` セグメント内でVIPを払い出す。このセグメントはルーターがLAN機器(スマホ/PC等)にDHCP払い出しする範囲と重複しないよう、ルーター側で範囲を絞って共存させている。**IPが希少なため濫用できない。**
- 各WordPress/PHPFPMリリースは現状、`service.type: ClusterIP` + `kube-vip.io/loadbalancerIPs`/`kube-vip.io/vipHost` アノテーションを**Helm管理外で手動付与**し、リリースごとに個別のVIPを得る運用になっている(本チャートの `templates/service.yaml` にはannotationsのテンプレート化自体が存在しないため)。
- **既知の問題**: この構成では、kube-vipがL2 ARP応答に加えて自前でTCPコネクションをプロキシしてしまうため、`externalTrafficPolicy`LoadBalancer/NodePort専用でありClusterIPには無効という制約とは別に、そもそもkube-vipの時点で)実クライアントIPが失われる。詳細はREADME.mdの「kube-vip等でグローバルIP/VIPが限られている環境での実IP取得(共有Ingress Controller構成)」を参照。
- 今後、実IP取得のためCilium組み込みIngress Controller(またはingress-nginx)へ移行する方針で合意済み(2026-08-08時点、ユーザーが選択)。ただし全リリース(wordpress-nginx系だけでなくphpfpm系も含む)の移行が必要な大掛かりな作業のため、本セッションではWordPressチャート側の対応(`ingress.yaml`/`forwardRealIP`は既存機能で対応済み、README migration手順を追記)のみ実施。実際のCilium Ingress有効化・各リリースのhelm upgradeはユーザー側の作業。
## チャート改修履歴
### 実IP取得の修正 + SMTP経由メール送信の追加(2026-08-08, v7.0.2-a
**背景**: ルーター(グローバルIP)配下の 192.168.9.x セグメントにコントロールプレーン/ワーカーノードがあり、その上のPodでWordPressが稼働する構成において、(1) 訪問者の実IPアドレスが正しく取得できない、(2) `wp_mail()` によるメール送信が失敗する、という2つの不具合が報告された。
**(1) 実IPアドレス取得の不具合**
原因は2つ複合していた:
- Service`LoadBalancer`/MetalLB想定)はデフォルトの `externalTrafficPolicy: Cluster` のため、kube-proxyが送信元IPをノード内部IPにSNATしてしまい、Nginxの `$remote_addr` が実IPではなくノードIPになっていた。
- 本チャートの `nginx.forwardRealIP`X-Forwarded-Forを信頼するreal_ipモジュール設定)は、Ingress ControllerやCDNなど**XFFヘッダーを付与するリバースプロキシが前段にある場合**にのみ機能する設計だが、このベアメタル構成ではService直下にPodがぶら下がるだけでXFFを付与する層が存在せず、機能していなかった(`trustedProxies``192.168.0.0/16` が含まれるためSNAT後のノードIPを「信頼済みプロキシ」とみなしてしまうが、そのIPがXFFを付与するわけではないので `$real_ip` は結局SNAT後のIPのままになる)。
さらに、`wp-config.php` 生成テンプレート内でPHP側が生のX-Forwarded-Forヘッダーを無条件に信頼してREMOTE_ADDRを上書きする処理があり、Nginxのreal_ip信頼境界を迂回してクライアントがIPを詐称できる状態だった(副次的なセキュリティ上の問題)。
**修正内容**:
- `values.yaml`: `service.externalTrafficPolicy: Local` をデフォルト追加(SNATを回避し実IPをそのまま透過させる。MetalLB L2モード等と組み合わせる想定。ClusterIPでは無視される)。
- `templates/service.yaml`: `externalTrafficPolicy` を条件付きで出力するよう変更。
- `templates/deployment.yaml`: `wp-config.php` 内のPHP側REMOTE_ADDR再判定処理を削除(NginxのfastcgiパラメータでREMOTE_ADDRは既に正しく渡っているため不要かつ危険だった)。
- `values.yaml`/`README.md`: `nginx.forwardRealIP` は本当にXFFを付与するリバースプロキシが前段にある場合のみ有効化する旨を明記。
**(2) メール送信の不具合**
原因: 使用しているAlpineベースのWordPressイメージには、PHPの `mail()``wp_mail()` が内部的に利用)を実際に配送するMTA(sendmail相当)が同梱されておらず、`sendmail_path` の送信先が存在しなかった。
**修正内容**[helmchart/phpfpm](https://git.cafepieters.com/helmchart/phpfpm) チャートと同一の手法を採用。ユーザー指定によりphpfpmの実装パターンをそのまま踏襲):
- `values.yaml``smtp.*` セクションを追加(`enabled`/`host`/`protocol`/`port`/`auth.*`/`from`/`tls.*`)。
- `templates/configmap-smtp.yaml`(新規): `/etc/msmtprc` を生成するConfigMap。
- `templates/secret-smtp.yaml`(新規): SMTPパスワードを格納するSecret。
- `templates/deployment.yaml`: `smtp.enabled: true` の場合のみ、`wordpress` コンテナの起動コマンドをシェルラッパーに変更し、`apk add msmtp ca-certificates``/etc/msmtprc` 配置(`chmod 644`、www-dataから読めるように) → PHPの `sendmail_path``msmtp -t` に向ける `99-smtp.ini` を生成 → `exec php-fpm` という順で起動する。
- `apk add` にrootが必要なため、SMTP有効時のみ既存の `securityContext: runAsUser/runAsGroup: 82` を外している(PHP-FPMワーカー自体はイメージ標準の `www.conf` によりuid82で動作するため、実際のPHPコード実行権限は変わらない)。`smtp.enabled: false`(デフォルト)では従来どおり非rootで起動する。
- msmtpのパスワードはmsmtprcに直書きせず `passwordeval "cat /etc/smtp-secrets/password"` で別ファイル参照(phpfpmの `CHANGELOG-8.5.6-f/g.md` で判明した「Secret/ConfigMapの権限が0600だとwww-dataから読めない」問題を踏まえ、最初から `0644` で実装済み)。
- WordPress本体は `wp_mail()` が自動的に `mail()`/`sendmail_path` を経由するため、phpfpmと異なりPHPコード側の変更(ヘルパークラスの読み込み等)は不要。
**対象ファイル**: `values.yaml`, `templates/service.yaml`, `templates/deployment.yaml`, `templates/configmap-smtp.yaml`(新規), `templates/secret-smtp.yaml`(新規), `README.md`, `Chart.yaml`