MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Kubernetes 多租户管理:Namespace 的使用与权限控制

2023-01-077.0k 阅读

Kubernetes 多租户管理基础认知

在现代云原生应用开发与部署中,Kubernetes(简称 K8s)已然成为容器编排的事实标准。随着企业内不同团队和项目对容器化资源的使用需求日益增长,实现多租户管理变得至关重要。多租户管理旨在让多个用户或团队(租户)能够在同一 Kubernetes 集群中安全、高效地共享资源,同时相互隔离,避免干扰。

Namespace(命名空间)是 Kubernetes 实现多租户管理的重要概念之一。它为集群资源提供了一种虚拟的隔离机制。可以将 Kubernetes 集群想象成一个公寓,Namespace 就如同公寓中的不同楼层,每个楼层(Namespace)可以住不同的租户(团队或项目),他们拥有自己独立的空间,互不干扰。

从技术层面来看,Namespace 是一种作用域,在 Kubernetes 集群内,通过 Namespace 可以对资源进行分组和隔离。不同 Namespace 中的资源名称可以相同,因为它们处于不同的“命名空间”之下。例如,在一个名为 development 的 Namespace 中有一个名为 my - app - deployment 的 Deployment,在另一个名为 production 的 Namespace 中同样可以存在一个 my - app - deployment 的 Deployment,二者相互独立。

Namespace 的创建与管理

  1. 通过命令行创建 Namespace 在 Kubernetes 集群环境下,可以使用 kubectl 命令行工具轻松创建 Namespace。以下是创建一个名为 example - namespace 的 Namespace 的示例命令:
kubectl create namespace example - namespace

上述命令执行后,Kubernetes 集群就会创建一个新的 example - namespace 命名空间。如果想要查看当前集群中有哪些 Namespace,可以使用以下命令:

kubectl get namespaces

该命令会列出所有 Namespace 及其状态,类似如下输出:

NAME              STATUS   AGE
default           Active   1d
example - namespace   Active   10s
kube - public       Active   1d
kube - system       Active   1d
  1. 通过配置文件创建 Namespace 除了命令行方式,还可以通过 YAML 或 JSON 配置文件来创建 Namespace,这种方式在自动化部署和版本控制方面更为方便。以下是一个创建 example - namespace 的 YAML 配置文件示例:
apiVersion: v1
kind: Namespace
metadata:
  name: example - namespace

将上述内容保存为 namespace - example.yaml 文件,然后使用以下命令创建 Namespace:

kubectl apply - f namespace - example.yaml

kubectl apply 命令会根据配置文件的内容创建或更新相应的资源。在这个例子中,会创建一个名为 example - namespace 的 Namespace。

如果需要删除一个 Namespace,可以使用 kubectl delete 命令。例如,删除 example - namespace

kubectl delete namespace example - namespace

当删除一个 Namespace 时,该 Namespace 内的所有资源(如 Pods、Deployments、Services 等)都会被一并删除。所以在执行删除操作前,务必确认该 Namespace 内的资源是否不再需要。

Namespace 中的资源隔离

  1. 资源名称隔离 如前文所述,Namespace 为资源提供了名称隔离。这意味着不同 Namespace 中的资源可以使用相同的名称。例如,在 dev Namespace 中可以有一个名为 web - service 的 Service,在 prod Namespace 中同样可以创建一个名为 web - service 的 Service。这种隔离机制避免了不同团队或项目在命名资源时的冲突,提高了资源命名的灵活性。
  2. 资源访问隔离 默认情况下,不同 Namespace 中的资源是相互隔离的,一个 Namespace 内的 Pod 无法直接访问另一个 Namespace 中的 Pod 或 Service,除非通过特定的网络策略或跨 Namespace 服务发现机制。例如,假设在 team - a Namespace 中有一个应用服务,在 team - b Namespace 中的应用无法直接通过内部集群网络访问 team - a 中的服务,这样就保证了不同租户之间资源的安全性和独立性。

Kubernetes 权限控制概述

在 Kubernetes 多租户管理中,权限控制是保障系统安全和资源合理使用的关键环节。Kubernetes 提供了一套基于角色的访问控制(RBAC)机制,通过定义角色(Role)和角色绑定(RoleBinding)来控制用户对集群资源的访问权限。

  1. 角色(Role) Role 是一组权限规则的集合,它定义了对特定资源的操作权限。例如,一个 Role 可以定义对某个 Namespace 中的 Pods 具有创建、读取、更新和删除的权限。以下是一个简单的 Role 定义示例,用于允许对 example - namespace 中的 Pods 进行操作:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: example - namespace
  name: pod - admin - role
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

在上述示例中,apiGroups 字段指定了资源所属的 API 组,"" 表示核心 API 组。resources 字段指定了权限作用的资源类型为 podsverbs 字段定义了允许的操作,包括获取、列表、监控、创建、更新、补丁和删除。

  1. 集群角色(ClusterRole) 与 Role 不同,ClusterRole 是集群级别的角色定义,它可以对整个集群的资源或跨 Namespace 的资源进行权限设置。例如,一个 ClusterRole 可以定义对所有 Namespace 中的 Secrets 具有读取权限。以下是一个 ClusterRole 示例:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: secret - reader - cluster - role
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "list", "watch"]

这个 ClusterRole 允许对所有 Namespace 中的 Secrets 进行读取操作。

  1. 角色绑定(RoleBinding)和集群角色绑定(ClusterRoleBinding) RoleBinding 将 Role 与用户或用户组关联起来,从而赋予用户相应的权限。同样,ClusterRoleBinding 将 ClusterRole 与用户或用户组关联起来。以下是一个 RoleBinding 示例,将 pod - admin - role 角色绑定给名为 user - 1 的用户:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: example - namespace
  name: pod - admin - binding
subjects:
- kind: User
  name: user - 1
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod - admin - role
  apiGroup: rbac.authorization.k8s.io

在上述示例中,subjects 字段指定了被绑定的用户 user - 1roleRef 字段指定了要绑定的 Role pod - admin - role

对于 ClusterRoleBinding,其原理类似,但作用于集群级别。例如,将 secret - reader - cluster - role 集群角色绑定给名为 admin - group 的用户组:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: secret - reader - binding
subjects:
- kind: Group
  name: admin - group
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret - reader - cluster - role
  apiGroup: rbac.authorization.k8s.io

通过 Role、ClusterRole、RoleBinding 和 ClusterRoleBinding 的组合使用,可以精细地控制不同用户或用户组对 Kubernetes 集群资源的访问权限。

Namespace 中的权限控制

  1. Namespace 特定的权限控制 在 Namespace 级别,可以通过创建 Role 和 RoleBinding 来实现对该 Namespace 内资源的权限控制。例如,假设在 finance - namespace 中,只允许财务团队的成员对该 Namespace 中的 Deployment 进行操作,而不允许其他团队成员访问。首先创建一个 Role:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: finance - namespace
  name: finance - deployment - role
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

然后创建一个 RoleBinding,将该 Role 绑定给财务团队的用户组:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: finance - namespace
  name: finance - deployment - binding
subjects:
- kind: Group
  name: finance - team - group
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: finance - deployment - role
  apiGroup: rbac.authorization.k8s.io

这样,只有属于 finance - team - group 用户组的成员才能对 finance - namespace 中的 Deployments 进行操作,其他用户则没有权限。

  1. 跨 Namespace 的权限控制 有时候,可能需要赋予某些用户跨多个 Namespace 的权限。例如,集群管理员可能需要对所有 Namespace 中的 Pods 进行查看和管理。这时可以使用 ClusterRole 和 ClusterRoleBinding。首先创建一个 ClusterRole:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster - pod - admin - role
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

然后创建一个 ClusterRoleBinding,将该 ClusterRole 绑定给管理员用户组:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: cluster - pod - admin - binding
subjects:
- kind: Group
  name: cluster - admins - group
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster - pod - admin - role
  apiGroup: rbac.authorization.k8s.io

通过这种方式,cluster - admins - group 用户组的成员就可以对所有 Namespace 中的 Pods 进行操作。

基于 Namespace 的资源配额管理

  1. 资源配额概念 资源配额(ResourceQuota)是 Kubernetes 用于限制 Namespace 内可使用资源总量的一种机制。通过设置资源配额,可以确保每个 Namespace(租户)在资源使用上不会过度消耗集群资源,从而保证不同租户之间的资源公平性和稳定性。例如,可以为某个 Namespace 设置 CPU 和内存的使用上限,以及 Pod、Service 等资源对象的数量上限。

  2. 创建资源配额 以下是一个为 example - namespace 创建资源配额的 YAML 示例,限制该 Namespace 内可使用的 CPU、内存以及 Pod 和 Service 的数量:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: example - quota
  namespace: example - namespace
spec:
  hard:
    pods: "10"
    services: "5"
    cpu: "2"
    memory: "4Gi"

在上述示例中,hard 字段定义了资源配额的具体限制。pods 限制为 10 个,意味着在 example - namespace 中最多只能创建 10 个 Pod;services 限制为 5 个,即最多可创建 5 个 Service;cpu 限制为 2 个 CPU 核心,memory 限制为 4GiB 内存。

如果在 example - namespace 中尝试创建超过这些限制的资源,Kubernetes 会拒绝该操作,并返回相应的错误信息。例如,当尝试创建第 11 个 Pod 时,会收到类似如下的错误:

Error from server (Forbidden): error when creating "pod - example.yaml": pods "example - pod - 11" is forbidden: exceeded quota: example - quota, requested: pods=1, used: pods=10, limited: pods=10
  1. 资源配额的动态调整 随着业务的发展,Namespace 内的资源需求可能会发生变化。可以通过更新资源配额的 YAML 文件来动态调整资源限制。例如,如果 example - namespace 需要更多的 Pod 资源,可以修改资源配额配置文件如下:
apiVersion: v1
kind: ResourceQuota
metadata:
  name: example - quota
  namespace: example - namespace
spec:
  hard:
    pods: "20"
    services: "5"
    cpu: "2"
    memory: "4Gi"

然后使用 kubectl apply 命令更新资源配额:

kubectl apply - f quota - example - updated.yaml

这样就将 example - namespace 中 Pod 的数量上限从 10 个调整到了 20 个。

网络策略与 Namespace 安全

  1. 网络策略基础 网络策略(NetworkPolicy)是 Kubernetes 用于定义 Pod 之间网络访问规则的一种资源。通过网络策略,可以实现细粒度的网络访问控制,增强 Namespace 的安全性。网络策略基于标签选择器来选择目标 Pod,并定义允许或拒绝的网络流量规则。

  2. Namespace 内的网络策略 例如,在 marketing - namespace 中,假设只有特定的一组前端 Pod 可以访问后端 API Pod。首先,为前端 Pod 和后端 API Pod 分别添加标签:

# 前端 Pod 配置
apiVersion: v1
kind: Pod
metadata:
  name: frontend - pod
  namespace: marketing - namespace
  labels:
    app: marketing - frontend
spec:
  containers:
  - name: frontend - container
    image: frontend - image

# 后端 API Pod 配置
apiVersion: v1
kind: Pod
metadata:
  name: api - pod
  namespace: marketing - namespace
  labels:
    app: marketing - api
spec:
  containers:
  - name: api - container
    image: api - image

然后创建一个网络策略,允许 marketing - frontend 标签的 Pod 访问 marketing - api 标签的 Pod:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: frontend - to - api - policy
  namespace: marketing - namespace
spec:
  podSelector:
    matchLabels:
      app: marketing - api
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: marketing - frontend

在上述网络策略中,podSelector 选择了目标后端 API Pod,ingress 部分定义了允许来自前端 Pod 的入站流量。这样就限制了只有前端 Pod 可以访问后端 API Pod,提高了 marketing - namespace 内的网络安全性。

  1. 跨 Namespace 的网络策略 有时候,可能需要定义跨 Namespace 的网络访问规则。例如,在 engineering - namespace 中的监控服务需要访问所有 Namespace 中的 Prometheus Exporter Pod。首先,为 Prometheus Exporter Pod 添加标签,假设标签为 app: prometheus - exporter。然后创建一个 NetworkPolicy:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: monitor - to - exporter - policy
  namespace: engineering - namespace
spec:
  podSelector:
    matchLabels:
      app: monitor - service
  ingress:
  - from:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          app: prometheus - exporter

在这个网络策略中,namespaceSelector: {} 表示匹配所有 Namespace,podSelector 选择了所有带有 app: prometheus - exporter 标签的 Pod。这样就允许了 engineering - namespace 中的监控服务访问所有 Namespace 中的 Prometheus Exporter Pod。

多租户场景下的 Namespace 管理实践

  1. 开发、测试与生产环境隔离 在企业应用开发过程中,通常会有开发、测试和生产等不同环境。通过使用 Namespace,可以将这些环境进行有效隔离。例如,创建 dev - namespacetest - namespaceprod - namespace 分别用于开发、测试和生产环境。在每个 Namespace 中,可以根据各自的需求设置不同的资源配额、权限控制和网络策略。 在 dev - namespace 中,开发人员可能需要较高的权限来快速迭代和测试代码,可以赋予他们对该 Namespace 内所有资源的完全访问权限。而在 prod - namespace 中,权限则需要严格控制,只有运维人员和特定的审批人员才能进行操作,同时设置更严格的资源配额以保证生产环境的稳定性。

  2. 多团队协作场景 当多个团队在同一 Kubernetes 集群中协作时,每个团队可以拥有自己的 Namespace。例如,电商公司的商品团队、订单团队和用户团队可以分别使用 product - namespaceorder - namespaceuser - namespace。每个团队可以在自己的 Namespace 内独立管理和部署应用,同时通过权限控制和网络策略来保证团队之间的资源隔离和安全性。如果订单团队的应用需要与商品团队的商品服务进行交互,可以通过定义合适的跨 Namespace 网络策略来实现安全的通信。

  3. Namespace 的生命周期管理 在多租户场景下,Namespace 的生命周期管理也很重要。随着项目的启动和结束,相应的 Namespace 可能需要创建和删除。例如,当一个新的业务项目启动时,创建一个新的 Namespace 并为其配置好资源配额、权限和网络策略等。当项目结束时,及时删除该 Namespace 及其所有资源,以释放集群资源。这可以通过自动化脚本来实现,结合 CI/CD 流程,在项目部署和拆除阶段自动创建和删除对应的 Namespace。

高级 Namespace 管理技巧

  1. Namespace 标签与注解的使用 Namespace 可以添加标签(Labels)和注解(Annotations)来进行元数据管理和辅助自动化流程。标签可以用于对 Namespace 进行分类和选择,例如,可以为不同业务部门的 Namespace 添加 department: financedepartment: engineering 标签,方便进行资源统计和权限管理。注解则可以用于记录一些额外的信息,如 Namespace 的创建者、用途描述等。 以下是为 example - namespace 添加标签和注解的 YAML 示例:
apiVersion: v1
kind: Namespace
metadata:
  name: example - namespace
  labels:
    environment: development
    project: my - project
  annotations:
    created - by: user - 1
    description: This namespace is for development of my - project

通过标签和注解,可以更方便地对 Namespace 进行管理和查询。例如,可以使用 kubectl get namespaces - l environment = development 命令来获取所有环境为开发的 Namespace。

  1. Namespace 资源的跨区域复制 在一些大规模分布式系统中,可能需要在不同区域的 Kubernetes 集群中复制 Namespace 及其资源。这可以通过一些工具如 kubectl - cross - cluster 或自定义脚本结合 Kubernetes API 来实现。例如,将 prod - namespace 及其所有资源从一个区域的集群复制到另一个区域的集群,以实现数据容灾和高可用性。在复制过程中,需要注意资源的依赖关系和网络配置等问题,确保复制后的 Namespace 能够正常运行。

  2. Namespace 与 Service Mesh 集成 Service Mesh 如 Istio 可以与 Namespace 结合使用,进一步增强多租户管理的能力。通过 Istio,可以在 Namespace 级别实现更细粒度的流量管理、安全策略和遥测数据收集。例如,在不同的 Namespace 中,可以为服务定义不同的流量路由规则,实现灰度发布、故障注入等功能。同时,Istio 可以提供统一的安全认证和授权机制,与 Kubernetes 的 RBAC 结合,为多租户应用提供更强大的安全保障。

常见问题与解决方法

  1. 权限不足问题 当用户在 Namespace 中执行操作时,可能会遇到权限不足的错误。例如,尝试删除一个 Deployment 时收到 forbidden: User "user - 1" cannot delete deployments.apps in the namespace "example - namespace" 错误。这种情况下,需要检查相应的 Role 和 RoleBinding 是否正确配置。可以通过 kubectl describe role pod - admin - role - n example - namespacekubectl describe rolebinding pod - admin - binding - n example - namespace 命令查看角色和角色绑定的详细信息,确认用户是否被正确赋予了相应的权限。如果权限不足,可以更新 Role 或 RoleBinding 配置文件并重新应用。

  2. 资源配额超额问题 如果在 Namespace 中创建资源时遇到资源配额超额的错误,如前文提到的创建 Pod 超过配额限制。首先,可以通过 kubectl describe quota example - quota - n example - namespace 命令查看当前资源配额的使用情况和限制。如果确实需要增加资源配额,可以编辑资源配额的 YAML 文件并重新应用。同时,也需要对 Namespace 内的资源使用情况进行分析,优化资源配置,避免不必要的资源浪费。

  3. 网络策略不生效问题 在配置网络策略后,如果发现网络访问没有按照预期的规则进行控制,可能是网络策略配置有误。首先,检查网络策略的标签选择器是否正确匹配目标 Pod。可以通过 kubectl get pods - l app = marketing - api - n marketing - namespace 命令确认 Pod 的标签是否正确。然后,检查网络策略的 ingressegress 规则是否符合需求,例如端口号、协议等配置是否正确。如果网络策略仍然不生效,还需要检查集群的网络插件是否支持网络策略功能,以及是否有其他网络配置冲突。

在 Kubernetes 多租户管理中,Namespace 的使用与权限控制是核心要点。通过合理地创建和管理 Namespace,精细地配置权限和资源配额,以及巧妙地运用网络策略,可以实现安全、高效的多租户环境,满足不同团队和项目在同一 Kubernetes 集群中的多样化需求。同时,在实践过程中,需要不断总结经验,解决遇到的各种问题,以提升 Kubernetes 集群的整体管理水平和运行效率。