K8s Ingress中PHP静态资源Nginx配置失效问题
K8s Ingress部署PHP应用静态资源及FPM访问问题
我通过K8s Ingress部署了PHP应用,原本能正常访问index.php和面板,PHP-FPM执行也没问题,但静态资源一直无法访问。本地Docker Compose里用的Nginx服务器片段配置能正常工作,但放到Ingress里就失效了。之前还能看到Ingress发往FPM的请求,但静态资源链接始终返回404;修改配置后更糟,现在连FPM都访问不了,请求直接被Ingress拦截返回404。我查了大量文档试了各种配置都解决不了,不想在FPM Pod里加Nginx容器,觉得这不是最佳实践,而且Ingress早就支持直接转发请求到FPM的场景。
相关配置如下:
apiVersion: v1 kind: ConfigMap metadata: name: ingress-cm data: SCRIPT_FILENAME: "/var/www/index.php" --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: "nginx" cert-manager.io/cluster-issuer: letsencrypt nginx.ingress.kubernetes.io/proxy-read-timeout: "1800" nginx.ingress.kubernetes.io/proxy-send-timeout: "1800" nginx.ingress.kubernetes.io/fastcgi_send_timeout: "1800" nginx.ingress.kubernetes.io/fastcgi_read_timeout: "1800" nginx.ingress.kubernetes.io/backend-protocol: "FCGI" nginx.ingress.kubernetes.io/fastcgi-index: "index.php" nginx.ingress.kubernetes.io/fastcgi-params-configmap: "ingress-cm" nginx.ingress.kubernetes.io/server-snippet: | ... location ~ ^/themes/.*/assets { try_files $uri 404; } location ~ ^/themes/.*/bundles { try_files $uri 404; } location ~ ^/themes/.*/resources { try_files $uri 404; } name: app-ingress spec: tls: - hosts: - {url} secretName: letsencrypt rules: - host: {url} http: paths: - path: / pathType: Prefix backend: service: name: app-service port: number: 9000 --- apiVersion: apps/v1 kind: Deployment metadata: name: app labels: app: app spec: replicas: 1 selector: matchLabels: app: app template: metadata: labels: app: app spec: imagePullSecrets: - name: {reg} containers: - name: app image: {image} ports: - containerPort: 9000 --- apiVersion: v1 kind: Service metadata: name: app-service labels: run: app-service spec: ports: - port: 9000 protocol: TCP selector: app: app
问题核心分析
- 静态资源访问失败:Ingress Controller是独立Pod,无法直接读取FPM Pod内的静态文件。之前的配置要么把静态请求转发给FPM(FPM无法处理静态资源返回404),要么Ingress自身找不到文件返回404。
- FPM突然无法访问:修改配置后,
server-snippet中的location规则覆盖了默认的FCGI转发逻辑,导致动态请求没有被发送到FPM服务。
解决方案
方案1:通过共享存储让Ingress直接访问静态资源
这种方案让Ingress Controller和FPM Pod共享静态资源存储,Ingress直接返回静态文件,动态请求转发给FPM。
修改ConfigMap参数:
apiVersion: v1 kind: ConfigMap metadata: name: ingress-cm data: SCRIPT_FILENAME: "/var/www/$fastcgi_script_name" PATH_INFO: "$fastcgi_path_info"把固定的
index.php改为$fastcgi_script_name,确保动态请求能正确对应到PHP文件路径。调整Ingress配置:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: "nginx" cert-manager.io/cluster-issuer: letsencrypt nginx.ingress.kubernetes.io/proxy-read-timeout: "1800" nginx.ingress.kubernetes.io/proxy-send-timeout: "1800" nginx.ingress.kubernetes.io/fastcgi_send_timeout: "1800" nginx.ingress.kubernetes.io/fastcgi_read_timeout: "1800" nginx.ingress.kubernetes.io/backend-protocol: "FCGI" nginx.ingress.kubernetes.io/fastcgi-index: "index.php" nginx.ingress.kubernetes.io/fastcgi-params-configmap: "ingress-cm" nginx.ingress.kubernetes.io/server-snippet: | root /var/www; # 优先处理静态资源 location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg)$ { try_files $uri =404; expires 1y; add_header Cache-Control "public, immutable"; } location ~ ^/themes/.*/(assets|bundles|resources) { try_files $uri =404; } name: app-ingress spec: tls: - hosts: - {url} secretName: letsencrypt rules: - host: {url} http: paths: - path: / pathType: Prefix backend: service: name: app-service port: number: 9000挂载共享存储:创建PVC存储静态资源,同时挂载到Ingress Controller Pod和FPM Pod(需修改Ingress Controller的Deployment配置添加挂载)。
方案2:拆分静态资源到独立服务(更推荐)
将静态资源部署为独立的Nginx服务,Ingress根据路径转发请求,彻底解耦动态和静态服务。
- 部署静态资源服务:创建一个Nginx Deployment和Service,挂载包含静态资源的PVC或使用内置静态资源的镜像。
- 修改Ingress配置:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: "nginx" cert-manager.io/cluster-issuer: letsencrypt nginx.ingress.kubernetes.io/proxy-read-timeout: "1800" nginx.ingress.kubernetes.io/proxy-send-timeout: "1800" nginx.ingress.kubernetes.io/fastcgi_send_timeout: "1800" nginx.ingress.kubernetes.io/fastcgi_read_timeout: "1800" nginx.ingress.kubernetes.io/backend-protocol: "FCGI" nginx.ingress.kubernetes.io/fastcgi-index: "index.php" nginx.ingress.kubernetes.io/fastcgi-params-configmap: "ingress-cm" name: app-ingress spec: tls: - hosts: - {url} secretName: letsencrypt rules: - host: {url} http: paths: # 静态资源路径转发到静态服务 - path: /themes pathType: Prefix backend: service: name: static-service port: number: 80 - path: /css pathType: Prefix backend: service: name: static-service port: number: 80 - path: /js pathType: Prefix backend: service: name: static-service port: number: 80 # 其余请求转发到FPM - path: / pathType: Prefix backend: service: name: app-service port: number: 9000
关键注意事项
- 不要用固定的
SCRIPT_FILENAME,必须使用$fastcgi_script_name确保动态请求路径正确。 - 静态资源的location规则优先级高于默认的Prefix路径,确保静态请求先被处理。
- 若使用共享存储,需确保Ingress Controller和FPM Pod的挂载路径一致,且文件权限正确。
内容的提问来源于stack exchange,提问作者muhammed ikinci
相关产品推荐
相关产品推荐

