基于 Kubernetes 的 PHP 项目双 Nginx 架构虚拟化部署
·
本文详细记录了在现有 Kubernetes 集群上,为一个 PHP 项目部署“双 Nginx”架构的完整过程。该方案采用 应用内嵌 Nginx + 外部 Ingress Nginx 的模式,实现了动静分离、高性能反向代理和灵活的外部访问控制。
📋 架构概览
| 项目 | 配置 |
|---|---|
| 应用类型 | PHP (ThinkPHP) |
| 容器运行时 | containerd |
| 部署方式 | Kubernetes Deployment |
| 网络架构 | 双 Nginx 模式 |
| 存储 | NFS PersistentVolume |
| Ingress 控制器 | ingress-nginx |
🏗️ “双 Nginx” 架构详解
-
内部 Nginx (Pod 内):
- 作为 PHP-FPM 的前置服务器,直接处理所有请求。
- 负责静态文件(JS, CSS, 图片)的高效服务。
- 将 PHP 动态请求通过
fastcgi_pass转发给同 Pod 内的 PHP-FPM 进程。 - 提供应用级的 URL 重写和安全规则。
-
外部 Ingress Nginx (Kubernetes 层):
- 作为集群的统一入口,管理所有对外暴露的服务。
- 接收来自客户端的所有流量,并根据 Host 和 Path 规则将请求路由到后端 Service。
- 统一处理 TLS/SSL 加密、HTTP 到 HTTPS 重定向等。
- 实现跨应用的负载均衡和高级流量管理。
✅ 优势:
- 性能:内部 Nginx 直接服务静态资源,避免了 Ingress 层的数据拷贝。
- 灵活性:可以独立配置每个应用的 Nginx 规则,无需修改全局 Ingress 配置。
- 隔离性:应用的特定需求(如复杂的 rewrite 规则)由内部 Nginx 承载,不影响其他服务。
✅ 第一步:准备持久化存储 (NFS)
为 PHP 应用创建基于 NFS 的持久化存储,用于存放代码和上传文件。
1. 创建 NFS PersistentVolume
# nfs-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv-dbb-live-api-test
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteMany # 必须支持多节点读写
persistentVolumeReclaimPolicy: Retain
nfs:
server: 192.168.122.189 # NFS 服务器 IP
path: /opt/nfs/dbb-live-api-test # NFS 共享目录
mountOptions:
- nfsvers=4.1
- hard
- intr
2. 创建 PersistentVolumeClaim
# nfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc-dbb-live-api-test
namespace: test # 部署目标命名空间
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
volumeName: nfs-pv-dbb-live-api-test # 关联已创建的 PV
🔧 操作步骤:
- 在 NFS 服务器 (
192.168.122.189) 上创建共享目录并设置权限:sudo mkdir -p /opt/nfs/dbb-live-api-test sudo chmod 755 /opt/nfs/dbb-live-api-test- 在
/etc/exports中添加导出规则:/opt/nfs/dbb-live-api-test *(rw,sync,no_root_squash)- 重新加载 NFS 配置:
exportfs -ra- 在 Kubernetes 集群中应用 PV 和 PVC YAML 文件。
✅ 第二步:构建应用镜像
本方案将 Nginx 和 PHP-FPM 打包进同一个 Docker 镜像。
1. Dockerfile 核心内容
FROM ubuntu:22.04
LABEL maintainer="devops@example.com"
# 设置环境变量
ENV NGINX_VERSION=1.26.2 \
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/*
# 添加 Nginx GPG 密钥和 APT 源
RUN curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor -o /usr/share/keyrings/nginx-archive-keyring.gpg && \
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" | tee /etc/apt/sources.list.d/nginx.list && \
echo "deb-src [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" | tee -a /etc/apt/sources.list.d/nginx.list
# 添加 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
# 安装 Nginx 和 PHP-FPM
RUN apt-get install -y nginx=${NGINX_VERSION}* 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/testliveapi1.doubbjt.com /var/log/nginx
# 复制自定义 Nginx 配置
COPY nginx.conf /etc/nginx/nginx.conf
COPY liveapi.doubbjt.com.conf /etc/nginx/conf.d/liveapi.doubbjt.com.conf
# 复制自定义 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 /var/log/nginx
# 暴露端口
EXPOSE 80
# 启动脚本
COPY start.sh /start.sh
RUN chmod +x /start.sh
CMD ["/start.sh"]
2. 自定义 Nginx 配置 (liveapi.doubbjt.com.conf)
server {
listen 80;
server_name liveapi.doubbjt.com;
# ⭐ 根目录指向挂载的 NFS 卷
root /www/wwwroot/testliveapi1.doubbjt.com;
index index.php index.html index.htm;
# ⭐ SSL 配置(证书和私钥从 Secret 挂载)
ssl_certificate /ssl/doubbjt.com.pem;
ssl_certificate_key /ssl/doubbjt.com.key;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000";
error_page 497 https://$host$request_uri;
# ⭐ 主要 location 块:反向代理到 PHP-FPM
location / {
proxy_pass http://dbb-live-api-service.test.svc.cluster.local:80;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_buffering off;
proxy_request_buffering off;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
client_max_body_size 100M;
}
# ⭐ Let's Encrypt 验证专用路径
location ^~ /.well-known/acme-challenge/ {
root /www/wwwroot/testliveapi1.doubbjt.com;
allow all;
default_type "text/plain";
try_files $uri =404;
}
# ⭐ 日志配置
access_log /var/log/nginx/liveapi.doubbjt.com.log main;
error_log /var/log/nginx/liveapi.doubbjt.com.error.log;
}
🔐 关键点:
location /: 将所有请求反向代理到后端的 Kubernetes Service。此配置确保了即使在 Pod 内,请求也遵循与生产环境一致的路由逻辑。location ^~ /.well-known/acme-challenge/: 为 Cert-Manager 等工具提供 ACME 挑战验证的专用路径。client_max_body_size 100M;: 允许大文件上传。
3. 自定义 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: 设置正确的时区。
4. 启动脚本 (start.sh)
#!/bin/bash
set -e
# 确保 Nginx 和 PHP-FPM 日志目录存在
mkdir -p /var/log/nginx /var/log/php-fpm
# 初始化时,如果 NFS 目录为空,可以从备份恢复或克隆代码
# if [ ! "$(ls -A /www/wwwroot/testliveapi1.doubbjt.com)" ]; then
# git clone https://your-repo.git /www/wwwroot/testliveapi1.doubbjt.com
# fi
# 启动 PHP-FPM (后台运行)
/usr/sbin/php-fpm${PHP_VERSION} --daemonize --fpm-config /etc/php/${PHP_VERSION}/fpm/php-fpm.conf
# 启动 Nginx (前台运行,作为主进程)
exec /usr/sbin/nginx -g "daemon off;"
✅ 第三步:部署 Kubernetes 资源
1. 创建 TLS Secret
首先,将 SSL 证书和私钥创建为 Kubernetes Secret。
kubectl create secret tls doubbjt-com-tls \
--cert=doubbjt.com.pem \
--key=doubbjt.com.key \
--namespace=test
🔐 敏感信息处理:原文中的证书内容已被移除,实际部署时需使用有效的证书文件。
2. Deployment 配置 (deployment.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:
name: dbb-live-api-deployment
namespace: test
labels:
app: dbb-live-api
spec:
replicas: 2
selector:
matchLabels:
app: dbb-live-api
template:
metadata:
labels:
app: dbb-live-api
spec:
containers:
- name: nginx-php
image: your-registry/dbb-live-api:v1.0 # 替换为你的镜像地址
ports:
- containerPort: 80
volumeMounts:
- name: code-storage
mountPath: /www/wwwroot/testliveapi1.doubbjt.com
- name: ssl-certs
mountPath: /ssl
readOnly: true
- name: nginx-logs
mountPath: /var/log/nginx
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 200m
memory: 256Mi
volumes:
- name: code-storage
persistentVolumeClaim:
claimName: nfs-pvc-dbb-live-api-test
- name: ssl-certs
secret:
secretName: doubbjt-com-tls
- name: nginx-logs
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: dbb-live-api-service
namespace: test
spec:
selector:
app: dbb-live-api
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
🔧 核心配置:
volumeMounts: 挂载 PVC 用于代码和上传文件,挂载 Secret 用于 SSL 证书。resources: 定义合理的 CPU 和内存限制。
3. Ingress 配置 (ingress.yaml)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: dbb-live-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"
spec:
ingressClassName: nginx
tls:
- hosts:
- liveapi.doubbjt.com
secretName: doubbjt-com-tls
rules:
- host: liveapi.doubbjt.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: dbb-live-api-service
port:
number: 80
🌐 流量走向:
- 客户端访问
https://liveapi.doubbjt.com- 请求到达
ingress-nginx-controllerPod。- Ingress Controller 根据规则,将请求转发到
dbb-live-api-service。- Service 将请求负载均衡到任一
dbb-live-api-deployment的 Pod。- Pod 内的 内部 Nginx 接收到请求,根据其配置进行处理(例如,如果是 PHP 请求,则通过
fastcgi_pass转发给同 Pod 内的 PHP-FPM)。
✅ 总结
你已完成以下目标:
✅ 为 PHP 项目设计并实现了“双 Nginx”架构,兼顾性能与灵活性
✅ 配置了基于 NFS 的 ReadWriteMany 存储,满足多副本应用的共享存储需求
✅ 编写了包含 Nginx、PHP-FPM 和自定义配置的生产级 Docker 镜像
✅ 通过 Kubernetes Secret 安全地管理了 SSL 证书
✅ 部署了完整的 Kubernetes 资源(Deployment, Service, Ingress),实现了应用的高可用和外部访问
此方案特别适用于需要高性能静态资源服务、复杂 URL 重写或对 PHP 环境有精细控制需求的传统 PHP 应用迁移至 Kubernetes 的场景。
更多推荐

所有评论(0)