Istio 软多租户支持
使用 Kubernetes 命名空间和 RBAC 创建 Istio 软多租户环境。
多租户在许多环境中广泛应用于多种不同的应用程序,但每个租户提供的实现细节和功能并非在所有环境中都遵循一种模式。 Kubernetes 多租户工作组 正在努力定义 Kubernetes 中应提供的多租户用例和功能。但是,从他们的工作中可以清楚地看到,由于无法完全防止恶意容器或工作负载访问其他租户的 Pod 或内核资源,因此只能实现“软多租户”。
软多租户
对于这篇博文,“软多租户”被定义为拥有一个 Kubernetes 控制平面,包含多个 Istio 控制平面和多个网格,每个租户一个控制平面和一个网格。集群管理员可以控制并查看所有 Istio 控制平面,而租户管理员只能控制特定的 Istio 实例。租户之间的分离通过 Kubernetes 命名空间和 RBAC 提供。
这种部署模型的一个用例是共享的企业基础设施,在这种基础设施中,预计不会发生恶意行为,但仍然需要租户之间干净分离。
这篇博文的底部描述了未来潜在的 Istio 多租户部署模型。
部署
多个 Istio 控制平面
部署多个 Istio 控制平面首先要将清单文件中的所有 namespace
引用替换为所需的命名空间。以 istio.yaml
为例,如果需要两个租户级 Istio 控制平面;第一个可以使用 istio.yaml
默认名称 istio-system
,第二个控制平面可以通过生成一个带有不同命名空间的新 YAML 文件来创建。例如,以下命令创建一个带有 istio-system1
Istio 命名空间的 YAML 文件。
$ cat istio.yaml | sed s/istio-system/istio-system1/g > istio-system1.yaml
istio.yaml
文件包含 Istio 控制平面部署的详细信息,包括构成控制平面的 Pod(Mixer、Pilot、Ingress、Galley、CA)。部署两个 Istio 控制平面 YAML 文件
$ kubectl apply -f install/kubernetes/istio.yaml
$ kubectl apply -f install/kubernetes/istio-system1.yaml
将在两个命名空间中运行两个 Istio 控制平面。
$ kubectl get pods --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
istio-system istio-ca-ffbb75c6f-98w6x 1/1 Running 0 15d
istio-system istio-ingress-68d65fc5c6-dnvfl 1/1 Running 0 15d
istio-system istio-mixer-5b9f8dffb5-8875r 3/3 Running 0 15d
istio-system istio-pilot-678fc976c8-b8tv6 2/2 Running 0 15d
istio-system1 istio-ca-5f496fdbcd-lqhlk 1/1 Running 0 15d
istio-system1 istio-ingress-68d65fc5c6-2vldg 1/1 Running 0 15d
istio-system1 istio-mixer-7d4f7b9968-66z44 3/3 Running 0 15d
istio-system1 istio-pilot-5bb6b7669c-779vb 2/2 Running 0 15d
如果需要,Istio 边车 和 附加组件 清单也必须部署以匹配租户 Istio 控制平面使用的配置的 namespace
。
这两个 YAML 文件的执行由集群管理员负责,而不是租户级管理员。集群管理员还需要配置和应用额外的 RBAC 限制,将租户管理员限制在分配的命名空间内。
分离公共资源和命名空间特定资源
Istio 存储库中的清单文件创建了所有 Istio 控制平面都将使用的公共资源以及每个控制平面复制的资源。虽然如上所述,通过替换 istio-system
命名空间引用来部署多个控制平面非常简单,但更好的方法是将清单文件拆分为一个针对所有租户部署一次的公共部分和一个租户特定部分。对于 自定义资源定义,角色和角色绑定应该从提供的 Istio 清单中分离出来。此外,提供的 Istio 清单中的角色和角色绑定可能不适合多租户环境,应该根据下一节的描述进行修改或增强。
Kubernetes RBAC 用于 Istio 控制平面资源
要将租户管理员限制在一个 Istio 命名空间内,集群管理员将创建一个包含以下内容的清单文件,至少包含一个 Role
和 RoleBinding
,类似于下面所示。在这个例子中,名为 sales-admin 的租户管理员被限制在 istio-system1
命名空间。完整的清单文件将包含更多 apiGroups
,这些 apiGroups
在 Role
下提供对租户管理员的资源访问权限。
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: istio-system1
name: ns-access-for-sales-admin-istio-system1
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["*"]
verbs: ["*"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: access-all-istio-system1
namespace: istio-system1
subjects:
- kind: User
name: sales-admin
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: ns-access-for-sales-admin-istio-system1
apiGroup: rbac.authorization.k8s.io
监视特定命名空间以进行服务发现
除了创建 RBAC 规则限制租户管理员对特定 Istio 控制平面的访问之外,还必须更新 Istio 清单以指定 Pilot 应监视以创建其 xDS 缓存的应用程序命名空间。这可以通过使用附加命令行参数 --appNamespace, ns-1
启动 Pilot 组件来完成。其中 ns-1 是租户应用程序将要部署的命名空间。下面显示了 istio-system1.yaml
文件中的一个示例片段。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: istio-pilot
namespace: istio-system1
annotations:
sidecar.istio.io/inject: "false"
spec:
replicas: 1
template:
metadata:
labels:
istio: pilot
spec:
serviceAccountName: istio-pilot-service-account
containers:
- name: discovery
image: docker.io/<user ID>/pilot:<tag>
imagePullPolicy: IfNotPresent
args: ["discovery", "-v", "2", "--admission-service", "istio-pilot", "--appNamespace", "ns-1"]
ports:
- containerPort: 8080
- containerPort: 443
在命名空间中部署租户应用程序
现在,集群管理员已经创建了租户的命名空间(例如 istio-system1
),并且 Pilot 的服务发现已配置为监视特定应用程序命名空间(例如 ns-1),请创建应用程序清单文件以部署到该租户的特定命名空间。例如
apiVersion: v1
kind: Namespace
metadata:
name: ns-1
并将命名空间引用添加到应用程序清单文件包含的每种资源类型中。例如
apiVersion: v1
kind: Service
metadata:
name: details
labels:
app: details
namespace: ns-1
虽然没有显示,但应用程序命名空间也将具有 RBAC 设置,限制对某些资源的访问。这些 RBAC 设置可以由集群管理员或租户管理员设置。
在多租户环境中使用 kubectl
当定义 路由规则 或 目标策略 时,必须确保 kubectl
命令的范围是 Istio 控制平面所在的命名空间,以确保资源在正确的命名空间中创建。此外,规则本身也必须限定在租户的命名空间内,以便它能够正确应用于该租户的网格。-i 选项用于在 Istio 控制平面部署所在的命名空间中创建(或获取或描述)规则。-n 选项将规则的范围限定在租户的网格,并且应设置为租户应用程序部署所在的命名空间。请注意,如果资源的 .yaml 文件正确地限定了范围,则可以在命令行中省略 -n 选项。
例如,以下命令需要添加到 istio-system1
命名空间中添加路由规则
$ kubectl –i istio-system1 apply -n ns-1 -f route_rule_v2.yaml
可以使用以下命令显示该规则
$ kubectl -i istio-system1 -n ns-1 get routerule
NAME KIND NAMESPACE
details-Default RouteRule.v1alpha2.config.istio.io ns-1
productpage-default RouteRule.v1alpha2.config.istio.io ns-1
ratings-default RouteRule.v1alpha2.config.istio.io ns-1
reviews-default RouteRule.v1alpha2.config.istio.io ns-1
有关多租户环境中 namespace
要求的更多详细信息,请参阅本文档的 多个 Istio 控制平面 部分。
测试结果
按照上述说明,集群管理员可以创建一个环境,通过 RBAC 和命名空间限制租户管理员可以部署的内容。
部署后,可以访问分配给特定租户管理员的 Istio 控制平面 Pod
$ kubectl get pods -n istio-system
NAME READY STATUS RESTARTS AGE
grafana-78d649479f-8pqk9 1/1 Running 0 1d
istio-ca-ffbb75c6f-98w6x 1/1 Running 0 1d
istio-ingress-68d65fc5c6-dnvfl 1/1 Running 0 1d
istio-mixer-5b9f8dffb5-8875r 3/3 Running 0 1d
istio-pilot-678fc976c8-b8tv6 2/2 Running 0 1d
istio-sidecar-injector-7587bd559d-5tgk6 1/1 Running 0 1d
prometheus-cf8456855-hdcq7 1/1 Running 0 1d
但是,不允许访问集群的所有 Pod
$ kubectl get pods --all-namespaces
Error from server (Forbidden): pods is forbidden: User "dev-admin" cannot list pods at the cluster scope
也不允许访问其他租户的命名空间
$ kubectl get pods -n istio-system1
Error from server (Forbidden): pods is forbidden: User "dev-admin" cannot list pods in the namespace "istio-system1"
租户管理员可以在为该租户配置的应用程序命名空间中部署应用程序。例如,更新 Bookinfo 清单文件,然后部署到租户的应用程序命名空间 ns-0,允许列出该租户命名空间使用的 Pod
$ kubectl get pods -n ns-0
NAME READY STATUS RESTARTS AGE
details-v1-64b86cd49-b7rkr 2/2 Running 0 1d
productpage-v1-84f77f8747-rf2mt 2/2 Running 0 1d
ratings-v1-5f46655b57-5b4c5 2/2 Running 0 1d
reviews-v1-ff6bdb95b-pm5lb 2/2 Running 0 1d
reviews-v2-5799558d68-b989t 2/2 Running 0 1d
reviews-v3-58ff7d665b-lw5j9 2/2 Running 0 1d
但不能访问其他租户的应用程序命名空间
$ kubectl get pods -n ns-1
Error from server (Forbidden): pods is forbidden: User "dev-admin" cannot list pods in the namespace "ns-1"
如果 附加工具(例如 Prometheus)已部署(也由 Istio namespace
限制),则返回的统计结果将仅代表从该租户的应用程序命名空间看到的流量。
结论
执行的评估表明 Istio 具有满足少量多租户用例的足够功能和安全性。它还表明 Istio 和 Kubernetes 无法为其他用例提供足够的性能和安全性,尤其是那些需要在不受信任的租户之间完全安全和隔离的用例。要实现更安全的安全和隔离模型所需的改进需要在容器技术(例如 Kubernetes)方面进行,而不是在 Istio 功能方面进行改进。
问题
- 来自一个租户的 Istio 控制平面的 CA(证书颁发机构)和 Mixer Pod 日志(例如
istio-system
命名空间)包含来自第二个租户的 Istio 控制平面的“信息”消息(例如istio-system1
命名空间)。
其他多租户模型的挑战
考虑了其他多租户部署模型
一个网格包含多个应用程序,每个租户在网格上都有一个应用程序。集群管理员可以控制并查看整个网格和所有应用程序,而租户管理员只能控制特定的应用程序。
一个 Istio 控制平面包含多个网格,每个租户一个网格。集群管理员可以控制并查看整个 Istio 控制平面和所有网格,而租户管理员只能控制特定的网格。
一个云环境(集群控制),但包含多个 Kubernetes 控制平面(租户控制)。
这些选项要么没有提供代码更改来进行正确支持,要么不能完全解决用例。
当前的 Istio 功能不适合支持第一个模型,因为它缺乏足够的 RBAC 功能来支持集群与租户操作。此外,在一个网格下拥有多个租户对于当前的网格模型以及 Istio 将配置传递到 Envoy 代理的方式来说太不安全了。
关于第二个选项,当前的 Istio 范式假设每个 Istio 控制平面只有一个网格。支持该模型所需的更改非常大。它们将需要基于命名空间对资源和安全域进行更细粒度的范围限定,以及额外的 Istio RBAC 更改。该模型可能会在未来的工作中得到解决,但目前还不可行。
第三种模型不能满足大多数用例,因为大多数集群管理员更喜欢一个通用的 Kubernetes 控制平面,他们将其作为 PaaS 提供给他们的租户。
未来工作
允许单个 Istio 控制平面控制多个网格将是一个明显的下一步功能。另一个改进是提供一个可以托管不同租户的单个网格,在租户之间提供一定程度的隔离和安全性。这可以通过使用与 Kubernetes 相同的逻辑命名空间概念,在一个控制平面内进行分区来实现。Istio 社区已经开始了一个 文档,用于定义额外的用例以及支持这些用例所需的 Istio 功能。
参考资料
- 关于 Kubernetes 多租户支持的视频,使用 RBAC 和命名空间进行多租户支持和安全建模,以及 支持的幻灯片。
- KubeCon 上讨论安全性的演讲,讨论了 Kubernetes 对“协作式软多租户”的支持,构建信任:如何保护您的 Kubernetes。
- Kubernetes 文档,介绍了 RBAC 和 命名空间。
- KubeCon 上关于 深入探讨多租户 的幻灯片。
- 关于 Kubernetes 的多租户模型 的 Google 文档。(需要权限)
- Cloud Foundry WIP 文档,多云和多租户
- Istio 自动多租户 101