前面我们已经了解了POD的设计原理,接下来我们了解POD的声明周期,init container,pod hook,health 三个部分
首先介绍pod的声明周期之前,我们先了解一下pod的状态,因为pod状态可以反应出当前我们的pod具体状态信息。
[root@master1 ~]# kubectl explain pod.status
KIND: Pod
VERSION: v1
RESOURCE: status <Object>
DESCRIPTION:
Most recently observed status of the pod. This data may not be up to date.
Populated by the system. Read-only. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
kubectl explain pod.status 命令来了解关于pod状态的一些信息,pod的状态定义在podstatus对象中,其中一个phas字段,
pending 挂起,pod信息已经提交给了集群,但是还没有被调度器调度给适合的节点或者pod里的镜像正在下载
running运行中,该pod已经绑定到了一个节点上,pod中所有的容器都已经被创建,至少有一个容器正在运行,或者正处于启动或重启状态
succeeded成功,pod中所有容器都已经终止了,并且至少一个容器是因为失败终止,也就是说,容器以非0状态退出,或者被系统终止
unknown未知,因为某些原因无法获取POD的状态,通常是因为于pod所在主机通信失败导致的
podstatus对象中包含了一个podcondition的数组,里面包含的数组属性有,
lastprobetime 最后一个探测到pod condition的时间戳
lastTranstitionTime:上次condition从一种状态转到到另一种状态的时间
message:上次condition状态转转的详细描述
reason:condition最后一次转换的原因
status:condition状态类型,可以为true,false,unknown
type:condition类型(podscheduled pod已经被调度到其他的node里,readypod能提供的服务请求,可以被添加到所有可匹配服务的负载均衡池中,initialized 所有init containers已经启动成功 unschedulabele 调度程序发现无法调度pod,例如缺乏资源或其他限制,containersready pod里所有容器都是ready状态)
重启策略
我们可以通过配置restartpolicy 字段来配置pod中所有容器的重启策略,其可能值为always,onfailure,never默认值为always.restartpolicy仅指通过kubelet在同一节点上重新启动容器,通过kubelet重新启动的退出容器将以指数增加延迟重新启动,上线为5min,并在成功执行10min后重置,不通类型的控制器可以控制pod的重启策略。
job适用于一次性任务如批量计算,任务结束后pod会被此类控制器清除,job的重启策略只能是onfailure或者never
replication controller,replicaset , or deployment此类控制器希望pod一直运行下去,他们的重启策略只能是always
daemonset 每个节点启动一个pod,很明显此类控制的重启策略也应该是always
初始化容器
了解了pod状态后,首先来了解下pod中最新启动的init container,也就是我们平常说的初始化容器,init container就是用来初始化工作的容器,可以使一个或者多个,如果有多个的话,这些容器会按照定义的顺序依次执行。我们知道一个pod里面的所有容器是共享数据卷和network namespace的,所以init container 里面产生的数据可以被主容器使用到。从上面的pod声明周期的图中可以看出初始化容器是独立于主容器之外的,只有所有的初始化容器执行完之后主容器才会被启动,那么初始化容器有哪些场景?
等待其他模块ready :这个可以用来解决服务之间的依赖问题,比如我们有一个web服务,该服务又依赖于另外一个数据库服务,但是在我们启动这个web服务的时候我们并不能保证依赖的这个数据库服务就可以启动起来了,所以可能会出现一段时间内的web服务连接数据库异常,要解决这个问题的话,我们就可以在web服务的pod中使用一个initcontaier,在这个初始化容器中去检查数据库是否准备好,准备好之后初始化容器就结束退出,然后我们主容器的web服务才被启动起来,这个时候去连接数据库就不会有问题了。
做初始化配置:比如集群里检测所有已经存在的成员节点,为主容器准备好集群的配置信息,这样主容器起来后就能用这个配置信息加入集群
其他场景,将pod注册到一个中央数据库,配置中心等
[root@master1 ~]# cat init-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
volumes:
- name: workdir
emptyDir: {}
initContainers:
- name: install
image: busybox
command:
- wget
- "-o"
- "/work-dir/index.html"
- https://www.baidu.com
volumeMounts:
- name: workdir
mountPath: "/work-dir"
containers:
- name: web
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
上面的资源清单中我们首先在pod顶层声明了一个名为workdir的volume,emptyDir{}这是一个临时的目录,数据会保存在kubelet的工作目录下,声明周期等同于POD的申明周期
然后我们定义了一个初始化容器,改容器会下载一个html到/work-dir目录下面,但是由于我们又将该目录声明挂载到了全局的volume,同样的主容器nginx也将目录/usr/share/nginx/html声明挂载到了全局的volume,所以在主容器的该目录下面会同步文件。
[root@master1 ~]# kubectl exec -it init-demo /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@init-demo:/# ll /work-dir
可以进入启动的pod内部
从上面的描述信息里面可以看到初始化容器已经启动了,处于running状态,所以还需要稍等,到初始化容器执行完成后退出初始化容器会变成completed状态,然后才会启动主容器,带到主容器也启动完成后,pod就会变成running状态。