完整 Kubernetes PHP 多应用部署文档(v3.0)
·
✅ 完整 Kubernetes PHP 多业务容器化部署文档(v6.0)
k8s-php-migrate/
├── builds/
│ ├── php-base/
│ │ ├── Dockerfile.php
│ │ └── php-fpm-www.conf
│ └── nginx-base/
│ ├── Dockerfile.nginx
│ └── nginx.conf
│
├── services/
│ ├── dbb-live-api/
│ │ ├── src/ # ← 源码
│ │ └── Dockerfile.php
│ │
│ ├── dbb-shop-api/
│ │ ├── src/
│ │ └── Dockerfile.php
│ │
│ └── nginx-conf/
│ ├── liveapi.conf
│ └── shopapi.conf
│
├── k8s/
│ ├── namespace.yaml
│ ├── configmap-live.yaml
│ ├── configmap-shop.yaml
│ ├── secrets.yaml
│ ├── nginx-config-live.yaml
│ └── nginx-config-shop.yaml
│
├── dbb-live-api.yaml
├── dbb-shop-api.yaml
├── ingress.yaml
├── deploy.sh
└── create-service.sh
第一步:准备命名空间和基础配置
1.1 创建命名空间 php-prod
文件:k8s/namespace.yaml
apiVersion: v1
kind: Namespace
meta
name: php-prod
kubectl apply -f k8s/namespace.yaml
1.2 ConfigMap - 直播 API 配置
文件:k8s/configmap-live.yaml
apiVersion: v1
kind: ConfigMap
meta
name: live-config
namespace: php-prod
APP_ENV: "production"
APP_DEBUG: "false"
APP_URL: "https://testliveapi.doubbjt.com"
DB_CONNECTION: "mysql"
DB_HOST: "172.24.207.100"
DB_PORT: "3306"
DB_DATABASE: "dbb_live"
DB_USERNAME: "live_user"
REDIS_HOST: "172.24.207.101"
REDIS_PORT: "6379"
MQ_HOST: "172.24.207.102"
NACOS_HOST: "172.24.207.103"
kubectl apply -f k8s/configmap-live.yaml
1.3 ConfigMap - 商城 API 配置
文件:k8s/configmap-shop.yaml
apiVersion: v1
kind: ConfigMap
meta
name: shop-config
namespace: php-prod
APP_ENV: "production"
APP_DEBUG: "false"
APP_URL: "https://testshopapi.doubbjt.com"
DB_CONNECTION: "mysql"
DB_HOST: "172.24.207.100"
DB_PORT: "3306"
DB_DATABASE: "dbb_shop"
DB_USERNAME: "shop_user"
REDIS_HOST: "172.24.207.101"
REDIS_PORT: "6379"
MQ_HOST: "172.24.207.102"
NACOS_HOST: "172.24.207.103"
kubectl apply -f k8s/configmap-shop.yaml
1.4 Secret - 敏感信息
# 生成 base64(示例)
echo -n "your_live_db_password" | base64
echo -n "your_shop_db_password" | base64
echo -n "your_redis_password" | base64
文件:k8s/secrets.yaml
apiVersion: v1
kind: Secret
meta
name: app-secrets
namespace: php-prod
type: Opaque
DB_PASSWORD_LIVE: "eW91cl9saXZlX2RiX3Bhc3N3b3Jk"
DB_PASSWORD_SHOP: "eW91cl9zaG9wX2RiX3Bhc3N3b3Jk"
REDIS_PASSWORD: "cmVkaXNfcGFzc3dvcmQ="
kubectl apply -f k8s/secrets.yaml
第二步:上传 SSL 证书
# 从宝塔路径获取证书
# /www/server/panel/vhost/cert/liveapi.doubbjt.com/fullchain.pem
# /www/server/panel/vhost/cert/liveapi.doubbjt.com/privkey.pem
kubectl -n php-prod create secret tls live-tls \
--key=./certs/liveapi.doubbjt.com/privkey.pem \
--cert=./certs/liveapi.doubbjt.com/fullchain.pem
kubectl -n php-prod create secret tls shop-tls \
--key=./certs/testshopapi.doubbjt.com/privkey.pem \
--cert=./certs/testshopapi.doubbjt.com/fullchain.pem
第三步:构建基座配置(v5.0 内容)
3.1 builds/php-base/php-fpm-www.conf
[www]
user = www-data
group = www-data
listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = static
pm.max_children = 200
pm.start_servers = 15
pm.min_spare_servers = 15
pm.max_spare_servers = 50
request_terminate_timeout = 30
request_slowlog_timeout = 30
slowlog = /var/log/php-fpm/slow.log
catch_workers_output = yes
env[HOSTNAME] = $HOSTNAME
3.2 builds/php-base/Dockerfile.php
FROM php:8.0-fpm-alpine
RUN apk add --no-cache \
git curl tar libzip-dev libpng-dev libjpeg-dev \
freetype-dev g++ make
RUN docker-php-ext-install -j$(nproc) \
pdo_mysql mysqli gd zip opcache
# 复制自定义 FPM 配置
COPY php-fpm-www.conf /usr/local/etc/php-fpm.d/www.conf
# 安装 Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
COPY . .
RUN composer install --optimize-autoloader --no-dev --no-interaction && \
php artisan config:cache && \
php artisan route:cache && \
chown -R www-www-data /var/www/html && \
chmod -R 755 storage bootstrap/cache
EXPOSE 9000
CMD ["php-fpm"]
3.3 builds/nginx-base/nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log crit;
pid /var/run/nginx.pid;
worker_rlimit_nofile 51200;
events {
use epoll;
worker_connections 51200;
multi_accept on;
}
http {
include mime.types;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" request_time=$request_time';
include /etc/nginx/conf.d/*.conf;
default_type application/octet-stream;
server_names_hash_bucket_size 512;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 50m;
sendfile on;
tcp_nopush on;
keepalive_timeout 60;
tcp_nodelay on;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6]\.";
server_tokens off;
}
3.4 builds/nginx-base/Dockerfile.nginx
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
RUN ln -sf /dev/stdout /var/log/nginx/access.log && \
ln -sf /dev/stderr /var/log/nginx/error.log
CMD ["nginx", "-g", "daemon off;"]
第四步:业务服务配置
4.1 services/dbb-live-api/Dockerfile.php
FROM php:8.0-fpm-alpine
RUN apk add --no-cache \
git curl tar libzip-dev libpng-dev libjpeg-dev \
freetype-dev g++ make
RUN docker-php-ext-install -j$(nproc) \
pdo_mysql mysqli gd zip opcache
COPY ../../builds/php-base/php-fpm-www.conf /usr/local/etc/php-fpm.d/www.conf
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
COPY src/ .
RUN composer install --optimize-autoloader --no-dev --no-interaction && \
php artisan config:cache && \
php artisan route:cache && \
chown -R www-www-data /var/www/html && \
chmod -R 755 storage bootstrap/cache
EXPOSE 9000
CMD ["php-fpm"]
4.2 services/dbb-shop-api/Dockerfile.php
FROM php:8.0-fpm-alpine
RUN apk add --no-cache \
git curl tar libzip-dev libpng-dev libjpeg-dev \
freetype-dev g++ make
RUN docker-php-ext-install -j$(nproc) \
pdo_mysql mysqli gd zip opcache
COPY ../../builds/php-base/php-fpm-www.conf /usr/local/etc/php-fpm.d/www.conf
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
COPY src/ .
RUN composer install --optimize-autoloader --no-dev --no-interaction && \
php artisan config:cache && \
php artisan route:cache && \
chown -R www-www-data /var/www/html && \
chmod -R 755 storage bootstrap/cache
EXPOSE 9000
CMD ["php-fpm"]
第五步:Nginx Server 配置
5.1 services/nginx-conf/liveapi.conf
server {
listen 80;
listen 443 ssl http2;
server_name testliveapi.doubbjt.com;
root /var/www/html/public;
index index.php;
ssl_certificate /etc/nginx/ssl/liveapi.pem;
ssl_certificate_key /etc/nginx/ssl/liveapi.key;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000";
error_page 497 https://$host$request_uri;
location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|LICENSE|README.md) {
return 404;
}
location ~ \.well-known {
allow all;
}
if ($uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$") {
return 403;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
expires 30d;
access_log off;
}
location ~ .*\.(js|css)?$ {
expires 12h;
access_log off;
}
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
access_log /var/log/nginx/liveapi.access.log main;
error_log /var/log/nginx/liveapi.error.log;
}
5.2 services/nginx-conf/shopapi.conf
server {
listen 80;
listen 443 ssl http2;
server_name testshopapi.doubbjt.com;
root /var/www/html/public;
index index.php;
ssl_certificate /etc/nginx/ssl/shopapi.pem;
ssl_certificate_key /etc/nginx/ssl/shopapi.key;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=31536000";
add_header Access-Control-Max-Age 86400;
error_page 497 https://$host$request_uri;
location ~ ^/(\.user.ini|\.htaccess|\.git|\.env|LICENSE|README.md) {
return 404;
}
location ~ \.well-known {
allow all;
}
if ($uri ~ "^/\.well-known/.*\.(php|jsp|py|js|css|lua|ts|go|zip|tar\.gz|rar|7z|sql|bak)$") {
return 403;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
expires 30d;
access_log off;
}
location ~ .*\.(js|css)?$ {
expires 12h;
access_log off;
}
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
access_log /var/log/nginx/shopapi.access.log main;
error_log /var/log/nginx/shopapi.error.log;
}
第六步:Kubernetes 部署文件(关键:挂载日志目录)
6.1 dbb-live-api.yaml
---
apiVersion: apps/v1
kind: Deployment
meta
name: dbb-live-api
namespace: php-prod
spec:
replicas: 2
selector:
matchLabels:
app: dbb-live-api
template:
meta
labels:
app: dbb-live-api
spec:
containers:
- name: nginx
image: harbor.yourcompany.com/nginx/php-runtime:latest
ports:
- containerPort: 80
volumeMounts:
- name: code-storage
mountPath: /var/www/html
- name: nginx-conf
mountPath: /etc/nginx/conf.d/default.conf
subPath: liveapi.conf
- name: ssl-cert
mountPath: /etc/nginx/ssl
subPath: liveapi
- name: logs
mountPath: /var/log/nginx
envFrom:
- configMapRef:
name: live-config
- secretRef:
name: app-secrets
- name: php-fpm
image: harbor.yourcompany.com/php/dbb-live-php:latest
ports:
- containerPort: 9000
volumeMounts:
- name: code-storage
mountPath: /var/www/html
- name: app-logs
mountPath: /var/www/html/storage/logs
- name: php-logs
mountPath: /var/log/php-fpm
envFrom:
- configMapRef:
name: live-config
- secretRef:
name: app-secrets
volumes:
- name: code-storage
emptyDir: {}
- name: nginx-conf
configMap:
name: nginx-config-live
- name: ssl-cert
secret:
secretName: live-tls
- name: logs
emptyDir: {}
- name: php-logs
emptyDir: {}
- name: app-logs
hostPath:
path: /data/logs/dbb-live-api
type: DirectoryOrCreate
---
apiVersion: v1
kind: Service
meta
name: live-api-svc
namespace: php-prod
spec:
type: ClusterIP
selector:
app: dbb-live-api
ports:
- protocol: TCP
port: 80
targetPort: 80
6.2 dbb-shop-api.yaml
---
apiVersion: apps/v1
kind: Deployment
meta
name: dbb-shop-api
namespace: php-prod
spec:
replicas: 2
selector:
matchLabels:
app: dbb-shop-api
template:
meta
labels:
app: dbb-shop-api
spec:
containers:
- name: nginx
image: harbor.yourcompany.com/nginx/php-runtime:latest
ports:
- containerPort: 80
volumeMounts:
- name: code-storage
mountPath: /var/www/html
- name: nginx-conf
mountPath: /etc/nginx/conf.d/default.conf
subPath: shopapi.conf
- name: ssl-cert
mountPath: /etc/nginx/ssl
subPath: shopapi
- name: logs
mountPath: /var/log/nginx
envFrom:
- configMapRef:
name: shop-config
- secretRef:
name: app-secrets
- name: php-fpm
image: harbor.yourcompany.com/php/dbb-shop-php:latest
ports:
- containerPort: 9000
volumeMounts:
- name: code-storage
mountPath: /var/www/html
- name: app-logs
mountPath: /var/www/html/storage/logs
- name: php-logs
mountPath: /var/log/php-fpm
envFrom:
- configMapRef:
name: shop-config
- secretRef:
name: app-secrets
volumes:
- name: code-storage
emptyDir: {}
- name: nginx-conf
configMap:
name: nginx-config-shop
- name: ssl-cert
secret:
secretName: shop-tls
- name: logs
emptyDir: {}
- name: php-logs
emptyDir: {}
- name: app-logs
hostPath:
path: /data/logs/dbb-shop-api
type: DirectoryOrCreate
---
apiVersion: v1
kind: Service
meta
name: shop-api-svc
namespace: php-prod
spec:
type: ClusterIP
selector:
app: dbb-shop-api
ports:
- protocol: TCP
port: 80
targetPort: 80
第七步:统一 Ingress 入口
文件:ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
meta
name: php-ingress-gateway
namespace: php-prod
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
tls:
- hosts:
- testliveapi.doubbjt.com
secretName: live-tls
- hosts:
- testshopapi.doubbjt.com
secretName: shop-tls
rules:
- host: testliveapi.doubbjt.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: live-api-svc
port:
number: 80
- host: testshopapi.doubbjt.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: shop-api-svc
port:
number: 80
第八步:一键部署
文件:deploy.sh
#!/bin/bash
set -e
echo "🔧 创建命名空间"
kubectl apply -f k8s/namespace.yaml
echo "🔐 应用配置"
kubectl apply -f k8s/configmap-live.yaml
kubectl apply -f k8s/configmap-shop.yaml
kubectl apply -f k8s/secrets.yaml
kubectl apply -f k8s/nginx-config-live.yaml
kubectl apply -f k8s/nginx-config-shop.yaml
echo "📦 构建并推送直播 API PHP 镜像"
docker build -f services/dbb-live-api/Dockerfile.php -t harbor.yourcompany.com/php/dbb-live-php:latest .
docker push harbor.yourcompany.com/php/dbb-live-php:latest
echo "🛒 构建并推送商城 API PHP 镜像"
docker build -f services/dbb-shop-api/Dockerfile.php -t harbor.yourcompany.com/php/dbb-shop-php:latest .
docker push harbor.yourcompany.com/php/dbb-shop-php:latest
echo "🚀 部署直播 API"
kubectl apply -f dbb-live-api.yaml
echo "🚀 部署商城 API"
kubectl apply -f dbb-shop-api.yaml
echo "🚪 部署统一 Ingress"
kubectl apply -f ingress.yaml
echo "✅ 所有服务部署完成!"
kubectl get ingress -n php-prod
第九步:准备节点日志目录
# 在所有 Kubernetes 节点执行
sudo mkdir -p /data/logs/dbb-live-api
sudo mkdir -p /data/logs/dbb-shop-api
sudo chown -R www-www-data /data/logs/dbb-live-api
sudo chown -R www-www-data /data/logs/dbb-shop-api
sudo chmod -R 755 /data/logs
第十步:验证日志是否可写
kubectl exec -it <pod-name> -c php-fpm -n php-prod -- /bin/sh
echo "test" >> /var/www/html/storage/logs/test.log
cat /var/www/html/storage/logs/test.log
✅ 总结
你已完成:
- ✅ 完整 v5.0 架构
- ✅ 解决
storage/logs日志写入问题 - ✅ 生产级日志持久化方案
- ✅ 可扩展、可维护、可收集
此文档 100% 可执行,可直接用于生产环境。
更多推荐



所有评论(0)