6、Pod资源管理器
资源管理
Pod
总结
Ingress
Label
标签选择器
定义标签选择器的方式
查看现有Pods的标签
使用apply的方式在yaml配置文件加入标签
直接打标签
标签选择器使用
资源注解(annotation)
基本使用
Pod生命周期
Pod对象的相位
容器的重启策略
资源需求及资源限制
Pod服务质量类别
资源限制
安全设定
Pod
总结
Ingress
Label
标签选择器
定义标签选择器的方式
查看现有Pods的标签
使用apply的方式在yaml配置文件加入标签
直接打标签
标签选择器使用
资源注解(annotation)
基本使用
Pod生命周期
Pod对象的相位
容器的重启策略
资源需求及资源限制
Pod服务质量类别
资源限制
安全设定
资源管理
我们的Kubernetes的主要目的在于,通过Pod的这种形式去运行容器,但是Pod和容器并不是对应关系,Pod可以理解为容器的有一层外壳,Pod在容器之外增加了一层抽象封装,这个抽象封装叫Pod,而且在一个Pod内部可以有多个容器,而且这些容器本身将共享同一个网络名称空间,这其实看上去Pod中哪怕只有一个容器的时候,好像只存在单一容器,事实上不是,在Pod中会存在一个基础架构的容器,当我们来使用原始方式去部署Kubernetes的时候,它用到的基础架构容器的对应的镜像叫pause,它创建以后一直处于暂停状态,我们甚至都看不见这么一个容器,而后,任何一个Pod中的pause容器回为加入到此Pod中其他正式的主要容器来实现提供网络名称空间,提供存储卷的定义等功能,比如我们要定义存储卷,那也就意味着存储卷属于Pod或者Pod的这个pause基础架构容器的,任何加入到此Pod的其他容器将共享底层基础Pod的Pid、Mount、User、Ipc、Uts、Network等主要空间,通过这种方式组织出来的多个容器,特别像是在同一个宿主机之上运行的多个进程,每一个容器是一个进程,而且进程和进程之间也可以通过lo接口进行通信了;
所以Pod在某种程度上来将,它更像是本来把散隔开来的容器组织成了虚拟机这种逻辑,当然主要目标和原因在于,如果某些容器需要在非常紧密的方式,,结合起来进行工作时,这种组织逻辑就特别有用,比如说,通常在一个Pod中跑多个容器,一般除非万不得已,不建议在一个Pod中跑多个容器,就像docker容器一个,在一个容器内部应该只运行一个应用程序,逻辑是近似的,那么为什么我们要设计出Pod,来封装多个容器呢,很多时候一个单一进程可能无法完成我们期望完成的任务,比如第一个容器跑的是nginx,因为nginx中是会生成很多日志的,那如果我们想要收集日志呢,像elk这样的日志系统,我们必须要在目标主机之上部署一个日志收集代理,比如filebeat,那如果一个容器只跑一个nginx,我们此时想收集nginx日志给他发送到一个统一日志收集系统里面,那在Docker容器当中是没有比较好的方式做到的,因此就必须要以非常紧密的方式,在同一个Pod中去跑第二个容器,来辅助这个主容器完成此类的额外管理任务;
所以在一个Pod中,通常只能有一个主容器,其他容器是为了辅助主容器的任务或者管理而设定的,而这个辅助容器,我们称之为边车,而收集日志,只是更多常见的边车方式之一,还有一种,比如说,我们这个容器提供了服务,但是我们不期望这个容器直接被访问,而是我们可以在同一个Pod上再部署一个容器,所有的用户请求想要到达主容器得先到达这个边车容器,而且对于现今主流的服务网格Istio工具的时候,Istio在很大程度上去实现网格化,就是通过为Pod中的每一个主容器添加一个前端代理来实现的,这个代理服务器为主容器的服务的访问,添加了非常强大的前端管理功能,包括 容器当前的健康状态、流量状态、链路状态等等可以按需做到链路侦测、流量调度、等各种各样的高级管理;
那么在同一个Pod当中他们共享Ipc、Uts、Network,那么多个容器他们之间可以通过lo接口互通,各容器也将共享同一个主机名,共享使用同一个IP地址以及同一个网络名称空间,在同一个Pod上的各容器,也能共享挂载同一组存储卷;
当然如果我们自己有一个机房,这个机房中的所有主机都使用了私有地址,所有机器都处于同一个私有网段中的,那这个机房当中构建LNMP架构,N需要访问P,P需要访问M,这都没问题,那么P就不需要公开给互联网访问了,P的客户端是N,所以也P才有访问M的需求,但是N就需要被外部的客户端访问了,那么N我们就需要给他公开到外部的客户端访问了;
如果此时这里不是一个机房,而是一个Kubernetes集群,而Kubernetes之上存在三种类型的网络,分别的node网络这个才是能与外币网络通信的接口,第二个是service网络,service网络仅能出现在iptables或ipvs规则当中用于路由和调度请求流量,第三种网络是Pod网络,就相当于我们机房里面的Kubernetes内部网络,每一个Pod都处于这个网络当中,Pod的IP地址都是在这个网络动态分配的IP地址,因此各个Pod无论在跑在哪个node上,是可以直接通信的,Pod和Pod之间可以使用彼此的地址,互相之间通信,但是Pod是动态的,随之有可能被Pod控制器所重建,因此IP地址会发生变化的,那这个时候Pod和Pod之间直接使用IP地址进行通信就不是一种理想的状态的,我们因为让他借助于service地址通信;
因此,在Kubernetes之上跑应用程序,他就有一个特点,我们必须在Pod前端增加一个抽象层,也就是我们的service,没一个应用程序为了能让客户端固定的访问到这个服务,我们都应该给它增加一个service前端,哪怕也只有一个,我们也必须对他进行代理,这个代理者也就是service,我们必须把资源实例化出创建出service对象来,它才有用,而创建service对象它的表现为所有节点上的iptables或ipvs规则,所以客户端访问这个Pod服务时候,需要先到service,而后service再向后反代或调度给Pod;
Service也称为Kubernetes的服务注册服务发现的组件,也称为叫做DNS,Kubernetes是使用DNS服务,而且这是一种动态注册和更新的DNS服务,来做服务总线的,实现方式叫CoreDns,发展到今天的Kubernetes的DNS,Dns已经迭代了三个了, 第一个是SkyDns,第二个是KubeDns,第三个才是CoreDns,CoreDns有很多KubeDns所不具有的优势,因此从Kubernetes1.12版本开始,开始使用CoreDns,Google大小人们使用Kubernetes的疑虑,它把Kubernetes这个项目由Google这家商业公司主导转为CNCF云原生计算基金会所管理,后来这个组织就越来越受到人们的关注,加入进来的成员越来越多,而后CNCF也开始接受更多扩展的其他项目,除了Kubernetes还有Prometheus、CoreDns、Habor等;
所以在学习Kubernetes应该树立一个概念,只要建构在Kubernetes之上的Pod都应该由于控制器来管理, 而且这个Pod一般不会由我们手动去创建,这种Pod叫做自助式Pod,它有一个特点,就是这个Pod一删除,它就不会被重建了,节点一宕机,在个Pod就没了,所以我们使用Pod虽然很多,但是绝对不会以手动的方式创建独立运行的Pod,而应该使用Pod控制器来创建Pod;
Pod控制器也是一类标准的Kubernetes资源,控制器有多种,不同的控制器有不同的功能和任务,控制器也是整个Kubernetes最核心的组成部分,整个集群的大脑,因为它主要通过和解循环,loop来完成确保用户所定义的每一个对象,它的当前状态和用户的期望值一致,如果不一致那么控制器就会通过一系列的逻辑操作来进行修复,所以说控制器里面包含的任务就像运维里面的发布、变更、故障处理等功能;
所以从某种意义上来讲,控制器就是运维,因此有了Kubernetes之后我们运维工程师的日常任务,基本上就不需要再去人为的接入和管理了,至少对于现在的无状态应用来讲,已经做到了,你只需要管理Kubernetes集群自身是否运行正常就可以了;
Pod
Pod本身创建完成之后所拥有的地址是私有地址,Pod网络当中动态分配的地址,而Pod网络中的地址是不能被集群之外的客户端所访问的,但是我们将来构建一个集群是必然需要将一些Pod公开给互联网上的用户访问的,比如一个LNMP,那么N就需要公开给外网访问,那么我们怎么能把集群外部的流量在必要时接入到集群内部的Pod呢,我们有三种方式;
第一种是使用service的nodeport类型,它会在集群节点上的每一个node节点打开一个端口,而后你访问,集群中的任何一个节点的地址和端口都可以访问到Pod,它首先会DNAT到service,然后service再调度给Pod;
第二种是使用hostPort,我们在定义Pod时候,使用hostPort的方式来将容器的端口映射到Node的端口,那这样的话这个容器跑在哪个节点,我们就可以使用哪个节点的地址和端口就行访问了,与nodeport的不同之处在于,hostPort仅在运行容器的节点打开端口,所以说它并不经由service;
第三种是可以直接使用hostNetwork,让Pod可以直接使用它所在主机的网络名称空间,因此,Pod的地址也就是主机的地址,Pod监听的端口也就是主机的端口,那这个时候直接访问Pod所在的node的地址和端口即可访问,那么很显然,Pod就不那么隐蔽了;
总结
第一种方式,访问逻辑是最通透最直接的,访问任何一个节点都能到达,但是这里有一个缺陷在于,我们创建的任何的服务都要在所有节点上增加一个iptables或者ipvs规则,所以如果服务使用同一个端口,都会导致端口冲突的,所以nodeport只能是随机映射的,他们一般是30000-32767之间的端口,因此这个时候我们就不得不得在Kubernetes集群之外的前端,人为的再建立一个负载均器,用户可以访问这个负载均衡器把这请求负载至后端的每一个物理节点映射的端口来,那这个负载均衡一旦宕机了,对应的服务也就获取不到了,所以必要的话,我们还需要keepalived来给他做高可用,那这就背离了Kubernetes的使用初衷,因为还需要在Kubernetes集群之外再加一个不受Kubernetes管理的层,层层转发性能不是特别的好,更何况我们的Kubernetes集群外的负载均衡器也无法按需创建;
那么目前来讲通常我们可以把Kubernetes集群部署在一个云计算环境当中,比如Openstarck,然后借助类似LBaaS来实现负载均衡的调度功能,当service被删除的时候我们的LBaaS需要支持使用命令或者其他的方式进行节点重组,我们的Kubernetes正好有一个这样的组件Cloud-controller-manager它能够通过这个组件与外部云计算环境的API相交互,用来在必要时来触发外部的类似LBaaS的云计算环境完成非由Kubernetes集群自身能完成的那些功能;
Ingress
Kubernetes的核心目标就是去运行Pod,而围绕在Pod之外,我们还有很多类型的资源,比如我们的Service,那么通过他是ipvs或者是iptables规则他们都是四层会话的,那么如果我们的服务是https服务,因为四层是不能卸载https会话的,那么所有的https证书就得安装的Pod里面,那就比较麻烦了,所以这里又有一个七层调度Ingress,其实它就是一个nginx或者haproxy等一类的实现组件;
Label
在一个Kubernetes集群之上,我们有可能会跑很多很多的Pod,那么Service如何识别哪些Pod是当前Service的Pod,Pod Controller又如何识别哪些Pod是当前Pod控制器的Pod,在一个Kubernetes集群我们会跑很多很多的Pod,还有我们的Kubernetes会把整个Kubernetes管理的整个大的空间划分多个名称空间namespace,因此我们创建Pod的时候实际上是在名称空间上创建,Pod是名称空间级别的资源,两个名称空间的Pod是可以同名的,但是在同一个名称空间任何两个Pod都不能同名,在Pod控制器的管理下,如果其中一个Pod故障了,那么控制器是需要重建的,那它怎么知道哪一个名称空间是自己的;
那么此时我们使用IP来区别不合适因为会变动,靠名称来识别也不合适,因为同一个namespace不能同名,那么Kubernetes的实现方式就是所谓的label和label selector来实现的,每次创建Pod都可以在Pod上附加一些标签上来,我们可以理解为元数据,我们可以自己网上面加标签,那么我们加上来的标签可以作为引用资源的引用者的过滤条件,而我们设定的过滤条件就叫做标签选择器,选择还可以有多种方式,精确选择、范围选择、模糊匹配等等;
正常情况下,我们在使用Kubernetes标签时,有几个要求必须是键值类型的,一个对象可以拥有不止一个标签,同一个标签也可以被添加至多个资源之上,实践当中我们可以为资源附加多个不同维度的标签以实现资源分组关联,例如版本标签、环境标签、分层标签、等用于交叉标识同一个资源所属的不同版本、环境架构层级等;
标签中的键的名称通畅是由键前缀和键名组成的,其格式可以如KEY_NAME/KEY_PREFIX_NAME;
键名至多能使用63个字符,可使用字母、数字、连接符号(-)、下划线(_)、点号(.)、等字符,且只能以字母或数字开头;
键前缀必须为DNS子域名格式,且不能超过253个字符,省略键前缀时,键将被视为用户的私有数据,不过由于Kuberetes系统组成火第三方组件自动为用户资源添加的键必须使用前缀而"kubernetes/"前缀预留给kubernetes的核心组件使用;
标签中的键值必须不能多于63个字符,它要么为空,要么是以字母或数字开头及结尾,且中间仅使用了字母、数字、连接符号(-)、下划线或点号(.)等字符的数据;
标签选择器
标签选择器用户表达标签的查询条件或选择标准,Kuberetes API目前支持两个选择器;
基于等值关系
操作符有=、==、!=三种,前面两个都表示等值,第三个表示不等;
基于集合关系
KEY in (value1,value2,...)
KEY not in (value1,value2,...)
KEY:所有存在此键名的标签的资源
!KEY:所有不存在此键名的标签的资源
使用标签选择器还能使用一下逻辑
同时指定多个选择器之间的逻辑关系为与操作;
使用"空值"的标签选择器意味着每个资源对象都将被选中;
"空的"标签选择器将无法选出任何资源;
定义标签选择器的方式
kubernetes的诸多资源对象必须以标签选择器的方式关联到Pod资源对象,例如Service、Deployment和ReplicaSet类型的资源等,他们在spec字段中嵌套使用嵌套的selector字段通过matchLabels来指定标签选择器,有的甚至还支持使用matchExpressions来构造复杂的标签选择器机制;
matchLabels:通过直接给定兼职对指定标签选择器;
matchExpressions:基于表达式指定的标签选择器列表,每个选择器如“{KEY: KEY_NAME,operator:OPERTOR,values:[VALUES1,VALUES2,...] }”,选择器列表之间为逻辑与关系;
使用In或者NotIn操作符时,其values非必须为非空字符串列表,而使用Expressions或者DostNotExist时,其values必须为空;
查看现有Pods的标签
[root@node1 ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
mage-56cd974f48-bzblm 1/1 Running 0 112s app=mage,pod-template-hash=56cd974f48
web-6c489ff6dd-76thk 1/1 Running 0 30s app=web,pod-template-hash=6c489ff6dd
web-6c489ff6dd-hf2jt 1/1 Running 0 2m8s app=web,pod-template-hash=6c489ff6dd
web-6c489ff6dd-mchs8 1/1 Running 0 2m29s app=web,pod-template-hash=6c489ff6dd
使用apply的方式在yaml配置文件加入标签
[root@node1 ~]# cat mage.yaml
apiVersion: v1
kind: Pod
metadata:
name: mage
namespace: default
labels:
app: demo
rel: stable
spec:
restartPolicy: Always
hostname: mage
containers:
- image: busybox:latest
imagePullPolicy: IfNotPresent
name: mage-busybox
command:
- "/bin/sh"
- "-c"
- "sleep 1000"
[root@node1 ~]# kubectl apply -f mage.yaml
[root@node1 ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
mage 0/1 ContainerCreating 0 6s app=demo,rel=stable
直接打标签
直接创建一个Pod
[root@node1 ~]# kubectl create deployment cce --image=ikubernetes/myapp:v1
直接给手动创建的Pod标签
[root@node1 ~]# kubectl get pods -n default --show-labels
强制删除标签
[root@node1 ~]# kubectl label pods -n default cce-fcd4c8cff-2tv5j cce=caichangen --overwrite
使用减号删除标签
[root@node1 ~]# kubectl label pods cce-fcd4c8cff-2tv5j app-
标签选择器使用
使用标签选择器做等值筛选
[root@node1 ~]# kubectl get pods -l app=caichangen -L app # -L 代表显示键和值
使用标签选择器做不等职筛选
[root@node1 ~]# kubectl get pods -l app!=caichangen -L app
使用in筛选出有app键但是值是caichangen或者cce
[root@node1 ~]# kubectl get pods -l "app in (caichangen,cce)" -L app
使用notin筛选出有app键但是值不是caichangen或者cce
[root@node1 ~]# kubectl get pods -l "app notin (caichangen,cce)" -L app
使用标签筛选出有app键的pod
[root@node1 ~]# kubectl get pods -l app -L app
使用标签筛选出没有app键的pod
[root@node1 ~]# kubectl get pods -l '!app' -L app
资源注解(annotation)
在Kubernetes之上除了能使用Label这种标签之外,还是使用资源注解,因为标签的键和值不能超过36个字符,如果我们想要表达一些非常常用的一些信息需要写的长一点,并且这些信息只是表示这个资源的元数据的,它不是用来做标签选择的,那这个时候我们的标签就会有问题了,那么正好资源注解解决了这个问题,它和标签很像,它也是键值型的数据,不过它不能用于标签选择器去挑选,只是为了给用户一种自定义资源元数据的接口,那么注解它的元数据不受字符数量限制,可大可小。可为结构化或非结构化,也可以使用标签特殊字符,但唯一的限制是注解不能够被标签选择器所选择;
基本使用
使用方式和Label差不多;
添加annotate
[root@node1 ~]# kubectl annotate pods web-6c489ff6dd-6kr97 cce=caichangen
pod/web-6c489ff6dd-6kr97 annotated
查看annotate
[root@node1 ~]# kubectl describe pods web-6c489ff6dd-6kr97
Name: web-6c489ff6dd-6kr97
Namespace: default
Priority: 0
Node: node2.cce.com/172.16.1.3
Start Time: Sat, 09 Nov 2019 15:19:41 +0800
Labels: app=web
pod-template-hash=6c489ff6dd
Annotations: cce: caichangen
修改annotate
[root@node1 ~]# kubectl annotate pods web-6c489ff6dd-6kr97 cce=123 --overwrite
删除annotate
[root@node1 ~]# kubectl annotate pods web-6c489ff6dd-6kr97 cce-
Pod生命周期
所谓Pod生命周期指的是,Pod从创建,退出结束终止之间经历的阶段;
第一阶段,第一阶段一般来讲,有时候我们为了启动一个Pod主容器,主容器在启动之前,可能需要给它做一个环境初始化,比如在启动Nginx主容器之前,我可以首先启动一个容器,能创建一个目录上,在目标上去创建一个文件,拖完之后再去启动主容器,在启动主容器这个阶段我们称之为初始化阶段,所以初始化容器就退出了,但是初始化容器未必是必须的,所以我们以后创建一个Pod如果有这种场景的必要的话,就可以使用初始化容器叫做,init container来做这个事情,但是还要注意的是,初始化容器也有可能存在多个,比如我们一个初始化容器只干一件事,第一个创建目录,第二个创建访问的文件,如果你有三个初始化容器的时候,只有所有的初始化工作完成了,你的主容器才能启动,否则的话主容器的没法启动的,那也就意味着初始化,容器开始正常退出之后,主容器才能启动,而且如果你多个初始化容器,这个多个初始容器,比如要依次启动,第一个启动结束,第二个启动结束。。。他们是串行的,最后才是主容器;
但是经过前面的测试,一个Pod里面可以是有多个容器的,Pod的容器和它的辅助容器(边车),他们是可以同时运行的,但是初始化容器如果有多个,那么他们必须串行,不能并行;
[root@node1 ~]# kubectl explain pods.spec.initContainers
第二阶段,第二阶段就是主容器的运行阶段,分为三个阶段,第一个主容器刚启动之后,第二是主容器正常运行,第三是主容器结束之前,post start hook这个时候是你的容器刚刚启动完成,它是一个钩子,这个时候你可以触发你的定义的钩子命令,来帮你在这个容器中做一些启动后的设置,那么pre start hook就是结束之前做的操作,而这个两个主要是用于触发一些命令来执行的,让用户可以自定义操作的;
[root@node1 ~]# kubectl explain pods.spec.containers.lifecycle
apiVersion: v1
kind: Pod
metadata:
annotations:
author: caichangen
data: 2019-11-09 18:04:12
name: cce
namespace: caichangen
spec:
containers:
- image: busybox:latest
imagePullPolicy: IfNotPresent
name: busybox
command:
- /bin/sh
- -c
- sleep 10000
lifecycle:
postStart: # 在容器启动之后创建一个文件夹
exec:
command:
- /bin/mkdir
- /cce
另外两个,在你的Pod正常运行当中,你的容器是靠容器的主进程来支撑的,容器的进程一旦停了,容器就停掉了,但是容器进程没停也不一定说明容器的是健康的,所以在容器里面有一个健康状态监测,那Pod也会面临同样的问题,在一个Pod中,容器运行是好好的,Pod也正常运行,但是Pod里面的这个容器的进程却没法接受请求或提供服务了,所以这儿我们需要为它提供健康状态检查,这个检查是我们自定义的,在docker中我们叫HEALTHCHECK,在Kubernetes的Pod中我们叫做liveeness probe叫存活性探测,意思就是监测Pod里面的容器,还是否处于健康状态,而这种存活的标准和条件,取决于用户的自定义命令,命令正常返回标识健康,否则就是不健康,liveeness probe它是在周期性内不断的进行监测的,一检查不健康,可以执行容器重启的操作。
[root@node1 ~]# kubectl explain pods.spec.containers.livenessProbe
exec:执行命令来做检测;
failureThreshold:状态发生转换时,检 测到失败几次,才发现是真的不可用;
httpGet:使用httpGet来做检测;
initialDelaySeconds:在容器启动多少秒后做检测;
periodSeconds:间隔时间,默认10秒一次;
successThreshold:状态发生转换时,检测成功几次才算成功;
tcpSocket:tcp的检测方式;
timeoutSeconds:超时时间,默认1秒;
存活性状态检查,主要是运行一些命令,来做存活性状态检查,所以这个命令一定是这个容器内部可以执行的一个命令,可以去通过去向容器自身的服务发请求,或者判断一个文件的存在性等任何我们可以执行的命令做存活性状态监测的,到底运行什么命令这个取决于用户以什么命令的执行结果判断为存活性或非存活,比如一个web服务器,通常情况下我们可以使用netstat判断一下本地的80端口监听与否来做存活性判断,如果失败会按照策略重启容器,它主要是通过命令的返回值进行判断的;
apiVersion: v1
kind: Pod
metadata:
annotations:
author: caichangen
data: 2019-11-09 18:04:12
name: cce
namespace: caichangen
spec:
containers:
- image: busybox:latest
imagePullPolicy: IfNotPresent
name: busybox
command:
- /bin/sh
- -c
- mkdir /cce; sleep 10;rm -rf /cce;
livenessProbe:
exec:
command: ['test','-e','/cce']
initialDelaySeconds: 3
successThreshold: 1
failureThreshold: 3
那么对于readiness probe,我们称为叫做就绪状态探测,那么在容器没有启动完成之前,我们是不应该做一些操作的,它和Service结合比较好,并且Service也是通过评测就绪状态监测来评判,是否加入到后端,不是说容器一启动就加入到后端,而是容器启动完成之后就绪之后Service才将其加入到Service内部来作为后端,那么如果在定义Pod的时候,没有定义就绪状态监测,那么Service会Pod的状态为Runing就是就绪了;
[root@node1 ~]# kubectl explain pods.spec.containers.readinessProbe
就绪状态检测,它的配置格式和健康状态检测很想像的,但是有一点不同,就绪状态检测是没有权利重启容器的,就绪状态检查成功了,Service就可以把它当中做后端服务器使用了,如果不成功就不会把Pod添加到Service去的,它也是周期性检查,循环检测直到检测就绪为止,它主要是通过命令的返回值进行判断的,返回值可以不是1但是最小值是1;
apiVersion: v1
kind: Pod
metadata:
annotations:
author: caichangen
data: 2019-11-09 18:04:12
name: cce
namespace: caichangen
spec:
containers:
- image: busybox:latest
imagePullPolicy: IfNotPresent
name: busybox
command:
- /bin/sh
- -c
- sleep 20;mkdir /cce;touch /cce/file;sleep 1000 # 此处不要忘记sleep,否则容器停止则会重启
readinessProbe:
exec:
command: ['test','-e','/cce/file']
initialDelaySeconds: 2
periodSeconds: 5
Pod对象的相位
Pod一旦启动之后,它总是处于其生命进程中的几个相位(phase)之一
Pending:API Server创建了Pod资源对象并已存入etcd中,但它尚未被调度完成,或仍处于从仓库中下载镜像的过程中;
Running:Pod已经被调度至某个节点,并且所有容器都已经被kubelet创建完成;
Succeeded:Pod中的所有从起都已经成功终止并且不会被重启;
Failed:所有容器都已经终止,但至少有一个容器终止失败,即返回了非0值的退出状态或已经被系统终止;
Unknown:API Server无法正常获取到Pod对象的状态信息,通畅是由于其无法与所在工作节点的kubelet通信所致;
容器的重启策略
Pod对象因容器程序崩溃或容器申请超出限制的资源等原因都有可能导致其被终止,此时是否应该重建,则取决于其重启策略(restartPolicy)
Always:但凡Pod对象终止就将其重启,此为默认设定;
OnFailure:仅在Pod对象出现错误时方才将其重启;
Never:从不重启
资源需求及资源限制
CPU属于可压缩(compressible)型资源,即资源额度可按需收缩,而内存则是不可压缩型资源,对其执行收缩操作可能会导致某种程度的问题,所以我们需要资源进行一定的限制;
CPU的计量方式:一个核心相当于1000个微核心,即1=1000m,0.5=500m;
内存的计量方式:默认单位为字节,也可以使用E、P、T、G、M和K后缀单位,或Ei、Ei、Pi、Ti、Gi、Mi和Ki形式的单位为后缀;
Pod服务质量类别
根据Pod对象的requests和limits属性,Kubernetes把Pod对象归类到BesteFFort、Buaranteed三个服务质量类别,可以使用describe查看QoS Class属性;
Guaranteed:每个容器都为CPU资源设置了具有相同值的requests和limits属性,以及每个容器都为内存资源社会了具有相同值的requests和limits属性的pod资源会自动归类为此类别,这类Pod资源具有最高优先级;
Burstable:至少有一个容器设置了CPU或者内存资源的requests属性,但不满足Guaranteed类别要求的Pod资源自动归属此类,他们具有中等优先级;
BestEffort:未为任何一个容器设置requests或limits属性的Pod资源自动归属此类别,他们的优先级为最低级别;
资源限制
CPU属于可压缩型资源,即资源额度可按需收缩,而内存属于不可压缩型资源,对齐执行收缩操作可能会导致某种程度的问题,CPU一个核心相当于1000个微核心,即1=1000m,0.5=500m;
kubectl explain pods.spec.containers.resources # CPU、内存资源限制
安全设定
可以设定一些用户、权限、内核参数等信息;
kubectl explain pods.spec.securityContext # Pod安全上下文设定
kubectl explain pods.container.securityContext # container安全上下文设定