Kubernetes 里对一些资源的引用限制是比较弱的,比如 Pod 里可以使用 Secret 与 ConfigMap、PVC 里可以使用 StorageClass。想对这种情况进行限制,必须通过额外的手段来做。
在 Kubernetes 中,CSI 存储的端到端多租户如下所示,除了存储侧多租户之外,Kubernetes 侧也需要多租户来对应着存储侧的多租户,这样才能保证端到端的多租户功能。
理想状态下,存储侧的租户 S1/S2 分别与 Kubernetes 侧的 K1/K2 租户对应,K1 租户不能使用 S2 中的存储资源,但是 Kubernetes Dynamic PV Provisioning 中所使用的 StorageClass 却可以被任意 Namespace 里的资源使用,这个就导致了整个端到端多租户并不完整。
要解决 Kubernetes 侧租户之间的隔离问题,可以使用 Kubernetes 的 RBAC 权限控制与 Validating Webhook。
首先创建一个 ClusterRole 来定义 Verb 为 use
,Object 为 StorageClass 名字:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: use-storageclass-sc1
rules:
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
resourceNames: ["sc1"]
verbs: ["use"]
其次在租户 Namespace 里创建 RoleBinding,来定义允许该 Namespace 使用这个 StorageClass:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: use-storageclass-sc1
namespace: ns1
subjects:
- kind: Group
name: system:serviceaccounts:ns1
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: use-storageclass-sc1
apiGroup: rbac.authorization.k8s.io
最后 PVC Validating Webhook 根据 PVC 信息构造 SAR 并向 Kubernetes 查询权限并返回结果:
apiVersion: authorization.k8s.io/v1
kind: SubjectAccessReview
spec:
groups:
- system:serviceaccounts:ns1
resourceAttributes:
group: storage.k8s.io
resource: storageclasses
name: sc1
namespace: ns1
verb: use
具体代码实现可参考:https://github.com/chenzhiwei/k8s-storage-webhook
使用Kubernetes原生RBAC这种方式反而是比较麻烦的,其实也可以自己定义一个规则,将规则放进ConfigMap里挂载到Webhook Pod中,Webhook直接读取并做相应判断更简单一些。比如:
apiVersion: v1
kind: ConfigMap
metadata:
name: storageclass-rules
data:
rules.json: |
{
"sc1": ["ns1", "ns2", "ns3"],
"sc2": ["ns4", "ns5"]
}
更新:Kubernetes v1.26 版本中添加了 Validating Admission Policy 功能,可以实现该功能,相对简单一些。