什么是Pod
Pod是K8S的一个逻辑概念,Pod其实是一组紧密协作的容器,容器就是我们应用程序执行代码的地方,在K8S里管理员要去管理应用的生命周期(包括异常退出等),那就需要获取应用运行的状态,获取应用的状态需要获取容器的运行状态。容器在K8S里是一个单进程,该进程就是应用进程,这样就可以从外部获取容器现在的状态,一个Pod内所有的进程共享资源。
为什么K8S要有Pod
方便去管理容器进程,也就是方便管理容器内主要的应用进程。
图为物理机,物理机上已经安装好了Kubelet进程,Kubelet接收到安装文件(一个有Pod信息)会先创建Infra Container(是一个镜像,大概 100~200KB 左右,永远处于暂停状态的容器。是用来对Pod共享网络的)会对Docker0这个网桥进行网络连接,然后其他Pod内部的容器在依次创建后会共享Infra网络,实现一个Pod内的网络共享。存储的共享还是需要每个Pod去挂载相同的存储地址来实现。
容器内使用Pod信息
1.通过环境变量
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName # 根据配置 "层级.引用" 类似key-value
2.通过配置文件
volumes: # 使用volume挂载到Pod
- name: podinfo
downwardAPI: # 使用该API,支持Pod和Container的信息
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
Pod健康检查
有三类探针:
- LivenessProbe: 判断是否存活,kubelet默认会重启不是存活的Pod
- ReadinessProbe:判断是否可用,service只有在readinessProbe为ready状态,对外提供服务
- StartupProbe:有且仅有一次的超长启动延时(针对慢应用)
探针的实现方式:
livenessProbe:
exec:
command:
- cat
- /tmp/health
livenessProbe:
tcpSocket:
port: 80
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 30 # 容器首次健康服务检查等待时间
timeoutSeconds: 1 # 等待健康检查相应的时间
Pod资源控制
资源控制范围包括:CPU,Memory和扩展资源如GPU(扩展资源只能获取整数个资源)
apiVersion: v1
kind: Pod
metadata:
name: test
spec:
containers:
- name: test
image: busybox
resources: # 机器上至少有这么多的资源才能被创建
request:
memory: "64Mi"
cpu: "250m"
ephemeral-storage: "2Gi"
limits: # 机器上至多有这么多的资源能被使用
memory: "128Mi"
cpu: "500m"
ephemeral-storage: "4Gi"
限制每个Namespace资源用量,超出限制时,用户无法提交新建
apiVersion: v1
kind: ResourceQuota
metadata:
name: demo
namespace: demo
spec:
hard:
cpu: "1000" #这个namespace下面的所有Pod使用的资源总量不超过1000
memory: 200Gi
pods: "10"
Pod Qos服务质量
就是说我们有多个Pod,每一个Pod重要程度不一样,比如某些Pod就算是在资源不足的时候我们也不希望他们会被驱逐。
所以可以对Pod的服务质量进行一个分类,分别是Guranteed,Bursable和BestEffort
Guranteed:Pod里面每个容器都会有内存和CPU的request声明和limit声明,且request和limit必须是一致的,以此告诉K8S这些Pod很重要,一定要保证Pod正常运行。
Bursable: 至少有一个容器存在内存和CPU的一个request,优先级比Guranteed低
BestEffort:request和limit都不填,意味着这个Pod可有可无
系统用request进行调度的,对CPU资源而言,系统会对Guranteed的Pod单独划分CPU资源,Bursable和BestEffort共用CPU资源(按照权重来使用不同的时间片),内存对资源而说,会对Pod划分OOMScore,score越高越优先被杀掉,Guranteed固定为-998,BestEffort固定为1000,Bursable则是按照内存大小和节点关系会根据算法计算出2~999范围内的值 ,资源不足发生驱逐时,优先驱逐BestEffort定义的容器。
Pod的调度
当我们希望Pod能够在指定的机器上运行的时候,或者定义那两个Pod在同一个机器上,或者定义那两个Pod不在同一个机器上,就要用到亲和度。
Pod亲和调度
1.PodAffinity
- requiredDuringSchedulingIgnoredDuringExecution:强制亲和(调度时,执行亲和校验;运行时,忽略标签内发生的变化带来的影响)
- preferredDuringSchedulingIgnoredDuringExecution:优先亲和
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In #操作符 In NotIn Exist DoesNotExist Gt Lt
values:
- S1
topogyKey: kubernetes.io/hostname #设置拓扑键,默认的设置topology.kubernetes.io/region topology.kubernetes.io/zone
2.podAntAffinity
- requiredDuringSchedulingIgnoredDuringExecution:强制反亲和
- preferredDuringSchedulingIgnoredDuringExecution:优先反亲和
Node亲和调度
1.NodeSelector: 强制调度到指定节点(强制调度Pod在指定的机器上创建)
2.NodeAffinity
- requiredDuringSchedulingIgnoredDuringExecution:强制反亲和
- preferredDuringSchedulingIgnoredDuringExecution:优先反亲和
3.Taint:一个Node可以有多个Taints
1.行为模式有:
-
PreferNoSchedule: 尽量不要调度过来
-
NoSchedule:禁止Pod调度来
-
NoExecute: 驱逐没有tolerantion的Pod,并禁止调度新的(如果有的Pod已经在运行了,而且没有tolerantion,就会被杀掉并调度到新的机器上)
apiVersion: v1 kind: Node metadata: name: demo spec: taints: - key: "k1" value: "v1" effect: "NoSchedule"
2.Pod的tolernation,只有设置对应的tolernation才能调度到有Taint的Node上
apiVersion: v1
kind: Pod
metadata:
namespace: demo
name: demo
spec:
containers:
- image: busybox
name: demo
tolerations:
- key: "k1"
operator: "Equal"
value: "v1" # 当op=Exist 可以为空 key和value和effect必须匹配上面的taints,这样Pod才能被调度到打了taint的Node上
effect: "NodSechedule" # 可以为空,匹配所有
tolerationsSeconds: 3600 #taint添加后,pod还能在node上运行的时间
优先级调度
很多Pod同时创建时,有的优先级高,有的优先级低。这时kubelet会根据Pod配置priority,得分高的会对得分低的进行资源抢占
1.使用PriorityClass创建节点,Pod中通过PriorityClassName引用相应优先级
apiVersion: v1
kind: PriortyClass
metadata:
name: high
value: 1000
globalDefault: false
2.系统默认优先级
1.没有设置均为0
2.用户可配置最大优先级为10亿,系统级别优先级为20亿
3.内置系统优先级:system-cluster-critical,system-node-critical
Pod调度过程
用户调教Yaml文件,webhook controller 会先对文件进行校验,校验成功后,Api-Server会创建Pod对象,这个对象会保存到ETCD里面。此时Pod的Node名称为空(这个Pod已经有了,但是还没有落实到相应的节点上),Kube Scheduler (Kube Scheduler 会不断查看资源对象,发现某个Pod刚创建,但Node是空的,就会创建)会watch到Pod的创建,同时发现Node名称为空,会找到合适的Node,并修改Pod名称为相应的Node名,相应节点上的kubelet watch(这个进程会不断的请求Api-Server去发现他的节点上有个Pod需不需要创建) 到Pod需要创建,会在Node节点上创建容器和网络。
其他
InitContainer
比普通容器先启动,执行成功后普通容器才能启动,且是按照顺序执行,执行完之后会关闭。普通容器可以并发启动。
Sidecar 容器设计模式
用一个辅助容器做辅助工作,如日志收集,debug,前置操作等。好处:对应业务代码没有侵入:功能解耦,共享,模式包括:
代理模式:代理网络等
适配器模型:适配不同外观需求
Pod容灾
让Pod在不同的区域内分布,实现Pod容灾
topologySpreadConstraints:
- topogyKey: address
maxSkew: 1 # 用于指明Pod在各个zone中容忍的最大不均匀数,值越小每个zone中Pod分布越均匀
whenUnsatisfiable: DoesNotSchedule
labelSelector:
matchLabels:
app: myapp
Pod容灾
让Pod在不同的区域内分布,实现Pod容灾
topologySpreadConstraints:
- topogyKey: address
maxSkew: 1 # 用于指明Pod在各个zone中容忍的最大不均匀数,值越小每个zone中Pod分布越均匀
whenUnsatisfiable: DoesNotSchedule
labelSelector:
matchLabels:
app: myapp