在Kubernetes中启用readOnlyRootFilesystem时如何豁免指定目录?
解决Kubernetes只读根文件系统下豁免目录的问题
这个场景我在GKE上处理过很多次,刚好能给你清晰的解决方案——核心思路是通过挂载可写卷来覆盖只读根文件系统上的特定目录,既保持根文件系统的只读安全性,又满足应用和探针的写入需求。
核心方案:用emptyDir挂载需要豁免的目录
当你启用readOnlyRootFilesystem: true后,根文件系统所有路径默认只读,但如果将一个可写卷(比如emptyDir)挂载到某个路径,这个路径就会变成可写状态,完美解决你的两个痛点:
- 给Flask提供可写的临时目录(比如
/tmp)和自定义存储路径 - 让存活探针能在可写目录里创建标记文件
下面是针对你的GKE环境(K8s 1.13.6-gke.13)的完整YAML配置示例:
apiVersion: v1 kind: Pod metadata: name: flask-app-pod spec: securityContext: runAsUser: 1000 runAsNonRoot: true readOnlyRootFilesystem: true containers: - name: flask-container image: your-flask-image:latest # 额外添加安全加固配置(可选但推荐) securityContext: allowPrivilegeEscalation: false capabilities: drop: ["ALL"] volumeMounts: # 豁免/tmp目录:覆盖原只读/tmp,变成可写临时存储 - name: tmp-volume mountPath: /tmp # 自定义可写目录:给Flask提供特定的写入路径(比如替代/opt/...) - name: app-data-volume mountPath: /opt/app/writable # 存活探针调整为写入/tmp(现在可写了) livenessProbe: exec: command: ["touch", "/tmp/liveness-check"] initialDelaySeconds: 5 periodSeconds: 10 volumes: - name: tmp-volume emptyDir: {} - name: app-data-volume emptyDir: {} # 如果需要持久化存储,替换成PVC(示例): # persistentVolumeClaim: # claimName: flask-app-pvc
关键细节说明
emptyDir的作用:这是Pod级别的临时存储,Pod启动时创建,删除时销毁,完全适配临时文件(比如Flask的缓存、探针标记)的需求,不需要额外权限,在GKE里直接可用。- 关于Flask的写入路径:你提到Flask尝试写入
/etc/...,强烈建议调整Flask的配置,让它只使用你挂载的可写目录(比如/tmp或/opt/app/writable),写入/etc属于不安全操作,不符合K8s安全最佳实践。如果实在无法修改应用,也可以用emptyDir挂载/etc的子目录,但不推荐这么做。 - 持久化需求:如果应用需要保存写入的文件(而非临时文件),把
emptyDir换成PersistentVolumeClaim即可,GKE会自动绑定对应的持久化存储。
验证方法
部署Pod后,你可以进入容器验证目录权限:
kubectl exec -it flask-app-pod -- bash # 检查/tmp是否可写 touch /tmp/test-file && echo "/tmp is writable" # 检查根目录其他路径是否只读(比如/etc) touch /etc/test-file # 应该报错"Read-only file system"
内容的提问来源于stack exchange,提问作者Leeran Setton
相关产品推荐
相关产品推荐

