Files
phpfpm/README.md
T
claudeandClaude Fable 5 e9428c6448
Helm Chart Release / release-chart (push) Successful in 5s
feat: IngressのproxyBodySizeもuploadMaxSizeに自動連動 (v8.5.9-c)
uploadMaxSizeでnginx/PHPのアップロード上限は連動していたが、
ingress.enabled: true の場合、ingress-nginx側にも独自の上限
(デフォルト1MB)があり、そこで先に弾かれるケースが残っていた。

templates/ingress.yaml で、ingress.annotationsに
nginx.ingress.kubernetes.io/proxy-body-sizeが明示指定されていない
場合、uploadMaxSizeの値を自動的に付与するようにした(merge使用、
明示指定があればそちらを優先)。

これでuploadMaxSize 1箇所の設定でnginx・PHP・Ingressの3箇所すべてに
反映される。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-07 00:09:20 +09:00

1093 lines
33 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.
# 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
# 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
```
### ソースからのインストール
```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` |
| `uploadMaxSize` | アップロード最大サイズ(nginx/PHP両方に反映) | `"100m"` |
> **📌 アップロードサイズ上限について**
> `uploadMaxSize` の値は、以下**すべて**に同時に反映されます。どれか一つでも小さいと、そこで上限に達して失敗するため、この1つの値で揃える設計です。
> - nginxPodコンテナ内)の `client_max_body_size`
> - PHPの `upload_max_filesize` / `post_max_size`
> - `ingress.enabled: true` の場合、ingress-nginxの `nginx.ingress.kubernetes.io/proxy-body-size`(明示指定があればそちらが優先)
>
> 単位は `k` / `m` / `g`(大文字小文字問わず)が使用できます(例: `"200m"`, `"1g"`)。
>
> 大きなファイルをPHP側でメモリに読み込んで処理する場合は、PHPの `memory_limit`(デフォルト128M程度)が不足する可能性があります。その場合は `phpEnv` 等ではなくカスタムイメージ、または将来的な設定拡張で対応してください。
### 永続化ストレージ
| パラメータ | 説明 | デフォルト |
|-----------|------|-----------|
| `persistence.enabled` | PVC有効化 | `true` |
| `persistence.size` | ストレージサイズ | `1Gi` |
| `persistence.accessMode` | アクセスモード | `ReadWriteOnce` |
> **📁 PVCマウント構成(php-fpmコンテナ)**
> php-fpm コンテナには PVC の**ルート**が `/var/www` にマウントされます。
>
> - `/var/www/html` — **公開フォルダ**nginxが配信するWebルート)
> - `/var/www/<任意のフォルダ>` — **非公開の格納先**(PHPからは読み書きできるが、Web経由では公開されない)
>
> nginx コンテナは `html` サブパスのみをマウントするため、`html/` 以外のディレクトリはWebサーバーのファイルシステムに存在せず、設定ミスでも公開されることはありません。設定ファイル・秘密鍵・アップロード受け皿・ログなど、公開したくないファイルの置き場として利用できます。
### Composer設定
| パラメータ | 説明 | デフォルト |
|-----------|------|-----------|
| `composer.enabled` | Composer有効化 | `false` |
| `composer.workingDir` | Composer導入先ディレクトリ(`{workingDir}/vendor/autoload.php` | `"/composer"` |
| `composer.packages` | インストールパッケージ | `[]` |
| `composer.useComposerJson` | composer.json使用 | `false` |
| `composer.composerJson` | composer.json内容 | `""` |
| `composer.installOptions` | installオプション | `"--no-dev --optimize-autoloader"` |
| `composer.additionalPhpExtensions` | 追加PHP拡張 | `[]` |
| `composer.additionalApkPackages` | 追加APKパッケージ | `[]` |
### Python設定(オプション)
PHPからPythonスクリプトを呼び出す用途(データ処理・機械学習ライブラリの利用など)向けに、Python仮想環境(venv)を導入できます。
| パラメータ | 説明 | デフォルト |
|-----------|------|-----------|
| `python.enabled` | Python有効化 | `false` |
| `python.venvDir` | venv導入先ディレクトリ(`{venvDir}/bin/python3` | `"/venv"` |
| `python.packages` | pipでインストールするパッケージ | `[]` |
| `python.useRequirementsTxt` | requirements.txt使用 | `false` |
| `python.requirementsTxt` | requirements.txtの内容 | `"requests>=2.31.0"` |
| `python.installOptions` | pip installオプション | `"--no-cache-dir"` |
| `python.additionalApkPackages` | 追加APKパッケージ(ネイティブ拡張のビルド用) | `[]` |
> **📌 Python導入先について**
> Composerと同様、デフォルトの `/venv` は**Webルート外かつPVCにマウントされない使い捨て領域**です。Pod再起動のたびにクリーンな仮想環境へ再構築されます。PVCに永続化したい場合は `python.venvDir` に `/var/www` 配下(例: `/var/www/venv`)を指定してください。
>
> PHPコードからは `exec()` 等で呼び出します:
> ```php
> exec('/venv/bin/python3 /var/www/scripts/process.py 2>&1', $output, $exitCode);
> ```
>
> **⚠️ 注意**: `numpy` や `pillow` など、Alpine(musl)向けの事前ビルド済みwheelが無いパッケージは、Pod起動のたびにソースからビルドされ、Raspberry Pi等のARM環境では起動に数分〜十数分かかる場合があります。ビルドに必要なパッケージ(`gcc`, `musl-dev`, `python3-dev` 等)は `python.additionalApkPackages` に指定してください。永続化(`venvDir`をPVC配下に)すれば再起動のたびの再ビルドを回避できますが、使い捨てによるクリーン環境維持のメリットとのトレードオフになります。
### 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` |
### PHP 汎用環境変数(phpEnv
| パラメータ | 説明 | デフォルト |
|-----------|------|-----------|
| `phpEnv` | PHP-FPM コンテナに渡す任意の環境変数(キーと値のマップ) | `{}` |
PHP 側では `$_ENV['KEY']` または `getenv('KEY')` で取得できます。
### SMTP設定
| パラメータ | 説明 | デフォルト |
|-----------|------|-----------|
| `smtp.enabled` | SMTP機能有効化 | `false` |
| `smtp.host` | SMTPサーバーホスト名 | `smtp.example.com` |
| `smtp.protocol` | プロトコル(auto/starttls/tls | `auto` |
| `smtp.port` | ポート番号 | `587` |
| `smtp.auth.enabled` | 認証有効化 | `true` |
| `smtp.auth.username` | SMTPユーザー名 | `smtp-user@example.com` |
| `smtp.auth.password` | SMTPパスワード | `""` (Secretで指定) |
| `smtp.from` | 送信元メールアドレス(固定) | `noreply@example.com` |
| `smtp.tls.verify` | TLS証明書検証 | `true` |
| `smtp.tls.allowSelfSigned` | 自己署名証明書を許可 | `false` |
### Ingress設定
| パラメータ | 説明 | デフォルト |
|-----------|------|-----------|
| `ingress.enabled` | Ingress有効化 | `false` |
| `ingress.className` | IngressClass名 | `""` |
| `ingress.annotations` | アノテーション | `{}` |
| `ingress.hosts` | ホスト設定 | `[{host: "example.tld"}]` |
| `ingress.tls` | TLS設定 | `[]` |
> **📌 Ingressのアップロードサイズ上限**
> `ingress.enabled: true` の場合、`nginx.ingress.kubernetes.io/proxy-body-size` アノテーションが `uploadMaxSize` の値で**自動的に**付与されます(明示的に `ingress.annotations` へ指定した場合はそちらが優先されます)。Ingressコントローラーがnginx以外の場合は、`ingress.annotations` にそのコントローラー向けの上限設定を明示的に指定してください。
### 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` | 追加の信頼プロキシ | `[]` |
> **📌 sitemap.xml のContent-Type**
> `/sitemap.xml`(静的ファイルとして配置した場合)は、常に `Content-Type: application/xml; charset=utf-8` で配信されます。標準の `mime.types` では `.xml` が `text/xml` 扱いでcharsetが付かず、ブラウザやGoogle Search Consoleなどのツールが正しく解釈できない場合があるための組み込み対応です(設定不要、常時有効)。
> なお、PHPで動的に生成する場合はこの設定は適用されません(PHP側で `header('Content-Type: application/xml; charset=utf-8');` を指定してください)。
## 使用例
### 例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 cafepieters/phpfpm -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
```
> **📌 Composerの導入先について**
> Composerパッケージはデフォルトで**Webルート外**の `/composer` に導入されます(`composer.workingDir` で変更可能)。
> `vendor/` や `composer.json` がWeb経由で公開されないため、情報漏洩などのセキュリティリスクを回避できます。
>
> `/composer` は**PVCにマウントされない使い捨て領域**です。Pod再起動のたびにクリーンな環境へ再構築されるため、万一不正アクセスでマルウェアを書き込まれても再起動で消え、常にクリーンなComposer環境を維持できます(PVCに永続化したい場合は `/var/www/composer` など `/var/www` 配下を指定)。
>
> PHPコードからは以下のように読み込みます:
> ```php
> require_once '/composer/vendor/autoload.php';
> ```
>
> 旧バージョン(Webルート直下 `/var/www/html` に導入)と同じ動作に戻す場合は `composer.workingDir: "/var/www/html"` を指定してください。
>
> **旧バージョンからのアップグレード**: 旧Webルートに `composer.json` / `composer.lock` / `vendor/` が残っている場合、Pod起動時に自動的に `workingDir` へ移行されます(v8.5.6-b以降)。
### 例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
<?php
require_once '/composer/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設定
```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: ベアメタル環境でのリアルIP取得
ベアメタルKubernetesやLoadBalancer経由でのアクセスで、PHPからクライアントの実IPアドレスを取得する設定です。
```yaml
# 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
<?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拡張)
```yaml
# values.yaml
composer:
enabled: true
packages:
- "intervention/image:^2.0"
additionalPhpExtensions:
- "gd"
- "exif"
# 注:GDが指定されている場合、依存パッケージ (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
```
**特記事項**: GD拡張を `additionalPhpExtensions` に指定した場合、以下の依存パッケージが自動的にインストールされます:
- `libpng-dev` - PNG画像処理
- `libjpeg-turbo-dev` - JPEG画像処理
- `freetype-dev` - フォント処理
`additionalApkPackages` で明示的に指定する必要はありません。
### 例9: 本番環境構成(フル機能)
```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リポジトリからデプロイ
helm install production-api cafepieters/phpfpm \
-f production-values.yaml \
--set externalDatabase.password=$(kubectl get secret db-password -o jsonpath='{.data.password}' | base64 -d)
```
### 例10: APIキーなどの任意環境変数を PHP に渡す(phpEnv)
`phpEnv` を使うと、DB 接続情報と同様に任意のキーと値を PHP-FPM コンテナの環境変数として渡せます。
```yaml
# values.yaml
phpEnv:
API_KEY: "your-api-key"
STRIPE_SECRET: "sk_live_xxxxxxxxxxxxxxxx"
REDIS_URL: "redis://localhost:6379"
EXTERNAL_SERVICE_URL: "https://api.example.com"
```
**PHPでの使用例**:
```php
<?php
// $_ENV または getenv() で取得
$apiKey = getenv('API_KEY');
$stripe = $_ENV['STRIPE_SECRET'];
$redisUrl = getenv('REDIS_URL');
echo "API Key: " . $apiKey;
```
**確認コマンド**:
```bash
# 設定された環境変数を確認
kubectl exec -it <pod-name> -c php-fpm -- env | grep -E "API_|STRIPE_|REDIS_"
```
**注意事項**:
- 機密性の高い値(APIキー、シークレット等)は `--set phpEnv.KEY=value` でデプロイ時に注入するか、Kubernetes の Secret を別途作成して参照することを推奨します。
- `phpEnv` の値はすべてプレーンテキストとして環境変数に設定されます(externalDatabase の password のみ Secret 経由)。
### 例11: SMTP設定によるメール送信
PHPアプリケーションからSMTP経由でメール送信を行う設定です。
```yaml
# values.yaml
smtp:
enabled: true
# Gmail の場合
host: "smtp.gmail.com"
protocol: "starttls" # または "tls" (port 465)
port: 587
# Office365の場合は以下のようにコメント解除
# host: "smtp.office365.com"
# port: 587
# protocol: "starttls"
auth:
enabled: true
username: "your-email@gmail.com"
# password は以下の方法で指定:
# helm install ... --set smtp.auth.password='your-password'
password: ""
# 送信元アドレス(PHPで上書き可能)
from: "noreply@your-domain.com"
tls:
verify: true
allowSelfSigned: false
persistence:
enabled: true
```
**PHPでの使用例**:
```php
<?php
// 設定を初期化
require_once '/etc/smtp-config/php-smtp-config.php';
SmtpConfig::init();
// デフォルトの送信元で送信
$to = 'user@example.com';
$subject = 'テストメール';
$body = 'このメールはSMTP経由で送信されています。';
if (mail($to, $subject, $body)) {
echo 'メール送信成功';
} else {
echo 'メール送信失敗';
}
// 異なる送信元で上書き指定
$headers = [
'From: custom@your-domain.com',
'Return-Path: custom@your-domain.com',
];
SmtpConfig::mail($to, $subject, $body, $headers, 'custom@your-domain.com');
```
### 例12: Python連携(requirements.txtを使用)
PHPからPythonスクリプトを呼び出してデータ処理を行う設定です。
```yaml
# values.yaml
python:
enabled: true
useRequirementsTxt: true
requirementsTxt: |
requests>=2.31.0
pandas>=2.0.0
installOptions: "--no-cache-dir"
```
**PHPでの使用例**:
```php
<?php
$script = escapeshellarg('/var/www/scripts/process.py');
exec("/venv/bin/python3 {$script} 2>&1", $output, $exitCode);
if ($exitCode === 0) {
echo implode("\n", $output);
} else {
error_log('Python script failed: ' . implode("\n", $output));
}
```
`/var/www/scripts/` のようなPVC上の非公開フォルダにPythonスクリプトを配置すれば、Web経由で公開されずに済みます(詳細はPVCマウント構成の項を参照)。
**デプロイ手順**:
```bash
# 1. Secretにパスワードを設定して展開
helm install my-app cafepieters/phpfpm \
-f values.yaml \
--set smtp.auth.password='your-secure-password'
# または、既存のSecretから取得
helm install my-app cafepieters/phpfpm \
-f values.yaml \
--set smtp.auth.password=$(kubectl get secret email-password -o jsonpath='{.data.password}' | base64 -d)
```
**設定詳細**:
- **protocol**:
- `auto`: 自動判定(推奨)
- `starttls`: SMTP + STARTTLS(ポート587
- `tls`: SSL/TLS(ポート465
- **from**: 固定の送信元アドレス
- PHPコードで `$fromAddress` パラメータを指定することで上書き可能
- `mail($to, $subject, $body, $headers, '-f custom@example.com')` で指定
- **認証**: PLAIN認証に対応(ほとんどのSMTPサーバーで利用可能)
**よくある設定**:
| プロバイダ | ホスト | ポート | プロトコル |
|-----------|-------|--------|----------|
| Gmail | smtp.gmail.com | 587 | starttls |
| Office365 | smtp.office365.com | 587 | starttls |
| Sendgrid | smtp.sendgrid.net | 587 | starttls |
| Amazon SES | email-smtp.region.amazonaws.com | 587 | starttls |
## アップグレード
```bash
# リポジトリを更新
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
```
## アンインストール
```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 <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
```
### ログ確認
```bash
# 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
```
## 高度な設定
### カスタムイメージの使用
```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: Helmリポジトリを追加するには?**
A: 以下のコマンドでリポジトリを追加できます。
```bash
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`を変更してください。
```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 <pod-name>:/var/www/html/ -c php-fpm
```
## 関連ドキュメント
- [Composer使用ガイド](./COMPOSER_GUIDE.md)
- [マイグレーションガイド](./MIGRATION_GUIDE.md)
- [Selenium別チャート化設計](./SELENIUM_SEPARATION_DESIGN.md)
## ライセンス
このHelmチャートはMITライセンスで公開されています。
## サポート
- Helmリポジトリ: https://git.cafepieters.com/api/packages/helmchart/helm
- 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統合
- 外部データベース対応