📝 本文首发于 栏轩·阁
欢迎访问阅读原文,获取更好的阅读体验。
一、前言
本文在已有 KubeSphere 环境和 K8s 集群的基础上,记录如何通过 KubeSphere 部署一个完整的 Nginx 网站。
适用场景
- 已在本地通过 Docker Desktop 启用 K8s 集群
- 已安装 KubeSphere(ks-core)
- 希望通过可视化界面 + 命令行结合的方式管理网站部署
本文重点
- 创建配置字典(ConfigMap)管理 Nginx 配置文件
- 创建持久卷(PVC)挂载网站静态文件
- 创建工作负载(Deployment)并配置挂载
- 创建 LoadBalancer 服务暴露到宿主机
- 通过
kubectl cp上传 HTML 文件
二、整体架构
用户访问 → localhost:8888 → envoy 代理容器(LoadBalancer)
→ K8s NodePort → Pod:80(Nginx)
├── /usr/share/nginx/html (PVC 持久卷)
└── /etc/nginx/conf.d/ (ConfigMap 配置)
三、创建配置字典(ConfigMap)
3.1 什么是配置字典
配置字典(ConfigMap)是 K8s 中用来存储配置文件的资源对象。这里用来存储 Nginx 的配置文件,挂载到 Pod 中后 Nginx 可以直接读取。
3.2 创建步骤
在 KubeSphere 项目中进入 配置 → 配置字典,点击创建。

3.3 nginx.conf(主配置)
用来控制 Nginx 的全局行为,包括工作进程数、日志格式、事件模型等:
nginx
user nginx;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
3.4 default.conf(站点配置)
用来配置具体的虚拟主机,定义监听端口、站点根目录等:
nginx
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
注意:站点根目录
root指向/usr/share/nginx/html,这就是后面要挂载持久卷的位置。
四、创建持久卷(PVC)
持久卷(PersistentVolumeClaim,PVC)用于持久化存储网站静态文件。这样即使 Pod 重启,上传的 HTML 文件也不会丢失。
在 KubeSphere 中创建: 进入 存储 → 持久卷声明,点击创建。
容量按需设置(本例设为 10Gi),访问模式选择 单节点读写(RWO)。存储卷创建后会自动绑定到后端的存储类(StorageClass)。
五、创建应用(工作负载)
5.1 镜像地址
docker.1ms.run/library/nginx:latest
使用国内镜像源加速拉取。如果使用 Docker Hub 官方镜像,地址为
nginx:latest。
5.2 挂载持久卷
将上一步创建的 PVC 挂载到容器内 Nginx 的网页根目录,用于存放 HTML 静态文件。
| 字段 | 值 |
|---|---|
| 挂载路径 | /usr/share/nginx/html |
| 存储卷 | 选择已创建的 PVC |
| 读写权限 | 读写 |
5.3 挂载配置字典
Nginx 有两个关键配置文件需要挂载,涉及多个路径,需分别配置:
| 存储卷 | 容器内挂载路径 | 子路径(Key 名称) |
|---|---|---|
| nginx 配置字典 | /etc/nginx/nginx.conf |
nginx.conf |
| nginx 配置字典 | /etc/nginx/conf.d/default.conf |
default.conf |


六、两种挂载方式的区别
在配置字典挂载时,KubeSphere 提供了两种挂载方式,理解其区别非常重要:
6.1 指定子路径(subPath)
适用于精准挂载单个文件 。当配置字典包含多个 Key 时,直接填写目标 Key 名称 (如 nginx.conf),挂载路径填写容器内完整文件路径(如 /etc/nginx/nginx.conf)。该方式仅替换指定文件,不会清空目标目录原有内容。
使用场景: 只想替换某个配置文件,保留 Nginx 镜像自带的其余默认配置。
6.2 选择指定键(items 模式)
需先指定挂载路径为容器内的父目录 ,再逐一为配置字典里的每个 Key 单独分配容器内子路径名。该模式会先清空目标父目录,再放入指定文件。
使用场景: 需要批量挂载多个配置文件,且不关心容器原有默认配置。
6.3 使用建议
- 想要保留容器原有文件(如 Nginx 原生配置)、仅替换个别配置文件,优先使用指定子路径。
- 需要批量挂载多个文件、且允许清空目标目录时,再使用选择指定键。
- 二者不要同时勾选,避免挂载异常。
七、创建服务暴露到宿主机
7.1 创建 Service
工作负载部署完成后,需要创建 Service 才能外部访问。在 KubeSphere 中进入 服务 → 服务,点击创建:
- 服务类型: LoadBalancer
- 端口映射: Pod 端口
80→ Service 端口8888(或其他你想要的端口) - 注意不需要配置键值对标签,Docker Desktop 会自动创建 envoy 代理容器供外部访问。
7.2 LoadBalancer 原理说明
在 Docker Desktop 的 K8s 环境中,Service 改为 LoadBalancer 类型后,kind-cloud-provider 组件会自动创建一个 envoy 代理容器,将宿主机端口映射到集群内部:
localhost:8888 → envoy 容器:8888 → NodePort → Pod:80
⚠️ 注意: 如果 Host 端口和已有的 Docker 容器端口冲突(如本地已有 Nginx 占用了 80 端口),LoadBalancer 会卡在
<pending>状态,需要手动指定一个空闲端口。
7.3 查看 Service 状态
bash
kubectl get svc -n <项目名称>
Expected output:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx LoadBalancer 10.96.135.68 172.18.0.6 8888:31056/TCP 2h
EXTERNAL-IP 出现 IP 地址(而非 <pending>)代表 LoadBalancer 创建成功。
八、上传 HTML 文件
8.1 403 问题
Service 创建成功后访问 http://localhost:8888 会出现 403 Forbidden ,原因很简单------页面根目录 /usr/share/nginx/html 是空的,Nginx 找不到默认页面。
8.2 使用 kubectl cp 上传文件
首先查看 Pod 名称:
bash
kubectl get pods -n <项目名称>
上传本地 dist/ 目录下的文件到 Pod:
bash
kubectl cp ./dist/. <Pod名称>:/usr/share/nginx/html/ -n <项目名称>
⚠️ 路径注意:
./dist/.------ 把dist目录里面的内容上传到目标路径(正确)./dist/------ 把dist目录本身 上传到目标路径,会变成html/dist/(错误)

8.3 删除或重新上传
如果传错目录结构,需要先清理再重新上传:
bash
kubectl exec -n <项目名称> <Pod名称> -- rm -rf /usr/share/nginx/html/*
⚠️ 注意:
rm -rf *通配符在部分 shell 环境中可能不生效,改用精确路径更可靠:
bashkubectl exec -n <项目名称> <Pod名称> -- rm -rf /usr/share/nginx/html/dist
命令说明:kubectl exec 可以进入容器内部执行 Linux 命令,-- 后面跟的就是要在容器内执行的命令。
8.4 访问验证
文件上传后再次访问 http://localhost:8888,可以看到页面正常显示。

九、常用运维命令
9.1 查看 Pod 状态和详情
bash
# 查看项目下所有 Pod
kubectl get pods -n <项目名称>
# 查看 Pod 详细信息(包括挂载、事件等)
kubectl describe pod -n <项目名称> <Pod名称>
9.2 查看配置字典内容
bash
kubectl get configmap -n <项目名称> <配置名称> -o yaml
9.3 查看持久卷(PVC)
bash
kubectl get pvc -n <项目名称>
9.4 查看 Service 和 External-IP
bash
kubectl get svc -n <项目名称>
9.5 查看 Pod 内部文件结构
bash
kubectl exec -n <项目名称> <Pod名称> -- ls -la /usr/share/nginx/html/
十、总结
| 阶段 | 操作 | 要点 |
|---|---|---|
| 配置 | 创建 ConfigMap | 挂载时注意区分 subPath 和 items 模式 |
| 存储 | 创建 PVC | 挂载到 /usr/share/nginx/html |
| 部署 | 创建 Deployment | 配置镜像和挂载路径 |
| 暴露 | 创建 LoadBalancer Service | 注意端口冲突,Docker Desktop 自动创建 envoy 代理 |
| 上传 | kubectl cp |
路径用 ./dist/. 不是 ./dist/ |
| 运维 | kubectl exec |
进入容器执行命令,方便调试和管理 |
通过 KubeSphere 可视化界面结合 kubectl 命令行,可以很方便地在本地 K8s 环境中完成 Nginx 网站部署。理解 ConfigMap 挂载机制和 LoadBalancer 在 Docker Desktop 下的工作原理,能帮助我们更快排查问题。