基于 Kubernetes 的 PHP 项目单 Nginx 架构虚拟化部署
·
本文详细记录了在现有 Kubernetes 集群上,为一个 PHP 项目部署“单 Nginx”架构的完整过程。该方案采用 仅使用 Ingress Nginx 的模式,将应用的反向代理和静态资源服务完全交给 Kubernetes 层的 Ingress Controller 处理。
📋 架构概览
| 项目 | 配置 |
|---|---|
| 应用类型 | PHP (ThinkPHP) |
| 容器运行时 | containerd |
| 部署方式 | Kubernetes Deployment |
| 网络架构 | 单 Nginx 模式 |
| 存储 | NFS PersistentVolume |
| Ingress 控制器 | ingress-nginx |
🏗️ “单 Nginx” 架构详解
-
Pod 内应用:
- 仅包含
php-fpm进程,负责执行 PHP 脚本。 - 不包含任何 Web 服务器(如 Nginx 或 Apache)。
- 仅包含
-
外部 Ingress Nginx (Kubernetes 层):
- 作为集群的统一入口,管理所有对外暴露的服务。
- 接收来自客户端的所有流量,并根据 Host 和 Path 规则将请求路由到后端 Service。
- 统一处理 TLS/SSL 加密、HTTP 到 HTTPS 重定向等。
- 直接从 Pod 中提供静态文件服务(通过挂载的 PVC),并动态地将 PHP 请求反向代理给
php-fpm。
✅ 优势:
- 简单性:架构更简单,运维复杂度低。
- 统一管理:所有应用的 SSL 证书、URL 重写规则都在 Ingress 层集中配置。
- 资源优化:每个 Pod 不再需要运行额外的 Nginx 进程,节省了 CPU 和内存。
✅ 第一步:准备持久化存储 (NFS)
为 PHP 应用创建基于 NFS 的持久化存储,用于存放代码和上传文件。
1. 创建 NFS PersistentVolume
# nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv-wanyanzhenjiang-api-test
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany # 必须支持多节点读写
persistentVolumeReclaimPolicy: Retain
nfs:
server: 192.168.122.189 # NFS 服务器 IP
path: /opt/nfs/wanyanzhenjiang-api-test # NFS 共享目录
mountOptions:
- nfsvers=4.1
- hard
- intr
2. 创建 PersistentVolumeClaim
# nfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc-wanyanzhenjiang-api-test
namespace: test # 部署目标命名空间
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
volumeName: nfs-pv-wanyanzhenjiang-api-test # 关联已创建的 PV
🔧 操作步骤:
- 在 NFS 服务器 (
192.168.122.189) 上创建共享目录并设置权限:sudo mkdir -p /opt/nfs/wanyanzhenjiang-api-test sudo chmod 755 /opt/nfs/wanyanzhenjiang-api-test- 在
/etc/exports中添加导出规则:/opt/nfs/wanyanzhenjiang-api-test *(rw,sync,no_root_squash)- 重新加载 NFS 配置:
exportfs -ra- 在 Kubernetes 集群中应用 PV 和 PVC YAML 文件。
✅ 第二步:构建应用镜像
本方案只包含 php-fpm 进程。
1. Dockerfile 核心内容
FROM ubuntu:22.04
LABEL maintainer="devops@example.com"
# 设置环境变量
ENV PHP_VERSION=8.1.29 \
DEBIAN_FRONTEND=noninteractive
# 使用阿里云镜像源加速 apt
RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list && \
sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
# 安装基础工具和依赖
RUN apt-get update && \
apt-get install -y curl wget gnupg lsb-release ca-certificates && \
rm -rf /var/lib/apt/lists/*
# 添加 PHP GPG 密钥和 APT 源
RUN curl -fsSL https://packages.sury.org/php/apt.gpg | gpg --dearmor -o /usr/share/keyrings/php-archive-keyring.gpg && \
echo "deb [signed-by=/usr/share/keyrings/php-archive-keyring.gpg] https://packages.sury.org/php/ $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/php.list
# 更新软件包列表
RUN apt-get update
# 仅安装 PHP-FPM 及其扩展
RUN apt-get install -y php${PHP_VERSION}-fpm php${PHP_VERSION}-mysql php${PHP_VERSION}-gd php${PHP_VERSION}-curl php${PHP_VERSION}-mbstring php${PHP_VERSION}-xml php${PHP_VERSION}-zip
# 清理缓存
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# 创建 Web 目录
RUN mkdir -p /www/wwwroot/testwanyanzhenjiangapi1.wanyanzhenjiang.com
# 复制自定义 PHP 配置
COPY php.ini /etc/php/${PHP_VERSION}/fpm/php.ini
# 创建 www-data 用户组并加入 php-fpm
RUN groupadd -g 82 www-data && \
usermod -u 82 -g www-data www-data && \
usermod -a -G www-data www-data
# 确保目录权限正确
RUN chown -R www-data:www-data /www
# 启动脚本
COPY start.sh /start.sh
RUN chmod +x /start.sh
CMD ["/start.sh"]
2. 自定义 PHP 配置 (php.ini)
[PHP]
zend.exception_ignore_args = On
zend.exception_string_param_max_len = 0
expose_php = Off
max_execution_time = 15
max_input_time = 30
memory_limit = 512M
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_WARNING & ~E_NOTICE
display_errors = Off
display_startup_errors = Off
log_errors = On
log_errors_max_len = 1024
ignore_repeated_errors = On
ignore_repeated_source = On
report_memleaks = On
variables_order = GPCS
request_order = GP
register_argc_argv = Off
auto_globals_jit = On
post_max_size = 50M
auto_prepend_file =
auto_append_file =
default_mimetype = text/html
default_charset =
[Session]
session.save_handler = files
session.save_path = "/tmp"
session.use_strict_mode = 0
session.use_cookies = 1
session.cookie_secure = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax
session.name = PHPSESSID
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 26
session.sid_bits_per_character = 5
[Date]
date.timezone = Asia/Shanghai
[mbstring]
mbstring.language = neutral
mbstring.internal_encoding = UTF-8
mbstring.http_input = auto
mbstring.http_output = UTF-8
mbstring.encoding_translation = Off
mbstring.detect_order = auto
mbstring.substitute_character = none
mbstring.func_overload = 0
[opcache]
opcache.enable = 1
opcache.enable_cli = 0
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 4000
opcache.validate_timestamps = 1
opcache.revalidate_freq = 2
opcache.fast_shutdown = 1
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off
✅ 优化说明:
expose_php = Off: 隐藏 PHP 版本信息,提升安全性。session.cookie_secure = 1: 仅通过 HTTPS 发送会话 Cookie。opcache.enable = 1: 启用 OPcache,大幅提升 PHP 脚本执行性能。date.timezone = Asia/Shanghai: 设置正确的时区。
3. 启动脚本 (start.sh)
#!/bin/bash
set -e
# 初始化时,如果 NFS 目录为空,可以从备份恢复或克隆代码
# if [ ! "$(ls -A /www/wwwroot/testwanyanzhenjiangapi1.wanyanzhenjiang.com)" ]; then
# git clone https://your-repo.git /www/wwwroot/testwanyanzhenjiangapi1.wanyanzhenjiang.com
# fi
# 启动 PHP-FPM (前台运行,作为主进程)
exec /usr/sbin/php-fpm${PHP_VERSION} --nodaemonize --fpm-config /etc/php/${PHP_VERSION}/fpm/php-fpm.conf
⚠️ 关键点:使用
--nodaemonize参数确保 PHP-FPM 在前台运行,这样它才能接收 SIGTERM 信号并优雅关闭。
✅ 第三步:部署 Kubernetes 资源
1. 创建 TLS Secret
首先,将 SSL 证书和私钥创建为 Kubernetes Secret。
kubectl create secret tls wanyanzhenjiang-com-tls \
--cert=wanyanzhenjiang.com.pem \
--key=wanyanzhenjiang.com.key \
--namespace=test
🔐 敏感信息处理:原文中的证书内容已被移除,实际部署时需使用有效的证书文件。
2. Deployment 配置 (deployment.yaml)
apiVersion: apps/v1
kind: Deployment
meta
name: wanyanzhenjiang-api-deployment
namespace: test
labels:
app: wanyanzhenjiang-api
spec:
replicas: 2
selector:
matchLabels:
app: wanyanzhenjiang-api
template:
meta
labels:
app: wanyanzhenjiang-api
spec:
containers:
- name: php-fpm
image: your-registry/wanyanzhenjiang-api-php:v1.0 # 替换为你的镜像地址
ports:
- containerPort: 9000 # PHP-FPM 默认 FastCGI 端口
volumeMounts:
- name: code-storage
mountPath: /www/wwwroot/testwanyanzhenjiangapi1.wanyanzhenjiang.com
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 200m
memory: 256Mi
volumes:
- name: code-storage
persistentVolumeClaim:
claimName: nfs-pvc-wanyanzhenjiang-api-test
---
apiVersion: v1
kind: Service
meta
name: wanyanzhenjiang-api-service
namespace: test
spec:
selector:
app: wanyanzhenjiang-api
ports:
- protocol: TCP
port: 9000
targetPort: 9000
type: ClusterIP
🔧 核心配置:
containerPort: 9000: PHP-FPM 侦听的 FastCGI 端口。volumeMounts: 挂载 PVC 用于代码和上传文件。
3. Ingress 配置 (ingress.yaml)
apiVersion: networking.k8s.io/v1
kind: Ingress
meta
name: wanyanzhenjiang-api-ingress
namespace: test
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "100m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
# 👇 关键:启用 fastcgi 支持
nginx.ingress.kubernetes.io/fastcgi-index: index.php
nginx.ingress.kubernetes.io/fastcgi-socket-path: /run/php/php8.1-fpm.sock
# 👇 将所有非静态文件请求转发给 php-fpm
nginx.ingress.kubernetes.io/configuration-snippet: |
location ~ \.php$ {
fastcgi_pass wanyanzhenjiang-api-service:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
spec:
ingressClassName: nginx
tls:
- hosts:
- wanyanzhenjiangapi.wanyanzhenjiang.com
secretName: wanyanzhenjiang-com-tls
rules:
- host: wanyanzhenjiangapi.wanyanzhenjiang.com
http:
paths:
# 👇 将根路径映射到代码目录
- path: /
pathType: Prefix
backend:
service:
name: wanyanzhenjiang-api-service
port:
number: 9000
🌐 流量走向:
- 客户端访问
https://wanyanzhenjiangapi.wanyanzhenjiang.com- 请求到达
ingress-nginx-controllerPod。- Ingress Controller 根据
configuration-snippet中的规则:
- 如果是
.php文件,则通过fastcgi_pass将请求转发给后端 Service 的 9000 端口(即 PHP-FPM)。- 如果是静态文件(JS, CSS, 图片),则直接从挂载的代码目录中读取并返回。
- PHP-FPM 执行 PHP 脚本,并将结果返回给 Ingress Controller,最终响应给客户端。
✅ 总结
你已完成以下目标:
✅ 为 PHP 项目设计并实现了“单 Nginx”架构,简化了部署结构
✅ 配置了基于 NFS 的 ReadWriteMany 存储,满足多副本应用的共享存储需求
✅ 编写了仅包含 PHP-FPM 的轻量级生产级 Docker 镜像
✅ 通过 Kubernetes Secret 安全地管理了 SSL 证书
✅ 部署了完整的 Kubernetes 资源(Deployment, Service, Ingress),实现了应用的高可用和外部访问
此方案特别适用于希望简化架构、统一管理入口、并对运维复杂度有要求的新建 PHP 应用迁移至 Kubernetes 的场景。
更多推荐

所有评论(0)