k8s 集群调度,标签,亲和性和反亲和性,污点和容忍,pod启动状态 排错详解

目录

pod启动创建过程

kubelet持续监听的原因

调度概念

调度约束

调度过程

优点

原理

优先级选项

示例

指定调度节点

标签基本操作

获取标签帮助

[添加标签(Add Labels):](#添加标签(Add Labels):)

[更新标签(Update Labels)](#更新标签(Update Labels))

[删除标签(Remove Labels)](#删除标签(Remove Labels))

[查询标签(Query Labels)](#查询标签(Query Labels))

[使用标签选择器(Label Selectors)](#使用标签选择器(Label Selectors))

标签匹配的运算符

亲和性

节点亲和性:

[Pod 亲和性:](#Pod 亲和性:)

硬策略和软策略

硬策略示例

软策略示例

软硬策略结合示例

pod亲和和反亲和

调度策略

[Pod 亲和性调度策略的详细说明](#Pod 亲和性调度策略的详细说明)

示例

[创建一个标签为 app=myapp01 的 Pod](#创建一个标签为 app=myapp01 的 Pod)

[使用 Pod 亲和性调度,创建多个 Pod 资源](#使用 Pod 亲和性调度,创建多个 Pod 资源)

[使用 Pod 反亲和性调度](#使用 Pod 反亲和性调度)

[污点(Taint) 和 容忍(Tolerations)](#污点(Taint) 和 容忍(Tolerations))

概念

格式和支持的效果(选项)

污点的基本操作

添加污点:

查看污点:

删除污点:

示例

容忍

举例说明

值得注意的操作

维护节点和应用程序操作

pod启动阶段的状态解读与排错技巧

[Pod启动阶段(相位 phase)](#Pod启动阶段(相位 phase))

pod可能的状态

故障排除步骤


pod启动创建过程

这里有三个 List-Watch,分别是 Controller Manager(运行在 Master),Scheduler(运行在 Master),kubelet(运行在 Node)。 他们在进程已启动就会监听(Watch)APIServer 发出来的事件。

  • 用户通过 kubectl 或其他 API 客户端提交创建 Pod 的请求给 APIServer

  • APIServer 将 Pod 对象的元数据尝试存入 etcd 中,待写入操作执行完成,APIServer返回确认信息给客户端。

  • etcd 接受创建 Pod 的信息后,在集群中保存该信息,并触发 Create 事件给APIserver。

  • Controller Manager 监听到 Create 事件后,调用 Replication Controller 来确保 Node 上的副本数量符合定义。一旦副本数量少于 RC 中定义的数量,RC 会自动创建副本。总之它是保证副本数量的 Controller(PS:扩容缩容的担当)。

  • 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 会通过监听(Watch)etcd 发过来的事件。其他组件也会监听(Watch)APIServer 发出来的事件。

调度约束

Kubernetes中的调度约束,这些约束是指在将Pod调度到节点上时需要考虑的各种条件和限制。这些约束包括但不限于:

  • 资源约束: 每个节点有一定的资源限制,如CPU和内存。调度器会考虑Pod的资源请求和节点的可用资源,确保Pod能够得到满足并不会超出节点的资源容量。

  • 亲和性和反亲和性: 可以指定Pod之间或Pod与节点之间的亲和性和反亲和性规则,以确保它们被调度到合适的节点上。例如,可以将Pod调度到与特定标签匹配的节点上,或者避免将它们调度到某些节点上。

  • 节点亲和性: 通过节点亲和性规则,可以指定Pod应该调度到与某些节点属性匹配的节点上。例如,将Pod调度到具有特定硬件特性或数据存储的节点上。

  • Pod 亲和性: 通过Pod亲和性规则,可以确保一组Pod被调度到同一节点上,或者避免它们被调度到同一节点上。

  • 污点和容忍: 污点用于标记节点上的不可接受条件,而容忍则允许一些Pod调度到带有污点的节点上。这有助于将特定类型的工作负载调度到适合的节点上。

这些约束通过Kubernetes的调度器实现,调度器会根据这些约束选择最佳的节点来放置Pod,以满足用户需求并确保集群的高效利用。

调度过程

Kubernetes(k8s)调度涉及调度器、控制器管理器和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: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      nodeName: node01
      containers:
      - name: myapp
        image: soscscs/myapp:v1
        ports:
        - containerPort: 80

kubectl apply -f myapp.yaml

kubectl get pods -o wide
  • apiVersion: 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添加标签app=web

kubectl label <资源类型> <资源名称> <标签键>=<标签值>
kubectl label pods nginx app=web
  • 这将给名为nginx的Pod添加了一个名为app,值为web的标签。

  • 添加标签是为资源附加额外的元数据,以便更容易地对其进行标识和分类。例如,为名为nginx的Pod添加标签app=web

更新标签(Update Labels)

更新标签是对已存在的标签进行更改。例如,将名为nginx的Pod的app标签的值从web更改为frontend

kubectl label <资源类型> <资源名称> <标签键>=<新标签值> --overwrite
kubectl label pods nginx app=frontend --overwrite
  • 使用--overwrite标志来确保标签的值被覆盖。

删除标签(Remove Labels)

删除标签是从资源中删除指定的标签。例如,从名为nginx的Pod中删除app标签:

kubectl label <资源类型> <资源名称> <标签键>-
kubectl label pods nginx app-
  • 删除一个 label,只需在命令行最后指定 label 的 key 名并与一个减号相连即可

  • 这将从Pod中删除名为app的标签。

查询标签(Query Labels)

查询标签是查找具有特定标签的资源。例如,查找具有app=web标签的所有Pod:

kubectl get <资源类型> -l <标签选择器>
kubectl get pods -l app=web

这将返回所有具有app=web标签的Pod列表。

使用标签选择器(Label Selectors)

spec:
  selector:
    <标签键>: <标签值>

在定义资源时使用标签选择器,以便在对资源进行操作时能够指定匹配的标签。例如,定义一个Service并选择具有特定标签的Pod:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: web
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

在这个例子中,Service选择了具有app=web标签的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.podAffinitypod.spec.affinity.podAntiAffinity 中的 preferredDuringSchedulingIgnoredDuringExecution 是软策略,表示首选但不是强制要求。系统会尽量遵循这些偏好,但在无法满足时也可以进行调度。

  • pod.spec.affinity.podAffinitypod.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: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: 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: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  # 定义节点亲和性,优先使用软策略
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1   # 如果有多个软策略选项的话,权重越大,优先级越高
        preference:
          matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - 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: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  # 定义节点亲和性
  affinity:
    nodeAffinity:
      # 先满足硬策略,排除有 kubernetes.io/hostname=node02 标签的节点
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: NotIn
            values:
            - node02
      # 再满足软策略,优先选择有 aaa=a 标签的节点
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: aaa
            operator: In
            values:
            - a

这个示例中,定义了一个Pod对象,其中包含了硬节点亲和性规则和软节点亲和性规则。让我们分析一下:

  • requiredDuringSchedulingIgnoredDuringExecution:这是一个硬节点亲和性规则,表示在调度时必须满足的条件。在这个规则中,指定了排除具有主机名为node02的节点,即必须在不包括node02的节点上调度该Pod。

  • preferredDuringSchedulingIgnoredDuringExecution:这是一个软节点亲和性规则,表示在调度时优先考虑的条件,但在执行时会被忽略。在这个规则中,指定了优先选择具有标签aaa=a的节点,即希望将该Pod调度到具有aaa=a标签的节点上。

根据这两个规则的组合,首先,调度器会先满足硬节点亲和性规则,即排除node02节点。然后,在满足了硬性要求的节点中,调度器会优先考虑软节点亲和性规则,即选择具有aaa=a标签的节点。这样,最终的调度结果将是在不包括node02节点的节点中,优先选择具有aaa=a标签的节点。

pod亲和和反亲和

  • 在Kubernetes(k8s)中,Pod亲和性和反亲和性用于指定Pod与节点的关系。亲和性定义了Pod如何倾向于在同一节点上调度,而反亲和性则定义了Pod如何避免与特定节点调度在一起。

  • 通过使用nodeSelector字段,你可以在PodSpec中指定节点标签,使Pod倾向于调度到具有特定标签的节点上,这就是亲和性的一种实现方式。相反,反亲和性可以通过tolerations字段实现,该字段定义了Pod可以容忍的节点上的污点,从而避免在这些节点上被调度。

  • 这样的机制有助于优化Pod的调度,使其更好地适应节点资源和约束条件。

调度策略

当使用 Kubernetes 进行 Pod 调度时,可以使用三种不同的调度策略来控制 Pod 的部署位置,分别是 nodeAffinity(节点亲和性)、podAffinity(Pod 亲和性)和 podAntiAffinity(Pod 反亲和性)。

  • 节点亲和性(nodeAffinity)

  • 匹配标签:对节点的标签进行匹配。

  • 操作符 :支持的操作符包括 InNotInExistsDoesNotExistGt(大于)和 Lt(小于)等。

  • 拓扑域支持:不支持拓扑域,只考虑节点的标签。

  • 调度目标:指定 Pod 应该调度到具有特定标签的节点上。

  • Pod 亲和性(podAffinity)

  • 匹配标签:对其他 Pod 的标签进行匹配。

  • 操作符 :与节点亲和性相同,支持的操作符包括 InNotInExistsDoesNotExist 等。

  • 拓扑域支持:支持拓扑域,可以指定 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 在 lab=a 的 Node 上,Pod2 在 lab=b 的 Node 上,Pod3 在 lab=a 的 Node 上,则 Pod2 和 Pod1、Pod3 不在同一个拓扑域,而 Pod1 和 Pod3 在同一个拓扑域。

示例

kubectl label node node01 lab=a
kubectl label node node02 lab=b

这两个命令的目的是给节点 node01node02 分别打上标签 lab=alab=b

创建一个标签为 app=myapp01 的 Pod

vim pod3.yaml

apiVersion: v1
kind: Pod
metadata:
  name: myapp01  # 设置 Pod 的名称为 myapp01
  labels:
    app: myapp01  # 给 Pod 添加标签 app: myapp01
spec:
  containers:
  - name: with-node-affinity  # 定义容器名称为 with-node-affinity
    image: soscscs/myapp:v1  # 使用镜像 soscscs/myapp:v1

kubectl apply -f pod3.yaml
kubectl get pods --show-labels -o wide

这段代码创建了一个名为 myapp01 的 Pod,并为其打上了标签 app=myapp01。下面是对代码的说明:

  • 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 已经成功创建,并且具有标签 app=myapp01,并且运行在 node01 节点上。

这样就成功创建了一个名为 myapp01 的 Pod,并为其打上了指定的标签。

使用 Pod 亲和性调度,创建多个 Pod 资源

vim pod4.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp02  # 设置 Pod 的名称为 myapp02
  labels:
    app: myapp02  # 给 Pod 添加标签 app: myapp02
spec:
  containers:
  - name: myapp02  # 定义容器名称为 myapp02
    image: soscscs/myapp:v1  # 使用镜像 soscscs/myapp:v1
  affinity:  # 定义亲和性
    podAffinity:  # Pod 亲和性规则
      requiredDuringSchedulingIgnoredDuringExecution:  # 在调度期间要求的 Pod 亲和性规则,在执行期间被忽略
      - labelSelector:  # 标签选择器
          matchExpressions:  # 匹配表达式列表
          - key: app  # 标签键为 app
            operator: In  # 使用 In 操作符
            values:  # 值列表
            - myapp01  # 匹配值为 myapp01
        topologyKey: lab  # 拓扑域键为 lab

kubectl 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 标签的条件,这里要求匹配的标签为 app=myapp01

    • topologyKey 指定了用于确定拓扑域的键,这里设置为 lab

  • 这段代码将确保创建的 myapp02 Pod 与具有标签 app=myapp01 的其他 Pod 在同一拓扑域上调度。

使用 Pod 反亲和性调度

vim pod5.yaml

apiVersion: 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.yaml

kubectl get pods --show-labels -o wide
  • 这个示例展示了如何在 Pod 中使用反亲和性调度。在这个例子中,Pod myapp10 的调度规则指定了反亲和性,即希望它不要与具有特定标签的其他 Pod 调度到同一个节点上。

    vim pod6.yaml

    apiVersion: 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 也有这个lab=a的标签,所以 node01 和 node02 是在一个拓扑域中,反亲和要求新 Pod 与指定 Pod 不在同一拓扑域,所以新 Pod 没有可用的 node 节点,即为 Pending 状态。

kubectl get pod --show-labels -owide
kubectl label nodes node02 lab=b --overwrite
kubectl get pod --show-labels -o wide
  • 根据输出,可以看出新的 Pod myapp20 因为反亲和性调度规则而处于 Pending 状态。由于 Pod myapp01 具有标签 app=myapp01,并且拓扑域键 lab 的值为 a,而节点 node01node02 都有拓扑域键 lab 的标签,因此它们被认为处于相同的拓扑域。

  • 由于新的 Pod myapp20 需要避免与具有标签 app=myapp01 的 Pod 调度到同一拓扑域,但在目前的节点中,没有节点符合该条件,因此该 Pod 保持在 Pending 状态。更新了 node02 的标签,但似乎仍然不符合新 Pod 的调度要求。

  • 最终,创建了一个新的 Pod myapp21,它成功在 node02 上运行,因为现在 node02 的标签为 lab=b,与之前的标签不同,因此不再满足与 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调度到带有该污点的节点上。

  • 污点由键值对(key=value)组成,其中键表示污点的名称,而值表示污点的效果,例如NoSchedule、PreferNoSchedule和NoExecute。

  • 通过在节点上设置污点,可以限制哪些Pod可以被调度到该节点上。

容忍度(Tolerations)

  • 容忍度是Pod的属性,用于指定Pod可以被调度到带有特定污点的节点上。

  • 每个容忍度包含键值对(key=value),其中键表示要容忍的污点的名称,而值表示要容忍的污点的效果。

  • Pod只有在其定义了与节点上污点匹配的容忍度时,才能被调度到带有该污点的节点上。

调度行为

  • 如果Pod的容忍度与节点上的污点匹配,那么该Pod可以被调度到带有该污点的节点上。

  • 如果Pod的容忍度与节点上的污点不匹配,且污点的效果是NoSchedule或PreferNoSchedule,那么该Pod将不会被调度到该节点上。

  • 如果Pod的容忍度与节点上的污点不匹配,但污点的效果是NoExecute,那么该节点上的已有Pod可能会被驱逐(Evicted)。

示例用法

  • 可以使用污点和容忍度来实现特定的调度需求,例如将某些特殊的Pod调度到专门的节点上,或者确保某些Pod不会被调度到某些节点上。

格式和支持的效果(选项)

#污点的组成格式如下:
key=value:effect

每个污点有一个 key 和 value 作为污点的标签,其中 value 可以为空,effect 描述污点的作用。

个污点由键值对(key=value)和一个效果(effect)组成。效果描述了污点的作用,而键值对表示该污点的标签。支持的效果包括:

  • NoSchedule(不调度): Kubernetes将不会将Pod调度到具有该污点的节点上。

  • PreferNoSchedule(尽量避免调度): Kubernetes将尽量避免将Pod调度到具有该污点的节点上,但不是绝对禁止。

  • NoExecute(不执行): Kubernetes将不会将Pod调度到具有该污点的节点上,并且会将节点上已经存在的Pod驱逐出去,确保节点不再运行这些Pod。

这种机制为Kubernetes提供了更精细的调度控制,使得系统可以根据特定的需求和场景进行灵活的调度决策。

污点的基本操作

用一个具体的示例来说明如何在Kubernetes中执行这些操作。

假设我们有一个名为node-1的节点,我们要给它添加一个污点,阻止Pod在这个节点上调度,除非它们具有特定的标签。我们将添加一个名为special=true:NoSchedule的污点。

添加污点

kubectl taint nodes <node-name> key=value:taint-effect
kubectl taint nodes node-1 special=true: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 key1=value1: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 check=mycheck: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 check=mycheck: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: myapp01
  labels:
    app: myapp01
spec:
  containers:
  - name: with-node-affinity
    image: soscscs/myapp:v1
  tolerations:
  - key: "check"
    operator: "Equal"
    value: "mycheck"
    effect: "NoExecute"
    tolerationSeconds: 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: "key"
    operator: "Exists"

  • 多个 Master 存在时,防止资源浪费,可设置如下:

    kubectl taint node Master-Name node-role.kubernetes.io/master=:PreferNoSchedule

  • 若某个 Node 更新升级系统组件,为防止业务中断,可先在该 Node 设置 NoExecute 污点,驱逐 Pod。

    kubectl taint node node01 check=mycheck:NoExecute

  • 若其他 Node 资源不足,可暂时给 Master 设置 PreferNoSchedule 污点,使 Pod 在 Master 上创建。

    kubectl taint node master node-role.kubernetes.io/master=:PreferNoSchedule

  • 所有 Node 更新操作完成后,移除污点。

    kubectl taint node node01 check=mycheck: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> <KEY>=<VALUE>:<EFFECT> 命令在节点上设置污点。污点可以阻止 Pod 在具有特定标签和效果的节点上调度。

  • 移除污点: 使用 kubectl taint node <NODE_NAME> <KEY>=<VALUE>:<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 启动或运行中的问题进行详细的排查和诊断,从而有效地解决问题并确保应用程序正常运行。

相关推荐
桂月二二1 小时前
Java与容器化:如何使用Docker和Kubernetes优化Java应用的部署
java·docker·kubernetes
007php0073 小时前
linux服务器上CentOS的yum和Ubuntu包管理工具apt区别与使用实战
linux·运维·服务器·ubuntu·centos·php·ai编程
人类群星闪耀时3 小时前
深度学习在灾难恢复中的作用:智能运维的新时代
运维·人工智能·深度学习
djykkkkkk3 小时前
ubuntu编译遇到的问题
linux·运维·ubuntu
LinkTime_Cloud3 小时前
GitLab 将停止为中国区用户提供服务,60天迁移期如何应对? | LeetTalk Daily
大数据·运维·gitlab
qq_429856573 小时前
linux 查看服务是否开机自启动
linux·运维·服务器
Smile丶凉轩4 小时前
Docker核心技术和实现原理
运维·docker·容器
清风细雨_林木木4 小时前
Docker使用——国内Docker的安装办法
运维·docker·容器
运维&陈同学4 小时前
【Kibana01】企业级日志分析系统ELK之Kibana的安装与介绍
运维·后端·elk·elasticsearch·云原生·自动化·kibana·日志收集
dessler5 小时前
Docker-Dockerfile讲解(三)
linux·运维·docker