k8s_day03_03

k8s_day03_03
容器资源限制

resource 相关 request、limit

​ 一个宿主机的内核之上可能管理了一组硬件,包括cpu、内存、一个宿主机上可能运行了多个容器,这些容器将共享底层的同一个内核,很显然 ,硬件是属于内核的,因此任何一个容器内的进程默认可以请求占有内核管理的所有硬件资源。

​ 尤其是多租户的情况当中,有人恶意的运行了一个容器,容器中的进程会尽可能多的占用CPU内存,进而会导致其他用户也无法运行了,容器间的隔离默认情况下 (或者使用docker默认启动时),在内核的名称空间级别进行了隔离,但是在进程运行时所用到的资源范围没有做太多的隔离操作

​ 因此,我们应该为每个应用设定其内部的运行时做 为资源的最小保证量和最大保证量。为了应用正常运行,系统应该预留一定范围的资源。 整个节点上运行的pod 会越来越多,直到最后,很可能因为其他Pod 所占用资源后,剩余量 虽然确保核心容器启动够了,但是随着后期的运行,需要用到更多内存,而节点无法分配时 就尴尬了。为了避免这种情况 ,就使用request :下阈值, 确保节点至少为Pod 或者容器配备的资源最少量; 当创建pod 时,如果节点无法满足 pod的request 资源请求,就不会调度到该节点,如果被调度到了满足request 的节点时,无论pod 用或不用申请的最小资源限制,pod要求预留的量, 节点必须预留。而且节点就会假设那么多预留的量已经被使用了。

​ limit :限制,上阈值,是用来表示 pod 请求分配资源的上限,最大无边界

​ 节点上重要的三资源: CPU 、Memory、 存储空间【因为用的是存储卷,先不讨论】

cpu:

​ 如何分配? cpu是可以压缩型资源,分配到的cpu不够,顶多是运行 比较慢而已,cpu 是支持抢占的 ,分给你用了,但是还可以拿回来

Memory:

​ 而内存是不可以压缩型, 意味着 应用本来现在是用的2G内存 ,现在给减少1G ,那应用就会崩溃.如果应用现在就占用了1G的内存 ,现在要扩展到2G,如果节点上没有物理内存资源了, 会使用交换内存 ,但是k8默认禁用swap . 这时候系统就会OOM ,就会触发内核中oom killer 把占用系统最多的内存(或者内存频繁分配)进程kill了

Mem ,CPU 的分配单位

Mem :1ki 1Mi i表示换算关系是1024 而不是1000

cpu: 毫核,1核=1000m核 【m表示毫核,100m 表示占用一个cpu十分之一的运行时间】

例子:

[root@master01 chapter4]# cat resource-requests-demo.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: stress-pod
spec:
  containers:
  - name: stress
    image: ikubernetes/stress-ng
    command: ["/usr/bin/stress-ng", "-c 1", "-m 1", "--metrics-brief"]
    resources:
      requests:
        memory: "128Mi"
        cpu: "200m"
      limits:
        memory: "512Mi"
        cpu: "400m"

正常情况下 , resources 可以 定义在pod上, 也可以定义在container上 定义在pod 就会对pod内所有容器生效,一般而言是定义在每一个资源上的,因为不同的容器 需求可能不一样。

验证cpu限制

[root@node01 ~]# kubectl exec  po/stress-pod -- top

Mem: 1848196K used, 2013324K free, 25120K shrd, 2248K buff, 748276K cached
CPU:  19% usr   2% sys   0% nic  78% idle   0% io   0% irq   0% sirq
Load average: 0.47 0.42 0.38 4/427 28
  PID  PPID USER     STAT   VSZ %VSZ CPU %CPU COMMAND
    6     1 root     R     6888   0%   1  10% {stress-ng-cpu} /usr/bin/stress-ng
    8     7 root     R     262m   7%   0  10% {stress-ng-vm} /usr/bin/stress-ng 
    1     0 root     S     6244   0%   0   0% /usr/bin/stress-ng -c 1 -m 1 --met
    7     1 root     S     6244   0%   1   0% {stress-ng-vm} /usr/bin/stress-ng 
    9     0 root     S     1504   0%   0   0% top
   14     0 root     S     1500   0%   0   0% top
   19     0 root     S     1500   0%   0   0% top
   24     0 root     R     1500   0%   0   0% top


物理机的是2个 。200m cpu 代表占用cpu 百分比是200/2000 =10% ,400/2000 =20% 所以最低用10%,最多20%。

​ stress-ng 是一个应用程序, 专门做压力测试的 “-c 1” 表示会运行一个cpu 压力进程 “-m 1” 会运行一个内存压力进程, “-- metrics-brief” 表示 简要输出指标信息。

​ 可能因为程序是压测程序,导致压测内存的程序变成2个就不测了

eg2 : 容器内存泄露示例

[root@master01 chapter4]# cat memleak-demo.yaml 
# Maintainer: MageEdu <mage@magedu.com>
# URL: http://www.magedu.com
# ---
apiVersion: v1
kind: Pod
metadata:
  name: memleak-pod
spec:
  containers:
  - name: simmemleak
    image: ikubernetes/simmemleak
    resources:
      requests:
        memory: "64Mi"
        cpu: "1"
      limits:
        memory: "64Mi"
        cpu: "1"

[root@master01 chapter4]# kubectl apply  -f  memleak-demo.yaml 
pod/memleak-pod created

[root@master01 chapter4]# kubectl  get po/memleak-pod  -w
NAME          READY   STATUS      RESTARTS   AGE
memleak-pod   0/1     OOMKilled   2          30s
memleak-pod   0/1     CrashLoopBackOff   2          41s
memleak-pod   0/1     OOMKilled          3          59s
memleak-pod   0/1     CrashLoopBackOff   3          71s
memleak-pod   0/1     OOMKilled          4          110s
memleak-pod   0/1     CrashLoopBackOff   4          111s
memleak-pod   1/1     Running            5          3m26s
memleak-pod   0/1     OOMKilled          5          3m27s
memleak-pod   0/1     CrashLoopBackOff   5          3m39s
memleak-pod   0/1     OOMKilled          6          6m23s
memleak-pod   0/1     CrashLoopBackOff   6          6m24s
memleak-pod   0/1     OOMKilled          7          11m
memleak-pod   0/1     CrashLoopBackOff   7          11m
 memleak-pod   0/1     OOMKilled          8          16m
memleak-pod   0/1     CrashLoopBackOff   8          16m

memleak-pod   0/1     CrashLoopBackOff   9          26m
memleak-pod   0/1     OOMKilled          10         26m
memleak-pod   0/1     CrashLoopBackOff   10         27m
memleak-pod   0/1     OOMKilled          11         32m
memleak-pod   0/1     CrashLoopBackOff   11         32m

​ 这个memleak-pod 会吃掉所有内存,所以限制多少内存都没有用。因为默认restartpolicy是always , 所以一旦发生oom ,就会oom kill 或者触发 CrashLoopBackOff 。 pod就会被重启,然后陷入内存耗尽、重启循环

​ k8s为了避免这种无谓的反复重启,他有一个退避算法。比如pod因为故障被重启:第一次重启 ,一般是立即重启,第二次可能还是立即,如果第三次也是立即重启还没有解决问题,第4次重启就会延长,比如等1秒重启,第五次就等5秒钟重启 ,第6次就20秒重启,直到到达最大次数结束还没有解决问题。如果重启容器仍然不成功,k8s就会将pod置于CrashLoopBackOff状态。

事实上k8s 对退避算法是这样实现的

​ 第1次,0秒 第2次,10秒 第3次,20秒 第4次,80秒 第5次,160秒 第7次,300秒,第8次之后都是5分钟。只要重启不成功就置于CrashLoopBackOff状态。

​ 因为重启的速度太快,所以频繁出现CrashLoopBackOff和 OOMKilled交叉,具体的状态值取决于容器退出的原因

容器可见资源

​ 即便容器做了资源限制, 但是容器中可见的资源量仍然是节点级别可用总量。这就有问题了,比如通常java程序设置堆内存是默认是按照主机内的内存总量比例 来的,这样就会让java容器很快oom

解决方法就是将 download api 将limits 定义的资源暴露给容器

现象如下

[root@node01 ~]# kubectl exec  po/stress-pod -- free  -m
             total       used       free     shared    buffers     cached
Mem:          3771       1842       1928          0          2        732
-/+ buffers/cache:       1107       2663
Swap:            0          0          0
[root@node01 ~]# 

[root@node01 ~]# kubectl exec  po/stress-pod -- cat /proc/cpuinfo |grep "^processor"
processor	: 0
processor	: 1

容器内可以看见节点总内存和cpu个数 ,而不是limit 限制的数量

Pod 服务质量类别

节点无法承载过多pod,资源不够的情况下,那种次序终止pod 就成问题

QoS Class:服务质量类别,代表了Pod的资源被优先满足的类别

Guaranteed:

​ Pod内的每个容器都分别设定了CPU和Memroy资源需求和资源限制,CPU的需求与限制相等,而且Memory的需求与限制也相等; 【保证】
Bustable:随便设置一个限制条件就行但是不能满足Guaranteed条件【二者之间】
BestEffort:未为任何一个容器设定任何需求或限制; 【尽力满足,就是不想满足呗】

综合应用案例
[root@master01 chapter4]# cat all-in-one.yaml 
# Maintainer: MageEdu <mage@magedu.com>
# URL: http://www.magedu.com
apiVersion: v1
kind: Pod
metadata:
  name: all-in-one
  namespace: default
spec:
  initContainers:
  - name: iptables-init
    image: ikubernetes/admin-box:latest
    imagePullPolicy: IfNotPresent
    command: ['/bin/sh','-c']
    args: ['iptables -t nat -A PREROUTING -p tcp --dport 8080 -j REDIRECT --to-port 80']
    securityContext:
      capabilities:
        add:
        - NET_ADMIN
  containers:
  - name: sidecar-proxy
    image: envoyproxy/envoy-alpine:v1.13.1
    command: ['/bin/sh','-c']
    args: ['sleep 3 && envoy -c /etc/envoy/envoy.yaml']
    lifecycle:
      postStart:
        exec:
          command: ['/bin/sh','-c','wget -O /etc/envoy/envoy.yaml http://ilinux.io/envoy.yaml']
    livenessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 5
    readinessProbe:
      tcpSocket:
        port: 80
      initialDelaySeconds: 5
  - name: demo
    image: ikubernetes/demoapp:v1.0
    imagePullPolicy: IfNotPresent
    env:
    - name: PORT
      value: '8080'
    livenessProbe:
      httpGet:
        path: '/livez'
        port: 8080
      initialDelaySeconds: 5
    readinessProbe:
      httpGet:
        path: '/readyz'
        port: 8080
      initialDelaySeconds: 15
    securityContext:
      runAsUser: 1001
      runAsGroup: 1001
    resources:
      requests:
        cpu: 0.5
        memory: "64Mi"
      limits:
        cpu: 2 
        memory: "1024Mi"
  securityContext:
    supplementalGroups: [1002, 1003]
    fsGroup: 2000
[root@master01 chapter4]# 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值