和一个个独立的应用容器一样,Pod 也被认为是相对临时性(而不是长期存在)的实体。 Pod 会被创建、赋予一个唯一的 ID(UID),并被调度到节点,并在终止(根据重启策略)或删除之前一直运行在该节点。
如果一个节点死掉了,调度到该节点 的 Pod 也被计划在给定超时期限结束后删除。
Pod 自身不具有自愈能力。如果 Pod 被调度到某节点 而该节点之后失效,或者调度操作本身失效,Pod 会被删除;与此类似,Pod 无法在节点资源 耗尽或者节点维护期间继续存活。Kubernetes 使用一种高级抽象,称作控制器,来管理这些相对而言可随时丢弃的 Pod 实例。
任何给定的 Pod (由 UID 定义)从不会被“重新调度(rescheduled)”到不同的节点; 相反,这一 Pod 可以被一个新的、几乎完全相同的 Pod 替换掉。 如果需要,新 Pod 的名字可以不变,但是其 UID 会不同。
如果某物声称其生命期与某 Pod 相同,例如存储卷, 这就意味着该对象在此 Pod (UID 亦相同)存在期间也一直存在。 如果 Pod 因为任何原因被删除,甚至某完全相同的替代 Pod 被创建时, 这个相关的对象(例如这里的卷)也会被删除并重建。
1)Pod创建过程;
2)运行初始化容器(init container)过程;
3)运行主容器(main container):
① 容器启动后钩子函数(post start)、容器终止前钩子函数(pre stop)
②容器存活性探测(liveness probe)、就绪性探测(readiness probe)
4) Pod终止过程。
取值
描述
**Pending**
(挂起)
Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间。
Running
(运行中)
Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。
Succeeded
(成功)
Pod 中的所有容器都已成功终止,并且不会再重启。
Failed
(失败)
Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。
Unknown
(未知)
因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。
如果某节点死掉或者与集群中其他节点失联,Kubernetes 会实施一种策略,将失去的节点上运行的所有 Pod 的取值设置为 Failed。
1、kubectl向apiserver发送一个创建pod的请求
2、apiserver收到请求后生成一个包含创建信息的yaml文件并写入etcd。
3、scheduler发现有新的pod要创建,经过计算再找出最适合创建的node进行创建。
4、node节点的kubelet接收到创建pod的信息后调用docker启动容器,然后将结果发送给apiserver
5、apiserver将接收到pod的信息存入etcd
Pod 有一个 PodStatus 对象,其中包含一个 PodConditions 数组。Pod 可能通过也可能未通过其中的一些状况测试。
PodScheduled
:Pod 已经被调度到某节点;ContainersReady
:Pod 中所有容器都已就绪;Initialized
:所有的 Init 容器 都已成功完成;Ready
:Pod 可以为请求提供服务,并且应该被添加到对应服务的负载均衡池中。字段名称
描述
type
Pod 状况的名称
status
表明该状况是否适用,可能的取值有 "True
", "False
" 或 "Unknown
"
lastProbeTime
上次探测 Pod 状况时的时间戳
lastTransitionTime
Pod 上次从一种状态转换到另一种状态时的时间戳
reason
机器可读的、驼峰编码(UpperCamelCase)的文字,表述上次状况变化的原因
message
人类可读的消息,给出上次状态转换的详细信息
初始化容器Init Container是在Pod的主容器启动之前要运行的容器,主要是做一些主容器的前置工作,可以是一个 它具有两大特征:
初始化容器必须运行完成直至结束,如果某个初始化容器运行失败,那么Kubernetes需要重启它直至成功完成。
初始化容器必须按照定义的顺序执行,当且仅当前一个成功之后,后面一个才能运行。
初始化容器有很多应用场景,下面列出的是最常见的几种:
提供主容器镜像中不具备的工具程序或自定义代码。
初始化容器要先于应用容器串行启动并运行完成;因此可用于延后应用容器的启动直至其依赖的条件得到满足。
例:
我们先创建一个init-pod.yml 文件
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
然后创建pod并查看: kubectl create -f init-pod.yml
[root@master ~]# kubectl create -f init-pod.yml
pod/myapp-pod created
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 23s
nginx-6799fc88d8-648cn 1/1 Running 0 48d
此时myapp-pod显示正在init初始化,我们describe看一下这个pod状态
[root@master ~]# kubectl describe pods myapp-pod
Name: myapp-pod
Namespace: default
Priority: 0
Node: node1/192.168.248.128
Start Time: Mon, 27 Jun 2022 15:49:59 +0800
Labels: app=myapp
Annotations: cni.projectcalico.org/containerID: bdead7238a0b177ce59049c3d13a180dadd5c867ad6eb3f0aa06710585eac8c5
cni.projectcalico.org/podIP: 10.101.149.3/32
cni.projectcalico.org/podIPs: 10.101.149.3/32
Status: Pending
IP: 10.101.149.3
IPs:
IP: 10.101.149.3
Init Containers:
init-myservice:
Container ID: docker://b2bcc9e7e88702bdf2fbd53fdfc5e70063d5fc3419338770f14b8b48804e4800
Image: busybox
Image ID: docker-pullable://busybox@sha256:5acba83a746c7608ed544dc1533b87c737a0b0fb730301639a0179f9344b1678
Port:
Host Port:
Command:
sh
-c
until nslookup myservice; do echo waiting from myservice; sleep 2s ;done
State: Running
Started: Mon, 27 Jun 2022 15:50:25 +0800
Ready: False
Restart Count: 0
Environment:
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-trqgw (ro)
mydb-containers:
Container ID:
Image: busybox
Image ID:
Port:
Host Port:
Command:
sh
-c
until nslookup mydb; do echo waiting from mydb; sleep 2s; done
State: Waiting
Reason: PodInitializing
Ready: False
Restart Count: 0
Environment:
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-trqgw (ro)
Containers:
myapp-containers:
Container ID:
Image: busybox
Image ID:
Port:
Host Port:
Command:
sh
-c
echo the app is running && sleep 600s
State: Waiting
Reason: PodInitializing
Ready: False
Restart Count: 0
Environment:
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-trqgw (ro)
Conditions:
Type Status
Initialized False
Ready False
ContainersReady False
PodScheduled True
Volumes:
kube-api-access-trqgw:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional:
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors:
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 6m12s default-scheduler Successfully assigned default/myapp-pod to node1
Normal Pulling 6m11s kubelet Pulling image "busybox"
Normal Pulled 5m46s kubelet Successfully pulled image "busybox" in 24.671646739s
Normal Created 5m46s kubelet Created container init-myservice
Normal Started 5m46s kubelet Started container init-myservice
此时正在启动init-myservice,由于我们还没没有创建myservice,所以init容器就一直在重启,我们看一下日志
[root@master ~]# kubectl logs myapp-pod -c init-myservice
Server: 10.96.0.10
Address: 10.96.0.10:53
** server can't find myservice.default.svc.cluster.local: NXDOMAIN
*** Can't find myservice.svc.cluster.local: No answer
*** Can't find myservice.cluster.local: No answer
*** Can't find myservice.localdomain: No answer
*** Can't find myservice.default.svc.cluster.local: No answer
*** Can't find myservice.svc.cluster.local: No answer
*** Can't find myservice.cluster.local: No answer
*** Can't find myservice.localdomain: No answer
waiting from myservice
Server: 10.96.0.10
Address: 10.96.0.10:53
** server can't find myservice.default.svc.cluster.local: NXDOMAIN
*** Can't find myservice.svc.cluster.local: No answer
*** Can't find myservice.cluster.local: No answer
*** Can't find myservice.localdomain: No answer
*** Can't find myservice.default.svc.cluster.local: No answer
*** Can't find myservice.svc.cluster.local: No answer
*** Can't find myservice.cluster.local: No answer
*** Can't find myservice.localdomain: No answer
waiting from myservice
Server: 10.96.0.10
Address: 10.96.0.10:53
** server can't find myservice.default.svc.cluster.local: NXDOMAIN
*** Can't find myservice.svc.cluster.local: No answer
*** Can't find myservice.cluster.local: No answer
*** Can't find myservice.localdomain: No answer
*** Can't find myservice.default.svc.cluster.local: No answer
*** Can't find myservice.svc.cluster.local: No answer
*** Can't find myservice.cluster.local: No answer
*** Can't find myservice.localdomain: No answer
waiting from myservice
Server: 10.96.0.10
Address: 10.96.0.10:53
** server can't find myservice.default.svc.cluster.local: NXDOMAIN
*** Can't find myservice.svc.cluster.local: No answer
*** Can't find myservice.cluster.local: No answer
*** Can't find myservice.localdomain: No answer
*** Can't find myservice.default.svc.cluster.local: No answer
*** Can't find myservice.svc.cluster.local: No answer
*** Can't find myservice.cluster.local: No answer
*** Can't find myservice.localdomain: No answer
waiting from myservice
通过日志发现myservice没有启动,所以init-myservice一直在重启,我们再将myservice创建启动后再看
[root@master ~]# cat myservice.yml
kind: Service
apiVersion: v1
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
[root@master ~]# kubectl create -f myservice.yml
service/myservice created
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:1/2 0 22m
nginx-6799fc88d8-648cn 1/1 Running 0 49d
此时发现STATUS变成了 Init:1/2 ,说明init-myservice初始化已经完成,我们再创建mydb启动看一下
[root@master ~]# cat mydb.yml
kind: Service
apiVersion: v1
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
[root@master ~]# kubectl create -f mydb.yml
service/mydb created
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 PodInitializing 0 29m
nginx-6799fc88d8-648cn 1/1 Running 0 49d
这次init容器都已经初始化完成并正在启动
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 32m
nginx-6799fc88d8-648cn 1/1 Running 0 49d
init初始化完成并启动容器成功
init初始化特殊说明:
在pod的启动过程中,init容器会按顺序在网络和数据卷启动之后启动,每个容器启动必须在上个容器成功退出后执行。
如果pod重启,那init容器必须重新执行
对init容器的spec修改被限制在image字段,修改其他字段不会生效,更改init容器的image字段,等于重启该pod。
为什么要有探针,因为探针可以探测pod当中的容器是否正常运行,我们知道容器启动,业务程序未必正常,因此,我们可以用livenessProbe探针来探测业务是否正常,而对于我们新建的pod如果不做就绪性探测,会被前端的service立刻关联,这样有可能导致部分客户端无法正常访问,所欲对于k8s探针主要分为两种:
1、ExecAction:在容器内执行指定命令,如果命令退出时返回码为0则认为诊断成功。
2、TCPsocketAction:对执定端口上的容器的IP地址进行tcp检查,如果端口打开则认为是诊断成功的。
3、HTTPGetAction:对指定的端口和路径上的容器的IP地址执行HTTP get请求。如果响应的状态码大于200且小于400,则被诊断认为是成功的。
Success(成功): 容器通过了诊断。
Failuer(失败): 容器未通过诊断。
Unknown(未知):诊断失败,因此不会采取任何行动。
例1:ExecAction
[root@master ~]# cat livenessprobe-exec.yaml
apiVersion: v1
kind: Pod
metadata:
name: livenessprobe-pod
namespace: default
labels:
app: liveness
spec:
containers:
验证:可以看到由于文件被删除已经crash了,并且重启了6次
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
livenessprobe-pod 0/1 CrashLoopBackOff 6 10m
例2:HttpGetAction
[root@master ~]# cat livenessprobe-gethttp.yaml
apiVersion: v1
kind: Pod
metadata:
name: livenessprobe-gethttp-pod
namespace: default
labels:
app: liveness-gethttp
spec:
containers:
验证:可以看到容器被重启了一次然后就一直正常运行
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
livenessprobe-gethttp-pod 1/1 Running 1 14m
[root@master ~]# cat readinessprobe-gethttp.yaml
apiVersion: v1
kind: Pod
metadata:
name: livenessprobe-gethttp-pod
namespace: default
labels:
app: liveness-gethttp
spec:
containers:
验证:
1.连入容器删除index.html文件
[root@master ~]# kubectl exec -it livenessprobe-gethttp-pod -- /bin/bash
root@livenessprobe-gethttp-pod:/# cd /usr/share/nginx/html/
root@livenessprobe-gethttp-pod:/usr/share/nginx/html# ls
50x.html index.html
root@livenessprobe-gethttp-pod:/usr/share/nginx/html# rm -rf index.html
root@livenessprobe-gethttp-pod:/usr/share/nginx/html# exit
2.查看pod状态
[root@master ~]# kubectl get pods -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
livenessprobe-gethttp-pod 1/1 Running 0 6s 10.244.1.38 node1
livenessprobe-gethttp-pod 0/1 Running 0 24s 10.244.1.38 node1
3.随后我们在在容器里创建出index.html文件,然后在观察pod
[root@master ~]# kubectl get pods -o wide -w
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
livenessprobe-gethttp-pod 1/1 Running 0 6s 10.244.1.38 node1
livenessprobe-gethttp-pod 0/1 Running 0 24s 10.244.1.38 node1
livenessprobe-gethttp-pod 1/1 Running 0 2m48s 10.244.1.38 node1
1. 用户向apiserver发送删除pod对象的命令
2. apiserver中的pod对象信息会随着时间的推移而更新,在宽限期内(默认是30s),pod被视为dead
3. 将pod标记为terminating(正在删除)状态
4. kubelet在监控到pod对象转为terminating状态的同时启动pod关闭过程
5. 端点控制器监控到pod对象的关闭行为时将其从所有匹配到此端点的service资源的端点列表中移除
6. 如果当前pod对象定义了 preStop钩子处理器,则在其标记为terminating后即会以同步的方式启动执行
7. pod对象中的容器进程收到停止信号
8. 宽限期结束后,若pod中还存在仍在运行的进程,那么pod对象会收到立即终止的信号
9. kubelet请求apiserver将此pod资源的宽限期设置为0,从而完成删除操作,此时pod对于用户已不可见
手机扫一扫
移动阅读更方便
你可能感兴趣的文章