关于devops:K8S实战十八-容器资源分配和资源限制

36次阅读

共计 4372 个字符,预计需要花费 11 分钟才能阅读完成。

前言

为了避免容器调度到资源有余的节点上,能够为容器指定资源起码要求量。

为了避免容器无节制的应用 CPU、内存 等资源,能够为容器指定资源最大容许使用量。

更新历史

  • 20200714 – 初稿 – 左程立
  • 原文地址 – https://blog.zuolinux.com/2020/07/14/container-resources-request-limit.html

资源申请和资源束缚

能够为容器指定资源申请量和资源束缚量。

资源个别指 CPU、内存。

资源申请量,指容器要求节点调配的最小容量,如果该节点可用容量小于容器要求的申请量,容器将被调度到其余适合节点。

资源束缚量,指容器要求节点限度其应用的最大容量,如果容器内存使用量超过内容束缚量,容器将被杀掉,如果指定了重启策略,容器杀掉后将被重启。

波及的参数

 束缚量
spec.containers[].resources.limits.cpu
spec.containers[].resources.limits.memory
spec.containers[].resources.limits.hugepages-<size>

申请量
spec.containers[].resources.requests.cpu
spec.containers[].resources.requests.memory
spec.containers[].resources.requests.hugepages-<size>

示例

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "password"
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: log-aggregator
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

资源单位

K8S 中的一个 cpu 等于云平台上的 1 个 vCPU/ 核或裸机 Intel 处理器上的 1 个超线程

spec.containers[].resources.requests.cpu 为 0.5 的容器必定可能取得申请 1 CPU 的容器的一半 CPU 资源。表达式 0.1 等价于表达式 100m,能够看作“100 millicpu”。具备小数点(如 0.1)的申请由 API 转换为 100m;最大精度是 1m。

优先思考应用 100m 的模式。

内存能够应用 E、P、T、G、M、K。也能够应用对应的 2 的幂数:Ei、Pi、Ti、Gi、Mi、Ki。

Pod 的资源申请和束缚

Pod 的申请量等于外部所有容器的申请量之和。

Pod 的束缚量等于外部所有容器的束缚量之和。

带资源申请的 Pod 如何调度

调度程序确保所调度的 Pod 的资源申请量小于节点的容量。

即,调度程序将查找到资源可用量短缺的,可用量大于申请量的节点来搁置 Pod。

带资源束缚的 Pod 如何运行 

内存资源束缚

如果容器超过其内存最大限度,则可能会被终止。如果容器可重新启动,kubelet 将重新启动容器。

如果一个容器内存使用量超过其内存申请值,那么当节点内存不足时,容器所处的 Pod 可能被逐出。

CPU 资源束缚

每个容器可能被容许也可能不被容许应用超过其 CPU 束缚的解决工夫。然而,容器不会因为 CPU 使用率过高而被杀死。

spec.containers[].resources.limits.cpu 先被转换为 millicore 值,再乘以 100。其后果就是每 100 毫秒内容器能够应用的 CPU 工夫总量。在此期间(100ms),容器所应用的 CPU 工夫不会超过它被调配的工夫。

默认的配额(quota)周期为 100 毫秒。CPU 配额的最小精度为 1 毫秒。

如何获知集群资源应用状况,须要通过 metrics-server 来获取。

metrics-server

查看是否已装置 metrics-server,以下阐明没装置

# kubectl top node
Error from server (NotFound): the server could not find the requested resource (get services http:heapster:)
# kubectl get pods,svc,deployments -n kube-system | grep metrics-server
# 

开始装置 metrics-server

git clone https://github.com/kubernetes-incubator/metrics-server
cd metrics-server/
git checkout release-0.3

批改 metrics-server/deploy/1.8+/metrics-server-deployment.yaml

      containers:
      - name: metrics-server
        #image: k8s.gcr.io/metrics-server/metrics-server:v0.3.6
        image: registry.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.6
        imagePullPolicy: IfNotPresent
        args:
          - --cert-dir=/tmp
          - --secure-port=4443
          - --metric-resolution=30s
          - --kubelet-preferred-address-types=InternalIP,Hostname,InternalDNS,ExternalDNS,ExternalIP
          - --kubelet-insecure-tls

参数阐明

--metric-resolution=30s:从 kubelet 采集数据的周期;--kubelet-preferred-address-types:优先应用 InternalIP 来拜访 kubelet,这样能够防止节点名称没有 DNS 解析记录时,通过节点名称调用节点 kubelet API 失败的状况(未配置时默认的状况);--kubelet-insecure-tls:kubelet 的 10250 端口应用的是 https 协定,连贯须要验证 tls 证书。--kubelet-insecure-tls 不验证客户端证书 

装置

kubectl apply -f deploy/1.8+/

再次查看,须要多等一会儿,确保采集到数据。

[root@master01 ~]# kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes"
{"kind":"NodeMetricsList","apiVersion":"metrics.k8s.io/v1beta1","metadata":{"selfLink":"/apis/metrics.k8s.io/v1beta1/nodes"},"items":[]}

[root@master01 1.8+]# kubectl top nodes
NAME       CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
master01   163m         4%     2093Mi          56%       
master02   147m         3%     1638Mi          44%       
master03   151m         3%     1609Mi          43%       
work01     141m         3%     1084Mi          29%       
work02     150m         3%     1097Mi          29%       
work03     138m         3%     1471Mi          39%   

[root@master01 1.8+]# kubectl top pod
NAME                                      CPU(cores)   MEMORY(bytes)   
mysql-0                                   15m          202Mi           
mysql-1                                   14m          191Mi           
mysql-2                                   13m          182Mi           
nfs-client-provisioner-7db698bbc9-8ph55   2m           8Mi  

曾经能够看到资源应用状况。

实际内存限额

创立一个测试用命名空间

# kubectl create namespace mem-example
namespace/mem-example created

创立一个最大限额 100M,但起码须要 250M 的容器

# cat memory-request-limit-2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: memory-demo-2
  namespace: mem-example
spec:
  containers:
  - name: memory-demo-2-ctr
    image: polinux/stress
    resources:
      requests:
        memory: "50Mi"
      limits:
        memory: "100Mi"
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]
# kubectl apply -f memory-request-limit-2.yaml
pod/memory-demo-2 created

查看发现创立失败

# kubectl get pod -n mem-example
NAME            READY   STATUS             RESTARTS   AGE
memory-demo-2   0/1     CrashLoopBackOff   3          88s

查看起因

# kubectl get pod -n mem-example -o go-template='{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' memory-demo-2
Container Name: memory-demo-2-ctr
LastState: map[terminated:map[containerID:docker://aaf41e exitCode:1 reason:OOMKilled]]

其中有 reason:OOMKilled,阐明超过了内存最大限额,导致了 OOM 而后被杀掉。

结束语

通过 resources.requests 和 resources.limits,能够对资源进行起码容量要求和最大容量限度,确保容器能够运行在资源短缺的节点上,同时也不会因为本身占用了过多资源而影响节点上其余容器。

分割我

微信公众号:zuolinux_com

正文完
 0