Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0cf3e29b9e | ||
|
|
f8aaa5944d | ||
|
|
5ab3428893 | ||
|
|
328a67213e | ||
|
|
6cd35ce023 | ||
|
|
c7397b3c9d | ||
|
|
9d8fb83bac | ||
|
|
abb5dba4a1 | ||
|
|
86cd705d06 | ||
|
|
6eb1c24732 | ||
|
|
3e1830426c | ||
|
|
c81083fd57 | ||
|
|
6ae463fc49 | ||
|
|
b872dd4bd9 | ||
|
|
6de85b9ad4 | ||
|
|
eb3eef601a | ||
|
|
7c5e9e44c8 | ||
|
|
e9428c6448 | ||
|
|
8f1b050bb2 | ||
|
|
e27f02992f | ||
|
|
1be71b95e4 | ||
|
|
3d384ab72e | ||
|
|
6e600bb308 | ||
|
|
4b2dece19b | ||
|
|
ffb760b913 | ||
|
|
85b7f69ccb | ||
|
|
be1c82e968 | ||
|
|
76a4a7874b | ||
|
|
e294f909c1 | ||
|
|
8ff43615fa | ||
|
|
112fae7059 | ||
|
|
5aa6583f69 | ||
|
|
982cc274d8 | ||
|
|
3fd01dd7e5 | ||
|
|
f48879446c | ||
|
|
84ed9e478e | ||
|
|
c8a745f997 | ||
|
|
ce6fcab5f3 | ||
|
|
d2c3b9671f | ||
|
|
e83fd7b6f6 | ||
|
|
b6f2f83a79 | ||
|
|
c1060efd4d | ||
|
|
06c63037f1 | ||
|
|
8b7a141caa | ||
|
|
adc9ce5934 | ||
|
|
ef238e9c42 | ||
|
|
28eb82a1d6 | ||
|
|
c31ee5ce93 | ||
|
|
e21bc2e1a5 | ||
|
|
3343995e21 | ||
|
|
a3f0245c64 | ||
|
|
6002da51d0 | ||
|
|
02696fc55e | ||
|
|
59a21fca9b | ||
|
|
31106e098f | ||
|
|
fb6ebfe2b0 | ||
|
|
fcd6bdbda5 | ||
|
|
6ab36861ab | ||
|
|
58c02e47a9 | ||
|
|
6c4f7c0bf2 | ||
|
|
3ced61563a |
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
trigger: always_on
|
||||||
|
description: Read the CLAUDE.md hierarchy via GEMINI.md before doing anything in this workspace
|
||||||
|
---
|
||||||
|
|
||||||
|
最初に、このディレクトリの `GEMINI.md` を読み、そこに列挙された CLAUDE.md を上から順にすべて読んで従うこと。
|
||||||
|
Read `GEMINI.md` in this directory first, then read and follow every CLAUDE.md it lists, in order.
|
||||||
@@ -5,6 +5,10 @@ on:
|
|||||||
- cron: '0 2 * * 1'
|
- cron: '0 2 * * 1'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY_URL: https://git.cafepieters.com
|
||||||
|
OWNER: helmchart
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
update-and-release:
|
update-and-release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -48,26 +52,35 @@ jobs:
|
|||||||
echo "Checking PHP versions..."
|
echo "Checking PHP versions..."
|
||||||
CURRENT=$(grep -A3 "php:" values.yaml | grep "tag:" | head -1 | sed 's/.*tag: *"\([^"]*\)".*/\1/' | tr -d ' ')
|
CURRENT=$(grep -A3 "php:" values.yaml | grep "tag:" | head -1 | sed 's/.*tag: *"\([^"]*\)".*/\1/' | tr -d ' ')
|
||||||
echo "Current PHP: $CURRENT"
|
echo "Current PHP: $CURRENT"
|
||||||
|
|
||||||
# Docker Hub API v2を使用してタグを取得
|
# jqの確認とインストール
|
||||||
# パターン: 8.4.12-fpm-alpine3.22 形式
|
if ! command -v jq &> /dev/null; then
|
||||||
LATEST=$(curl -s "https://registry.hub.docker.com/v2/repositories/library/php/tags?page_size=100" | \
|
echo "jq not found, installing..."
|
||||||
|
sudo apt-get update -qq && sudo apt-get install -y -qq jq
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Docker Hub API v2を使用してタグを取得(fpm-alpineでフィルタ)
|
||||||
|
echo "Fetching tags from Docker Hub..."
|
||||||
|
LATEST=$(curl -s "https://registry.hub.docker.com/v2/repositories/library/php/tags?page_size=100&name=fpm-alpine" | \
|
||||||
jq -r '.results[].name' | \
|
jq -r '.results[].name' | \
|
||||||
grep -E '^[0-9]+\.[0-9]+\.[0-9]+-fpm-alpine[0-9]+\.[0-9]+$' | \
|
grep -E '^[0-9]+\.[0-9]+\.[0-9]+-fpm-alpine[0-9]+\.[0-9]{2,3}$' | \
|
||||||
sort -V | tail -1)
|
sort -V | tail -1)
|
||||||
|
|
||||||
|
echo "DEBUG: Matched LATEST=$LATEST"
|
||||||
|
|
||||||
if [ -z "$LATEST" ]; then
|
if [ -z "$LATEST" ]; then
|
||||||
echo "Warning: Could not fetch latest PHP version, using current"
|
echo "Warning: Could not fetch latest PHP version, using current"
|
||||||
LATEST="$CURRENT"
|
LATEST="$CURRENT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# PHPバージョンを抽出 (8.4.12の部分)
|
# PHPバージョンを抽出 (8.5.2の部分)
|
||||||
APP_VERSION=$(echo "$LATEST" | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+')
|
APP_VERSION=$(echo "$LATEST" | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+')
|
||||||
if [ -z "$APP_VERSION" ]; then
|
if [ -z "$APP_VERSION" ]; then
|
||||||
echo "Error: Could not extract PHP version"
|
echo "Warning: Could not extract PHP version from: $LATEST"
|
||||||
exit 1
|
echo "Using current version instead"
|
||||||
|
APP_VERSION=$(echo "$CURRENT" | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Latest PHP: $LATEST"
|
echo "Latest PHP: $LATEST"
|
||||||
echo "PHP version: $APP_VERSION"
|
echo "PHP version: $APP_VERSION"
|
||||||
echo "current=$CURRENT" >> $GITHUB_OUTPUT
|
echo "current=$CURRENT" >> $GITHUB_OUTPUT
|
||||||
@@ -107,17 +120,38 @@ jobs:
|
|||||||
PHP_LATEST="${{ steps.php.outputs.latest }}"
|
PHP_LATEST="${{ steps.php.outputs.latest }}"
|
||||||
SELENIUM_CURRENT="${{ steps.selenium.outputs.current }}"
|
SELENIUM_CURRENT="${{ steps.selenium.outputs.current }}"
|
||||||
SELENIUM_LATEST="${{ steps.selenium.outputs.latest }}"
|
SELENIUM_LATEST="${{ steps.selenium.outputs.latest }}"
|
||||||
|
|
||||||
echo "Nginx: $NGINX_CURRENT vs $NGINX_LATEST"
|
echo "Nginx: $NGINX_CURRENT vs $NGINX_LATEST"
|
||||||
echo "PHP: $PHP_CURRENT vs $PHP_LATEST"
|
echo "PHP: $PHP_CURRENT vs $PHP_LATEST"
|
||||||
echo "Selenium: $SELENIUM_CURRENT vs $SELENIUM_LATEST"
|
echo "Selenium: $SELENIUM_CURRENT vs $SELENIUM_LATEST"
|
||||||
|
|
||||||
if [ "$NGINX_CURRENT" != "$NGINX_LATEST" ] || [ "$PHP_CURRENT" != "$PHP_LATEST" ] || [ "$SELENIUM_CURRENT" != "$SELENIUM_LATEST" ]; then
|
# 更新が必要かチェック
|
||||||
echo "update_needed=true" >> $GITHUB_OUTPUT
|
UPDATE_NEEDED=false
|
||||||
|
PHP_UPDATED=false
|
||||||
|
|
||||||
|
if [ "$PHP_CURRENT" != "$PHP_LATEST" ]; then
|
||||||
|
UPDATE_NEEDED=true
|
||||||
|
PHP_UPDATED=true
|
||||||
|
echo "PHP update detected"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$NGINX_CURRENT" != "$NGINX_LATEST" ]; then
|
||||||
|
UPDATE_NEEDED=true
|
||||||
|
echo "Nginx update detected"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$SELENIUM_CURRENT" != "$SELENIUM_LATEST" ]; then
|
||||||
|
UPDATE_NEEDED=true
|
||||||
|
echo "Selenium update detected"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "update_needed=$UPDATE_NEEDED" >> $GITHUB_OUTPUT
|
||||||
|
echo "php_updated=$PHP_UPDATED" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
if [ "$UPDATE_NEEDED" = "true" ]; then
|
||||||
echo "Update is needed"
|
echo "Update is needed"
|
||||||
else
|
else
|
||||||
echo "update_needed=false" >> $GITHUB_OUTPUT
|
echo "Already up to date - no action required"
|
||||||
echo "Already up to date"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Update values.yaml
|
- name: Update values.yaml
|
||||||
@@ -161,7 +195,7 @@ jobs:
|
|||||||
git diff values.yaml
|
git diff values.yaml
|
||||||
|
|
||||||
- name: Update Chart.yaml version
|
- name: Update Chart.yaml version
|
||||||
if: steps.check_update.outputs.update_needed == 'true'
|
if: steps.check_update.outputs.php_updated == 'true'
|
||||||
run: |
|
run: |
|
||||||
set -e
|
set -e
|
||||||
APP_VERSION="${{ steps.php.outputs.app_version }}"
|
APP_VERSION="${{ steps.php.outputs.app_version }}"
|
||||||
@@ -175,26 +209,43 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
git config user.name "GitHub Actions Bot"
|
git config user.name "GitHub Actions Bot"
|
||||||
git config user.email "actions@github.com"
|
git config user.email "actions@github.com"
|
||||||
git add values.yaml Chart.yaml
|
|
||||||
git commit -m "chore: update to PHP ${{ steps.php.outputs.app_version }}, nginx ${{ steps.nginx.outputs.latest }}, selenium ${{ steps.selenium.outputs.latest }}"
|
if [ "${{ steps.check_update.outputs.php_updated }}" = "true" ]; then
|
||||||
|
# PHP更新時はChart.yamlも含める
|
||||||
|
git add values.yaml Chart.yaml
|
||||||
|
git commit -m "chore: update to PHP ${{ steps.php.outputs.app_version }}, nginx ${{ steps.nginx.outputs.latest }}, selenium ${{ steps.selenium.outputs.latest }}"
|
||||||
|
else
|
||||||
|
# Nginx/Seleniumのみの更新時はvalues.yamlのみ
|
||||||
|
git add values.yaml
|
||||||
|
git commit -m "chore: update nginx to ${{ steps.nginx.outputs.latest }}, selenium to ${{ steps.selenium.outputs.latest }} (no release)"
|
||||||
|
fi
|
||||||
|
|
||||||
git push origin main
|
git push origin main
|
||||||
|
|
||||||
- name: Package Helm Chart
|
- name: Package Helm Chart
|
||||||
if: steps.check_update.outputs.update_needed == 'true'
|
if: steps.check_update.outputs.php_updated == 'true'
|
||||||
run: |
|
run: |
|
||||||
helm package .
|
helm package .
|
||||||
echo "Helm chart packaged"
|
CHART_FILE=$(ls *.tgz)
|
||||||
|
echo "CHART_FILE=${CHART_FILE}" >> $GITHUB_ENV
|
||||||
|
echo "Helm chart packaged: ${CHART_FILE}"
|
||||||
|
|
||||||
- name: Create Git Tag
|
- name: Create Git Tag
|
||||||
if: steps.check_update.outputs.update_needed == 'true'
|
if: steps.check_update.outputs.php_updated == 'true'
|
||||||
run: |
|
run: |
|
||||||
APP_VERSION="${{ steps.php.outputs.app_version }}"
|
APP_VERSION="${{ steps.php.outputs.app_version }}"
|
||||||
git tag -a "v$APP_VERSION" -m "Release PHP $APP_VERSION"
|
|
||||||
git push origin "v$APP_VERSION"
|
# タグが既に存在する場合はスキップ
|
||||||
echo "Git tag v$APP_VERSION created"
|
if git rev-parse "v$APP_VERSION" >/dev/null 2>&1; then
|
||||||
|
echo "Tag v$APP_VERSION already exists, skipping tag creation"
|
||||||
|
else
|
||||||
|
git tag -a "v$APP_VERSION" -m "Release PHP $APP_VERSION"
|
||||||
|
git push origin "v$APP_VERSION"
|
||||||
|
echo "Git tag v$APP_VERSION created"
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Create Gitea Release
|
- name: Create Gitea Release
|
||||||
if: steps.check_update.outputs.update_needed == 'true'
|
if: steps.check_update.outputs.php_updated == 'true'
|
||||||
env:
|
env:
|
||||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
@@ -202,59 +253,29 @@ jobs:
|
|||||||
CHART_NAME=$(grep '^name:' Chart.yaml | awk '{print $2}')
|
CHART_NAME=$(grep '^name:' Chart.yaml | awk '{print $2}')
|
||||||
PACKAGE_FILE="${CHART_NAME}-${APP_VERSION}.tgz"
|
PACKAGE_FILE="${CHART_NAME}-${APP_VERSION}.tgz"
|
||||||
RELEASE_BODY="PHP Helm Chart v${APP_VERSION} - Automated release"
|
RELEASE_BODY="PHP Helm Chart v${APP_VERSION} - Automated release"
|
||||||
curl -X POST -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" -d "{\"tag_name\":\"v${APP_VERSION}\",\"name\":\"v${APP_VERSION}\",\"body\":\"${RELEASE_BODY}\"}" "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases"
|
|
||||||
RELEASE_ID=$(curl -s -H "Authorization: token ${GITEA_TOKEN}" "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases/tags/v${APP_VERSION}" | jq -r '.id')
|
|
||||||
curl -X POST -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/gzip" --data-binary "@${PACKAGE_FILE}" "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=${PACKAGE_FILE}"
|
|
||||||
echo "Release created"
|
|
||||||
|
|
||||||
- name: Update Helm Repository Index
|
# リリースが既に存在する場合はスキップ
|
||||||
if: steps.check_update.outputs.update_needed == 'true'
|
if curl -s -H "Authorization: token ${GITEA_TOKEN}" "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases/tags/v${APP_VERSION}" | jq -e '.id' >/dev/null 2>&1; then
|
||||||
run: |
|
echo "Release v$APP_VERSION already exists, skipping release creation"
|
||||||
set -e
|
|
||||||
APP_VERSION="${{ steps.php.outputs.app_version }}"
|
|
||||||
CHART_NAME=$(grep '^name:' Chart.yaml | awk '{print $2}')
|
|
||||||
PACKAGE_FILE="${CHART_NAME}-${APP_VERSION}.tgz"
|
|
||||||
|
|
||||||
echo "Preparing Helm repository update..."
|
|
||||||
|
|
||||||
# パッケージファイルを一時ディレクトリに移動
|
|
||||||
mkdir -p /tmp/helm-repo
|
|
||||||
cp "${PACKAGE_FILE}" /tmp/helm-repo/
|
|
||||||
|
|
||||||
# gh-pagesブランチの処理
|
|
||||||
if git ls-remote --heads origin gh-pages | grep gh-pages; then
|
|
||||||
echo "gh-pages branch exists, checking out..."
|
|
||||||
git fetch origin gh-pages
|
|
||||||
git checkout gh-pages
|
|
||||||
else
|
else
|
||||||
echo "Creating new gh-pages branch..."
|
curl -X POST -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" -d "{\"tag_name\":\"v${APP_VERSION}\",\"name\":\"v${APP_VERSION}\",\"body\":\"${RELEASE_BODY}\"}" "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases"
|
||||||
git checkout --orphan gh-pages
|
RELEASE_ID=$(curl -s -H "Authorization: token ${GITEA_TOKEN}" "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases/tags/v${APP_VERSION}" | jq -r '.id')
|
||||||
git rm -rf . || true
|
curl -X POST -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/gzip" --data-binary "@${PACKAGE_FILE}" "${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets?name=${PACKAGE_FILE}"
|
||||||
echo "# Helm Repository" > README.md
|
echo "Release created"
|
||||||
git add README.md
|
|
||||||
git config user.name "GitHub Actions Bot"
|
|
||||||
git config user.email "actions@github.com"
|
|
||||||
git commit -m "Initialize gh-pages branch"
|
|
||||||
git push origin gh-pages
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# パッケージファイルをコピー
|
- name: Publish to Gitea Package Registry
|
||||||
cp /tmp/helm-repo/"${PACKAGE_FILE}" .
|
if: steps.check_update.outputs.php_updated == 'true'
|
||||||
|
run: |
|
||||||
# index.yamlを生成/更新
|
echo "🚀 Publishing ${CHART_FILE} to Gitea Package Registry..."
|
||||||
helm repo index . --url "https://git.cafepieters.com/${GITHUB_REPOSITORY}/raw/branch/gh-pages"
|
|
||||||
|
curl --fail-with-body \
|
||||||
# コミットしてプッシュ
|
-u "${{ secrets.REGISTRY_USER }}:${{ secrets.REGISTRY_TOKEN }}" \
|
||||||
git config user.name "GitHub Actions Bot"
|
-X POST \
|
||||||
git config user.email "actions@github.com"
|
--upload-file "${CHART_FILE}" \
|
||||||
git add "${PACKAGE_FILE}" index.yaml
|
"${REGISTRY_URL}/api/packages/${OWNER}/helm/api/charts"
|
||||||
git commit -m "chore: add ${CHART_NAME} v${APP_VERSION}" || echo "No changes to commit"
|
|
||||||
git push origin gh-pages
|
echo "✅ Chart published successfully!"
|
||||||
|
|
||||||
echo "Helm repository updated successfully"
|
|
||||||
|
|
||||||
# mainブランチに戻る
|
|
||||||
git checkout main
|
|
||||||
|
|
||||||
- name: Summary
|
- name: Summary
|
||||||
if: steps.check_update.outputs.update_needed == 'true'
|
if: steps.check_update.outputs.update_needed == 'true'
|
||||||
@@ -262,7 +283,16 @@ jobs:
|
|||||||
APP_VERSION="${{ steps.php.outputs.app_version }}"
|
APP_VERSION="${{ steps.php.outputs.app_version }}"
|
||||||
NGINX_VERSION="${{ steps.nginx.outputs.latest }}"
|
NGINX_VERSION="${{ steps.nginx.outputs.latest }}"
|
||||||
SELENIUM_VERSION="${{ steps.selenium.outputs.latest }}"
|
SELENIUM_VERSION="${{ steps.selenium.outputs.latest }}"
|
||||||
|
PHP_UPDATED="${{ steps.check_update.outputs.php_updated }}"
|
||||||
|
|
||||||
echo "Update completed!"
|
echo "Update completed!"
|
||||||
echo "- PHP: ${APP_VERSION}"
|
echo "- PHP: ${APP_VERSION}"
|
||||||
echo "- Nginx: ${NGINX_VERSION}"
|
echo "- Nginx: ${NGINX_VERSION}"
|
||||||
echo "- Selenium: ${SELENIUM_VERSION}"
|
echo "- Selenium: ${SELENIUM_VERSION}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [ "$PHP_UPDATED" = "true" ]; then
|
||||||
|
echo "✅ PHP version updated - Release created (v${APP_VERSION})"
|
||||||
|
else
|
||||||
|
echo "ℹ️ Nginx/Selenium only update - No release (waiting for next PHP update)"
|
||||||
|
fi
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
# 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 に分離(サービス完全停止の防止)
|
||||||
|
|
||||||
|
**背景(実際に発生した障害)**
|
||||||
|
|
||||||
|
`selenium.enabled: true` の構成(hotels / booking.e-stay.jp)で、php-fpm コンテナの
|
||||||
|
`CrashLoopBackOff` が断続的に発生し、その間サイト全体が Nginx の 502(`unsupported
|
||||||
|
FastCGI protocol version`)で完全に閲覧不能になる障害が続いた。v8.5.9-d で php-fpm の
|
||||||
|
起動方式(`exec php-fpm -F`)を修正した後も、8時間で1,375回という高頻度の再起動が
|
||||||
|
継続して観測された。
|
||||||
|
|
||||||
|
**原因(確定した2点)**
|
||||||
|
|
||||||
|
1. **`resources` values キーがテンプレート側で一切参照されていなかった(死んだ設定)。**
|
||||||
|
`values.yaml` の `resources: {}` にどんな値を書いても、nginx・php-fpm・selenium
|
||||||
|
いずれのコンテナにも CPU/メモリの requests・limits が反映されない実装だった。
|
||||||
|
このため全コンテナが `QoS Class: BestEffort`(実際のデプロイでも確認済み)で動作し、
|
||||||
|
ノードのメモリ逼迫時に Linux の OOM Killer に真っ先に狙われる状態だった。
|
||||||
|
Selenium(Chromium)はメモリを多く消費するため、Raspberry Pi 等のメモリに余裕がない
|
||||||
|
ノードでは他コンテナの OOM Kill を誘発しやすい。
|
||||||
|
2. **nginx・php-fpm・Selenium を同一 Pod のコンテナとして起動しており、Pod の Ready 判定
|
||||||
|
が「全コンテナの AND」になっていた。** readinessProbe を持たないコンテナは、
|
||||||
|
Running であれば Ready 扱いになる一方、CrashLoopBackOff で Waiting/Terminated を
|
||||||
|
繰り返している間は Ready=false になる。Kubernetes の Service は Pod 全体が Ready
|
||||||
|
でなければ Endpoints に含めないため、**Selenium だけが不調でも Service の
|
||||||
|
Endpoints がゼロになり、Selenium を全く使わない静的ページの配信まで巻き込まれて
|
||||||
|
サイト全体が停止していた**。`replicaCount: 1`(冗長性なし)の構成では、この1点が
|
||||||
|
即・全断につながる。
|
||||||
|
|
||||||
|
(OOM Kill が今回の php-fpm クラッシュの直接のトリガーだったかは、`kubectl describe pod`
|
||||||
|
の `Last State` / `Reason` 等での確認が必要で、本リリース時点では未確認・要検証。
|
||||||
|
ただし上記2点はコード上で確認できる確定した設計上の欠陥であり、いずれも本番運用の
|
||||||
|
安定性を損なうため、原因の切り分けを待たずに先に修正する。)
|
||||||
|
|
||||||
|
**対応**
|
||||||
|
|
||||||
|
- `selenium.enabled: true` のとき、Selenium は nginx/php-fpm と別の
|
||||||
|
**独立した Deployment(`<release>-phpfpm-selenium`)と Service** として起動するように
|
||||||
|
変更した(`templates/deployment-selenium.yaml` / `templates/service-selenium.yaml` を新設)。
|
||||||
|
- php-fpm コンテナの `SELENIUM_URL` 環境変数は、`selenium.enabled: true` のとき
|
||||||
|
自動的にこの新しい Service(`http://<release>-phpfpm-selenium:4444/wd/hub`)を
|
||||||
|
指すよう自動注入される(`phpEnv` で独自に設定していても、こちらが優先される)。
|
||||||
|
- `selenium.replicaCount`(既定 `1`)で Selenium の Pod 数を独立して設定可能。
|
||||||
|
- `selenium.mountHtml`(既定 `false`): `true` にすると Selenium コンテナにも
|
||||||
|
PVC の `html` サブパスをマウントする。別 Pod からの同時マウントになるため、
|
||||||
|
有効にする場合は `persistence.accessMode: ReadWriteMany`
|
||||||
|
(NFS バックエンドの StorageClass なら対応可能)が必要。
|
||||||
|
- メインの Service(`<release>-phpfpm`)・Deployment には
|
||||||
|
`app.kubernetes.io/component: web` ラベルを、Selenium 側には `component: selenium`
|
||||||
|
ラベルを付与し、セレクタが混線しないようにした。
|
||||||
|
- `resources` values キーを実際にコンテナへ反映されるよう修正し、**nginx・php-fpm・
|
||||||
|
selenium で個別に設定できる構造**に変更した:
|
||||||
|
```yaml
|
||||||
|
resources:
|
||||||
|
nginx: { requests: {...}, limits: {...} }
|
||||||
|
phpfpm: { requests: {...}, limits: {...} }
|
||||||
|
|
||||||
|
selenium:
|
||||||
|
resources: { requests: {...}, limits: {...} }
|
||||||
|
```
|
||||||
|
既定値は空(`{}`)で、requests/limits なしの現行動作を維持する。**本番運用では
|
||||||
|
設定を強く推奨する**(推奨値の例は `values.yaml` のコメントを参照)。
|
||||||
|
|
||||||
|
**互換性(重要・要対応)**
|
||||||
|
|
||||||
|
- **`selenium.enabled: true` を使っている既存リリースは、アップグレード後に
|
||||||
|
以下の対応が必要:**
|
||||||
|
1. Selenium コンテナがそれまで暗黙にマウントしていた PVC の `html` サブパスに
|
||||||
|
依存していた場合(例: ブラウザのダウンロード先を公開ディレクトリに置いていた等)、
|
||||||
|
`selenium.mountHtml: true` を設定し、`persistence.accessMode` を
|
||||||
|
`ReadWriteMany` に変更する。依存していなければ何もする必要はない
|
||||||
|
(既定 `mountHtml: false` のままでよい)。
|
||||||
|
2. `phpEnv.SELENIUM_URL` に `http://localhost:4444/wd/hub` 等を手動設定している場合、
|
||||||
|
Selenium が別 Pod になったことで `localhost` には到達できなくなる。ただし
|
||||||
|
チャートが自動的に新しい Service を指す値へ上書きするため、**多くの場合は
|
||||||
|
何もしなくても動作する**(自動注入の値が env リストの後方にあるため優先される)。
|
||||||
|
設定の混乱を避けるため、`phpEnv.SELENIUM_URL` の手動指定は削除することを推奨する。
|
||||||
|
- `resources: {}` は元々どのコンテナにも一切効いていなかったため、この構造変更で
|
||||||
|
既存の動作が変わることはない(誰も実質的な値を得ていなかったため、破壊的変更にはならない)。
|
||||||
|
|
||||||
|
**対象ファイル**: `templates/deployment.yaml`, `templates/deployment-selenium.yaml`(新規),
|
||||||
|
`templates/service.yaml`, `templates/service-selenium.yaml`(新規), `values.yaml`,
|
||||||
|
`README.md`, `Chart.yaml`, `CLAUDE.md`, `CHANGELOG-8.5.10-b.md`
|
||||||
|
|
||||||
|
## アップグレード手順
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo update
|
||||||
|
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.10-b -f values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
`selenium.enabled: true` の場合、上記「互換性」を確認のうえアップグレードすること。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**リリース日**: 2026-09-26
|
||||||
|
**担当**: プロサーバーエンジニア(Claude)
|
||||||
@@ -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 "<release>-phpfpm" with kind Deployment: Deployment.apps "<release>-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` 自体を `<chart名>-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(`<release>-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)
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
# Changelog - Version 8.5.2-a
|
||||||
|
|
||||||
|
## 新機能
|
||||||
|
|
||||||
|
### リアルIP転送機能の追加
|
||||||
|
|
||||||
|
ベアメタルKubernetesクラスターやLoadBalancer環境において、PHP側で訪問者の実IPアドレスを取得できる機能を追加しました。
|
||||||
|
|
||||||
|
#### 主な変更点
|
||||||
|
|
||||||
|
1. **values.yaml**
|
||||||
|
- `nginx.forwardRealIP` セクションを追加
|
||||||
|
- `enabled`: リアルIP取得機能の有効/無効
|
||||||
|
- `header`: リアルIPを取得するHTTPヘッダー名(デフォルト: X-Forwarded-For)
|
||||||
|
- `recursive`: 再帰的にリアルIPを検索(多段プロキシ対応)
|
||||||
|
- `trustedProxies`: 信頼するプロキシのネットワーク範囲
|
||||||
|
- `additionalTrustedProxies`: 環境に応じた追加プロキシ設定
|
||||||
|
|
||||||
|
2. **templates/configmap.yaml**
|
||||||
|
- Nginx の `http` セクションにリアルIP設定を追加
|
||||||
|
- `real_ip_header`, `real_ip_recursive`, `set_real_ip_from` ディレクティブを実装
|
||||||
|
- PHP-FPM へ渡す fastcgi_param にリアルIP情報を追加
|
||||||
|
- 既存の `customConfig.snippet` と競合しない構造
|
||||||
|
|
||||||
|
3. **README.md**
|
||||||
|
- リアルIP転送機能の設定パラメータ表を追加
|
||||||
|
- 例7としてベアメタル環境でのリアルIP取得の使用例を追加
|
||||||
|
- 検証用PHPコード例を追加
|
||||||
|
|
||||||
|
4. **examples/test-real-ip.php** (新規作成)
|
||||||
|
- リアルIP転送設定の動作確認用テストスクリプト
|
||||||
|
- WebUIで各種IP関連変数を確認可能
|
||||||
|
- 診断機能付き
|
||||||
|
|
||||||
|
## 技術詳細
|
||||||
|
|
||||||
|
### Nginx設定
|
||||||
|
```nginx
|
||||||
|
# HTTP-levelで設定
|
||||||
|
real_ip_header X-Forwarded-For;
|
||||||
|
real_ip_recursive on;
|
||||||
|
set_real_ip_from 10.0.0.0/8;
|
||||||
|
set_real_ip_from 172.16.0.0/12;
|
||||||
|
set_real_ip_from 192.168.0.0/16;
|
||||||
|
|
||||||
|
# PHP-FPMへ渡すパラメータ
|
||||||
|
fastcgi_param REMOTE_ADDR $remote_addr;
|
||||||
|
fastcgi_param HTTP_X_REAL_IP $remote_addr;
|
||||||
|
fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
|
||||||
|
```
|
||||||
|
|
||||||
|
### PHPでの利用
|
||||||
|
```php
|
||||||
|
// リアルIPアドレスの取得
|
||||||
|
$realIP = $_SERVER['REMOTE_ADDR'];
|
||||||
|
```
|
||||||
|
|
||||||
|
## 互換性
|
||||||
|
|
||||||
|
- 既存の `nginx.customConfig.snippet` 機能と完全に互換性あり
|
||||||
|
- デフォルトは `enabled: false` のため、既存環境への影響なし
|
||||||
|
- 有効化時のみ、リアルIP取得ロジックが動作
|
||||||
|
|
||||||
|
## セキュリティ
|
||||||
|
|
||||||
|
- `trustedProxies` には信頼できるプロキシのみを指定してください
|
||||||
|
- 不正なプロキシを信頼すると、IPスプーフィング攻撃のリスクがあります
|
||||||
|
|
||||||
|
## 使用例
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# values.yaml
|
||||||
|
nginx:
|
||||||
|
forwardRealIP:
|
||||||
|
enabled: true
|
||||||
|
header: "X-Forwarded-For"
|
||||||
|
recursive: true
|
||||||
|
trustedProxies:
|
||||||
|
- "10.0.0.0/8"
|
||||||
|
- "172.16.0.0/12"
|
||||||
|
- "192.168.0.0/16"
|
||||||
|
additionalTrustedProxies:
|
||||||
|
- "203.0.113.0/24" # 外部LoadBalancerのIPレンジ
|
||||||
|
```
|
||||||
|
|
||||||
|
## 検証方法
|
||||||
|
|
||||||
|
1. `examples/test-real-ip.php` を `/var/www/html/` に配置
|
||||||
|
2. ブラウザでアクセス: `http://your-service/test-real-ip.php`
|
||||||
|
3. `REMOTE_ADDR` にパブリックIPが表示されることを確認
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**リリース日**: 2026-02-10
|
||||||
|
**担当**: プロサーバーエンジニア(Claude)
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# Changelog - Version 8.5.6-a
|
||||||
|
|
||||||
|
## 変更点
|
||||||
|
|
||||||
|
### Composer導入先をWebルート外に変更(セキュリティ改善)
|
||||||
|
|
||||||
|
従来、Composerは Webルート `/var/www/html` 直下に導入されており、`composer.json` / `composer.lock` / `vendor/` がWeb経由で公開される状態でした。これらのファイルは公開する必要がなく、依存パッケージ構成の漏洩などセキュリティリスクとなるため、デフォルトの導入先をWebルート外の `/var/www` に変更しました。
|
||||||
|
|
||||||
|
#### 主な変更点
|
||||||
|
|
||||||
|
1. **values.yaml**
|
||||||
|
- `composer.workingDir` パラメータを追加(デフォルト: `"/var/www"`)
|
||||||
|
- Composerの導入先ディレクトリを任意のパスに変更可能
|
||||||
|
|
||||||
|
2. **templates/deployment.yaml**
|
||||||
|
- Composer実行時の作業ディレクトリを `composer.workingDir` に変更(`mkdir -p` で自動作成)
|
||||||
|
- `workingDir` がWebルート(`/var/www/html`)以外の場合、PVCの `composer` サブパスを `workingDir` にマウントし、vendor類を永続化(Pod再起動時の再構築を回避、従来と同等の永続化動作を維持)
|
||||||
|
|
||||||
|
3. **README.md**
|
||||||
|
- `composer.workingDir` のパラメータ説明を追加
|
||||||
|
- Composer導入先とautoload読み込みパスの解説を追加
|
||||||
|
- Selenium使用例の `require_once` パスを更新
|
||||||
|
|
||||||
|
## PHPコードでの利用
|
||||||
|
|
||||||
|
```php
|
||||||
|
// 新: デフォルトの読み込みパス
|
||||||
|
require_once '/var/www/vendor/autoload.php';
|
||||||
|
```
|
||||||
|
|
||||||
|
## 互換性
|
||||||
|
|
||||||
|
- **注意**: PHPコード内で `require_once '/var/www/html/vendor/autoload.php';` や相対パス `vendor/autoload.php` を使用している場合は、パスの修正が必要です。
|
||||||
|
- 旧バージョンと同じ動作(Webルート直下に導入)へ戻す場合は、以下を指定してください:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
composer:
|
||||||
|
workingDir: "/var/www/html"
|
||||||
|
```
|
||||||
|
|
||||||
|
- 既存のPVC内 `html/vendor` はそのまま残ります。不要であれば手動で削除してください。
|
||||||
|
|
||||||
|
## セキュリティ
|
||||||
|
|
||||||
|
- `vendor/` や `composer.json` / `composer.lock` がWebサーバー(Nginx)から配信されなくなり、依存パッケージ情報の漏洩や、vendor内スクリプトへの直接アクセスのリスクを排除できます。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**リリース日**: 2026-07-19
|
||||||
|
**担当**: プロサーバーエンジニア(Claude)
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# Changelog - Version 8.5.6-b
|
||||||
|
|
||||||
|
## 修正
|
||||||
|
|
||||||
|
### 旧Webルートにある既存 composer.json の自動移行
|
||||||
|
|
||||||
|
v8.5.6-a で Composer導入先を `/var/www/html` から `/var/www`(`composer.workingDir`)に変更しましたが、
|
||||||
|
`packages` / `useComposerJson` を使わずに既存の `composer.json` を利用していた環境では、
|
||||||
|
旧Webルートに残った `composer.json` を検出できず、
|
||||||
|
「No composer configuration found, skipping package installation」でインストールがスキップされる問題がありました。
|
||||||
|
|
||||||
|
**対応**: 起動時に `workingDir` に `composer.json` が無く、旧Webルート `/var/www/html` に存在する場合、
|
||||||
|
以下のファイルを自動的に `workingDir` へ移行してから `composer install` を実行するようにしました。
|
||||||
|
|
||||||
|
- `composer.json`
|
||||||
|
- `composer.lock`(存在する場合)
|
||||||
|
- `vendor/`(存在する場合 — 移動によりWebルートから排除され、公開リスクも解消されます)
|
||||||
|
|
||||||
|
移行はWebルートから該当ファイルが無くなるため一度だけ実行され、以降の再起動では通常フローで動作します。
|
||||||
|
|
||||||
|
### mbstring 拡張の依存パッケージ自動追加
|
||||||
|
|
||||||
|
`composer.additionalPhpExtensions` に `mbstring` を指定した場合、
|
||||||
|
Alpine 上でのビルドに必要な `oniguruma-dev` が無く
|
||||||
|
`configure: error: Package requirements (oniguruma) were not met` で失敗していました。
|
||||||
|
|
||||||
|
**対応**: GD拡張と同様に、`mbstring` 指定時は `oniguruma-dev` を自動的にAPKパッケージへ追加するようにしました。
|
||||||
|
|
||||||
|
## アップグレード手順
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo update
|
||||||
|
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.6-b -f values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Pod再起動時に自動移行が実行されます。PHPコード側の読み込みパスの更新を忘れずに行ってください:
|
||||||
|
|
||||||
|
```php
|
||||||
|
require_once '/var/www/vendor/autoload.php';
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**リリース日**: 2026-07-19
|
||||||
|
**担当**: プロサーバーエンジニア(Claude)
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# Changelog - Version 8.5.6-c
|
||||||
|
|
||||||
|
## 変更点
|
||||||
|
|
||||||
|
### Composerデフォルト導入先を `/var/www` から `/composer` に変更
|
||||||
|
|
||||||
|
v8.5.6-a で導入先をWebルート外の `/var/www` に変更しましたが、`/var/www` はWebルート `/var/www/html` の親ディレクトリであるため、ネストマウントの副産物としてPVCの `composer` サブパス内に空の `html/` ディレクトリが生成されていました(マウントポイント作成による正常動作だが紛らわしい)。
|
||||||
|
|
||||||
|
**対応**: デフォルトの `composer.workingDir` をWebルートと親子関係にない `/composer` に変更しました。これによりネストマウントが解消され、空フォルダは一切生成されなくなります。
|
||||||
|
|
||||||
|
## PHPコードでの利用
|
||||||
|
|
||||||
|
```php
|
||||||
|
require_once '/composer/vendor/autoload.php';
|
||||||
|
```
|
||||||
|
|
||||||
|
※ `values.yaml` のコメントにも読み込み方法を明記しています。
|
||||||
|
|
||||||
|
## アップグレード手順
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo update
|
||||||
|
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.6-c -f values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## 互換性
|
||||||
|
|
||||||
|
- **注意**: v8.5.6-a/b で `/var/www/vendor/autoload.php` を参照するようにPHPコードを更新済みの場合は、`/composer/vendor/autoload.php` への再修正が必要です。
|
||||||
|
- PVC上のデータは同じ `composer` サブパスを使用するため、既に移行済みの `composer.json` / `vendor/` はそのまま新しいマウント先(`/composer`)に引き継がれます。
|
||||||
|
- 旧Webルート(`/var/www/html`)からの自動移行機能(v8.5.6-b)はそのまま動作します。
|
||||||
|
- PVC上に残った空の `composer/html/` ディレクトリは、Pod再起動後は再作成されなくなるため、手動で削除すれば以後復活しません。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**リリース日**: 2026-07-19
|
||||||
|
**担当**: プロサーバーエンジニア(Claude)
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
# Changelog - Version 8.5.6-d
|
||||||
|
|
||||||
|
## 修正
|
||||||
|
|
||||||
|
### useComposerJson 使用時の YAML parse error を修正
|
||||||
|
|
||||||
|
`composer.useComposerJson: true` を指定すると、以下のエラーでデプロイに失敗する問題を修正しました。
|
||||||
|
|
||||||
|
```
|
||||||
|
YAML parse error on phpfpm/templates/deployment.yaml:
|
||||||
|
error converting YAML to JSON: yaml: line 96: did not find expected key.
|
||||||
|
```
|
||||||
|
|
||||||
|
**原因**: `templates/deployment.yaml` の heredoc 内で `{{ .Values.composer.composerJson }}` を
|
||||||
|
インデント処理なしで展開していたため、複数行の JSON の2行目以降が行頭に出力され、
|
||||||
|
YAML のブロックスカラー構造を破壊していました(`useComposerJson` 経路の潜在バグ)。
|
||||||
|
|
||||||
|
**対応**: `composerJson` / `composerLock` の展開を `trim | nindent 14` に変更し、
|
||||||
|
ブロックスカラーのインデントに揃えて出力するようにしました。
|
||||||
|
コンテナ内に書き出される `composer.json` / `composer.lock` は行頭からのクリーンな JSON になります。
|
||||||
|
|
||||||
|
## アップグレード手順
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo update
|
||||||
|
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.6-d -f values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用例
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
composer:
|
||||||
|
enabled: true
|
||||||
|
useComposerJson: true
|
||||||
|
composerJson: |
|
||||||
|
{
|
||||||
|
"require": {
|
||||||
|
"phpoffice/phpspreadsheet": "^2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
PHPコードからの読み込み:
|
||||||
|
|
||||||
|
```php
|
||||||
|
require_once '/composer/vendor/autoload.php';
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**リリース日**: 2026-07-19
|
||||||
|
**担当**: プロサーバーエンジニア(Claude)
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# Changelog - Version 8.5.6-e
|
||||||
|
|
||||||
|
## 変更点
|
||||||
|
|
||||||
|
### php-fpm コンテナのマウントを PVCルート → /var/www に変更
|
||||||
|
|
||||||
|
従来、php-fpm コンテナには PVC の `html` サブパスのみが `/var/www/html` にマウントされており、PVC上の他のディレクトリにはアクセスできませんでした。
|
||||||
|
|
||||||
|
**対応**: php-fpm コンテナには PVC の**ルート**を `/var/www` にマウントするように変更しました。
|
||||||
|
|
||||||
|
- `/var/www/html` — 公開フォルダ(nginxが配信するWebルート、従来どおり)
|
||||||
|
- `/var/www/<任意>` — **非公開ファイルの格納先**(PHPから読み書き可能だがWebには公開されない)
|
||||||
|
|
||||||
|
nginx コンテナは従来どおり `html` サブパスのみをマウントするため、`html/` 以外のディレクトリはWebサーバーのファイルシステムに存在せず、公開されることはありません。設定ファイル・秘密鍵・アップロード受け皿など、公開したくないファイルの置き場として利用できます。
|
||||||
|
|
||||||
|
### Composer導入先(/composer)を使い捨て領域に変更
|
||||||
|
|
||||||
|
v8.5.6-c/d では `/composer` をPVCの `composer` サブパスに永続化していましたが、このマウントを廃止しました。
|
||||||
|
|
||||||
|
`/composer` はコンテナローカルの**使い捨て領域**となり、Pod再起動のたびに `composer install` でクリーンに再構築されます。万一不正アクセスで `vendor/` 内にマルウェアを書き込まれても、再起動で消滅します。
|
||||||
|
|
||||||
|
- 永続化したい場合は `composer.workingDir` に `/var/www/composer` など `/var/www` 配下を指定してください。
|
||||||
|
- 再起動ごとにパッケージの再ダウンロードが発生します(クリーン環境維持とのトレードオフ)。
|
||||||
|
|
||||||
|
## アップグレード手順
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo update
|
||||||
|
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.6-e -f values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## 互換性
|
||||||
|
|
||||||
|
- autoloadパスは変わりません: `require_once '/composer/vendor/autoload.php';`
|
||||||
|
- PVC上に残っている旧 `composer/` サブパスのデータは、今後は `/var/www/composer` として見えます。不要であれば削除してください:
|
||||||
|
```bash
|
||||||
|
kubectl exec <pod> -c php-fpm -- rm -rf /var/www/composer
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**リリース日**: 2026-07-19
|
||||||
|
**担当**: プロサーバーエンジニア(Claude)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Changelog - Version 8.5.6-f
|
||||||
|
|
||||||
|
## 修正
|
||||||
|
|
||||||
|
### SMTPパスワードファイルをPHP-FPMワーカーから読めない問題を修正
|
||||||
|
|
||||||
|
`smtp.auth.enabled: true` でSMTP送信メールを設定した際、msmtpが以下のエラーで認証情報を取得できず、メール送信に失敗する問題を修正しました。
|
||||||
|
|
||||||
|
```
|
||||||
|
cat: can't open '/etc/smtp-secrets/password': Permission denied
|
||||||
|
```
|
||||||
|
|
||||||
|
**原因**: `/etc/smtp-secrets/password` を投影するSecretボリュームの `mode` が `0600`(所有者=rootのみ読み取り可)になっていました。msmtp は PHP の `mail()` 呼び出し経由で **PHP-FPMワーカー(`www-data` 等の非rootユーザー)** として実行されるため、rootのみ読み取り可のファイルを読めませんでした。
|
||||||
|
|
||||||
|
**対応**: `templates/deployment.yaml` の `smtp-secrets` ボリュームの `mode` を `0644`(全ユーザー読み取り可)に変更しました。このファイルはPod内にのみ存在し外部からアクセスできないため、許容できるトレードオフです。
|
||||||
|
|
||||||
|
## アップグレード手順
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo update
|
||||||
|
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.6-f -f values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Pod再起動後、SMTP経由のメール送信が正常に動作するようになります。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**リリース日**: 2026-07-19
|
||||||
|
**担当**: プロサーバーエンジニア(Claude)
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# Changelog - Version 8.5.6-g
|
||||||
|
|
||||||
|
## 修正
|
||||||
|
|
||||||
|
### /etc/msmtprc をPHP-FPMワーカーから読めない問題を修正
|
||||||
|
|
||||||
|
v8.5.6-f で `/etc/smtp-secrets/password`(SMTPパスワード)の権限を修正しましたが、
|
||||||
|
`/etc/msmtprc` 自体にも同様の問題が残っており、以下のエラーでメール送信が失敗していました。
|
||||||
|
|
||||||
|
```
|
||||||
|
ignoring system configuration file /etc/msmtprc: Permission denied
|
||||||
|
ignoring user configuration file /home/www-data/.msmtprc: No such file or directory
|
||||||
|
falling back to default account
|
||||||
|
msmtp: account default not found: no configuration file available
|
||||||
|
exit:78
|
||||||
|
```
|
||||||
|
|
||||||
|
**原因**: 起動スクリプト(rootで実行)が `/etc/msmtprc` を作成した後、`chmod 600` していたため、
|
||||||
|
PHP-FPMワーカー(`www-data` 等の非root)から読めませんでした。
|
||||||
|
|
||||||
|
**対応**: `templates/deployment.yaml` の `chmod 600 /etc/msmtprc` を `chmod 644` に変更しました。
|
||||||
|
`msmtprc` には実パスワードは含まれず(`passwordeval` で別ファイルから取得する設計)、
|
||||||
|
ホスト名・ポート・ユーザー名などの設定のみのため、読み取り権限を広げても実害はありません。
|
||||||
|
|
||||||
|
## アップグレード手順
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo update
|
||||||
|
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.6-g -f values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Pod再起動後、SMTP経由のメール送信が正常に動作するようになります。
|
||||||
|
|
||||||
|
### 動作確認
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl exec -n <namespace> <pod> -c php-fpm -- su -s /bin/sh www-data -c \
|
||||||
|
'printf "To: test@example.com\r\nFrom: noreply@example.com\r\nSubject: test\r\nMIME-Version: 1.0\r\nContent-Type: text/plain; charset=UTF-8\r\n\r\nbody\r\n" | /usr/bin/msmtp -t --debug; echo "exit:$?"'
|
||||||
|
```
|
||||||
|
|
||||||
|
`exit:0` で成功です。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**リリース日**: 2026-07-19
|
||||||
|
**担当**: プロサーバーエンジニア(Claude)
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# Changelog - Version 8.5.8-a
|
||||||
|
|
||||||
|
## 新機能
|
||||||
|
|
||||||
|
### Python導入オプションの追加
|
||||||
|
|
||||||
|
PHPからPythonスクリプトを呼び出す用途(データ処理・機械学習ライブラリの利用など)向けに、`values.yaml` の設定だけでPython仮想環境(venv)を導入できるようにしました。既存のComposerサポートと同じ設計方針を踏襲しています。
|
||||||
|
|
||||||
|
#### 主な変更点
|
||||||
|
|
||||||
|
1. **values.yaml**
|
||||||
|
- `python` セクションを新設
|
||||||
|
- `enabled`: Python有効化
|
||||||
|
- `venvDir`: venv導入先(デフォルト `/venv` — Webルート外かつPVCにマウントされない使い捨て領域)
|
||||||
|
- `packages` / `useRequirementsTxt` / `requirementsTxt`: pipパッケージ指定方法(Composerの `packages` / `useComposerJson` と同じ構造)
|
||||||
|
- `installOptions`: pip installオプション(デフォルト `--no-cache-dir`)
|
||||||
|
- `additionalApkPackages`: ネイティブ拡張ビルド用の追加APKパッケージ
|
||||||
|
|
||||||
|
2. **templates/deployment.yaml**
|
||||||
|
- `python.enabled` 時に `python3` / `py3-pip` をAPKでインストール
|
||||||
|
- `python3 -m venv` で仮想環境を構築
|
||||||
|
- `useRequirementsTxt` / `packages` に応じてpipインストールを実行
|
||||||
|
- `requirementsTxt` の複数行内容は `trim | nindent 14` で展開(v8.5.6-d のComposer修正と同じ手法でYAML破壊を回避)
|
||||||
|
|
||||||
|
3. **README.md**
|
||||||
|
- パラメータ表・使用例(例12)を追加
|
||||||
|
- Alpine(musl)向け事前ビルドwheelが無いパッケージ(numpy等)はビルドに時間がかかる旨の注意書きを追加
|
||||||
|
|
||||||
|
## 設計方針(Composerとの一貫性)
|
||||||
|
|
||||||
|
- デフォルトの `/venv` はPVCにマウントされず、**Pod再起動のたびにクリーンな環境へ再構築される使い捨て領域**です。不正アクセスで書き込まれても再起動で消えます。
|
||||||
|
- 永続化したい場合は `python.venvDir` に `/var/www` 配下のパスを指定してください(例: `/var/www/venv`)。
|
||||||
|
|
||||||
|
## 使用例
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
python:
|
||||||
|
enabled: true
|
||||||
|
useRequirementsTxt: true
|
||||||
|
requirementsTxt: |
|
||||||
|
requests>=2.31.0
|
||||||
|
pandas>=2.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
PHPからの呼び出し:
|
||||||
|
|
||||||
|
```php
|
||||||
|
exec('/venv/bin/python3 /var/www/scripts/process.py 2>&1', $output, $exitCode);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 互換性
|
||||||
|
|
||||||
|
- デフォルトは `enabled: false` のため、既存環境への影響はありません。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**リリース日**: 2026-07-19
|
||||||
|
**担当**: プロサーバーエンジニア(Claude)
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# Changelog - Version 8.5.9-a
|
||||||
|
|
||||||
|
## 修正
|
||||||
|
|
||||||
|
### sitemap.xml のContent-Typeを明示的に指定
|
||||||
|
|
||||||
|
`/sitemap.xml`(静的ファイル)へのアクセス時、標準の `mime.types` では `.xml` が `text/xml` 扱いとなり `charset` が付与されないため、ブラウザやGoogle Search Consoleなどのツールが正しく解釈できない場合がありました。
|
||||||
|
|
||||||
|
**対応**: `templates/configmap.yaml` のnginx設定に `location = /sitemap.xml` を追加し、`types { } default_type "application/xml; charset=utf-8";` によって明示的にContent-Typeを指定するようにしました。
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
location = /sitemap.xml {
|
||||||
|
types { }
|
||||||
|
default_type "application/xml; charset=utf-8";
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 注意事項
|
||||||
|
|
||||||
|
- この対応は `/sitemap.xml` が**静的ファイル**として `html/` 直下に配置されている場合に適用されます。
|
||||||
|
- PHPで動的に生成する場合(`/index.php` へのフォールバック経由)は、nginxのこの設定は適用されません。PHP側で `header('Content-Type: application/xml; charset=utf-8');` を明示的に指定してください。
|
||||||
|
- 設定不要・常時有効です(values.yamlへの変更はありません)。ファイルが存在しない場合は従来どおり404を返します。
|
||||||
|
|
||||||
|
## アップグレード手順
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo update
|
||||||
|
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.9-a -f values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**リリース日**: 2026-08-06
|
||||||
|
**担当**: プロサーバーエンジニア(Claude)
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
# Changelog - Version 8.5.9-b
|
||||||
|
|
||||||
|
## 新機能
|
||||||
|
|
||||||
|
### アップロード最大サイズを values.yaml で設定可能に
|
||||||
|
|
||||||
|
大きなファイルのアップロードが失敗する問題(nginxとPHPそれぞれに別々のアップロード上限があり、片方だけ上げても失敗する)に対応するため、`uploadMaxSize` パラメータを新設しました。
|
||||||
|
|
||||||
|
#### 主な変更点
|
||||||
|
|
||||||
|
1. **values.yaml**
|
||||||
|
- `uploadMaxSize: "100m"` を追加(デフォルト100MB)
|
||||||
|
|
||||||
|
2. **templates/configmap.yaml**
|
||||||
|
- nginx設定に `client_max_body_size {{ .Values.uploadMaxSize }};` を追加
|
||||||
|
|
||||||
|
3. **templates/deployment.yaml**
|
||||||
|
- PHP-FPM起動時に `/usr/local/etc/php/conf.d/99-uploads.ini` を生成し、
|
||||||
|
`upload_max_filesize` / `post_max_size` に同じ値を設定
|
||||||
|
- 常時適用(他機能の有効化状態に依存しない)
|
||||||
|
|
||||||
|
4. **README.md**
|
||||||
|
- パラメータ表と、nginx/PHP両方に反映される設計についての注記を追加
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
nginxの `client_max_body_size` だけを上げても、PHPには独自の `upload_max_filesize`(デフォルト2M)/ `post_max_size`(デフォルト8M)という別の上限があり、nginxを通過した後にPHP側で無言で失敗するケースがありました。この2つを同じ値で連動させることで、設定漏れによる失敗を構造的に防ぎます。
|
||||||
|
|
||||||
|
## 使用例
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
uploadMaxSize: "100m"
|
||||||
|
# 大きな動画ファイルなどを扱う場合
|
||||||
|
# uploadMaxSize: "500m"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 互換性
|
||||||
|
|
||||||
|
- デフォルト値は `100m`(従来の暗黙の上限より大幅に緩和)。既存よりアップロード可能サイズが大きくなる方向の変更のため、既存環境への悪影響はありません。
|
||||||
|
- 大きなファイルをPHP側でメモリに読み込んで処理する場合、`memory_limit`(デフォルト128M程度)が別途不足する可能性がある点に注意してください。
|
||||||
|
|
||||||
|
## アップグレード手順
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo update
|
||||||
|
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.9-b -f values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**リリース日**: 2026-08-06
|
||||||
|
**担当**: プロサーバーエンジニア(Claude)
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# Changelog - Version 8.5.9-c
|
||||||
|
|
||||||
|
## 新機能
|
||||||
|
|
||||||
|
### Ingressのアップロードサイズ上限も uploadMaxSize に自動連動
|
||||||
|
|
||||||
|
v8.5.9-b で `uploadMaxSize` によりnginx/PHPのアップロード上限を連動させましたが、`ingress.enabled: true` で運用している場合、Ingressコントローラー(ingress-nginx)にも独自のリクエストサイズ上限(デフォルト1MB)があり、そこで先に弾かれてしまうケースが残っていました。
|
||||||
|
|
||||||
|
**対応**: `templates/ingress.yaml` で、`ingress.annotations` に `nginx.ingress.kubernetes.io/proxy-body-size` が明示指定されていない場合、`uploadMaxSize` の値を自動的に付与するようにしました。ユーザーが `ingress.annotations` に明示的に指定した場合はそちらが優先されます。
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# 何も指定しなくても、Ingressにも uploadMaxSize の値(デフォルト100m)が反映される
|
||||||
|
uploadMaxSize: "100m"
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
これにより、`uploadMaxSize` 1箇所の設定で以下すべてに反映されます:
|
||||||
|
|
||||||
|
- nginx(Podコンテナ内)の `client_max_body_size`
|
||||||
|
- PHPの `upload_max_filesize` / `post_max_size`
|
||||||
|
- ingress-nginxの `nginx.ingress.kubernetes.io/proxy-body-size`
|
||||||
|
|
||||||
|
## 互換性
|
||||||
|
|
||||||
|
- Ingressコントローラーがingress-nginx以外の場合、このアノテーションは無視されます。該当コントローラー向けの設定を `ingress.annotations` に明示的に指定してください。
|
||||||
|
- 既存で `ingress.annotations` に独自の `proxy-body-size` を指定している場合、その値がそのまま優先されるため影響ありません。
|
||||||
|
|
||||||
|
## アップグレード手順
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo update
|
||||||
|
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.9-c -f values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**リリース日**: 2026-08-06
|
||||||
|
**担当**: プロサーバーエンジニア(Claude)
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
# Changelog - Version 8.5.9-d
|
||||||
|
|
||||||
|
## 不具合修正
|
||||||
|
|
||||||
|
### php-fpm を `exec php-fpm -F` で起動(CrashLoopBackOff / 502 の修正)
|
||||||
|
|
||||||
|
php-fpm コンテナの起動コマンドを、setup シェルスクリプト末尾の `php-fpm`(シェルの子プロセスとしてフォアグラウンド起動)から **`exec php-fpm -F`** に変更しました。
|
||||||
|
|
||||||
|
**背景(実際に発生した障害)**
|
||||||
|
|
||||||
|
`selenium.enabled: true` の構成(例: hotels / booking.e-stay.jp)で、php-fpm コンテナが次のエラーで永続的に CrashLoopBackOff に陥る事象が発生しました。
|
||||||
|
|
||||||
|
```
|
||||||
|
[NOTICE] Failed implicitly binding to ::, retrying with 0.0.0.0
|
||||||
|
[ERROR] unable to bind listening socket for address '9000': Address in use (98)
|
||||||
|
[ERROR] FPM initialization failed
|
||||||
|
```
|
||||||
|
|
||||||
|
php-fpm が 9000 を bind できず起動に失敗するため、nginx が `fastcgi_pass 127.0.0.1:9000` に投げても FastCGI ではない応答が返り、`upstream sent unsupported FastCGI protocol version: 60` として **全リクエストが 502** になります(`60` = `<`、= 9000 を握っている別プロセスが HTML 等を返している)。
|
||||||
|
|
||||||
|
**原因**
|
||||||
|
|
||||||
|
起動コマンドが `sh -c "<setup> ... php-fpm"` の形で、**php-fpm が setup シェルの子プロセス**になっていた。コンテナ PID1 はシェルであり、シェルは既定で受け取った `SIGTERM` を子プロセスへ転送しない。そのためコンテナ(php-fpm コンテナのみ)の再起動時に、PID1 のシェルだけが先に終了し、**旧 php-fpm が一時的に残存して 9000 を握ったまま**になることがある。この状態で新しい php-fpm が起動すると `Address in use` で失敗 → 再起動 → 同じ残存 → という自己増殖ループに入り、CrashLoopBackOff から復帰できなくなる。selenium サイドカーは 9000 を使用しておらず無関係(別 pod でのポート占有調査でも確認済み)。
|
||||||
|
|
||||||
|
**対応**
|
||||||
|
|
||||||
|
- `exec php-fpm` … php-fpm が setup シェルを置き換えて**コンテナの PID1 になる**。kubelet からの `SIGTERM`/`SIGKILL` が php-fpm 本体へ直接届き、停止時に 9000 が確実に解放されるため、次回起動での二重 bind が起きない。
|
||||||
|
- `-F`(`--nodaemonize`)… php-fpm.conf の `daemonize` 設定に依存せず、必ずフォアグラウンドで起動する(master が背後に残る事故を防ぐ)。
|
||||||
|
|
||||||
|
これは全サイト共通で安全な変更(コンテナ内で php-fpm を動かす際の定石)であり、既存の正常稼働サイトの挙動は変わりません。
|
||||||
|
|
||||||
|
**復旧手順(重要)**
|
||||||
|
|
||||||
|
チャートを `8.5.9-d` に上げても、既存 pod のネットワーク名前空間に残存プロセスがある場合は、その pod を作り直してクリーンな状態にする必要があります。`helm upgrade` で新しい pod に置き換わりますが、置き換わらない場合は crashloop 中の 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
|
||||||
|
```
|
||||||
|
|
||||||
|
**対象ファイル**: `templates/deployment.yaml`, `Chart.yaml`, `README.md`, `CLAUDE.md`, `CHANGELOG-8.5.9-d.md`
|
||||||
|
|
||||||
|
## アップグレード手順
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo update
|
||||||
|
helm upgrade <リリース名> cafepieters/phpfpm --version 8.5.9-d -f values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**リリース日**: 2026-09-06
|
||||||
|
**担当**: プロサーバーエンジニア(Claude)
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
# CLAUDE.md — phpfpm Helm Chart
|
||||||
|
|
||||||
|
> **共通ルール(要約)** — 詳細は `P:\Claude\CLAUDE.md`(全体共通)と `P:\Claude\HelmChart\CLAUDE.md`(Helm チャート共通: リリースフロー・ワークフロー・Gitea Secrets・クラスタ構成)を参照。
|
||||||
|
> 作業前に pull / 機能変更時は README 更新 / 作業単位ごとに commit → push まで / コミットに AI クレジットを付けない / pull で入った変更を revert しない / Helm・PHP はローカル実行不可(Python のみ可)。
|
||||||
|
|
||||||
|
## リポジトリ概要
|
||||||
|
|
||||||
|
Raspberry Pi などのベアメタルで稼働することを想定した、Kubernetes 上で動作する Nginx + PHP-FPM の Helm チャート。
|
||||||
|
Websites 組織の各サイト(e-learn.jp / fcdomain.com / hotels / tskholding.com など)はこのチャートでデプロイされる。
|
||||||
|
|
||||||
|
- **Gitea リポジトリ**: `ssh://git@192.168.9.65/helmchart/phpfpm`
|
||||||
|
- **Helm リポジトリ**: `https://git.cafepieters.com/api/packages/helmchart/helm`
|
||||||
|
- **主アプリ**: PHP(`docker.io/php:<tag>-fpm-alpine`)。サブアプリ: nginx
|
||||||
|
|
||||||
|
## 実行環境について
|
||||||
|
|
||||||
|
**PHP の実行環境(インタープリタ)はこのリポジトリには含まれていない。**
|
||||||
|
チャートは `docker.io/php:<tag>-fpm-alpine` の公式イメージを Kubernetes 上で起動するものであり、PHP コードそのものは PVC(`/var/www/html`)に別途配置する必要がある。
|
||||||
|
|
||||||
|
## 設計上の注意(既知の落とし穴)
|
||||||
|
|
||||||
|
- `templates/configmap.yaml` が実際に使われている nginx 設定。`templates/configmap-nginx.yaml` は `.Values.nginx.enabled` が values.yaml に存在せず常に未出力の**死んだファイル**なので注意。
|
||||||
|
- PVC はルートを `/var/www` にマウントする(`html/` が公開フォルダ、それ以外は非公開)。`/composer` は Pod 再起動ごとにクリーン再構築される使い捨て領域。
|
||||||
|
- `uploadMaxSize` 1箇所で nginx `client_max_body_size`・PHP `upload_max_filesize`/`post_max_size`・Ingress `proxy-body-size` の3箇所が連動する。
|
||||||
|
- Secret / ConfigMap をファイルとして PHP-FPM ワーカー(`www-data`)から読ませる場合、権限は `0644` にする(`0600` だと読めない)。
|
||||||
|
- Selenium(`selenium.enabled: true`)は v8.5.10-b 以降、nginx/php-fpm と別の Deployment/Service(`<release>-phpfpm-selenium`)。同一 Pod のサイドカーには**しない**(Selenium 単体の不調でメインの Pod が Service の Endpoints から外れ、静的ページ配信まで巻き込んで全断する設計だったため分離した)。
|
||||||
|
|
||||||
|
## チャート改修履歴
|
||||||
|
|
||||||
|
### nginx.customConfig の取り違え防止(ドキュメント修正、2026-10-20, v8.5.11-a)
|
||||||
|
|
||||||
|
- **症状 / 背景**: あるプロジェクトのレポートで「`serverSnippet` が効かない。既定の `snippet:` はどのテンプレートも読まない古いキーでは」という指摘があった。別件で、`snippet` に `client_max_body_size` を書いていたプロジェクトが `directive is duplicate` で nginx 起動失敗する障害(2026-09-29)も起きていた。
|
||||||
|
- **原因**:
|
||||||
|
- 指摘は誤り。実際に使われる `templates/configmap.yaml` が読むのは `snippet` で、`values.yaml`・README と一致している。`serverSnippet` / `httpSnippet` は、一度も出力されない `templates/configmap-nginx.yaml`(`.Values.nginx.enabled` が values に無く常に偽)だけが読むキーで、values・README に載ったことがない(コミット `31106e0` 由来)。指定すると黙って無視される。
|
||||||
|
- README 例6・例9 が `snippet` に `client_max_body_size` を書く手順を案内しており、v8.5.9-b 以降は `uploadMaxSize` の自動出力と重複して起動失敗する。例6 はチャート本体と重複する `location ~ \.php$` も再定義していた。
|
||||||
|
- **修正内容**: 挙動の変更なし(ドキュメント・コメントのみ)。`values.yaml` と README に「読まれるキーは `snippet` のみ、挿入先は server ブロック内、`client_max_body_size` は書かず `uploadMaxSize` を使う」を明記。README 例6・例9 を `uploadMaxSize` 指定に修正。`configmap-nginx.yaml` 先頭に「未使用」の注記を追加。
|
||||||
|
- **やらなかったこと**: `snippet` を `serverSnippet` に改名する(動いているキーを壊すため)。`serverSnippet` を `snippet` の別名として有効化する(これまで無視されていた設定が突然有効になり、重複で起動失敗する恐れがあるため)。`http` レベルの snippet が必要になった場合は、別途 `configmap.yaml` に正式対応を追加する。
|
||||||
|
- **対象ファイル**: `values.yaml`, `README.md`, `templates/configmap-nginx.yaml`(コメントのみ), `Chart.yaml`
|
||||||
|
|
||||||
|
### Cron(CronJob)定期実行機能を追加(2026-09-27, v8.5.10-e)
|
||||||
|
|
||||||
|
- **背景**: 定期実行したいPHPスクリプト(レポート送信・バッチ処理等)を動かす手段がなく、外部で別途スケジューラを用意する必要があった。
|
||||||
|
- **追加内容**: `cron.jobs`(配列)にジョブを定義すると、`templates/cronjob.yaml`がジョブごとにKubernetes CronJobを生成する。php-fpmと同じPHPイメージを使用し、PVCルートを`/var/www`にマウント、`externalDatabase`/`phpEnv`/`extraEnv`/`extraEnvFrom`/`SELENIUM_URL`をphp-fpmコンテナと同じ内容で注入する。`smtp.enabled: true`の場合はCronJob内でも自動的にmsmtpを導入する(`templates/deployment.yaml`のSMTP設定と重複実装、変更時は両方揃えること)。
|
||||||
|
- **設計上の注意点**:
|
||||||
|
- CronJobが生成するPodのラベル(`app.kubernetes.io/name`)は`phpfpm.cron.name`ヘルパーで`<chart>-cron`というバリアント名にしている。Selenium分離(v8.5.10-b)と同じ理由で、nginx/php-fpm DeploymentのmatchLabels(`name: phpfpm, instance: <release>`)と一致させると、ReplicaSetコントローラーがCronJob由来のPodを誤って自身の管理対象とみなし削除する事故につながるため。
|
||||||
|
- CronJob名は`trunc 52`で切り詰めている(Kubernetesの実務上の制約。CronJobは生成するJob/Pod名にタイムスタンプ等のsuffixが付くため、フルの253/63文字ではなく52文字程度に収める必要がある)。
|
||||||
|
- Composer(`/composer`)・Python venv(`/venv`)はデフォルトでPVC非マウントの使い捨て領域のため、CronJobのPodには存在しない。意図的にCronJob側では再インストールを行わない設計とした(頻繁な実行での再インストールコストを避けるため)。CronJobから使いたい場合は`composer.workingDir`/`python.venvDir`を`/var/www`配下に変更しPVC上へ永続化することをREADMEで案内している。
|
||||||
|
- **対象ファイル**: `templates/cronjob.yaml`(新規), `templates/_helpers.tpl`, `values.yaml`, `README.md`, `Chart.yaml`
|
||||||
|
|
||||||
|
### ingress.tls[].secretNameをhostから自動導出可能に(2026-09-27, v8.5.10-d)
|
||||||
|
|
||||||
|
- **背景**: `ingress.hosts[].host` は既にYAMLアンカー(`&appDomain`)で `ingress.tls[].hosts` と値を共有できるようになっていたが、`ingress.tls[].secretName` は独立した文字列指定が必須で、ドメイン変更時に別途書き換えが必要だった。
|
||||||
|
- **修正内容**: `templates/ingress.yaml` で `secretName` を省略可能にし、未指定時はそのエントリの最初のhostから自動生成する(`.`を`-`に置換して`-tls`を付与。例: `example.tld` → `example-tld-tls`)。明示的に指定した場合はそちらが優先される(後方互換)。デフォルトの`values.yaml`も自動導出を使う例に更新。
|
||||||
|
- **対象ファイル**: `templates/ingress.yaml`, `values.yaml`, `README.md`, `Chart.yaml`
|
||||||
|
|
||||||
|
### 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`自体を`<chart名>-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(`<release>-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点はコード上確認済みの確定した欠陥のため先行修正した。
|
||||||
|
|
||||||
|
**対象ファイル**: `templates/deployment.yaml`, `templates/deployment-selenium.yaml`(新規), `templates/service.yaml`, `templates/service-selenium.yaml`(新規), `values.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.10-b.md`
|
||||||
|
|
||||||
|
### 外部Secret連携(extraEnvFrom / extraEnv / SMTP existingSecret)を追加(2026-09-08, v8.5.10-a)
|
||||||
|
|
||||||
|
**背景**: 別リポジトリの `helmchart/secret-manager` チャートが各ネームスペースへ配布する
|
||||||
|
`cred-<名前>` Secret(メールの msmtprc / API キー)を、phpfpm 側から参照する口が無かった
|
||||||
|
(`phpEnv` は直書きのみ、SMTP パスワードは `smtp.auth.password` 直書き+自作 Secret のみ)。
|
||||||
|
|
||||||
|
**修正内容**:
|
||||||
|
- `values.yaml` に `extraEnvFrom`(`envFrom` 配列)と `extraEnv`(生の env エントリ配列)を追加。
|
||||||
|
php-fpm コンテナに既存 Secret/ConfigMap をまるごと env 注入できる。
|
||||||
|
- `smtp.auth.existingSecret` / `existingSecretKey` を追加。チャートで msmtprc を生成しつつ
|
||||||
|
パスワードファイルだけ既存 Secret から取る。
|
||||||
|
- `smtp.existingMsmtprcSecret` / `existingMsmtprcSecretKey` を追加。完成済み msmtprc を持つ
|
||||||
|
既存 Secret をそのまま `/etc/smtp-config/msmtprc` としてマウント(secret-manager が生成する
|
||||||
|
`msmtprc` キーを想定)。指定時は `configmap-smtp` を生成せず host/port/auth.* は無視、
|
||||||
|
`smtp-secrets` ボリュームも張らない(msmtprc にパスワードが内包されるため)。
|
||||||
|
- `templates/secret-smtp.yaml` / `templates/configmap-smtp.yaml` を上記フラグで出し分け。
|
||||||
|
- 既定値は全て空 → 既存挙動は不変(`helm template` の全シナリオで確認済み)。
|
||||||
|
- 主アプリ(PHP 8.5.10)は変わらないため手動リリース `8.5.10-a`。
|
||||||
|
|
||||||
|
**対象ファイル**: `values.yaml`, `templates/deployment.yaml`, `templates/configmap-smtp.yaml`,
|
||||||
|
`templates/secret-smtp.yaml`, `Chart.yaml`, `README.md`, `CLAUDE.md`
|
||||||
|
|
||||||
|
### php-fpm を `exec php-fpm -F` で起動しCrashLoopBackOffを修正(2026-09-06, v8.5.9-d)
|
||||||
|
|
||||||
|
setup シェル末尾の `php-fpm`(シェルの子プロセス)を **`exec php-fpm -F`** に変更。selenium 有効構成(hotels)で php-fpm が `unable to bind ... '9000': Address in use` を出して永続 CrashLoopBackOff になり、nginx が非FastCGI応答を受けて全リクエスト502(`unsupported FastCGI protocol version: 60`)になる障害の修正。原因は php-fpm が setup シェルの子で、コンテナ PID1 のシェルが `SIGTERM` を子へ転送しないため、コンテナ再起動時に旧 php-fpm が残存し 9000 を握ったまま次回起動が二重 bind で失敗する自己増殖ループ。`exec` で php-fpm を PID1 にしてシグナルを直接受けさせ(停止時に 9000 を確実解放)、`-F` で `daemonize` 設定に依存せず必ずフォアグラウンド起動にした。全サイト共通で安全(コンテナで php-fpm を動かす定石)。復旧には `helm upgrade` に加え、残存プロセスを持つ既存 pod の削除が必要な場合がある。
|
||||||
|
|
||||||
|
**対象ファイル**: `templates/deployment.yaml`, `Chart.yaml`, `README.md`, `CLAUDE.md`, `CHANGELOG-8.5.9-d.md`
|
||||||
|
|
||||||
|
### Ingressのproxy-body-sizeもuploadMaxSizeに連動(2026-08-06, v8.5.9-c)
|
||||||
|
|
||||||
|
v8.5.9-bのフォローアップ。`templates/ingress.yaml` で `merge (deepCopy .Values.ingress.annotations) (dict "nginx.ingress.kubernetes.io/proxy-body-size" .Values.uploadMaxSize)` を使い、ユーザーが明示指定していなければ `uploadMaxSize` をIngressの `proxy-body-size` にも自動反映。明示指定があればそちらが優先(sprigのmergeはdst=ユーザー指定annotationsが優先、srcのデフォルト値は不足分のみ補う)。これで `uploadMaxSize` 1箇所でnginx・PHP・Ingressの3箇所すべてが揃う。
|
||||||
|
|
||||||
|
**対象ファイル**: `templates/ingress.yaml`, `values.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.9-c.md`
|
||||||
|
|
||||||
|
### uploadMaxSize の追加(2026-08-06, v8.5.9-b)
|
||||||
|
|
||||||
|
nginxの `client_max_body_size` とPHPの `upload_max_filesize`/`post_max_size` を1つの `uploadMaxSize`(デフォルト `"100m"`)で連動させるパラメータを追加。片方だけ上げてももう片方の上限でアップロードが無言で失敗する問題への対応。PHP側は起動時に `/usr/local/etc/php/conf.d/99-uploads.ini` を常時生成(他機能の有効/無効に依存しない)。memory_limitは対象外(別途必要なら将来検討)。
|
||||||
|
|
||||||
|
**対象ファイル**: `values.yaml`, `templates/configmap.yaml`, `templates/deployment.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.9-b.md`
|
||||||
|
|
||||||
|
### sitemap.xml のContent-Type明示(2026-08-06, v8.5.9-a)
|
||||||
|
|
||||||
|
`templates/configmap.yaml` に `location = /sitemap.xml { types { } default_type "application/xml; charset=utf-8"; ... }` を追加。標準mime.typesでは `.xml` が `text/xml` 扱いでcharset無しになる問題への対応。静的ファイルの場合のみ有効、PHP動的生成には効かない(PHP側でheader()指定が必要)。設定不要・常時有効。
|
||||||
|
|
||||||
|
**対象ファイル**: `templates/configmap.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.9-a.md`
|
||||||
|
|
||||||
|
### Python導入オプションの追加(2026-07-19, v8.5.8-a)
|
||||||
|
|
||||||
|
`python` セクションを新設し、`values.yaml` の設定だけでPython仮想環境(venv)を導入可能にした。Composerと同じ設計方針(デフォルト導入先 `/venv` はPVC非マウントの使い捨て領域、`packages`/`useRequirementsTxt`の二択、`additionalApkPackages`でネイティブ拡張ビルド対応)。requirements.txtの展開は `trim | nindent 14`(v8.5.6-dのバグ修正と同じ手法)。PHPからは `exec('/venv/bin/python3 script.py')` で呼び出す。
|
||||||
|
|
||||||
|
なお、この改修中に自動更新ワークフローがPHP 8.5.8へのフルリリース(v8.5.8)を実行したため、本機能はそのタグの上に手動リリース `8.5.8-a` として適用した。
|
||||||
|
|
||||||
|
**対象ファイル**: `values.yaml`, `templates/deployment.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.8-a.md`
|
||||||
|
|
||||||
|
### /etc/msmtprc の権限を0600→0644に修正(2026-07-19, v8.5.6-g)
|
||||||
|
|
||||||
|
v8.5.6-f のフォローアップ。`/etc/smtp-secrets/password` の権限修正だけでは不十分で、起動スクリプトが `cp` 後に `chmod 600` していた `/etc/msmtprc` 自体もrootのみ読み取り可のままだった(msmtp: account default not found, exit:78)。`chmod 644` に変更。msmtprcには平文パスワードは含まれない(passwordeval経由で別ファイル参照)ため実害なし。
|
||||||
|
|
||||||
|
**対象ファイル**: `templates/deployment.yaml`, `Chart.yaml`, `CHANGELOG-8.5.6-g.md`
|
||||||
|
|
||||||
|
### SMTPパスワードSecretの権限を0600→0644に修正(2026-07-19, v8.5.6-f)
|
||||||
|
|
||||||
|
`smtp-secrets` ボリュームの `mode: 0600` が原因で、rootではなく `www-data`(PHP-FPMワーカー)として動く msmtp が `/etc/smtp-secrets/password` を読めず、SMTP認証に失敗する不具合を修正。`0644` に変更(Pod内にしか存在しないファイルのため許容範囲)。
|
||||||
|
|
||||||
|
**対象ファイル**: `templates/deployment.yaml`, `Chart.yaml`, `CHANGELOG-8.5.6-f.md`
|
||||||
|
|
||||||
|
### PVCルートを /var/www にマウント + /composer を使い捨て化(2026-07-19, v8.5.6-e)
|
||||||
|
|
||||||
|
php-fpm コンテナのマウントを「`html` サブパスのみ」から「PVCルート → `/var/www`」に変更。`html/` は公開フォルダ、それ以外(`/var/www/<任意>`)は非公開ファイルの格納先として使える。nginx は `html` サブパスのみマウントするため非公開分は公開されない。あわせて `/composer` のPVC永続化マウントを廃止し、Pod再起動ごとにクリーン再構築される使い捨て領域とした(マルウェア混入対策、ユーザー要望)。永続化したい場合は `workingDir` に `/var/www/composer` 等を指定。
|
||||||
|
|
||||||
|
**対象ファイル**: `templates/deployment.yaml`, `values.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.6-e.md`
|
||||||
|
|
||||||
|
### useComposerJson の YAML parse error 修正(2026-07-19, v8.5.6-d)
|
||||||
|
|
||||||
|
`useComposerJson: true` 指定時、heredoc 内の `{{ .Values.composer.composerJson }}` がインデント無しで展開され、複数行JSONの2行目以降がブロックスカラーを破壊して YAML parse error になる潜在バグを修正。`trim | nindent 14` で展開するよう変更(`composerLock` も同様)。
|
||||||
|
|
||||||
|
**対象ファイル**: `templates/deployment.yaml`, `Chart.yaml`, `CHANGELOG-8.5.6-d.md`
|
||||||
|
|
||||||
|
### Composerデフォルト導入先を /composer に変更(2026-07-19, v8.5.6-c)
|
||||||
|
|
||||||
|
`/var/www` はWebルート `/var/www/html` の親のため、ネストマウントでPVCの `composer` サブパス内に空の `html/` が生成されていた。デフォルトをWebルートと親子関係にない `/composer` に変更してネストを解消。autoloadは `require_once '/composer/vendor/autoload.php';`(values.yaml のコメントにも明記)。
|
||||||
|
|
||||||
|
**対象ファイル**: `values.yaml`, `templates/deployment.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.6-c.md`
|
||||||
|
|
||||||
|
### 旧composer.jsonの自動移行 + mbstring依存の自動追加(2026-07-19, v8.5.6-b)
|
||||||
|
|
||||||
|
v8.5.6-a のフォローアップ。起動時に `workingDir` に `composer.json` が無く旧Webルート `/var/www/html` にある場合、`composer.json` / `composer.lock` / `vendor/` を自動移行する。また `additionalPhpExtensions` に `mbstring` 指定時、ビルドに必要な `oniguruma-dev` を自動追加(GDと同じ仕組み)。
|
||||||
|
|
||||||
|
なお、PVC上の `composer/html/`(空ディレクトリ)はネストマウントのマウントポイント作成による正常な副産物で、実害なし。
|
||||||
|
|
||||||
|
**対象ファイル**: `templates/deployment.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.6-b.md`
|
||||||
|
|
||||||
|
### composer.workingDir — Composer導入先のWebルート外への変更(2026-07-19, v8.5.6-a)
|
||||||
|
|
||||||
|
Composerの導入先をWebルート `/var/www/html` からWebルート外の `/var/www` に変更し、`vendor/` や `composer.json` がWeb経由で公開されないようにした。`values.yaml` の `composer.workingDir` で導入先を変更可能(旧動作に戻すには `"/var/www/html"` を指定)。導入先がWebルート以外の場合、PVCの `composer` サブパスをマウントして永続化する。
|
||||||
|
|
||||||
|
PHP側の読み込みは `require_once '/var/www/vendor/autoload.php';`。
|
||||||
|
|
||||||
|
**対象ファイル**: `values.yaml`, `templates/deployment.yaml`, `README.md`, `Chart.yaml`, `CHANGELOG-8.5.6-a.md`
|
||||||
|
|
||||||
|
### phpEnv — 汎用 PHP 環境変数サポート(2026-04-17)
|
||||||
|
|
||||||
|
`values.yaml` に `phpEnv` セクションを追加し、DB 接続情報と同様に任意のキーと値を PHP-FPM コンテナの環境変数として渡せるようにした。
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
phpEnv:
|
||||||
|
API_KEY: "your-api-key"
|
||||||
|
STRIPE_SECRET: "sk_live_..."
|
||||||
|
REDIS_URL: "redis://localhost:6379"
|
||||||
|
```
|
||||||
|
|
||||||
|
PHP 側では `$_ENV['API_KEY']` または `getenv('API_KEY')` で取得できる。
|
||||||
|
|
||||||
|
**対象ファイル**: `values.yaml`, `templates/deployment.yaml`, `README.md`
|
||||||
+2
-2
@@ -2,6 +2,6 @@ apiVersion: v2
|
|||||||
name: phpfpm
|
name: phpfpm
|
||||||
description: Nginx + PHP-FPM Helm Chart with external DB and optional Selenium support
|
description: Nginx + PHP-FPM Helm Chart with external DB and optional Selenium support
|
||||||
type: application
|
type: application
|
||||||
version: 8.5.2
|
version: 8.5.12
|
||||||
appVersion: "8.5.2"
|
appVersion: "8.5.12"
|
||||||
icon: https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/PHP-logo.svg/330px-PHP-logo.svg.png
|
icon: https://upload.wikimedia.org/wikipedia/commons/thumb/2/27/PHP-logo.svg/330px-PHP-logo.svg.png
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# GEMINI.md — Antigravity (Gemini) 用エントリポイント(HelmChart\phpfpm)
|
||||||
|
|
||||||
|
このディレクトリのルールはすべて **`CLAUDE.md`** に記載されている。本ファイルにはルール本文を書かず、読むべき CLAUDE.md への参照だけを置く(正本は常に CLAUDE.md)。
|
||||||
|
|
||||||
|
## 必ず最初に実行すること
|
||||||
|
|
||||||
|
以下のファイルを**上から順に**読み込み、すべての指示に従うこと。上位ほど広い範囲に適用される共通ルールで、下位は上位を前提とした補足・例外である。
|
||||||
|
|
||||||
|
1. `P:\Claude\CLAUDE.md` — 全組織共通ルール(Git 運用・コミット書式・実行環境・情報記載の原則)
|
||||||
|
2. `P:\Claude\HelmChart\CLAUDE.md` — HelmChart 組織共通ルール
|
||||||
|
3. `P:\Claude\HelmChart\phpfpm\CLAUDE.md` — phpfpm リポジトリ固有ルール(このディレクトリ)
|
||||||
|
|
||||||
|
> Antigravity はワークスペース(または git ルート)直下のルールしか自動で読まず、親フォルダを遡らない。そのため上位階層のパスをここに明示している。`P:\Claude` はクラウド同期されており、デスクトップ・ノート PC とも同じパスで存在する。
|
||||||
|
|
||||||
|
## 読み替え
|
||||||
|
|
||||||
|
- CLAUDE.md 中の「Claude」「Claude Code」は、Antigravity で作業する場合は Gemini 自身のことと読み替える。
|
||||||
|
- Git のコミット者は Antigravity でも `user.name = Claude` / `user.email = claude@cafepieters.com` のまま使う(変更しない)。コミットメッセージに AI クレジットを付けない。
|
||||||
|
- Claude Code 固有の機能(`.claude/` 設定、スキル、メモリ等)に関する記述は無視してよい。
|
||||||
|
|
||||||
|
## 保守ルール
|
||||||
|
|
||||||
|
- ルールの追加・変更は **CLAUDE.md にのみ**行う。本ファイルと `.agents/rules/claude-md.md` は参照だけを保持し、内容を増やさない。
|
||||||
|
- CLAUDE.md を新しいディレクトリに追加したときは、同じ形式の `GEMINI.md` と `.agents/rules/claude-md.md` も併置する。
|
||||||
@@ -0,0 +1,226 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Real IP Test Script
|
||||||
|
*
|
||||||
|
* このスクリプトは、NginxのリアルIP転送設定が正しく動作しているかを確認します。
|
||||||
|
*
|
||||||
|
* 使用方法:
|
||||||
|
* 1. values.yamlでnginx.forwardRealIP.enabled=trueに設定
|
||||||
|
* 2. このファイルを /var/www/html/ に配置
|
||||||
|
* 3. ブラウザでアクセス: http://your-service/test-real-ip.php
|
||||||
|
*/
|
||||||
|
|
||||||
|
header('Content-Type: text/html; charset=utf-8');
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ja">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Real IP Test</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 50px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
background: white;
|
||||||
|
padding: 30px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
color: #333;
|
||||||
|
border-bottom: 3px solid #4CAF50;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
padding: 12px;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
tr:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
.success {
|
||||||
|
color: #4CAF50;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.warning {
|
||||||
|
color: #ff9800;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.info {
|
||||||
|
background: #e3f2fd;
|
||||||
|
padding: 15px;
|
||||||
|
border-left: 4px solid #2196F3;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
background: #f4f4f4;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>🔍 Real IP Detection Test</h1>
|
||||||
|
|
||||||
|
<div class="info">
|
||||||
|
<strong>ℹ️ 情報:</strong> このページは、NginxのリアルIP転送設定が正しく動作しているかを確認します。
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>📊 IP Address Information</h2>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>変数名</th>
|
||||||
|
<th>値</th>
|
||||||
|
<th>説明</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>REMOTE_ADDR</code></td>
|
||||||
|
<td class="success"><?php echo htmlspecialchars($_SERVER['REMOTE_ADDR'] ?? 'not set'); ?></td>
|
||||||
|
<td>クライアントの実IPアドレス(Nginx real_ip設定適用後)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>HTTP_X_REAL_IP</code></td>
|
||||||
|
<td><?php echo htmlspecialchars($_SERVER['HTTP_X_REAL_IP'] ?? 'not set'); ?></td>
|
||||||
|
<td>Nginxが設定したリアルIP(互換性用)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>HTTP_X_FORWARDED_FOR</code></td>
|
||||||
|
<td><?php echo htmlspecialchars($_SERVER['HTTP_X_FORWARDED_FOR'] ?? 'not set'); ?></td>
|
||||||
|
<td>プロキシチェーン全体(カンマ区切り)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>HTTP_CLIENT_IP</code></td>
|
||||||
|
<td><?php echo htmlspecialchars($_SERVER['HTTP_CLIENT_IP'] ?? 'not set'); ?></td>
|
||||||
|
<td>一部のプロキシが使用</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2>🔧 All HTTP Headers</h2>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Header Name</th>
|
||||||
|
<th>Value</th>
|
||||||
|
</tr>
|
||||||
|
<?php
|
||||||
|
$headers = [];
|
||||||
|
foreach ($_SERVER as $key => $value) {
|
||||||
|
if (strpos($key, 'HTTP_') === 0) {
|
||||||
|
$headerName = str_replace('_', '-', substr($key, 5));
|
||||||
|
$headers[$headerName] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ksort($headers);
|
||||||
|
|
||||||
|
foreach ($headers as $name => $value) {
|
||||||
|
echo '<tr>';
|
||||||
|
echo '<td><code>' . htmlspecialchars($name) . '</code></td>';
|
||||||
|
echo '<td>' . htmlspecialchars($value) . '</td>';
|
||||||
|
echo '</tr>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<h2>✅ 診断結果</h2>
|
||||||
|
<div class="info">
|
||||||
|
<?php
|
||||||
|
$remoteAddr = $_SERVER['REMOTE_ADDR'] ?? '';
|
||||||
|
$xForwardedFor = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '';
|
||||||
|
|
||||||
|
// プライベートIPかどうかをチェック
|
||||||
|
function isPrivateIP($ip) {
|
||||||
|
$privateRanges = [
|
||||||
|
'10.0.0.0|10.255.255.255',
|
||||||
|
'172.16.0.0|172.31.255.255',
|
||||||
|
'192.168.0.0|192.168.255.255',
|
||||||
|
'127.0.0.0|127.255.255.255'
|
||||||
|
];
|
||||||
|
|
||||||
|
$longIP = ip2long($ip);
|
||||||
|
foreach ($privateRanges as $range) {
|
||||||
|
list($start, $end) = explode('|', $range);
|
||||||
|
if ($longIP >= ip2long($start) && $longIP <= ip2long($end)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($remoteAddr) && !isPrivateIP($remoteAddr)) {
|
||||||
|
echo '<p class="success">✅ <strong>正常:</strong> REMOTE_ADDR にパブリックIPアドレスが設定されています。</p>';
|
||||||
|
echo '<p>リアルIP転送設定が正しく動作しています。</p>';
|
||||||
|
} elseif (!empty($remoteAddr) && isPrivateIP($remoteAddr)) {
|
||||||
|
echo '<p class="warning">⚠️ <strong>注意:</strong> REMOTE_ADDR がプライベートIPアドレスです: ' . htmlspecialchars($remoteAddr) . '</p>';
|
||||||
|
echo '<p>これは以下のいずれかが原因です:</p>';
|
||||||
|
echo '<ul>';
|
||||||
|
echo '<li>リアルIP転送設定(nginx.forwardRealIP.enabled)が無効</li>';
|
||||||
|
echo '<li>trustedProxiesの設定が不適切</li>';
|
||||||
|
echo '<li>LoadBalancerがX-Forwarded-Forヘッダーを送信していない</li>';
|
||||||
|
echo '</ul>';
|
||||||
|
|
||||||
|
if (!empty($xForwardedFor)) {
|
||||||
|
echo '<p><strong>ヒント:</strong> X-Forwarded-For ヘッダーには値があります: ' . htmlspecialchars($xForwardedFor) . '</p>';
|
||||||
|
echo '<p>values.yaml で <code>nginx.forwardRealIP.enabled: true</code> に設定してください。</p>';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo '<p class="warning">⚠️ REMOTE_ADDR が設定されていません</p>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>📝 PHPでの使用例</h2>
|
||||||
|
<pre style="background: #f4f4f4; padding: 15px; border-radius: 5px; overflow-x: auto;">
|
||||||
|
<code><?php
|
||||||
|
/**
|
||||||
|
* 訪問者のリアルIPアドレスを取得する関数
|
||||||
|
*/
|
||||||
|
function getRealIP() {
|
||||||
|
// nginx.forwardRealIP.enabled が true の場合、
|
||||||
|
// REMOTE_ADDR に実IPが設定されている
|
||||||
|
return $_SERVER['REMOTE_ADDR'] ?? 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用例
|
||||||
|
$visitorIP = getRealIP();
|
||||||
|
echo "訪問者のIPアドレス: " . $visitorIP;
|
||||||
|
|
||||||
|
// データベースに記録する例
|
||||||
|
// $stmt = $pdo->prepare("INSERT INTO access_log (ip_address, visited_at) VALUES (?, NOW())");
|
||||||
|
// $stmt->execute([$visitorIP]);
|
||||||
|
?></code></pre>
|
||||||
|
|
||||||
|
<h2>⚙️ Helm設定例</h2>
|
||||||
|
<pre style="background: #f4f4f4; padding: 15px; border-radius: 5px; overflow-x: auto;">
|
||||||
|
<code># values.yaml
|
||||||
|
nginx:
|
||||||
|
forwardRealIP:
|
||||||
|
enabled: true
|
||||||
|
header: "X-Forwarded-For"
|
||||||
|
recursive: true
|
||||||
|
trustedProxies:
|
||||||
|
- "10.0.0.0/8"
|
||||||
|
- "172.16.0.0/12"
|
||||||
|
- "192.168.0.0/16"
|
||||||
|
additionalTrustedProxies:
|
||||||
|
- "あなたのLoadBalancerのIPレンジ"</code></pre>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -19,3 +19,45 @@ app.kubernetes.io/instance: {{ .Release.Name }}
|
|||||||
app.kubernetes.io/name: {{ include "phpfpm.name" . }}
|
app.kubernetes.io/name: {{ include "phpfpm.name" . }}
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
{{- end }}
|
{{- 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=<release>)とラベルの組が完全に一致しないようにする。
|
||||||
|
component ラベルだけを足す設計だと、Selenium の Pod も name=phpfpm/instance=<release>
|
||||||
|
を持つため 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 }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Cron(CronJob)用の名前・ラベル(v8.5.10-e)。
|
||||||
|
|
||||||
|
Selenium と同じ理由で、CronJobが生成するPodのラベルにも nginx/php-fpm の
|
||||||
|
Deployment と同じ app.kubernetes.io/name("phpfpm")+ instance を持たせては
|
||||||
|
いけない。同じ組み合わせだとDeploymentのReplicaSetコントローラーが
|
||||||
|
matchLabels(name=phpfpm, instance=<release>)に一致するPodとしてCronJob由来
|
||||||
|
のPodまで対象に含めてしまい、replicaCountとの差分調整でCronJobのPodを
|
||||||
|
意図せず削除する等の事故につながる。name自体をvariant("phpfpm-cron")に
|
||||||
|
することで構造的に衝突を防ぐ。
|
||||||
|
*/}}
|
||||||
|
{{- define "phpfpm.cron.name" -}}
|
||||||
|
{{- printf "%s-cron" (include "phpfpm.name" .) | trunc 63 | trimSuffix "-" -}}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "phpfpm.cron.selectorLabels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "phpfpm.cron.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end }}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
{{- if and .Values.composer.enabled .Values.composer.useComposerJson }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{ include "phpfpm.fullname" . }}-composer-config
|
||||||
|
labels:
|
||||||
|
{{- include "phpfpm.labels" . | nindent 4 }}
|
||||||
|
data:
|
||||||
|
composer.json: |
|
||||||
|
{{ .Values.composer.composerJson | indent 4 }}
|
||||||
|
{{- if .Values.composer.composerLock }}
|
||||||
|
composer.lock: |
|
||||||
|
{{ .Values.composer.composerLock | indent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{{- /*
|
||||||
|
【未使用】このファイルは出力されない。
|
||||||
|
下の if が参照する .Values.nginx.enabled は values.yaml に存在しないため、常に偽になる。
|
||||||
|
実際に使われる nginx 設定は templates/configmap.yaml(deployment.yaml が nginx.conf キーを
|
||||||
|
マウントしている)。カスタム設定として読まれるのは nginx.customConfig.snippet のみで、
|
||||||
|
このファイルだけが読む serverSnippet / httpSnippet は指定しても無視される。
|
||||||
|
nginx の設定を変更する場合は configmap.yaml を編集すること。
|
||||||
|
*/ -}}
|
||||||
|
{{- if .Values.nginx.enabled }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{ include "phpfpm.fullname" . }}-nginx-config
|
||||||
|
labels:
|
||||||
|
{{- include "phpfpm.labels" . | nindent 4 }}
|
||||||
|
data:
|
||||||
|
default.conf: |
|
||||||
|
{{- if or .Values.nginx.forwardRealIP.enabled (and .Values.nginx.customConfig.enabled .Values.nginx.customConfig.httpSnippet) }}
|
||||||
|
# HTTP-level configuration
|
||||||
|
{{- if .Values.nginx.forwardRealIP.enabled }}
|
||||||
|
# Real IP forwarding configuration
|
||||||
|
real_ip_header {{ .Values.nginx.forwardRealIP.header }};
|
||||||
|
{{- if .Values.nginx.forwardRealIP.recursive }}
|
||||||
|
real_ip_recursive on;
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# Trusted proxy networks
|
||||||
|
{{- range .Values.nginx.forwardRealIP.trustedProxies }}
|
||||||
|
set_real_ip_from {{ . }};
|
||||||
|
{{- end }}
|
||||||
|
{{- range .Values.nginx.forwardRealIP.additionalTrustedProxies }}
|
||||||
|
set_real_ip_from {{ . }};
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if and .Values.nginx.customConfig.enabled .Values.nginx.customConfig.httpSnippet }}
|
||||||
|
# Custom HTTP-level configuration
|
||||||
|
{{ .Values.nginx.customConfig.httpSnippet | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 8080;
|
||||||
|
server_name _;
|
||||||
|
root /var/www/html;
|
||||||
|
index index.php index.html;
|
||||||
|
|
||||||
|
# Security headers
|
||||||
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
|
add_header X-Content-Type-Options "nosniff" always;
|
||||||
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
|
||||||
|
{{- if and .Values.nginx.customConfig.enabled .Values.nginx.customConfig.serverSnippet }}
|
||||||
|
# Custom server-level configuration
|
||||||
|
{{ .Values.nginx.customConfig.serverSnippet | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# Health check endpoint
|
||||||
|
location /health {
|
||||||
|
access_log off;
|
||||||
|
return 200 "healthy\n";
|
||||||
|
add_header Content-Type text/plain;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Default location block
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.php?$query_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
# PHP-FPM handler
|
||||||
|
location ~ \.php$ {
|
||||||
|
try_files $uri =404;
|
||||||
|
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||||
|
fastcgi_pass 127.0.0.1:9000;
|
||||||
|
fastcgi_index index.php;
|
||||||
|
include fastcgi_params;
|
||||||
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||||
|
|
||||||
|
{{- if .Values.nginx.forwardRealIP.enabled }}
|
||||||
|
# Pass real IP information to PHP-FPM
|
||||||
|
fastcgi_param REMOTE_ADDR $remote_addr;
|
||||||
|
fastcgi_param HTTP_X_REAL_IP $realip_remote_addr;
|
||||||
|
fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# Standard FastCGI parameters
|
||||||
|
fastcgi_param SERVER_NAME $host;
|
||||||
|
fastcgi_param SERVER_PORT $server_port;
|
||||||
|
fastcgi_param HTTPS $https if_not_empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Deny access to hidden files
|
||||||
|
location ~ /\. {
|
||||||
|
deny all;
|
||||||
|
access_log off;
|
||||||
|
log_not_found off;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
{{- if and .Values.smtp.enabled (not .Values.smtp.existingMsmtprcSecret) }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{ include "phpfpm.fullname" . }}-smtp-config
|
||||||
|
labels:
|
||||||
|
{{- include "phpfpm.labels" . | nindent 4 }}
|
||||||
|
data:
|
||||||
|
msmtprc: |
|
||||||
|
# msmtp設定ファイル
|
||||||
|
# PHPのsendmail_pathから呼び出される
|
||||||
|
|
||||||
|
defaults
|
||||||
|
{{- if .Values.smtp.tls.verify }}
|
||||||
|
tls on
|
||||||
|
tls_trust_file /etc/ssl/certs/ca-certificates.crt
|
||||||
|
{{- else }}
|
||||||
|
tls off
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.smtp.tls.allowSelfSigned }}
|
||||||
|
tls_certcheck off
|
||||||
|
{{- else }}
|
||||||
|
tls_certcheck on
|
||||||
|
{{- end }}
|
||||||
|
{{- if eq .Values.smtp.protocol "starttls" }}
|
||||||
|
# STARTTLS (SMTP + STARTTLS at port 587)
|
||||||
|
protocol smtp
|
||||||
|
{{- else if eq .Values.smtp.protocol "tls" }}
|
||||||
|
# SSL/TLS (SMTPS at port 465)
|
||||||
|
protocol smtps
|
||||||
|
{{- else }}
|
||||||
|
# Auto mode - protocol will be determined by port
|
||||||
|
{{- if eq (int .Values.smtp.port) 465 }}
|
||||||
|
protocol smtps
|
||||||
|
{{- else }}
|
||||||
|
protocol smtp
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
account default
|
||||||
|
host {{ .Values.smtp.host }}
|
||||||
|
port {{ .Values.smtp.port }}
|
||||||
|
{{- if eq .Values.smtp.protocol "starttls" }}
|
||||||
|
protocol smtp
|
||||||
|
{{- else if eq .Values.smtp.protocol "tls" }}
|
||||||
|
protocol smtps
|
||||||
|
{{- else if eq (int .Values.smtp.port) 465 }}
|
||||||
|
protocol smtps
|
||||||
|
{{- else }}
|
||||||
|
protocol smtp
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.smtp.auth.enabled }}
|
||||||
|
auth on
|
||||||
|
user {{ .Values.smtp.auth.username }}
|
||||||
|
passwordeval "cat /etc/smtp-secrets/password"
|
||||||
|
{{- else }}
|
||||||
|
auth off
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
from {{ .Values.smtp.from }}
|
||||||
|
{{- if .Values.smtp.tls.verify }}
|
||||||
|
tls on
|
||||||
|
tls_trust_file /etc/ssl/certs/ca-certificates.crt
|
||||||
|
{{- else }}
|
||||||
|
tls off
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.smtp.tls.allowSelfSigned }}
|
||||||
|
tls_certcheck off
|
||||||
|
{{- else }}
|
||||||
|
tls_certcheck on
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# PHPスクリプトで利用する設定用PHPクラス
|
||||||
|
php-smtp-config.php: |
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PHPからSMTP設定を利用するためのヘルパークラス
|
||||||
|
* 使用例:
|
||||||
|
* SmtpConfig::init();
|
||||||
|
* mail($to, $subject, $body);
|
||||||
|
*
|
||||||
|
* // 別の送信者で上書きする場合:
|
||||||
|
* $headers = [
|
||||||
|
* 'From: custom@example.com',
|
||||||
|
* 'Return-Path: custom@example.com',
|
||||||
|
* ];
|
||||||
|
* mail($to, $subject, $body, implode("\r\n", $headers), '-f custom@example.com');
|
||||||
|
*/
|
||||||
|
class SmtpConfig {
|
||||||
|
private static $initialized = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SMTP設定を初期化
|
||||||
|
* PHP-FPMスタートアップ時に呼び出す
|
||||||
|
*/
|
||||||
|
public static function init() {
|
||||||
|
if (self::$initialized) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PHPメール設定の確認
|
||||||
|
$sendmailPath = ini_get('sendmail_path');
|
||||||
|
if (!empty($sendmailPath)) {
|
||||||
|
error_log("SMTP configured via sendmail_path: " . $sendmailPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定した送信者でメール送信
|
||||||
|
*
|
||||||
|
* @param string $to 受信者アドレス
|
||||||
|
* @param string $subject メール件名
|
||||||
|
* @param string $body メール本文
|
||||||
|
* @param array $headers オプションのヘッダー
|
||||||
|
* @param string $fromAddress 送信元アドレス(オプション)
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function mail($to, $subject, $body, $headers = [], $fromAddress = null) {
|
||||||
|
$headerString = '';
|
||||||
|
if (!empty($headers)) {
|
||||||
|
if (is_array($headers)) {
|
||||||
|
$headerString = implode("\r\n", $headers);
|
||||||
|
} else {
|
||||||
|
$headerString = (string)$headers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 送信元アドレスでmsmtpを呼び出す
|
||||||
|
$parameters = '';
|
||||||
|
if (!empty($fromAddress)) {
|
||||||
|
// メールヘッダーにFromを追加
|
||||||
|
if (!preg_match('/^From:/mi', $headerString)) {
|
||||||
|
$headerString .= (!empty($headerString) ? "\r\n" : '') . "From: " . $fromAddress;
|
||||||
|
}
|
||||||
|
// sendmail互換パラメータで送信者を指定
|
||||||
|
$parameters = '-f ' . escapeshellarg($fromAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mail($to, $subject, $body, $headerString, $parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PHPのメール設定を取得
|
||||||
|
*/
|
||||||
|
public static function getConfig() {
|
||||||
|
return [
|
||||||
|
'sendmail_path' => ini_get('sendmail_path'),
|
||||||
|
'sendmail_from' => ini_get('sendmail_from'),
|
||||||
|
'SMTP' => ini_get('SMTP'),
|
||||||
|
'smtp_port' => ini_get('smtp_port'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{- end }}
|
||||||
@@ -29,6 +29,25 @@ data:
|
|||||||
sendfile on;
|
sendfile on;
|
||||||
keepalive_timeout 65;
|
keepalive_timeout 65;
|
||||||
|
|
||||||
|
{{- if .Values.nginx.forwardRealIP.enabled }}
|
||||||
|
# ========================================
|
||||||
|
# Real IP forwarding configuration
|
||||||
|
# ========================================
|
||||||
|
# クライアントの実IPアドレスを取得する設定
|
||||||
|
real_ip_header {{ .Values.nginx.forwardRealIP.header }};
|
||||||
|
{{- if .Values.nginx.forwardRealIP.recursive }}
|
||||||
|
real_ip_recursive on;
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# 信頼するプロキシのネットワーク範囲
|
||||||
|
{{- range .Values.nginx.forwardRealIP.trustedProxies }}
|
||||||
|
set_real_ip_from {{ . }};
|
||||||
|
{{- end }}
|
||||||
|
{{- range .Values.nginx.forwardRealIP.additionalTrustedProxies }}
|
||||||
|
set_real_ip_from {{ . }};
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
server_name localhost;
|
server_name localhost;
|
||||||
@@ -36,6 +55,18 @@ data:
|
|||||||
root /var/www/html;
|
root /var/www/html;
|
||||||
index index.php index.html index.htm;
|
index index.php index.html index.htm;
|
||||||
|
|
||||||
|
# アップロード可能な最大サイズ(PHP側のupload_max_filesize/post_max_sizeと連動)
|
||||||
|
client_max_body_size {{ .Values.uploadMaxSize }};
|
||||||
|
|
||||||
|
# sitemap.xml のContent-Typeを明示的に指定
|
||||||
|
# 標準のmime.typesでは .xml は text/xml 扱いでcharsetが付かず、
|
||||||
|
# ブラウザやSearch Consoleが正しく解釈できない場合があるため
|
||||||
|
location = /sitemap.xml {
|
||||||
|
types { }
|
||||||
|
default_type "application/xml; charset=utf-8";
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.php?$query_string;
|
try_files $uri $uri/ /index.php?$query_string;
|
||||||
}
|
}
|
||||||
@@ -45,6 +76,12 @@ data:
|
|||||||
fastcgi_pass 127.0.0.1:9000;
|
fastcgi_pass 127.0.0.1:9000;
|
||||||
fastcgi_index index.php;
|
fastcgi_index index.php;
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
|
{{- if .Values.nginx.forwardRealIP.enabled }}
|
||||||
|
# リアルIP情報をPHP-FPMに渡す
|
||||||
|
fastcgi_param REMOTE_ADDR $remote_addr;
|
||||||
|
fastcgi_param HTTP_X_REAL_IP $remote_addr;
|
||||||
|
fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
|
||||||
|
{{- end }}
|
||||||
}
|
}
|
||||||
|
|
||||||
error_page 500 502 503 504 /50x.html;
|
error_page 500 502 503 504 /50x.html;
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
{{- range .Values.cron.jobs }}
|
||||||
|
---
|
||||||
|
# CronJobのPodは、nginx/php-fpmのDeploymentとは別のReplicaSetに属するため、
|
||||||
|
# jobTemplate.spec.template.metadata.labels には phpfpm.cron.selectorLabels
|
||||||
|
# (app.kubernetes.io/name: <chart>-cron)を使う。ここで通常の
|
||||||
|
# phpfpm.selectorLabels(name: phpfpm)を使ってしまうと、nginx/php-fpm
|
||||||
|
# DeploymentのmatchLabelsと一致するPodが増え、ReplicaSetコントローラーが
|
||||||
|
# replicaCountとの差分調整でCronJob由来のPodを意図せず削除する事故につながる
|
||||||
|
# (Selenium分離(v8.5.10-b)と同じ理由)。
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: {{ printf "%s-cron-%s" (include "phpfpm.fullname" $) .name | trunc 52 | trimSuffix "-" }}
|
||||||
|
labels:
|
||||||
|
{{- include "phpfpm.labels" $ | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: cron
|
||||||
|
spec:
|
||||||
|
schedule: {{ .schedule | quote }}
|
||||||
|
{{- if .timeZone }}
|
||||||
|
timeZone: {{ .timeZone | quote }}
|
||||||
|
{{- end }}
|
||||||
|
concurrencyPolicy: {{ .concurrencyPolicy | default "Forbid" }}
|
||||||
|
{{- if hasKey . "suspend" }}
|
||||||
|
suspend: {{ .suspend }}
|
||||||
|
{{- end }}
|
||||||
|
successfulJobsHistoryLimit: {{ .successfulJobsHistoryLimit | default 3 }}
|
||||||
|
failedJobsHistoryLimit: {{ .failedJobsHistoryLimit | default 1 }}
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
{{- if .activeDeadlineSeconds }}
|
||||||
|
activeDeadlineSeconds: {{ .activeDeadlineSeconds }}
|
||||||
|
{{- end }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
{{- include "phpfpm.cron.selectorLabels" $ | nindent 12 }}
|
||||||
|
app.kubernetes.io/component: cron
|
||||||
|
spec:
|
||||||
|
restartPolicy: {{ .restartPolicy | default "OnFailure" }}
|
||||||
|
containers:
|
||||||
|
- name: cron
|
||||||
|
image: "{{ $.Values.image.php.registry }}/{{ $.Values.image.php.repository }}:{{ $.Values.image.php.tag }}"
|
||||||
|
imagePullPolicy: {{ $.Values.image.php.pullPolicy }}
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
echo "Starting cron job: {{ .name }}"
|
||||||
|
|
||||||
|
{{- if $.Values.smtp.enabled }}
|
||||||
|
# ========================================
|
||||||
|
# SMTP設定(msmtp) — templates/deployment.yaml のSMTP設定と同じ内容。
|
||||||
|
# 変更する場合は両方のファイルを揃えること。
|
||||||
|
# ========================================
|
||||||
|
echo "Installing msmtp for mail sending..."
|
||||||
|
apk add --no-cache msmtp ca-certificates
|
||||||
|
|
||||||
|
cp /etc/smtp-config/msmtprc /etc/msmtprc
|
||||||
|
chmod 644 /etc/msmtprc
|
||||||
|
|
||||||
|
cat > /usr/local/etc/php/conf.d/99-smtp.ini << 'PHP_SMTP_EOF'
|
||||||
|
sendmail_path = "/usr/bin/msmtp -t"
|
||||||
|
sendmail_from = "{{ $.Values.smtp.from }}"
|
||||||
|
PHP_SMTP_EOF
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
echo "Running: {{ .command }}"
|
||||||
|
{{ .command }}
|
||||||
|
{{- with (.resources | default $.Values.resources.phpfpm) }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml . | nindent 16 }}
|
||||||
|
{{- end }}
|
||||||
|
volumeMounts:
|
||||||
|
# php-fpmコンテナと同様、PVCルートを/var/wwwにマウントする。
|
||||||
|
# html/ は公開コード、それ以外は非公開ファイルの置き場として利用できる。
|
||||||
|
- name: app-storage
|
||||||
|
mountPath: /var/www
|
||||||
|
{{- if $.Values.smtp.enabled }}
|
||||||
|
- name: smtp-config
|
||||||
|
mountPath: /etc/smtp-config
|
||||||
|
readOnly: true
|
||||||
|
{{- if and $.Values.smtp.auth.enabled (not $.Values.smtp.existingMsmtprcSecret) }}
|
||||||
|
- name: smtp-secrets
|
||||||
|
mountPath: /etc/smtp-secrets
|
||||||
|
readOnly: true
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
env:
|
||||||
|
{{- if $.Values.externalDatabase.enabled }}
|
||||||
|
- name: DB_HOST
|
||||||
|
value: {{ $.Values.externalDatabase.host | quote }}
|
||||||
|
- name: DB_PORT
|
||||||
|
value: {{ $.Values.externalDatabase.port | quote }}
|
||||||
|
- name: DB_NAME
|
||||||
|
value: {{ $.Values.externalDatabase.database | quote }}
|
||||||
|
- name: DB_USER
|
||||||
|
value: {{ $.Values.externalDatabase.username | quote }}
|
||||||
|
- name: DB_PASS
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ include "phpfpm.fullname" $ }}-db-secret
|
||||||
|
key: {{ include "phpfpm.fullname" $ }}-db-key
|
||||||
|
{{- end }}
|
||||||
|
{{- range $key, $value := $.Values.phpEnv }}
|
||||||
|
- name: {{ $key }}
|
||||||
|
value: {{ $value | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if $.Values.selenium.enabled }}
|
||||||
|
- name: SELENIUM_URL
|
||||||
|
value: "http://{{ include "phpfpm.fullname" $ }}-selenium:4444/wd/hub"
|
||||||
|
{{- end }}
|
||||||
|
{{- with $.Values.extraEnv }}
|
||||||
|
{{- toYaml . | nindent 16 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with $.Values.extraEnvFrom }}
|
||||||
|
envFrom:
|
||||||
|
{{- toYaml . | nindent 16 }}
|
||||||
|
{{- end }}
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
dnsConfig:
|
||||||
|
options:
|
||||||
|
- name: ndots
|
||||||
|
value: "1"
|
||||||
|
volumes:
|
||||||
|
- name: app-storage
|
||||||
|
{{- if $.Values.persistence.enabled }}
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ include "phpfpm.fullname" $ }}-pvc
|
||||||
|
{{- else }}
|
||||||
|
emptyDir: {}
|
||||||
|
{{- end }}
|
||||||
|
{{- if $.Values.smtp.enabled }}
|
||||||
|
- name: smtp-config
|
||||||
|
{{- if $.Values.smtp.existingMsmtprcSecret }}
|
||||||
|
secret:
|
||||||
|
secretName: {{ $.Values.smtp.existingMsmtprcSecret }}
|
||||||
|
items:
|
||||||
|
- key: {{ $.Values.smtp.existingMsmtprcSecretKey | default "msmtprc" }}
|
||||||
|
path: msmtprc
|
||||||
|
{{- else }}
|
||||||
|
configMap:
|
||||||
|
name: {{ include "phpfpm.fullname" $ }}-smtp-config
|
||||||
|
items:
|
||||||
|
- key: msmtprc
|
||||||
|
path: msmtprc
|
||||||
|
{{- end }}
|
||||||
|
{{- if and $.Values.smtp.auth.enabled (not $.Values.smtp.existingMsmtprcSecret) }}
|
||||||
|
- name: smtp-secrets
|
||||||
|
secret:
|
||||||
|
secretName: {{ $.Values.smtp.auth.existingSecret | default (printf "%s-smtp" (include "phpfpm.fullname" $)) }}
|
||||||
|
items:
|
||||||
|
- key: {{ $.Values.smtp.auth.existingSecretKey | default "password" }}
|
||||||
|
path: password
|
||||||
|
mode: 0644
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
{{- if .Values.selenium.enabled }}
|
||||||
|
# Selenium を nginx/php-fpm と別 Deployment にする理由(v8.5.10-b):
|
||||||
|
#
|
||||||
|
# 以前は selenium/standalone-chromium を nginx・php-fpm と同一 Pod のサイドカー
|
||||||
|
# コンテナとして起動していた。Kubernetes は Pod の Ready 条件を「全コンテナが Ready」
|
||||||
|
# の AND で判定するため、readinessProbe を持たないコンテナは「Running であれば Ready」
|
||||||
|
# として扱われる一方、CrashLoopBackOff で Waiting/Terminated を繰り返す間は Ready=false
|
||||||
|
# になる。この間 Pod 全体が Service の Endpoints から外れるため、Selenium コンテナ
|
||||||
|
# だけが不安定(起動失敗・OOM等)でも、Selenium を全く使わない静的ページの配信まで
|
||||||
|
# 巻き込まれてサービス全体が完全停止していた。
|
||||||
|
#
|
||||||
|
# Selenium を独立した Deployment/Service に分離することで、Selenium の不調が
|
||||||
|
# nginx/php-fpm Pod の Ready 状態に一切影響しなくなり、スクレイピング機能のみが
|
||||||
|
# 影響を受け、サイト自体は表示され続ける。
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "phpfpm.fullname" . }}-selenium
|
||||||
|
labels:
|
||||||
|
{{- include "phpfpm.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: selenium
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.selenium.replicaCount | default 1 }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "phpfpm.selenium.selectorLabels" . | nindent 6 }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
{{- include "phpfpm.selenium.selectorLabels" . | nindent 8 }}
|
||||||
|
app.kubernetes.io/component: selenium
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: selenium
|
||||||
|
image: "{{ .Values.image.selenium.registry }}/{{ .Values.image.selenium.repository }}:{{ .Values.image.selenium.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.selenium.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- containerPort: 4444 # Selenium用ポート
|
||||||
|
{{- with .Values.selenium.resources }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.selenium.mountHtml }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: app-storage
|
||||||
|
mountPath: /var/www/html
|
||||||
|
subPath: html
|
||||||
|
{{- end }}
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
dnsConfig:
|
||||||
|
options:
|
||||||
|
- name: ndots
|
||||||
|
value: "1"
|
||||||
|
{{- if .Values.selenium.mountHtml }}
|
||||||
|
volumes:
|
||||||
|
- name: app-storage
|
||||||
|
# 別 Pod から同じ PVC の html/ サブパスを読み書きするため、
|
||||||
|
# persistence.accessMode を ReadWriteMany にする必要がある
|
||||||
|
# (NFS バックエンドの StorageClass なら対応可能)。
|
||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ include "phpfpm.fullname" . }}-pvc
|
||||||
|
{{- else }}
|
||||||
|
emptyDir: {}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
+314
-30
@@ -7,12 +7,18 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
replicas: {{ .Values.replicaCount }}
|
replicas: {{ .Values.replicaCount }}
|
||||||
selector:
|
selector:
|
||||||
|
# 注意: Deployment.spec.selector は作成後 immutable。既存リリースの
|
||||||
|
# アップグレードを壊さないため、ここに app.kubernetes.io/component は
|
||||||
|
# 追加しない(component ラベルは下の pod template と Service の
|
||||||
|
# selector のみに付与する。template.metadata.labels は matchLabels の
|
||||||
|
# superset であればよいため、追加ラベルを持たせても問題ない)。
|
||||||
matchLabels:
|
matchLabels:
|
||||||
{{- include "phpfpm.selectorLabels" . | nindent 6 }}
|
{{- include "phpfpm.selectorLabels" . | nindent 6 }}
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
{{- include "phpfpm.selectorLabels" . | nindent 8 }}
|
{{- include "phpfpm.selectorLabels" . | nindent 8 }}
|
||||||
|
app.kubernetes.io/component: web
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: nginx
|
- name: nginx
|
||||||
@@ -20,6 +26,10 @@ spec:
|
|||||||
imagePullPolicy: {{ .Values.image.nginx.pullPolicy }}
|
imagePullPolicy: {{ .Values.image.nginx.pullPolicy }}
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 80
|
- containerPort: 80
|
||||||
|
{{- with .Values.resources.nginx }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: app-storage
|
- name: app-storage
|
||||||
mountPath: /var/www/html
|
mountPath: /var/www/html
|
||||||
@@ -34,30 +44,262 @@ spec:
|
|||||||
- sh
|
- sh
|
||||||
- -c
|
- -c
|
||||||
- |
|
- |
|
||||||
echo "Starting PHP-FPM with conditional logic..."
|
echo "Starting PHP-FPM setup process..."
|
||||||
{{- if or .Values.selenium.enabled .Values.externalDatabase.enabled }}
|
|
||||||
(
|
# ========================================
|
||||||
{{- if .Values.selenium.enabled }}
|
# アップロードサイズ上限(nginxのclient_max_body_sizeと連動)
|
||||||
echo "Installing selenium dependencies..."
|
# ========================================
|
||||||
apk add --no-cache curl zip libzip-dev && \
|
cat > /usr/local/etc/php/conf.d/99-uploads.ini << 'UPLOADS_INI_EOF'
|
||||||
docker-php-ext-install zip && \
|
upload_max_filesize = {{ .Values.uploadMaxSize }}
|
||||||
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \
|
post_max_size = {{ .Values.uploadMaxSize }}
|
||||||
composer require php-webdriver/webdriver
|
UPLOADS_INI_EOF
|
||||||
{{- end }}
|
|
||||||
{{- if .Values.externalDatabase.enabled }}
|
{{- if or .Values.composer.enabled .Values.selenium.enabled .Values.externalDatabase.enabled .Values.python.enabled }}
|
||||||
echo "Installing pdo_mysql for PHP 8.4 Alpine..."
|
# ========================================
|
||||||
apk add --no-cache mysql-client mysql-dev
|
# APKパッケージのインストール
|
||||||
docker-php-ext-install pdo_mysql
|
# ========================================
|
||||||
{{- end }}
|
APK_PACKAGES=""
|
||||||
)
|
|
||||||
|
{{- if or .Values.composer.enabled .Values.selenium.enabled }}
|
||||||
|
# Composer本体に必要なパッケージ
|
||||||
|
APK_PACKAGES="$APK_PACKAGES curl zip libzip-dev"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
php-fpm
|
|
||||||
|
{{- if .Values.externalDatabase.enabled }}
|
||||||
|
# MySQL/MariaDB接続に必要なパッケージ
|
||||||
|
APK_PACKAGES="$APK_PACKAGES mysql-client mysql-dev"
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.smtp.enabled }}
|
||||||
|
# SMTP送信に必要なパッケージ
|
||||||
|
APK_PACKAGES="$APK_PACKAGES msmtp ca-certificates"
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.python.enabled }}
|
||||||
|
# Python本体に必要なパッケージ
|
||||||
|
APK_PACKAGES="$APK_PACKAGES python3 py3-pip"
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.composer.additionalApkPackages }}
|
||||||
|
# ユーザー指定の追加APKパッケージ(Composer用)
|
||||||
|
{{- range .Values.composer.additionalApkPackages }}
|
||||||
|
APK_PACKAGES="$APK_PACKAGES {{ . }}"
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.python.additionalApkPackages }}
|
||||||
|
# ユーザー指定の追加APKパッケージ(Python用)
|
||||||
|
{{- range .Values.python.additionalApkPackages }}
|
||||||
|
APK_PACKAGES="$APK_PACKAGES {{ . }}"
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# PHP拡張(gd / mbstring)の依存パッケージを自動的に追加
|
||||||
|
{{- if .Values.composer.additionalPhpExtensions }}
|
||||||
|
for ext in {{ join " " .Values.composer.additionalPhpExtensions }}; do
|
||||||
|
if [ "$ext" = "gd" ]; then
|
||||||
|
echo "GD extension detected, adding required dependencies..."
|
||||||
|
APK_PACKAGES="$APK_PACKAGES libpng-dev libjpeg-turbo-dev freetype-dev"
|
||||||
|
fi
|
||||||
|
if [ "$ext" = "mbstring" ]; then
|
||||||
|
echo "mbstring extension detected, adding required dependencies..."
|
||||||
|
APK_PACKAGES="$APK_PACKAGES oniguruma-dev"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
if [ -n "$APK_PACKAGES" ]; then
|
||||||
|
echo "Installing APK packages: $APK_PACKAGES"
|
||||||
|
apk add --no-cache $APK_PACKAGES
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# PHP拡張のインストール
|
||||||
|
# ========================================
|
||||||
|
{{- if or .Values.composer.enabled .Values.selenium.enabled }}
|
||||||
|
echo "Installing PHP zip extension..."
|
||||||
|
docker-php-ext-install zip
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.externalDatabase.enabled }}
|
||||||
|
echo "Installing pdo_mysql extension..."
|
||||||
|
docker-php-ext-install pdo_mysql
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.composer.additionalPhpExtensions }}
|
||||||
|
echo "Installing additional PHP extensions..."
|
||||||
|
{{- range .Values.composer.additionalPhpExtensions }}
|
||||||
|
docker-php-ext-install {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
# ========================================
|
||||||
|
# Composerのインストールと実行
|
||||||
|
# ========================================
|
||||||
|
{{- if or .Values.composer.enabled .Values.selenium.enabled }}
|
||||||
|
echo "Installing Composer..."
|
||||||
|
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||||
|
|
||||||
|
# Composer導入先(デフォルトはWebルート外の /composer)
|
||||||
|
# PHPからは require_once '{{ .Values.composer.workingDir | default "/composer" }}/vendor/autoload.php'; で読み込む
|
||||||
|
mkdir -p {{ .Values.composer.workingDir | default "/composer" }}
|
||||||
|
cd {{ .Values.composer.workingDir | default "/composer" }}
|
||||||
|
|
||||||
|
{{- if .Values.composer.enabled }}
|
||||||
|
# ユーザー定義のComposer設定
|
||||||
|
{{- if .Values.composer.useComposerJson }}
|
||||||
|
# composer.jsonファイルを使用
|
||||||
|
echo "Creating composer.json from values..."
|
||||||
|
cat > composer.json << 'COMPOSER_JSON_EOF'
|
||||||
|
{{- .Values.composer.composerJson | trim | nindent 14 }}
|
||||||
|
COMPOSER_JSON_EOF
|
||||||
|
|
||||||
|
{{- if .Values.composer.composerLock }}
|
||||||
|
echo "Creating composer.lock from values..."
|
||||||
|
cat > composer.lock << 'COMPOSER_LOCK_EOF'
|
||||||
|
{{- .Values.composer.composerLock | trim | nindent 14 }}
|
||||||
|
COMPOSER_LOCK_EOF
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
echo "Running composer install..."
|
||||||
|
composer install {{ .Values.composer.installOptions }}
|
||||||
|
|
||||||
|
{{- else if .Values.composer.packages }}
|
||||||
|
# パッケージリストから直接インストール
|
||||||
|
echo "Installing Composer packages..."
|
||||||
|
{{- range .Values.composer.packages }}
|
||||||
|
composer require {{ . }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.composer.installOptions }}
|
||||||
|
# オプティマイズ実行
|
||||||
|
composer install {{ .Values.composer.installOptions }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- else }}
|
||||||
|
# 旧Webルート(/var/www/html)に composer.json がある場合は移行(v8.5.6-a以前からのアップグレード対応)
|
||||||
|
if [ ! -f composer.json ] && [ -f /var/www/html/composer.json ]; then
|
||||||
|
echo "Migrating legacy composer files from /var/www/html to $(pwd)..."
|
||||||
|
mv /var/www/html/composer.json ./composer.json
|
||||||
|
if [ -f /var/www/html/composer.lock ]; then mv /var/www/html/composer.lock ./composer.lock; fi
|
||||||
|
if [ -d /var/www/html/vendor ]; then mv /var/www/html/vendor ./vendor; fi
|
||||||
|
fi
|
||||||
|
# composer.jsonが既に存在する場合はそれを使用
|
||||||
|
if [ -f composer.json ]; then
|
||||||
|
echo "Found existing composer.json, running composer install..."
|
||||||
|
composer install {{ .Values.composer.installOptions }}
|
||||||
|
else
|
||||||
|
echo "No composer configuration found, skipping package installation"
|
||||||
|
fi
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.selenium.enabled }}
|
||||||
|
# Selenium用のパッケージインストール(レガシー互換性)
|
||||||
|
echo "Installing Selenium WebDriver package..."
|
||||||
|
composer require php-webdriver/webdriver
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.python.enabled }}
|
||||||
|
{{- $pythonDir := .Values.python.venvDir | default "/venv" }}
|
||||||
|
# ========================================
|
||||||
|
# Python仮想環境のセットアップ
|
||||||
|
# ========================================
|
||||||
|
echo "Setting up Python virtual environment..."
|
||||||
|
|
||||||
|
# Python導入先(デフォルトはWebルート外の /venv、Composerと同様の使い捨て領域)
|
||||||
|
# PHPからの呼び出し方: exec('{{ $pythonDir }}/bin/python3 /path/to/script.py 2>&1', $output, $exitCode);
|
||||||
|
python3 -m venv {{ $pythonDir }}
|
||||||
|
|
||||||
|
{{- if .Values.python.useRequirementsTxt }}
|
||||||
|
echo "Creating requirements.txt from values..."
|
||||||
|
cat > /tmp/requirements.txt << 'REQUIREMENTS_TXT_EOF'
|
||||||
|
{{- .Values.python.requirementsTxt | trim | nindent 14 }}
|
||||||
|
REQUIREMENTS_TXT_EOF
|
||||||
|
|
||||||
|
echo "Installing Python packages from requirements.txt..."
|
||||||
|
{{ $pythonDir }}/bin/pip install {{ .Values.python.installOptions }} -r /tmp/requirements.txt
|
||||||
|
rm -f /tmp/requirements.txt
|
||||||
|
|
||||||
|
{{- else if .Values.python.packages }}
|
||||||
|
echo "Installing Python packages..."
|
||||||
|
{{- range .Values.python.packages }}
|
||||||
|
{{ $pythonDir }}/bin/pip install {{ $.Values.python.installOptions }} "{{ . }}"
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- else }}
|
||||||
|
echo "No Python package configuration found, virtual environment created without additional packages"
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.smtp.enabled }}
|
||||||
|
# ========================================
|
||||||
|
# SMTP設定(msmtp)
|
||||||
|
# ========================================
|
||||||
|
echo "Configuring SMTP for mail sending..."
|
||||||
|
|
||||||
|
# msmtprc設定ファイルをコピー
|
||||||
|
# msmtpはPHP-FPMワーカー(www-data等の非root)から実行されるため、
|
||||||
|
# rootが作成するこのファイルも読み取り可にする必要がある
|
||||||
|
# (実パスワードはpasswordeval経由で別ファイルから取得するため、
|
||||||
|
# msmtprc自体に平文パスワードは含まれない)
|
||||||
|
cp /etc/smtp-config/msmtprc /etc/msmtprc
|
||||||
|
chmod 644 /etc/msmtprc
|
||||||
|
|
||||||
|
# PHP設定をphp.ini.d/に作成
|
||||||
|
cat > /usr/local/etc/php/conf.d/99-smtp.ini << 'PHP_SMTP_EOF'
|
||||||
|
; SMTP設定 - msmtp経由でメール送信
|
||||||
|
sendmail_path = "/usr/bin/msmtp -t"
|
||||||
|
sendmail_from = "{{ .Values.smtp.from }}"
|
||||||
|
PHP_SMTP_EOF
|
||||||
|
|
||||||
|
echo "SMTP configured:"
|
||||||
|
echo " Host: {{ .Values.smtp.host }}:{{ .Values.smtp.port }}"
|
||||||
|
echo " Protocol: {{ .Values.smtp.protocol }}"
|
||||||
|
echo " From: {{ .Values.smtp.from }}"
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
echo "Setup complete, starting PHP-FPM..."
|
||||||
|
# exec で php-fpm をコンテナの PID1 に置き換える。
|
||||||
|
# 目的: setup シェルを介さず php-fpm 自身が SIGTERM/SIGKILL を直接受け取れる
|
||||||
|
# ようにする。シェルは既定で子プロセスへシグナルを転送しないため、exec せず
|
||||||
|
# `php-fpm`(子)のまま起動すると、コンテナ再起動時にシェル(PID1)だけが落ちて
|
||||||
|
# 旧 php-fpm が一時的に残存し、9000 を握ったまま次回起動が
|
||||||
|
# 「unable to bind ... '9000': Address in use」で失敗して CrashLoopBackOff に陥る。
|
||||||
|
# exec すれば php-fpm が PID1 になり、停止時に 9000 が確実に解放される。
|
||||||
|
# -F(--nodaemonize): 設定に依存せず必ずフォアグラウンドで起動する
|
||||||
|
# (デーモン化して master が背後に残る事故を防ぐ)。
|
||||||
|
exec php-fpm -F
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 9000 # PHP-FPMは9000ポートでリッスン
|
- containerPort: 9000 # PHP-FPMは9000ポートでリッスン
|
||||||
|
{{- with .Values.resources.phpfpm }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
|
# PVCルートを /var/www にマウント
|
||||||
|
# - /var/www/html のみ nginx が公開(nginx側は html サブパスだけをマウント)
|
||||||
|
# - それ以外(/var/www/<任意>)は非公開ファイルの格納先として利用可能
|
||||||
|
# ※ Composer導入先(デフォルト /composer)は意図的にマウントしない:
|
||||||
|
# Pod再起動のたびにクリーンな環境へ再構築される使い捨て領域とする
|
||||||
- name: app-storage
|
- name: app-storage
|
||||||
mountPath: /var/www/html
|
mountPath: /var/www
|
||||||
subPath: html
|
{{- if and .Values.composer.enabled .Values.composer.useComposerJson }}
|
||||||
|
- name: composer-config
|
||||||
|
mountPath: /tmp/composer-init
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.smtp.enabled }}
|
||||||
|
- name: smtp-config
|
||||||
|
mountPath: /etc/smtp-config
|
||||||
|
readOnly: true
|
||||||
|
{{- if and .Values.smtp.auth.enabled (not .Values.smtp.existingMsmtprcSecret) }}
|
||||||
|
- name: smtp-secrets
|
||||||
|
mountPath: /etc/smtp-secrets
|
||||||
|
readOnly: true
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
env:
|
env:
|
||||||
{{- if .Values.externalDatabase.enabled }}
|
{{- if .Values.externalDatabase.enabled }}
|
||||||
- name: DB_HOST
|
- name: DB_HOST
|
||||||
@@ -74,17 +316,25 @@ spec:
|
|||||||
name: {{ include "phpfpm.fullname" . }}-db-secret
|
name: {{ include "phpfpm.fullname" . }}-db-secret
|
||||||
key: {{ include "phpfpm.fullname" . }}-db-key
|
key: {{ include "phpfpm.fullname" . }}-db-key
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.selenium.enabled }}
|
{{- range $key, $value := .Values.phpEnv }}
|
||||||
- name: selenium
|
- name: {{ $key }}
|
||||||
image: "{{ .Values.image.selenium.registry }}/{{ .Values.image.selenium.repository }}:{{ .Values.image.selenium.tag }}"
|
value: {{ $value | quote }}
|
||||||
imagePullPolicy: {{ .Values.image.selenium.pullPolicy }}
|
{{- end }}
|
||||||
ports:
|
{{- if .Values.selenium.enabled }}
|
||||||
- containerPort: 4444 # Selenium用ポート
|
# Selenium は別 Deployment/Service(templates/deployment-selenium.yaml)として
|
||||||
volumeMounts:
|
# 稼働する(v8.5.10-b 以降。selenium.enabled=true の Pod と同居させない設計に変更)。
|
||||||
- name: app-storage
|
# phpEnv に SELENIUM_URL を書いても、この行が env リストの後方にあるため
|
||||||
mountPath: /var/www/html
|
# 最終的にこちらが優先される(Kubernetes は同名 env の重複時、後方の値を採用する)。
|
||||||
subPath: html
|
- name: SELENIUM_URL
|
||||||
{{- end }}
|
value: "http://{{ include "phpfpm.fullname" . }}-selenium:4444/wd/hub"
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.extraEnv }}
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.extraEnvFrom }}
|
||||||
|
envFrom:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
dnsPolicy: ClusterFirst
|
dnsPolicy: ClusterFirst
|
||||||
dnsConfig:
|
dnsConfig:
|
||||||
options:
|
options:
|
||||||
@@ -101,3 +351,37 @@ spec:
|
|||||||
- name: nginx-config
|
- name: nginx-config
|
||||||
configMap:
|
configMap:
|
||||||
name: {{ include "phpfpm.fullname" . }}-nginx-config
|
name: {{ include "phpfpm.fullname" . }}-nginx-config
|
||||||
|
{{- if and .Values.composer.enabled .Values.composer.useComposerJson }}
|
||||||
|
- name: composer-config
|
||||||
|
configMap:
|
||||||
|
name: {{ include "phpfpm.fullname" . }}-composer-config
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.smtp.enabled }}
|
||||||
|
- name: smtp-config
|
||||||
|
{{- if .Values.smtp.existingMsmtprcSecret }}
|
||||||
|
# 完成済み msmtprc を持つ既存 Secret(secret-manager の cred-* 等)を利用
|
||||||
|
secret:
|
||||||
|
secretName: {{ .Values.smtp.existingMsmtprcSecret }}
|
||||||
|
items:
|
||||||
|
- key: {{ .Values.smtp.existingMsmtprcSecretKey | default "msmtprc" }}
|
||||||
|
path: msmtprc
|
||||||
|
{{- else }}
|
||||||
|
configMap:
|
||||||
|
name: {{ include "phpfpm.fullname" . }}-smtp-config
|
||||||
|
items:
|
||||||
|
- key: msmtprc
|
||||||
|
path: msmtprc
|
||||||
|
{{- end }}
|
||||||
|
{{- if and .Values.smtp.auth.enabled (not .Values.smtp.existingMsmtprcSecret) }}
|
||||||
|
- name: smtp-secrets
|
||||||
|
secret:
|
||||||
|
secretName: {{ .Values.smtp.auth.existingSecret | default (printf "%s-smtp" (include "phpfpm.fullname" .)) }}
|
||||||
|
items:
|
||||||
|
- key: {{ .Values.smtp.auth.existingSecretKey | default "password" }}
|
||||||
|
path: password
|
||||||
|
# 0600だとSecretボリュームの所有者はroot、
|
||||||
|
# msmtpはPHP-FPMワーカー(www-data等の非root)から実行されるため読めない
|
||||||
|
# → 全ユーザー読み取り可にする(ボリュームはPod内にしか存在しないため許容範囲)
|
||||||
|
mode: 0644
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -6,7 +6,9 @@ metadata:
|
|||||||
labels:
|
labels:
|
||||||
{{- include "phpfpm.labels" . | nindent 4 }}
|
{{- include "phpfpm.labels" . | nindent 4 }}
|
||||||
annotations:
|
annotations:
|
||||||
{{- toYaml .Values.ingress.annotations | nindent 4 }}
|
{{- /* uploadMaxSize を ingress-nginx の proxy-body-size に自動反映(明示指定があればそちらを優先) */}}
|
||||||
|
{{- $ingressAnnotations := merge (deepCopy .Values.ingress.annotations) (dict "nginx.ingress.kubernetes.io/proxy-body-size" .Values.uploadMaxSize) }}
|
||||||
|
{{- toYaml $ingressAnnotations | nindent 4 }}
|
||||||
spec:
|
spec:
|
||||||
{{- if .Values.ingress.className }}
|
{{- if .Values.ingress.className }}
|
||||||
ingressClassName: {{ .Values.ingress.className }}
|
ingressClassName: {{ .Values.ingress.className }}
|
||||||
@@ -29,7 +31,9 @@ spec:
|
|||||||
{{- if .Values.ingress.tls }}
|
{{- if .Values.ingress.tls }}
|
||||||
tls:
|
tls:
|
||||||
{{- range .Values.ingress.tls }}
|
{{- range .Values.ingress.tls }}
|
||||||
- secretName: {{ .secretName }}
|
{{- /* secretName省略時は、このエントリの最初のhostから自動生成する(例: example.tld → example-tld-tls)。
|
||||||
|
明示的に指定した場合はそちらを優先する。 */}}
|
||||||
|
- secretName: {{ .secretName | default (printf "%s-tls" ((first .hosts) | replace "." "-")) }}
|
||||||
hosts:
|
hosts:
|
||||||
{{- range .hosts }}
|
{{- range .hosts }}
|
||||||
- {{ . }}
|
- {{ . }}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{{- if and .Values.smtp.enabled (not .Values.smtp.existingMsmtprcSecret) (not .Values.smtp.auth.existingSecret) }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: {{ include "phpfpm.fullname" . }}-smtp
|
||||||
|
labels:
|
||||||
|
{{- include "phpfpm.labels" . | nindent 4 }}
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
{{- if .Values.smtp.auth.enabled }}
|
||||||
|
password: {{ .Values.smtp.auth.password | b64enc }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
{{- if .Values.selenium.enabled }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "phpfpm.fullname" . }}-selenium
|
||||||
|
labels:
|
||||||
|
{{- include "phpfpm.labels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: selenium
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
ports:
|
||||||
|
- port: 4444
|
||||||
|
targetPort: 4444
|
||||||
|
protocol: TCP
|
||||||
|
name: selenium
|
||||||
|
selector:
|
||||||
|
{{- include "phpfpm.selenium.selectorLabels" . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
@@ -13,3 +13,4 @@ spec:
|
|||||||
name: http
|
name: http
|
||||||
selector:
|
selector:
|
||||||
{{- include "phpfpm.selectorLabels" . | nindent 4 }}
|
{{- include "phpfpm.selectorLabels" . | nindent 4 }}
|
||||||
|
app.kubernetes.io/component: web
|
||||||
|
|||||||
+319
-21
@@ -4,46 +4,59 @@ image:
|
|||||||
nginx:
|
nginx:
|
||||||
registry: docker.io
|
registry: docker.io
|
||||||
repository: nginx
|
repository: nginx
|
||||||
tag: "1.29.4-alpine-perl"
|
tag: "1.31.8-alpine-perl"
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
php:
|
php:
|
||||||
registry: docker.io
|
registry: docker.io
|
||||||
repository: php
|
repository: php
|
||||||
tag: "8.5.2-fpm-alpine3.22"
|
tag: "8.5.12-fpm-alpine3.24"
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
selenium:
|
selenium:
|
||||||
registry: docker.io
|
registry: docker.io
|
||||||
repository: selenium/standalone-chromium
|
repository: selenium/standalone-chromium
|
||||||
tag: "143.0-chromedriver-143.0"
|
tag: "155.0-chromedriver-155.0"
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
service:
|
service:
|
||||||
# type: ClusterIP
|
type: ClusterIP
|
||||||
type: LoadBalancer
|
# type: LoadBalancer
|
||||||
port: 80
|
port: 80
|
||||||
|
|
||||||
|
# アップロード可能な最大サイズ
|
||||||
|
# 以下3箇所に同じ値を反映する(どれか一つでも小さいと、そこで上限に達して失敗するため):
|
||||||
|
# - 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
|
||||||
|
# 単位はnginx/PHP共通でk/m/g(大文字小文字問わず)が使用可能(例: "100m", "1g")
|
||||||
|
uploadMaxSize: "100m"
|
||||||
|
|
||||||
ingress:
|
ingress:
|
||||||
enabled: false
|
enabled: false
|
||||||
className: ""
|
className: ""
|
||||||
annotations: {}
|
# nginx.ingress.kubernetes.io/proxy-body-size は uploadMaxSize の値が自動的に付与されるため
|
||||||
# {
|
# 明示的に指定する必要はない(Ingress側の上限もnginx/PHPと揃う)
|
||||||
# acme.cert-manager.io/http01-ingress-class: "nginx",
|
# 別の値にしたい場合や別コントローラーを使う場合は、ここに明示指定すれば上書きされる
|
||||||
# cert-manager.io/cluster-issuer: "letsencrypt-issuer",
|
annotations:
|
||||||
# nginx.ingress.kubernetes.io/from-to-www-redirect: "true",
|
{
|
||||||
# nginx.ingress.kubernetes.io/proxy-body-size: "100m"
|
acme.cert-manager.io/http01-ingress-class: "nginx",
|
||||||
# }
|
cert-manager.io/cluster-issuer: "letsencrypt-issuer",
|
||||||
|
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
|
||||||
|
}
|
||||||
hosts:
|
hosts:
|
||||||
- host: example.tld
|
- host: &appDomain example.tld
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
tls: []
|
# secretNameは省略可能。省略した場合、そのエントリの最初のhostの"."を"-"に
|
||||||
# [
|
# 置換し"-tls"を付与した値が自動生成される(例: example.tld → example-tld-tls)。
|
||||||
# {
|
# appDomainの変更だけでhostとsecretNameが揃うため、通常は明示指定しなくてよい。
|
||||||
# hosts: [ "example.com" ],
|
# 別の証明書Secret名にしたい場合のみ secretName: "your-secret-name" を追加する。
|
||||||
# secretName: "example-tls"
|
tls:
|
||||||
# }
|
[
|
||||||
# ]
|
{
|
||||||
|
hosts: [*appDomain]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
persistence:
|
persistence:
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -51,13 +64,190 @@ persistence:
|
|||||||
size: 1Gi
|
size: 1Gi
|
||||||
|
|
||||||
nginx:
|
nginx:
|
||||||
|
# 独自のnginx設定を、server { } ブロックの末尾へそのまま挿入する(templates/configmap.yaml)。
|
||||||
|
# 読まれるキーは snippet のみ。serverSnippet / httpSnippet は未使用の
|
||||||
|
# templates/configmap-nginx.yaml 専用で出力されないため、指定しても無視される。
|
||||||
|
# また挿入先は server ブロック内のため、http レベル専用のディレクティブ
|
||||||
|
# (limit_req_zone 等)は書けない。
|
||||||
|
#
|
||||||
|
# 【重複注意】以下はチャートが自動で出力するため snippet に書かない
|
||||||
|
# (書くと "directive is duplicate" 等で nginx が起動しなくなる):
|
||||||
|
# - client_max_body_size → uploadMaxSize で設定する
|
||||||
|
# - location = /sitemap.xml(Content-Typeの明示)
|
||||||
customConfig:
|
customConfig:
|
||||||
enabled: false
|
enabled: false
|
||||||
snippet: |-
|
snippet: |-
|
||||||
|
|
||||||
|
# リアルIP転送設定(ベアメタル/LoadBalancer環境向け)
|
||||||
|
forwardRealIP:
|
||||||
|
# リアルIP取得機能を有効化
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# リアルIPを取得するヘッダー名
|
||||||
|
# LoadBalancer/Ingressによって異なる
|
||||||
|
# - X-Real-IP: シンプルな1段プロキシ
|
||||||
|
# - X-Forwarded-For: 多段プロキシ対応(推奨)
|
||||||
|
header: "X-Forwarded-For"
|
||||||
|
|
||||||
|
# 再帰的にリアルIPを検索(多段プロキシ環境で推奨)
|
||||||
|
recursive: true
|
||||||
|
|
||||||
|
# 信頼するプロキシのネットワーク範囲
|
||||||
|
# ベアメタルクラスターでは、PodネットワークとServiceネットワークを指定
|
||||||
|
trustedProxies:
|
||||||
|
- "10.0.0.0/8" # プライベートネットワーク
|
||||||
|
- "172.16.0.0/12" # プライベートネットワーク
|
||||||
|
- "192.168.0.0/16" # プライベートネットワーク
|
||||||
|
|
||||||
|
# 追加で信頼するプロキシ(環境に応じてカスタマイズ)
|
||||||
|
additionalTrustedProxies: []
|
||||||
|
# - "203.0.113.0/24" # 外部LoadBalancerなど
|
||||||
|
|
||||||
|
# Composer設定
|
||||||
|
composer:
|
||||||
|
# Composerを使用するかどうか
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Composerの導入先ディレクトリ(composer.json / vendor の配置先)
|
||||||
|
# デフォルトの /composer はWebルート外かつPVCにマウントされない「使い捨て」領域:
|
||||||
|
# - vendor/ や composer.json がWeb経由で公開されない
|
||||||
|
# - Pod再起動のたびにクリーンな環境へ再構築されるため、
|
||||||
|
# 不正アクセスでマルウェアを書き込まれても再起動で消える
|
||||||
|
#
|
||||||
|
# 【重要】PHPコードからの autoload.php の読み込み方:
|
||||||
|
# require_once '/composer/vendor/autoload.php';
|
||||||
|
#
|
||||||
|
# PVC上に永続化したい場合は /var/www 配下(例: "/var/www/composer")を指定
|
||||||
|
# 旧来の動作(Webルート直下に導入)へ戻す場合は "/var/www/html" を指定
|
||||||
|
workingDir: "/composer"
|
||||||
|
|
||||||
|
# Composerでインストールするパッケージ
|
||||||
|
# packages配列が空の場合、composer.jsonを使用
|
||||||
|
packages: []
|
||||||
|
# - "monolog/monolog:^2.0"
|
||||||
|
# - "guzzlehttp/guzzle:^7.0"
|
||||||
|
|
||||||
|
# composer.jsonファイルを使用する場合
|
||||||
|
useComposerJson: false
|
||||||
|
|
||||||
|
# composer.jsonの内容(useComposerJson: trueの場合に使用)
|
||||||
|
composerJson: |
|
||||||
|
{
|
||||||
|
"require": {
|
||||||
|
"monolog/monolog": "^2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# composer.lockファイルの内容(オプション、再現性を保証)
|
||||||
|
composerLock: ""
|
||||||
|
|
||||||
|
# Composerのインストールオプション
|
||||||
|
installOptions: "--no-dev --optimize-autoloader"
|
||||||
|
|
||||||
|
# 追加のAPKパッケージ(Composer依存関係のビルドに必要な場合)
|
||||||
|
additionalApkPackages: []
|
||||||
|
# - "libpng-dev"
|
||||||
|
# - "libjpeg-turbo-dev"
|
||||||
|
|
||||||
|
# 追加のPHP拡張(docker-php-ext-installで導入)
|
||||||
|
additionalPhpExtensions: []
|
||||||
|
# - "gd"
|
||||||
|
# - "zip"
|
||||||
|
|
||||||
|
# Python設定(オプション、PHPからPythonスクリプトを呼び出す用途)
|
||||||
|
python:
|
||||||
|
# Pythonを使用するかどうか
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# Python仮想環境(venv)の導入先ディレクトリ
|
||||||
|
# デフォルトの /venv はWebルート外かつPVCにマウントされない「使い捨て」領域:
|
||||||
|
# - Pod再起動のたびにクリーンな環境へ再構築される(Composerと同じ設計)
|
||||||
|
#
|
||||||
|
# 【重要】PHPからのPython呼び出し方(execを利用):
|
||||||
|
# exec('/venv/bin/python3 /path/to/script.py 2>&1', $output, $exitCode);
|
||||||
|
#
|
||||||
|
# PVC上に永続化したい場合は /var/www 配下(例: "/var/www/venv")を指定
|
||||||
|
venvDir: "/venv"
|
||||||
|
|
||||||
|
# pipでインストールするパッケージ
|
||||||
|
# packages配列が空の場合、requirements.txtを使用
|
||||||
|
packages: []
|
||||||
|
# - "requests>=2.31.0"
|
||||||
|
# - "pillow"
|
||||||
|
|
||||||
|
# requirements.txtを使用する場合
|
||||||
|
useRequirementsTxt: false
|
||||||
|
|
||||||
|
# requirements.txtの内容(useRequirementsTxt: trueの場合に使用)
|
||||||
|
requirementsTxt: |
|
||||||
|
requests>=2.31.0
|
||||||
|
|
||||||
|
# pip installのオプション
|
||||||
|
installOptions: "--no-cache-dir"
|
||||||
|
|
||||||
|
# 追加のAPKパッケージ(ネイティブ拡張のビルドに必要な場合、例: numpy等)
|
||||||
|
additionalApkPackages: []
|
||||||
|
# - "gcc"
|
||||||
|
# - "musl-dev"
|
||||||
|
# - "python3-dev"
|
||||||
|
# - "jpeg-dev"
|
||||||
|
|
||||||
|
# Selenium設定
|
||||||
|
# v8.5.10-b以降、Selenium(有効時)はnginx/php-fpmと同一Podのサイドカーではなく、
|
||||||
|
# 独立したDeployment/Service(<release>-phpfpm-selenium)として起動する。
|
||||||
|
# 理由: サイドカー方式だとSelenium単体の不調(起動失敗・OOM等)でPod全体がReady=false
|
||||||
|
# になり、Seleniumを使わない静的ページ配信まで巻き込まれてサービス全体が止まっていた。
|
||||||
|
# php-fpmコンテナのSELENIUM_URL環境変数は、enabled:true時に自動でこのServiceを指す
|
||||||
|
# (phpEnvで独自に設定しても、こちらの値が優先される)。
|
||||||
selenium:
|
selenium:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
# Selenium Deployment自体のレプリカ数
|
||||||
|
replicaCount: 1
|
||||||
|
# Chromiumはメモリを多く使う。ノードのメモリ枯渇によるOOM Killを防ぐため、
|
||||||
|
# 実運用では必ずrequests/limitsを設定することを推奨する(下記resourcesセクション参照)。
|
||||||
|
resources: {}
|
||||||
|
# trueにすると、SeleniumコンテナにもPVCのhtmlサブパスを/var/www/htmlとしてマウントする
|
||||||
|
# (ブラウザのダウンロード先を公開ディレクトリに置きたい場合など)。別Podからの同時マウント
|
||||||
|
# になるため、有効にする場合はpersistence.accessModeをReadWriteMany
|
||||||
|
# (NFSバックエンドのStorageClassなら対応可能)にする必要がある。
|
||||||
|
# 通常のスクレイピング用途(スクリーンショット等をstorage/等の非公開領域に保存する場合)
|
||||||
|
# では不要なため、既定はfalse。
|
||||||
|
mountHtml: false
|
||||||
|
|
||||||
|
# 定期実行タスク(Kubernetes CronJob)
|
||||||
|
# php-fpmと同じPHPイメージ(image.php)を使い、指定したスケジュールで
|
||||||
|
# 1回限りのコマンドを実行するCronJobを作成する。複数ジョブを配列で定義できる。
|
||||||
|
# jobsが空の場合、CronJobは1つも作成されない。
|
||||||
|
#
|
||||||
|
# 【マウント/環境変数】/var/wwwにPVCルートをマウントし、externalDatabase/phpEnv/
|
||||||
|
# extraEnv/extraEnvFrom/SELENIUM_URLはphp-fpmコンテナと同じ内容が渡される。
|
||||||
|
# html/ 配下の公開コード、または /var/www/<非公開フォルダ> 配下の
|
||||||
|
# 非公開スクリプト・出力先のどちらも利用できる。
|
||||||
|
#
|
||||||
|
# 【Composer/Pythonとの併用について】
|
||||||
|
# composer.workingDir / python.venvDir が既定の /composer, /venv
|
||||||
|
# (PVC非マウントの使い捨て領域)のままの場合、CronJobのPodには存在しない
|
||||||
|
# (php-fpmの長時間稼働Pod内だけに存在する)ため利用できない。
|
||||||
|
# CronJobからComposer/Pythonの成果物を使いたい場合は、
|
||||||
|
# composer.workingDir: "/var/www/composer" のように/var/www配下へ変更し、
|
||||||
|
# PVC上に永続化すること(本体Deployment側で一度セットアップされていれば、
|
||||||
|
# CronJob側は改めてインストールし直す必要はない)。
|
||||||
|
#
|
||||||
|
# 【SMTPとの併用】smtp.enabled: true の場合、CronJobのPodでもmsmtpの導入・
|
||||||
|
# msmtprc配置・sendmail_path設定を自動で行うため、PHPのmail()関数がそのまま使える。
|
||||||
|
cron:
|
||||||
|
jobs: []
|
||||||
|
# - name: daily-report # 必須。CronJob名の一部に使用(英数字とハイフンのみ、小文字推奨)
|
||||||
|
# schedule: "0 18 * * *" # 必須。標準cron形式(timeZone省略時はUTC基準)
|
||||||
|
# command: "php /var/www/html/cron/daily-report.php"
|
||||||
|
# timeZone: "Asia/Tokyo" # 省略時はUTC(Kubernetes 1.27+で安定サポート)
|
||||||
|
# concurrencyPolicy: "Forbid" # Allow / Forbid / Replace(既定: Forbid。前回実行の長期化による多重起動を防止)
|
||||||
|
# restartPolicy: "OnFailure" # OnFailure / Never(既定: OnFailure)
|
||||||
|
# successfulJobsHistoryLimit: 3
|
||||||
|
# failedJobsHistoryLimit: 1
|
||||||
|
# activeDeadlineSeconds: 3600 # 実行タイムアウト(秒)。省略可
|
||||||
|
# suspend: false # trueにするとコード変更なしでこのジョブだけ一時停止できる
|
||||||
|
# resources: {} # 未指定時は resources.phpfpm を流用
|
||||||
|
|
||||||
externalDatabase:
|
externalDatabase:
|
||||||
enabled: false
|
enabled: false
|
||||||
@@ -67,4 +257,112 @@ externalDatabase:
|
|||||||
username: user
|
username: user
|
||||||
password: pass
|
password: pass
|
||||||
|
|
||||||
resources: {}
|
# SMTP設定(PHPのメール送信用)
|
||||||
|
smtp:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
# SMTPサーバー設定
|
||||||
|
host: "smtp.example.com"
|
||||||
|
|
||||||
|
# プロトコルとポート設定
|
||||||
|
# - auto: 自動判定(推奨)
|
||||||
|
# - starttls: STARTTLS(ポート587)
|
||||||
|
# - tls: SSL/TLS(ポート465)
|
||||||
|
protocol: "auto"
|
||||||
|
|
||||||
|
# ポート番号(通常は自動判定されるため手動設定は不要)
|
||||||
|
# protocol: auto の場合は以下の値を参考に
|
||||||
|
# - 25: SMTP (非暗号化)
|
||||||
|
# - 587: SMTP + STARTTLS (暗号化)
|
||||||
|
# - 465: SMTP + SSL/TLS (暗号化)
|
||||||
|
port: 587
|
||||||
|
|
||||||
|
# 認証設定
|
||||||
|
auth:
|
||||||
|
enabled: true
|
||||||
|
username: "smtp-user@example.com"
|
||||||
|
# password はSecretで管理する
|
||||||
|
# values-secret.yaml などで以下のように指定:
|
||||||
|
# smtp:
|
||||||
|
# auth:
|
||||||
|
# password: "your-smtp-password"
|
||||||
|
password: ""
|
||||||
|
|
||||||
|
# 【外部Secret連携】チャートで msmtprc を生成しつつ、パスワードファイルだけ
|
||||||
|
# 既存 Secret から取りたい場合に指定する。
|
||||||
|
# 例: secret-manager チャートが配布する cred-<プロバイダ> の SMTP_PASSWORD キー
|
||||||
|
# existingSecret: "cred-gmail"
|
||||||
|
# existingSecretKey: "SMTP_PASSWORD"
|
||||||
|
# 指定時は smtp.auth.password と自作の -smtp Secret は使われない。
|
||||||
|
existingSecret: ""
|
||||||
|
existingSecretKey: "password"
|
||||||
|
|
||||||
|
# 送信元アドレス(固定値)
|
||||||
|
# PHPプログラムで mail() 関数の $additional_parameters で上書き可能
|
||||||
|
# 例: mail($to, $subject, $body, $headers, "-f user@example.com")
|
||||||
|
from: "noreply@example.com"
|
||||||
|
|
||||||
|
# TLS/SSL設定
|
||||||
|
tls:
|
||||||
|
# 証明書検証を有効化(本番環境では true を推奨)
|
||||||
|
verify: true
|
||||||
|
# 自己署名証明書を許可する場合(テスト環境のみ)
|
||||||
|
allowSelfSigned: false
|
||||||
|
|
||||||
|
# 【外部Secret連携】完成済みの msmtprc がまるごと入っている既存 Secret を使う。
|
||||||
|
# 指定するとチャート内の msmtprc 生成(configmap-smtp)は行わず、
|
||||||
|
# host / port / protocol / auth.* / tls.* は無視される(from だけ PHP の
|
||||||
|
# sendmail_from 用に使用)。
|
||||||
|
# secret-manager チャートが cred-<プロバイダ> に生成する msmtprc キーを
|
||||||
|
# そのまま利用できる:
|
||||||
|
# existingMsmtprcSecret: "cred-gmail"
|
||||||
|
# existingMsmtprcSecretKey: "msmtprc"
|
||||||
|
existingMsmtprcSecret: ""
|
||||||
|
existingMsmtprcSecretKey: "msmtprc"
|
||||||
|
|
||||||
|
# nginx / php-fpm コンテナの CPU/メモリ requests・limits。
|
||||||
|
# v8.5.10-b より前は本キーがテンプレート側で参照されておらず(死んだ設定)、
|
||||||
|
# 何を指定してもコンテナには一切反映されない不具合があった(既存デプロイは
|
||||||
|
# 全コンテナが requests/limits なしの QoS Class: BestEffort になっていた)。
|
||||||
|
# BestEffortはノードのメモリ逼迫時にOOM Killの対象になりやすいため、
|
||||||
|
# 本番運用では requests/limits の設定を推奨する。例:
|
||||||
|
# resources:
|
||||||
|
# nginx:
|
||||||
|
# requests: { cpu: "50m", memory: "64Mi" }
|
||||||
|
# limits: { memory: "128Mi" }
|
||||||
|
# phpfpm:
|
||||||
|
# requests: { cpu: "100m", memory: "256Mi" }
|
||||||
|
# limits: { memory: "512Mi" }
|
||||||
|
# (selenium用は selenium.resources を参照。Chromiumは256Mi等では確実に不足する)
|
||||||
|
resources:
|
||||||
|
nginx: {}
|
||||||
|
phpfpm: {}
|
||||||
|
|
||||||
|
# PHP-FPM コンテナに渡す任意の環境変数
|
||||||
|
# DB接続情報(externalDatabase)と同様に、values.yamlで設定した値がPHPに環境変数として渡される
|
||||||
|
# PHPからは $_ENV['KEY'] または getenv('KEY') で取得可能
|
||||||
|
phpEnv: {}
|
||||||
|
# API_KEY: "your-api-key"
|
||||||
|
# STRIPE_SECRET: "sk_live_xxxxxxxxxxxxxxxx"
|
||||||
|
# REDIS_URL: "redis://localhost:6379"
|
||||||
|
# SOME_SERVICE_URL: "https://api.example.com"
|
||||||
|
|
||||||
|
# 既存の Secret / ConfigMap をまるごと環境変数として PHP-FPM コンテナへ注入する(envFrom)。
|
||||||
|
# 別リポジトリの secret-manager チャートが各ネームスペースへ配布する
|
||||||
|
# cred-<名前> Secret(API キー等)をそのまま読み込む用途を想定。
|
||||||
|
# 変更は secret-manager 側を更新するだけで全プロジェクトに反映できる。
|
||||||
|
extraEnvFrom: []
|
||||||
|
# - secretRef:
|
||||||
|
# name: cred-gemini
|
||||||
|
# - secretRef:
|
||||||
|
# name: cred-openai
|
||||||
|
# - configMapRef:
|
||||||
|
# name: some-shared-config
|
||||||
|
|
||||||
|
# 個別の環境変数を追加する(生の env エントリ配列。value / valueFrom(secretKeyRef 等) 使用可)。
|
||||||
|
extraEnv: []
|
||||||
|
# - name: OPENAI_API_KEY
|
||||||
|
# valueFrom:
|
||||||
|
# secretKeyRef:
|
||||||
|
# name: cred-openai
|
||||||
|
# key: OPENAI_API_KEY
|
||||||
Reference in New Issue
Block a user