kubernetes----资源清单4
资源清单
K8s中所有的内容都抽象为资源,资源实例化之后,叫做对象
简单来说K8S,将多台机器整合成一个平台,控制节点和计算节点
在k8s中,一般使用yaml格式的文件来创建符合我们预期期望的pod,这样的yaml文件我们一般称为资源清单
集群资源分类
名称空间级别
默认系统组件会安装在kube-system名称空间下,默认是default名称空间
工作负载型资源(workload):Pod,ReplicaSet,Deployment,StatefulSet,DaemonSet,Job,CronJob(ReplicationController在v1.11版本被废弃)
- Pod,一个Pod是K8S中的最小部署单元,一个Pod可以拥有一个或多个容器,运行在node节点上
- 只要有POD就会启动PAUSE容器,PAUSE网络栈是lo环回口
- POD同一个POD里面的容器端口不可以冲突
- 一个或多个容器的集合,一组容器一个单元
- 一个pod共享网络命名空间,也可以共享存储,实现数据共享
- 数据不会持久
- RplicationController,RC已经被RS替换了
- ReplicaSet,RS,RS是调度器,管理POD创建,通过标签选择控制POD副本数量
- Deployment,DP-->RS-->Pod,控制RS创建,去创建POD,会更新和回滚
- 更新,新建RS,在RS下创建POD,新创建一个POD,就会删除旧RS下在一个POD,达到滚动更新的状态
- 回滚,启动一个RS,启动版本的POD,在DP中,升级后不会删除旧版本的RS,仅被停用
- StatefulSet,有状态服务的管理器
- DaemonSet ,在每个节点运行一个POD的主键
- 只要有需要,每个node节点都会运行,可以指定某些NODE不会运行POD,打标志污点,默认所有的都会运行一个
- 每个NODE会创建一个守护进程,比如创建容器收集日志或监控等,可以把很多POD放一起,也可以分开
- Job 批处理任务,仅执行一次,保证批处理任务一个或多个结束
- 如果脚本执行错误,是没有办法执行正常退出的,JOB会判断脚本是否是正常即出,直到正常退出为止,或指定次数
- CronJob,批处理任务
服务发现及负载均衡型资源(ServiceDiscovery LoadBalance):Service,Ingress(简单来说就是将服务暴露出去)
- Service,四层
- Ingress,七层
配置与存储型资源:Volume(存储卷)、CSI(容器存储接口,可以扩展各种各样的第三方存储卷)
- Volume,给POD提供持久化数据的能力
- CSI,容器存储接口,只要存储资源符合K8S中的CSI规划,那K8S就可以调用此存储资源
特殊类型的存储卷:ConfigMap(当配置中心来使用的资源类型)、Secret(保存敏感数据)、DownwardAPI(把外部环境中的信息输出给容器)
- ConfigMap,存储配置文件,达到热更新的一种状态
- Secret,加密存储方案,可以保存密码文件,密钥等
- DownwardAPI,通过下载文件接口,调用存储资源
集群级别
不管在什么名称空间,在其他名称空间都可以看的到,一旦定义后,在全集群中都可见或调用
集群级资源:Namespace,Node,Role,ClusterRole,RoleBinding,ClusterRoleBinding
- Namespace,名称空间
- Node,工作节点
- Role,角色
- ClusterRole,
- RoleBinding,
- ClusterRoleBinding
元数据型
比如,HPA,根据CPU的利用率,简单来说主是通过某个指标进行操作
元数据型资源:HPA,PodTemplate,LimitRange
- HPA,基于RS定义,例,CPU利用率大于80%,进行扩容,最大10个,最小2个POD,HPA会一直监控资源利用率,设置一定的阀值,水平扩展
YAML
YAML是一个可读性高,用来表达数据序列的格式。
是一种标记语言,但为了强调这种语言以数据做中心,而不是以标记语言为重点
基本语法
缩进时不允许使用TAB键,只允许使用空格
缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
#标识注释,从这个字符一直到行尾,都会被解释器忽略
YAML支持的数据结构
对象:键值对的集合,又称为映射(mapping)/ 哈希(hashed)/ 字典(dictionary)
数组:一组按次序排列的值,又称为序列(sequence)/ 列表(list)
纯量(scalars):单个的、不可再分的值
常用字段解释
参数名 | 字段类型 | 说明 |
---|---|---|
version | String | 这里是指的是K8S API的版本,目前基本上是v1,可以用kubectl api versions命令查询 |
kind | String | 这里指的是yaml文件定义的资源类型和角色,比如:Pod |
metadata | object | 元数据对象,固走值就写metadata |
metadata.name | string | 元数据对象的名字,这里由我们编写,比如命名Pod的名字 |
metadata.namespace | string | 元数据对象的命名空间,由我们自身定义 |
Sped | Object | 详细定义对象,固定值就写Spec |
spec.containers[] | list | 这里是Spec对象的容器列表定义,是个列表 |
spec.containers[].name | String | 这里定义容器的名字 |
spec.containers.image | String | 这里定义要用到的镜像名称混子了没行 |
spec.containers[].name | String | 定义容器的名字 |
spec.containers[].image | String | 定义要用到的镜像名称 |
spec.containers[].imagePullPolicy | String | 定义鏡像拉取策略,有Always,Never.INotPresent三个值可选(1)Aways:意思是每次都尝试重新拉取镜像(2)Never:表示仅使用本地镜像(3)INotPresent:如果本地有镜像就使用本地镜像,没有就拉取在线镜像。上面三个值都没设置的话,默认是Always. |
spec.containers[].command[] | List | 指定容器启动命令,因为是数组可以指定多个,不指走则使用镜像打包时使用的启动命令。 |
spec.containers[].args[] | List | 指定容器启动命令参数,因为是数组可以指定多个。 |
spec.containers[].workingDir | String | 指定容器的工作目录 |
spec.containers[].volumeMounts[] | List | 指定容器内部的存储卷配置 |
spec.containers[].volumeMounts[].name | String | 指定可以被容器挂载的存储卷的名称 |
spec.containers[].volumeMounts[].mountPath | String | 指定可以被容器挂载的存储卷的路径 |
spec.containers[].volumeMounts[].readOnly | String | 设置存储卷路径的读写模式,ture或者false,string 默认为读写模式 |
spec.containers[].ports[] | List | 指定容器需要用到的端口列表 |
spec.containers[].ports[].name | String | 指定端口名称 |
spec.containers[].ports[].containerPort | String | 指定容器需要监听的端口号 |
spec.containers[].ports[].hostPort | String | 指定容器所在主机需要监听的端口号,默认跟上面containerPort相同,注意设置了hostPort司一台主机无法启动该容器的相同副本(因为主机的端口号不能相同,这样会冲突) |
spec.containers[].ports[].protoco | String | 指定端口协议,支持TCP和UDP,默认值为ТСР |
spec.containers[].env[] | List | 指定容器运行前需设置的环境变量列表 |
spec.containers[].env[].name | String | 指定环境变量名称 |
spec.containers[].env[].value | String | 指定环境变量值 |
spec.containers[].resources | Object | 指定资源限制和资源请求的值(这里开始就是设置容器的资源上限) |
spec.containers[].resources.limits | Object | 指定设置容器运行时资源的运行上限 |
spec.containers[].resources.limits.cpu | Object | 指定CPU的限制,单位为core数,将用于String docker run --cpu-shares參数(这里前面文章Pod资源限制有讲过) |
spec.containers[].resources.limits.memory | String | 指定MEM内存的限制,单位为MIB,GiB |
spec.containers[].resources.requests | Object | 指定容器启动和调度时的限制设置 |
spec.containers[].resources.requests.cpu | String | CPU请求,单位为core数,容器启动时初始化可用数量 |
spec.containers[].resources.requests.memon | String | 内存请求,单位为MIB,GiB,容器启动的初始化可用数量 |
spec.restartPolicy | String | 定义Pod的重启策略,可选值为Aways,OnFailure,默认值为Always. 1.Always:Pod一旦终止运行,则无论容器是如何终止的,kubelet服务都将重启它。2.0nFailure:只有Pod以非零退出码终止时,kubelet才会重启该容器。如果容器正常结束(退出码为0),则kubelet将不会重启它3.Never:Pod终止后,kubelet将退出码报告给Master,不会重启该Pod. |
spec.nodeselector | Object | 定义Node的Label过滤标签,以key:value格式指定 |
spec.imagePullSecrets | Object | 定义pul镜像时使用secret名称,以name:secretkey格式指定 |
spec.hostNetwork | Boolean | 定义是否使用主机网络模式,默认值为false,设置true表示使用宿主Boolean机网络,不使用docker网桥,同时设置了true将无法在同一台宿主机上启动第二个副本 |
资源清单格式
apiversion:group/apiversion #如果没有给定group名称,那么默认为core,可以使用kubect1 api-versions#获取当前k8s版本上所有的apiVersion版本信息(每个版本可能不同)
kind: #资源类别
metadata: #资源元数据
name
namespace
lables
annotations #主要目的是方便用户阅读查找
spec: #期望的状态(disired state)
status: #当前状态,本字段有Kubernetes自身维护,用户不能去定义
获取apiversion版本信息
kubectl api-versions
获取资源的apiversion版本信息及字段设置帮助文档
kubectl explain pod
KIND: Pod
VERSION: v1
kubectl explain pod.apiVersion
KIND: Pod
VERSION: v1
kubectl explain ingress
KIND: Ingress
VERSION: networking.k8s.io/v1
字段配置格式
apiVersion <string> #表示字符串类型
kind <string>
metadata <Object> #表示需要嵌套多层字段
labels <map[string]string> #表示由k:v组成的映射
finalizers <[]string> #表示字串列表
ownerReferences <[]Object> #表示对象列表
hostPID <boolean> #布尔类型
priority <integer> #整形
name <string> -required- #如果类型后面接-required-,表示为必值字段
spec <Object> #
status <Object>
示例:通过定义清单文件创建POD
编写POD文件一个POD运行两个容器
vim pods-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: app-pod
labels:
app: app
version: v1
spec:
containers:
- name: appname
image: nginx
- name: apptest
image: nginx
创建POD
kubectl apply -f pods-demo.yaml
会发现容器名称为apptest启动失败
排错思路
查看POD状态
kubectl get pods
查看容器中的信息,查看状态和事件
kubectl describe pod
查看容器中的日志信息,多个容器需要加-c,指定容器名称
kubectl log app-pod -c apptest #可以看到是端口冲突
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: ipv6 not available
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2021/03/19 05:11:17 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
2021/03/19 05:11:17 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
2021/03/19 05:11:17 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
2021/03/19 05:11:17 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
2021/03/19 05:11:17 [emerg] 1#1: bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
2021/03/19 05:11:17 [emerg] 1#1: still could not bind()
nginx: [emerg] still could not bind()
查看pods详细信息,看POD运行在哪个节点上
kubectl get pods -o wide
实时刷新POD状态
kubectl get pods -w
解决方法
删除第二个容器,或者修改容器端口,一个POD中端口不可以冲突
容器生命周期
例:一个POD中运行两个容器,如果两个容器存在,容器中运行的进程或已中断,由于某种故障未退出,POD处于RUNNING状态,这时服务是不可用的,但对于POD来说是可用,那如何让POD初始化如何去做
POD创建和死亡的过程
容器环境初始化
在POD创建中,基础容器PAUSE会自动被创建
POD生命周期内部
进行INIT C的一个过程,运行POD中的容器,前提条件容器中有文件存在,才可以运行,可以通过INIT C来生成,INIT C只是用于初始化,初始化完成后会死亡,可有多个INIT C,也可以没有,每一个INIT C运行之后,下一个INIT C才可以构建,不可以并行运行,线级过程,在POD创建中,基础容器PAUSE会自动被创建,才进行INIT C,在主容器运行过程中,会有一个START和STOP操作,运行之前,可以让它执行指令,退出同理
readiness就绪检测
例deployment管理4个POD,若某个POD状态RUNNING才可以对外访问,若POD当前是RUNNING状态,里面进程还未启动,会影响用户体验,可以检测让POD中的进程正常启动才变更RUNNING状态
liveness生存检测,主容器的生存周期
在主容器,运行一个NGINX进程,若NGINX僵尸进程,也就相当于服务挂了,若NGINX进程还存在,那么容器也在运行,容器运行那边POD也就存在,POD存在,就表示,用户访问会调度到此服务,当发现容器内部不能对外进行访问的时间,应该如何处理,重启,重建POD
当主容器中的进程与liveness检测不一致,不能工作时,可以重启或删除等操作,可定义策略
init 容器
Pod能够具有多个容器,应用运行在容器里面,但是它也可能有一个或多个先于应用容器启动的Init容器
Init容器与普通的容器非常像,除了如下两点:
- Init容器总是运行到成功完成为止
- 每个Init容器都必须在下一个Init容器启动之前成功完成(mainC如果退出那么POD就退出了)
如果Pod的Init容器失败,Kubernetes会不断地重启该Pod,直到Init容器成功为止。然而,如果Pod对应的restartPolicy为Never,它不会重新启动,与重启策略有关系,默认是一般重启
init 容器的作用
因为Init容器具有与应用程序容器分离的单独镜像,所以它们的启动相关代码具有如下优势:
- 它们可以包含并运行实用工具,但是出于安全考虑,是不建议在应用程序容器镜像中包含这些实用工具的(需要有一些文件创建和数据的梳理,会造成冗余,保证工具的稳定性,可以写入到INITC中)
- 它们可以包含使用工具和定制化代码来安装,但是不能出现在应用程序镜像中。例如,创建镜像没必要FROM另一个镜像,只需要在安装过程中使用类似sed,awk,python或dig这样的工具。(主要指的是冗余性)
- 应用程序镜像可以分离出创建和部署的角色,而没有必要联合它们构建一个单独的镜像。(在主容器运行中,构建代码,运行代码,注意流程,构建代码可以给INIT C)
- Init容器使用Linux Namespace,所以相对应用程序容器来说具有不同的文件系统视图。因此,它们能够具有访问Secret的权限,而应用程序容器则不能(让INIT去获取文件给主容器,给完之后在退出)
- 它们必须在应用程序容器启动之前运行完成,而应用程序容器是并行运行的,所以Init容器能够提供了一种简单的阻塞或延迟应用容器的启动的方法,直到满足了一组先决条件。(例,一个POD两个容器,A容器nginx+php,B容器MYSQL,A容器启动较快,会导致用户A容器提供服务,B容器还未启动,导致后端服务未启动成功和正在启动中,可以在A容器的INITC中加入检测B容器是否启动正常,等待B容器启动成功,在启动A容器)
示例,创建一个POD,一个容器,有两个INITC,当满足INITC条件才会启动主容器,INITC是顺序执行的
[root@k8s-master test]# cat init-damo.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: [‘sh‘, ‘-c‘, ‘echo The app is running! && sleep 3600‘]
initContainers:
- name: init-myservice
image: busybox
command: [‘sh‘, ‘-c‘, ‘until nslookup myservice; do echo waiting for myservice; sleep 2; done;‘]
- name: init-mydb
image: busybox
command: [‘sh‘, ‘-c‘, ‘until nslookup mydb; do echo waiting for mydb; sleep 2; done;‘]
创建POD
kubectl apply -f init-damo.yaml
发现POD状态一直不成功,INITC两个没有处理完
[root@k8s-master test]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 2m57s
[root@k8s-master test]# kubectl describe pods myapp-pod
Init Containers:
init-myservice:
Ready: False #查看此INIT状态是失败的
创建一个myservice文件,第一个INITC,模拟后端服务的条件
[root@k8s-master test]# cat myservice.yaml
kind: Service
apiVersion: v1
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
创建svc
kubectl apply -f myservice.yaml
[root@k8s-master test]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:1/2 0 17m
[root@k8s-master test]# kubectl describe pods myapp-po
Init Containers:
init-myservice:
Ready: True #启动成功
创建一个myservice文件,第一个INITC,模拟后端服务的条件
[root@k8s-master test]# cat mydb.yaml
kind: Service
apiVersion: v1
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
创建第二个SVC
kubectl apply -f mydb.yaml
查看POD日志
[root@k8s-master test]# kubectl logs myapp-pod
The app is running!
查看pod状态
[root@k8s-master test]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 25m
特殊说明
- 在Pod启动过程中,Init容器会按顺序在网络和数据卷初始化之后启动(在PAUSE中完成的,每一个启动的是PAUSE,对它操作基本于无)。每个容器必须在下一个容器启动之前成功退出(如果有两个INIT容器,第一个容器执行完成后退出码非0,就不会执行第二个)
- 如果由于运行时或失败退出,将导致容器启动失败,它会根据Pod的restartPolicy指定的策略进行重试。然而,如果Pod的restartPolicy设置为Always,Init容器失败时会使用RestartPolicy策略
- 在所有的Init容器没有成功之前,Pod将不会变成Ready状态。Init容器的端口将不会在Service中进行聚集。正在初始化中的Pod处于Pending状态,但应该会将Initializing状态设置为true口
- 如果Pod重启,所有Init容器必须重新执行(类似幂等,每次执行的结果都一致)
- 对Init容器spec的修改被限制在容器image字段,修改其他字段都不会生效。更改Init容器的image字段,等价于重启该Pod
- Init容器具有应用容器的所有字段。除了readinessProbe,因为Init容器无法定义不同于完成(completion)的就绪(readiness)之外的其他状态。这会在验证过程中强制执行(INIT字段与completion字段基本一致,INIT作用就是就绪检测,所以没必须在进行就绪检测,而且执行完就退出了)
- 在Pod中的每个app和Init容器的名称必须唯一;与任何其它容器共享同一个名称,会在验证时抛出错误(例 同一组INIT C 端口是可以相同的,第一个运行完就会退出,不会有冲突)
容器探针
探针是由kubelet对容器执行的定期诊断。要执行诊断,kubelet调用由容器实现的Handler。有三种类型的处理程序
- ExecAction:在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功。
- TCPSocketAction:对指定端口上的容器的IP地址进行TCP检查。如果端口打开,则诊断被认为是成功的。
- HTTPGetAction:对指定的端口和路径上的容器的IP地址执行HTTP Get请求。如果响应的状态码大于等于200且小于400,则诊断被认为是成功的
每次探测都将获得以下三种结果之一
成功:容器通过了诊断
失败:容器未通过诊断
未知:诊断失败,因此不会采取任何行动
- livenessProbe:指示容器是否正在运行。如果存活探测失败,则kubelet会杀死容器,并且容器将受到其重启策略的影响。如果容器不提供存活探针,则默认状态为Success (容器的生命周期,检测应用程序和资源是否可用)
- readinessProbe:指示容器是否准备好服务请求。如果就绪探测失败,端点控制器将从与Pod匹配的所有Service的端点中删除该Pod的IP地址。初始延迟之前的就绪状态默认为Failure。如果容器不提供就绪探针,则默认状态为Success(就绪检测成功,MAINC才可以对外进行访问)
示例就绪检测
检测/usr/share/nginx/html/index1.html文件,若文件可以被访问,则让该POD启动,反之一直被探测,直到能被访问为止
[root@k8s-master test]# cat read.yaml
apiVersion: v1
kind: Pod
metadata:
name: readiness-httpget-pod
namespace: default
spec:
containers:
- name: readiness-httpget-container
image: wangyanglinux/myapp:v1
imagePullPolicy: IfNotPresent #如果镜像本地存在,不重新下载远程镜像
readinessProbe:
httpGet:
port: 80
path: /index1.html
initialDelaySeconds: 1 #延迟时间,1秒后启动
periodSeconds: 3 #3秒后重试,周期时间
创建pod
kubectl apply -f read.yaml
[root@k8s-master test]# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
readiness-httpget-pod 0/1 Running 0 29s
[root@k8s-master ~]# kubectl describe pods readiness-httpget-pod
Warning Unhealthy 22s (x21 over 82s) kubelet Readiness probe failed: HTTP probe failed with statuscode: 404
进入容器创建index1.html检测文件
[root@k8s-master ~]# kubectl exec readiness-httpget-pod -it -- /bin/sh
/ # cd /usr/share/nginx/
/usr/share/nginx # ls
html
/usr/share/nginx # cd html/
/usr/share/nginx/html # ls
50x.html index.html
/usr/share/nginx/html # echo 1 > index1.html
/usr/share/nginx/html #
[root@k8s-master test]# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
readiness-httpget-pod 1/1 Running 0 4m14s
示例存活检测,可基于文件是否存在的机制
创建一个文件,60秒后删除,简单来说此POD可以存活60秒后重启,当然不一定是60秒,还有延时时间和重试时间
[root@k8s-master test]# cat live-exec.yaml
apiVersion: v1
kind: Pod
metadata:
name: liveness-exec-pod
namespace: default
spec:
containers:
- name: liveness-exec-container
image: busybox
imagePullPolicy: IfNotPresent
command: ["/bin/sh","-c","touch /tmp/live ; sleep 60; rm -rf /tmp/live; sleep 3600"]
livenessProbe:
exec:
command: ["test","-e","/tmp/live"]
initialDelaySeconds: 1
periodSeconds:
创建pod
kubectl apply -f live-exec.yaml
可以看到重启次数,和当前存活多长时间
[root@k8s-master test]# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
liveness-exec-pod 1/1 Running 0 7s
liveness-exec-pod 1/1 Running 1 100s
liveness-exec-pod 1/1 Running 2 3m19s
liveness-exec-pod 1/1 Running 3 4m58s
liveness-exec-pod 1/1 Running 4 6m37s
liveness-exec-pod 1/1 Running 5 8m16s
liveness-exec-pod 1/1 Running 6 9m55s
liveness-exec-pod 0/1 CrashLoopBackOff 6 11m
liveness-exec-pod 1/1 Running 7 14m
liveness-exec-pod 0/1 CrashLoopBackOff 7 16m
示例 生存检测,基于httpget方法,状态码的方法
[root@k8s-master test]# cat live-http.yaml
apiVersion: v1
kind: Pod
metadata:
name: liveness-httpget-pod
namespace: default
spec:
containers:
- name: liveness-httpget-container
image: wangyanglinux/myapp:v1
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
livenessProbe:
httpGet:
port: http
path: /index.html
initialDelaySeconds: 1 #延时1秒后监控
periodSeconds: 3 #3秒监控一次
timeoutSeconds: 10 #延时统计最大延迟时间
创建pods
[root@k8s-master test]# kubectl apply -f live-http.yaml
pod/liveness-httpget-pod created
[root@k8s-master test]# kubectl get pods
NAME READY STATUS RESTARTS AGE
liveness-exec-pod 0/1 CrashLoopBackOff 7 16m
liveness-httpget-pod 1/1 Running 0 3s
[root@k8s-master test]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
liveness-exec-pod 0/1 CrashLoopBackOff 7 16m 10.20.36.72 192.168.10.82 <none> <none>
liveness-httpget-pod 1/1 Running 0 10s 10.20.36.71 192.168.10.82 <none> <none>
[root@k8s-master test]# curl 10.20.36.71
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@k8s-master test]# kubectl exec liveness-httpget-pod -it -- /bin/sh
/ # rm -f /usr/share/nginx/html/index.html
可以看到这里POD已经重启了
[root@k8s-master test]# kubectl get pods
NAME READY STATUS RESTARTS AGE
liveness-exec-pod 0/1 CrashLoopBackOff 7 19m
liveness-httpget-pod 1/1 Running 1 2m29s
示例使用TCP端口的方式
镜像是80端口,改成8080验证效果
[root@k8s-master test]# cat live-tcp.yaml
apiVersion: v1
kind: Pod
metadata:
name: probe-tcp
spec:
containers:
- name: nginx
image: wangyanglinux/myapp:v1
livenessProbe:
initialDelaySeconds: 5
timeoutSeconds: 1
tcpSocket:
port: 8080
periodSeconds: 3
创建pods
kubectl apply -f live-tcp.yaml
可以看到一直重启
[root@k8s-master test]# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
probe-tcp 1/1 Running 1 16s
示例将检测机制整理到一起
删除default名称空间下的POD
kubectl delete pods --all
创建pod
[root@k8s-master test]# kubectl apply -f live-http2.yaml
pod/liveness-httpget-pod created
可以看到状态是running,但ready还没有准备好
[root@k8s-master test]# kubectl get pods
NAME READY STATUS RESTARTS AGE
liveness-httpget-pod 0/1 Running 0 4s
进入POD中的窗口创建index1.html文件
[root@k8s-master test]# kubectl exec liveness-httpget-pod -it -- /bin/sh
/ # cd /usr/share/nginx/html/
/usr/share/nginx/html # ls
50x.html index.html
/usr/share/nginx/html # echo 1 > index1.html
查看POD ready 已经正常了
[root@k8s-master test]# kubectl get pods
NAME READY STATUS RESTARTS AGE
liveness-httpget-pod 1/1 Running 0 55s
在进入容器中删除index.html文件
[root@k8s-master test]# kubectl exec liveness-httpget-pod -it -- rm -f /usr/share/nginx/html/index.html
可以查看到已经重启过POD了
[root@k8s-master test]# kubectl get pods
NAME READY STATUS RESTARTS AGE
liveness-httpget-pod 0/1 Running 1 2m44s
Pod hook
Pod hook(钩子)是由Kubernetes管理的kubelet发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。可以同时为Pod中的所有容器都配置hook
Hook的类型包括两种:
- exec:执行一段命令
- HТТP:发送HTTP请求
PodSpec中有一个restartPolicy字段,可能的值为Always、OnFailure和Never。默认为Always,restartPolicy适用于Pod中的所有容器。restartPolicy仅指通过同一节点上的kubelet重新启动容器。失败的容器由kubelet以五分钟为上限的指数退避延迟(10秒,20秒,40秒.)重新启动,并在成功执行十分钟后重置。如Pod文档中所述,一旦绑定到一个节点,Pod将永远不会重新绑定到另一个节点。
Pod phase
Pod的status字段是一个PodStatus对象,PodStatus中有一个phase字段。
Pod的相位(phase)是Pod在其生命周期中的简单宏观概述。该阶段并不是对容器或Pod的综合汇总,也不是为了做为综合状态机
Pod相位的数量和含义是严格指定的。除了本文档中列举的状态外,不应该再假定Pod有其他的phase值
POD当前的一个反馈
状态 | 说明 |
---|---|
挂起(Pending) | Pod已被Kubernetes系统接受,但有一个或者多个容器镜像尚未创建。等待时间包括调度Pod的时间和通过网络下载镜像的时间,这可能需要花点时间 |
运行中(Running) | 该Pod已经绑定到了一个节点上,Pod中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态 |
成功(Succeeded) | Pod中的所有容器都被成功终止,并且不会再重启 |
失败(Failed) | Pod中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止(POD只要有一个容器不正常状态退出,那状态就是失败) |
未知(Unknown) | 因为某些原因无法取得Pod的状态,通常是因为与Pod所在主机通信失败 |
示例start stop
[root@k8s-master test]# cat post.yaml
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
preStop:
exec:
#command: ["/usr/sbin/nginx", "-s", "quit"]
command: ["/bin/sh", "-c", "echo Hello from the postStop handler > /usr/share/message"]
[root@k8s-master test]# kubectl apply -f post.yaml
pod/lifecycle-demo created
[root@k8s-master test]# kubectl get pods
NAME READY STATUS RESTARTS AGE
lifecycle-demo 1/1 Running 0 4s
查看POD中poststart执行没有
[root@k8s-master test]# kubectl exec lifecycle-demo -it -- /bin/bash
root@lifecycle-demo:/# cat /usr/share/message
Hello from the postStart handler
状态
POD中只有一个容器并且下在运行,容器成功退出
记录事件完成
如果 restartPolicy 为:
Always:重启容器;Pod phase 仍为 Running
OnFailure:Pod phase 变成 Succeeded
Never:Pod phase 变成 Succeeded
Pod 中只有一个容器并且正在运行。容器退出失败
记录失败事件
如果 restartPolicy 为:
Always:重启容器;Pod phase 仍为 Running
OnFailure:重启容器;Pod phase 仍为 Running
Never:Pod phase 变成 Failed
Pod 中有两个容器并且正在运行。容器1退出失败
记录失败事件
如果 restartPolicy 为:
Always:重启容器;Pod phase 仍为 Running
OnFailure:重启容器;Pod phase 仍为 Running
Never:不重启容器;Pod phase 仍为 Running
如果有容器1没有处于运行状态,并且容器2退出:
记录失败事件
如果 restartPolicy 为:
Always:重启容器; Pod phase 仍为 Running
OnFailure:重启容器; Pod phase 仍为 Running
Never:Pod phase 变成 Failed
Pod 中只有一个容器并处于运行状态。容器运行时内存超出限制
容器以失败状态终止
记录 OOM 事件
如果 restartPolicy 为 :
Always:重启容器;Pod phase 仍为 Running
OnFailure:重启容器;Pod phase 仍为 Running
小结
了解容器的生命周期,POD创建和死亡的过程
INITC顺序执行
存活检测,文件存在的方式,或者脚本的成功执行状态码
生存检测,HTTPGET,TCP端口的方式
容器启动与退出动作