# 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有効時) ### 基本インストール ```bash # リポジトリのクローン git clone https://git.cafepieters.com/helmchart/phpfpm.git cd phpfpm # デフォルト設定でインストール helm install my-phpfpm . # カスタム設定でインストール helm install my-phpfpm . -f my-values.yaml ``` ### 動作確認 ```bash # 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` | 設定スニペット | `""` | ## 使用例 ### 例1: シンプルなPHPアプリケーション ```yaml # values.yaml replicaCount: 2 persistence: enabled: true size: 5Gi service: type: LoadBalancer resources: requests: memory: "256Mi" cpu: "200m" limits: memory: "512Mi" cpu: "500m" ``` ```bash helm install my-app . -f values.yaml ``` ### 例2: Composerパッケージ利用 ```yaml # 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を使用 ```yaml # 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接続 ```yaml # 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統合(スクレイピング) ```yaml # 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 get('https://example.com'); echo $driver->getTitle(); $driver->quit(); ``` ### 例6: カスタムNginx設定 ```yaml # 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: 画像処理アプリケーション(GD拡張) ```yaml # 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 ``` ### 例8: 本番環境構成(フル機能) ```yaml # 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" ``` **デプロイ**: ```bash # Secretを先に作成 kubectl create secret generic db-password --from-literal=password='SuperSecurePass' # デプロイ helm install production-api . \ -f production-values.yaml \ --set externalDatabase.password=$(kubectl get secret db-password -o jsonpath='{.data.password}' | base64 -d) ``` ## アップグレード ```bash # 設定変更後のアップグレード helm upgrade my-phpfpm . -f values.yaml # 特定のパラメータのみ変更 helm upgrade my-phpfpm . --set replicaCount=5 # ロールバック helm rollback my-phpfpm 1 ``` ## アンインストール ```bash # チャートの削除 helm uninstall my-phpfpm # PVCも削除する場合 kubectl delete pvc -l app.kubernetes.io/name=phpfpm ``` ## トラブルシューティング ### Pod起動が遅い **原因**: Composerパッケージのダウンロード時間 **対策**: ```yaml composer: installOptions: "--no-dev --optimize-autoloader --prefer-dist" ``` ### メモリ不足エラー **対策**: ```yaml resources: requests: memory: "512Mi" limits: memory: "2Gi" ``` ### PHP拡張エラー **対策**: 必要なAPKパッケージを追加 ```yaml composer: additionalApkPackages: - "build-base" - "autoconf" ``` ### データベース接続エラー **確認**: ```bash # 環境変数確認 kubectl exec -it -c php-fpm -- env | grep DB_ # 接続テスト kubectl exec -it -c php-fpm -- mysql -h $DB_HOST -u $DB_USER -p$DB_PASS ``` ### ログ確認 ```bash # PHP-FPMログ kubectl logs -c php-fpm # Nginxログ kubectl logs -c nginx # Seleniumログ(有効時) kubectl logs -c selenium # リアルタイム監視 kubectl logs -f -c php-fpm ``` ## 高度な設定 ### カスタムイメージの使用 ```yaml image: php: registry: my-registry.com repository: custom-php-fpm tag: "latest" ``` ### 水平オートスケーリング ```yaml # 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 | ## セキュリティ考慮事項 ### データベースパスワードの管理 ```bash # 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の適用 ```yaml # 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の有効化 ```yaml 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の最適化 ```yaml composer: installOptions: "--no-dev --optimize-autoloader --classmap-authoritative --apcu-autoloader" additionalPhpExtensions: - "apcu" additionalApkPackages: - "apcu-dev" ``` ## よくある質問(FAQ) **Q: PHPバージョンを変更するには?** A: `image.php.tag`を変更してください。 ```yaml image: php: tag: "8.3.15-fpm-alpine3.21" ``` **Q: 複数ドメインに対応できますか?** A: Ingressで複数ホストを設定できます。 ```yaml ingress: hosts: - host: domain1.com paths: [...] - host: domain2.com paths: [...] ``` **Q: SeleniumとComposerは同時に使えますか?** A: はい、完全に共存可能です。 **Q: 既存のPHPアプリをデプロイするには?** A: PVCにファイルをコピーしてください。 ```bash kubectl cp ./my-app :/var/www/html/ -c php-fpm ``` ## 関連ドキュメント - [Composer使用ガイド](./COMPOSER_GUIDE.md) - [マイグレーションガイド](./MIGRATION_GUIDE.md) - [Selenium別チャート化設計](./SELENIUM_SEPARATION_DESIGN.md) ## ライセンス このHelmチャートはMITライセンスで公開されています。 ## サポート - Issue: https://git.cafepieters.com/helmchart/phpfpm/issues - リポジトリ: https://git.cafepieters.com/helmchart/phpfpm ## 変更履歴 ### v2.0.0 - Composer対応追加 - PHP拡張の柔軟な追加機能 - 統合的な依存関係管理 ### v1.0.0 - 初回リリース - Nginx + PHP-FPM基本構成 - Selenium統合 - 外部データベース対応