ThinkPHP容器化部署:Kubernetes中实现WebSocket服务
1. 项目背景与核心需求在云原生架构逐渐成为主流的今天将传统PHP应用容器化部署到Kubernetes集群已成为许多开发团队的刚需。ThinkPHP作为国内流行的PHP框架其与WebSocket实时通信能力的结合在客服系统、实时监控等场景中有着广泛需求。但实际部署时会遇到几个典型问题PHP-FPM传统运行模式与常驻内存的WebSocket服务存在天然矛盾单一容器需要同时处理HTTP请求和维持WebSocket长连接Kubernetes的Pod生命周期管理与PHP Worker进程的稳定性需要特殊处理这个方案通过定制Docker镜像在单个容器内实现NginxPHP-FPMWebSocket Worker的协同工作解决了以下痛点传统PHP应用无法保持持久化TCP连接的问题容器内多进程管理的复杂性K8s环境下服务发现的适配2. 技术架构设计2.1 整体方案设计采用分层架构设计[Kubernetes Service] | [Pod] ├── [Nginx] :80 └── [PHP-FPM] ├── Web应用处理 └── [Worker进程] :2346 (WebSocket)关键设计要点使用webdevops/php-nginx镜像作为基础内置Nginx和PHP-FPM的进程管理通过Supervisor管理WebSocket Worker进程的守护模式端口映射80: HTTP服务2346: WebSocket服务2.2 核心组件选型组件版本选择理由基础镜像webdevops/php-nginx:7.4内置NginxPHP-FPM集成方案PHP扩展安装器mlocati/docker-php-extension-installer官方推荐的扩展安装方案进程管理Supervisor可靠的多进程守护方案3. 详细实现步骤3.1 Docker镜像构建3.1.1 Dockerfile配置FROM webdevops/php-nginx:7.4 EXPOSE 2346 # 1. 安装扩展管理工具 ADD ./containerConfig/install-php-extensions /usr/local/bin/ RUN chmod x /usr/local/bin/install-php-extensions sync # 2. 安装必要扩展 RUN install-php-extensions \ pcntl sockets redis \ # 其他业务所需扩展... docker-php-ext-enable opcache # 3. 复制项目代码 COPY . /app # 4. 配置覆盖 RUN cp /app/containerConfig/vhost.conf /opt/docker/etc/nginx/vhost.conf \ cp /app/containerConfig/10-init.sh /opt/docker/bin/service.d/supervisor.d/10-init.sh3.1.2 关键扩展说明pcntl进程控制WebSocket Worker需要socketsWebSocket底层依赖redis常见会话存储方案opcache生产环境必装性能优化扩展3.2 配置文件详解3.2.1 Nginx配置 (vhost.conf)server { listen 80; root /app/public; location / { try_files $uri /index.php$is_args$args; } location ~ \.php$ { # 固定指向容器内PHP-FPM服务 fastcgi_pass php:9000; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } # WebSocket代理配置 location /ws { proxy_pass http://127.0.0.1:2346; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; } }3.2.2 Supervisor启动脚本 (10-init.sh)#!/bin/bash cd /app php think worker:server -d重要提示必须确保脚本有可执行权限chmod x3.3 Kubernetes部署配置3.3.1 Deployment示例apiVersion: apps/v1 kind: Deployment metadata: name: php-websocket spec: replicas: 2 selector: matchLabels: app: php-websocket template: metadata: labels: app: php-websocket spec: containers: - name: php-app image: your-registry/php-demo:v1 ports: - containerPort: 80 - containerPort: 2346 resources: requests: cpu: 500m memory: 512Mi limits: cpu: 1000m memory: 1Gi livenessProbe: httpGet: path: /health port: 80 initialDelaySeconds: 30 periodSeconds: 103.3.2 Service配置apiVersion: v1 kind: Service metadata: name: php-websocket-service spec: selector: app: php-websocket ports: - name: http port: 80 targetPort: 80 - name: websocket port: 2346 targetPort: 2346 type: ClusterIP4. 常见问题与解决方案4.1 WebSocket连接不稳定现象客户端频繁断开重连排查步骤检查Worker进程是否存活kubectl exec -it [pod] -- supervisorctl status验证端口连通性kubectl exec -it [pod] -- netstat -tulnp | grep 2346检查K8s Service的会话保持配置解决方案增加Worker进程的心跳检测机制调整K8s的readinessProbe检查间隔考虑使用Redis存储会话状态4.2 性能优化建议容器资源限制resources: limits: cpu: 2 memory: 2Gi requests: cpu: 1 memory: 1GiPHP参数调优; php.ini pm.max_children 50 pm.start_servers 10 pm.min_spare_servers 5 pm.max_spare_servers 30Nginx优化worker_processes auto; worker_connections 1024; keepalive_timeout 65;5. 进阶实践技巧5.1 多环境配置管理通过ConfigMap实现环境差异配置kubectl create configmap php-config \ --from-fileconfig/test/database.php \ --from-fileconfig/test/cache.php在Deployment中挂载volumes: - name: app-config configMap: name: php-config volumeMounts: - mountPath: /app/config name: app-config5.2 日志收集方案标准输出日志收集# 修改Worker启动命令 php think worker:server -d /proc/1/fd/1使用Filebeat收集# sidecar容器配置 - name: filebeat image: docker.elastic.co/beats/filebeat:7.12.0 volumeMounts: - mountPath: /var/log/php name: php-logs5.3 自动化构建部署CI/CD流水线示例# .gitlab-ci.yml stages: - build - deploy build_image: stage: build script: - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA . - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA deploy_k8s: stage: deploy script: - kubectl set image deployment/php-websocket php-app$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA