善良有点二 發表於 2025-5-27 10:26:00

K8s进阶之多租户场景下的资源配额(ResourceQuota)

<h2 id="概述">概述</h2>
<p>ResourceQuota官方文档:https://kubernetes.io/zh-cn/docs/concepts/policy/resource-quotas/</p>
<p>在 Kubernetes(K8s)中,ResourceQuota(资源配额)是一种用于管理命名空间(Namespace)资源使用的核心机制。它通过限制命名空间内可消耗的资源总量,实现资源的精细化分配和隔离,避免单个命名空间过度占用集群资源,保障集群稳定性和多租户环境的公平性。</p>
<p>ResourceQuota 通常与 LimitRange 的配合使用:</p>
<ul>
<li>ResourceQuota:限制命名空间级别的资源总量(如整个命名空间最多使用 2 核 CPU)。</li>
<li>LimitRange:限制单个 Pod / 容器的资源请求 / 限制范围(如单个 Pod 的 CPU 请求必须≥100m 且≤500m)。</li>
</ul>
<blockquote>
<p>关于LimitRange可以查看这篇文章:K8s进阶之LimitRange</p>
</blockquote>
<h2 id="应用场景">应用场景</h2>
<h3 id="多租户资源隔离">多租户资源隔离</h3>
<h4 id="场景">场景:</h4>
<p>在多租户集群中(如开发、测试、生产环境共用一个集群),不同租户或团队使用独立的命名空间。</p>
<h4 id="作用">作用:</h4>
<p>为每个命名空间设置 CPU、内存、存储等资源的硬限制,防止某个租户滥用资源影响其他租户。</p>
<h3 id="开发--测试环境资源管控">开发 / 测试环境资源管控</h3>
<h4 id="场景-1">场景:</h4>
<p>开发和测试环境通常需要快速迭代,但资源使用可能缺乏约束(如临时创建大量 Pod)。</p>
<h4 id="作用-1">作用:</h4>
<p>限制命名空间内可创建的 Pod、服务、PersistentVolumeClaim(PVC)等对象的数量,避免资源浪费。</p>
<h3 id="生产环境资源预留与保障">生产环境资源预留与保障</h3>
<h4 id="场景-2">场景:</h4>
<p>生产环境需要为关键应用预留资源,避免被非关键业务抢占。</p>
<h4 id="作用-2">作用:</h4>
<p>为生产环境的命名空间设置较高的资源配额,同时限制非生产环境的资源上限。<br>
结合LimitRange(资源限制范围),确保 Pod 的资源请求 / 限制符合配额要求。</p>
<h3 id="防止集群资源耗尽">防止集群资源耗尽</h3>
<h4 id="场景-3">场景:</h4>
<p>当集群资源有限时(如 CPU、内存总量固定),未限制的命名空间可能导致集群整体资源不足,影响所有业务。</p>
<h4 id="作用-3">作用:</h4>
<p>通过全局配额(在default命名空间或所有命名空间启用),限制整个集群的资源使用上限,保障系统组件(如 kube-proxy、CoreDNS)和高优先级应用的资源可用性。</p>
<h2 id="resourcequota支持的资源类型">ResourceQuota支持的资源类型</h2>
<h3 id="计算资源">计算资源</h3>
<ul>
<li>requests.cpu:所有 Pod 的 CPU 请求总量(以核心数为单位,如1表示 1 核,0.5或500m表示 0.5 核)</li>
<li>requests.memory:内存请求总量(如1Gi、512Mi)</li>
<li>limits.cpu:CPU 限制总量(Pod 可突发使用的最大 CPU)</li>
<li>limits.memory:内存限制总量(Pod 的 OOM 阈值)</li>
</ul>
<h3 id="存储资源">存储资源</h3>
<ul>
<li>persistentvolumeclaims:PVC 数量上限</li>
<li>storageclass.storage:特定存储类的存储总量(如storageclass.storage.k8s.io/ssd=100Gi)</li>
</ul>
<h3 id="对象数量">对象数量</h3>
<ul>
<li>pods:Pod 数量上限(包括运行中、已终止的 Pod)</li>
<li>services:服务数量上限</li>
<li>replicationcontrollers:复制控制器数量上限</li>
<li>secrets:Secret 数量上限</li>
<li>configmaps:ConfigMap 数量上限</li>
<li>deployments.apps:Deployment 数量上限(需启用apps API 组)</li>
<li>statefulsets.apps:StatefulSet 数量上限</li>
</ul>
<h2 id="resourcequota资源文件解析">ResourceQuota资源文件解析</h2>
<pre><code>apiVersion: v1
kind: ResourceQuota
metadata:
name: namespace-quota
namespace: my-namespace# 指定要应用配额的命名空间
spec:
hard:
    # 计算资源配额
    requests.cpu: "2"      # CPU 总请求量上限
    requests.memory: 4Gi   # 内存总请求量上限
    limits.cpu: "4"          # CPU 总限制量上限
    limits.memory: 8Gi       # 内存总限制量上限

    # 存储资源配额
    requests.storage: 10Gi   # 存储总请求量上限
    persistentvolumeclaims: "2"# PVC 数量上限

    # 对象数量配额
    pods: "10"               # Pod 数量上限
    services: "5"            # Service 数量上限
    configmaps: "10"         # ConfigMap 数量上限
    secrets: "10"            # Secret 数量上限
    replicationcontrollers: "5"# ReplicationController 数量上限
    services.loadbalancers: "2"# LoadBalancer 类型 Service 数量上限
    services.nodeports: "2"      # NodePort 类型 Service 数量上限
</code></pre>
<h2 id="实战案例">实战案例</h2>
<p>创建命名空间并配置资源配额</p>
<pre><code># 创建命名空间
# kubectl create namespace dev
namespace/dev created

# 查看命名空间是否创建成功
# kubectl get ns dev
NAME   STATUS   AGE
dev    Active   5s
</code></pre>
<p>配置资源配额</p>
<pre><code># 定义资源配额
# cat dev-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
# 指定要应用配额的命名空间
namespace: dev
spec:
hard:
    # 计算资源配额
    # CPU 总请求量上限,1核心
    requests.cpu: "1"
    # 内存总请求量上限,1G
    requests.memory: 1Gi
    # CPU 总限制量上限,1核心
    limits.cpu: "1"
    # 内存总限制量上限,1G
    limits.memory: 1Gi

    # 存储资源配额
   # 存储总请求量上限
    requests.storage: 5Gi
    # PVC 数量上限
    persistentvolumeclaims: "2"

    # 对象数量配额
    # Pod 数量上限
    pods: "10"
    # Service 数量上限
    services: "2"
    # ConfigMap 数量上限
    configmaps: "3"
    # Secret 数量上限
    secrets: "10"
    # ReplicationController 数量上限
    replicationcontrollers: "5"
    # LoadBalancer 类型 Service 数量上限
    services.loadbalancers: "2"
    # NodePort 类型 Service 数量上限
    services.nodeports: "2"
    # Deployment 数量上限
    apps/deployments: "3"
    # replicasets 数量上限
    apps/replicasets: "3"
    # job的数量上限
    batch/jobs: "2"
    # cronjobs的数量上限
    batch/cronjobs: "2"

# 创建资源配额
# kubectl apply -f dev-quota.yaml
resourcequota/dev-quota created
</code></pre>
<p>查看一下详细信息</p>
<pre><code># 查看quota
# kubectl get quota -n dev
NAME      AGE   REQUEST                                                                                                                                                                                                                                                                                                                           LIMIT
dev-quota   59s   apps/deployments: 0/3, apps/replicasets: 0/3, batch/cronjobs: 0/2, batch/jobs: 0/2, configmaps: 1/3, persistentvolumeclaims: 0/2, pods: 0/10, replicationcontrollers: 0/5, requests.cpu: 0/1, requests.memory: 0/1Gi, requests.storage: 0/5Gi, secrets: 0/10, services: 0/2, services.loadbalancers: 0/2, services.nodeports: 0/2   limits.cpu: 0/1, limits.memory: 0/1Gi

# 查看详细信息
# kubectl describe quota dev-quota -n dev
Name:                   dev-quota
Namespace:            dev
Resource                UsedHard
--------                --------
apps/deployments      0   3
apps/replicasets      0   3
batch/cronjobs          0   2
batch/jobs            0   2
configmaps            1   3
limits.cpu            0   1
limits.memory         0   1Gi
persistentvolumeclaims0   2
pods                  0   10
replicationcontrollers0   5
requests.cpu            0   1
requests.memory         0   1Gi
requests.storage      0   5Gi
secrets               0   10
services                0   2
services.loadbalancers0   2
services.nodeports      0   2
</code></pre>
<h2 id="验证resourcequota">验证ResourceQuota</h2>
<h3 id="验证计算资源">验证计算资源</h3>
<p>当我们创建Pod时不指定CPU和memory的资源会发生什么呢?</p>
<p>创建Pod时会报错,错误信息提示我们需要指定request和limit,当在ResourceQuota限制的命名空间内,创建Pod时,需要配置对应的资源限额,这是一个强制性的诉求</p>
<pre><code># cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: dev
spec:
containers:
- name: nginx-container-1
    image: nginx:latest
# kubectl apply -f pod.yaml
Error from server (Forbidden): error when creating "pod.yaml": pods "nginx-pod" is forbidden: failed quota: dev-quota: must specify limits.cpu for: nginx-container-1; limits.memory for: nginx-container-1; requests.cpu for: nginx-container-1; requests.memory for: nginx-container-1

</code></pre>
<p>创建出一个符合规则约束的Pod,看看会发生什么</p>
<pre><code># cat pod-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-1
namespace: dev
spec:
containers:
- name: nginx-container-1
    image: nginx:latest
    # 定义资源限制
    resources:
      requests:
      cpu: "0.5"
      memory: "500Mi"
      limits:
      cpu: "0.5"
      memory: "500Mi"

# kubectl apply -f pod-1.yaml
pod/nginx-pod-1 created

# 查看quota,发现Used列产生了数据
# kubectl describe quota -n dev
Name:                   dev-quota
Namespace:            dev
Resource                Used   Hard
--------                ----   ----
apps/deployments      0      3
apps/replicasets      0      3
batch/cronjobs          0      2
batch/jobs            0      2
configmaps            1      3
limits.cpu            500m   1
limits.memory         500Mi1Gi
persistentvolumeclaims0      2
pods                  1      10
replicationcontrollers0      5
requests.cpu            500m   1
requests.memory         500Mi1Gi
requests.storage      0      5Gi
secrets               0      10
services                0      2
services.loadbalancers0      2
services.nodeports      0      2
</code></pre>
<p>在创建一个Pod,将CPU和memory分别设置为0.8和800Mi</p>
<p>发现在我们创建时,提示报错了,为什么呢?因为我们创建的Pod资源请求超出了规定的配额</p>
<pre><code># cat pod-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod-2
namespace: dev
spec:
containers:
- name: nginx-container-2
    image: nginx:latest
    resources:
      requests:
      cpu: "0.8"
      memory: "800Mi"
      limits:
      cpu: "0.8"
      memory: "800Mi"
# kubectl apply -f pod-2.yaml
Error from server (Forbidden): error when creating "pod-2.yaml": pods "nginx-pod-2" is forbidden: exceeded quota: dev-quota, requested: limits.cpu=800m,limits.memory=800Mi,requests.cpu=800m,requests.memory=800Mi, used: limits.cpu=500m,limits.memory=500Mi,requests.cpu=500m,requests.memory=500Mi, limited: limits.cpu=1,limits.memory=1Gi,requests.cpu=1,requests.memory=1Gi
</code></pre>
<h3 id="验证service资源">验证service资源</h3>
<p>我们先创建两个service,类型分别是nodePort和loadBalancer</p>
<pre><code># cat service-1.yaml
# NodePort类型的service
apiVersion: v1
kind: Service
metadata:
name: nginx-nodeport
namespace: dev
spec:
type: NodePort
ports:
    - protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30080

---
# LoadBalancer类型service
apiVersion: v1
kind: Service
metadata:
name: nginx-loadbalancer
namespace: dev
spec:
type: LoadBalancer
ports:
    - protocol: TCP
      port: 80
      targetPort: 80
# 创建
# kubectl apply -f service-1.yaml
service/nginx-nodeport created
service/nginx-loadbalancer created
# 查看
# kubectl get service -n dev
NAME               TYPE         CLUSTER-IP   EXTERNAL-IP   PORT(S)      AGE
nginx-loadbalancer   LoadBalancer   10.96.1.23   &lt;pending&gt;   80:30531/TCP   5s
nginx-nodeport       NodePort       10.96.1.11   &lt;none&gt;      80:30080/TCP   5s
</code></pre>
<p>查看一下quota详细信息</p>
<pre><code># kubectl describe quota dev-quota -n dev
Name:                   dev-quota
Namespace:            dev
Resource                Used   Hard
--------                ----   ----
apps/deployments      0      3
apps/replicasets      0      3
batch/cronjobs          0      2
batch/jobs            0      2
configmaps            1      3
limits.cpu            500m   1
limits.memory         500Mi1Gi
persistentvolumeclaims0      2
pods                  1      10
replicationcontrollers0      5
requests.cpu            500m   1
requests.memory         500Mi1Gi
requests.storage      0      5Gi
secrets               0      10
services                2      2
services.loadbalancers1      2
services.nodeports      2      2
</code></pre>
<p>这里nodeports的数量为2,为什么呢?因为loadbalancer类型的service底层使用的就是nodeport。所以创建loadbalancer类型的service时会自动创建一个nodeport。</p>
<blockquote>
<p>关于service可以学习这篇文章:K8s新手系列之Service资源</p>
</blockquote>
<p>这个时候我们在创建一个clusterip类型的service,看看会发生什么?<br>
再继续创建的话,会报错,提示我们service的数量已经不够了</p>
<pre><code># cat service-3.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-clusterip
namespace: dev
spec:
type: ClusterIP
ports:
    - protocol: TCP
      port: 80
      targetPort: 80
# kubectl apply -f service-3.yaml
Error from server (Forbidden): error when creating "service-3.yaml": services "nginx-clusterip" is forbidden: exceeded quota: dev-quota, requested: services=1, used: services=2, limited: services=2
</code></pre>
<h3 id="验证其它资源">验证其它资源</h3>
<p>这里大家可以根据上面的案例自行测试,</p>
<h2 id="resourcequota管理">ResourceQuota管理</h2>
<h3 id="查看resourcequota">查看ResourceQuota</h3>
<pre><code>kubectl get quota &lt;quota-name&gt; -n &lt;namespace&gt;

# 查看详细信息
kubectl describe quota&lt;quota-name&gt; -n &lt;namespace&gt;
</code></pre>
<h3 id="删除resourcequota">删除ResourceQuota</h3>
<pre><code>kubectl delete quota &lt;quota-name&gt; -n &lt;namespace&gt;
</code></pre>
<h3 id="修改已经定义好的resourcequota">修改已经定义好的ResourceQuota</h3>
<h4 id="方式一直接修改资源清单文件重新应用即可">方式一,直接修改资源清单文件,重新应用即可</h4>
<p>示例:</p>
<pre><code># cat dev-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
# 指定要应用配额的命名空间
namespace: dev
spec:
hard:
    # 修改为10
    requests.cpu: "10"
    # 修改为10G
    requests.memory: 10Gi
    limits.cpu: "1"
    limits.memory: 10Gi
    # 修改为50G
    requests.storage: 50Gi
    persistentvolumeclaims: "2"

    pods: "10"
    services: "2"
    configmaps: "3"
    secrets: "10"
    replicationcontrollers: "5"
    services.loadbalancers: "2"
    services.nodeports: "2"
    apps/deployments: "3"
    apps/replicasets: "3"
    batch/jobs: "2"
    batch/cronjobs: "2"
# 重新应用
# kubectl apply -f dev-quota.yaml
resourcequota/dev-quota configured

# 查看更新后的资源
# kubectl describe quota dev-quota -n dev
Name:                   dev-quota
Namespace:            dev
Resource                Used   Hard
--------                ----   ----
apps/deployments      0      3
apps/replicasets      0      3
batch/cronjobs          0      2
batch/jobs            0      2
configmaps            1      3
limits.cpu            500m   1
limits.memory         500Mi10Gi # 已更新
persistentvolumeclaims0      2
pods                  1      10
replicationcontrollers0      5
requests.cpu            500m   10
requests.memory         500Mi10Gi # 已更新
requests.storage      0      50Gi # 已更新
secrets               0      10
services                2      2
services.loadbalancers1      2
services.nodeports      2      2
</code></pre>
<h4 id="方式二使用kubectl-edit-命令直接编辑保存即可">方式二:使用<code>kubectl edit</code> 命令直接编辑保存即可</h4>


</div>
<div id="MySignature" role="contentinfo">
    <p>本文来自博客园,作者:huangSir-devops,转载请注明原文链接:https://www.cnblogs.com/huangSir-devops/p/18895344,微信Vac6666666,欢迎交流</p><br><br>
来源:https://www.cnblogs.com/huangSir-devops/p/18895344
頁: [1]
查看完整版本: K8s进阶之多租户场景下的资源配额(ResourceQuota)