diff --git a/CHANGELOG-8.5.10-b.md b/CHANGELOG-8.5.10-b.md index d0eac16..3965f7e 100644 --- a/CHANGELOG-8.5.10-b.md +++ b/CHANGELOG-8.5.10-b.md @@ -1,5 +1,10 @@ # Changelog - Version 8.5.10-b +> ⚠️ **v8.5.10-b は単体では既存リリースの `helm upgrade` が失敗する不具合を含む** +> (`Deployment.spec.selector: ... field is immutable`)。設計・原因の記録として +> 本ファイルは残すが、**実際の適用は v8.5.10-c 以降を使うこと**。修正内容は +> `CHANGELOG-8.5.10-c.md` を参照。 + ## 不具合修正・アーキテクチャ変更 ### Selenium を独立した Deployment/Service に分離(サービス完全停止の防止) diff --git a/CHANGELOG-8.5.10-c.md b/CHANGELOG-8.5.10-c.md new file mode 100644 index 0000000..6c0672b --- /dev/null +++ b/CHANGELOG-8.5.10-c.md @@ -0,0 +1,60 @@ +# Changelog - Version 8.5.10-c + +## 不具合修正 + +### v8.5.10-b の Selenium分離が既存リリースのアップグレードを壊す問題を修正 + +v8.5.10-b で Selenium を独立 Deployment/Service に分離した際、既存の nginx/php-fpm +Deployment の `spec.selector.matchLabels` に `app.kubernetes.io/component: web` を +追加した。しかし **`Deployment.spec.selector` は作成後 immutable** であり、 +既存リリースを `helm upgrade` すると次のエラーで失敗する。 + +``` +cannot patch "-phpfpm" with kind Deployment: Deployment.apps "-phpfpm" +is invalid: spec.selector: Invalid value: ...: field is immutable. +``` + +**対応** + +- 既存の nginx/php-fpm Deployment の `spec.selector.matchLabels` は + 元の内容(`app.kubernetes.io/name` + `app.kubernetes.io/instance` のみ)に戻し、 + 以後も変更しない。 +- Selenium 側は `app.kubernetes.io/component` ラベルではなく、 + **`app.kubernetes.io/name` 自体を `-selenium` という別名にする**方式に変更した + (新ヘルパー `phpfpm.selenium.name` / `phpfpm.selenium.selectorLabels`。 + `templates/_helpers.tpl`)。component ラベルを足すだけの設計だと、Selenium の Pod も + nginx/php-fpm 側 Deployment の selector(name+instance)に一致してしまい、 + 2つの Deployment(ReプリカSet)が同じ Pod 集合を取り合う selector 重複を起こすため、 + name 自体を variant にして構造的に重複を防止する。 +- `templates/deployment-selenium.yaml` / `templates/service-selenium.yaml` の + selector・pod template labels をこの新ヘルパーに合わせて修正。 + `app.kubernetes.io/component: selenium` は情報用のラベルとして pod template には + 引き続き付与する(selector には使わない。README の `kubectl logs -l + app.kubernetes.io/component=selenium` 等の運用コマンドはそのまま使える)。 +- メインの Service(`-phpfpm`)の selector に残した + `app.kubernetes.io/component: web` は Service の selector なので immutable 制約は + 受けず、そのまま維持している(Selenium 側が別名になったことで実質不要になったが、 + 害はないため多層防御として残す)。 + +**v8.5.10-b をまだ適用していない場合**: 8.5.10-b は上記のバグを含むため、 +直接 **8.5.10-c 以降**を適用すること。 + +**v8.5.10-b の適用に失敗した場合**(今回のエラーが出た場合): リリースは +アップグレードに失敗した時点のリビジョンのままのはずなので、Chart version を +`8.5.10-c` に変更して再度アップグレードすればよい(追加の手動復旧は不要)。 + +**対象ファイル**: `templates/_helpers.tpl`, `templates/deployment.yaml`, +`templates/deployment-selenium.yaml`, `templates/service-selenium.yaml`, `Chart.yaml`, +`CHANGELOG-8.5.10-c.md` + +## アップグレード手順 + +```bash +helm repo update +helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.10-c -f values.yaml +``` + +--- + +**リリース日**: 2026-09-26 +**担当**: プロサーバーエンジニア(Claude) diff --git a/CLAUDE.md b/CLAUDE.md index 556e348..951f6c3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -27,6 +27,12 @@ Websites 組織の各サイト(e-learn.jp / fcdomain.com / hotels / tskholding ## チャート改修履歴 +### v8.5.10-bのDeployment.spec.selector変更が既存リリースのアップグレードを壊す不具合を修正(2026-09-26, v8.5.10-c) + +v8.5.10-bでnginx/php-fpm Deploymentのspec.selector.matchLabelsに`app.kubernetes.io/component: web`を追加したが、Deployment.spec.selectorは作成後immutableのため既存リリースの`helm upgrade`が「field is immutable」で失敗する不具合を確認・修正した。既存Deploymentのselectorは元の内容(name+instanceのみ)に戻し、Selenium側はcomponentラベルではなく`app.kubernetes.io/name`自体を`-selenium`という別名にする方式(新ヘルパー`phpfpm.selenium.name`/`phpfpm.selenium.selectorLabels`)に変更した。componentラベルだけを足す設計だと、SeleniumのPodもnginx/php-fpm側Deploymentのselector(name+instance)に一致してしまい2つのDeployment(ReplicaSet)が同じPod集合を取り合う選択重複を起こすため、name自体をvariantにして構造的に防止する。v8.5.10-bは未適用ならスキップしてv8.5.10-c以降を直接使うこと。 + +**対象ファイル**: `templates/_helpers.tpl`, `templates/deployment.yaml`, `templates/deployment-selenium.yaml`, `templates/service-selenium.yaml`, `Chart.yaml`, `CHANGELOG-8.5.10-c.md` + ### Selenium を独立Deployment/Serviceに分離 + resources死んだ設定を修正(2026-09-26, v8.5.10-b) `selenium.enabled: true` 構成で断続的な php-fpm CrashLoopBackOff とサイト完全停止が続いた件の調査で、2つの設計上の欠陥を確認した。(1) `resources` values キーがテンプレート側で全く参照されておらず、nginx/php-fpm/selenium いずれのコンテナにも requests/limits が反映されない死んだ設定だった(全コンテナが QoS Class: BestEffort → ノードのメモリ逼迫時に OOM Kill の対象になりやすい)。(2) nginx・php-fpm・Selenium が同一 Pod のコンテナで、Kubernetes の Pod Ready 判定は全コンテナの AND のため、Selenium だけが不調(起動失敗・OOM 等)でも Pod 全体が Service の Endpoints から外れ、Selenium を使わない静的ページ配信まで巻き込まれてサービス全体が停止していた。対応: Selenium を独立した Deployment(`-phpfpm-selenium`)/Service に分離(`app.kubernetes.io/component: web`/`selenium` ラベルでセレクタを分離、php-fpm の `SELENIUM_URL` は新Serviceを指すよう自動注入)。`resources` を `resources.nginx`/`resources.phpfpm`/`selenium.resources` に構造化し実際にコンテナへ反映されるよう修正。既存 `selenium.enabled: true` 利用者は `selenium.mountHtml`(PVC html サブパスへの依存があれば true + `persistence.accessMode: ReadWriteMany`)を確認する必要がある。OOM Kill が実際のクラッシュトリガーだったかは本リリース時点では未確認(要検証)だが、上記2点はコード上確認済みの確定した欠陥のため先行修正した。 diff --git a/Chart.yaml b/Chart.yaml index b2344eb..83b3d13 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -2,6 +2,6 @@ apiVersion: v2 name: phpfpm description: Nginx + PHP-FPM Helm Chart with external DB and optional Selenium support type: application -version: 8.5.10-b +version: 8.5.10-c appVersion: "8.5.10" icon: https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/PHP-logo.svg/330px-PHP-logo.svg.png diff --git a/README.md b/README.md index 1516f64..fb11598 100644 --- a/README.md +++ b/README.md @@ -957,13 +957,15 @@ kubectl delete pod -n -l app.kubernetes.io/name=phpfpm これに加えて、`resources` values キーが v8.5.10-a 以前はテンプレート側で参照されておらず、どのコンテナにも requests/limits が反映されない「死んだ設定」だった。全コンテナが `QoS Class: BestEffort` になり、ノードのメモリ逼迫時に OOM Killer の対象になりやすい状態だった(Chromium を含む Selenium は特にメモリを消費するため、この影響を受けやすい)。 -**対策**: **v8.5.10-b 以降にアップグレードする**。 +**対策**: **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(`-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-b -f values.yaml +helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.10-c -f values.yaml ``` アップグレード後に確認すべき点は `CHANGELOG-8.5.10-b.md` の「互換性(重要・要対応)」を参照(`selenium.mountHtml` / `phpEnv.SELENIUM_URL` の扱い)。 @@ -1168,7 +1170,7 @@ kubectl cp ./my-app :/var/www/html/ -c php-fpm - [Composer使用ガイド](./COMPOSER_GUIDE.md) - [マイグレーションガイド](./MIGRATION_GUIDE.md) -- Selenium別Deployment化の設計・経緯は本READMEの「Selenium設定」セクションと `CHANGELOG-8.5.10-b.md` を参照(旧: 本リンク先の設計ドキュメントは作成されず実装が先行したため削除) +- Selenium別Deployment化の設計・経緯は本READMEの「Selenium設定」セクションと `CHANGELOG-8.5.10-b.md`(設計)・`CHANGELOG-8.5.10-c.md`(既存リリースのアップグレードを壊す不具合の修正)を参照(旧: 本リンク先の設計ドキュメントは作成されず実装が先行したため削除) ## ライセンス diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index d5a3d59..d6cb932 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -19,3 +19,25 @@ app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/name: {{ include "phpfpm.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} + +{{/* +Selenium 用の名前・セレクタラベル(v8.5.10-b)。 + +nginx/php-fpm の既存 Deployment は spec.selector が作成後 immutable なため、 +そちらの selector には手を加えられない("field is immutable" でアップグレードが +失敗する)。そのため Selenium 側は app.kubernetes.io/name 自体を variant +("phpfpm-selenium")にして、nginx/php-fpm の Deployment の selector +(name=phpfpm, instance=)とラベルの組が完全に一致しないようにする。 +component ラベルだけを足す設計だと、Selenium の Pod も name=phpfpm/instance= +を持つため nginx/php-fpm 側 Deployment の selector にも一致してしまい、 +2つの Deployment(ReplicaSet)が同じ Pod 集合を取り合う selector 重複を起こす。 +name を variant にすることで、この重複を構造的に防止する。 +*/}} +{{- define "phpfpm.selenium.name" -}} +{{- printf "%s-selenium" (include "phpfpm.name" .) | trunc 63 | trimSuffix "-" -}} +{{- end }} + +{{- define "phpfpm.selenium.selectorLabels" -}} +app.kubernetes.io/name: {{ include "phpfpm.selenium.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/templates/deployment-selenium.yaml b/templates/deployment-selenium.yaml index 9534a01..994620e 100644 --- a/templates/deployment-selenium.yaml +++ b/templates/deployment-selenium.yaml @@ -23,12 +23,11 @@ spec: replicas: {{ .Values.selenium.replicaCount | default 1 }} selector: matchLabels: - {{- include "phpfpm.selectorLabels" . | nindent 6 }} - app.kubernetes.io/component: selenium + {{- include "phpfpm.selenium.selectorLabels" . | nindent 6 }} template: metadata: labels: - {{- include "phpfpm.selectorLabels" . | nindent 8 }} + {{- include "phpfpm.selenium.selectorLabels" . | nindent 8 }} app.kubernetes.io/component: selenium spec: containers: diff --git a/templates/deployment.yaml b/templates/deployment.yaml index c278750..eda4cb3 100644 --- a/templates/deployment.yaml +++ b/templates/deployment.yaml @@ -7,9 +7,13 @@ metadata: spec: replicas: {{ .Values.replicaCount }} selector: + # 注意: Deployment.spec.selector は作成後 immutable。既存リリースの + # アップグレードを壊さないため、ここに app.kubernetes.io/component は + # 追加しない(component ラベルは下の pod template と Service の + # selector のみに付与する。template.metadata.labels は matchLabels の + # superset であればよいため、追加ラベルを持たせても問題ない)。 matchLabels: {{- include "phpfpm.selectorLabels" . | nindent 6 }} - app.kubernetes.io/component: web template: metadata: labels: diff --git a/templates/service-selenium.yaml b/templates/service-selenium.yaml index 4e49c3a..8dde344 100644 --- a/templates/service-selenium.yaml +++ b/templates/service-selenium.yaml @@ -14,6 +14,5 @@ spec: protocol: TCP name: selenium selector: - {{- include "phpfpm.selectorLabels" . | nindent 4 }} - app.kubernetes.io/component: selenium + {{- include "phpfpm.selenium.selectorLabels" . | nindent 4 }} {{- end }}