当前位置: 首页 > news >正文

k8s:pod-1

k8s:pod-1

pod生命周期

pod创建过程:

运行初始化容器(init container) > 运行主容器(main container) >容器启动后钩子(post start) 容器终止前钩子(pre stop)

容器的存活性探测(liveness probe)、就绪性探测(readiness probe)

在这里插入图片描述

在生命周期中会出现5种状态:
  • 挂起(Pending):apiserver已经创建了pod资源对象,但它尚未被调度完成或者仍处于下载镜像的过程中
  • 运行中(Running):pod已经被调度至某节点,并且所有容器都已经被kubelet创建完成
  • 成功(Succeeded):pod中的所有容器都已经成功终止并且不会被重启
  • 失败(Failed):所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态
  • 未知(Unknown):apiserver无法正常获取到pod对象的状态信息,通常由网络通信失败所导致
pod的创建过程

步骤 1: 用户提交请求

  • 动作: 用户通过 kubectl、客户端库或 REST API 向 Kubernetes API Server 提交 Pod 的定义文件(通常是 YAML 或 JSON 格式)。
  • 角色: API Server 是集群的网关和管理前端。

步骤 2: API Server 持久化存储

  • 动作: API Server 对请求进行验证和准入控制,然后根据用户提交的信息,在 etcd 中创建一个新的 Pod 对象,并将其状态设置为 Pending
  • 角色: etcd 是 Kubernetes 的“唯一可信数据源”,所有集群状态都存储于此。

步骤 3: 事件驱动与监听机制

  • 动作: API Server 中 Pod 资源的创建和更新事件会被诸如 Scheduler 和 Kubelet 这样的组件监听到。这些组件通过 Watch 机制与 API Server 建立长连接,实时获取与其相关的资源变动。
  • 关键: 这是 Kubernetes 声明式 API 和控制器模式的核心,各组件通过“观察-调整-反馈”循环来驱动系统达到期望状态。

步骤 4: Scheduler 调度决策

  • 动作
    1. Scheduler 监测到有一个新的 Pod 被创建,且其 nodeName 为空,于是开始调度流程。
    2. 它通过一系列预选和优选算法,从集群中选择一个最适合的节点。
    3. 调度器将决策结果(即目标节点名)通过 nodeName 字段绑定到 Pod 对象上,并将此更新提交给 API Server。
  • 角色: Scheduler 是负责资源分配的“调度中心”。

步骤 5: Kubelet 创建容器

  • 动作
    1. 目标节点上的 Kubelet 监测到有一个 Pod 被调度到了自己所在的节点。
    2. Kubelet 根据 Pod 规格描述,通过 Container Runtime(如 Docker、containerd 等)来拉取镜像、创建并启动容器。
    3. 它还会根据配置设置网络、挂载存储卷等。
  • 角色: Kubelet 是节点上的“代理”,负责管理本节点 Pod 的生命周期。

步骤 6: 状态上报与完成

  • 动作
    1. Kubelet 持续监控容器的状态。一旦容器启动成功,Kubelet 会将 Pod 的状态更新为 Running 并上报给 API Server。如果启动失败,则上报 Failed
    2. API Server 接收到状态更新后,再次将 Pod 的最新状态写入 etcd。
  • 最终状态: 此时,Pod 的完整信息(包括其运行状态)已在 etcd 中持久化,整个创建流程结束。

流程核心特点总结

  • 中心化存储:所有状态都以 Pod 对象的形式存储在 etcd 中,API Server 是唯一可对其进行操作的中心。
  • 事件驱动:Scheduler 和 Kubelet 等组件不主动轮询,而是通过 Watch 机制监听 API Server 的事件,实现高效、实时的协同。
  • 异步操作:用户的创建请求的返回,仅表示 API Server 已接收并存储了 Pod 的定义,并不代表 Pod 已成功运行。后续的调度和创建过程是异步进行的。
  • 自我修复:如果 Pod 在运行过程中意外终止,Kubelet 会监测到这一状态变化,并根据 Pod 的 restartPolicy 决定是否重启容器,并再次将最新状态上报给 API Server,进入一个新的状态更新循环。

pod的终止过程

步骤 1: 用户发起删除命令

  • 动作: 用户通过 kubectl delete pod 或其他客户端向 API Server 发送删除 Pod 的请求。

步骤 2 , 3: API Server 标记 Pod 为终止状态

  • 动作
    1. API Server 接收到删除请求后,不会立即删除 Pod 对象,而是会修改 Pod 的元数据。
    2. 它会在 Pod 上设置一个删除时间戳deletionGracePeriodSeconds(宽限期,默认30秒)
    3. Pod 的状态随之变为 Terminating。此时,Pod 虽然仍在运行,但已被视为“正在死亡”的状态。

步骤 4: Kubelet 监控到终止状态并启动关闭流程

  • 动作: 目标节点上的 Kubelet 通过 Watch 机制监测到其管理的 Pod 被标记为 Terminating,随即开始触发本节点的 Pod 关闭过程。

步骤 5: 从 Service 端点列表中移除

  • 动作Endpoints Controller(端点控制器)同样监控到 Pod 进入 Terminating 状态。它会立即将这个 Pod 的 IP 地址从所有关联的 Service 的 Endpoints(或 EndpointSlice)列表中移除
  • 关键作用: 这一步切断了流向该 Pod 的新流量,是确保优雅终止、避免请求丢失的关键。此后,Service 的负载均衡器不会再转发新的连接到此 Pod。

步骤 6: 执行 preStop Hook

  • 动作: 如果 Pod 中定义了 preStop 钩子处理器,Kubelet 会同步地在 Pod 的容器内执行它。
  • 目的: 这是应用在收到终止信号前,执行自定义清理逻辑(如通知注册中心、完成剩余任务、优雅关闭连接)的最后机会。preStop 钩子的执行时间包含在宽限期之内。

步骤 7: 发送 SIGTERM 信号

  • 动作preStop 钩子执行完毕后(或如果没有定义钩子),Kubelet 会向 Pod 内每个容器的主进程发送 SIGTERM 信号。
  • 目的: 这是一个“优雅终止”信号,通知应用程序自行关闭。设计良好的应用会捕获此信号并开始清理工作,然后退出。

步骤 8: 宽限期结束与强制终止

  • 动作
    • 情况A(成功): 如果所有容器在主进程收到 SIGTERM 后,在宽限期结束前自行退出,则关闭流程顺利完成。
    • 情况B(超时): 如果宽限期(例如30秒)结束后,Pod 中仍有容器在运行,Kubelet 会向这些容器发送 SIGKILL 信号,立即强制终止进程

最终清理

  • 动作: 无论进程是自行退出还是被强制杀死,一旦 Pod 内的所有容器都停止运行,Kubelet 就会通知 API Server,API Server 随后会彻底清理并删除 etcd 中的 Pod 记录。
  • 结果: 至此,Pod 对象对于用户而言已完全消失,其生命周期正式结束。

流程核心特点总结

  • 优雅终止:核心设计思想是给予应用充分的时间进行清理,而非直接暴力杀死。
  • 流量切断:通过先从 Service 移除端点来防止新的请求到达正在关闭的 Pod。
  • 双重信号:先 SIGTERM(友好协商),再 SIGKILL(强制措施)。
  • 可配置性terminationGracePeriodSecondspreStop 钩子让用户可以根据应用特性定制关闭行为

初始化容器

初始化容器是在 Pod 的主应用程序容器启动之前运行的一个或多个特殊容器,它们为 Pod 的部署提供了强大的前置准备和校验能力。

核心特征
  1. 强制性成功完成
    • 每个初始化容器都必须运行直至结束
    • 如果某个初始化容器运行失败(即退出码非零),Kubernetes 会根据 Pod 的 restartPolicy 策略(通常为 AlwaysOnFailure重启它,直到它成功运行完毕
    • 这是一个“全部或没有”的操作:所有初始化容器都必须成功,Pod 才能启动主容器。
  2. 顺序执行
    • 初始化容器按照它们在 Pod 清单中定义的顺序逐个执行
    • 当前一个初始化容器成功退出后,下一个初始化容器才能开始启动。
    • 这与主容器的并行启动模式形成鲜明对比。
主要应用场景

初始化容器与主容器共享镜像空间,这使得它们非常适合完成以下前置工作:

  • 提供主容器不具备的工具或代码
    • 场景:主容器镜像是为了最小化和安全而构建的,可能不包含 curlnslookupdig 或特定脚本等调试或设置工具。
    • 做法:可以使用一个包含必要工具的初始化容器镜像,来执行这些操作,而无需污染主容器镜像。
  • 延迟应用启动,直到依赖就绪
    • 场景:主应用容器需要依赖外部服务(如数据库、API 后端、缓存服务)先正常运行。
    • 做法:在初始化容器中使用一个脚本,通过循环检测(如 curlnc)来等待依赖服务变为可连接状态。只有当依赖服务就绪后,初始化容器才会成功退出,从而允许主容器启动。
  • 生成配置文件或下载数据
    • 场景:主容器运行所需的配置文件需要根据环境变量或 API 查询结果动态生成。
    • 做法:让初始化容器从 ConfigMap、Secret 或外部服务获取数据,然后渲染生成最终的配置文件,并存入一个共享的 Volume 中供主容器使用。
  • 权限分离与安全控制
    • 场景:主容器需要以非 root 用户运行以保证安全,但某些初始化步骤(如修改文件系统权限、挂载敏感目录)需要更高的权限。
    • 做法:可以让初始化容器以高权限运行来完成这些设置,然后退出。随后主容器以低权限运行,从而减小了攻击面。

假设要以主容器来运行nginx,但是要求在运行nginx之前先要能够连接上mysql所在服务器

创建pod-initcontainer.yaml
[root@master ~]# vim pod-initcontainer.yamlapiVersion: v1
kind: Pod
metadata:name: pod-initcontainernamespace: dev
spec:containers:- name: main-containerimage: nginx:1.17.1ports: - name: nginx-portcontainerPort: 80initContainers:- name: test-mysqlimage: busybox:1.30command: ['sh', '-c', 'until ping 192.168.100.10 -c 2 ; do echo waiting for mysql...; sleep 2; done;']
创建pod
[root@master ~]# kubectl create ns dev
namespace/dev created[root@master ~]# kubectl create -f pod-initcontainer.yaml 
pod/pod-initcontainer created
查看pod
 [root@master ~]# kubectl describe pod pod-initcontainer -n dev Normal  Scheduled  7m59s  default-scheduler  Successfully assigned dev/pod-initcontainer toNormal  Pulling    8m     kubelet            Pulling image "busybox:1.30"Normal  Pulled     7m58s  kubelet            Successfully pulled image "busybox:1.30" in 1.Normal  Created    7m58s  kubelet            Created container test-mysqlNormal  Started    7m58s  kubelet            Started container test-mysqlNormal  Pulling    7m56s  kubelet            Pulling image "nginx:1.17.1"Normal  Pulled     7m47s  kubelet            Successfully pulled image "nginx:1.17.1" in 8.Normal  Created    7m47s  kubelet            Created container main-containerNormal  Started    7m47s  kubelet            Started container main-container#可以看到这里是先运行第一个初始化容器,然后再运行主容器,pod也是正常运行#现在关闭192.168.100.10模拟故障#删除pod[root@master ~]# kubectl delete -f pod-initcontainer.yaml#192.167.100.10关机,再次创建[root@master ~]# kubectl apply -f pod-initcontainer.yaml 
pod/pod-initcontainer created[root@master ~]# kubectl get pods -n dev
NAME                READY   STATUS    RESTARTS   AGE
pod-initcontainer   0/1     Pending   0          11s
#查看会发现出问题了,原因是192.168.100.10关机,初始化过程失败导致主容器一直不能运行,实验成功

钩子函数

钩子函数能够感知自身生命周期中的事件,并在相应的时刻到来时运行用户指定的程序代码。

kubernetes在主容器的启动之后和停止之前提供了两个钩子函数:

  • post start:容器创建之后执行,如果失败了会重启容器
  • pre stop :容器终止之前执行,执行完成之后容器将成功终止,在其完成之前会阻塞删除容器的操作
钩子处理器支持3种定义动作
  • Exec命令:在容器内执行一次命令

    lifecycle:postStart: exec:command:- cat- /tmp/healthy
    
  • TCPSocket:在当前容器尝试访问指定的socket

    lifecycle:postStart:tcpSocket:port: 8080
    
  • HTTPGet:在当前容器中向某url发起http请求

    lifecycle:postStart:httpGet:path: / #URI地址port: 80 #端口号host: 192.168.5.3 #主机地址scheme: HTTP #支持的协议,http或者https
    
以exec方式为例,创建pod-hook-exec.yaml
[root@master ~]# vim pod-hook-exec.yamlapiVersion: v1
kind: Pod
metadata:name: pod-hook-execnamespace: dev
spec:containers:- name: main-containerimage: nginx:1.17.1ports:- name: nginx-portcontainerPort: 80lifecycle:postStart: exec: command: ["/bin/sh", "-c", "echo test111... > /usr/share/nginx/html/index.html"]preStop:exec: command: ["/usr/sbin/nginx","-s","quit"]
创建pod
[root@master ~]# kubectl apply -f pod-hook-exec.yaml 
pod/pod-hook-exec created
查看pod
[root@master ~]# kubectl get pods  pod-hook-exec -n dev -o wide
NAME            READY   STATUS    RESTARTS   AGE   IP              NODE    NOMINATED NODE   READINESS GATES
pod-hook-exec   1/1     Running   0          26s   172.16.104.28   node2   <none>           <none>
访问测试
[root@master ~]# curl 172.16.104.28
test111...

容器探测

容器探测是 Kubernetes 用于检测容器应用实例是否正常工作的健康检查机制。通过定期执行诊断,确保业务的可用性。

两种核心探针类型

1. Liveness Probe(存活性探针)
  • 作用:检测应用实例当前是否处于正常运行状态
  • 失败后果:如果探测失败,Kubernetes 会重启容器
  • 使用场景:用于恢复"进程存在但应用已死"的状态
    • 应用死锁
    • 内部错误导致无法响应
    • 内存泄漏导致应用卡死
2. Readiness Probe(就绪性探针)
  • 作用:检测应用实例当前是否可以接收请求
  • 失败后果:如果探测失败,Kubernetes 会将该实例从 Service 的负载均衡中摘除不转发流量
  • 使用场景:用于处理"应用正在启动或临时不可用"的情况
    • 应用启动较慢,需要时间初始化
    • 依赖服务暂时不可用
    • 临时高负载无法处理新请求
两种探针都支持三种探测方式:
  • Exec命令:在容器内执行一次命令,如果命令执行的退出码为0,则认为程序正常,否则不正常
  • TCPSocket:将会尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常
  • HTTPGet:调用容器内Web应用的URL,如果返回的状态码在200和399之间,则认为程序正常,否则不正常
创建pod-liveness-exec.yaml(exec)
apiVersion: v1
kind: Pod
metadata:name: pod-liveness-execnamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1ports: - name: nginx-portcontainerPort: 80livenessProbe:exec:command: ["/bin/cat","/tmp/hello.txt"] 
[root@master ~]# kubectl apply -f pod-liveness-exec.yaml 
pod/pod-liveness-exec created

查看

  Normal   Scheduled  20s               default-scheduler  Successfully assigned dev/pod-liveness-exec to node1Normal   Pulled     20s               kubelet            Container image "nginx:1.17.1" already present on machineNormal   Created    20s               kubelet            Created container nginxNormal   Started    20s               kubelet            Started container nginxWarning  Unhealthy  0s (x2 over 10s)  kubelet            Liveness probe failed: /bin/cat: /tmp/hello.txt: No such file or directory
#这里由于没有这个文件,导致运行失败,存活性探针检测到运行失败然后就会重启容器
[root@master ~]# kubectl get pods -n dev
NAME                READY   STATUS    RESTARTS     AGE
pod-hook-exec       1/1     Running   0            13m
pod-initcontainer   1/1     Running   0            17m
pod-liveness-exec   1/1     Running   4 (3s ago)   2m3s
#这里发现重启了4次
如果想让它恢复正常,可以修改为存在的文件,这样运行就会成功,就不会一直重启
创建pod-liveness-tcpsocket.yaml(TCPSocket)
apiVersion: v1
kind: Pod
metadata:name: pod-liveness-tcpsocketnamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1ports: - name: nginx-portcontainerPort: 80livenessProbe:tcpSocket:port: 8080
创建pod
[root@master ~]# kubectl apply -f pod-liveness-tcpsocket.yaml 
pod/pod-liveness-tcpsocket created
查看
[root@master ~]# kubectl describe pods pod-liveness-tcpsocket -n devNormal   Scheduled  19s   default-scheduler  Successfully assigned dev/pod-liveness-tcpsocket to node1Normal   Pulled     19s   kubelet            Container image "nginx:1.17.1" already present on machineNormal   Created    19s   kubelet            Created container nginxNormal   Started    19s   kubelet            Started container nginxWarning  Unhealthy  9s    kubelet            Liveness probe failed: dial tcp 172.16.166.152:8080: connect: connection refused#这里是因为无法连接到8080端口而失败
[root@master ~]# kubectl get pods pod-liveness-tcpsocket  -n dev
NAME                     READY   STATUS    RESTARTS     AGE
pod-liveness-tcpsocket   1/1     Running   4 (5s ago)   2m6s
#这里重启了4次,如果想恢复正常,则把8080端口换成80端口
创建pod-liveness-httpget.yaml(HTTPGet)
[root@master ~]# vim pod-liveness-httpget.yamlapiVersion: v1
kind: Pod
metadata:name: pod-liveness-httpgetnamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1ports:- name: nginx-portcontainerPort: 80livenessProbe:httpGet:    scheme: HTTP port: 80 path: /hello 
[root@master ~]# kubectl apply -f pod-liveness-httpget.yaml 
pod/pod-liveness-httpget created

查看

[root@master ~]# kubectl describe pod pod-liveness-httpget -n devNormal   Scheduled  20s               default-scheduler  Successfully assigned dev/pod-liveness-httpget to node2Normal   Pulled     20s               kubelet            Container image "nginx:1.17.1" already present on machineNormal   Created    20s               kubelet            Created container nginxNormal   Started    20s               kubelet            Started container nginxWarning  Unhealthy  1s (x2 over 11s)  kubelet            Liveness probe failed: HTTP probe failed with statuscode: 404#这里返回404原因是因为没有这个网页[root@master ~]# kubectl get pod pod-liveness-httpget -n dev
NAME                   READY   STATUS    RESTARTS      AGE
pod-liveness-httpget   1/1     Running   1 (28s ago)   58s
#这里重启了一次,如果想恢复正常,则需要换成能够访问的路径
livenessProbe其他的配置
[root@master ~]# kubectl explain pod.spec.containers.livenessProbeFIELDS:exec <Object>  tcpSocket    <Object>httpGet      <Object>initialDelaySeconds  <integer>  # 容器启动后等待多少秒执行第一次探测timeoutSeconds       <integer>  # 探测超时时间。默认1秒,最小1秒periodSeconds        <integer>  # 执行探测的频率。默认是10秒,最小1秒failureThreshold     <integer>  # 连续探测失败多少次才被认定为失败。默认是3。最小值是1successThreshold     <integer>  # 连续探测成功多少次才被认定为成功。默认是1
重启策略
三种重启策略

Pod 的重启策略在 .spec.restartPolicy 字段中定义,共有三种:

  1. Always(默认值)
    • 行为:只要容器终止运行,无论其退出代码是什么,Kubernetes 都会自动重启该容器。
    • 适用场景:适用于需要长期持续运行的应用,如 Web 服务器、API 服务等。
  2. OnFailure
    • 行为:只有当容器异常终止(即退出码不为 0)时,才会自动重启。如果容器正常退出(退出码为 0),则不会重启。
    • 适用场景:适用于执行一次性任务或批处理作业,但任务可能因临时故障而失败需要重试的场景。
  3. Never
    • 行为:无论容器因何种原因终止,都不会对其进行重启。
    • 适用场景:适用于确保证任务只运行一次且不允许自动重试的场景。
创建pod-restartpolicy.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-restartpolicynamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1ports:- name: nginx-portcontainerPort: 80livenessProbe:httpGet:scheme: HTTPport: 80path: /hellorestartPolicy: Never       #运行失败不会重启

测试

[root@master ~]# kubectl apply -f pod-restartpolicy.yaml 
pod/pod-restartpolicy created
#查看
[root@master ~]# kubectl describe pods pod-restartpolicy -n devNormal   Scheduled  25s               default-scheduler  Successfully assigned dev/pod-restartpolicy to node2Normal   Pulled     24s               kubelet            Container image "nginx:1.17.1" already present on machineNormal   Created    24s               kubelet            Created container nginxNormal   Started    24s               kubelet            Started container nginxWarning  Unhealthy  4s (x2 over 14s)  kubelet            Liveness probe failed: HTTP probe failed with statuscode: 404#状态码返回404是因为没有这个网页[root@master ~]# kubectl get pods -n dev
NAME                READY   STATUS      RESTARTS   AGE
pod-restartpolicy   0/1     Completed   0          76s

Pod调度

pod调度有4种方式:

  • 自动调度:运行在哪个节点上完全由Scheduler经过一系列的算法计算得出
  • 定向调度:NodeName、NodeSelector
  • 亲和性调度:NodeAffinity、PodAffinity、PodAntiAffinity
  • 污点(容忍)调度:Taints、Toleration

定向调度

核心概念
  • 作用:直接将 Pod 调度到指定的 Node 节点上。
  • 级别:这是一种强制性的调度约束。
  • 绕过调度器:当设置了 nodeName 时,Kubernetes 的默认调度器(kube-scheduler)会被绕过。它不会进行任何资源充足性检查(如 CPU、内存)、节点选择策略检查(如节点亲和性)或污点容忍度检查。
  • 风险:如果指定的节点不存在,或者节点资源不足,Pod 将会运行失败,并处于 Pending 状态。
创建一个pod-nodename.yaml文件
[root@master ~]# vim pod-nodename.yamlapiVersion: v1
kind: Pod
metadata:name: pod-nodenamenamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1nodeName: node1    #调度到node1节点上

查看

[root@master ~]# kubectl apply -f pod-nodename.yaml 
pod/pod-nodename created[root@master ~]# kubectl get pods -n dev -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
pod-nodename   1/1     Running   0          18s   172.16.166.153   node1   <none>           <none>

接下来,删除pod,修改nodeName的值为node3(无节点)

apiVersion: v1
kind: Pod
metadata:name: pod-nodenamenamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1nodeName: node3

查看

[root@master ~]# kubectl apply -f pod-nodename.yaml 
pod/pod-nodename created[root@master ~]# kubectl get pods -n dev -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP       NODE    NOMINATED NODE   READINESS GATES
pod-nodename   0/1     Pending   0          35s   <none>   node3   <none>           <none>
#确实调度到了node3,但是由于没有这个节点导致pod运行失败

NodeSelector

NodeSelector 是 Pod 规范中的一个字段,它通过为 Pod 指定一个或多个节点标签选择器,将 Pod 强制调度到拥有对应标签的节点上。它提供了一种比 nodeName 更灵活、更具声明性的调度方式。

核心概念
  • 作用:根据节点的标签来选择合适的节点。
  • 机制:它是一个简单的键值对匹配。Pod 的 nodeSelector 中指定的键值必须与目标节点上设置的标签完全匹配,Pod 才能被调度到该节点。
  • 级别:这是一种强制性的调度约束。如果没有任何节点拥有匹配的标签,Pod 将无法被调度,并处于 Pending 状态。
  • 经过调度器:与 nodeName 不同,nodeSelector 会经过 kube-scheduler。调度器会检查节点的资源是否充足,并确保节点满足 Pod 的其他要求
首先为节点node1,node2添加标签
[root@master ~]# kubectl label nodes node1 tag=test1
node/node1 labeled
[root@master ~]# kubectl label nodes node2 tag=test2
node/node2 labeled
创建一个pod-nodeselector.yaml文件
apiVersion: v1
kind: Pod
metadata:name: pod-nodeselectornamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1nodeSelector: tag: test1
[root@master ~]# kubectl apply -f pod-nodeselector.yaml
pod/pod-nodeselector created

查看

[root@master ~]# kubectl get pods -n dev -o wide 
NAME               READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
pod-nodeselector   1/1     Running   0          46s   172.16.166.154   node1   <none>           <none>

可以发现是在node1上运行,修改文件为,让pod在node2上运行

apiVersion: v1
kind: Pod
metadata:name: pod-nodeselectornamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1nodeSelector:tag: test2

再次运行查看

[root@master ~]# kubectl get pods -n dev -o wide 
NAME               READY   STATUS    RESTARTS   AGE   IP              NODE    NOMINATED NODE   READINESS GATES
pod-nodeselector   1/1     Running   0          5s    172.16.104.31   node2   <none>           <none>
#可以发现这次运行在node2上
#如果不存在这个标签,则会运行失败

修改标签为tag=test3

[root@master ~]# kubectl get pods -n dev -o wide 
NAME               READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
pod-nodeselector   0/1     Pending   0          9s    <none>   <none>   <none>           <none>
#如果没有指定的标签则会运行失败

亲和性调度

Affinity,它在NodeSelector的基础之上的进行了扩展,可以通过配置的形式,实现优先选择满足条件的Node进行调度,如果没有,也可以调度到不满足条件的节点上,使调度更加灵活。

Affinity主要分为三类:

  • nodeAffinity(node亲和性): 以node为目标,解决pod可以调度到哪些node的问题

  • podAffinity(pod亲和性) : 以pod为目标,解决pod可以和哪些已存在的pod部署在同一个拓扑域中的问题

  • podAntiAffinity(pod反亲和性) : 以pod为目标,解决pod不能和哪些已存在pod部署在同一个拓扑域中的问题

关于亲和性(反亲和性)使用场景的说明:

亲和性:如果两个应用频繁交互,那就有必要利用亲和性让两个应用的尽可能的靠近,这样可以减少因网络通信而带来的性能损耗。

反亲和性:当应用的采用多副本部署时,有必要采用反亲和性让各个应用实例打散分布在各个node上,这样可以提高服务的高可用性

NodeAffinity

可配置选项

pod.spec.affinity.nodeAffinityrequiredDuringSchedulingIgnoredDuringExecution  Node节点必须满足指定的所有规则才可以,相当于硬限制nodeSelectorTerms  节点选择列表matchFields   按节点字段列出的节点选择器要求列表matchExpressions   按节点标签列出的节点选择器要求列表(推荐)key    键values 值operator 关系符 支持Exists, DoesNotExist, In, NotIn, Gt, LtpreferredDuringSchedulingIgnoredDuringExecution 优先调度到满足指定的规则的Node,相当于软限制 (倾向)preference   一个节点选择器项,与相应的权重相关联matchFields   按节点字段列出的节点选择器要求列表matchExpressions   按节点标签列出的节点选择器要求列表(推荐)key    键values 值operator 关系符 支持In, NotIn, Exists, DoesNotExist, Gt, Ltweight 倾向权重,在范围1-100。关系符的使用说明:
- matchExpressions:- key: nodeenv              # 匹配存在标签的key为nodeenv的节点operator: Exists- key: nodeenv              # 匹配标签的key为nodeenv,且value是"xxx"或"yyy"的节点operator: Invalues: ["xxx","yyy"]- key: nodeenv              # 匹配标签的key为nodeenv,且value大于"xxx"的节点operator: Gtvalues: "xxx"
创建pod-nodeaffinity-required.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-nodeaffinity-requirednamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1affinity:  nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms:- matchExpressions: - key: tagoperator: Invalues: ["xxx","yyy"]

查看

[root@master ~]# kubectl apply -f pod-nodeaffinity-required.yaml
[root@master ~]# kubectl get pods -n dev
NAME                        READY   STATUS    RESTARTS   AGE
pod-nodeaffinity-required   0/1     Pending   0          13s
#这里失败是因为没有values: ["xxx","yyy"],删除pod然后换成有的
[root@master ~]# kubectl delete -f pod-nodeaffinity-required.yaml
pod "pod-nodeaffinity-required" deletedapiVersion: v1
kind: Pod
metadata:name: pod-nodeaffinity-requirednamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1affinity:nodeAffinity:requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: tagoperator: Invalues: ["test1","yyy"]

再次运行查看

[root@master ~]# kubectl get pods -n dev -o wide 
NAME                        READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
pod-nodeaffinity-required   1/1     Running   0          8s    172.16.166.155   node1   <none>

运行在了node1节点上

查看node1的标签

[root@master ~]# kubectl get nodes node1 --show-labels 
NAME    STATUS   ROLES    AGE    VERSION    LABELS
node1   Ready    <none>   7d4h   v1.28.15   beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node1,kubernetes.io/os=linux,tag=test1
PodAffinity

PodAffinity主要实现以运行的Pod为参照,实现让新创建的Pod跟参照pod在一个区域的功能

PodAffinity可配置选项

pod.spec.affinity.podAffinityrequiredDuringSchedulingIgnoredDuringExecution  硬限制namespaces       指定参照pod的namespacetopologyKey      指定调度作用域labelSelector    标签选择器matchExpressions  按节点标签列出的节点选择器要求列表(推荐)key    键values 值operator 关系符 支持In, NotIn, Exists, DoesNotExist.matchLabels    指多个matchExpressions映射的内容preferredDuringSchedulingIgnoredDuringExecution 软限制podAffinityTerm  选项namespaces      topologyKeylabelSelectormatchExpressions  key    键values 值operatormatchLabels weight 倾向权重,在范围1-100
topologyKey用于指定调度时作用域,例如:如果指定为kubernetes.io/hostname,那就是以Node节点为区分范围如果指定为beta.kubernetes.io/os,则以Node节点的操作系统类型来区分
创建pod-podaffinity-target.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-podaffinity-targetnamespace: devlabels:tag: test
spec:containers:- name: nginximage: nginx:1.17.1nodeName: node1 
[root@master ~]# kubectl apply -f pod-podaffinity-target.yaml 
pod/pod-podaffinity-target created
#查看pod
[root@master ~]# kubectl get pods -n dev
NAME                     READY   STATUS    RESTARTS   AGE
pod-podaffinity-target   1/1     Running   0          24s
创建pod-podaffinity-required.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-podaffinity-requirednamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1affinity:podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector:matchExpressions:- key: tagoperator: Invalues: ["xxx","yyy"]		#新pod的标签要匹配之前创建的pod标签topologyKey: kubernetes.io/hostname
[root@master ~]# kubectl apply -f pod-podaffinity-required.yaml 
pod/pod-podaffinity-required created
#查看
[root@master ~]# kubectl get pods -n dev
NAME                       READY   STATUS    RESTARTS   AGE
pod-podaffinity-required   0/1     Pending   0          17s
pod-podaffinity-target     1/1     Running   0          2m1s
#由于没有匹配到上一个pod的标签,因此运行失败,删除这个pod修改标签
[root@master ~]# kubectl delete -f pod-podaffinity-required.yaml 
pod "pod-podaffinity-required" deleted
[root@master ~]# vim pod-podaffinity-required.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-podaffinity-requirednamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1affinity:podAffinity:requiredDuringSchedulingIgnoredDuringExecution:- labelSelector:matchExpressions:- key: tagoperator: Invalues: ["test","yyy"]    #修改为testtopologyKey: kubernetes.io/hostname[root@master ~]# kubectl apply -f pod-podaffinity-required.yaml 
pod/pod-podaffinity-required created
#再次查看pod会发现运行成功,查看部署节点
[root@master ~]# kubectl get pods -n dev
NAME                       READY   STATUS    RESTARTS   AGE
pod-podaffinity-required   1/1     Running   0          18s
pod-podaffinity-target     1/1     Running   0          3m55s[root@master ~]# kubectl get pods -n dev -o wide 
NAME                       READY   STATUS    RESTARTS   AGE     IP               NODE    NOMINATED NODE   READINESS GATES
pod-podaffinity-required   1/1     Running   0          54s     172.16.166.158   node1   <none>           <none>
pod-podaffinity-target     1/1     Running   0          4m31s   172.16.166.157   node1   <none>           <none>
#可以看到都是部署到node1节点
PodAntiAffinity

PodAntiAffinity主要实现以运行的Pod为参照,让新创建的Pod跟参照pod不在一个区域中的功能

创建pod-podantiaffinity-required.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-podantiaffinity-requirednamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1affinity:  podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector:matchExpressions: - key: tagoperator: Invalues: ["test"]topologyKey: kubernetes.io/hostname
[root@master ~]# kubectl apply -f pod-podantiaffinity-required.yaml 
pod/pod-podantiaffinity-required created 
#查看
[root@master ~]# kubectl get pods -n dev -o wide 
NAME                           READY   STATUS    RESTARTS   AGE     IP               NODE    NOMINATED NODE   READINESS GATES
pod-podaffinity-required       1/1     Running   0          9m19s   172.16.166.158   node1   <none>           <none>
pod-podaffinity-target         1/1     Running   0          12m     172.16.166.157   node1   <none>           <none>
pod-podantiaffinity-required   1/1     Running   0          17s     172.16.104.32    node2   <none>           <none>

污点和容忍

组成部分
  • key: 污点的键(标签名)
  • value: 污点的值(标签值)
  • effect: 污点的作用效果
污点效果(effect)类型
1. PreferNoSchedule
  • 作用: Kubernetes 会尽量避免将 Pod 调度到具有该污点的 Node 上
  • 行为: 除非没有其他节点可调度,否则不会选择该节点
  • 影响: 不影响已存在的 Pod
2. NoSchedule
  • 作用: Kubernetes 不会将 Pod 调度到具有该污点的 Node 上
  • 行为: 硬性限制,新 Pod 不会被调度到该节点
  • 影响: 不影响当前 Node 上已存在的 Pod
3. NoExecute
  • 作用: Kubernetes 不会将 Pod 调度到具有该污点的 Node 上,同时驱逐已存在的 Pod
  • 行为:
    • 新 Pod 不会被调度到该节点
    • 节点上已存在的 Pod 会被驱逐(除非设置了容忍)
  • 影响: 同时影响新 Pod 调度和已有 Pod 运行

命令:

# 设置污点
kubectl taint nodes node1 key=value:effect
# 去除污点
kubectl taint nodes node1 key:effect-
# 去除所有污点
kubectl taint nodes node1 key-

关闭node2节点进行测试,给node1节点设置污点

[root@master ~]# kubectl taint nodes node1 tag=test:PreferNoSchedule
node/node1 tainted
#创建pod
[root@master ~]# kubectl run taint1 --image=nginx:1.17.1 -n dev
pod/taint1 created[root@master ~]# kubectl get pods -n dev -o wide
NAME     READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
taint1   1/1     Running   0          39s   172.16.166.159   node1   <none>           <none>
#这里由于没有其他节点可用,只能在node1运行,将node1的污点修改为NoSchedule
[root@master ~]# kubectl taint nodes node1 tag:PreferNoSchedule-
node/node1 untainted
[root@master ~]# kubectl taint nodes node1 tag=chenyu:NoSchedule
node/node1 tainted
#再次创建pod
[root@master ~]# kubectl run taint2 --image=nginx:1.17.1 -n dev
pod/taint2 created
[root@master ~]# kubectl get pods -n dev -o wide
NAME     READY   STATUS    RESTARTS   AGE     IP               NODE     NOMINATED NODE   READINESS GATES
taint1   1/1     Running   0          2m25s   172.16.166.159   node1    <none>           <none>
taint2   0/1     Pending   0          13s     <none>           <none>   <none>           <none>
#由于pod设置了NoSchedule的,pod没有节点能够运行,于是运行失败
再次修改node1的节点,设置为NoExecute
[root@master ~]# kubectl taint nodes node1 tag:NoSchedule-
node/node1 untainted
[root@master ~]# kubectl taint nodes node1 tag=test:NoExecute
node/node1 tainted
#再次创建pod
[root@master ~]# kubectl get pods -n dev -o wide
NAME     READY   STATUS    RESTARTS   AGE   IP       NODE     NOMINATED NODE   READINESS GATES
taint3   0/1     Pending   0          5s    <none>   <none>   <none>           <none>
#不仅运行失败,之前两个pod也被踢出节点使用kubeadm搭建的集群,默认就会给master节点添加一个污点标记,所以pod就不会调度到master节点上.
容忍(Toleration)

添加容忍后pod就会忽略污点,不管是什么污点都能调度

创建pod-toleration.yaml
apiVersion: v1
kind: Pod
metadata:name: pod-tolerationnamespace: dev
spec:containers:- name: nginximage: nginx:1.17.1tolerations:      # 添加容忍- key: "tag"        # 要容忍的污点的keyoperator: "Equal" # 操作符value: "test"    # 容忍的污点的valueeffect: "NoExecute"   # 添加容忍的规则,这里必须和标记的污点规则相同
[root@master ~]# kubectl apply -f pod-toleration.yaml 
pod/pod-toleration created
[root@master ~]# kubectl get pods -n dev -o wide
NAME             READY   STATUS    RESTARTS   AGE   IP               NODE    NOMINATED NODE   READINESS GATES
pod-toleration   1/1     Running   0          22s   172.16.166.164   node1   <none>           <none>

容忍的详细配置

FIELDS:key       # 对应着要容忍的污点的键,空意味着匹配所有的键value     # 对应着要容忍的污点的值operator  # key-value的运算符,支持Equal和Exists(默认)effect    # 对应污点的effect,空意味着匹配所有影响tolerationSeconds   # 容忍时间, 当effect为NoExecute时生效,表示pod在Node上的停留时间
http://www.dtcms.com/a/574615.html

相关文章:

  • 蓝牙钥匙 第45次 密码学基础在蓝牙钥匙中的应用:构建数字车锁的安全基石
  • Java练习——常用API1
  • hyip网站开发推荐个做淘宝主图视频的网站
  • 企业网站建设所需要的资料wordpress有什么数据库引擎
  • 上海云盾除了WAF,CDN还提供哪些细粒度的访问控制功能?
  • 高级机器学习作业(二)度量学习 + 稀疏学习 + GMM-EM半监督学习
  • Retimer vs Redriver:高速信号传输的“修复师”与“整形师”
  • 基于电鱼 RK3588 AI 工控机的智慧工地视频智能分析方案——减少布线复杂度与网络延迟,实现高效边缘智能
  • layout常用操作,DFF触发器版图为例
  • 海报设计网站官网网站建设服务条款
  • 网站建设是什么语言wordpress站关注别人
  • 创建网站怎么创怎样用网站做app
  • 制作购物网站教程南京设计公司有哪些公司
  • cmd控制台出现 系统找不到指定的路径。
  • 婚恋网站建设教程网站源码还可以做授权么
  • 【App开发】Mumu模拟器安装使用与Android Studio连接指南
  • 宝安中心地铁站是几号线通辽网站制作
  • 广东网站备案多长时间自助建站代理
  • 从零开始搭建 flask 博客实验(3)
  • 使用 Python 解释 Telegram 被封禁的原因(附中文版与中文群组频道搜索机器人示例)
  • Rust 练习册 3:深入理解闭包(Closure)
  • 官方网站制作wordpress 镜像
  • C语言应用实例:解方程(二分查找)
  • t想学网站建设石家庄专业建站公司
  • 基础数据结构之数组的双指针技巧之对撞指针(两端向中间):三数之和(LeetCode 15 中等题)
  • 网站鼠标悬停动态效果代码网站一个月
  • ASP.NET网站建设实战网络推广的方式有哪些?
  • 防止缓存穿透
  • 防火墙培训
  • 李宏毅机器学习笔记40