Files
phpfpm/README.md
Claude 02696fc55e
All checks were successful
Helm Chart Release / release-chart (push) Successful in 12s
feat: Add Real IP forwarding feature for bare-metal clusters
ベアメタルKubernetesクラスターやLoadBalancer環境において、
PHP側で訪問者の実IPアドレスを取得できる機能を追加。

Changes:
- Add nginx.forwardRealIP configuration in values.yaml
- Implement real_ip_header and set_real_ip_from in Nginx config
- Pass real IP info to PHP-FPM via fastcgi_param
- Add usage example and documentation in README.md
- Create test-real-ip.php for verification
- Update chart version to 8.5.2-a

Features:
- Compatible with existing customConfig.snippet
- Configurable trusted proxy networks
- Supports multi-tier proxy with recursive option
- Default disabled for backward compatibility

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 09:21:55 +09:00

21 KiB
Raw Blame History

PHP-FPM Helm Chart

Alpine LinuxベースのNginx + PHP-FPM環境をKubernetesにデプロイするためのHelmチャートです。Composer、Selenium、外部データベース接続など、本格的なPHPアプリケーション実行に必要な機能を統合しています。

特徴

  • 🚀 軽量: Alpine Linuxベースで高速起動
  • 📦 Composer対応: 依存パッケージ管理を柔軟にカスタマイズ
  • 🌐 Nginx統合: PHP-FPMとNginxのマルチコンテナ構成
  • 🔧 カスタマイズ可能: Nginx設定、PHP拡張を自由に追加
  • 🤖 Selenium統合: ブラウザ自動化・スクレイピングに対応
  • 💾 永続化ストレージ: PVCによるデータ永続化
  • 🔐 外部DB接続: MySQL/MariaDB接続機能を内蔵
  • 📊 本番対応: Ingress、TLS、リソース管理に対応

クイックスタート

前提条件

  • Kubernetes 1.19+
  • Helm 3.0+
  • PV プロビジョナーpersistence有効時

基本インストール

# Helmリポジトリを追加
helm repo add cafepieters https://git.cafepieters.com/api/packages/helmchart/helm
helm repo update

# デフォルト設定でインストール
helm install my-phpfpm cafepieters/phpfpm

# カスタム設定でインストール
helm install my-phpfpm cafepieters/phpfpm -f my-values.yaml

# 特定のバージョンをインストール
helm install my-phpfpm cafepieters/phpfpm --version 2.0.0

ソースからのインストール

# リポジトリのクローン
git clone https://git.cafepieters.com/helmchart/phpfpm.git
cd phpfpm

# デフォルト設定でインストール
helm install my-phpfpm .

# カスタム設定でインストール
helm install my-phpfpm . -f my-values.yaml

動作確認

# Podの確認
kubectl get pods -l app.kubernetes.io/name=phpfpm

# サービスの確認
kubectl get svc -l app.kubernetes.io/name=phpfpm

# ログ確認
kubectl logs -l app.kubernetes.io/name=phpfpm -c php-fpm
kubectl logs -l app.kubernetes.io/name=phpfpm -c nginx

アーキテクチャ

┌─────────────────────────────────────────────┐
│  Kubernetes Pod                             │
│                                             │
│  ┌──────────────┐      ┌─────────────────┐ │
│  │   Nginx      │─────▶│   PHP-FPM       │ │
│  │   :80        │      │   :9000         │ │
│  └──────────────┘      │   + Composer    │ │
│         │              │   + Extensions  │ │
│         │              └─────────────────┘ │
│         │                      │           │
│  ┌──────▼──────────────────────▼────────┐  │
│  │   Persistent Volume (PVC)            │  │
│  │   /var/www/html                      │  │
│  └──────────────────────────────────────┘  │
│                                             │
│  ┌─────────────────────────────────────┐   │
│  │   Selenium (Optional)               │   │
│  │   :4444                             │   │
│  └─────────────────────────────────────┘   │
└─────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────┐
│  External Database (Optional)               │
│  MySQL/MariaDB                              │
└─────────────────────────────────────────────┘

主要な設定パラメータ

基本設定

パラメータ 説明 デフォルト
replicaCount Podのレプリカ数 1
image.php.tag PHPバージョン 8.5.2-fpm-alpine3.23
image.nginx.tag Nginxバージョン 1.29.4-alpine-perl
service.type Serviceタイプ LoadBalancer
service.port Serviceポート 80

永続化ストレージ

パラメータ 説明 デフォルト
persistence.enabled PVC有効化 true
persistence.size ストレージサイズ 1Gi
persistence.accessMode アクセスモード ReadWriteOnce

Composer設定

パラメータ 説明 デフォルト
composer.enabled Composer有効化 false
composer.packages インストールパッケージ []
composer.useComposerJson composer.json使用 false
composer.composerJson composer.json内容 ""
composer.installOptions installオプション "--no-dev --optimize-autoloader"
composer.additionalPhpExtensions 追加PHP拡張 []
composer.additionalApkPackages 追加APKパッケージ []

Selenium設定

パラメータ 説明 デフォルト
selenium.enabled Selenium有効化 false
image.selenium.tag Seleniumバージョン 144.0-chromedriver-144.0

外部データベース設定

パラメータ 説明 デフォルト
externalDatabase.enabled 外部DB接続有効化 false
externalDatabase.host DBホスト名 mariadb-hostname
externalDatabase.port DBポート 3306
externalDatabase.database データベース名 dbname
externalDatabase.username ユーザー名 user
externalDatabase.password パスワード pass

Ingress設定

パラメータ 説明 デフォルト
ingress.enabled Ingress有効化 false
ingress.className IngressClass名 ""
ingress.annotations アノテーション {}
ingress.hosts ホスト設定 [{host: "example.tld"}]
ingress.tls TLS設定 []

Nginx設定

パラメータ 説明 デフォルト
nginx.customConfig.enabled カスタム設定有効化 false
nginx.customConfig.snippet 設定スニペット ""
nginx.forwardRealIP.enabled リアルIP取得有効化 false
nginx.forwardRealIP.header リアルIP取得ヘッダー "X-Forwarded-For"
nginx.forwardRealIP.recursive 再帰的IP検索 true
nginx.forwardRealIP.trustedProxies 信頼するプロキシネットワーク ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
nginx.forwardRealIP.additionalTrustedProxies 追加の信頼プロキシ []

使用例

例1: シンプルなPHPアプリケーション

# values.yaml
replicaCount: 2

persistence:
  enabled: true
  size: 5Gi

service:
  type: LoadBalancer

resources:
  requests:
    memory: "256Mi"
    cpu: "200m"
  limits:
    memory: "512Mi"
    cpu: "500m"
helm install my-app cafepieters/phpfpm -f values.yaml

例2: Composerパッケージ利用

# values.yaml
composer:
  enabled: true
  packages:
    - "monolog/monolog:^3.0"
    - "guzzlehttp/guzzle:^7.0"
    - "vlucas/phpdotenv:^5.0"
  installOptions: "--no-dev --optimize-autoloader"

persistence:
  enabled: true
  size: 2Gi

例3: composer.jsonを使用

# values.yaml
composer:
  enabled: true
  useComposerJson: true
  composerJson: |
    {
      "require": {
        "php": ">=8.0",
        "slim/slim": "^4.0",
        "slim/psr7": "^1.0",
        "monolog/monolog": "^3.0"
      },
      "autoload": {
        "psr-4": {
          "App\\": "src/"
        }
      }
    }
  installOptions: "--optimize-autoloader"

replicaCount: 3

ingress:
  enabled: true
  className: nginx
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
  hosts:
    - host: api.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: api-tls
      hosts:
        - api.example.com

例4: MySQL接続

# values.yaml
composer:
  enabled: true
  packages:
    - "illuminate/database:^10.0"

externalDatabase:
  enabled: true
  host: mysql.default.svc.cluster.local
  port: 3306
  database: myapp
  username: appuser
  password: "SecurePassword123"

persistence:
  enabled: true
  size: 3Gi

例5: Selenium統合スクレイピング

# values.yaml
composer:
  enabled: true
  packages:
    - "symfony/dom-crawler:^6.0"
    - "symfony/css-selector:^6.0"
    - "monolog/monolog:^3.0"

selenium:
  enabled: true  # php-webdriver/webdriverが自動追加

persistence:
  enabled: true
  size: 5Gi

resources:
  requests:
    memory: "1Gi"
    cpu: "1000m"
  limits:
    memory: "3Gi"
    cpu: "2000m"

PHPコード例:

<?php
require_once '/var/www/html/vendor/autoload.php';

use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;

// Seleniumに接続
$driver = RemoteWebDriver::create(
    'http://localhost:4444',
    DesiredCapabilities::chrome()
);

$driver->get('https://example.com');
echo $driver->getTitle();
$driver->quit();

例6: カスタムNginx設定

# values.yaml
nginx:
  customConfig:
    enabled: true
    snippet: |
      client_max_body_size 100M;
      
      location ~ \.php$ {
          fastcgi_pass 127.0.0.1:9000;
          fastcgi_index index.php;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          include fastcgi_params;
          
          fastcgi_read_timeout 300;
          fastcgi_send_timeout 300;
      }
      
      location /admin {
          auth_basic "Administrator Area";
          auth_basic_user_file /etc/nginx/.htpasswd;
      }

persistence:
  enabled: true

例7: ベアメタル環境でのリアルIP取得

ベアメタルKubernetesやLoadBalancer経由でのアクセスで、PHPからクライアントの実IPアドレスを取得する設定です。

# values.yaml
service:
  type: LoadBalancer

nginx:
  forwardRealIP:
    # リアルIP取得機能を有効化
    enabled: true

    # リアルIPを取得するヘッダー環境に応じて変更
    # - X-Real-IP: シンプルな1段プロキシ
    # - X-Forwarded-For: 多段プロキシ対応(推奨)
    header: "X-Forwarded-For"

    # 再帰的にリアルIPを検索多段プロキシ環境で推奨
    recursive: true

    # 信頼するプロキシのネットワーク範囲
    # ベアメタルクラスターのPodネットワークとServiceネットワークを指定
    trustedProxies:
      - "10.0.0.0/8"      # Kubernetesデフォルトのクラスタネットワーク
      - "172.16.0.0/12"   # Dockerデフォルトネットワーク
      - "192.168.0.0/16"  # プライベートネットワーク

    # 追加で信頼するプロキシ外部LoadBalancerなど
    additionalTrustedProxies:
      - "203.0.113.0/24"  # 外部LoadBalancerのIPレンジ

persistence:
  enabled: true

この設定により、PHP側で以下の変数から実IPアドレスが取得できます

  • $_SERVER['REMOTE_ADDR'] - クライアントの実IPアドレス
  • $_SERVER['HTTP_X_REAL_IP'] - 同上(互換性用)
  • $_SERVER['HTTP_X_FORWARDED_FOR'] - プロキシチェーン全体

検証用PHPコード:

<?php
echo "Real IP: " . $_SERVER['REMOTE_ADDR'] . "\n";
echo "X-Real-IP: " . ($_SERVER['HTTP_X_REAL_IP'] ?? 'not set') . "\n";
echo "X-Forwarded-For: " . ($_SERVER['HTTP_X_FORWARDED_FOR'] ?? 'not set') . "\n";

注意事項:

  • trustedProxiesには、信頼できるプロキシLoadBalancer、Ingressコントローラーのみを指定してください
  • 不正なプロキシを信頼すると、IPスプーフィング攻撃のリスクがあります
  • customConfig.snippetとの併用も可能です(競合しません)

例8: 画像処理アプリケーションGD拡張

# values.yaml
composer:
  enabled: true
  packages:
    - "intervention/image:^2.0"
  additionalPhpExtensions:
    - "gd"
    - "exif"
  additionalApkPackages:
    - "libpng-dev"
    - "libjpeg-turbo-dev"
    - "freetype-dev"

persistence:
  enabled: true
  size: 10Gi

service:
  type: ClusterIP

ingress:
  enabled: true
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"
  hosts:
    - host: images.example.com

例9: 本番環境構成(フル機能)

# production-values.yaml
replicaCount: 5

image:
  php:
    tag: "8.5.2-fpm-alpine3.23"
  nginx:
    tag: "1.29.4-alpine-perl"

composer:
  enabled: true
  useComposerJson: true
  composerJson: |
    {
      "require": {
        "php": ">=8.1",
        "slim/slim": "^4.0",
        "monolog/monolog": "^3.0",
        "vlucas/phpdotenv": "^5.0",
        "firebase/php-jwt": "^6.0"
      },
      "autoload": {
        "psr-4": {
          "App\\": "src/"
        }
      }
    }
  installOptions: "--no-dev --optimize-autoloader --classmap-authoritative"
  additionalPhpExtensions:
    - "opcache"

externalDatabase:
  enabled: true
  host: mysql-primary.database.svc.cluster.local
  port: 3306
  database: production_db
  username: prod_user
  password: "{{ .Values.dbPassword }}"  # 外部から注入

persistence:
  enabled: true
  size: 20Gi
  storageClass: ssd-storage

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  className: nginx
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  hosts:
    - host: api.production.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: production-tls
      hosts:
        - api.production.com

nginx:
  customConfig:
    enabled: true
    snippet: |
      client_max_body_size 50M;
      fastcgi_read_timeout 300;
      
      # Opcache設定
      fastcgi_param PHP_VALUE "
        opcache.enable=1
        opcache.memory_consumption=256
        opcache.interned_strings_buffer=16
        opcache.max_accelerated_files=10000
        opcache.revalidate_freq=0
        opcache.validate_timestamps=0
      ";

resources:
  requests:
    memory: "512Mi"
    cpu: "500m"
  limits:
    memory: "1Gi"
    cpu: "1000m"

デプロイ:

# Secretを先に作成
kubectl create secret generic db-password --from-literal=password='SuperSecurePass'

# Helmリポジトリからデプロイ
helm install production-api cafepieters/phpfpm \
  -f production-values.yaml \
  --set externalDatabase.password=$(kubectl get secret db-password -o jsonpath='{.data.password}' | base64 -d)

アップグレード

# リポジトリを更新
helm repo update cafepieters

# 最新バージョンにアップグレード
helm upgrade my-phpfpm cafepieters/phpfpm -f values.yaml

# 特定のパラメータのみ変更
helm upgrade my-phpfpm cafepieters/phpfpm --set replicaCount=5

# 特定のバージョンにアップグレード
helm upgrade my-phpfpm cafepieters/phpfpm --version 2.1.0

# ロールバック
helm rollback my-phpfpm 1

アンインストール

# チャートの削除
helm uninstall my-phpfpm

# PVCも削除する場合
kubectl delete pvc -l app.kubernetes.io/name=phpfpm

トラブルシューティング

Pod起動が遅い

原因: Composerパッケージのダウンロード時間

対策:

composer:
  installOptions: "--no-dev --optimize-autoloader --prefer-dist"

メモリ不足エラー

対策:

resources:
  requests:
    memory: "512Mi"
  limits:
    memory: "2Gi"

PHP拡張エラー

対策: 必要なAPKパッケージを追加

composer:
  additionalApkPackages:
    - "build-base"
    - "autoconf"

データベース接続エラー

確認:

# 環境変数確認
kubectl exec -it <pod-name> -c php-fpm -- env | grep DB_

# 接続テスト
kubectl exec -it <pod-name> -c php-fpm -- mysql -h $DB_HOST -u $DB_USER -p$DB_PASS

ログ確認

# PHP-FPMログ
kubectl logs <pod-name> -c php-fpm

# Nginxログ
kubectl logs <pod-name> -c nginx

# Seleniumログ有効時
kubectl logs <pod-name> -c selenium

# リアルタイム監視
kubectl logs -f <pod-name> -c php-fpm

高度な設定

カスタムイメージの使用

image:
  php:
    registry: my-registry.com
    repository: custom-php-fpm
    tag: "latest"

水平オートスケーリング

# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: phpfpm-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-phpfpm
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

リソース制限の推奨値

環境 CPU Request CPU Limit Memory Request Memory Limit
開発 100m 500m 256Mi 512Mi
ステージング 200m 1000m 512Mi 1Gi
本番(小) 500m 1000m 512Mi 1Gi
本番(大) 1000m 2000m 1Gi 2Gi

セキュリティ考慮事項

データベースパスワードの管理

# Secretの作成
kubectl create secret generic db-secret \
  --from-literal=password='YourSecurePassword'

# values.yamlで参照
externalDatabase:
  password: "{{ .Values.dbPassword }}"

# デプロイ時に注入
helm install my-app . \
  --set dbPassword=$(kubectl get secret db-secret -o jsonpath='{.data.password}' | base64 -d)

NetworkPolicyの適用

# networkpolicy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: phpfpm-netpol
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: phpfpm
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: ingress-nginx
    ports:
    - protocol: TCP
      port: 80

パフォーマンス最適化

Opcacheの有効化

composer:
  additionalPhpExtensions:
    - "opcache"

nginx:
  customConfig:
    enabled: true
    snippet: |
      fastcgi_param PHP_VALUE "
        opcache.enable=1
        opcache.memory_consumption=256
        opcache.interned_strings_buffer=16
        opcache.max_accelerated_files=10000
        opcache.revalidate_freq=60
      ";

Composerの最適化

composer:
  installOptions: "--no-dev --optimize-autoloader --classmap-authoritative --apcu-autoloader"
  additionalPhpExtensions:
    - "apcu"
  additionalApkPackages:
    - "apcu-dev"

よくある質問FAQ

Q: Helmリポジトリを追加するには?

A: 以下のコマンドでリポジトリを追加できます。

helm repo add cafepieters https://git.cafepieters.com/api/packages/helmchart/helm
helm repo update

# 利用可能なバージョンを確認
helm search repo cafepieters/phpfpm --versions

Q: PHPバージョンを変更するには?

A: image.php.tagを変更してください。

image:
  php:
    tag: "8.3.15-fpm-alpine3.21"

Q: 複数ドメインに対応できますか?

A: Ingressで複数ホストを設定できます。

ingress:
  hosts:
    - host: domain1.com
      paths: [...]
    - host: domain2.com
      paths: [...]

Q: SeleniumとComposerは同時に使えますか?

A: はい、完全に共存可能です。

Q: 既存のPHPアプリをデプロイするには?

A: PVCにファイルをコピーしてください。

kubectl cp ./my-app <pod-name>:/var/www/html/ -c php-fpm

関連ドキュメント

ライセンス

このHelmチャートはMITライセンスで公開されています。

サポート

変更履歴

v2.0.0

  • Composer対応追加
  • PHP拡張の柔軟な追加機能
  • 統合的な依存関係管理

v1.0.0

  • 初回リリース
  • Nginx + PHP-FPM基本構成
  • Selenium統合
  • 外部データベース対応