Files
wordpress/templates/deployment.yaml
T
claude 6d1b7bc8d6
Helm Chart Release / release-chart (push) Successful in 6s
feat: 外部Secret連携(extraEnvFrom / extraEnv / SMTP existingSecret)を追加
helmchart/secret-manager が各ネームスペースへ配布する cred-* Secret を
WordPress 側から参照できるようにする(phpfpm と同一方針)。
- extraEnvFrom / extraEnv: 既存 Secret/ConfigMap を wordpress コンテナへ env 注入
- smtp.auth.existingSecret / existingSecretKey: パスワードファイルだけ既存 Secret から取得
- smtp.existingMsmtprcSecret / existingMsmtprcSecretKey: 完成済み msmtprc を
  そのままマウント(指定時は configmap-smtp を生成せず host/port/auth.* は無視)
既定値は全て空のため既存挙動は不変。手動リリース 7.1.0-b。
2026-09-08 14:16:14 +09:00

432 lines
19 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "wordpress-nginx.fullname" . }}
labels:
{{- include "wordpress-nginx.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "wordpress-nginx.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "wordpress-nginx.selectorLabels" . | nindent 8 }}
spec:
securityContext:
fsGroup: 82
fsGroupChangePolicy: "OnRootMismatch"
initContainers:
- name: wordpress-init
image: "{{ .Values.image.wordpress.registry }}/{{ .Values.image.wordpress.repository }}:{{ .Values.image.wordpress.tag }}"
imagePullPolicy: {{ .Values.image.wordpress.pullPolicy }}
command: ["/bin/sh", "-c"]
args:
- |
set -e
echo "=== WordPress Initialization Started ==="
echo "Copying WordPress to emptyDir..."
# wp-contentは別マウントのPVCのため、ここではコアファイルのみコピーする。
# "cp -r /usr/src/wordpress/* /var/www/html/" のようにwp-contentを含めて
# 丸ごとコピーすると、既存のPVC上のwp-contentディレクトリにイメージ同梱の
# デフォルトファイル(hello.php等)が毎回上書きマージされてしまい、
# ユーザーが削除したはずのプラグインがPod再起動のたびに復活する原因になる。
for item in /usr/src/wordpress/*; do
name=$(basename "$item")
if [ "$name" = "wp-content" ]; then
continue
fi
cp -r "$item" /var/www/html/
done
echo "WordPress files copied"
if [ ! -d /var/www/html/wp-content/themes ]; then
echo "Initializing wp-content in PVC..."
cp -rp /usr/src/wordpress/wp-content/* /var/www/html/wp-content/
echo "wp-content initialized"
else
echo "wp-content already exists, preserving user data"
fi
echo "Generating wp-config.php..."
cat > /var/www/html/wp-config.php << 'EOF'
<?php
define('DB_NAME', getenv('WORDPRESS_DB_NAME'));
define('DB_USER', getenv('WORDPRESS_DB_USER'));
define('DB_PASSWORD', getenv('WORDPRESS_DB_PASSWORD'));
define('DB_HOST', getenv('WORDPRESS_DB_HOST'));
define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');
$table_prefix = getenv('WORDPRESS_TABLE_PREFIX') ?: 'wp_';
define('AUTH_KEY', getenv('WP_AUTH_KEY'));
define('SECURE_AUTH_KEY', getenv('WP_SECURE_AUTH_KEY'));
define('LOGGED_IN_KEY', getenv('WP_LOGGED_IN_KEY'));
define('NONCE_KEY', getenv('WP_NONCE_KEY'));
define('AUTH_SALT', getenv('WP_AUTH_SALT'));
define('SECURE_AUTH_SALT', getenv('WP_SECURE_AUTH_SALT'));
define('LOGGED_IN_SALT', getenv('WP_LOGGED_IN_SALT'));
define('NONCE_SALT', getenv('WP_NONCE_SALT'));
if ( defined( 'WP_CLI' ) ) {
$_SERVER['HTTP_HOST'] = '127.0.0.1';
}
// HTTPS Detection under Proxy
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
// 実クライアントIPの解決はNginx側(real_ipモジュール)で完結しており、
// fastcgi_param REMOTE_ADDR として渡されるためPHP側での再判定は行わない。
// ここでX-Forwarded-Forを無条件に信頼して上書きすると、Nginxの信頼済み
// プロキシ判定を迂回してクライアントがIPを詐称できてしまうため実施しない。
$protocol = 'http';
if ( isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ) {
$protocol = 'https';
} elseif ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ) {
$protocol = 'https';
}
define( 'WP_HOME', $protocol . '://' . $_SERVER['HTTP_HOST'] . '/' );
define( 'WP_SITEURL', $protocol . '://' . $_SERVER['HTTP_HOST'] . '/' );
$multisite_enabled = getenv('WORDPRESS_MULTISITE_ENABLED');
if ( $multisite_enabled === 'true' ) {
define('WP_ALLOW_MULTISITE', true);
define('MULTISITE', true);
define('SUBDOMAIN_INSTALL', getenv('WORDPRESS_MULTISITE_SUBDOMAINS') === 'true');
define('DOMAIN_CURRENT_SITE', getenv('WORDPRESS_MULTISITE_DOMAIN'));
define('PATH_CURRENT_SITE', '/');
define('SITE_ID_CURRENT_SITE', 1);
define('BLOG_ID_CURRENT_SITE', 1);
}
define( 'WP_AUTO_UPDATE_CORE', false );
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('WP_DEBUG_DISPLAY', false);
define('FS_METHOD', 'direct');
define('WP_MEMORY_LIMIT', '256M');
define('WP_MAX_MEMORY_LIMIT', '512M');
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', __DIR__ . '/' );
}
require_once ABSPATH . 'wp-settings.php';
EOF
echo "wp-config.php generated"
echo "Setting up WP-CLI..."
curl -o /tmp/wp-cli.phar https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar 2>/dev/null || true
chmod +x /tmp/wp-cli.phar
echo "Waiting for database connection..."
max_attempts=30
attempt=0
while [ $attempt -lt $max_attempts ]; do
if php -r "\$link = @mysqli_connect('${WORDPRESS_DB_HOST}', '${WORDPRESS_DB_USER}', '${WORDPRESS_DB_PASSWORD}', '${WORDPRESS_DB_NAME}'); if (\$link) { echo 'Connected'; mysqli_close(\$link); exit(0); } exit(1);" 2>/dev/null; then
echo "Database connection successful"
break
fi
attempt=$((attempt + 1))
echo "Waiting for database... ($attempt/$max_attempts)"
sleep 2
done
if [ $attempt -eq $max_attempts ]; then
echo "ERROR: Database connection timeout"
exit 1
fi
echo "Checking if WordPress is already installed..."
TABLES=$(/tmp/wp-cli.phar --path=/var/www/html db query "SHOW TABLES LIKE '${WORDPRESS_TABLE_PREFIX}options';" 2>/dev/null || echo "")
if [ -z "$TABLES" ]; then
echo "=== Starting WordPress Installation ==="
# 初回インストール時のパスワード処理
INSTALL_PASSWORD="$WP_ADMIN_PASSWORD"
if [ -z "$INSTALL_PASSWORD" ]; then
# パスワードが空の場合は、ランダムに生成する
INSTALL_PASSWORD=$(openssl rand -base64 32 | tr -d "=+/" | cut -c1-20)
echo "INFO: WP_ADMIN_PASSWORD is not set. Generated random password."
fi
INSTALL_URL="http://127.0.0.1"
echo "Installing WordPress..."
/tmp/wp-cli.phar --path=/var/www/html core install \
--url="$INSTALL_URL" \
--title="$WP_SITE_TITLE" \
--admin_user="$WP_ADMIN_USER" \
--admin_password="$INSTALL_PASSWORD" \
--admin_email="$WP_ADMIN_EMAIL" \
--skip-email
echo "=== WordPress Installation Completed ==="
echo "Admin User: $WP_ADMIN_USER"
if [ -z "$WP_ADMIN_PASSWORD" ]; then
echo "INFO: Generated admin password. Check Secret for details."
else
echo "Admin password was set from values.yaml"
fi
else
echo "WordPress is already installed, skipping installation"
if [ -f /tmp/wp-cli.phar ]; then
echo "Running WordPress core update check..."
/tmp/wp-cli.phar --path=/var/www/html core update-db 2>/dev/null || echo "No database update needed"
fi
fi
echo "=== WordPress Initialization Completed ==="
volumeMounts:
- name: wordpress-data
mountPath: /var/www/html
- name: wordpress-persistent
mountPath: /var/www/html/wp-content
env:
- name: WORDPRESS_DB_HOST
value: {{ .Values.wordpress.dbHost | quote }}
- name: WORDPRESS_DB_NAME
value: {{ .Values.wordpress.dbName | quote }}
- name: WORDPRESS_DB_USER
value: {{ .Values.wordpress.dbUser | quote }}
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "wordpress-nginx.fullname" . }}-secret
key: db-password
- name: WORDPRESS_TABLE_PREFIX
value: {{ .Values.wordpress.tablePrefix | quote }}
- name: WP_SITE_TITLE
value: {{ .Values.wordpress.siteTitle | quote }}
- name: WP_ADMIN_USER
value: {{ .Values.wordpress.adminUser | quote }}
- name: WP_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "wordpress-nginx.fullname" . }}-secret
key: admin-password
- name: WP_ADMIN_EMAIL
value: {{ .Values.wordpress.adminEmail | quote }}
- name: WP_AUTH_KEY
valueFrom:
secretKeyRef:
name: {{ include "wordpress-nginx.fullname" . }}-secret
key: auth-key
- name: WP_SECURE_AUTH_KEY
valueFrom:
secretKeyRef:
name: {{ include "wordpress-nginx.fullname" . }}-secret
key: secure-auth-key
- name: WP_LOGGED_IN_KEY
valueFrom:
secretKeyRef:
name: {{ include "wordpress-nginx.fullname" . }}-secret
key: logged-in-key
- name: WP_NONCE_KEY
valueFrom:
secretKeyRef:
name: {{ include "wordpress-nginx.fullname" . }}-secret
key: nonce-key
- name: WP_AUTH_SALT
valueFrom:
secretKeyRef:
name: {{ include "wordpress-nginx.fullname" . }}-secret
key: auth-salt
- name: WP_SECURE_AUTH_SALT
valueFrom:
secretKeyRef:
name: {{ include "wordpress-nginx.fullname" . }}-secret
key: secure-auth-salt
- name: WP_LOGGED_IN_SALT
valueFrom:
secretKeyRef:
name: {{ include "wordpress-nginx.fullname" . }}-secret
key: logged-in-salt
- name: WP_NONCE_SALT
valueFrom:
secretKeyRef:
name: {{ include "wordpress-nginx.fullname" . }}-secret
key: nonce-salt
- name: WORDPRESS_MULTISITE_ENABLED
value: {{ .Values.wordpress.multisite.enabled | quote }}
- name: WORDPRESS_MULTISITE_SUBDOMAINS
value: {{ .Values.wordpress.multisite.subdomains | quote }}
- name: WORDPRESS_MULTISITE_DOMAIN
value: {{ .Values.wordpress.multisite.domain | quote }}
securityContext:
runAsUser: 82
runAsGroup: 82
containers:
- name: nginx
image: "{{ .Values.image.nginx.registry }}/{{ .Values.image.nginx.repository }}:{{ .Values.image.nginx.tag }}"
imagePullPolicy: {{ .Values.image.nginx.pullPolicy }}
ports:
- name: http
containerPort: 80
protocol: TCP
volumeMounts:
- name: wordpress-data
mountPath: /var/www/html
- name: wordpress-persistent
mountPath: /var/www/html/wp-content
- name: nginx-config
mountPath: /etc/nginx/conf.d/default.conf
subPath: default.conf
{{- if .Values.wordpress.adsTxt.enabled }}
- name: adstxt-config
mountPath: /var/www/html/ads.txt
subPath: ads.txt
{{- end }}
{{- if .Values.healthCheck.enabled }}
livenessProbe:
{{- toYaml .Values.healthCheck.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.healthCheck.readinessProbe | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources.nginx | nindent 12 }}
- name: wordpress
image: "{{ .Values.image.wordpress.registry }}/{{ .Values.image.wordpress.repository }}:{{ .Values.image.wordpress.tag }}"
imagePullPolicy: {{ .Values.image.wordpress.pullPolicy }}
{{- if .Values.smtp.enabled }}
# SMTP有効時はapk addでmsmtpを導入する必要があるためrootで起動し、
# セットアップ後にphp-fpmへexecする(ワーカープロセス自体はイメージ標準の
# www.confによりwww-data(uid82)で動作するため実処理は非rootのまま)
command: ["/bin/sh", "-c"]
args:
- |
set -e
echo "Configuring SMTP for mail sending..."
apk add --no-cache msmtp ca-certificates
# msmtpはPHP-FPMワーカー(www-data等の非root)から実行されるため、
# rootが作成するこのファイルも読み取り可にする必要がある
# (実パスワードはpasswordeval経由で別ファイルから取得するため、
# msmtprc自体に平文パスワードは含まれない)
cp /etc/smtp-config/msmtprc /etc/msmtprc
chmod 644 /etc/msmtprc
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
{{- if .Values.smtp.existingMsmtprcSecret }}
echo "SMTP configured from existing secret: {{ .Values.smtp.existingMsmtprcSecret }}"
{{- else }}
echo "SMTP configured: {{ .Values.smtp.host }}:{{ .Values.smtp.port }}"
{{- end }}
exec php-fpm
{{- else }}
command: ["php-fpm"]
securityContext:
runAsUser: 82
runAsGroup: 82
{{- end }}
env:
- name: WORDPRESS_DB_HOST
value: {{ .Values.wordpress.dbHost | quote }}
- name: WORDPRESS_DB_NAME
value: {{ .Values.wordpress.dbName | quote }}
- name: WORDPRESS_DB_USER
value: {{ .Values.wordpress.dbUser | quote }}
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "wordpress-nginx.fullname" . }}-secret
key: db-password
- name: WORDPRESS_TABLE_PREFIX
value: {{ .Values.wordpress.tablePrefix | quote }}
{{- with .Values.extraEnv }}
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with .Values.extraEnvFrom }}
envFrom:
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
- name: wordpress-data
mountPath: /var/www/html
- name: wordpress-persistent
mountPath: /var/www/html/wp-content
{{- 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 }}
resources:
{{- toYaml .Values.resources.wordpress | nindent 12 }}
volumes:
- name: wordpress-data
emptyDir: {}
- name: wordpress-persistent
{{- if .Values.persistence.enabled }}
persistentVolumeClaim:
claimName: {{ include "wordpress-nginx.fullname" . }}-pvc
{{- else }}
emptyDir: {}
{{- end }}
- name: nginx-config
configMap:
name: {{ include "wordpress-nginx.fullname" . }}-nginx-config
{{- if .Values.wordpress.adsTxt.enabled }}
- name: adstxt-config
configMap:
name: {{ include "wordpress-nginx.fullname" . }}-adstxt
{{- 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 "wordpress-nginx.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 "wordpress-nginx.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 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}