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

8.7 KiB
Raw Blame History

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: Ciliumkube-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-vipARP方式、静的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コネクションをプロキシしてしまうため、externalTrafficPolicyLoadBalancer/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つ複合していた:

  • ServiceLoadBalancer/MetalLB想定)はデフォルトの externalTrafficPolicy: Cluster のため、kube-proxyが送信元IPをノード内部IPにSNATしてしまい、Nginxの $remote_addr が実IPではなくノードIPになっていた。
  • 本チャートの nginx.forwardRealIPX-Forwarded-Forを信頼するreal_ipモジュール設定)は、Ingress ControllerやCDNなどXFFヘッダーを付与するリバースプロキシが前段にある場合にのみ機能する設計だが、このベアメタル構成ではService直下にPodがぶら下がるだけでXFFを付与する層が存在せず、機能していなかった(trustedProxies192.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 チャートと同一の手法を採用。ユーザー指定によりphpfpmの実装パターンをそのまま踏襲):

  • values.yamlsmtp.* セクションを追加(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_pathmsmtp -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