[云原生k8s] k8s资源限制以及探针检查

目录

一、资源限制

1.1、资源限制的使用

1.2、request资源(请求)和limit资源(约束)

1.3、Pod和容器的资源请求和限制

1.4、官方文档示例

1.5、资源限制实操

编写yaml资源配置清单

释放内存(node节点,以node01为例)

创建资源

跟踪查看pod状态

查看容器日志

删除pod

修改yaml配置资源清单,提高mysql资源限制

二、健康检查

2.1、健康检查的定义

2.2、探针的三种规则

livenessProbe存活探针

readinessProbe就绪探针

startupProbe启动探针(1.17版本新增)

同时定义

2.3、Probe支持的三种检测方法

exec

tcpSocket

2.4、探测结果

2.5、exec方式

2.6、httpGet方式

2.7、tcpSocket方式

总结

1. 探针

2. 检查方式

3. 常用的探针可选参数

4、重启策略


一、资源限制

1.1、资源限制的使用

当定义Pod时可以选择性地为每个容器设定所需要的资源数量。最常见的可设定资源是CPU和内存大小,以及其他类型的资源。

1.2、request资源(请求)和limit资源(约束)

  1. 当为Pod中的指定了request资源时,调度器就使用该信息来决定将Pod调度到哪个节点上。当还为容器指定了limit资源时,kubelet就会确保运行的容器不会使用超过所设的limit资源量。kubelet还会为容器预留所设的request资源量,供该容器使用
  2. 如果Pod所在的节点具有足够的可用资源,容器可用使用超过所设置的request资源量。不过,容器不可以使用超过所设置的limit资源量。
  3. 如果给容器设置了内存的limit值,但未设置内存的request值,Kubernetes会自动为其设置于内存limit相匹配的request值。类似的,如果给容器设置了CPU的limit值但未设置CPU的request值,则Kubernetes自动为其设置CPU的request值,并使之与CPU的limit值匹配。

1.3、Pod和容器的资源请求和限制

定义创建容器时预分配的CPU资源
spec.containers[].resources.requests.cpu
定义创建容器时预分配的内存资源
spec.containers[].resources.requests.memory
定义创建容器时预分配的巨页资源
spec.containers[].resources.requests.hugepages-<size>
定义cpu的资源上限
spec.containers[].resources.limits.cpu
定义内存的资源上限
spec.containers[].resources.limits.memory
定义巨页的资源上限
spec.containers[].resources.limits.hugepages-<size>

1.4、官方文档示例

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"

此例子中Pod有两个Container。每个Container的请求为0.25cpu和64MiB(226字节)内存,每个容器的资源约束为0.5cpu和128MiB内存。你可以认为该Pod的资源请求为0.5cpu和128MiB内存,资源限制为1cpu和256MiB内存

1.5、资源限制实操

编写yaml资源配置清单

[root@master ~]# mkdir /opt/test
[root@master ~]# cd !$
cd /opt/test
[root@master test]# vim test1.yaml
 
apiVersion: v1
kind: Pod
metadata:
  name: test1
spec:
  containers:
  - name: web
    image: nginx
    env:
    - name: WEB_ROOT_PASSWORD
      value: "password"
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: db
    image: mysql
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "password"
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

释放内存(node节点,以node01为例)

由于mysql对于内存的使用要求比较高,因此需要检查内存的可以的空间是否能够满足mysql的正常运行,若剩余内存不够,可对其进行释放操作。

查看内存

free -mh

内存总量为4G,实际使用1.1G,因此可用内存应该为2.6G左右。

但是由于有2G的内存被用于缓存,导致了free仅为600M。

600M剩余可用内存显然是不够用的美因茨需要释放缓存。

手动释放缓存

echo [1\2\3] > /proc/sys/vm/drop_caches
[root@master .pokemonsay]# free -mh
              total        used        free      shared  buff/cache   available
Mem:           3.7G        1.1G        600M         18M        2.0G        2.2G
Swap:            0B          0B          0B
[root@master .pokemonsay]# cat /proc/sys/vm/drop_caches
0
[root@master .pokemonsay]# echo 3 > /proc/sys/vm/drop_caches
[root@master .pokemonsay]# free -mh
              total        used        free      shared  buff/cache   available
Mem:           3.7G        1.0G        2.1G         18M        549M        2.3G
Swap:            0B          0B          0B
[root@master .pokemonsay]#

0:0是系统默认值,默认情况下表示不释放内存,由操作系统自动管理
1:释放页缓存
2:释放dentries和inodes
3:释放所有缓存

注意:

如果因为是应用有像内存泄漏、溢出的问题,从swap的使用情况是可用比较快速判断的,但free上面的情况反而会比较难查看。相反,如果在这个时候,我们告诉用户,修改系统的一个值,“可以”释放内存,free就大了。用户会怎么想?不会觉得操作系统“有问题”吗?所以说,既然核心是可以快速清空buffer或cache,也不难做到(这从上面的操作中可以明显看到),但是核心并没有这么做(默认值是0),我们就不应该随便去改变它。

一般情况下,应用在系统上稳定运行了,free值也会保持在一个稳定值,虽然看上去可能比较小。当发生内存不足、应用获取不到可用内存、OOM错误等问题时,还是更应该去分析应用方面的原因,如果用户量太大导致内存不足,发生应用内存溢出等情况,否则,清空buffer,强制腾出free的大小,可能只是把问题给暂时屏蔽了。

创建资源

kubectl apply -f test1.yaml

跟踪查看pod状态

kubectl get pod -o wide -w

OOM(OverOfMemory)表示服务的运行超过了我们所设定的约束值。
Ready:2/2,status:Running说明该pod已成功创建并运行,但运行过程中发生OOM问题被kubelet杀死并重新拉起新的pod。

查看容器日志

kubectl logs test1 -c web

 nginx启动正常,接下来查看mysql日志

kubectl logs test1 -c mysql

锁定问题容器为mysql

删除pod

kubectl delete -f test1.yaml

修改yaml配置资源清单,提高mysql资源限制

[root@master test]# vim test1.yaml  
 
apiVersion: v1
kind: Pod
metadata:  
  name: test1
spec:  
  containers:  
  - name: web    
    image: nginx    
    env:    
    - name: WEB_ROOT_PASSWORD      
      value: "password"    
    resources:      
    requests:         
      memory: "64Mi"        
      cpu: "250m"      
    limits:        
      memory: "128Mi"        
      cpu: "500m"  
  - name: db    
    image: mysql    
    env:    
    - name: MYSQL_ROOT_PASSWORD      
      value: "password"    
    resources:      
    requests:        
      memory: "512Mi"        
      cpu: "0.5"      
    limits:        
      memory: "1024Mi"        
      cpu: "1"

再按照上述方法查看一下

kubectl get pod -o wide -w

kubectl describe pod test1
#查看pod的详细信息

kubectl describe node node01
#查看node1节点详细信息

 可以根据所看到的node节点信息,去分析。

二、健康检查

2.1、健康检查的定义

 健康检查又称为探针(Probe),是由kubelet对容器执行的定期诊断。

2.2、探针的三种规则

livenessProbe存活探针

判断容器是否正在运行。如果探测失败,则kubelet会杀死容器,并且容器将根据restartPolicy来设置Pod状态,如果容器不提供存活探针,则默认状态为Success。

readinessProbe就绪探针

判断容器是否准备好接受请求。如果探测失败,端点控制器将从与Pod匹配的所有service endpoints中剔除该Pod的IP地址。初始延迟之前的就绪状态默认为Failure。如果容器不提供就绪探针,则默认状态为Success。

startupProbe启动探针(1.17版本新增)

判断容器内的应用程序是否已启动,主要针对于不能确定具体启动时间的应用。如果匹配了startupProbe探针,则在startupProbe状态为Success之前,其他所有探针都处于无效状态,直到它成功后才起作用。如果startupProbe,则默认状态为Success。

同时定义

以上三种规则可同时定义。在readinessProbe检测成功之前,Pod的running状态是不会变成ready状态的。

2.3、Probe支持的三种检测方法

exec

在容器内执行命令,如果容器退出时反码为0则认为诊断成功。

tcpSocket

对指定端口上的容器的IP地址执行httpGet请求。如果响应的状态码大于等于200且小于400(2xx和3xx),则诊断被认为是成功的。

2.4、探测结果

每次探测都将获得以下三种结果之一:

  • 成功:容器通过了诊断
  • 失败:容器未通过诊断
  • 未知:诊断失败,因此不会采取任何行动

2.5、exec方式

vim exec.yaml
 
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness				#为了健康检查定义的标签
  name: liveness-exec
spec:						#定义了Pod中containers的属性
  containers:
  - name: liveness
    image: busybox
    args:						#传入的命令
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy;sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5			#表示pod中容器启动成功后,多少秒后进行健康检查 
      periodSeconds: 5				#在首次健康检查后,下一次健康检查的间隔时间 5s

在配置文件中,可以看到Pod具有单个Container。该perioSeconds字段指定kubelet应该每5秒执行一次活动性探测。该initiaDelaySeconds字段告诉kubelet在执行第一个探测之前应该等待5秒。为了执行探测,kubelet cat /tmp/healthy在容器中执行命令。如果命令成功执行,则返回0,并且kubelet认为Container仍然重要。如果命令返回非0值,则kubelet将杀死Container并重启它。

  1. 在这个配置文件中,可以看到Pod只有一个容器。
  2. 容器中的command字段表示创建一个/tmp/live文件后休眠30秒,休眠结束后删除该文件,并休眠10分钟。
  3. 仅使用livenessProbe存活探针,并使用exec检查方式,对/tmp/live文件进行存活检测。
  4. initialDelaySeconds字段表示kubelet在执行第一次探测前应该等待5秒。
  5. periodSeconds字段表示kubelet每隔5秒执行一次存活探测。

2.6、httpGet方式

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/liveness
    args:
    - /server
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
        - name: Custom-Header
          value: Awesome
      initialDelaySeconds: 3
      periodSeconds: 3

在配置文件中,可以看到Pod具有单个Container。该periodSeconds字段指定kubectl应该每3秒执行一次活动性探测。该initiaDelaySeconds字段告诉kubelet在执行第一个探测之前应等待3秒。为了执行探测,kubectl将HTTP GET请求发送到Container中运行并在端口8080上侦听的服务器。如果服务器/healthz路径的处理程序返回成功代码,则kubectl会认为任何大于或等于400的代码均表示成功,其他代码都表示失败。

2.7、tcpSocket方式

定义TCP活动度探针

第三种类型的活动性探针使用TCP套接字,使用此配置,kubelet将尝试在指定端口上打开容器的套接字。如果可以建立连接,则认为该让其运行状况良好,如果不能,则认为该容器是故障容器。

apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
  - name: goproxy
    image: k8s.gcr.io/goproxy:0.1
    ports:
    - containerPort: 8080
    readinessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20

如图所示,TCP检查的配置与HTTP检查非常相似,此示例同时使用就绪和活跃度探针,容器启动5秒后,kubelet将发送第一个就绪探测器。这些尝试连接到goproxy端口8080上的容器。如果探测成功,则容器将标记为就绪,kubelet将继续每10秒运行一次检查。

除了就绪探针之外,此配置还包括活动探针。容器启动后15秒钟,kubelet将运行第一个活动谈着,就像就绪探针一样,这些尝试goproxy在端口8080上连接到容器。如果活动探针失败,则容器将重新启动。

总结

1. 探针

探针分为3种

livenessProbe(存活探针)∶判断容器是否正常运行,如果失败则杀掉容器(不是pod),再根据重启策略是否重启容器
readinessProbe(就绪探针)∶判断容器是否能够进入ready状态,探针失败则进入noready状态,并从service的endpoints中剔除此容器
startupProbe∶判断容器内的应用是否启动成功,在success状态前,其它探针都处于无效状态

2. 检查方式

检查方式分为3种

exec∶使用 command 字段设置命令,在容器中执行此命令,如果命令返回状态码为0,则认为探测成功
httpget∶通过访问指定端口和url路径执行http get访问。如果返回的http状态码为大于等于200且小于400则认为成功
tcpsocket∶通过tcp连接pod(IP)和指定端口,如果端口无误且tcp连接成功,则认为探测成功

3. 常用的探针可选参数

常用的探针可选参数有4个

initialDelaySeconds∶ 容器启动多少秒后开始执行探测
periodSeconds∶探测的周期频率,每多少秒执行一次探测
failureThreshold∶探测失败后,允许再试几次
timeoutSeconds ∶ 探测等待超时的时间 

4、重启策略

Pod在遇到故障之后“重启”的动作Pod在遇到故障之后“重启”的动作

Always:当容器终止退出后,总是“重启”容器,默认策略

OnFailure:当容器异常退出(退出状态码非0)时,重启容器

Never:当容器终止退出,从不“重启”容器。

(注意:k8s中不支持重启Pod资源,只有删除重建,重建)

猜你喜欢

转载自blog.csdn.net/qq_57377057/article/details/127729859