[kubernetes] 资源管理 ---- 资源请求和限制

当Kubernetes调度Pod时,容器是否有足够的资源来实际运行是很重要的。 如果大型应用程序被调度到资源有限的节点上,则节点可能会耗尽内存或CPU资源,并且可能会停止工作!

 

请求和限制

请求和限制是Kubernetes用于控制CPU和内存等资源的机制。 请求是保证容器能够得到的资源。 如果容器请求资源,Kubernetes会将其调度到可以为其提供该资源的节点上。 另一方面,限制则是确保容器的资源请求永远不会超过某个值。 容器只允许达到限制设定的资源值,无法获得更多资源。

重要的是要记住,限制永远不会低于请求。 如果你试试这个,Kubernetes将抛出一个错误,不会让你运行容器。

请求和限制基于单个容器。 虽然Pod通常包含一个容器,但通常也会看到Pods包含多个容器。 Pod中的每个容器都有自己的限制和请求,但由于Pod总是被认为是一个组,因此您需要将组内每个容器的限制和请求加在一起以获取Pod的聚合值。

 

容器设置

有两种类型的资源:CPU和内存(还有GPU卡的资源请求)

Kubernetes调度程序使用这些来确定运行Pod的位置(即哪个节点)。

如果您是在Google Kubernetes Engine中运行,则默认名称空间已经为您设置了一些请求和限制。


这些默认设置仅仅适用于Hello World应用,更改成适合您的应用非常重要。

资源的典型Pod spec可能看起来像这样。 这个Pod有两个容器:


Pod中的每个容器都可以设置自己的请求和限制,这些都是附加的设置。 因此在上面的示例中,Pod的总请求为500 mCPU,内存为128 MiB,总需求为1 CPU256MiB

CPU

CPU资源以毫秒定义。 如果您的容器需要运行两个完整的核心,那么您将设置值2000m。 如果您的容器只需要1/4的核心,那么您将设置一个250m的值。

关于CPU请求要记住的一件事是,如果您输入的值大于最大节点的核心数,则永远不会调度您的Pod。 假设您有一个需要四个核心的Pod,但您的Kubernetes群集由双核VM组成——您的Pod将永远不会被调度!

除非您的应用程序专门用于利用多个核心(科学计算和某些数据库),否则通常最好将CPU请求保持在1或更低,并运行更多副本以扩展它。 这为系统提供了更大的灵活性和可靠性。

就CPU限制而言,事情其实很有趣。 CPU被认为是可压缩资源。 如果您的应用程序开始达到您的CPU限制,Kubernetes会开始限制您的容器。 这意味着CPU将受到人为限制,使您的应用程序性能可能更差! 但是,它不会被终止或退出。 您可以使用Liveness探针的运行状况检查来确保性能未受影响。

内存

内存资源以字节为单位定义。 通常,你给内存一个mebibyte值(这基本上与兆字节相同),实际上你可以提供从字节到PB的任何单位。

和CPU一样,如果您输入的内存请求大于节点上的内存量,则你的Pod永远不会被调度。

与CPU资源不同,内存无法压缩。 因为没有办法限制内存使用量,如果容器超过其内存限制,它将被终止。 如果您的Pod由DeploymentStatefulSetDaemonSet或其他类型的控制器管理,则控制器会轮转替换。

节点

请务必记住,您无法设置大于节点提供的资源的请求。 例如,如果您拥有一个双核群集,具有2.5核心请求的Pod则永远不会被调度到这里!

Namepsace 命名空间设置

在一个理想的世界里,Kubernetes的容器设置足以照顾好一切,但这个世界是一个黑暗而可怕的地方。 人们很容易忘记设置资源限制,或者流氓团队可以设置非常高的请求和限制,并占用超过他们公平份额的群集。

要防止出现这些情况,可以在命名空间级别设置ResourceQuotasLimitRanges

ResourceQuotas

创建命名空间后,可以使用ResourceQuotas将其锁定。ResourceQuotas非常强大,但我们只看看如何使用它们来限制CPU和内存资源的使用。

资源配额可能如下所示:


看一下这个例子,你可以看到有四个部分。 配置每个部分都是可选的。

requests.cpu是命名空间中所有容器的最大组合CPU请求(以毫秒为单位)。 在上面的示例中,您可以拥有50个具有10m请求的容器,5个具有100m请求的容器,甚至一个具有500m请求的容器。 只要命名空间中请求的总CPU和小于500m

requests.memory是命名空间中所有容器的最大组合内存请求。 在上面的示例中,您可以拥有50个具有2MiB请求的容器,5个具有20MiB请求的容器,甚至是具有100MiB请求的单个容器。 只要命名空间中请求的总内存小于100MiB

limits.cpu是命名空间中所有容器的最大组合CPU限制。 它就像requests.cpu,但是这里指的是限制。

limits.memory是命名空间中所有容器的最大组合内存限制。 它就像requests.memory,但是同样地这里指的是限制。

如果您使用的是生产和开发命名空间(与每个团队或服务的命名空间不同),则常见的模式是在生产命名空间上没有配额,在开发命名空间上则是没有严格的配额。 这使得生产能够在流量激增的情况下获取所需的所有资源。

LimitRange

LimitRange(简称limits)基于namespace的资源管理,包括pod和container的最小、最大和default、defaultrequests等。

您还可以在命名空间中创建LimitRange。 与命名空间作为整体查看的配额不同,LimitRange适用于单个容器。 这有助于防止人们在命名空间内创建超小容器或超大容器。

一旦创建limits,以后创建资源时,K8S将该limits资源限制条件默认/强制给pod,创建后发现不符合规则,将暂停创建pod。

在创建资源时,用户可以为pod自定义资源管理限制,在创建时会去检查和匹配limits值,发现不匹配将在创建时报错。创建后,该pod的资源使用遵守自定义规则,而不会遵守namespace的limits限制。


LimitRange可能如下所示:

 


看一下这个例子,你可以看到有四个部分。 同样,设置每个部分都是可选的。

default section设置容器中容器的默认限制。 如果在limitRange中设置这些值,则任何未明确设置这些值的容器都将被分配默认值。

defaultRequest section设置Pod中容器的默认请求。 如果在limitRange中设置这些值,则任何未明确设置这些值的容器都将被分配默认值。

max section将设置Pod中容器可以设置的最大限制。 默认部分不能高于此值。 同样,在容器上设置的限制不能高于此值。 请务必注意,如果设置了此值且默认部分未设置,则任何未自行显式设置这些值的容器都将被指定为最大值作为限制。

min section设置Pod中容器可以设置的最小请求。 defaultRequest部分不能低于此值。 同样,在容器上设置的请求也不能低于此值。 请务必注意,如果设置了此值且defaultRequest部分未设置,则min值也将成为defaultRequest值。


 

  kubectl delete -f lykops-limitrangerange.yaml
    cat << EOF > lykops-limitrangerange.yaml
    apiVersion: v1
    kind: LimitRange
    metadata:
      namespace: default
      name: lykops-limitrange
      labels:
        project: lykops
        app: limitrange
        version: v1
    spec:
      limits:
      - max:
          cpu: 1
          memory: 1Gi
        min:
          cpu: 0.05
          memory: 64Mi
        type: Pod
        #注意pod只能这么多参数
      - default:
          cpu: 0.2
          memory: 200Mi
        defaultRequest:
          cpu: 0.01
          memory: 16Mi
        max:
          cpu: 0.25
          memory: 256Mi
        min:
          cpu: 0.005
          memory: 8Mi
        #container只能这么多参数
        type: Container
    EOF
    kubectl create -f lykops-limitrangerange.yaml

 
每容器(type: container)

    min:资源紧张时,最低保证可以使用的资源是: CPU 0.005个核,内存8M
    max:资源空闲时,最大可以使用的资源是:CPU 0.25个核,内存256M
    default:默认时,限制使用的资源是:CPU 0.2个核,内存200M
    defaultRequest:默认时,最低保证可以使用的资源是: CPU 0.01个核,内存16M

每pod(type: pod)

    min:最低保证可以使用的资源是: CPU 0.05个核,内存64M
    max最大可以使用的资源是:CPU 1个核,内存1G

使用规则

1、每个namespace应该只有一个limits;

2、limits值设置:

    每容器(type: container)
        max>=default>=defaultRequest>min
    每pod(type: pod)
        max>=min
    整个
        容器的max*容器数<=pod的max
        容器的min*容器数<=pod的min

3、创建资源时,pod自定义资源限制的规则:

    自定义的单个request>=limits的容器的defaultrequets
    自定义的request的总和>=limits的pod的min
    自定义的单个limit<=limits的容器的requets
    自定义的limit的总和<=limits的pod的max

使用心得

为了防止出现创建资源失败的情况,个人建议:

    1、只使用limits的pod或者container中的一种,尽量不使用同时使用,特别在pod中有多容器需求的情况下。
    2、尽量使用max,尽量不同时使用max和min
    3、由于limits会针对该namespace下的所有新建的pods,所以在该namespace下应该运行哪些资源需求相同的业务
    4、在复杂的limits配置下,不要在创建资源时使用自定义配置。

 

参考: http://dockone.io/article/8152

你可能感兴趣的:(大数据/云计算,k8s)