Helm Chart Release / release-chart (push) Successful in 5s
cron.jobs(配列)にジョブを定義すると、php-fpmと同じPHPイメージを使う Kubernetes CronJobをジョブごとに生成する。 - templates/cronjob.yaml(新規): PVCルートを/var/wwwにマウントし、 externalDatabase/phpEnv/extraEnv/extraEnvFrom/SELENIUM_URLをphp-fpm コンテナと同じ内容で注入。smtp.enabled時はmsmtpも自動導入。 - templates/_helpers.tpl: phpfpm.cron.name/selectorLabelsを追加。 Selenium分離と同じ理由で、生成PodのラベルをDeploymentのselectorと 衝突しないバリアント名(<chart>-cron)にする。 - values.yaml: cronセクションを追加(既定は空配列で無効)。 - README.md: パラメータ表と使用例、Composer/Pythonとの併用時の注意点 (デフォルトの使い捨て領域はCronJobから見えないため、永続化パスへの 変更が必要)を追加。 templates/deployment.yamlは変更していない(既存Deploymentへの影響なし)。 手動リリース 8.5.10-e。
1237 lines
44 KiB
Markdown
1237 lines
44 KiB
Markdown
# 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_URL(自動注入)
|
||
┌─────────────────────────────┐ ┌──────────────────────────────┐
|
||
│ External Database (Optional)│ │ Selenium Deployment(Optional)│
|
||
│ MySQL/MariaDB │ │ 独立Pod・独立Service :4444 │
|
||
└─────────────────────────────┘ └──────────────────────────────┘
|
||
```
|
||
|
||
> **Selenium は独立した Deployment/Service(v8.5.10-b以降)**。以前は上の Pod 内の
|
||
> サイドカーコンテナだったが、Selenium 単体の不調(起動失敗・OOM等)で Pod 全体が
|
||
> Service の Endpoints から外れ、サイト全体が停止する問題があったため分離した
|
||
> (下記トラブルシューティング参照)。
|
||
|
||
## 主要な設定パラメータ
|
||
|
||
### 基本設定
|
||
|
||
| パラメータ | 説明 | デフォルト |
|
||
|-----------|------|-----------|
|
||
| `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つの値で揃える設計です。
|
||
> - nginx(Podコンテナ内)の `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設定
|
||
|
||
v8.5.10-b以降、Seleniumは独立したDeployment/Service(`<release>-phpfpm-selenium`)として起動する(nginx/php-fpmと同一Podのサイドカーではない)。
|
||
|
||
| パラメータ | 説明 | デフォルト |
|
||
|-----------|------|-----------|
|
||
| `selenium.enabled` | Selenium有効化 | `false` |
|
||
| `selenium.replicaCount` | Selenium Deploymentのレプリカ数 | `1` |
|
||
| `selenium.resources` | SeleniumコンテナのCPU/メモリ requests・limits | `{}` |
|
||
| `selenium.mountHtml` | PVCの`html`サブパスをSeleniumにもマウントするか(別Podからの同時マウントになるため`true`にする場合は`persistence.accessMode: ReadWriteMany`が必要) | `false` |
|
||
| `image.selenium.tag` | Seleniumバージョン | `144.0-chromedriver-144.0` |
|
||
|
||
`selenium.enabled: true`のとき、php-fpmコンテナの`SELENIUM_URL`環境変数は自動的にこのServiceを指す値(`http://<release>-phpfpm-selenium:4444/wd/hub`)に設定される。`phpEnv.SELENIUM_URL`を独自に指定していても、この自動注入された値が優先される。
|
||
|
||
### Cron(定期実行)設定
|
||
|
||
`cron.jobs`に1件以上定義すると、php-fpmと同じPHPイメージ(`image.php`)を使ってスケジュール実行するKubernetes CronJobが、ジョブごとに1つずつ作成される。既定は空配列で、何も作成されない。
|
||
|
||
| パラメータ | 説明 | デフォルト |
|
||
|-----------|------|-----------|
|
||
| `cron.jobs` | CronJob定義の配列 | `[]` |
|
||
| `cron.jobs[].name` | ジョブ名(英数字とハイフン、CronJob名の一部に使用) | 必須 |
|
||
| `cron.jobs[].schedule` | 標準cron形式のスケジュール | 必須 |
|
||
| `cron.jobs[].command` | 実行するシェルコマンド(文字列) | 必須 |
|
||
| `cron.jobs[].timeZone` | タイムゾーン(Kubernetes 1.27+) | 省略時UTC |
|
||
| `cron.jobs[].concurrencyPolicy` | `Allow`/`Forbid`/`Replace` | `Forbid` |
|
||
| `cron.jobs[].restartPolicy` | `OnFailure`/`Never` | `OnFailure` |
|
||
| `cron.jobs[].successfulJobsHistoryLimit` | 成功ジョブの保持数 | `3` |
|
||
| `cron.jobs[].failedJobsHistoryLimit` | 失敗ジョブの保持数 | `1` |
|
||
| `cron.jobs[].activeDeadlineSeconds` | 実行タイムアウト(秒) | 省略可 |
|
||
| `cron.jobs[].suspend` | `true`でこのジョブだけ一時停止 | `false` |
|
||
| `cron.jobs[].resources` | CPU/メモリ requests・limits | `resources.phpfpm`を流用 |
|
||
|
||
```yaml
|
||
# values.yaml
|
||
cron:
|
||
jobs:
|
||
- name: daily-report
|
||
schedule: "0 18 * * *"
|
||
timeZone: "Asia/Tokyo"
|
||
command: "php /var/www/html/cron/daily-report.php"
|
||
```
|
||
|
||
> **📌 CronJobの構成について**
|
||
> - PVCルートを`/var/www`にマウントする(php-fpmコンテナと同じ)。`html/`配下の公開コード、または非公開ディレクトリのスクリプト・出力先どちらも利用できる。
|
||
> - `externalDatabase` / `phpEnv` / `extraEnv` / `extraEnvFrom` / `SELENIUM_URL`(selenium有効時)は、php-fpmコンテナと同じ内容が渡される。
|
||
> - `smtp.enabled: true`の場合、CronJobのPodでも自動的にmsmtpを導入してmsmtprcを配置するため、PHPの`mail()`関数がそのまま使える。
|
||
> - **Composer/Pythonとの併用**: `composer.workingDir`/`python.venvDir`が既定の`/composer`・`/venv`(PVC非マウントの使い捨て領域)のままだと、php-fpmの常駐Pod内にしか存在しないためCronJobからは使えない。CronJobから使いたい場合は`composer.workingDir: "/var/www/composer"`のように`/var/www`配下へ変更し、PVC上に永続化すること。
|
||
> - CronJobの名前は52文字を超えないよう自動的に切り詰められる(Kubernetesの制約)。`cron.jobs[].name`は短く分かりやすい名前にすること。
|
||
> - 生成されるPodのラベル(`app.kubernetes.io/name`)は`<chart>-cron`というバリアント名になっており、nginx/php-fpmのDeploymentのselectorとは一致しない(Selenium分離と同じ設計)。
|
||
|
||
### 外部データベース設定
|
||
|
||
| パラメータ | 説明 | デフォルト |
|
||
|-----------|------|-----------|
|
||
| `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 コンテナに渡す任意の環境変数(キーと値のマップ) | `{}` |
|
||
| `extraEnvFrom` | 既存の Secret / ConfigMap をまるごと環境変数として注入(`envFrom` 配列) | `[]` |
|
||
| `extraEnv` | 個別の環境変数を追加(生の `env` エントリ配列。`valueFrom`/`secretKeyRef` 可) | `[]` |
|
||
|
||
PHP 側では `$_ENV['KEY']` または `getenv('KEY')` で取得できます。
|
||
|
||
`extraEnvFrom` は、別リポジトリの **secret-manager** チャートが各ネームスペースへ配布する
|
||
`cred-<名前>` Secret(API キー等)をそのまま読み込む用途を想定しています。認証情報の変更は
|
||
secret-manager 側を更新するだけで全プロジェクトに反映できます。
|
||
|
||
```yaml
|
||
extraEnvFrom:
|
||
- secretRef:
|
||
name: cred-gemini # GEMINI_API_KEY 等が丸ごと環境変数になる
|
||
- secretRef:
|
||
name: cred-openai
|
||
extraEnv:
|
||
- name: ANTHROPIC_API_KEY
|
||
valueFrom:
|
||
secretKeyRef:
|
||
name: cred-claude
|
||
key: ANTHROPIC_API_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.auth.existingSecret` | パスワードを取得する既存 Secret 名(`smtp.auth.password` と自作 Secret の代わり) | `""` |
|
||
| `smtp.auth.existingSecretKey` | 上記 Secret 内のキー名 | `password` |
|
||
| `smtp.existingMsmtprcSecret` | 完成済み `msmtprc` を持つ既存 Secret 名。指定時はチャートの msmtprc 生成を行わず host/port/auth.* は無視(`from` のみ使用) | `""` |
|
||
| `smtp.existingMsmtprcSecretKey` | 上記 Secret 内の `msmtprc` キー名 | `msmtprc` |
|
||
| `smtp.from` | 送信元メールアドレス(固定) | `noreply@example.com` |
|
||
| `smtp.tls.verify` | TLS証明書検証 | `true` |
|
||
| `smtp.tls.allowSelfSigned` | 自己署名証明書を許可 | `false` |
|
||
|
||
#### secret-manager チャートとの連携(メール設定の一元管理)
|
||
|
||
**secret-manager** が `cred-gmail` などに生成する完成済み `msmtprc` をそのまま使う場合:
|
||
|
||
```yaml
|
||
smtp:
|
||
enabled: true
|
||
from: "no-reply@your-domain.com" # PHP の sendmail_from 用に必要
|
||
existingMsmtprcSecret: "cred-gmail" # このSecretの msmtprc キーをそのまま利用
|
||
```
|
||
|
||
サーバ設定はチャート側 values に残し、パスワードだけ一元管理したい場合:
|
||
|
||
```yaml
|
||
smtp:
|
||
enabled: true
|
||
host: "smtp.gmail.com"
|
||
port: 587
|
||
auth:
|
||
enabled: true
|
||
username: "no-reply@your-domain.com"
|
||
existingSecret: "cred-gmail"
|
||
existingSecretKey: "SMTP_PASSWORD"
|
||
```
|
||
|
||
### Ingress設定
|
||
|
||
| パラメータ | 説明 | デフォルト |
|
||
|-----------|------|-----------|
|
||
| `ingress.enabled` | Ingress有効化 | `false` |
|
||
| `ingress.className` | IngressClass名 | `""` |
|
||
| `ingress.annotations` | アノテーション | `{}` |
|
||
| `ingress.hosts` | ホスト設定 | `[{host: "example.tld"}]` |
|
||
| `ingress.tls` | TLS設定(`secretName`省略可) | `[]` |
|
||
|
||
> **📌 Ingressのアップロードサイズ上限**
|
||
> `ingress.enabled: true` の場合、`nginx.ingress.kubernetes.io/proxy-body-size` アノテーションが `uploadMaxSize` の値で**自動的に**付与されます(明示的に `ingress.annotations` へ指定した場合はそちらが優先されます)。Ingressコントローラーがnginx以外の場合は、`ingress.annotations` にそのコントローラー向けの上限設定を明示的に指定してください。
|
||
|
||
> **📌 hostとTLS secretNameの共有**
|
||
> `ingress.hosts[].host` にYAMLアンカー(例: `&appDomain`)を付けておくと、`ingress.tls[].hosts` で `*appDomain` として再利用でき、ドメイン名を1箇所の変更で揃えられます(デフォルトのvalues.yamlも参照)。
|
||
> さらに `ingress.tls[].secretName` は**省略可能**で、省略した場合はそのエントリの最初のhostから自動生成されます(`.`を`-`に置換して`-tls`を付与。例: `example.tld` → `example-tld-tls`)。別の証明書Secret名を使いたい場合のみ `secretName` を明示的に指定してください(指定時はそちらが優先されます)。
|
||
|
||
### 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が自動追加。独立Deployment/Serviceとして起動する
|
||
resources:
|
||
requests:
|
||
memory: "1Gi"
|
||
cpu: "500m"
|
||
limits:
|
||
memory: "3Gi"
|
||
cpu: "2000m"
|
||
|
||
persistence:
|
||
enabled: true
|
||
size: 5Gi
|
||
|
||
resources:
|
||
nginx:
|
||
requests: { memory: "64Mi", cpu: "50m" }
|
||
limits: { memory: "128Mi" }
|
||
phpfpm:
|
||
requests: { memory: "256Mi", cpu: "200m" }
|
||
limits: { memory: "512Mi", cpu: "1000m" }
|
||
```
|
||
|
||
**PHPコード例**:
|
||
```php
|
||
<?php
|
||
require_once '/composer/vendor/autoload.php';
|
||
|
||
use Facebook\WebDriver\Remote\RemoteWebDriver;
|
||
use Facebook\WebDriver\Remote\DesiredCapabilities;
|
||
|
||
// Seleniumに接続(SELENIUM_URLはselenium.enabled:trueのとき自動注入される。
|
||
// 別Deploymentになったため localhost では到達できない点に注意)
|
||
$driver = RemoteWebDriver::create(
|
||
getenv('SELENIUM_URL') ?: 'http://<release>-phpfpm-selenium:4444/wd/hub',
|
||
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"
|
||
```
|
||
|
||
### php-fpm が CrashLoopBackOff/全リクエストが 502(`Address in use` / `unsupported FastCGI protocol version: 60`)
|
||
|
||
**症状**: php-fpm コンテナが `CrashLoopBackOff` になり、nginx ログに `upstream sent unsupported FastCGI protocol version: 60`、php-fpm ログに次が出る。
|
||
|
||
```
|
||
[ERROR] unable to bind listening socket for address '9000': Address in use (98)
|
||
[ERROR] FPM initialization failed
|
||
```
|
||
|
||
**原因**: php-fpm が 9000 を bind できず起動失敗し、nginx が非 FastCGI 応答を受けて 502 になる。v8.5.9-c 以前は php-fpm を setup シェルの子プロセスとして起動していたため、コンテナ再起動時に PID1 のシェルが `SIGTERM` を子へ転送せず、旧 php-fpm が残存して 9000 を握ったまま次回起動が二重 bind で失敗する自己増殖ループに陥ることがあった。
|
||
|
||
**対策**: **v8.5.9-d 以降にアップグレードする**(起動を `exec php-fpm -F` に変更済み。php-fpm が PID1 になりシグナルを直接受けて 9000 を確実解放、`-F` で必ずフォアグラウンド起動)。アップグレード後も残存プロセスを持つ既存 pod が残る場合は作り直す。
|
||
|
||
```bash
|
||
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.9-d -f values.yaml
|
||
kubectl delete pod -n <namespace> -l app.kubernetes.io/name=phpfpm
|
||
```
|
||
|
||
### `selenium.enabled: true` でコンテナが不安定になるとサイト全体が完全停止する
|
||
|
||
**症状**: `selenium.enabled: true` の構成で、いずれかのコンテナ(php-fpm・Selenium 等)が `CrashLoopBackOff` になっている間、Selenium を全く使わない静的ページも含めてサイト全体が閲覧不能(502等)になる。`kubectl get pod` で `2/3` や `1/3` の READY 表示が続く。
|
||
|
||
**原因**: v8.5.10-b より前は Selenium が nginx/php-fpm と同一 Pod のサイドカーコンテナだった。Kubernetes は Pod の Ready 条件を「全コンテナが Ready」の AND で判定するため、readinessProbe を持たないコンテナは Running であれば Ready 扱いになる一方、いずれか1つでも CrashLoopBackOff で Waiting/Terminated を繰り返している間は Pod 全体が Ready=false になる。Service は Ready な Pod にしかトラフィックを流さないため、`replicaCount: 1`(冗長性なし)の構成では **1つのコンテナの不調がサイト全体の完全停止に直結していた**。
|
||
|
||
これに加えて、`resources` values キーが v8.5.10-a 以前はテンプレート側で参照されておらず、どのコンテナにも requests/limits が反映されない「死んだ設定」だった。全コンテナが `QoS Class: BestEffort` になり、ノードのメモリ逼迫時に OOM Killer の対象になりやすい状態だった(Chromium を含む Selenium は特にメモリを消費するため、この影響を受けやすい)。
|
||
|
||
**対策**: **v8.5.10-c 以降にアップグレードする**(v8.5.10-b は既存リリースの
|
||
アップグレードが `spec.selector: ... field is immutable` で失敗する不具合を含むため、
|
||
v8.5.10-b を経由せず直接 v8.5.10-c 以降を使うこと。詳細は `CHANGELOG-8.5.10-c.md`)。
|
||
|
||
1. Selenium が独立した Deployment/Service(`<release>-phpfpm-selenium`)になり、Selenium 単体の不調がメイン Pod(nginx/php-fpm)の Ready 状態に一切影響しなくなった。
|
||
2. `resources.nginx` / `resources.phpfpm` / `selenium.resources` で実際に requests/limits を設定できるようになった。本番運用では設定を強く推奨する(未設定のままだと引き続き BestEffort のままで、OOM Kill のリスクは残る)。
|
||
|
||
```bash
|
||
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.10-c -f values.yaml
|
||
```
|
||
|
||
アップグレード後に確認すべき点は `CHANGELOG-8.5.10-b.md` の「互換性(重要・要対応)」を参照(`selenium.mountHtml` / `phpEnv.SELENIUM_URL` の扱い)。
|
||
|
||
### データベース接続エラー
|
||
|
||
**確認**:
|
||
```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ログ(有効時。v8.5.10-b以降は別Pod・別Deploymentのため -c 指定は不要)
|
||
kubectl logs -l app.kubernetes.io/component=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別Deployment化の設計・経緯は本READMEの「Selenium設定」セクションと `CHANGELOG-8.5.10-b.md`(設計)・`CHANGELOG-8.5.10-c.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統合
|
||
- 外部データベース対応 |