作者:周虚(应金挺)
SREWorks的开源招引了许多用户来尝试布置和运用咱们的产品,其间不乏一些初次接触Kubernetes的朋友。跟着SREWorks云原生运维渠道运用的继续深化,部分用户关于其间的原理和概念还存在一些困惑。因此,咱们特推出 《Kubernetes资源编列系列》 ,从底层的Pod YAML开端,逐步递进地解说相关内容,希望可以回答咱们关于Kubernetes的一些疑问,让用户关于云原生相关技能有更深化的了解。
1.Pod全体结构
Pod YAML的全体结构,可以开端分为Resource(资源)、Object(元数据)、Spec(标准)、Status(情况)。 本文将会围绕这四部分逐个打开。
- Resource:界说资源类型与版本, 作为从Rest API中获取资源必带的特点。
- Object:资源的元数据特点,清晰资源的根本标识。
- Spec / Status:
-
-
Spec:界说资源的希望情况,包含用户供给的装备、体系扩展的默许值,以及周边体系初始化或许更改值(scheduler、hpa等)。
-
Status:界说资源的当时情况,然后依据Spec界说的申明式装备,使pod不断朝希望情况靠近。
-
2.Resource(资源)-Rest API
k8s资源按照Scope可以分为Namespace资源、Cluster资源,Namespace在k8s可以认为是软租户的效果,完结资源层面的隔离,Pod资源便是属于Namespace资源,而Namespace不光体现在YAML参数中,也表现在k8s Rest API中。
Rest API的全体结构,以Pod举例
apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: default
依据上述YAML,可以清晰出namespace为default, name为test-pod的Pod资源目标,也便是清晰出Pod为Namespace资源,该Pod资源目标对应的apiVersion为v1,后续k8s自内联相关的Group为/api,自然而然,咱们就将该目标的数据分离出来了:
- group:api
- apiVersion:v1
- kind:Pod
- name:test-pod
- namespace:default
依据上述的数据展示,apiserver自然而然会相应的注册出下列rest api,
-
/api/{apiVersion}/{kind}
:该kind下的一切资源列表 -
/api/{apiVersion}/namespace/{namespace}/{kind}/
:该kind下当时namespace的一切资源列表 -
/api/{apiVersion}/namespace/{namespace}/{kind}/{name}
:该kind下当时namespace且名为name的资源 -
/api/{apiVersion}/namespace/{namespace}/{kind}/{name}/{subresource}
:该kind下当时namespace且名为name的资源下子资源操作
后续依据扩展,咱们就需求清晰出method,这样一个真实完好的Rest API就诞生了。
3.Object(元数据)
在rest api中清晰了Resource的kind、apiVersion, 也确认了Object的namespace、name,作为但凡k8s资源目标都会引证的公共结构,自然也存在许多公共机制供运用。
metadata:
annotations:
alibabacloud.com/owner: testdemo
k8s.aliyun.com/pod-eni: "true"
creationTimestamp: "2022-06-02T07:21:36Z"
deleteTimestamp: "2022-06-02T07:22:51Z"
labels:
app: taihao-app-cn-shanghai-pre-cloud-resource
pod-template-hash: 5bbb759f78
name: testdemo-5bbb759f78-27v88
namespace: default
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
controller: true
kind: ReplicaSet
name: testdemo-5bbb759f78
uid: 9c3f268a-c0d1-4038-bb2b-b92928f45e3d
resourceVersion: "60166035"
uid: e4236960-8be2-41bf-ac44-e7460378afbb
观察上述YAML,咱们将其收拾一下,有这样一些字段:
- namespace:常规来说,Namespace资源才会运用该资源目标
- name:代表资源实例称号
- uid:是资源的唯一标识,可以差异已删去与从头创立的同名资源实例
- resourceVersion:是k8s的内部版本,具有时刻特点,依据此就能清晰该资源对是什么时分发生改动的,也是确保k8s list-watch中心机制
- creationTimestamp: 资源实例创立时刻
- deleteTimestamp: 资源实例删去时刻,后续会在pod的生命周期内讲到对该字段应用
- ownerReferences: 资源从属目标,从上面yaml可知,该Pod资源从属于名为testdemo-5bb759f78, ownerReferences内部是没有namespace参数,也便是ownerReferences不允许跨namespace, 将资源由下到上可以建立起来
- labels:标签, k8s内的服务发现以及相应的软关联,都是围绕label运作的,比方testdemo-5bb759f78 replicaset 的labelselector(标签挑选器)可以挑选到当时Pod的label,确保两者关联由上到下的建立
-
annotations: 注释,一般来说会是作为额定字段供应给周边体系运用,比方当时
k8s.aliyun.com/pod-eni="true"
是供给网络体系运用
label & labelSelector
Deployment 会依据自己的labelseletor:app=taihao-app-cluster 以及计算出podtemplate的hash lable:pod-template-hash: 5b8b879786 , 挑选出出契合的replicaset, replicaset再依据自己的labelselector 去挑选出契合的pods, 相应的服务发现service,也是经过labelselector去挑选出契合的Pod
Owner & GC(废物收回)
依据Pod的metadata.ownerReferences找寻到对应的replicaset,replicaset依据本身的metadata.ownerReferences 找寻到deploy;当deployment被删去后,依据原有owner构建的树状,收回原有的rs与pod。
Deploy & Replicaset
依据label&labelselector,清晰了从上到下的挑选概括;依据owner&GC,清晰了关联资源的收回流程。
apiVersion: apps/v1
kind: ReplicaSet
metadata:
generation: 1
labels:
app: testdemo
pod-template-hash: bcd889947
name: testdemo-bcd889947
namespace: taihao
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
controller: true
kind: Deployment
name: testdemo
uid: 1dddc849-c254-4cf5-aec8-9e1c2b5e65af
spec:
replicas: 1
selector:
matchLabels:
app: testdemo
pod-template-hash: bcd889947
template:
metadata:
creationTimestamp: null
labels:
app: testdemo
pod-template-hash: bcd889947
spec:
containers:
- args:
- -c
- sleep 1000000
command:
- sh
image: centos:7
imagePullPolicy: IfNotPresent
name: testdemo
status:
fullyLabeledReplicas: 1
observedGeneration: 1
replicas: 1
replicaset.spec.replicas: 实例数,rs操控下的Pod个数
replicaset.spec.selector:依据label 挑选出对应的Pod
replicaset.spec.template:replicaset创立的Pod会依据podtemplate
replicaset.status:replicaset 当时管理Pod的情况
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: testdemo
name: testdemo
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: testdemo
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: testdemo
spec:
containers:
- args:
- -c
- sleep 1000000
command:
- sh
image: centos:7
imagePullPolicy: IfNotPresent
name: testdemo
status:
availableReplicas: 1
observedGeneration: 2
readyReplicas: 1
replicas: 2
unavailableReplicas: 1
updatedReplicas: 1
deploy.spec.replicas: deploy希望的pod实例格局
deploy.spec.revisionHistoryLimit:deploy 管理replicaset的保存三个月
deploy.spec.selector:deploy 挑选契合标签
deploy.spec.strategy:deploy的升级战略
deploy.template:deploy依据此模版要创立的pod格局
4.Spec(标准)
Spec作为Pod的希望情况,必定程度上也覆盖了Pod完好生命周期的逻辑,Pod的生命周期分为以下阶段
- Pending:代表Pod处于未调度阶段
- Creating:节点上的kubelet已经发现了Pod,处于创立阶段
- Running:至少一个容器运转结束,kubelet这会建议健康监测
- Terminating:Pod处于删去情况,kubelet开端收回容器
- Terminated: Pod 销毁完结
Pod生命周期: Pending
Pod资源创立结束后,处于还未调度阶段,这个时分scheduler(调度器)依据pod yaml本身的装备与节点资源情况情况,来进行调度。
scheduler会去剖析podyaml,将其间的战略提取出来,与节点组中的节点装备进行匹配,若匹配成功后,会选出最佳节点,从头修正pod yaml,将spec.nodeName更新掉,完结整个调度环节
资源战略
资源战略标明Pod运转需求的资源情况,以demo为例,Pod需求2核4G的资源,那么调度过去的节点也需求有2核4G的资源剩下,Pod才干运转在该节点上
节点标签挑选战略
节点标签挑选战略,挑选节点是否存在topology.kubernetes.io/region: cn-hangzhou
亲和战略
亲和战略,有节点亲和与Pod亲和(Pod地点节点优先调度),常规来说可以优先满意亲和的节点上,当时比方便是节点亲和,满意标签disk-type=aaa
或许disk-type=bbb
污点战略
污点战略,当节点上装备了污点,若Pod没有容忍该污点的战略,则Pod不允许调度到该节点上
Pod生命周期: Creating
当Pod调度结束后,开端创立阶段,kubelet会依据pod.spec 希望情况来创立出Pod
kubelet 在创立Pod阶段,一共大致经历以下过程
- Group装备:首要是为了容器装备cgroup,里边触及了对容器资源约束,比方不允许超越cpu、memory装备,这儿触及到Pod的qos级别断定
- 初始化环境装备:首要是对相关Pod数据存储目录进行装备,触及到volume,则会去引证CSI协议,也会去获取镜像secret,为了后续拉取镜像进行准备工作
- 创立pause容器:创立pause容器,该容器首要是为了后续装备容器网络,装备容器网络会去调用CNI
- 创立Pod容器:依据imagesecret拉取事务镜像,在创立Pod容器阶段,也会将相应的Pod YAML装备传输进去,在发动Pod容器结束后,会依据poststart进行相关的回调
上述阶段,会挑选部分要害概念进行详细说明
image
spec:
containers:
- image: testdemo:v1
imagePullPolicy: Always
name: test-config
imagePullSecrets:
- name: image-regsecret
imagePullSecrets: 拉取镜像的密钥,确保可以拉取image:testdemo:v1,尤其在镜像库是私有库的阶段
imagePullPolicy:镜像拉取战略
- Always:总是拉取镜像
- IfNotPresent:本地若有则运用本地镜像,不进行拉取
- Never:只运用本地镜像,不拉取
containers
留意这个containers用的是复数,可以填多个容器镜像: 比方可以放 nginx 和 事务容器。这样做的好处是可以尽量削减事务容器中与事务无关的代码或进程。
container触及许多装备,其间有触及到volume、env、dnsconfig、host等基础装备
spec:
containers:
- env:
- name: TZ
value: Asia/Shanghai
image: testdemo:v1
name: taihao-app-cn-shanghai-pre-share
volumeMounts:
- mountPath: /home/admin
name: test-config
readOnly: true
dnsConfig:
nameservers:
- 100.100.1.1
- 100.100.2.1
options:
- name: ndots
value: "3"
- name: timeout
value: "3"
- name: attempts
value: "3"
searches:
- default.svc.cluster.local
- svc.cluster.local
- cluster.local
hostAliases:
- hostnames:
- kubernetes
- kubernetes.default
- kubernetes.default.svc
- kubernetes.default.svc.cluster.local
ip: 1.1.1.1
volumes:
- configMap:
defaultMode: 420
name: test-config
name: test-config
env:装备Pod的环境变量
dnsConfig:装备Pod的域名解析
hostALiases:装备/etc/hosts文件内容
volume/volumeMount: 装备文件挂载到容器内,也可以装备文件存储体系挂载到容器内
postStart
containers:
- image: testdemo:v1
imagePullPolicy: Always
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- sleep 5
当时poststart demo 是建议command指令,也可以建议http恳求,首要效果可以作为资源布置以及环境准备。
Pod生命周期: Running
在Pod running阶段的时分,Pod就迎来对其健康的查看,当时kubelet 供给三种方法断定
- readiness:查看Pod是否为健康
- liveness:件看Pod是否正常,若查看失利,则重启容器
- readinessGate:供给给第三方组件健康验证,第三方组件验证不过,则Pod不为健康
spec:
readinessGates:
- conditionType: TestPodReady
containers:
- image: testdemo:v1
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
initialDelaySeconds: 45
periodSeconds: 5
successThreshold: 1
tcpSocket:
port: 8080
timeoutSeconds: 1
readinessProbe:
failureThreshold: 3
httpGet:
path: /actuator/health
port: 8989
scheme: HTTP
initialDelaySeconds: 25
periodSeconds: 3
successThreshold: 1
timeoutSeconds: 1
readiness与liveness查看参数都是共同的
- httpGet / tcpSocket:都是查看方法,一种是http恳求验证,一种是tcpSocket,其间也有exec执行指令,以及grpc方式验证
- initialDelaySeconds:延迟多久开端查看,原因在于容器发动的时分,一般需求过段时刻进行验证
- periodSeconds:查验时刻周期
- failureThreshold:接连几回失利,则代表这轮查验失利
- successThreshold:接连几回成功,则代表这轮查验成功
- timeoutSeconds:代表查验超时时刻,若查验在该装备时刻内没有回来,则认为查验失利
readiness、liveness虽然参数不一样,但对查验的成果行为不共同。
- readiness默许情况下为false,也便是Pod为不健康,直到查看经过,才将Pod变为健康
- liveness默许情况下为true,不会在刚开端就将Pod重启,只有等查看不经过后,才会进行容器重启操作
readinessGate 是Pod健康的扩展,kubelet会依据此,默许在pod.status.conditions上装备对应的condition, 比方当时比方readinessGate为conditionType: TestPodReady
, 则相应就会有conditions
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2022-07-05T09:16:07Z"
status: "false"
type: TestPodReady
当该condition.status为false时,则Pod就会一直是不健康,哪怕readiness查看经过,直到第三方体系去操作更新Pod该condition.status为true,才干够将Pod变为健康,这样就可以接入更多的Pod健康目标。
Pod生命周期: Terminating
client 在建议恳求删去Pod的时分,实际上是装备
pod.metadata.deletionTimestamp,kubelet感知到后,开端进行Pod收回流程
整个Pod的收回周期,常规来说preStop—>SIGTERM—>SIGKILL
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- sleep 5
当kubelet进行preStop后,开端建议SIGTERM给容器内进程,若超越总默许耗时30S(metadata.DeletionGracePeriodSeconds),则强制建议SIGKILL给容器,也便是prestop+SIGTERM总耗时不允许超越30s。
5.Status(情况)
status:
conditions:
- lastProbeTime: null
lastTransitionTime: "2022-07-05T09:16:07Z"
status: "True"
type: TestPodReady
- lastProbeTime: null
lastTransitionTime: "2022-07-05T09:16:07Z"
status: "True"
type: Initialized
- lastProbeTime: null
lastTransitionTime: "2022-07-05T09:16:14Z"
status: "True"
type: Ready
- lastProbeTime: null
lastTransitionTime: "2022-07-05T09:16:14Z"
status: "True"
type: ContainersReady
- lastProbeTime: null
lastTransitionTime: "2022-07-05T09:16:07Z"
status: "False"
type: ContainerDiskPressure
- lastProbeTime: null
lastTransitionTime: "2022-07-05T09:16:07Z"
status: "True"
type: PodScheduled
containerStatuses:
- containerID: containerd://xxxxx
image: docker.io/library/testdemo:v1
imageID: docker.io/library/centos@sha256:xxxx
lastState: {}
name: zxtest
ready: true
restartCount: 0
started: true
state:
running:
startedAt: "2022-07-05T09:16:13Z"
hostIP: 21.1.96.23
phase: Running
podIP: 10.11.17.172
podIPs:
- ip: 10.11.17.172
qosClass: Guaranteed
startTime: "2022-07-05T09:16:07Z"
依据上述YAML样例,将Pod status情况拆建出来剖析一下:
-
conditions: conditions是作为一种更详尽的情况报告,其本身也是一种扩展机制,其他的扩展字段也可以放入其间,比方可以标明网络情况,其间readinessGate便是这种扩展机制的表现,但决定Pod是否ready,永远只看type: Ready是否为true
-
containerStatuses: Pod内各容器的情况
-
hostIP: Pod地点节点ip地址
-
phase: Pod的生命周期情况
- Pending:代表Pod有一个容器或许多个容器还未运转,其间包含Pod调度到节点之前以及拉取镜像
- Running:代表Pod已绑定到节点上,至少有一个容器运转或在重启
- Successed:代表Pod一切容器已终止
- Failed:代表Pod内至少有一个容器终止失利
- Unknown:代表无法获取Pod情况
-
podIP / podIPs:Pod的IP地址,假如有ipv4、ipv6,则可以在podIPs上装备
-
qosClass:代表kubernetes服务等级
- Guaranteed:resource.requests与resource.limits共同
- Burstable:resource.requests与resource.limits 不共同
- BestEffort:没有装备resource.requests与resource.limits
- startTime:发动时刻
经过以上Pod四个部分拆解,咱们根本搞清了一个Pod在k8s下“从哪里来”的这个问题。本系列的后续的文章会对“到哪里去”这个问题继续打开:Kubernetes的魅力在于不仅仅是拉起一个工作负载,而是可以召之即来挥之即去地编列海量工作负载。
后续文章均会发布在咱们的大众号“阿里智能运维”上,请咱们继续重视~也欢迎咱们在大众号后台留言想了解的内容和感兴趣的相关论题,与SREWorks团队进行交流。