这个现象很多Kubernetes初学者都会遇到。比如修改了 Pod 里 Nginx 的默认页面(比如 /usr/share/nginx/html/index.html),重启服务器或 Pod 后又变回原来的默认页面 —— 其实这完全是 Kubernetes 的设计机制 导致的,不是你操作错了。下面详细解释。


一、为什么修改会“恢复原状”

你遇到的这个情况本质上是:

Pod 是临时的(Ephemeral),Pod 中的容器文件系统不是持久的。

1. Pod 的文件系统是临时层

当你启动一个 Pod 时,K8s 会从镜像(比如 nginx:latest)创建容器。
容器的文件系统由几层组成:

镜像层(只读) + 可写层(运行时临时层)

举个例子:

nginx:latest
  ├─ /usr/share/nginx/html/index.html   # 镜像自带的文件(只读)
  ├─ ...
  └─ 你运行时修改的文件 → 写在“可写层”

这个可写层只在容器运行时存在,一旦:

  • Pod 被删除重建,或者
  • 节点(服务器)重启,Pod 被调度到别的节点上
    ➡️ 这个临时层就会消失,文件全部回到镜像的原始状态

二、为什么K8s会这样设计

Kubernetes 的核心理念是:

Pod 不可变(Immutable),销毁与重建是常态。

K8s 不会像传统服务器那样“保留修改状态”,而是认为:

  • 你定义的 YAML 文件才是唯一真相(desired state);
  • 实际运行的 Pod 只是根据 YAML 临时生成的副本;
  • 修改 Pod 内容相当于临时改运行时文件,不属于声明式配置的一部分

三、正确的修改方式(3种解决方案)

方法1:重新制作镜像(推荐)

如果你想要 永久修改 Nginx 首页,正确做法是:

  1. 把自定义的 index.html 放入你的工作目录;
  2. 写一个 Dockerfile 基于 nginx 修改:
FROM nginx:latest
COPY index.html /usr/share/nginx/html/index.html
  1. 构建并推送:
docker build -t my-nginx:1.0 .
docker push my-nginx:1.0
  1. 在 Pod 或 Deployment YAML 里引用:
containers:
  - name: web
    image: my-nginx:1.0

这样重启服务器也不会恢复原样,因为镜像本身包含了你的新页面。


方法2:挂载 ConfigMap(常见于生产)

如果你不想重新打包镜像,也可以用 ConfigMap 挂载文件内容

kubectl create configmap nginx-index --from-file=index.html

然后在 Pod 中这样写:

volumes:
- name: html
  configMap:
    name: nginx-index
containers:
- name: nginx
  image: nginx:latest
  volumeMounts:
  - name: html
    mountPath: /usr/share/nginx/html

这样,Nginx 的首页来自 ConfigMap,修改 ConfigMap 就能更新页面。


方法3:挂载持久卷(PersistentVolume)

如果你希望文件在节点重启后依旧存在(例如运行在本地测试环境),可以使用 PersistentVolume (PV) + PersistentVolumeClaim (PVC)

简化示例:

volumes:
- name: html
  persistentVolumeClaim:
    claimName: nginx-pvc
containers:
- name: nginx
  image: nginx:latest
  volumeMounts:
  - name: html
    mountPath: /usr/share/nginx/html

这样内容会保存在持久存储上(本地磁盘或网络存储),不会因为 Pod 重建而丢失。


四、总结对比

方式

优点

缺点

适用场景

直接修改 Pod 内文件

快速临时改

重启后丢失

临时测试

自定义镜像

永久保存更改

要重打包镜像

部署正式版本

ConfigMap

修改方便、可热更新

仅适合小文件

配置类文件

持久卷 (PV/PVC)

文件长期保存

要配置存储

数据类文件或本地测试


总结

如果是在学习或测试环境:

  • 临时看效果:直接 kubectl exec 进去改;
  • 想保存修改:用 ConfigMap 或 Dockerfile
  • 服务器重启后依旧想保留:挂载持久卷

更多推荐