目录
前言
Pod生命周期
Pod 相位 状态值
挂起(Pending)
运行中(Running)
成功(Succeeded)
失败(Failed)
未知(Unknown)
Init Containers
Init Contianers的作用
Init Contianers实验
特殊说明
总结
写在后面
前面我们部署了k8s容器环境,也知道了怎么书写数据自己的Pod,那本节我们就一起来学习Pod的生命周期。这个是重点来的哦,因为在实际运用的过程中,对于Pod生命周期每个阶段的进行检测,进而分析和排错。
上图主要描述了在容器环境初始化完成之后,pod从创建到退出,中间这段时间经历的过程;
从大的方向上看,pod生命周期分两个阶段:
在 Pod 启动时,pause容器总是创建的第一个容器。每个pod中都存在一个pause容器。这个是k8s自动创建的。
对于Init Container来说,一个pod中可以定义多个初始化容器,他们必须是串行执行,只有当所有的初始化容器执行完后,对应的主容器才会启动;如上图所示,会按顺序把1、2、3的InitC都执行完成之后,才进入Main Container阶段
Main Container生命周期又分为三个阶段:
readness——就绪检测,检测成功后,Pod状态改为Ready
liveness——生存检测,
对于对容器的健康状态检查和就绪状态检查,我们也可以定义开始检查的延迟时长;因为有些容器存在容器显示running状态,但内部程序还没有初始化,如果立即做健康状态检查,可能存在健康状态为不健康,从而导致容器重启的状况;
首先在介绍 Pod 的生命周期之前,我们先了解下 Pod 的状态,因为 Pod 状态可以反映出当前我们的 Pod 的具体状态信息,也是我们分析排错的一个必备的方式。
我们可以通过命令kubectl explain pod.status
查看到
Pod已被K8s系统接受,但有一个或者多个容器镜像尚未创建,等待时间包括调度Pod的时间和通过网络下载镜像的时间。这可能需要花点时间。
该Pod已经绑定到了一个节点上,Pod中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或者重启状态。
Pod中所有的容器都被成功终止并且不会再重启。
Pod中所有容器都已经终止,并且至少有一个容器是因为失败终止。也就是说,至少有一个容器以非0状态退出或者被系统终止。
因为某些原因无法取得Pod的状态,通常是因为与Pod所在主机通信失败。
Init Containers是在Pod的主容器启动之前要运行的容器,主要是做一些主容器的前置工作。
一个Pod能够具有多个容器,应用运行在应用容器里面,但是该Pod中可能有一个或多个先于应用容器启动的Init容器。
Init容器与普通容器非常像,除了以下两点:
注意:如果Pod的Init容器失败,Kubernetes会不断重启该Pod,知道Init容器成功位置。然而,如果Pod对应的重启策略restartPolicy为Never时,Pod不会重新启动。
因为Init容器具有与应用程序容器分离的单独镜像,所以它们的启动相关代码具有如下优势:
下面我们通过实际例子来进一步认识init containers。
# init-pod.yaml
# author: 攻城狮白玉
apiVersion: v1
kind: Pod
metadata:
name: baiyu-pod
namespace: baiyu-learn-k8s
labels:
app: baiyu-app
version: v1
spec:
containers:
- name: baiyu-app-container
image: busybox:1.32
command: ['sh', '-c', 'echo The app is running && sleep 3600']
initContainers:
- name: init-baiyu-service
image: busybox:1.32
command: ['sh', '-c','until nslookup baiyu-service; do echo waiting for baiyu-service; sleep 2;done;']
- name: init-baiyu-db
image: busybox:1.32
command: ['sh', '-c', 'until nslookup baiyu-db; do echo waiting for baiyu-db; sleep 2; done;']
上面的yaml,运行了一个pod。里面有一个main container,有两个init container
kubectl create -f init-pod.yaml
然后执行kubectl get pod -n baiyu-learn-k8s -o wide -w
查看容器状态
此时无论多久,上面这个容器都不会变成running状态的。这是因为我们写了两个init container的条件没有满足。
第一个init container里面,我们执行了下面这句命令,表示在我们能解析到有这个baiyu-service
名称的网络服务就打破循环。
until nslookup baiyu-service;
do
echo waiting for baiyu-service;
sleep 2;
done;
此处补充个小知识点,便是Linux中until的用法。
until跟while类似,都是一个固定循环。
但是until跟while又有不同,则是它们的条件满足不同。
until是直到条件为真时,打破循环。而while是条件为真时一直循环,条件为假时打破循环。
此时,我们通过命令
kubectl logs baiyu-pod -n baiyu-learn-k8s --container init-baiyu-service
查看pod中的init-baiyu-service容器的日志,可以发现它一直在循环检测服务是否起来
为了满足我们init-pod中的init container的条件,我们准备了以下脚本实现两个service,用于满足init C的条件。
# init-service.yaml
# author: 攻城狮白玉
kind: Service
apiVersion: v1
metadata:
name: baiyu-service
namespace: baiyu-learn-k8s
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
---
kind: Service
apiVersion: v1
metadata:
name: baiyu-db
namespace: baiyu-learn-k8s
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
执行命令启动脚本kubectl apply -f init-service.yaml
使用kubectl get pod -n baiyu-learn-k8s -o wide -w
查看我们的pod的状态。结果如下图所示,在两个init容器执行完成之后,main 容器进行执行,最终Pod完成启动Pod状态变为Running
restartPolicy
设置为Always
,Init容器失败时会使用RestartPolicy策略Ready
状态。Init容器的端口将不会再Service中进行聚集。正在初始化中的Pod处于Pending
状态,但应该会将Initializing
状态设置为truereadinessProbe
,因为Init容器无法定义不同于完成(completion)的就绪(readiness)之外的其他状态。这会在验证过程中强制执行。本文介绍了k8s整体容器的生命周期以及Init Container的基本概念和作用,并通过一个实战例子进一步加深了各位同学对init Containers的理解。限于篇幅,并没有把容器的生命周期所有知识点写完,下一篇我会介绍容器生命周期的两个探针,readness和liveness。以及启停时的动作钩子
如果觉得有用的话,麻烦一键三连支持一下攻城狮白玉,并把本文分享给更多的小伙伴。你的简单支持,我的无限创作动力