实验环境:
1、win10,vmwrokstation虚机;
2、k8s集群:3台centos7.6 1810虚机,1个master节点,2个node节点
k8s version:v1.22.2
containerd://1.5.5
前面我们已经了解了 Pod 的设计原理,接下来我们来了解下 Pod 的生命周期。下图展示了一个 Pod 的完整生命周期过程,其中包含 Init Container
、Pod Hook
、健康检查
三个主要部分,接下来我们就来分别介绍影响 Pod 生命周期的部分:
首先在介绍 Pod 的生命周期之前,我们先了解下 Pod 的状态,因为 Pod 状态可以反应出当前我们的 Pod 的具体状态信息,也是我们分析排错的一个必备的方式。
首先先了解下 Pod 的状态值,我们可以通过 kubectl explain pod.status
命令来了解关于 Pod 状态的一些信息,Pod 的状态定义在 PodStatus
对象中,其中有一个 phase
字段,下面是 phase
的可能取值:
[root@master1 ~]#kubectl explain pod.status
phase <string>
The phase of a Pod is a simple, high-level summary of where the Pod is in
its lifecycle. The conditions array, the reason and message fields, and the
individual container status arrays contain more detail about the pod's
status. There are five possible phase values:
Pending: The pod has been accepted by the Kubernetes system, but one or
more of the container images has not been created. This includes time
before being scheduled as well as time spent downloading images over the
network, which could take a while.
Running: The pod has been bound to a
node, and all of the containers have been created. At least one container
is still running, or is in the process of starting or restarting.
Succeeded: All containers in the pod have terminated in success, and will
not be restarted.
Failed: All containers in the pod have terminated, and at
least one container has terminated in failure. The container either exited
with non-zero status or was terminated by the system.
Unknown: For some
reason the state of the pod could not be obtained, typically due to an
error in communicating with the host of the pod.
Pod 中的所有容器都被成功终止,并且不会再重启
0
状态退出或者被系统终止除此之外,PodStatus
对象中还包含一个 PodCondition
的数组,里面包含的属性有:
[root@master1 ~]#kubectl explain pod.status.conditions
FIELDS:
lastProbeTime <string>
Last time we probed the condition.
lastTransitionTime <string>
Last time the condition transitioned from one status to another.
message <string>
Human-readable message indicating details about last transition.
reason <string>
Unique, one-word, CamelCase reason for the condition's last transition.
status <string> -required-
Status is the status of the condition. Can be True, False, Unknown. More
info:
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions
type <string> -required-
Type is the type of the condition. More info:
https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-conditions
[root@master1 ~]#
init containers
已经启动成功)注意:阳明大佬说过,这个pod.status.conditions在排错上还是很有用的;
我们可以通过配置 restartPolicy
字段来设置 Pod 中所有容器的重启策略,其可能值为 Always
、OnFailure
和 Never
,默认值为 Always
,restartPolicy
指通过 kubelet 在同一节点上重新启动容器。通过 kubelet 重新启动的退出容器将以指数增加延迟(10s,20s,40s…)重新启动,上限为 5 分钟,并在成功执行 10 分钟后重置(这个是什么意思??)。不同类型的的控制器可以控制 Pod 的重启策略:
Job
:适用于一次性任务如批量计算,任务结束后 Pod 会被此类控制器清除。Job 的重启策略只能是"OnFailure"
或者"Never"
。ReplicaSet
、Deployment
:此类控制器希望 Pod 一直运行下去,它们的重启策略只能是"Always"
。DaemonSet
:每个节点上启动一个 Pod,很明显此类控制器的重启策略也应该是"Always"
。注意:个人对这里的"并在成功执行 10 分钟后重置"不是很懂…………??
注意:
InitCongtainer和InfraContainer是同一个容器的吧?不是的;
一个 Pod 里面的所有容器是共享数据卷和
Network Namespace
的;
了解了 Pod 状态后,首先来了解下 Pod 中最新启动的 Init Container
,也就是我们平时常说的初始化容器。Init Container
就是用来做初始化工作的容器,可以是一个或者多个,如果有多个的话,这些容器会按定义的顺序依次执行。我们知道一个 Pod 里面的所有容器是共享数据卷和 Network Namespace的,所以 Init Container
里面产生的数据可以被主容器使用到。从上面的 Pod 生命周期的图中可以看出初始化容器是独立与主容器之外的,只有所有的`初始化容器执行完之后,主容器才会被启动。那么初始化容器有哪些应用场景呢:
**等待其他模块 Ready:**这个可以用来解决服务之间的依赖问题,比如我们有一个 Web 服务,该服务又依赖于另外一个数据库服务,但是在我们启动这个 Web 服务的时候我们并不能保证依赖的这个数据库服务就已经启动起来了,所以可能会出现一段时间内 Web 服务连接数据库异常。要解决这个问题的话我们就可以在 Web 服务的 Pod 中使用一个 InitContainer
,在这个初始化容器中去检查数据库是否已经准备好了,准备好了过后初始化容器就结束退出,然后我们主容器的 Web 服务才被启动起来,这个时候去连接数据库就不会有问题了。
**做初始化配置:**比如集群里检测所有已经存在的成员节点,为主容器准备好集群的配置信息,这样主容器起来后就能用这个配置信息加入集群。
比如说:我们的一个数据挂载。
比如说,我们把main container里面的一个volume给挂载到宿主机上去,但是,有可能我们这个主容器,容器它不是包装了一个镜像,镜像里面很有可能给它添加了一个非root用户,那么主容器里面,它是一个非root的用户,然后我们把数据挂载到宿主机上的时候,宿主机上有个root用户,那么这个时候,这个root用户说不是就不能访问到这个数据目录了,因为他们的权限不同。那么这个时候,其实我们是可以添加一个初始化容器的,去把我们对应数据目录的权限去做一个chageown,去把它修改为主容器里面的user:group,这样就可以正常去访问了。因为我们知道,linux下你的用户和用户组如果不一样的话,你肯定是没办法去写入的。
其它场景:如将 Pod 注册到一个中央数据库、配置中心等。
❤️实验测试:
比如现在我们来实现一个功能,在 Nginx Pod 启动之前去重新初始化首页内容,如下所示的资源清单:(init-pod.yaml)
[root@master1 ~]#vim init-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
volumes:
- name: workdir
emptyDir: {} #注意:这个是emptyDir{}类型的存储,你可认为是一种临时存储
initContainers:
- name: install
image: busybox
command:
- wget
- "-O"
- "/work-dir/index.html"
- http://www.baidu.com # https
volumeMounts:
- name: workdir
mountPath: "/work-dir"
containers:
- name: web
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
上面的资源清单中我们首先在 Pod 顶层声明了一个名为 workdir 的 Volume
,前面我们用了 hostPath 的模式,这里我们使用的是 emptyDir{}
,这个是一个临时的目录,数据会保存在 kubelet 的工作目录下面,生命周期等同于 Pod 的生命周期。
然后我们定义了一个初始化容器,该容器会下载一个 html 文件到 /work-dir
目录下面,但是由于我们又将该目录声明挂载到了全局的 Volume,同样的主容器 nginx 也将目录 /usr/share/nginx/html
声明挂载到了全局的 Volume,所以在主容器的该目录下面会同步初始化容器中创建的 index.html
文件。
直接创建上面的 Pod:
[root@master1 ~]#kubectl apply -f init-demo.yaml
pod/init-demo created
创建完成后可以查看该 Pod 的状态:
[root@master1 ~]#kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
init-demo 0/1 Init:0/1 0 11s <none> node1 <none> <none>
可以发现 Pod 现在的状态处于 Init:0/1
状态,意思就是现在第一个初始化容器还在执行过程中,此时我们可以查看 Pod 的详细信息:
[root@master1 ~]#kubectl describe pod init-demo
Name: init-demo
Namespace: default
Priority: 0
Node: node1/172.29.9.52
Start Time: Sat, 06 Nov 2021 17:36:21 +0800
Labels: <none>
Annotations: <none>
Status: Running
IP: 10.244.1.6
IPs:
IP: 10.244.1.6
Init Containers:
install:
Container ID: containerd://7b8ae516ae003458e439f9efe9d31c9e33b44593e827b2518007a7dbf103f69e
Image: busybox
Image ID: docker.io/library/busybox@sha256:15e927f78df2cc772b70713543d6b651e3cd8370abf86b2ea4644a9fba21107f
Port: <none>
Host Port: <none>
Command:
wget
-O
/work-dir/index.html
http://www.baidu.com
State: Terminated
Reason: Completed
Exit Code: 0
Started: Sat, 06 Nov 2021 17:36:39 +0800
Finished: Sat, 06 Nov 2021 17:36:39 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-wzm78 (ro)
/work-dir from workdir (rw)
Containers:
web:
Container ID: containerd://194aaf1d7c003029d1d89bafd946de1d919efa15f0e1032184fc4b95d4e05ae8
Image: nginx
Image ID: docker.io/library/nginx@sha256:644a70516a26004c97d0d85c7fe1d0c3a67ea8ab7ddf4aff193d9f301670cf36
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Sat, 06 Nov 2021 17:36:55 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/usr/share/nginx/html from workdir (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-wzm78 (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
workdir:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
SizeLimit: <unset>
kube-api-access-wzm78:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 119s default-scheduler Successfully assigned default/init-demo to node1
Normal Pulling 118s kubelet Pulling image "busybox"
Normal Pulled 101s kubelet Successfully pulled image "busybox" in 16.310146437s
Normal Created 101s kubelet Created container install
Normal Started 101s kubelet Started container install
Normal Pulling 100s kubelet Pulling image "nginx"
Normal Pulled 85s kubelet Successfully pulled image "nginx" in 15.212796527s
Normal Created 85s kubelet Created container web
Normal Started 85s kubelet Started container web
[root@master1 ~]#
从上面的描述信息里面可以看到初始化容器已经启动了,现在处于 Running
状态,**所以还需要稍等,到初始化容器执行完成后退出初始化容器会变成 Completed
状态,然后才会启动主容器。**待到主容器也启动完成后,Pod 就会变成Running
状态,然后我们去访问下 Pod 主页,验证下是否有我们初始化容器中下载的页面信息:
这里也需要注意下:
[root@master1 ~]#kubectl get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
init-demo 1/1 Running 0 3m3s 10.244.1.6 node1 <none> <none>
[root@master1 ~]#curl 10.244.1.6
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc>