kubernetes之管理容器的计算资源

资源类型

CPU 和 memory 都是 资源类型。资源类型具有基本单位。CPU 的单位是 core,memory 的单位是 byte。这些都统称为计算资源。

CPU含义:

CPU 资源的限制和请求以cpu为单位。Kubernetes 中的一个 cpu 等于一个core,就是逻辑CPU。1颗逻辑CPU等于1000millicores。500m=0.5颗cpu。

内存含义:

内存的限制和请求以字节为单位。您可以使用以下后缀之一作为平均整数或定点整数表示内存:E,P,T,G,M,K。您还可以使用两个字母的等效的幂数:Ei,Pi,Ti ,Gi,Mi,Ki。

POD中的资源请求和资源限制

  • requests 资源请求 pod最低需求(表示Pod对资源的最小需求,因此在调度的时候会如果Node剩余的资源不能满足Pod的需求,则不会调度到对应的Node上。Scheduler调度的时候并不关注在调度时具体的资源使用情况,而是根据现存Pod的资源请求情况来进行调度。调度器首先将不符合请求的Node排除在外,然后在执行优选策略最后在选定pod)
  • limits 资源限制 pod最大的使用资源

cpu-requests

执行下面yaml的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: v1
kind: Pod
metadata:
name: my-demo
namespace: default
labels:
name: myapp
tier: appfront
spec:
containers:
- name: myapp
image: ikubernetes/stress-ng
command: ["/usr/bin/stress-ng","-c 1","--metrics-brief"]
ports:
- name: http
containerPort: 80
resources:
requests:
memory: "128Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "500m"

查看结果:

1
2
3
4
5
6
7
8
9
10
$ kubectl exec my-demo -- top
Mem: 3914044K used, 126532K free, 205252K shrd, 2176K buff, 2650160K cached
CPU: 21% usr 0% sys 0% nic 78% idle 0% io 0% irq 0% sirq
Load average: 0.12 0.08 0.09 3/694 17
PID PPID USER STAT VSZ %VSZ CPU %CPU COMMAND
5 1 root R 6900 0% 0 25% {stress-ng-cpu} /usr/bin/stress-ng
14 0 root R 1512 0% 1 4% top
1 0 root S 6256 0% 1 0% /usr/bin/stress-ng -c 1 --metrics-
6 0 root S 1516 0% 1 0% top
10 0 root S 1516 0% 1 0% top

我们看到CPU占用是25%,为什么呢?因为我们的node是2个core。我们最大限制是0.5核。所以应该是1/4。

QoS(服务质量等级)

是作用在 Pod 上的一个配置,当 Kubernetes 创建一个 Pod 时,它就会给这个 Pod 分配一个 QoS 等级,可以是以下等级之一:

  • Guaranteed:同时设置了CPU和内存的requests和limits 而且值必须相等。(这类的pod是最高优先级)
  • Burstable:pod至少有一个容器设置了cpu或内存的requests和limits,且不满足 Guarantee 等级的要求。即内存或CPU的值设置的不同。(中等优先级)
  • BestEffort:没有任何一个容器设置了requests或limits的属性。(最低优先级)

Guaranteed样例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: v1
kind: Pod
metadata:
name: my-demo
namespace: default
labels:
name: myapp
tier: appfront
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v2
ports:
- name: http
containerPort: 80
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "512Mi"
cpu: "500m"

结果:

1
2
3
4
$ kubectl describe pod my-demo
......
QoS Class: Guaranteed
......

Burstable样例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: v1
kind: Pod
metadata:
name: my-demo02
namespace: default
labels:
name: myapp
tier: appfront
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v2
ports:
- name: http
containerPort: 80
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "500m"

结果:

1
2
3
4
$ kubectl describe pod my-demo02
....
QoS Class: Burstable
....

BestEffort样例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: Pod
metadata:
name: my-demo03
namespace: default
labels:
name: myapp
tier: appfront
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v2
ports:
- name: http
containerPort: 80

结果:

1
2
3
4
$ kubectl describe pod my-demo03
....
QoS Class: BestEffort
....

容器中的JVM资源限制

在Kubernetes环境中部署Java程序不一会就重启了,这意味着你的pod是不健康的。然后我们可以通过describe去查看一下重启的原因。发现是因为Pod超出了资源限制被kill掉,在日志最后一行会出现一个kill的字段。为什么Kubernetes会kill掉,因为它超出了Kubernetes对Pod的资源限制。默认情况下Docker容器会使用宿主机所有的资源,但如果不做资源限制,会影响整个宿主机。然后整个宿主机资源不够会实现飘移,会转移到其他主机上,然后再异常,可能会起到一种雪崩的效应,所以一般我们都是要做Pod资源限制。如果Java容器中未设置JVM的-Xmx(最大的堆内存使用)参数,一旦这个Pod的使用内存超出Kubernetes的limits限制,Kubernetes就会把它杀掉并重启一个新的Pod。在JVM中这个值建议要比limits要小一点,小个10%吧,因为超过这个limits限制就会杀死掉从新在拉起新的Pod。

  • Host

    1
    2
    3
    4
    cat /proc/meminfo 
    MemTotal: 197869260 kB
    MemFree: 3698100 kB
    MemAvailable: 62230260 kB
  • 容器

    1
    2
    3
    4
    docker run -it --rm alpine cat /proc/meminfo
    MemTotal: 197869260 kB
    MemFree: 3677800 kB
    MemAvailable: 62210088 kB

kubernetes之管理容器的计算资源
https://system51.github.io/2019/08/26/kubernetes-Resource-constraints/
作者
Mr.Ye
发布于
2019年8月26日
许可协议