K8s + Nacos(YAML + MySQL + NodePort)+ PHP 项目对接 Nacos 配置中心
·
🧩 一、整体架构
+----------------+ +------------------+
| Client | <-> | Nginx (Pod) |
+----------------+ +--------+---------+
|
v
+---------+----------+
| PHP-FPM (sock) |
+---------+----------+
|
v
+--------v--------+
| Nacos Server |
+--------+--------+
|
v
+----v-----+
| MySQL |
+----------+
- 所有配置从 Nacos 拉取,替代
.env - 使用
php-fpm.sock通信(Unix Socket) - 支持平滑上下线(PreStop 注销 Nacos)
- 支持 K8s 滚动更新
📦 二、项目结构
php-nacos-app/
├── src/
│ ├── index.php
│ └── config/
│ └── nacos_loader.php
├── nginx/
│ └── nginx.conf
├── docker/
│ ├── php-fpm.Dockerfile
│ └── nginx.Dockerfile
├── k8s/
│ ├── nacos-deploy.yaml
│ ├── php-deploy.yaml
│ └── configmap-fallback.yaml
└── README.md
🐘 三、PHP 代码改造
1. src/index.php
<?php
// src/index.php
require_once __DIR__ . '/../config/nacos_loader.php';
header("Content-Type: text/html; charset=utf-8");
echo "<h1>✅ PHP 服务运行中</h1>";
echo "<p><strong>应用名称:</strong>" . APP_NAME . "</p>";
echo "<p><strong>环境:</strong>" . APP_ENV . "</p>";
echo "<p><strong>数据库:</strong>" . DB_HOST . "</p>";
echo "<p><strong>配置来源:</strong>Nacos(Data ID: " . ($_ENV['NAOCUS_DATA_ID'] ?? 'php-app-prod.yaml') . ")</p>";
echo "<p><strong>Pod IP:</strong>" . ($_SERVER['SERVER_ADDR'] ?? 'unknown') . "</p>";
2. config/nacos_loader.php
<?php
// config/nacos_loader.php
class NacosConfigLoader
{
private $nacosHost;
private $dataId;
private $group;
public function __construct($host = 'nacos.middleware.svc.cluster.local', $port = 8848)
{
$this->nacosHost = "{$host}:{$port}";
$this->dataId = $_ENV['NAOCUS_DATA_ID'] ?? 'php-app-prod.yaml';
$this->group = $_ENV['NAOCUS_GROUP'] ?? 'DEFAULT_GROUP';
}
public function load(): array
{
$url = "http://{$this->nacosHost}/nacos/v1/cs/configs?dataId=" . urlencode($this->dataId) . "&group=" . urlencode($this->group);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && $response) {
return $this->parseYaml($response);
}
error_log("⚠️ Nacos 配置拉取失败,使用降级配置");
return $this->getFallbackConfig();
}
private function parseYaml($content): array
{
$config = [];
foreach (explode("\n", $content) as $line) {
$line = trim($line);
if (empty($line) || strpos($line, ':') === false || $line[0] === '#') continue;
[$k, $v] = explode(':', $line, 2);
$config[trim($k)] = trim($v);
}
return $config;
}
private function getFallbackConfig(): array
{
return [
'APP_NAME' => 'Fallback App',
'APP_ENV' => 'fallback',
'DATABASE_HOST' => 'localhost',
'REDIS_HOST' => 'localhost',
'LOG_LEVEL' => 'debug'
];
}
}
// 加载配置
$config = (new NacosConfigLoader())->load();
define('APP_NAME', $config['APP_NAME'] ?? 'Unknown');
define('APP_ENV', $config['APP_ENV'] ?? 'local');
define('DB_HOST', $config['DATABASE_HOST'] ?? '127.0.0.1');
define('REDIS_HOST', $config['REDIS_HOST'] ?? '127.0.0.1');
define('LOG_LEVEL', $config['LOG_LEVEL'] ?? 'debug');
🐳 四、Docker 镜像构建
1. docker/php-fpm.Dockerfile
# docker/php-fpm.Dockerfile
FROM php:8.1-fpm-alpine
# 安装依赖
RUN apk add --no-cache \
curl \
tzdata \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
# 安装 PHP 扩展
RUN docker-php-ext-install curl
# 创建 sock 目录
RUN mkdir -p /var/run/php && chown www-data:www-data /var/run/php
# 设置工作目录
WORKDIR /var/www/html
# 复制代码
COPY src /var/www/html
# 允许 www-data 写日志等
RUN chown -R www-data:www-data /var/www/html
# 暴露 sock 文件(通过 volume 共享)
EXPOSE 9000
CMD ["php-fpm"]
2. docker/nginx.Dockerfile
# docker/nginx.Dockerfile
FROM nginx:alpine
# 复制 Nginx 配置
COPY nginx/nginx.conf /etc/nginx/nginx.conf
# 复制站点代码(用于静态文件)
COPY src /var/www/html
# 创建 sock 目录挂载点
RUN mkdir -p /run/php
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
3. nginx/nginx.conf
# nginx/nginx.conf
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
root /var/www/html;
index index.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
fastcgi_pass unix:/run/php/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location /health {
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;
}
}
}
🛠 五、K8s 部署文件
1. k8s/nacos-deploy.yaml
# k8s/nacos-deploy.yaml
---
# 1. 命名空间
apiVersion: v1
kind: Namespace
meta
name: middleware
---
# 2. 数据库密码 Secret
apiVersion: v1
kind: Secret
meta
name: nacos-db-secret
namespace: middleware
type: Opaque
MYSQL_SERVICE_PASSWORD: bWFjb3MyMDI0 # echo -n "nacos2024" | base64
---
# 3. Nacos Deployment
apiVersion: apps/v1
kind: Deployment
meta
name: nacos
namespace: middleware
labels:
app: nacos
spec:
replicas: 1
selector:
matchLabels:
app: nacos
template:
meta
labels:
app: nacos
spec:
containers:
- name: nacos
image: nacos/nacos-server:v2.4.1
ports:
- containerPort: 8848
env:
- name: MODE
value: "standalone"
- name: PREFER_HOST_MODE
value: "hostname"
- name: SERVER_PORT
value: "8848"
- name: SPRING_DATASOURCE_PLATFORM
value: "mysql"
- name: MYSQL_SERVICE_HOST
value: "192.168.1.100" # 🔁 替换为你的 MySQL IP
- name: MYSQL_SERVICE_PORT
value: "3306"
- name: MYSQL_SERVICE_DB_NAME
value: "nacos"
- name: MYSQL_SERVICE_USER
value: "nacos"
- name: MYSQL_SERVICE_PASSWORD
valueFrom:
secretKeyRef:
name: nacos-db-secret
key: MYSQL_SERVICE_PASSWORD
- name: MYSQL_DATABASE_NUM
value: "1"
- name: NACOS_AUTH_ENABLE
value: "true"
- name: NACOS_AUTH_TOKEN
value: "SecretKey01234567890123456789012345678901"
resources:
requests:
memory: "1.5Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "1"
readinessProbe:
httpGet:
path: /nacos/actuator/health
port: 8848
initialDelaySeconds: 30
livenessProbe:
httpGet:
path: /nacos/actuator/health
port: 8848
initialDelaySeconds: 60
volumeMounts:
- name: timezone
mountPath: /etc/localtime
readOnly: true
volumes:
- name: timezone
hostPath:
path: /etc/localtime
---
# 4. NodePort Service
apiVersion: v1
kind: Service
meta
name: nacos
namespace: middleware
spec:
type: NodePort
ports:
- port: 8848
targetPort: 8848
nodePort: 30848
protocol: TCP
name: http
selector:
app: nacos
2. k8s/configmap-fallback.yaml
# k8s/configmap-fallback.yaml
apiVersion: v1
kind: ConfigMap
meta
name: php-app-fallback-config
namespace: default
fallback.php: |
<?php
return [
"APP_NAME" => "Fallback App",
"APP_ENV" => "fallback",
"DATABASE_HOST" => "db-fallback",
"REDIS_HOST" => "redis-fallback",
"LOG_LEVEL" => "warning"
];
3. k8s/php-deploy.yaml
# k8s/php-deploy.yaml
apiVersion: apps/v1
kind: Deployment
meta
name: php-app
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: php-app
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
minReadySeconds: 10
template:
meta
labels:
app: php-app
spec:
volumes:
- name: php-socket
emptyDir: {}
- name: fallback-config
configMap:
name: php-app-fallback-config
containers:
# PHP-FPM 容器
- name: php-fpm
image: your-registry/php-fpm:8.1 # 替换为你的镜像
volumeMounts:
- name: php-socket
mountPath: /run/php
env:
- name: NAOCUS_DATA_ID
value: "php-app-prod.yaml"
- name: NAOCUS_GROUP
value: "DEFAULT_GROUP"
resources:
limits:
memory: "512Mi"
cpu: "200m"
# Nginx 容器
- name: nginx
image: your-registry/nginx-php:alpine # 替换为你的镜像
ports:
- containerPort: 80
volumeMounts:
- name: php-socket
mountPath: /run/php
- name: fallback-config
mountPath: /var/www/html/config/fallback.php
subPath: fallback.php
readinessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 5
periodSeconds: 5
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
resources:
limits:
memory: "256Mi"
cpu: "100m"
# 平滑下线:先注销 Nacos,再停止
terminationGracePeriodSeconds: 30
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- >
# 等待 5 秒,让负载均衡器感知下线
sleep 5
---
# Service 暴露
apiVersion: v1
kind: Service
meta
name: php-app
namespace: default
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30080
protocol: TCP
name: http
selector:
app: php-app
🚀 六、部署流程
1. 构建并推送镜像
# 构建 PHP-FPM
docker build -f docker/php-fpm.Dockerfile -t your-registry/php-fpm:8.1 .
docker push your-registry/php-fpm:8.1
# 构建 Nginx
docker build -f docker/nginx.Dockerfile -t your-registry/nginx-php:alpine .
docker push your-registry/nginx-php:alpine
🔁 替换
your-registry为你的镜像仓库地址
2. 部署 Nacos
kubectl apply -f k8s/nacos-deploy.yaml
等待 Pod Running:
kubectl get pods -n middleware -l app=nacos
3. 部署 PHP 应用
kubectl apply -f k8s/configmap-fallback.yaml
kubectl apply -f k8s/php-deploy.yaml
4. 访问服务
浏览器访问:
http://<任意K8s节点IP>:30080
你应该看到 PHP 输出的配置信息,来源为 Nacos。
✅ 七、验证功能
| 功能 | 验证方式 |
|---|---|
| Nacos 配置 | 修改 Nacos 中 php-app-prod.yaml,刷新页面看是否生效 |
| 滚动更新 | kubectl set image deploy/php-app php-fpm=your-registry/php-fpm:8.2,观察是否不中断 |
| 平滑下线 | 删除 Pod,观察 preStop 是否执行,Nacos 是否不再注册 |
| 降级机制 | 停止 Nacos,重启 Pod,看是否使用 fallback 配置 |
🔐 八、安全建议
- Nacos 启用权限认证
- PHP 镜像使用非 root 用户
- K8s 配置 NetworkPolicy 限制访问
- 敏感配置加密(Nacos 支持 AES)
📎 附件:常用命令
# 查看日志
kubectl logs -l app=php-app -c nginx
kubectl logs -l app=php-app -c php-fpm
# 查看服务
kubectl get svc php-app
# 滚动重启
kubectl rollout restart deploy/php-app
# 进入容器
kubectl exec -it deploy/php-app -c nginx -- sh
✅ 现在你已经拥有了一个完整、可生产、可维护的 PHP + Nacos + K8s 部署方案!
如果你需要我提供:
- ✅ GitHub 仓库模板
- ✅ CI/CD 流水线(GitLab CI / GitHub Actions)
- ✅ Prometheus 监控指标
- ✅ 自动化脚本一键部署
欢迎继续提问!我可以为你定制企业级交付方案。
更多推荐



所有评论(0)