k8s——Pod进阶(资源限制和探针)

一、资源限制

1.1 资源限制的定义

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

当为Pod中的容器指定了request资源时,调度器就使用该信息来决定将Pod调度到哪个节点上。当还为容器指定了limit资源时,kubelet就会确保运行的容器不会使用超出所设的limit资源量。kubelet还会为容器预留所设的request资源量, 供该容器使用。

如果Pod运行所在的节点具有足够的可用资源,容器可以使用超出所设置的request资源量。不过,容器不可以使用超出所设置的limit资源量。

如果给容器设置了内存的limit值,但未设置内存的request值,Kubernetes会自动为其设置与内存limit相匹配的request值。 类似的,如果给容器设置了CPU的 limit值但未设置CPU的request 值,则Kubernetes自动为其设置CPU的request值并使之与CPU的limit值匹配。

官方示例:https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/

1.2 Pod和容器的资源请求和限制

| spec.containers[].resources.requests.cpu | 定义创建容器时预分配的CPU资源 |
| spec.containers[].resources.requests.memory | 定义创建容器时预分配的内存资源 |
| spec.containers[].resources.limits.cpu | 定义 cpu 的资源上限 |

spec.containers[].resources.limits.memory 定义内存的资源上限

1.3 CPU资源单位

CPU资源的request和limit以cpu为单位。Kubernetes中的一个cpu相当于1个vCPU(1个超线程)。

Kubernetes也支持带小数 CPU 的请求。spec.containers[].resources.requests.cpu为0.5的容器能够获得一个cpu的 、一半CPU资源(类似于Cgroup对CPU资源的时间分片)。表达式0.1等价于表达式100m(毫核),表示每1000毫秒内容器可以使用的CPU时间总量为 0.1*1000 毫秒。

Kubernetes不允许设置精度小于1m的CPU资源。

1.4 内存资源单位

内存的request和limit以字节为单位。可以以整数表示,或者以10为底数的指数的单位(E、P、T、G、M、K)来表示, 或者以2为底数的指数的单位(Ei、Pi、Ti、Gi、Mi、Ki)来表示。

1.5 实验操作

1.5.1 OOM资源不足被干掉

apiVersion: v1
kind: Pod
metadata:
  name: ky-web-db
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: "abc123"
    resources:
      requests:
        memory: "64Mi"
        cpu: "0.25"
      limits:
        memory: "128Mi"
        cpu: "500m"

资源不足第一个进程被杀死,注意如果节点上有资源会拉取节点资源创建,可先把节点关闭

查看日志信息,db因资源不足被干掉

1.5.2 资源充足

apiVersion: v1
kind: Pod
metadata:
  name: ky-web-db
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: "abc123"
    resources:
      requests:
        memory: "64Mi"
        cpu: "0.5"
      limits:
        memory: "1Gi"
        cpu: "1"

给足资源后,状态为running

查看日志信息后,调度给了node01

查看node01详细信息,可以看到资源详细情况

二、探针

2.1 探针的定义

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

2.2 探针的规则

  • 存活探针(livenessProbe):判断容器是否运行正常,如果探测失败则杀死容器(不是pod),容器根据容器策略决定是否重启
  • 就绪探针(readinessProbe):判断pod是否能进入ready状态,做好接受请求的准备。如果探针失败会进入not ready状态且从service自愿的endpoints中剔除,service将不会再把访问请求转发给pod
  • 启动探针(startupProbe):判断容器内的应用是否启动成功,在检测成功状态为success真会玩,其他的探针都会处于失效状态

2.3 Probe三种检查方式

  • exec:通过command设置,执行在容器内执行的linux命令来进行探测,如果返回码为0,则为探测成功,非0就为探测失败
  • httpget:通过http get请求访问制定容器端口和url路径,如果访问状态吗为>=200且<=400(2xx 300),则认为探测成功
  • tcpsocket:通过制定的端口发送TCP连接,如果端口无误且三次握手成功(TCP连接成功),则认为探测成功

2.4 探测的结果

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

2.5 实验部署

2.5.1 exec方式------liveness

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: busybox
    imagePullPolicy: IfNotPresent
    args:             ###启动容器参数
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60
    livenessProbe:     #定义了容器的就绪探针
      exec:            #在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功。
        command:       #指定了执行的命令
        - cat
        - /tmp/healthy
      failureThreshold: 1            #就绪探针在连续失败一次后被视为失败
      initialDelaySeconds: 5         #延迟5秒启动容器
      periodSeconds: 5               #每隔5秒探测一次
  • touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 60

创建一个名为 /tmp/healthy 的文件,暂停执行脚本,等待 30 秒钟,删除后,再次暂停执行脚本,等待额外的 60 秒钟

initialDelaySeconds:指定kubelet在执行第一次探测前应该等待5秒,即第一次探测是在容器启动后的第6秒才开始执行。默认是0秒,最小值是0。

periodSeconds:指定了kubelet应该每5秒执行一次存活探测。默认是10秒。最小值是1。

failureThreshold: 当探测失败时,Kubernetes将在放弃之前重试的次数。 存活探测情况下的放弃就意味着重新启动容器。就绪探测情况下的放弃Pod会被打上未就绪的标签。默认值是 3。最小值是1。

timeoutSeconds:探测的超时后等待多少秒。默认值是1秒。最小值是1。(在Kubernetes 1.20版本之前,exec探针会忽略timeoutSeconds探针会无限期地持续运行,甚至可能超过所配置的限期,直到返回结果为止。)

总结:可以看到Pod中只有一个容器。kubelet在执行第一次探测前需要等待5秒,kubelet会每5秒执行一次存活探测。kubelet 在容器内执行命令cat /tmp/healthy来进行探测。如果命令执行成功并且返回值为0,kubelet 就会认为这个容器是健康存活的。 当到达第31秒时,这个命令返回非0值,kubelet会杀死这个容器并重新启动它。

探针失败

/tmp/healthy文件不存在,探测失败

2.5.2 httpGet方式

apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget
  namespace: default
spec:
  containers:
  - name: liveness-httpget-container
    image: soscscs/myapp:v1           #soscscs:nginx1.12
    imagePullPolicy: IfNotPresent      #拉取策略
    ports:
    - name: http
      containerPort: 80
    livenessProbe:              #探针
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1     #延迟1秒开始探测
      periodSeconds: 3          #每3秒探测一次
      timeoutSeconds: 10         #超时时间10秒

删除index.html页面,报错404,探针失败

httpget:通过http get请求访问制定容器端口和url路径,如果访问状态吗为>=200且<=400(2xx 300),则认为探测成功

当我们删除页面后会404报错,然后就会探测失败,最后会重启

2.5.3 tcpSocket方式

apiVersion: v1
kind: Pod
metadata:
  name: xzq-tcp-live
spec:
  containers:
  - name: nginx
    image: soscscs/myapp:v1
    livenessProbe:
      initialDelaySeconds: 5  #第一次探测延迟5秒,第6秒开始
      timeoutSeconds: 1
      tcpSocket:
        port: 8080
      periodSeconds: 10     #每10秒探测一次
      failureThreshold: 2   #允许2次失败

2.5.4 就绪检测------readiness

apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget
  namespace: default
spec:
  containers:
  - name: readiness-httpget-container
    image: soscscs/myapp:v1
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    readinessProbe:
      httpGet:
        port: 80
        path: /index1.html
      initialDelaySeconds: 1
      periodSeconds: 3
    livenessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10

有实例在运行,但是就绪失败

探针http,404报错

bash可能是权限不足,用sh进入写一个页面

kubectl describe pod readiness-httpget

2.5.5 就绪检测2------readiness

apiVersion: v1
kind: Pod
metadata:
  name: myapp1
  labels:
     app: myapp
spec:
  containers:
  - name: myapp
    image: soscscs/myapp:v1
    ports:
    - name: http
      containerPort: 80
    readinessProbe:
      httpGet:
        port: 80
        path: /index.html
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 10 
---
apiVersion: v1
kind: Pod
metadata:
  name: myapp2
  labels:
     app: myapp
spec:
  containers:
  - name: myapp
    image: soscscs/myapp:v1
    ports:
    - name: http
      containerPort: 80
    readinessProbe:
      httpGet:
        port: 80
        path: /index.html
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 10 
---
apiVersion: v1
kind: Pod
metadata:
  name: myapp3
  labels:
     app: myapp
spec:
  containers:
  - name: myapp
    image: soscscs/myapp:v1
    ports:
    - name: http
      containerPort: 80
    readinessProbe:
      httpGet:
        port: 80
        path: /index.html
      initialDelaySeconds: 5
      periodSeconds: 5
      timeoutSeconds: 10 
---
apiVersion: v1
kind: Service
metadata:
  name: myapp
spec:
  selector:
    app: myapp
  type: ClusterIP
  ports:
  - name: http
    port: 80
    targetPort: 80

查看集群中服务、pod和端点的信息

删除页面看效果,readiness探测失败,Pod无法进入READY状态,且端点控制器将从 endpoints中剔除删除该Pod的IP地址

2.5.6 启动、退出动作

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: soscscs/myapp:v1
    lifecycle:   #此为关键字段,定义容器的生命周期
      postStart:   #容器启动后立即执行的操作
        exec:          #允许容器启动后执行特定的命令
          command: ["/bin/sh", "-c", "echo Hello from the postStart handler >> /var/log/nginx/message"]      
      preStop:    #容器停止后立即执行的命令
        exec:
          command: ["/bin/sh", "-c", "echo Hello from the poststop handler >> /var/log/nginx/message"]
    volumeMounts:       #将存储卷挂载到容器指定路径上
    - name: message-log      #存储卷名字
      mountPath: /var/log/nginx/
      readOnly: false       #可以读和写
  initContainers:
  - name: init-myservice
    image: soscscs/myapp:v1
    command: ["/bin/sh", "-c", "echo 'Hello initContainers'   >> /var/log/nginx/message"]
    volumeMounts:
    - name: message-log
      mountPath: /var/log/nginx/
      readOnly: false
  volumes:
  - name: message-log
    hostPath:   #hostPath类型,将存储卷挂载到主机上
      path: /data/volumes/nginx/log/      #主机路径
      type: DirectoryOrCreate      #类型为目录,如无目录,会自动创建

创建后去node01查看日志

进入到日志路径下,日志瞎看到先初始化后才探针

在node01下删除pod

关闭探针=关闭生命周期

cat message
相关推荐
木向3 分钟前
leetcode22:括号问题
开发语言·c++·leetcode
comli_cn4 分钟前
使用清华源安装python包
开发语言·python
筑基.11 分钟前
basic_ios及其衍生库(附 GCC libstdc++源代码)
开发语言·c++
m0_7482451724 分钟前
Web第一次作业
java
小码的头发丝、24 分钟前
Java进阶学习笔记|面向对象
java·笔记·学习
雨颜纸伞(hzs)25 分钟前
C语言介绍
c语言·开发语言·软件工程
J总裁的小芒果27 分钟前
THREE.js 入门(六) 纹理、uv坐标
开发语言·javascript·uv
m0_5485147728 分钟前
前端Pako.js 压缩解压库 与 Java 的 zlib 压缩与解压 的互通实现
java·前端·javascript
坊钰1 小时前
【Java 数据结构】移除链表元素
java·开发语言·数据结构·学习·链表