本文发布已超过一年。较旧的文章可能包含过时内容。请检查页面中的信息自发布以来是否已失效。

Kubernetes 1.30:只读卷挂载最终可以真正只读了

自 Kubernetes 诞生以来,只读卷挂载(read-only volume mounts)一直是一个特性。令人惊讶的是,在 Linux 上的某些条件下,只读挂载并非完全只读。从 v1.30 版本开始,通过对递归只读挂载(recursive read-only mounts)的 Alpha 支持,可以使其完全只读。

只读卷挂载默认并非完全只读

卷挂载可能比看起来更复杂。

你可能期望以下清单会使容器中 /mnt 下的所有内容都是只读的

---
apiVersion: v1
kind: Pod
spec:
  volumes:
    - name: mnt
      hostPath:
        path: /mnt
  containers:
    - volumeMounts:
        - name: mnt
          mountPath: /mnt
          readOnly: true

然而,/mnt 下的任何子挂载可能仍然是可写的!例如,假设主机上的 /mnt/my-nfs-server 是可写的。在容器内部,对 /mnt/* 的写入将被拒绝,但对 /mnt/my-nfs-server/* 的写入仍然是可写的。

新的挂载选项:recursiveReadOnly

Kubernetes 1.30 添加了一个新的挂载选项 recursiveReadOnly,以使子挂载递归地只读。

该选项可以按如下方式启用

---
apiVersion: v1
kind: Pod
spec:
  volumes:
    - name: mnt
      hostPath:
        path: /mnt
  containers:
    - volumeMounts:
        - name: mnt
          mountPath: /mnt
          readOnly: true
          # NEW
          # Possible values are `Enabled`, `IfPossible`, and `Disabled`.
          # Needs to be specified in conjunction with `readOnly: true`.
          recursiveReadOnly: Enabled

这是通过使用 Linux 内核 v5.12 中添加的 mount_setattr(2) 并应用带有 AT_RECURSIVE 标志的 MOUNT_ATTR_RDONLY 属性来实现的。

为了向后兼容,recursiveReadOnly 字段不是 readOnly 的替代品,而是与其结合使用的。要获得正确的递归只读挂载,必须同时设置这两个字段。

特性可用性

要启用 recursiveReadOnly 挂载,需要使用以下组件

  • Kubernetes:v1.30 或更高版本,并且启用了 RecursiveReadOnlyMounts feature gate。从 v1.30 开始,该特性门被标记为 Alpha。

  • CRI 运行时

    • containerd:v2.0 或更高版本
  • OCI 运行时

    • runc:v1.1 或更高版本
    • crun:v1.8.6 或更高版本
  • Linux 内核:v5.12 或更高版本

后续计划?

Kubernetes SIG Node 希望并预计该特性在未来的 Kubernetes 版本中能升级到 Beta,最终达到通用可用性(GA),这样用户就不再需要手动启用该特性门了。

为了向后兼容,recursiveReadOnly 的默认值仍将是 Disabled

如何了解更多?

请查看文档,了解 recursiveReadOnly 挂载的更多详细信息。

如何参与贡献?

此特性由 SIG Node 社区推动。请加入我们,与社区联系,分享您关于上述特性及其他方面的想法和反馈。我们期待您的来信!