使用分层资源配额

管理员可以使用 Kubernetes 资源配额工具来确保在不同用户之间公平共享资源。由 ResourceQuota 对象定义的资源配额,可提供限制条件来限制单个命名空间中的聚合资源消耗。

层次结构控制器扩展了每个命名空间的资源配额的概念,支持分层命名空间。HierarchicalResourceQuota 对象限制一个子树中所有命名空间的总资源消耗量,使管理员能够跨多个相关命名空间限制资源消耗。

启用分层资源配额时,层次结构控制器会安装两个验证准许 webhook,一个真正强制实施资源消耗限制,另一个用来验证分层资源配额。

启用分层资源配额

分层资源配额由层次结构控制器提供。如需启用分层资源配额,请按以下步骤操作:

  1. 使用 Config Sync 1.6.2 或更高版本安装层次结构控制器

  2. 在 Config Management Operator 的配置文件中,将 spec.hierarchyController 对象中 enableHierarchicalResourceQuota 的值设置为 true

    # config-management.yaml
    
    apiVersion: configmanagement.gke.io/v1
    kind: ConfigManagement
    metadata:
      name: config-management
    spec:
      hierarchyController:
        enabled: true
        # Set to true to enable hierarchical resource quotas:
        enableHierarchicalResourceQuota: true
      # ...other fields...
    
  3. 应用配置:

    kubectl apply -f config-management.yaml
    

    大约一分钟后,层次结构控制器和分层资源配额就可以在您的集群上使用。

如需验证是否已启用分层资源配额,请按以下步骤操作:

  1. 在任何命名空间中创建 HierarchicalResourceQuota 对象,如下所示:

    cat > example-hrq.yaml <<EOF
    apiVersion: hierarchycontroller.configmanagement.gke.io/v1alpha1
    kind: HierarchicalResourceQuota
    metadata:
      name: example-hrq
    spec:
      hard:
        configmaps: "1"
    EOF
    
    kubectl apply -f example-hrq.yaml -n default
    
  2. 确认已在命名空间中使用相同 spec.hard(1 个 configmap)创建名为 gke-hc-hrq 的新 ResourceQuota 对象,例如:

    kubectl describe resourcequota gke-hc-hrq -n default
    

    输出:

    Name:           gke-hc-hrq
    Namespace:      default
    Resource        Used    Hard
    --------        ----    ----
    configmaps      0       1
    
  3. 清理:

    kubectl delete hrq -n default example-hrq
    

    确保移除自动创建的对象:

    kubectl get resourcequota gke-hc-hrq -n default
    

    输出:

    Error from server (NotFound): resourcequotas "gke-hc-hrq" not found
    

使用分层资源配额

设置配额

设置 HierarchicalResourceQuota 与设置常规 ResourceQuota 相同,但具有不同的 apiVersionkind;因此,您可以像在 ResourceQuota 中一样在 spec.hard 字段中设置资源限制。

假设有一个名为 team-a 的团队拥有一个名为 service-a 的服务,并且有一个名为 team-b 的子团队,三者均由分层命名空间表示,如下所示:

kubectl hns tree team-a

输出:

team-a
├── service-a
└── team-b

如果要限制 team-a 中的 configmaps 数量,但不限制任何后代中的数量,您可以按照常规方式创建常规 ResourceQuota,如下所示:

cat > team-a-rq.yaml <<EOF
apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-a-rq
  namespace: team-a
spec:
  hard:
    configmaps: "1"
EOF

kubectl apply -f team-a-rq.yaml

相比之下,如需限制 team-a 及其后代中的 configmaps 总数,请替换上一示例中的 apiVersionkind

cat > team-a-hrq.yaml <<EOF
# Modify the following two lines:
apiVersion: hierarchycontroller.configmanagement.gke.io/v1alpha1
kind: HierarchicalResourceQuota
# Everything below this line remains the same
metadata:
  name: team-a-hrq
  namespace: team-a
spec:
  hard:
    configmaps: "1"

EOF

kubectl apply -f team-a-hrq.yaml

在这三种命名空间中尝试创建 configmap 都会成功。例如,我们可能会选择在其中一个子命名空间中创建 configmap

kubectl create configmap config-1 --from-literal key=value -n team-b

输出:

confimap/config-1 created

但如果再尝试在任何一个命名空间中创建新 configmap 都将失败,包括在同级或父级命名空间中:

kubectl create configmap config-2 --from-literal key=value -n service-a
kubectl create configmap config-2 --from-literal key=value -n team-a

二者的输出:

Error from server (Forbidden): admission webhook "resourcesquotasstatus.hierarchycontroller.configmanagement.gke.io" denied the request: exceeded hierarchical quota in namespace "team-a": "team-a-hrq", requested: configmaps=1, used: configmaps=1, limited: configmaps=1

检查配额

如需查看 HierarchicalResourceQuota 的当前限制和使用情况,请使用 kubectl describe 命令查看常规资源配额:

kubectl describe hrq team-a-hrq -n team-a

输出:

# ...other fields...
Spec:
  Hard:
    Configmaps:  1
Status:
  Hard:
    Configmaps:  1
  Used:
    Configmaps:  1

更新命名空间层次结构

命名空间始终受其祖先中的任何 HierarchicalResourceQuota 的限制。修改命名空间层次结构会触发任何配额的用量的重新计算。

从具有分层配额的子树中移除命名空间

当命名空间从其祖先中具有分层配额的子树中移出时,它将不再受这些配额的限制,并且其资源将从配额的使用量中删除。

例如,如果从前面的子树中移除 team-b,则 team-b 中的 configmap 消耗将没有任何限制。分层配额用量重置为 0,这意味着 team-aservice-a 现在总共可多消耗一个 configmap

将命名空间添加到具有分层配额的子树

将命名空间添加到具有分层配额的子树后,该命名空间将受到分层配额的限制,其资源用量将被添加到配额的用量。

例如,如果将另一个命名空间添加到上一个子树,则新添加的命名空间中将不允许再消耗 configmap。同样,新添加的命名空间中的任何现有 configmap 用量都会添加到分层配额的使用量中。

即使新命名空间的用量超过了分层配额中的限制,分层配额也不会阻止您将新的命名空间移动到子树中。但是,如果超出限制,将禁止使用更多资源,直到用量低于限制或上限增加为止。这与施加的限制低于命名空间中的现有用量时 Kubernetes ResourceQuota 的行为类似。

一般规则

在极端情况下,分层资源配额的行为与 Kubernetes 资源配额类似。例如:

  • 如果多个分层资源配额应用于同一个命名空间,则遵循最严格的资源限制。
  • 如果您创建的限制低于已消耗的资源量,则不会删除现有资源,但是任何将来的资源消耗都将被禁止,直到使用率降至该限制以下或直至上限增加为止。

问题排查

消耗资源时出现 InternalError

当您消耗资源时(例如,创建 configmap),您的请求可能会在 10 秒内停止响应,并且您会看到以下错误消息:

Error from server (InternalError): Internal error occurred: resource quota evaluates timeout

除非 gke-hc-controller-manager pod 处于错误状态,否则不应出现此错误消息。

要解决此问题,拥有权限的管理员可以通过在 hnc-system 命名空间中直接使用 gke-hc-controller-manager- 前缀来删除 pod。pod 会自动重启。在 pod 准备就绪之前,请注意以下事项:

如果上述操作无法解决此问题,请向我们报告情况以便进行分析,最好是您可以使用下列命令来获取日志:

kubectl logs -n hnc-system deployment/gke-hc-controller-manager -c manager

后续步骤