pod的生命周期

pod的生命周期

pod在整个生命周期的过程中的几个状态:

Pending:创建了pod资源并存入etcd中,但尚未完成调度。

ContainerCreating:Pod 的调度完成,被分配到指定 Node 上。处于容器创建的过程中。通常是在拉取镜像的过程中。

Running:Pod 包含的所有容器都已经成功创建,并且成功运行起来。

Succeeded:Pod中的所有容器都已经成功终止并且不会被重启

Failed:所有容器都已经终止,但至少有一个容器终止失败,也就是说容器返回了非0值的退出状态或已经被系统终止。

Unknown:因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。

pod生命周期的重要行为

pause容器:在启动任何容器之前,先创建pause基础容器,它初始化Pod的环境并为后续加⼊的容器提供共享的名称空间。

初始化容器:一个pod可以拥有任意数量的init容器。init容器是按照顺序以此执行的,并且仅当最后一个init容器执行完毕才会去启动主容器。

生命周期钩子:pod允许定义两种类型的生命周期钩子,启动后(post-start)钩子和停止前(pre-stop)钩子

这些生命周期钩子是基于每个容器来指定的,和init容器不同的是,init容器是应用到整个pod。而这些钩子是针对容器的,是在容器启动后和停止前执行的。

容器探测:

  • ​ Startup(启动探测):探测容器是否正常运行
  • ​ Liveness(存活探测):判断容器是否处于runnning状态,根据重启策略决定是否重启容器
  • ​ Readiness(就绪检测):判断容器是否准备就绪并对外提供服务,将容器设置为不可用,不接受

pod启动流程:

pause container (基础容器)——> initcontainer(初始化容器) ——> containers (主容器)——> post-start(容器启动后钩子)——>StartupProbe(启动探测)——>LivenessProbe(存活探测)——>ReadinessProbe(就绪探测)——>Pre-stop(容器结束前钩子)

pod终止流程:

(1)用户发出删除 pod 命令:kubectl delete pods ,kubectl delete -f yaml

(2)Pod 对象随着时间的推移更新,在宽限期(默认情况下30秒),pod 被视为“dead”状态

(3)将 pod 标记为“Terminating”状态

(4)第三步同时运行,监控到 pod 对象为“Terminating”状态的同时启动 pod 关闭过程

(5)第三步同时进行,endpoints 控制器监控到 pod 对象关闭,将pod与service匹配的 endpoints 列表中删除

(6)如果 pod 中定义了 preStop 钩子处理程序,则 pod 被标记为“Terminating”状态时以同步的方式启动执行;若宽限期结束后,preStop 仍未执行结束,第二步会重新执行并额外获得一个2秒的小宽限期

(7)Pod 内对象的容器收到 TERM 信号

(8)宽限期结束之后,若存在任何一个运行的进程,pod 会收到 SIGKILL 信号

(9)Kubelet 请求 API Server 将此 Pod 资源宽限期设置为0从而完成删除操作

定义初始化容器

初始化容器会在主容器之前执行,与主容器共享存储卷。

初始化容器与主容器区别:

  1. 初始化容器不支持Readinessprobe,运维他们必须在Pod就绪之前运行完成
  2. 每个初始化容器必须运行成功,下一个才能够运行(串行执行)
# 如果pod初始化容器失败,kubernetes会根据重启策略决定是否重启初始化容器,不断地重启该pod,知道初始化容器成功为止,然而如果Pod对于的restartPolicy值为Never,就不会重新启动。
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    # 解析域名,但会一直重复循环
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
    # 第一个initcontainer没有运行完,不会运行此initcontainer
  - name: init-mydb
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
  # 更加不会运行container里面的容器
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
apiVersion: v1
kind: Pod
metadata:
  name: initnginx
spec:
  initContainers:
  - name: install
    image: docker.io/library/busybox:1.28
    imagePullPolicy: IfNotPresent
    # 下载百度页面到/work-dir目录
    command:
    - wget
    - "-O"
    - "/work-dir/index.html"
    - "https://www.baidu.com"
    # 挂载workdir卷到/work-dir
    volumeMounts:
    - name: workdir
      mountPath: /work-dir
  containers:
  - name: nginx
    image: docker.io/xianchao/nginx:v1
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    # 挂载workerdir物理卷到容器的/usr/share/nginx/html,该卷和initcontainer挂载的是同一个卷
    volumeMounts:
    - name: workdir
      mountPath: /usr/share/nginx/html
  dnsPolicy: Default
  # 临时创建一个workdir的卷
  volumes:
  - name: workdir
    emptyDir: {}

定义钩子

postStart:容器创建之后立刻执行,用于资源部署、环境准备等。

preStop:在容器被终止前执行,用于优雅关闭应用程序、通知其他系统等

### 用法
......
containers:
- image: sample:v2  
     name: war
     # 定义生命周期
     lifecycle:
       # 在容器创建成功后,复制/sample.war到/app文件夹中
       postStart:
         exec:
           command:
           - “cp”
           - “/sample.war”
           - “/app”
       prestop:
         # 容器结束前请求接口,把请求发送给监控系统
         httpGet:
           host: monitor.com
           path: /waring
           port: 8080
           scheme: HTTP        
......

优雅删除资源对象

#(默认)K8S通知node执行docker stop命令,docker会先向容器中PID为1的进程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认超时时间(30s),会继续发送SIGKILL的系统信号强行kill掉进程。

#使用pod生命周期(利用PreStop回调函数),它执行在发送终止信号之前。

#默认情况下,所有的删除操作的优雅退出时间都在30秒以内。kubectl delete命令支持--grace-period=的选项,以运行用户来修改默认值。0表示删除立即执行,并且立即从API中删除pod。在节点上,被设置了立即结束的的pod,仍然会给一个很短的优雅退出时间段,才会开始被强制杀死。

apiVersion: v1
kind: Pod
metadata:
  name: life-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: docker.io/xianchao/nginx:v1
    imagePullPolicy: IfNotPresent
    lifecycle:
      # 启动容器后执行此命令,重定向此文件
      postStart:
         exec:
           command: ["/bin/sh", "-c","echo 'lifecycle hookshandler' > /usr/share/nginx/html/test.html"]
      # 结束容器前执行此命令,提前关闭nginx服务(可以在删除pod时正常停止nginx服务)
      preStop:
         exec:
           command:
           - "/bin/sh"
           - "-c"
           - "nginx -s stop"

探测Probe

#startupProbe:探测容器中的应用是否已经启动。如果提供了启动探测(startup probe),则禁用所有其他探测,直到它成功为止。如果启动探测失败,kubelet 将杀死容器,容器服从其重启策略进行重启。如果容器没有提供启动探测,则默认状态为成功Success。

### livenessprobe:用指定的方式(**exec、tcp、http**)检测pod中的容器是否正常运行,如果检测失败,则认为容器不健康,那么Kubelet将根据Pod中设置的 restartPolicy策略来判断Pod 是否要进行重启操作,如果容器配置中没有配置 livenessProbe,Kubelet 将认为存活探针探测一直为success(成功)状态。

### readnessprobe:就绪性探测,用于检测容器中的应用是否可以接受请求,当探测成功后才使Pod对外提供网络访问,将容器标记为就绪状态,可以加到pod前端负载,如果探测失败,则将容器标记为未就绪状态,会把pod从前端负载移除
# 常见探测模式(所有的探测都支持下面三种探针):
- exec:在容器中执行一个命令,并根据返回的状态码进行诊断**,只有返回0为成功。
- cpSocket:通过与容器的某TCP端口尝试建立连接,**如果能够建立TCP连接,说明容器健康。
- httpGet:通过向容器IP地址的某指定端口的path发起HTTP GET请求。**如果响应的状态码大于等于200且小于400,则认为容器健康。

startupProbe 启动探测

apiVersion: v1
kind: Pod
metadata:
  name: check
  namespace: default
  labels:
    app: check
spec:
  containers:
  - name: check
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    # 容器启动后,运行10秒退出,改变容器状态
    # 这时pod根据启动探测发现pod的服务异常,会自动重启服务
    command:
    - /bin/sh
    - -c
    - sleep 10;exit
    
    # 在上面的例子中, 容器进程返回值非零, Kubernetes则认为容器发生故障, 需要重启。 有不少情况是发生了故障, 但进程并不会退出。 比如访问Web服务器时显示500内部错误, 可能是系统超载, 也可能是资源死锁, 此时httpd进程并没有异常退出, 在这种情况下重启容器可能是最直接、 最有效的解决方案。
# Pod探针相关的属性:
# 探针(Probe)有许多可选字段,可以用来更加精确的控制Liveness和Readiness两种探针的行为
initialDelaySeconds:容器启动后要等待多少秒后探针开始工作,单位“秒”,默认是 0 秒,最小值是 0 
periodSeconds: 执行探测的时间间隔(单位是秒),默认为 10s,单位“秒”,最小值是1
timeoutSeconds: 探针执行检测请求后,等待响应的超时时间,默认为1,单位“秒”。
successThreshold:连续探测几次成功,才认为探测成功,默认为 1,在 Liveness 探针中必须为1,最小值为1。
failureThreshold: 探测失败的重试次数,重试一定次数后将认为失败,在 readiness 探针中,Pod会被标记为未就绪,默认为 3,最小值为 1
# ExecAction
apiVersion: v1
kind: Pod
metadata:
  name: startupprobe
spec:
  containers:
  - name: startup
    image: xianchao/tomcat-8.5-jre8:v1
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 8080
  # 启动探测
  startupProbe:
    exec:
      command:
      - "/bin/sh"
      - "-c"
      # 该指令会报错,就会触发exec探测,重启pod,重启次数多了就会变成clashbackoff状态
      - "aa ps aux | grep tomcat"
    initialDelaySeconds: 20 #容器启动后多久开始探测
    periodSeconds: 20 #执行探测的时间间隔
    timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
    successThreshold: 1 #成功多少次才算成功
    failureThreshold: 3 #失败多少次才算失败
# tcpSocket
apiVersion: v1
kind: Pod
metadata:
  name: startupprobe
spec:
  containers:
  - name: startup
    image: xianchao/tomcat-8.5-jre8:v1
    imagePullPolicy: IfNotPresent
    ports:
    # 声明容器端口为8080
    - containerPort: 8080
  # 启动探测
  startupProbe:
    # 探测8080端口是否存在,存在则成功
    tcpSocket:
      port: 8080
    initialDelaySeconds: 20 #容器启动后多久开始探测
    periodSeconds: 20 #执行探测的时间间隔
    timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
    successThreshold: 1 #成功多少次才算成功
    failureThreshold: 3 #失败多少次才算失败
apiVersion: v1
kind: Pod
metadata:
  name: startupprobe
spec:
  containers:
  - name: startup
    image: xianchao/tomcat-8.5-jre8:v1
    imagePullPolicy: IfNotPresent
    ports:   
    - containerPort: 8080
  # 启动探测  
  startupProbe:
    # 探测http服务是否正常,正常则成功
    httpGet:
      path: /
      port: 8080
    initialDelaySeconds: 20 #容器启动后多久开始探测
    periodSeconds: 20 #执行探测的时间间隔
    timeoutSeconds: 10 #探针执行检测请求后,等待响应的超时时间
    successThreshold: 1 #成功多少次才算成功
    failureThreshold: 3 #失败多少次才算失败

livenessprobe 存活探测

### 容器在初始化后,首先创建一个 /tmp/healthy 文件,然后执行睡眠命令,睡眠 30 秒,到时间后执行删除 /tmp/healthy 文件命令。而设置的存活探针检检测方式为执行 shell 命令,用 cat 命令输出 healthy 文件的内容,如果能成功执行这条命令,存活探针就认为探测成功,否则探测失败。在前 30 秒内,由于文件存在,所以存活探针探测时执行 cat /tmp/healthy 命令成功执行。30 秒后 healthy 文件被删除,所以执行命令失败,Kubernetes 会根据 Pod 设置的重启策略来判断,是否重启 Pod。

apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec
  labels:
    app: liveness
spec:
  containers:
  - name: liveness
    image: busybox:1.28
    imagePullPolicy: IfNotPresent
    #创建测试探针探测的文件
    args:                       
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
  # 存活探测
  livenessProbe:
    initialDelaySeconds: 10   #延迟检测时间
    periodSeconds: 5          #检测时间间隔
    # 使用exec探针,如果cat /tmp/healthy返回错误请求,则说明异常。连续两次都成功,说明正常
    exec:
      command:
      - cat
      - /tmp/healthy
### 上面 Pod 中启动的容器是一个 SpringBoot 应用,其中引用了 Actuator 组件,提供了 /actuator/health 健康检查地址,存活探针可以使用 HTTPGet 方式向服务发起请求,请求 8081 端口的 /actuator/health 路径来进行存活判断:任何大于或等于200且小于400的代码表示探测成功。任何其他代码表示失败。

apiVersion: v1
kind: Pod
metadata:
  name: liveness-http
  labels:
    test: liveness
spec:
  containers:
  - name: liveness
    image: mydlqclub/springboot-helloworld:0.0.1
    imagePullPolicy: IfNotPresent
  livenessProbe:
    initialDelaySeconds: 20   #延迟加载时间
    periodSeconds: 5          #重试时间间隔
    timeoutSeconds: 10        #超时时间设置
    httpGet:
      scheme: HTTP
      port: 8081
      path: /actuator/health
        
        
### httpGet相关字段
- scheme: 用于连接host的协议,默认为HTTP。
- host:要连接的主机名,默认为Pod IP,可以在http request head中设置host头部。
- port:容器上要访问端口号或名称。
- path:http服务器上的访问URI。
- httpHeaders:自定义HTTP请求headers,HTTP允许重复headers。
# TCP 检查方式和 HTTP 检查方式非常相似,在容器启动 initialDelaySeconds 参数设定的时间后,kubelet 将发送第一个 livenessProbe 探针,尝试连接容器的 80 端口,如果连接失败则将杀死 Pod 重启容器。

apiVersion: v1
kind: Pod
metadata:
  name: liveness-tcp
  labels:
    app: liveness
spec:
  containers:
  - name: liveness
    image: docker.io/xianchao/nginx:v1
    imagePullPolicy: IfNotPresent
  livenessProbe:
    initialDelaySeconds: 15
    periodSeconds: 20
    tcpSocket:
      port: 80

readnessprobe

Pod 的ReadinessProbe 探针使用方式和 LivenessProbe 探针探测方法一样,也是支持三种,只是一个是用于探测应用的存活,一个是判断是否对外提供流量的条件。

# 容器启动正常后,启动service服务并访问服务看能否正常,能否正常提供流量等


apiVersion: v1
kind: Service
metadata:
  name: springboot
  labels:
    app: springboot
spec:
  type: NodePort
  ports:
  - name: server
    port: 8080
    targetPort: 8080
    nodePort: 31180
  - name: management
    port: 8081
    targetPort: 8081
    nodePort: 31181
  selector:
    app: springboot
---
apiVersion: v1
kind: Pod
metadata:
  name: springboot
  labels:
    app: springboot
spec:
  containers:
  - name: springboot
    image: mydlqclub/springboot-helloworld:0.0.1
    imagePullPolicy: IfNotPresent
    ports:
    - name: server
      containerPort: 8080
    - name: management
      containerPort: 8081
  readinessProbe:
    initialDelaySeconds: 20   
    periodSeconds: 5          
    timeoutSeconds: 10   
    httpGet:
      scheme: HTTP
      port: 8081
      path: /actuator/health

几种探测混合使用

# 先执行startupPorbe,成功后再同步并行livenessProbe和readinessProbe

apiVersion: v1
kind: Service
metadata:
  name: springboot-live
  labels:
    app: springboot
spec:
  type: NodePort
  ports:
  - name: server
    port: 8080
    targetPort: 8080
    nodePort: 31180
  - name: management
    port: 8081
    targetPort: 8081
    nodePort: 31181
  selector:
    app: springboot
---
apiVersion: v1
kind: Pod
metadata:
  name: springboot-live
  labels:
    app: springboot
spec:
  containers:
  - name: springboot
    image: mydlqclub/springboot-helloworld:0.0.1
    imagePullPolicy: IfNotPresent
    ports:
    - name: server
      containerPort: 8080
    - name: management
      containerPort: 8081
    # 探测服务是否能提供对应的功能,成功则加到service资源
    readinessProbe:
      initialDelaySeconds: 20   
      periodSeconds: 5          
      timeoutSeconds: 10   
      httpGet:
        scheme: HTTP
        port: 8081
        path: /actuator/health
    # 探测服务是否存活
    # 如果在容器内kill掉进程,就会触发
    livenessProbe:
      initialDelaySeconds: 20
      periodSeconds: 5
      timeoutSeconds: 10
      httpGet:
        scheme: HTTP
        port: 8081
        path: /actuator/health
    # 探测服务是否存在
    # 探测服务是否返回正常的状态码
    startupProbe:
      initialDelaySeconds: 20
      periodSeconds: 5
      timeoutSeconds: 10
      httpGet:
        scheme: HTTP
        port: 8081
        path: /actuator/health

总结:

pod在整个生命周期中有非常多的用户行为:

**1、**初始化容器完成初始化

**2、**主容器启动后可以做启动后钩子主容器结束前可以做结束前钩子

**3、**在主容器运行中可以做一些健康检测,如startupprobe、livenessprobe,readnessprobe。livenessprobe和readnessprobe没有先后顺序之分。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值