目录
[添加标签(Add Labels):](#添加标签(Add Labels):)
[更新标签(Update Labels)](#更新标签(Update Labels))
[删除标签(Remove Labels)](#删除标签(Remove Labels))
[查询标签(Query Labels)](#查询标签(Query Labels))
[使用标签选择器(Label Selectors)](#使用标签选择器(Label Selectors))
[Pod 亲和性:](#Pod 亲和性:)
[Pod 亲和性调度策略的详细说明](#Pod 亲和性调度策略的详细说明)
[创建一个标签为 app=myapp01 的 Pod](#创建一个标签为 app=myapp01 的 Pod)
[使用 Pod 亲和性调度,创建多个 Pod 资源](#使用 Pod 亲和性调度,创建多个 Pod 资源)
[使用 Pod 反亲和性调度](#使用 Pod 反亲和性调度)
[污点(Taint) 和 容忍(Tolerations)](#污点(Taint) 和 容忍(Tolerations))
[Pod启动阶段(相位 phase)](#Pod启动阶段(相位 phase))
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" 不能存在。 -
这些运算关系在定义亲和性规则时用于匹配标签的条件
亲和性
在 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: 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):
-
匹配标签:对节点的标签进行匹配。
-
操作符 :支持的操作符包括
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 在 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
这两个命令的目的是给节点 node01
和 node02
分别打上标签 lab=a
和 lab=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 状态。由于 Podmyapp01
具有标签app=myapp01
,并且拓扑域键lab
的值为a
,而节点node01
和node02
都有拓扑域键lab
的标签,因此它们被认为处于相同的拓扑域。 -
由于新的 Pod
myapp20
需要避免与具有标签app=myapp01
的 Pod 调度到同一拓扑域,但在目前的节点中,没有节点符合该条件,因此该 Pod 保持在 Pending 状态。更新了node02
的标签,但似乎仍然不符合新 Pod 的调度要求。 -
最终,创建了一个新的 Pod
myapp21
,它成功在node02
上运行,因为现在node02
的标签为lab=b
,与之前的标签不同,因此不再满足与 Podmyapp20
的反亲和性调度要求。
污点(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 启动或运行中的问题进行详细的排查和诊断,从而有效地解决问题并确保应用程序正常运行。