本文目录导读:

PHP 与 Istio 集成的核心思路是通过 Istio 的 Sidecar 代理自动拦截 PHP 应用的网络流量,实现服务治理能力(如流量管理、可观测性、安全认证),而无需修改 PHP 代码本身。
下面分几部分详细说明:部署集成、关键配置、常见问题 以及 特殊场景(如长连接、异步任务)。
部署集成(Sidecar 自动注入)
Istio 主要是通过 Init Container(设置网络路由)和 Sidecar Container(Envoy 代理)来实现透明拦截,对于 PHP 应用,需要确保 Pod 创建时注入这些容器。
方式(推荐): 在 Kubernetes 命名空间上启用自动注入。
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: php-app
labels:
istio-injection: enabled
部署 PHP 服务(关键点):
- 确保
labels和ports定义准确,以便 Istio 识别服务。 - 不要声明
hostPort,避免端口冲突。 - PHP-FPM 监听
9000端口,请暴露该端口。
# php-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-fpm
namespace: php-app
spec:
replicas: 2
selector:
matchLabels:
app: php-fpm
template:
metadata:
labels:
app: php-fpm
version: v1
spec:
containers:
- name: php-fpm
image: php:8.2-fpm
ports:
- containerPort: 9000
# 确保有健康检查(Istio 依赖它进行就绪状态判断)
readinessProbe:
tcpSocket:
port: 9000
initialDelaySeconds: 5
periodSeconds: 10
resources:
requests:
cpu: "100m"
memory: "128Mi"
注意:如果是
Apache + mod_php(监听 80 端口),原理相同,只需暴露 80 端口即可。
验证注入:
kubectl -n php-app get pods # 你会看到每个 Pod 有 3 个容器(Init + 主业务 + Envoy) kubectl -n php-app logs deploy/php-fpm -c istio-proxy
配置流量规则
只要 Pod 被注入了 Sidecar,PHP 服务的网格能力就自动开启了,通常需要配置以下资源:
官方 ServiceEntry(使外部调用进入网格)
# destination-rule.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: php-fpm-dr
namespace: php-app
spec:
host: php-fpm
subsets:
- name: v1
labels:
version: v1
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
tls:
mode: ISTIO_MUTUAL # 如果要开启 mTLS
VirtualService(做流量切分或重试)
# virtual-service.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: php-fpm-vs
namespace: php-app
spec:
hosts:
- "php-fpm" # 目标服务
http:
- match:
- uri:
prefix: "/api"
route:
- destination:
host: php-fpm
subset: v1
weight: 100
timeout: 30s
retries:
attempts: 3
perTryTimeout: 2s
关键优化配置
PHP 应用(尤其是 PHP-FPM)与 Istio 集成时,有几点需要特别注意,否则会导致性能问题或连接中断。
A. 处理长连接(FastCGI / 数据库连接)
PHP-FPM 处理完请求后会保持 TCP 连接,等待下一个请求,但 Envoy 默认有 idle timeout(默认 1 小时),PHP 脚本处理时间超过该时长,连接会被 Envoy 切断。
解决方案: 在 DestinationRule 或 VirtualService 中调整超时。
trafficPolicy:
connectionPool:
tcp:
idleTimeout: 300s # 调整为 5 分钟
B. 支持 HTTP/1.1(PHP 默认版本)
Istio 默认支持 HTTP/1.1,但如果你使用 curl 或某些老旧的 PHP 库,需要确保协议匹配。
检查 Envoy 日志:
kubectl logs -n php-app deploy/php-fpm -c istio-proxy --tail=100 | grep "upstream_cluster"
C. 健康检查与就绪探针
Istio 通过 K8s 的就绪探针来判断 Pod 是否就绪,如果探针配置不当,流量可能被拒绝。
建议: 使用 httpGet 或 tcpSocket 探针指向 PHP-FPM 监听的端口,而不是依赖 exec 命令。
常见问题与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 请求 503 / 连接被拒 | PHP-FPM 未监听 0.0.0 |
修改 PHP-FPM 配置 listen = 0.0.0.0:9000 |
| 日志显示“upstream reset” | PHP-FPM 处理超时,Envoy 断开连接 | 设置 Timeout 参数(见上文) |
| Envoy 占内存过大 | PHP 应用中大量调用外部服务 | 开启访问日志并监控;使用 Sidecar 资源的 limits.memory |
| PHP 无法连接 MySQL | MySQL 在网格外或使用了不同的命名空间 | 使用 ServiceEntry 将 MySQL 加入网格,或配置 NETWORK_POLICY |
| mTLS 握手失败 | PHP 应用本身不支持 TLS 或未安装证书 | 在 PeerAuthentication 中设置 PERMISSIVE 模式(兼容模式) |
特殊场景(Swoole / Workerman / 常驻内存)
如果你使用 Swoole 或 Workerman 这类常驻内存的服务(监听 TCP/UDP 长连接),集成方式略有不同:
- 协议匹配:Swoole 默认使用 TCP 或自定义协议,Istio 默认是 HTTP,需要配置
VirtualService的tcp规则,或使用HTTP/2。 - 连接保持:长连接会导致 Envoy 的并发连接数被占用,需调大
connectionPool.tcp.maxConnections。 - 端口协议:K8s 需要将端口协议声明为
TCP,否则 Istio 可能误判为 HTTP。
ports: - name: tcp-9501 # 必须包含协议前缀 tcp- containerPort: 9501
完整示例:PHP + Nginx 架构
PHP 应用是 Nginx + PHP-FPM 两层,Nginx 充当 Web 服务器,此时只需将 Nginx 容器 和 PHP-FPM 容器 放在同一个 Pod 中(共享网络),然后只让 Nginx 暴露端口,Istio 只拦截 Nginx 的流量。
containers: - name: nginx image: nginx:latest ports: - containerPort: 80 # Nginx 通过 127.0.0.1:9000 访问 PHP-FPM(流量在 Pod 内部,不经过 Sidecar) - name: php-fpm image: php:8.2-fpm # 不暴露端口,仅通过 localhost 访问
好处:
- PHP 内部通信(如 Redis、MySQL)由 Nginx 或 PHP-FPM 自己处理,不经过 Sidecar,性能损耗小。
- Istio 只需统一管理对外流量。
- 核心:无需改代码,通过 K8s 标签和 Istio 自动注入即可。
- 关键调优:重点调整超时时间、健康检查、连接池参数。
- 排查手段:检查
istio-proxy日志和envoy配置。 - 性能考虑:PHP 应用性能瓶颈通常不在网络层,尽可能让 Istio 只处理南北向流量,内部服务调用走 K8s Service。
如果你的 PHP 服务出现问题时,可以再告诉我具体现象(503、超时、TLS 错误),我可以帮你进一步分析。