【云原生】Kubernetes-----POD资源限制与探针机制

目录

引言

一、资源限制

(一)基本定义

(二)资源单位

1.CPU资源

2.内存资源

(三)请求与限制

(四)定义方式

1.编写yaml文件

2.查看资源情况

(五)资源不足

二、Pod探针机制

(一)检测方式

(二)存活探针

1.定义

2.使用方法

2.1 使用exec方式

2.2 使用httpGet方式

2.3 使用tcpSocket方式

(三)就绪探针

1.定义

2.探针使用

3.service探测

(四)启动探针

1.定义

2.探针应用

3.主要作用

(五)生命周期钩子

1.钩子种类

1.1 启动钩子(postStart)

1.2 停止钩子(preStop)

2.定义文件

3.启动pod

4.查看文件

5.重要性及应用场景

三、总结

(一)资源限制

(二)探针机制

(三)生命钩子

(四)pod的状态

(五)Container生命周期


引言

在Kubernetes集群中,Pod是最小的部署单元,负责运行应用程序的容器。为了确保Pod的稳定运行和集群资源的高效利用,Kubernetes提供了Pod资源限制和探针机制。本文将详细介绍这两种机制及其在实际应用中的重要性。

一、资源限制

(一)基本定义

Pod资源限制是Kubernetes中一项重要的资源管理功能,用于限制Pod中的容器可以使用的CPU、内存等资源。这有助于防止因某个Pod消耗过多资源而导致整个集群性能下降或崩溃

官方网址:Resource Management for Pods and Containers | Kubernetes

(二)资源单位

CPU 和 内存 都是 资源类型。每种资源类型具有其基本单位

1.CPU资源

在Kubernetes中,CPU资源以核心数为单位,也支持带小数 。CPU 的请求可以表示为整数或小数(如0.5表示半个核心)

0.5=500m(毫核)表示每 1000 毫秒内容器可以使用的 CPU 时间总量为 0.5*1000 毫秒

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

2.内存资源

内存资源以字节为单位,但通常使用更易读的单位(如Mi、Gi)来表示。

此外,Kubernetes还支持对临时存储资源进行限制。

(三)请求与限制

在定义Pod时,可以为每个容器指定资源请求(requests)和限制(limits)。请求表示容器正常运行所需的最小资源量,而限制则表示容器可以使用的最大资源量。Kubernetes调度器会根据Pod的资源请求来选择合适的节点进行调度,以确保节点具有足够的资源来满足Pod的需求。同时,kubelet会监控Pod中容器的资源使用情况,并在容器使用资源超过限制时采取相应的措施(如终止容器)

针对每个容器,你都可以指定其资源限制和请求,包括如下选项:

  • 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>

(四)定义方式

1.编写yaml文件

[root@master01 data]#vim resources.yaml
[root@master01 data]#cat resources.yaml
apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
  - name: nginxweb                #容器的名称是nginxweb
    image: nginx:1.18.0           #容器使用的Docker镜像是nginx的1.18.0版本
    resources:                    #定义容器的资源请求和限制
      requests:                   #定义容器的资源请求
        memory: "64Mi"            #容器启动时请求的内存量为64MiB
        cpu: "250m"               #容器启动时请求的CPU为250m(即0.25个CPU核心)
      limits:                     #定义容器的资源限制
        memory: "128Mi"           #容器可以使用的最大内存量为128MiB
        cpu: "500m"               #容器可以使用的最大CPU为500m(即0.5个CPU核心)
  - name: mysql                   #容器的名称是mysql
    image: mysql:5.7              #容器使用的Docker镜像是mysql的5.7版本
    env:                          #定义容器的环境变量
    - name: MYSQL_ROOT_PASSWORD   #环境变量的名称,固定名称,不能自定义
      value: "abc123"             #环境变量的值是abc123,MySQL root用户的密码
    resources:                    #定义容器的资源请求和限制
      requests:                   #定义容器的资源请求
        memory: "128Mi"           #容器启动时请求的内存量为64MiB
        cpu: "0.5"                #容器启动时请求的CPU为0.5个CPU核心
      limits:                     #定义容器的资源限制
        memory: "512Mi"           #容器可以使用的最大内存量为512MiB
        cpu: "1"                  #容器可以使用的最大CPU为1个CPU核心

2.查看资源情况

[root@master01 data]#kubectl apply -f resources.yaml 
pod/app created
[root@master01 data]#kubectl get pods -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
app    2/2     Running   0          4s    10.244.1.125   node01   <none>           <none>
[root@master01 data]#kubectl describe nodes node01 |sed -n '/Non-terminated Pods/,/$$/p'
Non-terminated Pods:          (3 in total)
  Namespace                   Name                     CPU Requests  CPU Limits   Memory Requests  Memory Limits  AGE
  ---------                   ----                     ------------  ----------   ---------------  -------------  ---
  default                     app                      750m (18%)    1500m (37%)  192Mi (11%)      640Mi (37%)    78s
  kube-flannel                kube-flannel-ds-qvmn9    100m (2%)     0 (0%)       50Mi (2%)        0 (0%)         9d
  kube-system                 kube-proxy-zmh82         0 (0%)        0 (0%)       0 (0%)           0 (0%)         9d
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests     Limits
  --------           --------     ------
  cpu                850m (21%)   1500m (37%)
  memory             242Mi (14%)  640Mi (37%)
  ephemeral-storage  0 (0%)       0 (0%)
  hugepages-1Gi      0 (0%)       0 (0%)
  hugepages-2Mi      0 (0%)       0 (0%)
Events:              <none>

----------------------------------------------------------------------------
#Non-terminated Pods:未终止或正在运行的pod详细信息
#CPU Requests:Pod请求的CPU资源量。这个值是一个相对值,表示Pod期望获得的CPU资源的百分比或毫核数
#CPU Limits: Pod可以使用的最大CPU资源量。如果CPU使用量超过这个限制,会被Kubernetes系统杀死
#Memory Requests: Pod请求的内存资源量。这个值是一个绝对值,表示Pod需要的内存量
#Memory Limits: Pod可以使用的最大内存资源量。如果Pod的内存使用量超过这个限制,也会被系统杀死

#Allocated resources:这部分显示了节点上所有 Pods 的资源请求和限制的总和
#Resource:资源类型
#Requests: 显示了所有Pods请求的资源的总和
#Limits: 显示了所有Pods限制的资源的总和

(五)资源不足

当内存资源不足是,pod容器会处于OOMKilled状态,这通常表明容器配置的内存限制过低或应用程序内存泄露

如果Pod中的容器使用超出其分配的内存限制,它可能会被系统的Out-Of-Memory (OOM) killer终止。

[root@master01 data]#vim  limit.yaml 
[root@master01 data]#cat  limit.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: limit
spec:
  containers:
  - name: web-nginx
    image: nginx:1.18
    env:
    - name: WEB_ROOT_PASSWORD
      value: "password"
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: mysqld
    image: mysql:5.7
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "abc123"
    resources:
      requests:
        memory: "16Mi"     #降低内存,模拟因内存资源不足,导致容器无法启动
        cpu: "0.25"
      limits:
        memory: "64Mi"
        cpu: "500m"

执行文件后可能会先启动程序,而后会因为资源不足退出容器,并显示状态为OOMKilled

[root@master01 data]#kubectl apply -f limit.yaml 
pod/limit created
[root@master01 data]#kubectl get pod limit -w
NAME    READY   STATUS              RESTARTS   AGE
limit   0/2     ContainerCreating   0          2s
limit   2/2     Running             0          3s
limit   1/2     OOMKilled           0          42s
limit   2/2     Running             1          43s
limit   1/2     OOMKilled           1          81s
......

此时需要去删除该pod并调整yaml文件中的资源限制,或者优化内存,重新生成新的pod实例

二、Pod探针机制

Pod探针是Kubernetes中用于监控Pod内部容器状态的机制。通过探针,可以检测容器是否正在运行、是否准备好接收请求以及是否成功启动等状态。探针类型包括存活探针(livenessProbe)、就绪探针(readinessProbe)和启动探针(startupProbe)。

(一)检测方式

探针有三种检测方式

exec :在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功。

tcpSocket :对指定端口上的容器的IP地址进行TCP检查(三次握手)。如果端口打开,则诊断被认为是成功的。

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

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

成功:容器通过了诊断。

失败:容器未通过诊断。

未知:诊断失败,因此不会采取任何行动

(二)存活探针

1.定义

livenessProbe:存活探针

存活探针用于检测容器是否正在运行。如果探测失败,kubelet将杀死容器并根据重启策略进行重启。这有助于及时发现并修复容器中的故障,确保应用程序的可用性。

2.使用方法

2.1 使用exec方式

在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功

[root@master01 data]#vim liveness-exec.yaml 
[root@master01 data]#cat liveness-exec.yaml 
apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-ex
spec:
  containers:
  - name: nginx-ln
    image: nginx:1.18.0
    livenessProbe:             #定义存活探针
      exec:                    #执行exec探针命令
        command: ["test","-e","/usr/share/nginx/html/index.php"]
#检查/usr/share/nginx/html/index.html文件是否存在。如果存在,探针会成功;如果不存在,探针会失败
#当探针失败后,会根据重启策略,决定是否重启,不指定策略默认会一直重启
      failureThreshold: 2      
      initialDelaySeconds: 5
      periodSeconds: 5        

-------------------------------------------------------------------------------------
'failureThreshold'
#当探测失败时,Kubernetes将在放弃之前重试的次数。设置为2,表示可以重复2次,加上第一次默认执行一共为3次
#在存活探针中,放弃就意味着重新启动容器。
#在就绪探针中,放弃后Pod会被打上未就绪的标签。默认值是3。最小值是1

'initialDelaySeconds'
#在容器启动后等待多长时间(以秒为单位)才开始执行探针。这允许容器有时间启动并准备好接受请求。

'periodSeconds'
#指定了kubelet应该多长时间执行一次存活探测(以秒为单位)

追踪查看容器状态

[root@master01 data]#kubectl apply -f liveness-exec.yaml
pod/liveness created
[root@master01 data]#kubectl get pod -w
NAME          READY   STATUS              RESTARTS   AGE
liveness-ex   0/1     ContainerCreating   0          1s
liveness-ex   1/1     Running             0          2s
liveness-ex   0/1     Completed           0          17s

查看容器的事件信息

[root@master01 data]#kubectl describe pod liveness-ex |sed -n "/Events/,/$$/p"
Events:
  Type     Reason     Age    From               Message
  ----     ------     ----   ----               -------
  Normal   Scheduled  2m24s  default-scheduler  Successfully assigned default/liveness-ex to node02
  Normal   Pulled     2m24s  kubelet            Container image "nginx:1.18.0" already present on machine
  Normal   Created    2m23s  kubelet            Created container nginx-ln
  Normal   Started    2m23s  kubelet            Started container nginx-ln
  Warning  Unhealthy  2m17s  kubelet            Liveness probe failed:
  Normal   Killing    2m17s  kubelet            Stopping container nginx-ln
#探针失败,关闭容器
2.2 使用httpGet方式
[root@master01 data]#vim liveness-httpget.yaml
[root@master01 data]#cat liveness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget
  namespace: default
spec:
  containers:
  - name: liveness-httpget
    image: nginx:1.18.0
    imagePullPolicy: IfNotPresent    #定义镜像拉取策略
    ports:
    - name: http                     #定义端口名称,下面探测时使用
      containerPort: 80              #定义端口
    livenessProbe:                   #定义存活探针
      httpGet:                       #指定使用HTTP GET请求进行探测。
        port: http                   #这指定了要访问的容器的端口,为上面的http端口名称
        path: /index.html            #这是要访问的HTTP路径。表示站点目录下的index.html文件
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10             #探测的超时后等待多少秒。默认值是1秒。最小值是1

模拟探测失败

[root@master01 data]#kubectl apply -f liveness-httpget.yaml
pod/liveness-httpget created
[root@master01 data]#kubectl exec -it  liveness-httpget -- rm -rf /usr/share/nginx/html/index.html
#删除探测的文件

同时在另一个终端上追踪信息

[root@master01 data]#kubectl get pod liveness-httpget -w
NAME               READY   STATUS              RESTARTS   AGE
liveness-httpget   0/1     ContainerCreating   0          3s
liveness-httpget   1/1     Running             0          3s
liveness-httpget   1/1     Running             1          34s
......

查看事件信息

[root@master01 data]#kubectl describe pod liveness-httpget |sed -n "/Events/,/$$/p"
Events:
  Type     Reason     Age                From               Message
  ----     ------     ----               ----               -------
  Normal   Scheduled  80s                default-scheduler  Successfully assigned default/liveness-httpget to node02
  Warning  Unhealthy  49s (x3 over 55s)  kubelet            Liveness probe failed: HTTP probe failed with statuscode: 404
  Normal   Killing    49s                kubelet            Container liveness-httpget failed liveness probe, will be restarted
  Normal   Pulled     48s (x2 over 79s)  kubelet            Container image "nginx:1.18.0" already present on machine
  Normal   Created    48s (x2 over 79s)  kubelet            Created container liveness-httpget
  Normal   Started    48s (x2 over 79s)  kubelet            Started container liveness-httpget
#状态码为404,表示找不到文件,所以探测失败,而后重新创建容器
2.3 使用tcpSocket方式
[root@master01 data]#vim liveness-tcp.yaml
[root@master01 data]#cat liveness-tcp.yaml
apiVersion: v1
kind: Pod
metadata:
  name: probe-tcp
spec:
  containers:
  - name: nginx
    image: nginx:1.18.0
    livenessProbe:             #定义了存活探针的配置
      initialDelaySeconds: 5   #在容器启动后,等待5秒才开始进行存活检查
      timeoutSeconds: 1        #每次存活探针尝试的超时时间设置为 1 秒
      tcpSocket:               #定义了使用 TCP 套接字进行探针检查
        port: 8080             #探针将尝试连接容器的8080端口
      periodSeconds: 10        #每隔10秒执行一次存活检查
      failureThreshold: 2      #如果连续2次探针检查都失败,会认为容器不再存活,并尝试重启该容器

生成pod并进行追踪

[root@master01 data]#kubectl apply -f liveness-tcp.yaml
pod/liveness-tcp created
[root@master01 data]#kubectl get pod liveness-tcp -w
NAME           READY   STATUS              RESTARTS   AGE
liveness-tcp   0/1     ContainerCreating   0          1s
liveness-tcp   1/1     Running             0          3s
liveness-tcp   1/1     Running             1          21s  #第一次是init(5秒)+period(10秒)*2,一般会上下存在误差
liveness-tcp   1/1     Running             2          41s  #第二次是period(10秒)+period(10秒)重试了两次
liveness-tcp   1/1     Running             3          61s
liveness-tcp   1/1     Running             4          81s
......
[root@master01 data]#kubectl describe pod liveness-tcp |sed -n '/Event/,/$$/p'
Events:
  Type     Reason     Age                 From               Message
  ----     ------     ----                ----               -------
  Normal   Scheduled  2m8s                default-scheduler  Successfully assigned default/liveness-tcp to node01
  Normal   Created    69s (x4 over 2m7s)  kubelet            Created container nginx
  Normal   Started    69s (x4 over 2m7s)  kubelet            Started container nginx
  Normal   Pulled     50s (x5 over 2m7s)  kubelet            Container image "nginx:1.18.0" already present on machine
  Warning  Unhealthy  50s (x8 over 2m)    kubelet            Liveness probe failed: dial tcp 10.244.1.128:8080: connect: connection refused
  Normal   Killing    50s (x4 over 110s)  kubelet            Container nginx failed liveness probe, will be restarted

(三)就绪探针

1.定义

就绪探针用于检测容器是否准备好接收请求。在容器启动过程中或更新后,可能需要一些时间才能完全准备好。就绪探针会定期探测容器状态,只有当容器就绪时才会将其加入到服务负载均衡中。这有助于避免将请求发送到尚未准备好的容器,提高服务的稳定性和可用性。

有时候,应用会暂时性地无法为请求提供服务。 例如,应用在启动时可能需要加载大量的数据或配置文件,或是启动后要依赖等待外部服务。 在这种情况下,既不想杀死应用,也不想给它发送请求。 Kubernetes 提供了就绪探针来发现并缓解这些情况。 容器所在 Pod 上报还未就绪的信息,并且不接受通过 Kubernetes Service 的流量

2.探针使用

2.1 定义文件

使用httpGet的方式去使用就绪探针

[root@master01 data]#vim readiness-httpget.yaml
[root@master01 data]#cat readiness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget
  namespace: default
spec:
  containers:
  - name: readiness-httpget-container
    image: nginx:1.18.0
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    readinessProbe:             #定义就绪探针的配置,用于确定容器是否准备好接受流量
      httpGet:                  #使用 HTTP GET 请求进行探针检查。
        port: http              #探针将尝试访问名为http的端口,上述自定义的端口名称
        path: /index.php        #探针将尝试访问/index.php路径
      initialDelaySeconds: 1    #在容器启动后,等待1秒才开始进行就绪检查
      periodSeconds: 3          #每隔 3 秒执行一次就绪检查
    livenessProbe:              #定义存活探针的配置
      httpGet:                  #同样使用 HTTP GET请求方式
        port: http              #探针将尝试访问名为http的端口
        path: /index.html       #探针将尝试访问 /index.html 路径,这是 Nginx 的默认首页
      initialDelaySeconds: 1    #等待 1 秒才开始进行存活检查
      periodSeconds: 3          #每隔 3 秒执行一次存活检查。
      timeoutSeconds: 10        #每次存活探针尝试的超时时间设置为 10 秒

2.2 查看结果

[root@master01 data]#kubectl apply -f readiness-httpget.yaml
pod/readiness-httpget created
[root@master01 data]#kubectl get pod readiness-httpget
NAME                READY   STATUS    RESTARTS   AGE
readiness-httpget   0/1     Running   0          3s
#容器状态处于Running,但是readiness探测失败,无法进入READY状态

可以通过查看event事件,找出错误信息

[root@master01 data]#kubectl get event |grep readiness-httpget
4m          Normal    Scheduled   pod/readiness-httpget   Successfully assigned default/readiness-httpget to node02
3m59s       Normal    Pulled      pod/readiness-httpget   Container image "nginx:1.18.0" already present on machine
3m59s       Normal    Created     pod/readiness-httpget   Created container readiness-httpget-container
3m58s       Normal    Started     pod/readiness-httpget   Started container readiness-httpget-container
2m54s       Warning   Unhealthy   pod/readiness-httpget   Readiness probe failed: HTTP probe failed with statuscode: 404

#错误信息表示虽然成功启动容器,但是就绪探针在访问时找不到文件,出现404报错

解决此问题需要准备好就绪探针探测的文件,即index.php文件

[root@master01 data]#kubectl exec -it  readiness-httpget bash
#进入容器
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@readiness-httpget:/# echo "this is index.php" > /usr/share/nginx/html/index.php
#添加探测文件
root@readiness-httpget:/# exit
exit
[root@master01 data]#kubectl get pod readiness-httpget
NAME                READY   STATUS    RESTARTS   AGE
readiness-httpget   1/1     Running   0          8m18s
#再次查看,进入READY状态

当删除index.html文件时,存活探针会探测失败,容器进行重启

[root@master01 data]#kubectl exec -it readiness-httpget -- rm -rf /usr/share/nginx/html/index.html
[root@master01 data]#kubectl get pod readiness-httpget -w
NAME                READY   STATUS    RESTARTS   AGE
readiness-httpget   1/1     Running   0          13m
readiness-httpget   0/1     Running   1          13m

3.service探测

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

3.1 定义文件

在yaml文件中添加三个Pod实例,并创建一个service去管理三个pod 

[root@master01 data]#vim readiness-nginx.yaml
[root@master01 data]#cat readiness-nginx.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
     app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.18.0
        ports:
        - name: http
          containerPort: 80
        readinessProbe:
          httpGet:
            port: 80
            path: /index.html
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 10
#创建deployment控制器,管理三个pod实例,定义探针策略
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  selector:
    app: nginx
  type: ClusterIP
  ports:
  - name: http
    port: 80
    targetPort: 80
#创建service进行管理

执行文件后,会生成三个pod实例,并由service管理,当其中一个pod实例的就绪探针探测失败后,该地址会退出READY状态,且端点控制器将从 endpoints 中剔除删除该 Pod 的 IP 地址

[root@master01 data]#kubectl apply -f readiness-nginx.yaml
deployment.apps/nginx created
service/nginx created
[root@master01 data]#kubectl get pod 
NAME                     READY   STATUS      RESTARTS   AGE
nginx-848cb98b8f-rfmzp   1/1     Running     0          39s
nginx-848cb98b8f-tkh9d   1/1     Running     0          39s
nginx-848cb98b8f-tllxd   1/1     Running     0          39s
[root@master01 data]#kubectl get endpoints/nginx -o wide
NAME                   ENDPOINTS                                     AGE
endpoints/nginx        10.244.2.147,10.244.1.129:80,10.244.1.130:80  107s
#查看关联的后端地址
[root@master01 data]#kubectl exec -it nginx-848cb98b8f-rfmzp -- rm -rf /usr/share/nginx/html/index.html
#删除其中一个pod实例的探针探索的文件
[root@master01 data]#kubectl get pods,svc,endpoints -o wide
NAME                         READY   STATUS             RESTARTS   AGE    IP             NODE     NOMINATED NODE   READINESS GATES
pod/nginx-848cb98b8f-rfmzp   0/1     Running            0          107s   10.244.2.147   node02   <none>           <none>
pod/nginx-848cb98b8f-tkh9d   1/1     Running            0          107s   10.244.1.130   node01   <none>           <none>
pod/nginx-848cb98b8f-tllxd   1/1     Running            0          107s   10.244.1.129 node01   <none>           <none>
#被删除探针探索的文件的pod实例,退出READY状态
NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE    SELECTOR
service/kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   10d    <none>
service/nginx        ClusterIP   10.96.222.66   <none>        80/TCP    107s   app=nginx

NAME                   ENDPOINTS                         AGE
endpoints/kubernetes   192.168.83.30:6443                10d
endpoints/nginx        10.244.1.129:80,10.244.1.130:80   107s
#后端关联的podIP同时也被删除

同样的,当恢复完文件后,该pod实例会恢复正常,进入READY状态,同时将自己的地址添加到端点控制器当中

[root@master01 data]#kubectl get pod -owide
NAME                     READY   STATUS             RESTARTS   AGE    IP             NODE     NOMINATED NODE   READINESS GATES
nginx-848cb98b8f-rfmzp   1/1     Running            0          21m    10.244.2.147   node02   <none>           <none>
nginx-848cb98b8f-tkh9d   1/1     Running            0          21m    10.244.1.130   node01   <none>           <none>
nginx-848cb98b8f-tllxd   1/1     Running            0          21m    10.244.1.129   node01   <none>           <none>
[root@master01 data]#kubectl get endpoints nginx 
NAME    ENDPOINTS                                         AGE
nginx   10.244.1.129:80,10.244.1.130:80,10.244.2.147:80   22m

(四)启动探针

1.定义

启动探针用于检测容器是否成功启动。在某些情况下,容器启动可能需要较长时间(如加载大量数据或执行初始化操作)。启动探针会在容器启动后立即开始探测,并在探测成功前阻止其他探针(如存活探针和就绪探针)的探测。这有助于确保容器在完全启动并准备好之前不会被错误地终止或加入到服务负载均衡中。

如果配置了 startupProbe 探测,在则在 startupProbe 状态为 Success 之前,其他所有探针都处于无效状态,直到它成功后其他探针才起作用。 如果 startupProbe 失败,kubelet 将杀死容器,容器将根据 restartPolicy 来重启。如果容器没有配置 startupProbe, 则默认状态为 Success

2.探针应用

写一个包含三种探针的yaml文件

[root@master01 data]#vim  startup-httpget.yaml 
[root@master01 data]#cat  startup-httpget.yaml 
apiVersion: v1  
kind: Pod  
metadata:  
  name: nginx-startup-probe  
  labels:  
    app: nginx  
spec:  
  containers:  
  - name: nginx  
    image: nginx:1.18.0 
    ports:
    - name: http
      containerPort: 80
    startupProbe:
      httpGet:
        path: /index1.html      #探测的HTTP路径,确保你的应用可以提供该路径的响应 
        port: http             #容器开放的端口
      failureThreshold: 30     #在标记容器启动失败之前,允许启动探针失败的次数
      periodSeconds: 10        #启动探针的探测频率(秒)
      successThreshold: 1      #在标记容器启动成功之前,需要启动探针成功的次数
#failureThreshold设置为30,表示在启动探针连续失败30次之后,容器将被标记为启动失败。
#periodSeconds设置为10,表示启动探针每10秒执行一次。
#successThreshold设置为1,表示只要启动探针成功一次,容器就被标记为启动成功。
    livenessProbe:
      httpGet:
        path: /index.html
        port: http
      failureThreshold: 3
      periodSeconds: 10
    readinessProbe:
      httpGet:
        path: /index.html
        port: http
      failureThreshold: 3
      periodSeconds: 10

 当startuo探针探测失败时,即使存活与就绪探针的探测结果确定是正确,但是容器依然无法进入READY状态,启动探针作为第一道关卡,会确保容器成功启动后才可以允许存活与就绪探针工作

[root@master01 data]#kubectl apply -f startup-httpget.yaml 
pod/nginx-startup-probe created
[root@master01 data]#kubectl get pod nginx-startup-probe  -w
NAME                  READY   STATUS    RESTARTS   AGE
nginx-startup-probe   0/1     Running   0          3s
nginx-startup-probe   0/1     Running   1          5m13s
nginx-startup-probe   0/1     Running   3          10m
nginx-startup-probe   0/1     Running   2          15m

#因为启动探针的failureThreshold与periodSeconds的值分别为30,10。
#所以启动探针完整的执行一遍时间为30 * 10 =300(s),即5分钟

可以使用kubectl get events -w命令追踪事件信息

[root@master01 data]#kubectl get events -w
......
0s          Warning   Unhealthy   pod/nginx-startup-probe      Startup probe failed: HTTP probe failed with statuscode: 404
0s          Warning   Unhealthy   pod/nginx-startup-probe      Startup probe failed: HTTP probe failed with statuscode: 404
0s          Warning   Unhealthy   pod/nginx-startup-probe      Startup probe failed: HTTP probe failed with statuscode: 404
0s          Warning   Unhealthy   pod/nginx-startup-probe      Startup probe failed: HTTP probe failed with statuscode: 404
0s          Warning   Unhealthy   pod/nginx-startup-probe      Startup probe failed: HTTP probe failed with statuscode: 404
0s          Warning   Unhealthy   pod/nginx-startup-probe      Startup probe failed: HTTP probe failed with statuscode: 404
0s          Warning   Unhealthy   pod/nginx-startup-probe      Startup probe failed: HTTP probe failed with statuscode: 404
0s          Warning   Unhealthy   pod/nginx-startup-probe      Startup probe failed: HTTP probe failed with statuscode: 404
0s          Warning   Unhealthy   pod/nginx-startup-probe      Startup probe failed: HTTP probe failed with statuscode: 404
0s          Warning   Unhealthy   pod/nginx-startup-probe      Startup probe failed: HTTP probe failed with statuscode: 404
0s          Normal    Killing     pod/nginx-startup-probe      Container nginx failed startup probe, will be restarted
60m         Warning   Unhealthy   pod/liveness-tcp             Liveness probe failed: dial tcp 10.244.1.128:8080: connect: connection refused
0s          Warning   Unhealthy   pod/nginx-startup-probe      Startup probe failed: HTTP probe failed with statuscode: 404

上述操作的目的主要在于告诉攻城狮们启动容器是在存活与就绪探针之前开始工作,必须等到启动探针工作完毕,或成功探测指定次数之后,存活与就绪探针才进入工作。实际上,在启动探针中可以加上初始化的操作,等到初始化操作完成后,去探测初始化信息,成功之后在进行其它探针的工作。

例如创建一个存储文件,而后使用exec的检测方式,使用cat命令去查看这个文件是否存在,完成探测任务

3.主要作用

启动探针的主要作用在于 

延缓其他探针生效:在容器启动初期,启动探针先于存活探针(Liveness Probe)和就绪探针(Readiness Probe)生效。当启动探针配置存在时,kubelet不会执行存活和就绪探针,直到启动探针成功为止。

防止频繁重启:若应用启动期间,存活探针或就绪探针就开始工作,而此时应用可能还没有完全启动成功,这两个探针可能会因为应用未能及时响应而触发容器重启,造成不必要的服务中断和循环重启。启动探针的存在可以有效地防止此类情况的发生。

确保应用稳定:启动探针使得Kubernetes能够在应用真正启动完毕后才将其视为健康的,并开始接受流量,从而保障了集群中应用服务的稳定性。

(五)生命周期钩子

在Kubernetes中,Pod的生命周期包含了多个阶段,而生命周期钩子(Lifecycle Hooks)允许用户在Pod中的容器生命周期中的特定点执行操作。主要有两种生命周期钩子:postStart 和 preStop。

1.钩子种类

1.1 启动钩子(postStart)

作用:在容器创建后立即执行。它常用于在容器启动后执行一些初始化的工作,比如设置环境变量、启动子进程、检查或加载数据等。postStart 钩子保证在容器的主进程启动前执行。

特点

异步执行,不保证在容器ENTRYPOINT之前运行。

如果没有参数传递给处理程序,容器ENTRYPOINT和钩子执行是异步操作。

如果钩子花费太长时间以至于容器不能运行或者挂起,容器将不能达到running状态。

如果PostStart钩子失败,容器将会被kill。

1.2 停止钩子(preStop)

作用:在容器终止之前执行。允许容器在停止前优雅地关闭,比如保存文件、关闭连接、发送信号等。preStop 钩子给容器提供了一个机会,以便在容器终止前完成一些清理工作。

特点

同步执行,即在删除容器的调用发出之前必须完成。

如果钩子在执行期间挂起,Pod将停留在running状态并且永不会达到failed状态。

如果PreStop钩子失败,容器同样也会被kill。

2.定义文件

生命周期钩子在Pod定义中的containers部分的lifecycle字段下定义

[root@master01 data]#vim post.yaml
[root@master01 data]#cat post.yaml
apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-hooks
spec:
  containers:
  - name: lifecycle-hooks
    image: nginx:1.18.0
    lifecycle:              #定义容器的生命周期钩子
      postStart:            #容器启动后立即执行的命令
        exec:               #使用exec的方式进入容器执行命令
          command: ["/bin/sh", "-c", "echo containers start >> /var/log/nginx/post.log"]
#command指令表示需要执行的命令
#命令表示在容器启动后,立即输出containers start到 /var/log/nginx/post.log文件中
      preStop:              #容器停止前执行的命令
        exec:               #同样使用exec的方式进入容器执行命令
          command: ["/bin/sh", "-c", "echo containers stop >> /var/log/nginx/post.log"]
#表示在容器停止前输出containers stop到 /var/log/nginx/post.log文件中
    volumeMounts:            #定义了容器内的卷挂载点
    - name: post-log         #挂载的卷的名字
      mountPath: /var/log/nginx/  #容器内的挂载路径
      readOnly: false         #卷是否以只读方式挂载。false表示否
  initContainers:             #定义了 Pod 启动前运行的初始化容器列表
  - name: init-mypod
    image: nginx:1.18.0       
    command: ["/bin/sh", "-c", "echo 'initContainers is ready'   >> /var/log/nginx/post.log"]
    volumeMounts:
    - name: post-log 
      mountPath: /var/log/nginx/
      readOnly: false
#同样的,定义了如何将名为pod-log的卷挂载到初始化容器内,挂载路径同样是/var/log/nginx/
  volumes:
  - name: post-log
    hostPath:                 #将宿主机上的一个目录或文件挂载到Pod中
      path: /data/nginx/log/  #宿主机上的文件或目录路径
      type: DirectoryOrCreate #如果指定的路径不存在,则会创建它

3.启动pod

启动pod并查看该pod在哪一个节点上创建

[root@master01 data]#kubectl apply -f post.yaml
pod/lifecycle-hooks created
[root@master01 data]#kubectl get pod lifecycle-hooks -o wide
NAME              READY   STATUS    RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
lifecycle-hooks   1/1     Running   0          25s   10.244.1.134   node01   <none>           <none>
#该pod在node01节点上启动

4.查看文件

在节点上查看文件

[root@node01 ~]#cd /data/nginx/log/
[root@node01 log]#ls
access.log  error.log  post.log
[root@node01 log]#cat post.log 
initContainers is ready
containers start

在master节点上删除容器

[root@master01 data]#kubectl delete -f post.yaml
pod "lifecycle-hooks" deleted
[root@master01 data]#kubectl get pod lifecycle-hooks 
Error from server (NotFound): pods "lifecycle-hooks" not found

回到node节点查看文件

[root@node01 log]#cat post.log 
initContainers is ready
containers start
containers stop    #容器退出前,会将此信息追加到post.log文件当中

5.重要性及应用场景

优雅的停止服务:在生产环境中,当需要更新或重启服务时,使用PreStop钩子可以通知外部系统(如负载均衡器、服务发现组件等)该容器即将停止服务,从而实现优雅的流量迁移,避免服务中断或影响用户体验。

资源清理:通过PostStart和PreStop钩子,可以在容器启动和停止时执行资源清理操作,如删除临时文件、关闭数据库连接等,确保资源的正确使用和释放。

配置加载:在PostStart钩子中加载配置文件或启动子进程,可以确保容器在启动后立即进入正确的运行状

三、总结

(一)资源限制

在Kubernetes中,Pod资源限制(Resource Limits)的作用非常重要,它们允许管理员或用户为Pod中的容器设置资源使用的上限和下限,以确保资源的合理使用和系统的稳定性。以下是Pod资源限制的主要作用:

  1. 资源隔离:通过设置资源限制,可以确保一个Pod或容器不会消耗过多的系统资源,如CPU、内存等。这有助于将不同的应用或工作负载隔离开来,防止一个Pod耗尽所有资源而导致其他Pod受到影响。

  2. 提高稳定性:通过限制资源的消耗,可以减少由于某个Pod的意外行为(如内存泄漏、无限循环等)导致的系统崩溃或不稳定。当Pod达到其资源限制时,Kubernetes会采取适当的措施(如终止Pod),以防止对整个集群造成负面影响。

  3. 公平调度:资源限制有助于Kubernetes调度器(Scheduler)在集群中公平地分配资源。调度器会考虑每个Pod的资源请求和限制,以找到最合适的节点来运行Pod。这有助于确保集群中的资源得到合理的利用,避免某些节点过载而其他节点空闲。

  4. 成本优化:通过限制Pod的资源使用,可以更有效地管理云资源的使用,从而降低成本。管理员可以根据应用的实际需求设置合理的资源限制,避免购买过多的云资源而造成浪费。

  5. 服务质量(QoS)保证:Kubernetes根据Pod的资源请求和限制将Pod分为不同的服务质量(QoS)类别。这些类别决定了在资源争用或节点资源不足时,Pod的调度和驱逐策略。通过设置适当的资源限制,可以为不同的应用或服务提供不同的QoS保证。

  6. 监控和告警:资源限制还可以与Kubernetes的监控和告警系统配合使用,以便在Pod接近或超过其资源限制时发出警报。这有助于管理员及时发现并解决潜在的问题,避免对业务造成影响。

(二)探针机制

Pod探针机制在Kubernetes中扮演着至关重要的角色,它主要用于监控Pod中容器的健康状态,并根据这些状态信息来决定Pod的生命周期事件,如是否应该重启容器、是否应该将Pod添加到Service的Endpoints列表中等。

kubelet 使用存活探针来确定什么时候要重启容器。 例如,存活探针可以探测到应用死锁(应用在运行,但是无法继续执行后面的步骤)情况。 重启这种状态下的容器有助于提高应用的可用性,即使其中存在缺陷。

存活探针的常见模式是为就绪探针使用相同的低成本 HTTP 端点,但具有更高的 failureThreshold。 这样可以确保在硬性终止 Pod 之前,将观察到 Pod 在一段时间内处于非就绪状态。

kubelet 使用就绪探针可以知道容器何时准备好接受请求流量,当一个 Pod 内的所有容器都就绪时,才能认为该 Pod 就绪。 这种信号的一个用途就是控制哪个 Pod 作为 Service 的后端。 若 Pod 尚未就绪,会被从 Service 的负载均衡器中剔除。

kubelet 使用启动探针来了解应用容器何时启动。 如果配置了这类探针,存活探针和就绪探针成功之前不会重启,确保这些探针不会影响应用的启动。 启动探针可以用于对慢启动容器进行存活性检测,避免它们在启动运行之前就被杀掉。

(三)生命钩子

生命钩子(Lifecycle Hooks)在Kubernetes中,特别是Pod的生命周期管理中,提供了一种机制来在容器生命周期的特定事件发生时执行自定义操作。这些钩子允许用户定义在容器启动之前、之后以及容器终止之前执行的操作

初始化容器

通过PostStart钩子,可以在容器启动后立即执行一些初始化操作,如加载配置文件、设置环境变量、启动子进程等。这对于需要在容器启动后立即进行的一些设置和配置非常有用。

资源准备和清理

在容器启动之前,可以使用Init Containers(初始化容器)来执行一些前置任务,如从外部系统下载配置文件、设置网络策略、等待其他依赖项就绪等。这些初始化容器通过完成必要的准备工作,为主容器提供一个稳定的运行环境。在容器终止之前,PreStop钩子可以用于执行资源清理操作,如关闭数据库连接、删除临时文件、发送退出通知等。这有助于确保容器在退出时不会留下任何未清理的资源或状态。

优雅地终止容器

PreStop钩子允许容器在接收到终止信号之前执行一些清理操作,如等待当前请求处理完成、保存状态到持久化存储等。这有助于实现容器的优雅终止,确保在容器退出时不会丢失重要数据或导致服务中断。

日志和监控

生命钩子可以用于触发日志记录或监控事件,以便在容器生命周期的关键时刻收集相关信息。例如,在PostStart钩子中记录容器的启动时间、版本信息等,或在PreStop钩子中记录容器的退出原因和状态。

扩展性和灵活性

生命钩子提供了灵活的扩展机制,允许用户根据需要在容器生命周期的不同阶段执行自定义操作。这使得Kubernetes更加适应各种应用场景和需求,为用户提供了更大的灵活性和控制力。

故障处理和恢复

在某些情况下,容器可能会因为某些原因(如配置错误、资源不足等)而启动失败或运行异常。通过生命钩子,可以在这些情况下执行一些故障处理和恢复操作,如重新加载配置文件、释放资源、重启容器等。这有助于提高系统的稳定性和可用性。

(四)pod的状态

Pending(等待中)

Pod已经被Kubernetes系统接受,但是有一个或多个容器镜像尚未创建。

Pod等待被调度到一个节点上。可能涉及下载镜像、分配IP地址、执行初始化容器等操作。

如果Pod一直处于等待中,可能是由于资源不足、调度问题或其他原因导致。

Running(运行中)

Pod已经被调度到一个节点上,并且所有的容器都已创建。

至少有一个容器正在运行,或者正在启动或重启。

Succeeded(已完成)

Pod中的所有容器都已成功完成并退出。

通常适用于一次性或批处理作业。

Failed(失败)

Pod中的一个或多个容器由于某种原因失败。

这可能是由于容器的退出代码非零、初始化容器失败、依赖资源不可用等原因导致。

Unknown(未知)

由于某种原因,Pod的状态无法确定。

这可能是由于与API服务器的通信问题或其他异常情况导致。

Terminating(终止中)

当Pod被删除或终止时,它将进入终止中的状态。

在这个状态下,Kubernetes会尝试停止容器并清理资源。

ContainerCreating(创建容器中)

当Pod的容器正在创建中时,Pod将进入此状态。

这可能涉及到拉取容器镜像、创建容器等操作。

CrashLoopBackOff

这不是Pod的官方状态,但经常出现在Pod描述中。

表明Pod中的一个或多个容器尝试启动后失败,并正在尝试重启。

可能是由于应用程序错误、配置问题等引起的。

ImagePullBackOff

Pod无法拉取一个或多个容器镜像。

可能是因为镜像不存在,或者与容器注册中心的认证问题。

Evicted

当节点上的资源(如内存或磁盘空间)不足时,Pod可能会被驱逐。

驱逐行为是Kubernetes为了保护节点稳定性而自动执行的操作。

OOMKilled

如果Pod中的容器使用超出其分配的内存限制,它可能会被系统的Out-Of-Memory (OOM) killer终止。这通常表明容器配置的内存限制过低或应用程序内存泄露

(五)Container生命周期

Waiting:启动到运行中间的一个等待状态。

Running:运行状态。

Terminated:终止状态。 如果没有任何异常的情况下,container应该会从Waiting状态变为Running状态,这时容器可用。

但如果长时间处于Waiting状态,container会有一个字段reason表明它所处的状态和原因,如果这个原因很容易能标识这个容器再也无法启动起来时,例如ContainerCannotRun,整个服务启动就会迅速返回。(这里是一个失败状态返回的特性,不详细阐述)

  • 22
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值