侧边栏壁纸
博主头像
路小飞博主等级

行动起来,活在当下

  • 累计撰写 72 篇文章
  • 累计创建 12 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

10- Kubernetes 资源管理

路小飞
2024-10-22 / 0 评论 / 0 点赞 / 9 阅读 / 11936 字

10.1 Kubernetes 资源管理

10.1.1 ResourcceQuota 简介

ResourceQuota 是什么

在使用 Kubernetes 时,公司可能会有多个项目组,每个项目组都有自己的命名空间,能够在其中创建资源。然而,他们通常对 Kubernetes 集群的规模和可调度资源的数量并不了解,这可能导致资源的过量分配,从而影响集群的可用性。为了解决这个问题,Kubernetes 引入了 ResourceQuota 的概念。

ResourceQuota 是 Kubernetes 中的一种资源对象,用于限制特定命名空间内的资源使用。

定义一个 ResourceQuota

使用以下 YAML 文件定义 ResourceQuota:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: my-resource-quota
  namespace: my-namespace
spec:
  hard:
    requests.cpu: "10"                      # CPU 请求总量限制,10 表示 10000m
    limits.cpu: "20"                         # CPU 限制总量限制
    requests.memory: "20Gi"                  # 内存请求总量限制
    limits.memory: "40Gi"                    # 内存限制总量限制
    pods: "30"                               # Pod 总数量限制
    replicationcontrollers: "5"              # 复制控制器总数量限制
    replicasets.apps: "10"                   # 副本集总数量限制
    deployments.apps: "10"                   # Deployment 总数量限制
    persistentvolumeclaims: "15"             # PVC 总数量限制
    requests.storage: "100Gi"                # 存储请求总量限制
    services: "10"                           # 服务总数量限制
    secrets: "100"                           # 秘密总数量限制
    configmaps: "100"                        # 配置映射总数量限制
    networkpolicies: "5"                     # 网络策略总数量限制
    ingresses.networking.k8s.io: "10"        # Ingress 总数量限制

10.1.2 使用 ResourceQuota 案例

假设我们有一个命名空间 dev,我们希望限制该命名空间中使用的资源量,以确保不会超出集群资源的容量。

步骤 1: 创建命名空间

首先,我们需要创建一个命名空间:

apiVersion: v1
kind: Namespace
metadata:
  name: dev

可以使用以下命令创建命名空间:

kubectl apply -f namespace.yaml
步骤 2: 创建 ResourceQuota

接下来,我们在该命名空间中定义一个 ResourceQuota。我们希望限制 dev 命名空间中 CPU 和内存的使用量,具体如下:

  • 最大 CPU 限制为 4 个核心
  • 最大内存限制为 8 GiB
  • 最多允许 10 个 Pod

以下是 ResourceQuota 的 YAML 文件:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: dev-resource-quota
  namespace: dev
spec:
  hard:
    requests.cpu: "4"
    requests.memory: "8Gi"
    limits.cpu: "4"
    limits.memory: "8Gi"
    pods: "10"

使用以下命令应用 ResourceQuota

kubectl apply -f resource-quota.yaml
步骤 3: 验证 ResourceQuota

你可以通过以下命令查看命名空间的 ResourceQuota 状态:

kubectl get resourcequota -n dev

这将显示 dev 命名空间中当前的资源使用情况和限制。

[root@master-01 ~]# kubectl get resourcequota -n dev
NAME                 AGE   REQUEST                                                 LIMIT
dev-resource-quota   12s   pods: 0/10, requests.cpu: 0/4, requests.memory: 0/8Gi   limits.cpu: 0/4, limits.memory: 0/8Gi

步骤 4: 尝试创建资源

现在,如果你在 dev 命名空间中尝试创建超出限制的 Pod 或者设置超出配额的资源请求,将会失败。例如,以下 Pod 定义将会被拒绝,因为它请求的 CPU 和内存超过了配额:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
  namespace: dev
spec:
  containers:
  - name: example-container
    image: nginx
    resources:
      requests:
        cpu: "2"
        memory: "6Gi"
      limits:
        cpu: "2"
        memory: "6Gi"
[root@master-01 ~]# kubectl get pod -n dev
NAME          READY   STATUS    RESTARTS   AGE
example-pod   0/1     Pending   0          10s
[root@master-01 ~]# kubectl describe pod example-pod -n dev
Name:         example-pod
Namespace:    dev
Priority:     0
Node:         <none>
Labels:       <none>
Annotations:  <none>
Status:       Pending
IP:           
IPs:          <none>
Containers:
  example-container:
    Image:      nginx
    Port:       <none>
    Host Port:  <none>
    Limits:
      cpu:     2
      memory:  6Gi
    Requests:
      cpu:        2
      memory:     6Gi
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-zdbrw (ro)
Conditions:
  Type           Status
  PodScheduled   False 
Volumes:
  kube-api-access-zdbrw:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   Guaranteed
Node-Selectors:              <none>
Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  22s   default-scheduler  0/2 nodes are available: 2 Insufficient cpu, 2 Insufficient memory.
[root@master-01 ~]# 

步骤 5: 创建资源成功的示例

如果你创建的 Pod 符合配额要求,比如:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod-2
  namespace: dev
spec:
  containers:
  - name: example-container
    image: nginx
    resources:
      requests:
        cpu: "1"
        memory: "2Gi"
      limits:
        cpu: "1"
        memory: "2Gi"

这个 Pod 将会成功创建,因为它在配额限制内。

[root@master-01 ~]# kubectl -n dev get pod
NAME            READY   STATUS    RESTARTS   AGE
example-pod-2   1/1     Running   0          2m43s
[root@master-01 ~]# kubectl -n dev get resourcequotas 
NAME                 AGE     REQUEST                                                   LIMIT
dev-resource-quota   6m41s   pods: 1/10, requests.cpu: 1/4, requests.memory: 2Gi/8Gi   limits.cpu: 1/4, limits.memory: 2Gi/8Gi

[root@master-01 ~]# kubectl -n dev get resourcequotas dev-resource-quota -oyaml
apiVersion: v1
kind: ResourceQuota
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"ResourceQuota","metadata":{"annotations":{},"name":"dev-resource-quota","namespace":"dev"},"spec":{"hard":{"limits.cpu":"4","limits.memory":"8Gi","pods":"10","requests.cpu":"4","requests.memory":"8Gi"}}}
  creationTimestamp: "2024-10-22T14:10:58Z"
  name: dev-resource-quota
  namespace: dev
  resourceVersion: "38337"
  uid: 2ecf9dc6-4017-42de-a9c7-4d6c939cde63
spec:
  hard:
    limits.cpu: "4"
    limits.memory: 8Gi
    pods: "10"
    requests.cpu: "4"
    requests.memory: 8Gi
status:
  hard:
    limits.cpu: "4"
    limits.memory: 8Gi
    pods: "10"
    requests.cpu: "4"
    requests.memory: 8Gi
  used:
    limits.cpu: "1"
    limits.memory: 2Gi
    pods: "1"
    requests.cpu: "1"
    requests.memory: 2Gi
[root@master-01 ~]# 

10.2 Pod 的资源限制

通过使用 ResourceQuota,我们能够限制 Kubernetes 集群中命名空间的可用资源。然而,在同一个命名空间内,如果分配了 16 核 CPU 和 64 GB 内存,但某个 Pod 未设定资源限制,可能会导致该 Pod 占用整个命名空间的资源。为防止这种情况发生,我们应为每个 Pod 设置资源限制。

假设我们有一个 Java 进程,最低需要 1 核 CPU 和 2GB 内存才能正常启动,并且需要 10 个副本以支撑业务量。在这种情况下,我们需要创建一个 Deployment,设置副本数为 10,requests.cpu 为 1,requests.memory 为 2GB。在创建该资源时,Scheduler 会根据一系列算法将 Pod 部署到合适的节点上,而被调度的节点至少需要有 1 核 CPU 和 2GB 的空闲资源。

如果未设置 requests 字段,Scheduler 在调度时将不会检查节点上的资源是否满足应用程序的最低需求。此时,Pod 可能会随机部署到资源不足的节点上,导致容器无法启动,形成恶性循环。如果 10 个副本中有 3 个部署到资源紧张的节点上,它们之间会出现资源竞争,可能导致所有副本都无法启动。此外,启动过程中高 CPU 使用率可能会使正在运行的 Pod 和节点不可用,进而引发系统崩溃。因此,合理设置 requestslimits 是非常必要的。

10.2.1 Pod 的资源限制

在 Pod 的 YAML 文件中,你可以在 spec.containers 下的 resources 字段中设置请求和限制。例如:

yamlCopy CodeapiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: my-container
    image: nginx
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

在容器的 resources 字段下,我们定义了对内存和 CPU 的限制和请求。

limits 定义了对资源的最大限制:

  • memory: "200Mi" 表示最大可用内存为 200MiB。
  • cpu: "500m" 表示最大可用 CPU 为 500 毫核(0.5 核)。

requests 定义了对资源的请求:

  • memory: "100Mi" 表示请求 100MiB 的内存。

  • cpu: "250m" 表示请求 250 毫核(0.25 核)的 CPU。

10.2.2 服务质量等级 Qos

尽管我们实施了资源限制,但在实际使用中,节点资源仍然可能不足。为了解决资源不足的问题,Kubernetes 会通过重启或驱逐 Pod 来释放资源,然而这种操作可能导致一些关键服务的不可用。实际上,优先重启或驱逐一些不重要的 Pod 会更为理想,而这一决策是通过服务质量(QoS,Quality of Service)来决定的。因此,在生产环境中,QoS 是一个至关重要的环节。

服务质量等级(Quality of Service,QoS)在 Kubernetes 中也起着重要作用。在 Kubernetes 中,Pod 根据其请求的资源量和使用的资源情况,被分为以下三个 QoS 等级:

Kubernetes 中的 QoS 主要分为三种类别:

1. Guaranteed(保证型)

条件

  • Pod 中每个容器都必须指定 limits.cpurequests.cpu 字段,并且需要两者需要相等;

  • Pod 中每个容器都必须指定 limits.cpurequests.cpu 字段,并且需要两者需要相等;

特点

  • Pods 将始终获得其请求的资源(CPU 和内存)。
  • 在资源不足的情况下,Kubernetes 优先保留保证型 Pods。
  • 容器会在节点上的资源使用限制内运行。

适用场景

  • 适用于对性能要求较高的应用,比如数据库和关键业务服务。

案例

apiVersion: v1
kind: Pod
metadata:
  name: db-service
spec:
  containers:
    - name: postgres
      image: postgres:latest
      resources:
        requests:
          memory: "2Gi"
          cpu: "1"
        limits:
          memory: "2Gi"
          cpu: "1"

2. Burstable

条件

  • Pod 不符合 Guaranteed 的配置要求。
  • Pod 中至少有一个容器配置了 limits.cpurequests.cpulimits.cpurequests.cpu 字段中的一个。

特点:

  • Pods 在资源充足时可以使用超过 requests 的资源,但在资源紧张时可能会被限制到请求的值。
  • 在资源不足的情况下,Kubernetes 会第二优先驱逐此类 Pods。

适用场景

  • 适用于需要一定资源保证但也可以利用额外资源的应用,例如 Web 服务或后台处理任务。

案例

apiVersion: v1
kind: Pod
metadata:
  name: web-app
spec:
  containers:
    - name: nginx
      image: nginx:latest
      resources:
        requests:
          memory: "512Mi"
          cpu: "0.5"
        limits:
          memory: "1Gi"
          cpu: "1"

3. Best Effort

定义

  • 如果 Pod 中的容器没有设置 requestslimits

特点:

  • Pods 不会有任何资源保证,只有在资源充足时才能运行。
  • 在资源不足的情况下,这类 Pods 最先被驱逐。

适用场景

  • 适用于不重要的应用,比如测试或批处理作业。

案例

apiVersion: v1
kind: Pod
metadata:
  name: batch-job
spec:
  containers:
    - name: data-processor
      image: my-dataprocessor:latest

因此,当节点资源不足时,Kubernetes 将优先保证 Guaranteed Pod 的资源需求,然后是 Burstable Pod,最后是 BestEffort Pod。管理员可以根据应用的重要性和资源需求来设置 Pod 的 QoS 等级,以确保关键应用能够获得足够的资源,保障其服务质量。

通常情况下,依赖的底层中间件的 Qos 会配置为 Guaranteed,其他服务可能并不需要那么高的 Qos。

0

评论区