创建一个pod 的工作流程
kubectl run pod2 --image=nginx
1、kubectl向apiserver发起创建pod请求,apiserver将创建pod配置写入etcd
2、scheduler收到apiserver有新pod的事件,scheduler根据自身调度算法选择一个合适的节点,并打标记 pod=k8s-node1
3、kubelet收到分配到自己节点的pod,调用docker api创建容器,并获取容器状态汇报给apiserver
controller-manager 负责控制器的创建,例如deployment
kube-proxy 负责service的创建
requests:最小的申请值,limits:容器最大使用上限
2、requests 必须小于limits,小于limits 20%-30%(良性)
、limits尽量不要超过宿主机实际物理配置,不然限制没意义
4、requests会影响pod调度,必须有节点能够满足该配置pod才能运行
5、requests只是一个预留性质,并非实际占用
节点资源空闲
节点资源紧张
Kubernetes基于list-watch机制的控制器架构,实现组件间交互的解耦。
其他组件监控自己负责的资源,当这些资源发生变化时, kubeapiserver会通知这些组件,这个过程类似于发布与订阅。
Pod中影响调度的主要属性
资源限制对Pod调度的影响
容器资源限制:
resources.limits.cpu
resources.limits.memory
容器使用的最小资源需求,作为容器调度时资源分配的依据:
resources.requests.cpu
resources.requests.memory
CPU单位:可以写m也可以写浮点数,例如0.5=500m, 1=1000m
nodeSelector & nodeAffinity的区别
nodeSelector:
用于将Pod调度到匹配Label的Node上,如果没有匹配的标签会调度失败。
作用:
• 约束Pod到特定的节点运行
• 完全匹配节点标签
应用场景:
• 专用节点:根据业务线将Node分组管理
• 配备特殊硬件:部分Node配有SSD硬盘、 GPU
案例: 确保Pod分配到具有SSD硬盘的节点上
第一步:给节点添加标签
格式: kubectl label nodes <node-name> <label-key>=<label-value>
例如: kubectl label nodes k8s-node1 disktype=ssd
验证: kubectl get nodes --show-labels
#yaml文件
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
nodeSelector:
disktype: “ssd”
containers:
- name: nginx
image: nginx:1.19
第二步:添加nodeSelector字段到Pod配置中
最后,验证:
kubectl get pods -o wide
删除节点标签: kubectl label node k8s-node1 <label-key>
nodeAffinity:
节点亲和类似于nodeSelector,可以根据节点上 的标签来约束Pod可以调度到哪些节点。
相比nodeSelector
• 匹配有更多的逻辑组合,不只是字符串的完全相等,支持的操作
符有: In、 NotIn、 Exists、 DoesNotExist、 Gt、 Lt
• 调度分为软策略和硬策略,而不是硬性要求
• 硬(required):必须满足
• 软(preferred):尝试满足,但不保证
Taint(污点)与Tolerations(污点容忍)
基于节点标签分配是站在Pod的角度上,通过在Pod上添加属性,来确定Pod是否要调度到指定的Node上,其实我们也可以站在 Node的角度上,通过在Node上添加污点属性,来避免Pod被分配到不合适的节点上。
Taints:
Tolerations:
第一步:给节点添加污点
格式: kubectl taint node [node] key=value:[effect]
例如: kubectl taint node k8s-node1 gpu=yes:NoSchedule
验证: kubectl describe node k8s-node1 |grep Taint
其中[effect] 可取值:
• NoSchedule :一定不能被调度
• PreferNoSchedule:尽量不要调度,非必须配置容忍
• NoExecute:不仅不会调度,还会驱逐Node上已有的Pod
第二步:
如果希望Pod可以被分配到带有污点的节点上,要在Pod配置
中添加污点容忍(tolrations)字段
删除污点: kubectl taint node [node] key:[effect]-
nodeName: 指定节点名称,用于将Pod调度到指定的Node上,不经过调度器。
#yaml案例
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
nodeName: k8s-node2
containers:
- name: web
image: nginx
1、nodeselector与taint是分别独立,两者都用都必须满足
2、这两个完美组合,指哪打哪
3、如果加污点容忍,该pod会肯定分配到带有污点的节点上嘛?
不会
master节点为什么打污点?
1、管理节点
2、安全
tolerations:
# Make sure calico-node gets scheduled on all nodes.
- effect: NoSchedule
operator: Exists
# Mark the pod as a critical add-on for rescheduling.
- key: CriticalAddonsOnly
operator: Exists
- effect: NoExecute
operator: Exists
deployment特点:用镜像可以启动多个pod副本,一模一样,会分散到集群节点上。
DaemonSet功能
• 在每一个Node上运行一个Pod
• 新加入的Node也同样会自动运行一个Pod
应用场景:网络插件、监控Agent、日志Agent
示例:部署一个日志采集程序
调度失败原因分析
#查看调度结果:
kubectl get pod <NAME> -o wide
查看调度失败原因:
节点CPU/内存不足
有污点,没容忍
没有匹配到节点标签
1、多个pod副本如何统一对外提供服务?
增加负载均衡器
2、pod短暂的,如何保障这一组pod的准确性?
可以指定pod ip、pod名称