天河手机网站建设网站建设 讲话
news/
2025/9/27 11:03:31/
文章来源:
天河手机网站建设,网站建设 讲话,前端为啥不用wordpress,房屋设计师室内设计目录
pod启动创建过程
kubelet持续监听的原因
调度概念
调度约束
调度过程
优点
原理
优先级选项
示例
指定调度节点
标签基本操作
获取标签帮助
添加标签#xff08;Add Labels#xff09;#xff1a;
更新标签#xff08;Update Labels#xff09;
删除标…目录
pod启动创建过程
kubelet持续监听的原因
调度概念
调度约束
调度过程
优点
原理
优先级选项
示例
指定调度节点
标签基本操作
获取标签帮助
添加标签Add Labels
更新标签Update Labels
删除标签Remove Labels
查询标签Query Labels
使用标签选择器Label Selectors
标签匹配的运算符
亲和性
节点亲和性
Pod 亲和性
硬策略和软策略
硬策略示例
软策略示例
软硬策略结合示例
pod亲和和反亲和
调度策略
Pod 亲和性调度策略的详细说明
示例
创建一个标签为 appmyapp01 的 Pod
使用 Pod 亲和性调度创建多个 Pod 资源
使用 Pod 反亲和性调度
污点(Taint) 和 容忍(Tolerations)
概念
格式和支持的效果选项
污点的基本操作
添加污点
查看污点
删除污点
示例
容忍
举例说明
值得注意的操作
维护节点和应用程序操作
pod启动阶段的状态解读与排错技巧
Pod启动阶段相位 phase
pod可能的状态
故障排除步骤 pod启动创建过程
这里有三个 List-Watch分别是 Controller Manager运行在 MasterScheduler运行在 Masterkubelet运行在 Node。 他们在进程已启动就会监听WatchAPIServer 发出来的事件。 用户通过 kubectl 或其他 API 客户端提交创建 Pod 的请求给 APIServer APIServer 将 Pod 对象的元数据尝试存入 etcd 中待写入操作执行完成APIServer返回确认信息给客户端。 etcd 接受创建 Pod 的信息后在集群中保存该信息并触发 Create 事件给APIserver。 Controller Manager 监听到 Create 事件后调用 Replication Controller 来确保 Node 上的副本数量符合定义。一旦副本数量少于 RC 中定义的数量RC 会自动创建副本。总之它是保证副本数量的 ControllerPS扩容缩容的担当。 Replication Controller 创建 Pod 的副本。 APIServer 更新 etcd 中的 Pod 信息并向 Controller Manager 发送更新事件。 Scheduler 监听到更新事件后根据调度算法将 Pod 绑定到合适的 Node 上。 Scheduler 更新 Pod 的信息包括它所部署的 Node然后将信息反馈给 APIServer。 APIServer 更新 etcd 中的 Pod 信息并将更新成功的事件发送给 Scheduler。 kubelet 在 Node 上监听 APIServer 发送的 Pod 更新事件根据更新信息调用 Docker 启动容器。 kubelet 将 Pod 的状态信息反馈给 APIServer并更新至 etcd。 APIServer 将 Pod 的状态信息持久化存储在 etcd 中APIServer将确认信息发送至相关的 kubelet事件将通过它被接受完成整个启动创建过程。
kubelet持续监听的原因
kubelet持续监听的原因在于保持对集群中 Pod 状态的实时感知和响应。即使创建过程完成kubelet仍然需要 实时调整资源 如果通过 kubectl 进行扩容或缩容操作kubelet会感知这些变化根据最新的 Pod 副本数量调整 Node 上的资源。 镜像更新 如果 Pod 的镜像文件升级kubelet会自动获取最新的镜像文件并加载确保 Pod 使用的是最新的容器镜像。
通过持续监听kubelet能够及时响应各种变化确保集群中的 Pod 始终处于最新、正确的状态。这种实时性是 Kubernetes 系统的关键特性之一。
调度概念
Kubernetes集群调度是指Kubernetes系统中的调度器scheduler负责将应用程序的工作负载如Pod分配到可用的集群节点上。调度器通过考虑诸如节点资源利用率、硬件约束、亲和性和反亲和性规则等因素选择最佳的节点来放置Pod以实现高效的资源利用和负载均衡。调度器的工作包括评估节点的可用资源、满足Pod的资源需求、遵循用户定义的调度策略等。 Kubernetes 是通过 List-Watch 机制进行每个组件的协作保持数据同步的每个组件之间的设计实现了解耦。 用户是通过 kubectl 根据配置文件向 APIServer 发送命令在 Node 节点上面建立 Pod 和 Container。 APIServer 经过 API 调用权限控制调用资源和存储资源的过程实际上还没有真正开始部署应用。这里 需要 Controller Manager、Scheduler 和 kubelet 的协助才能完成整个部署过程。 在 Kubernetes 中所有部署的信息都会写到 etcd 中保存。实际上 etcd 在存储部署信息的时候会发送 Create 事件给 APIServer而 APIServer 会通过监听Watchetcd 发过来的事件。其他组件也会监听WatchAPIServer 发出来的事件。
调度约束
Kubernetes中的调度约束这些约束是指在将Pod调度到节点上时需要考虑的各种条件和限制。这些约束包括但不限于 资源约束 每个节点有一定的资源限制如CPU和内存。调度器会考虑Pod的资源请求和节点的可用资源确保Pod能够得到满足并不会超出节点的资源容量。 亲和性和反亲和性 可以指定Pod之间或Pod与节点之间的亲和性和反亲和性规则以确保它们被调度到合适的节点上。例如可以将Pod调度到与特定标签匹配的节点上或者避免将它们调度到某些节点上。 节点亲和性 通过节点亲和性规则可以指定Pod应该调度到与某些节点属性匹配的节点上。例如将Pod调度到具有特定硬件特性或数据存储的节点上。 Pod 亲和性 通过Pod亲和性规则可以确保一组Pod被调度到同一节点上或者避免它们被调度到同一节点上。 污点和容忍 污点用于标记节点上的不可接受条件而容忍则允许一些Pod调度到带有污点的节点上。这有助于将特定类型的工作负载调度到适合的节点上。
这些约束通过Kubernetes的调度器实现调度器会根据这些约束选择最佳的节点来放置Pod以满足用户需求并确保集群的高效利用。
调度过程
Kubernetesk8s调度涉及调度器、控制器管理器和kubelet。当使用kubectl创建作业时kube-controller检测到它创建一个Pod实例并将其发送到API服务器。kube-scheduler在检测到未调度的Pod时选择一个节点将Pod绑定到它并向API服务器发送绑定指令。相应节点上的kubelet在检测到绑定指令后指示节点的容器API运行Pod。这个过程确保了Kubernetes集群中资源的有效分配和工作负载的分发。
优点
Scheduler是Kubernetes的调度器其主要任务是将定义的Pod分配到集群的节点上。 公平确保每个节点都能获得公平的资源分配避免资源不均衡。 资源高效利用最大化集群中所有资源的利用率确保资源被充分利用而不浪费。 效率调度器需要具备良好的性能能够快速而有效地对大批量的Pod完成调度工作以满足用户的需求。 灵活允许用户根据自己的需求控制调度的逻辑例如通过标签、调度策略等方式定制调度规则以适应不同的应用场景和需求。
原理
调度器作为一个独立的程序运行并监听 API Server负责将未指定节点的 Pod 分配到合适的节点上。整个调度过程分为预算策略predicate和优选策略priorities两个阶段分别用于先过滤不满足条件的节点和对通过的节点进行排序。最后从中选择优先级最高的节点进行调度。如果在任何一个阶段出现错误调度器会立即返回错误信息。
如果在 predicate 过程中没有合适的节点pod 会一直在 pending 状态不断重试调度直到有节点满足条件。 经过这个步骤如果有多个节点满足条件就继续 priorities 过程按照优先级大小对节点排序。
优先级选项
Kubernetes Pod 调度过程中使用的一系列优先级选项及其作用 LeastRequestedPriority最低资源请求优先级根据节点的 CPU 和内存使用率来确定权重使用率越低的节点权重越高。这意味着优先选择资源利用率较低的节点来部署 Pod。 BalancedResourceAllocation平衡资源分配优先级根据节点上 CPU 和内存使用率的平衡程度来确定权重。如果节点上的 CPU 和内存使用率越接近权重越高。通常与最低资源请求优先级一起使用以便在选择节点时考虑资源的平衡分配。 ImageLocalityPriority镜像本地性优先级倾向于选择已经存在所需镜像的节点部署 Pod。权重根据镜像的总大小来确定镜像总大小越大权重越高。
示例
举例来说假设有三个 Kubernetes 节点node01、node02 和 node03。现在有一个 Pod 需要调度到其中一个节点上。 LeastRequestedPriority最低资源请求优先级如果 node01 的 CPU 和内存使用率较低node02 的使用率中等而 node03 的使用率较高那么优先选择调度到 node01因为它的资源使用率最低。 BalancedResourceAllocation平衡资源分配优先级假设 node01 的 CPU 使用率为20%内存使用率为60%而 node02 的 CPU 和内存使用率均为50%则根据平衡资源分配优先级可能更倾向于选择 node02因为它的资源使用情况更平衡。 ImageLocalityPriority镜像本地性优先级如果 node01 已经存在 Pod 所需的镜像而 node02 和 node03 没有那么优先选择调度到 node01因为它具有镜像的本地性。
指定调度节点
pod.spec.nodeName 将 Pod 直接调度到指定的 Node 节点上会跳过 Scheduler 的调度策略该匹配规则是强制匹配
vim myapp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: myapp
spec:replicas: 3selector:matchLabels:app: myapptemplate:metadata:labels:app: myappspec:nodeName: node01containers:- name: myappimage: soscscs/myapp:v1ports:- containerPort: 80kubectl apply -f myapp.yamlkubectl get pods -o wideapiVersion: apps/v1: 指定了使用的 Kubernetes API 版本。 kind: Deployment: 定义了这个配置文件描述的 Kubernetes 资源类型即部署。 metadata: 包含有关资源的元数据比如名称。 name: myapp: 指定部署的名称为 myapp。 spec: 定义了部署的规格包括副本数量、选择器和模板。 replicas: 3: 指定了要创建的 Pod 的副本数量为 3。 selector: 定义了用于选择要管理的 Pod 的标签。 matchLabels: 指定了匹配标签的条件。 app: myapp: 指定了标签 app 的值为 myapp。 template: 定义了要创建的 Pod 的模板。 metadata: 包含了 Pod 模板的元数据包括标签。 labels: 指定了 Pod 模板的标签。 app: myapp: 指定了标签 app 的值为 myapp。 spec: 指定了 Pod 的规格。 nodeName: node01: 使用 nodeName 字段将 Pod 直接调度到名为 node01 的节点上。 containers: 指定了要在 Pod 中运行的容器列表。 name: myapp: 定义了容器的名称为 myapp。 image: soscscs/myapp:v1: 指定了要在容器中运行的镜像。 ports: 指定了容器要监听的端口。 containerPort: 80: 指定了容器监听的端口号为 80。
通过应用此配置文件成功地创建了一个名为 myapp 的 Deployment其中包含了三个 Pod每个 Pod 都直接调度到了名为 node01 的节点上并且每个 Pod 内运行一个名为 myapp 的容器该容器使用 soscscs/myapp:v1 镜像并监听端口 80。
kubectl describe pod myapp-查看详细事件发现未经过 scheduler 调度分配
这些事件显示了 Pod 的创建过程但没有显示与调度相关的事件这是因为在 Pod 的配置中明确指定了 nodeName: node01这意味着 Pod 将直接调度到名为 node01 的节点上而不经过调度器的调度分配过程。
因此在描述中看不到与调度相关的事件而只能看到与 Pod 创建、拉取镜像、容器创建和启动等过程相关的事件。
pod.spec.nodeSelector通过 kubernetes 的 label-selector 机制选择节点由调度器调度策略匹配 label然后调度 Pod 到目标节点该匹配规则属于强制约束
标签基本操作
获取标签帮助
kubectl label --help添加标签Add Labels
添加标签是为资源附加额外的元数据以便更容易地对其进行标识和分类。例如为名为nginx的Pod添加标签appweb
kubectl label 资源类型 资源名称 标签键标签值
kubectl label pods nginx appweb这将给名为nginx的Pod添加了一个名为app值为web的标签。 添加标签是为资源附加额外的元数据以便更容易地对其进行标识和分类。例如为名为nginx的Pod添加标签appweb
更新标签Update Labels
更新标签是对已存在的标签进行更改。例如将名为nginx的Pod的app标签的值从web更改为frontend
kubectl label 资源类型 资源名称 标签键新标签值 --overwrite
kubectl label pods nginx appfrontend --overwrite使用--overwrite标志来确保标签的值被覆盖。
删除标签Remove Labels
删除标签是从资源中删除指定的标签。例如从名为nginx的Pod中删除app标签
kubectl label 资源类型 资源名称 标签键-
kubectl label pods nginx app-删除一个 label只需在命令行最后指定 label 的 key 名并与一个减号相连即可 这将从Pod中删除名为app的标签。
查询标签Query Labels
查询标签是查找具有特定标签的资源。例如查找具有appweb标签的所有Pod
kubectl get 资源类型 -l 标签选择器
kubectl get pods -l appweb这将返回所有具有appweb标签的Pod列表。
使用标签选择器Label Selectors
spec:selector:标签键: 标签值在定义资源时使用标签选择器以便在对资源进行操作时能够指定匹配的标签。例如定义一个Service并选择具有特定标签的Pod
apiVersion: v1
kind: Service
metadata:name: nginx-service
spec:selector:app: webports:- protocol: TCPport: 80targetPort: 80在这个例子中Service选择了具有appweb标签的Pod作为其后端。
标签匹配的运算符 In表示 label 的值必须在指定的列表中。 例如key: app, operator: In, values: [web, db] 表示 app 的值必须是 web 或 db。 NotIn表示 label 的值不能在指定的列表中。 例如key: env, operator: NotIn, values: [dev, test] 表示 env 的值不能是 dev 或 test。 Gt表示 label 的值必须大于指定的值。 例如key: replica, operator: Gt, values: [3] 表示 replica 的值必须大于 3。 Lt表示 label 的值必须小于指定的值。 例如key: version, operator: Lt, values: [2.0] 表示 version 的值必须小于 2.0。 Exists表示某个 label 必须存在。 例如key: app, operator: Exists 表示 app 必须存在。 DoesNotExist表示某个 label 不能存在。 例如key: deprecated, operator: DoesNotExist 表示 deprecated 不能存在。 这些运算关系在定义亲和性规则时用于匹配标签的条件
亲和性
官方将 Pod 指派给节点 | Kubernetes
在 Kubernetes 中亲和性Affinity是一种机制用于控制 Pod 如何被调度到节点上。亲和性规则允许你指定 Pod 与特定节点或其他 Pod 之间的偏好关系。通过使用亲和性可以确保相关的 Pod 在同一节点上运行或者避免将它们调度到同一节点上以提高性能、可用性或安全性。
亲和性在 Kubernetes 中有两种类型节点亲和性和 Pod 亲和性。节点亲和性定义了 Pod 与节点之间的关系而 Pod 亲和性定义了 Pod 与其他 Pod 之间的关系。
节点亲和性 通过 nodeAffinity 字段指定可以使用 nodeSelector 或 nodeSelectorTerms 定义节点上的标签和条件以确保 Pod 被调度到满足这些条件的节点上。 pod.spec.nodeAffinity 中的 preferredDuringSchedulingIgnoredDuringExecution 是软策略表示首选但不是强制要求。系统会尽量遵循这些偏好但在无法满足时也可以进行调度。 pod.spec.nodeAffinity 中的 requiredDuringSchedulingIgnoredDuringExecution 是硬策略表示 Pod 必须满足这些条件才能被调度。如果无法满足条件Pod 将不会被调度。
Pod 亲和性 通过 affinity 字段中的 podAffinity 和 podAntiAffinity 字段定义。podAffinity 用于描述 Pod 与其他 Pod 的关系而 podAntiAffinity 用于定义 Pod 与其他 Pod 的排斥关系。可以使用 labelSelector 和 topologyKey 来定义匹配规则。 pod.spec.affinity.podAffinity 和 pod.spec.affinity.podAntiAffinity 中的 preferredDuringSchedulingIgnoredDuringExecution 是软策略表示首选但不是强制要求。系统会尽量遵循这些偏好但在无法满足时也可以进行调度。 pod.spec.affinity.podAffinity 和 pod.spec.affinity.podAntiAffinity 中的 requiredDuringSchedulingIgnoredDuringExecution 是硬策略表示 Pod 必须满足这些条件才能被调度。如果无法满足条件Pod 将不会被调度。
硬策略和软策略
在 Kubernetes 中硬策略和软策略通常用于定义 Pod 的亲和性或节点的亲和性。这些策略决定了 Kubernetes 调度器在安排 Pod 时的行为。 硬策略requiredDuringSchedulingIgnoredDuringExecution 当使用硬策略时调度器必须严格遵守亲和性规则。这意味着 Pod 必须满足定义的亲和性条件才能被调度到节点上。如果无法满足条件Pod 将会一直处于 Pending 状态直到满足条件为止。即使在运行时如果条件不再满足Pod 也不会被迁移到其他节点。 软策略preferredDuringSchedulingIgnoredDuringExecution 当使用软策略时调度器会尽量遵守定义的亲和性规则但不是必须的。如果有多个节点符合软策略的条件调度器会倾向于选择满足条件的节点但如果无法满足条件调度器仍然可以将 Pod 调度到其他节点上。如果在运行时条件不再满足Pod 也不会被迁移到其他节点。
这两种策略提供了灵活性和可靠性之间的权衡。硬策略确保 Pod 被调度到满足条件的节点上但可能会导致更多的 Pod 无法调度。软策略提供了更灵活的调度但可能会导致一些 Pod 被调度到不太理想的节点上。在设计亲和性规则时需要根据具体情况选择适当的策略来平衡资源利用率和可用性要求
硬策略示例
# 创建目录
mkdir /opt/affinity
# 切换目录
cd /opt/affinity# 编辑 Pod 配置文件
vim pod1.yaml
apiVersion: v1
kind: Pod
metadata:name: affinitylabels:app: node-affinity-pod
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1# 定义节点亲和性affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostname # 指定node的标签operator: NotIn # 设置Pod安装到kubernetes.io/hostname的标签值不在values列表中的node上values:- node02# 应用 Pod 配置
kubectl apply -f pod1.yaml# 获取 Pod 列表
kubectl get pods -o wide# 删除所有 Pod重新应用配置并查看 Pod 列表
kubectl delete pod --all kubectl apply -f pod1.yaml kubectl get pods -o wide# 如果硬策略不满足条件Pod 状态一直会处于 Pending 状态。这个示例中创建了一个名为 affinity 的 Pod并且定义了节点亲和性规则使用了硬策略 requiredDuringSchedulingIgnoredDuringExecution。逐步解析这个示例 metadata 部分指定了 Pod 的元数据包括名称和标签。 spec 部分定义了 Pod 的规格其中包含了容器的相关信息。 在 affinity 字段下定义了节点亲和性规则。这里使用了 nodeAffinity表示节点亲和性。 在 requiredDuringSchedulingIgnoredDuringExecution 中指定了节点选择器条件。matchExpressions 用于指定匹配条件key 指定了要匹配的标签键这里是 kubernetes.io/hostname即节点的主机名。operator 设置为 NotIn表示标签值不在指定的列表中。而 values 则列出了不允许的节点主机名这里只有一个节点 node02。 最后应用了这个 Pod 的配置文件并通过 kubectl get pods -o wide 命令来查看 Pod 的状态和所在的节点。由于节点亲和性规则指定了 Pod 不能运行在 node02 上所以 Pod 被成功调度到了 node01 上状态为 Running。 最后的删除并重新创建操作是为了再次验证规则确保当条件不满足时Pod 状态会一直保持在 Pending。
这个示例清晰地展示了硬策略的行为当指定的条件无法满足时Pod 将无法被调度并且状态会一直保持在 Pending。
软策略示例
# 编辑 Pod2 配置文件
vim pod2.yaml
apiVersion: v1
kind: Pod
metadata:name: affinitylabels:app: node-affinity-pod
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1# 定义节点亲和性优先使用软策略affinity:nodeAffinity:preferredDuringSchedulingIgnoredDuringExecution:- weight: 1 # 如果有多个软策略选项的话权重越大优先级越高preference:matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- node03# 应用 Pod2 配置
kubectl apply -f pod2.yaml# 获取 Pod 列表
kubectl get pods -o wide这个YAML文件描述了一个Pod对象其中包含一个名为affinity的Pod。 apiVersion: 指定了Kubernetes API的版本这里使用的是v1版本。 kind: 定义了Kubernetes对象的类型这里是一个Pod对象。 metadata: 包含了有关该Pod的元数据包括名称name和标签labels。 name: 指定了Pod的名称为affinity。 labels: 为Pod添加了一个标签标签的键为app值为node-affinity-pod。 spec: 包含了Pod的规格即容器和其他配置信息。 containers: 定义了Pod中的容器列表。 name: 指定了容器的名称为with-node-affinity。 image: 指定了容器所使用的镜像为soscscs/myapp:v1。 affinity: 定义了Pod的亲和性规则。 nodeAffinity: 定义了节点亲和性规则。 preferredDuringSchedulingIgnoredDuringExecution: 指定了软节点亲和性规则即在调度时优先考虑但在执行时忽略。 weight: 指定了该规则的权重为1权重越大优先级越高。 preference: 指定了偏好项即优先调度到具有特定主机名的节点。 matchExpressions: 定义了匹配表达式。 key: 指定了匹配的键为kubernetes.io/hostname即主机名。 operator: 指定了匹配操作符为In表示匹配主机名列表中的任何一个值。 values: 指定了匹配的主机名列表这里只有一个值node03。
总结该Pod对象具有一个软节点亲和性规则表示优先调度到具有主机名为node03的节点。权重为1这意味着在具有多个软策略选项的情况下优先级较高。然而根据输出结果该Pod最终被调度到了节点node02上这是由于node02满足了调度要求并且优先级高于node03。
软硬策略结合示例
如果把硬策略和软策略合在一起使用则要先满足硬策略之后才会满足软策略
# 定义 Pod 配置
apiVersion: v1
kind: Pod
metadata:name: affinitylabels:app: node-affinity-pod
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1# 定义节点亲和性affinity:nodeAffinity:# 先满足硬策略排除有 kubernetes.io/hostnamenode02 标签的节点requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: NotInvalues:- node02# 再满足软策略优先选择有 aaaa 标签的节点preferredDuringSchedulingIgnoredDuringExecution:- weight: 1preference:matchExpressions:- key: aaaoperator: Invalues:- a这个示例中定义了一个Pod对象其中包含了硬节点亲和性规则和软节点亲和性规则。让我们分析一下 requiredDuringSchedulingIgnoredDuringExecution这是一个硬节点亲和性规则表示在调度时必须满足的条件。在这个规则中指定了排除具有主机名为node02的节点即必须在不包括node02的节点上调度该Pod。 preferredDuringSchedulingIgnoredDuringExecution这是一个软节点亲和性规则表示在调度时优先考虑的条件但在执行时会被忽略。在这个规则中指定了优先选择具有标签aaaa的节点即希望将该Pod调度到具有aaaa标签的节点上。
根据这两个规则的组合首先调度器会先满足硬节点亲和性规则即排除node02节点。然后在满足了硬性要求的节点中调度器会优先考虑软节点亲和性规则即选择具有aaaa标签的节点。这样最终的调度结果将是在不包括node02节点的节点中优先选择具有aaaa标签的节点。
pod亲和和反亲和 在Kubernetesk8s中Pod亲和性和反亲和性用于指定Pod与节点的关系。亲和性定义了Pod如何倾向于在同一节点上调度而反亲和性则定义了Pod如何避免与特定节点调度在一起。 通过使用nodeSelector字段你可以在PodSpec中指定节点标签使Pod倾向于调度到具有特定标签的节点上这就是亲和性的一种实现方式。相反反亲和性可以通过tolerations字段实现该字段定义了Pod可以容忍的节点上的污点从而避免在这些节点上被调度。 这样的机制有助于优化Pod的调度使其更好地适应节点资源和约束条件。
调度策略
当使用 Kubernetes 进行 Pod 调度时可以使用三种不同的调度策略来控制 Pod 的部署位置分别是 nodeAffinity节点亲和性、podAffinityPod 亲和性和 podAntiAffinityPod 反亲和性。 节点亲和性nodeAffinity 匹配标签对节点的标签进行匹配。 操作符支持的操作符包括 In、NotIn、Exists、DoesNotExist、Gt大于和 Lt小于等。 拓扑域支持不支持拓扑域只考虑节点的标签。 调度目标指定 Pod 应该调度到具有特定标签的节点上。 Pod 亲和性podAffinity 匹配标签对其他 Pod 的标签进行匹配。 操作符与节点亲和性相同支持的操作符包括 In、NotIn、Exists、DoesNotExist 等。 拓扑域支持支持拓扑域可以指定 Pod 应该与其他 Pod 在同一拓扑域比如同一节点还是不同拓扑域。 调度目标指定 Pod 应该与其他具有特定标签的 Pod 部署在同一拓扑域。 Pod 反亲和性podAntiAffinity 匹配标签同样对其他 Pod 的标签进行匹配。 操作符与节点亲和性和 Pod 亲和性相同。 拓扑域支持同样支持拓扑域可以指定 Pod 应该与其他 Pod 在同一拓扑域还是不同拓扑域。 调度目标指定 Pod 应该与其他具有特定标签的 Pod 部署在不同的拓扑域即不在同一节点或同一拓扑域。
这些调度策略可以帮助用户更灵活地控制 Pod 的部署根据业务需求和系统架构优化资源利用和提高容错能力。
Pod 亲和性调度策略的详细说明 调度条件 仅当节点和至少一个已运行且具有标签键为“app”且值为“myapp01”的 Pod 处于同一拓扑域时才可以将该 Pod 调度到节点上。 具体来说如果节点 N 具有带有键为 lab 和某个值 V 的标签则 Pod 有资格在节点 N 上运行以便集群中至少有一个具有键为 lab和值为 V 的节点正在运行具有键“app”和值“myapp01”的 Pod。 topologyKey topologyKey 是节点标签的键。如果两个节点使用此键标记并且具有相同的标签值则调度器会将这两个节点视为处于同一拓扑域中。 调度器试图在每个拓扑域中放置数量均衡的 Pod。 拓扑域的定义 如果 lab对应的值不一样就是不同的拓扑域。比如 Pod1 在 laba 的 Node 上Pod2 在 labb 的 Node 上Pod3 在 laba 的 Node 上则 Pod2 和 Pod1、Pod3 不在同一个拓扑域而 Pod1 和 Pod3 在同一个拓扑域。
示例
kubectl label node node01 laba
kubectl label node node02 labb这两个命令的目的是给节点 node01 和 node02 分别打上标签 laba 和 labb
创建一个标签为 appmyapp01 的 Pod
vim pod3.yamlapiVersion: v1
kind: Pod
metadata:name: myapp01 # 设置 Pod 的名称为 myapp01labels:app: myapp01 # 给 Pod 添加标签 app: myapp01
spec:containers:- name: with-node-affinity # 定义容器名称为 with-node-affinityimage: soscscs/myapp:v1 # 使用镜像 soscscs/myapp:v1kubectl apply -f pod3.yaml
kubectl get pods --show-labels -o wide这段代码创建了一个名为 myapp01 的 Pod并为其打上了标签 appmyapp01。下面是对代码的说明 vim pod3.yaml创建了一个名为 pod3.yaml 的文件并编辑该文件以定义 Pod 对象的配置。 metadata 部分指定了 Pod 的名称和标签。 spec 部分定义了 Pod 的规格其中包含一个容器使用镜像 soscscs/myapp:v1。 kubectl apply -f pod3.yaml使用 Pod 配置文件 pod3.yaml 创建 Pod 对象。 kubectl get pods --show-labels -o wide显示所有 Pod 的信息包括标签以宽格式输出。可以看到 myapp01 Pod 已经成功创建并且具有标签 appmyapp01并且运行在 node01 节点上。
这样就成功创建了一个名为 myapp01 的 Pod并为其打上了指定的标签。
使用 Pod 亲和性调度创建多个 Pod 资源
vim pod4.yaml
apiVersion: v1
kind: Pod
metadata:name: myapp02 # 设置 Pod 的名称为 myapp02labels:app: myapp02 # 给 Pod 添加标签 app: myapp02
spec:containers:- name: myapp02 # 定义容器名称为 myapp02image: soscscs/myapp:v1 # 使用镜像 soscscs/myapp:v1affinity: # 定义亲和性podAffinity: # Pod 亲和性规则requiredDuringSchedulingIgnoredDuringExecution: # 在调度期间要求的 Pod 亲和性规则在执行期间被忽略- labelSelector: # 标签选择器matchExpressions: # 匹配表达式列表- key: app # 标签键为 appoperator: In # 使用 In 操作符values: # 值列表- myapp01 # 匹配值为 myapp01topologyKey: lab # 拓扑域键为 labkubectl apply -f pod4.yaml
kubectl get pods --show-labels -o wide这段代码创建了一个名为 myapp02 的 Pod并使用了 Pod 亲和性调度策略以确保它与具有特定标签的其他 Pod 在同一拓扑域上。下面是对代码的说明 vim pod4.yaml创建了一个名为 pod4.yaml 的文件并编辑该文件以定义 Pod 对象的配置。 metadata 部分指定了 Pod 的名称和标签。 spec 部分定义了 Pod 的规格其中包含一个容器使用镜像 soscscs/myapp:v1。 affinity 部分定义了 Pod 的亲和性策略这里使用了 podAffinity 策略。 requiredDuringSchedulingIgnoredDuringExecution 指定了 Pod 调度时必须满足的条件。 labelSelector 指定了匹配其他 Pod 标签的条件这里要求匹配的标签为 appmyapp01。 topologyKey 指定了用于确定拓扑域的键这里设置为 lab。 这段代码将确保创建的 myapp02 Pod 与具有标签 appmyapp01 的其他 Pod 在同一拓扑域上调度。
使用 Pod 反亲和性调度
vim pod5.yamlapiVersion: v1
kind: Pod
metadata:name: myapp10 # Pod 的名称labels:app: myapp10 # Pod 的标签
spec:containers:- name: myapp10 # 容器的名称image: soscscs/myapp:v1 # 容器所使用的镜像affinity:podAntiAffinity: # 反亲和性调度规则preferredDuringSchedulingIgnoredDuringExecution: # 在调度时优先考虑的规则执行时忽略- weight: 100 # 权重podAffinityTerm: # 匹配的 Pod 亲和性条件labelSelector: # 标签选择器matchExpressions: # 匹配的表达式- key: app # 匹配的键operator: In # 匹配操作符values: # 匹配的值- myapp01 # 与该 Pod 亲和的标签值topologyKey: kubernetes.io/hostname # 拓扑域键kubectl apply -f pod5.yamlkubectl get pods --show-labels -o wide这个示例展示了如何在 Pod 中使用反亲和性调度。在这个例子中Pod myapp10 的调度规则指定了反亲和性即希望它不要与具有特定标签的其他 Pod 调度到同一个节点上。
vim pod6.yamlapiVersion: v1
kind: Pod
metadata:name: myapp20 # Pod 的名称labels:app: myapp20 # Pod 的标签
spec:containers:- name: myapp20 # 容器的名称image: soscscs/myapp:v1 # 容器所使用的镜像affinity:podAntiAffinity: # 反亲和性调度规则requiredDuringSchedulingIgnoredDuringExecution: # 在调度时必须满足的规则执行时忽略- labelSelector: # 标签选择器matchExpressions: # 匹配的表达式- key: app # 匹配的键operator: In # 匹配操作符values: # 匹配的值- myapp01 # 与该 Pod 亲和的标签值topologyKey: lab # 拓扑域键这样配置的 Pod 在调度时将会确保不与具有标签 app: myapp01 的其他 Pod 调度到同一个拓扑域上
由于指定 Pod 所在的 node01 节点上具有带有键 lab和标签值 a 的标签node02 也有这个laba的标签所以 node01 和 node02 是在一个拓扑域中反亲和要求新 Pod 与指定 Pod 不在同一拓扑域所以新 Pod 没有可用的 node 节点即为 Pending 状态。
kubectl get pod --show-labels -owide
kubectl label nodes node02 labb --overwrite
kubectl get pod --show-labels -o wide根据输出可以看出新的 Pod myapp20 因为反亲和性调度规则而处于 Pending 状态。由于 Pod myapp01 具有标签 appmyapp01并且拓扑域键 lab 的值为 a而节点 node01 和 node02 都有拓扑域键 lab 的标签因此它们被认为处于相同的拓扑域。 由于新的 Pod myapp20 需要避免与具有标签 appmyapp01 的 Pod 调度到同一拓扑域但在目前的节点中没有节点符合该条件因此该 Pod 保持在 Pending 状态。更新了 node02 的标签但似乎仍然不符合新 Pod 的调度要求。 最终创建了一个新的 Pod myapp21它成功在 node02 上运行因为现在 node02 的标签为 labb与之前的标签不同因此不再满足与 Pod myapp20 的反亲和性调度要求。
污点(Taint) 和 容忍(Tolerations) 节点亲和性是Pod的一种属性偏好或硬性要求它使Pod被吸引到一类特定的节点。Taint 则相反它使节点能够排斥一类特定的 Pod。 Taint 和 Toleration 相互配合可以用来避免 Pod 被分配到不合适的节点上。每个节点上都可以应用一个或多个 taint 这表示对于那些不能容忍这些 taint 的 Pod是不会被该节点接受的。如果将 toleration 应用于 Pod 上则表示这些 Pod 可以但不一定被调度到具有匹配 taint 的节点上。 使用 kubectl taint 命令可以给某个 Node 节点设置污点Node 被设置上污点之后就和 Pod 之间存在了一种相斥的关系可以让 Node 拒绝 Pod 的调度执行甚至将 Node 已经存在的 Pod 驱逐出去。
概念
污点Taints 污点是应用于节点的标记用于阻止将新的Pod调度到带有该污点的节点上。 污点由键值对keyvalue组成其中键表示污点的名称而值表示污点的效果例如NoSchedule、PreferNoSchedule和NoExecute。 通过在节点上设置污点可以限制哪些Pod可以被调度到该节点上。
容忍度Tolerations 容忍度是Pod的属性用于指定Pod可以被调度到带有特定污点的节点上。 每个容忍度包含键值对keyvalue其中键表示要容忍的污点的名称而值表示要容忍的污点的效果。 Pod只有在其定义了与节点上污点匹配的容忍度时才能被调度到带有该污点的节点上。
调度行为 如果Pod的容忍度与节点上的污点匹配那么该Pod可以被调度到带有该污点的节点上。 如果Pod的容忍度与节点上的污点不匹配且污点的效果是NoSchedule或PreferNoSchedule那么该Pod将不会被调度到该节点上。 如果Pod的容忍度与节点上的污点不匹配但污点的效果是NoExecute那么该节点上的已有Pod可能会被驱逐Evicted。
示例用法
可以使用污点和容忍度来实现特定的调度需求例如将某些特殊的Pod调度到专门的节点上或者确保某些Pod不会被调度到某些节点上。
格式和支持的效果选项
#污点的组成格式如下
keyvalue:effect每个污点有一个 key 和 value 作为污点的标签其中 value 可以为空effect 描述污点的作用。个污点由键值对keyvalue和一个效果effect组成。效果描述了污点的作用而键值对表示该污点的标签。支持的效果包括 NoSchedule不调度 Kubernetes将不会将Pod调度到具有该污点的节点上。 PreferNoSchedule尽量避免调度 Kubernetes将尽量避免将Pod调度到具有该污点的节点上但不是绝对禁止。 NoExecute不执行 Kubernetes将不会将Pod调度到具有该污点的节点上并且会将节点上已经存在的Pod驱逐出去确保节点不再运行这些Pod。
这种机制为Kubernetes提供了更精细的调度控制使得系统可以根据特定的需求和场景进行灵活的调度决策。
污点的基本操作
用一个具体的示例来说明如何在Kubernetes中执行这些操作。
假设我们有一个名为node-1的节点我们要给它添加一个污点阻止Pod在这个节点上调度除非它们具有特定的标签。我们将添加一个名为specialtrue:NoSchedule的污点。
添加污点
kubectl taint nodes node-name keyvalue:taint-effect
kubectl taint nodes node-1 specialtrue:NoSchedule这将在node-1节点上添加一个名为special、值为true的污点并且该污点的效果为NoSchedule意味着除非Pod具有与此污点匹配的容忍Toleration否则不会在该节点上调度。
查看污点
kubectl describe node node-name
kubectl describe node node-1运行此命令将显示有关node-1节点的详细信息包括其上的污点。
删除污点
kubectl taint nodes node-name key:NoSchedule-
kubectl taint nodes node-1 special:NoSchedule-这会从node-1节点上删除名为special的污点并且污点的效果为NoSchedule。
示例
# 显示集群中的节点信息包括名称、状态、角色、年龄和版本
kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 11d v1.20.11
node01 Ready none 11d v1.20.11
node02 Ready none 11d v1.20.11# master 节点设置了一个 NoSchedule 类型的污点导致不允许在此节点上调度 Pod
kubectl describe node master
......
Taints: node-role.kubernetes.io/master:NoSchedule# 给 node01 节点设置一个名为 key1值为 value1 的 NoSchedule 类型的污点
kubectl taint node node01 key1value1:NoSchedule# 在节点说明中查找 Taints 字段用于查看节点上设置的污点信息
kubectl describe node node-name # 从 node01 节点中移除名为 key1 的污点
kubectl taint node node01 key1:NoSchedule-# 显示 Pod 的信息包括名称、就绪状态、状态、重启次数、年龄、IP 地址、所在节点等
kubectl get pods -o wide# 给 node02 节点设置一个名为 check值为 mycheck 的 NoExecute 类型的污点导致 Pod 在此节点上被驱逐
kubectl taint node node02 checkmycheck:NoExecute# 查看 Pod 状态会发现 node02 上的 Pod 已经被全部驱逐
# 注如果是 Deployment 或者 StatefulSet 资源类型为了维持副本数量则会在别的 Node 上再创建新的 Pod
kubectl get pods -o wide容忍
通过在 Pod 上设置容忍(Tolerations)可以允许 Pod 在存在污点的节点上被调度。这使得在一些特定情况下例如需要部署某些特殊任务或者维护节点时依然能够将 Pod 调度到被标记为污点的节点上。容忍(Tolerations)允许 Pod 忽略节点上的污点并允许被调度从而灵活地管理集群资源。
举例说明
# 在节点 node01 上设置了一个名为 mycheck 的污点并且指定了 NoExecute 效果
kubectl taint node node01 checkmycheck:NoExecute# 编辑名为 pod3.yaml 的 Pod 配置文件
vim pod3.yaml# 应用 Pod3 的配置文件
kubectl apply -f pod3.yaml# 当在两个节点上都设置了污点后Pod 将无法创建成功
kubectl get pods -o wide
# 此时输出显示 Pod 处于 Pending 状态无法调度到任何节点运行# 编辑 pod3.yaml 文件为 Pod 定义容忍策略使其能够在具有污点的节点上运行
vim pod3.yaml# pod3.yaml 文件内容
apiVersion: v1
kind: Pod
metadata:name: myapp01labels:app: myapp01
spec:containers:- name: with-node-affinityimage: soscscs/myapp:v1tolerations:- key: checkoperator: Equalvalue: mycheckeffect: NoExecutetolerationSeconds: 3600# 为 Pod 设置容忍策略确保其能够在具有指定污点的节点上运行
# 其中的 key、value、effect 需要与节点上设置的污点保持一致
# operator 的值为 Exists 将会忽略 value 值即存在即可
# tolerationSeconds 用于描述当 Pod 需要被驱逐时可以在节点上继续保留运行的时间# 再次应用更新后的 Pod3 配置文件
kubectl apply -f pod3.yaml# 验证 Pod 创建成功并在指定的节点上正常运行
kubectl get pods -o wide
# 输出显示 Pod 已成功创建并运行在节点 node01 上值得注意的操作
未指定 key 值时表示容忍所有的污点 key。
tolerations:- operator: Exists未指定 effect 值时表示容忍所有的污点作用。
tolerations:- key: keyoperator: Exists多个 Master 存在时防止资源浪费可设置如下
kubectl taint node Master-Name node-role.kubernetes.io/master:PreferNoSchedule若某个 Node 更新升级系统组件为防止业务中断可先在该 Node 设置 NoExecute 污点驱逐 Pod。
kubectl taint node node01 checkmycheck:NoExecute若其他 Node 资源不足可暂时给 Master 设置 PreferNoSchedule 污点使 Pod 在 Master 上创建。
kubectl taint node master node-role.kubernetes.io/master:PreferNoSchedule所有 Node 更新操作完成后移除污点。
kubectl taint node node01 checkmycheck:NoExecute-维护节点和应用程序操作
管理节点的调度状态 Cordon 使用 kubectl cordon NODE_NAME 命令将指定节点标记为不可调度状态。这将阻止新的 Pod 在此节点上调度。 Drain 使用 kubectl drain NODE_NAME 命令使节点进入排水状态。这将释放节点上的所有 Pod并且不再接受新的 Pod。执行排水操作通常在需要维护节点或者从集群中移除节点时使用。 注执行 drain 命令会自动做了两件事情: 1.设定此 node 为不可调度状态cordon) 2.evict驱逐了 Pod Uncordon 使用 kubectl uncordon NODE_NAME 命令将节点标记为可调度状态恢复节点的正常调度功能。这允许新的 Pod 再次在该节点上调度。
设置和移除污点 设置污点 使用 kubectl taint node NODE_NAME KEYVALUE:EFFECT 命令在节点上设置污点。污点可以阻止 Pod 在具有特定标签和效果的节点上调度。 移除污点 使用 kubectl taint node NODE_NAME KEYVALUE:EFFECT- 命令在节点上移除指定的污点。这将允许 Pod 再次在该节点上调度。
常见的污点效果Effect NoSchedule 阻止新的 Pod 调度到节点上但不会驱逐现有的 Pod。 PreferNoSchedule 倾向于不在该节点上调度新的 Pod但不会阻止 Pod 调度。 NoExecute 阻止新的 Pod 调度到节点上并且将现有 Pod 驱逐出该节点。
常见参数 --ignore-daemonsets 当执行 kubectl drain NODE_NAME 命令时使用该选项可以忽略 DaemonSet 管理下的 Pod。DaemonSet 是 Kubernetes 中一种控制器类型它确保在集群中的每个节点上运行一个副本的 Pod。通常情况下节点的排水操作不会影响 DaemonSet 管理的 Pod因为它们被认为是关键的系统组件需要保持运行。使用 --ignore-daemonsets 选项可以确保在排水节点时不会影响 DaemonSet 的 Pod。 --delete-local-data 当执行 kubectl drain NODE_NAME 命令时如果节点上有挂载本地卷的 Pod使用该选项可以强制删除这些 Pod。本地卷是直接挂载在节点上的存储卷而不是通过网络挂载的。在某些情况下需要强制删除这些 Pod例如当节点需要被彻底清空时。 --force 当执行 kubectl drain NODE_NAME 命令时使用该选项可以强制释放不是由控制器管理的 Pod。控制器管理的 Pod 包括 Deployment、StatefulSet、DaemonSet 等。通常情况下控制器会确保 Pod 的数量和状态符合预期但是如果需要强制释放一些不是由控制器管理的 Pod可以使用 --force 选项。
通过合理管理节点的调度状态和设置/移除污点可以有效地管理集群中的资源确保应用程序的高可用性和稳定性。
pod启动阶段的状态解读与排错技巧
Pod启动阶段相位 phase
Pod 创建完之后一直到持久运行起来中间有很多步骤也就有很多出错的可能因此会有很多不同的状态。 调度到某台 node 上 Kubernetes 根据一定的优先级算法选择一个 node 节点来运行 Pod。 拉取镜像 Pod 需要拉取其包含的镜像以便在节点上创建容器。 挂载存储配置等 Pod 可能需要挂载存储卷或配置文件等资源。 运行起来 当所有必需的资源准备就绪后Pod 开始在节点上运行。如果定义了健康检查系统会根据检查结果设置 Pod 的状态。
pod可能的状态 Pending挂起 表示 Pod 资源对象已创建但尚未完成调度或正在拉取镜像。 Running运行中 Pod 已经被调度到节点上并且至少有一个容器正在运行或处于启动或重启状态。也就是说Running状态下的Pod不一定能被正常访问 Succeeded成功 表示 Pod 中的所有容器已成功终止通常用于短期任务执行完毕后的状态反馈。有些pod不是长久运行的比如job、cronjob一段时间后Pod中的所有容器都被成功终止并且不会再重启。需要反馈任务执行的结果。 Failed失败 所有容器都已终止并且至少有一个容器由于失败而终止可能是由于命令错误等原因。也就是说容器以非0状态退出或者被系统终止比如 command 写的有问题。 Unknown未知 表示无法读取 Pod 的状态通常是由于控制器kube-controller-manager无法与 Pod 通信导致的。
故障排除步骤
需要排查 Pod 启动或运行中的问题时以下是一些详细的故障排除步骤
查看 Pod 事件 使用 kubectl describe 命令检查 Pod 事件以了解 Pod 启动过程中可能出现的问题。这将提供关于 Pod 创建、调度和运行过程中的详细信息。
kubectl describe pod POD_NAME期望输出 Pod 的事件日志包括调度、镜像拉取、容器启动等信息。
查看 Pod 日志 如果 Pod 处于 Failed 状态使用 kubectl logs 命令查看 Pod 的日志以获取失败的原因。可以通过指定容器名称来查看特定容器的日志。
kubectl logs POD_NAME [-c CONTAINER_NAME]期望输出 容器的标准输出和标准错误日志显示应用程序的运行日志或错误信息。
进入 Pod 内部 如果 Pod 处于 Running 状态但服务没有提供可以使用 kubectl exec 命令进入 Pod 内部。这样可以检查 Pod 内部的环境和运行状态以便进一步诊断问题。
kubectl exec -it POD_NAME -- /bin/bash期望操作 在 Pod 内部运行命令进行故障排查如检查网络配置、运行状态或日志文件。
查看集群信息 使用 kubectl get nodes 命令检查集群中节点的状态以确保节点正常运行。这可以帮助排除可能导致 Pod 无法调度或运行的节点问题。
kubectl get nodes期望输出 集群中所有节点的列表包括它们的状态Ready、NotReady 或其他。
检查集群状态 使用 kubectl cluster-info 命令检查整个集群的状态包括控制平面和核心服务。这有助于确定是否存在集群范围的问题。
kubectl cluster-info期望输出 集群控制平面组件的状态和访问URL如 Kubernetes master 和 kubeDNS。
查看 kubelet 日志 最后查看 kubelet 的日志以发现与 Pod 启动或运行相关的任何问题。可以使用 journalctl 命令来查看 kubelet 的日志。
journalctl -u kubelet期望输出 kubelet 服务的日志提供与 Pod 生命周期和节点状态相关的详细信息。
通过执行以上步骤可以对 Pod 启动或运行中的问题进行详细的排查和诊断从而有效地解决问题并确保应用程序正常运行。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/919374.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!