k8s入门到实战(十二)—— pod的深入理解

pod 深入理解

pod 容器生命周期

pod 的几种状态

可以使用命令kubectl get pod -w实时监控查看 pod 的状态

  • running:正常运行状态
  • Pending:资源分配不对的时候会挂起,出现此状态
  • Terminating:某个节点突然关机,上面的 pod 就会是这种状态
  • ContainerCreating:容器创建的时候
  • OOMKilled:当要求的内存超过限制的时候,k8s 会把这个容器 kill 后重启
  • ErrImagePull:宿主机上不了网,镜像拉取失败

生命周期

在这里插入图片描述

每个 Pod 里运行着一个特殊的被称之为 Pause 的容器,其他容器则为业务容器,这些业务容器共享 Pause 容器的网络栈和 Volume 挂载卷,因此他们之间通信和数据交换更为高效。在设计时可以充分利用这一特性,将一组密切相关的服务进程放入同一个 Pod 中;同一个 Pod 里的容器之间仅需通过localhost 就能互相通信。

Pause 容器,又叫 Infra 容器

比如说现在有一个 Pod,其中包含了一个容器 A 和一个容器 B Pod ip,它们两个就要共享 Network Namespace。在 k8s 里的解法是这样的:它会在每个 Pod 里,额外起一个 Infra container 小容器来共享整个 Pod 的 Network Namespace。

Infra container 是一个非常小的镜像,大概 700KB 左右,是一个 C 语言写的、永远处于 “暂停” 状态的容器。由于有了这样一个 Infra container 之后,其他所有容器都会通过 Join Namespace 的方式加入到 Infra container 的 Network Namespace 中。

所以说一个 Pod 里面的所有容器,它们看到的网络视图是完全一样的。即:它们看到的网络设备、IP 地址、Mac 地址等等,跟网络相关的信息,其实全是一份,这一份都来自于 Pod 第一次创建的这个 Infra container。这就是 Pod 解决网络共享的一个解法。

由于需要有一个相当于说中间的容器存在,所以整个 Pod 里面,必然是 Infra container 第一个启动。并且整个 Pod 的生命周期是等同于 Infra container 的生命周期的,与容器 A 和 B 是无关的。这也是为什么在 k8s 里面,它是允许去单独更新 Pod 里的某一个镜像的,即:做这个操作,整个 Pod 不会重建,也不会重启,这是非常重要的一个设计。

Pod hook(钩子)是由 k8s 管理的 kubelet 发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。可以同时为 Pod 中的所有容器都配置 hook。

init 容器

官网:https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/init-containers/

Init 容器是一种特殊容器,在 Pod 内的应用容器启动之前运行。Init 容器可以包括一些应用镜像中不存在的实用工具和安装脚本。

每个 pod 中可以包含多个容器, 应用运行在这些容器里面,同时 Pod 也可以有一个或多个先于应用容器启动的 Init 容器。

Init 容器与普通的容器非常像,除了如下两点:

  • 它们总是运行到完成。
  • 每个都必须在下一个启动之前成功完成。

如果 Pod 的 Init 容器失败,kubelet 会不断地重启该 Init 容器直到该容器成功为止。 然而,如果 Pod 对应的 restartPolicy 值为 “Never”,并且 Pod 的 Init 容器失败, 则 k8s 会将整个 Pod 状态设置为失败。

为 Pod 设置 Init 容器需要在 Pod 规约 中添加 initContainers 字段, 该字段以 Container 类型对象数组的形式组织,和应用的 containers 数组同级相邻。

Init 容器的状态在 status.initContainerStatuses 字段中以容器状态数组的格式返回 (类似 status.containerStatuses 字段)。

下面我们编写一个案例测试 init 容器

  1. 编写 yaml 文件my-init.yaml
apiVersion: v1
kind: Pod
metadata:name: myapp-podlabels:app: myapp
spec:containers:- name: myapp-containerimage: busybox:1.28command: ['sh', '-c', 'echo The app is running! && sleep 3600']initContainers:- name: init-myserviceimage: busybox:1.28command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]- name: init-mydbimage: busybox:1.28command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
  1. 根据文件创建 pod
[root@k8s-master k8s]# vim my-init.yaml
[root@k8s-master k8s]# kubectl apply -f my-init.yaml 
pod/myapp-pod created
  1. 查看 pod
[root@k8s-master k8s]# kubectl get pod
NAME        READY   STATUS     RESTARTS   AGE
myapp-pod   0/1     Init:0/2   0          86s

可以看到我们的这个 pod 没有运行成功,这是因为 init 容器没有启动成功

Init 容器会等待至发现名称为 mydbmyservice 的服务。

  1. 接下来我们创建这两个服务,编写 yaml 文件init-svc.yaml
apiVersion: v1
kind: Service
metadata:name: myservice
spec:ports:- protocol: TCPport: 80targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:name: mydb
spec:ports:- protocol: TCPport: 80targetPort: 9377
  1. 启动两个服务,查看 pod 状态
[root@k8s-master k8s]# vim init-svc.yaml
[root@k8s-master k8s]# kubectl apply -f init-svc.yaml 
service/myservice created
service/mydb created
[root@k8s-master k8s]# kubectl get pod
NAME        READY   STATUS    RESTARTS   AGE
myapp-pod   1/1     Running   0          5m13s

可以看到 pod 已经顺利启动了

总结

Init 容器与普通的容器非常像,区别是每个都必须在下一个容器启动之前成功完成。

如果 Pod 的 Init 容器失败,kubelet 会不断地重启该 Init 容器直到该容器成功为止。 然而,如果 Pod 对应的 restartPolicy 值为 “Never”,k8s 不会重新启动 Pod。容器重启策略默认是Always

为 Pod 设置 Init 容器需要在 Pod 的 spec 中添加 initContainers 字段, 该字段以 Container类型对象数组的形式组织,和应用的 containers 数组同级相邻。

Init 容器支持应用容器的全部字段和特性,包括资源限制、数据卷和安全设置。

如果为一个 Pod 指定了多个 Init 容器,这些容器会按顺序逐个运行。 每个 Init 容器必须运行成功,下一个才能够运行。当所有的 Init 容器运行完成时, k8s 才会为 Pod 初始化应用容器并像平常一样运行。

容器探针

官网:https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

当你使用 k8s 的时候,有没有遇到过 Pod 在启动后一会就挂掉然后又重新启动这样的恶性循环?你有没有想过 k8s 是如何检测 pod 是否还存活?虽然容器已经启动,但是 k8s 如何知道容器的进程是否准备好对外提供服务了呢?

k8s 探针(Probe)是用于检查容器运行状况的一种机制。探针可以检查容器是否正在运行,容器是否能够正常响应请求,以及容器内部的应用程序是否正常运行等。在 k8s 中,探针可以用于确定容器的健康状态,如果容器的健康状态异常,k8s 将会采取相应的措施,例如重启容器或将其从服务中删除。

为什么需要容器探针?

容器探针可以确保您的容器在任何时候都处于可预测的状态。

如果没有容器探针,那么容器对于 k8s 平台而言,就处于一个黑盒状态。下面是没有使用容器探针可能出现的一些 case:

  • 容器未启动,负载均衡就把流量转发给容器,导致请求大量异常
  • 容器内服务不可用/发生异常,负载均衡把流量转发给容器,导致请求大量异常
  • 容器已经不正常工作(如容器死锁导致的应用程序停止响应),k8s 平台本身无法感知,不能即时低重启容器。

探测类型

针对运行中的容器,kubelet 可以选择是否执行以下三种探针,以及如何针对探测结果作出反应:

分别是Liveness Probe(存活探针)、Readiness Probe(就绪探针)、Startup Probe(启动探针)

# livenessProbe
用于检查容器是否正在运行,如果Liveness Probe检查失败,则Kubernetes将重启容器# readinessProbe
用于检查容器是否能够正常响应请求,如果Readiness Probe检查失败,则Kubernetes将停止将流量发送到该容器# startupProbe
用于检查容器内部的应用程序是否已经启动并且已经准备好接受流量,如果Startup Probe检查失败,则Kubernetes将重启容器

探针资源 yaml 中的常用的配置,如下。可根据具体的需求去设置,心跳机制

spec:containers:# 就绪探针readinessProbe:# 检测方式httpGet: # 超时时间timeoutSeconds: # 延迟时间initialDelaySeconds:# 失败次数限制failureThreshold:# 每多少秒检测一次periodSeconds:# 存活探针livenessProbe:# 检测方式httpGet: # 超时时间timeoutSeconds: # 延迟时间initialDelaySeconds:# 失败次数限制failureThreshold:# 每多少秒检测一次periodSeconds:

探针机制

使用探针来检查容器有四种不同的方法。 每个探针都必须准确定义为这四种机制中的一种:请求-响应。

#exec
在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。#httpGet
对容器的 IP 地址上指定端口和路径执行 HTTP GET 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。#tcpSocket
对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。如果远程系统 (容器)在打开连接后立即将其关闭,这算作是健康的。#grpc
使用 gRPC 执行一个远程过程调用。 目标应该实现 gRPC健康检查。 如果响应的状态是"SERVING",则认为诊断成功。 gRPC 探针是一个 alpha 特性,只有在你启用了"GRPCContainerProbe"特性门控时才能使用。

探测结果

不管是那种每次探测都将获得以下三种结果之一:

  • Success(成功)容器通过了诊断。
  • Failure(失败)容器未通过诊断。
  • Unknown(未知)诊断失败,因此不会采取任何行动。

测试

  1. 编辑 yaml 文件my-liveness.yaml
apiVersion: v1
kind: Pod
metadata:labels:test: livenessname: liveness-exec
spec:containers:- name: livenessimage: busyboxargs:- /bin/sh- -c- touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600livenessProbe:exec:	# exec方式检测command:- cat- /tmp/healthyinitialDelaySeconds: 5	# 容器启动成功后5s,开始执行探针检测periodSeconds: 5			# 每隔5s检测一次

从 yaml 文件中可以看出:首先创建目录/tmp/healthy,每隔5秒进行探针检测,检测目录是否存在,pod 创建完成后30s,删除目录,这时候探针就检测不到了,重复检测,在600秒后,pod 结束

  1. 启动 pod
[root@k8s-master k8s]# vim my-liveness.yaml
[root@k8s-master k8s]# kubectl apply -f my-liveness.yaml 
pod/liveness-exec configured
  1. 查看 pod 描述信息
kubectl describe pod liveness-exec
......
Events:Type     Reason     Age                  From               Message----     ------     ----                 ----               -------Normal   Scheduled  2m26s                default-scheduler  Successfully assigned default/liveness-exec to k8s-node2Normal   Pulling    61s                  kubelet            Pulling image "busybox"Normal   Pulled     45s                  kubelet            Successfully pulled image "busybox" in 15.275s (15.275s including waiting)Normal   Created    45s                  kubelet            Created container livenessNormal   Started    45s                  kubelet            Started container livenessWarning  Unhealthy  1s (x3 over 11s)     kubelet            Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directoryNormal   Killing    1s                   kubelet            Container liveness failed liveness probe, will be restarted

可以看到,容器在创建30秒后Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory无法打开这个目录了,这时候容器探针检测失败,重新启动

我们这个案例是使用exec机制(在容器内执行指定命令)来检测探针是否成功,官网还有 httpGet 请求和 tcpSocket,自行测试即可

节点亲和性

问题:每次pod调度都是随机事件,不知道pod会被调度到哪一个节点

Scheduler 是 k8s 的调度器,主要的任务是把定义的 pod 分配到集群的节点上。听起来非常简单,但有很多要考虑的问题:

  • 公平:如何保证每个节点都能被分配资源
  • 资源高效利用:集群所有资源最大化被使用
  • 效率:调度的性能要好,能够尽快地对大批量的 pod 完成调度工作
  • 灵活:允许用户根据自己的需求控制调度的逻辑

Scheduler 是作为单独的程序运行的,启动之后会一直监听 API Server ,获取 Pod.Spec.NodeName 为空的 pod,对每个 pod 都会创建一个 binding,表明该 pod 应该放到哪个节点上。

调度的几个部分

  • 首先是过滤掉不满足条件的节点,这个过程称为 predicate(预选);
  • 然后对通过的节点按照优先级排序,这个是 priority(优选);
  • 最后从中选择优先级最高的节点。

如果中间任何一步骤有错误,就直接返回错误(先预选,后优选)

Predicate(预选)有一系列的算法可以使用:

  • PodFitsResources:节点上剩余的资源是否大于 pod 请求的资源
  • PodFitsHost:如果 pod 指定了 NodeName,检查节点名称是否和 NodeName 匹配
  • PodFitsHostPorts:节点上已经使用的 port 是否和 pod 申请的 port 冲突
  • PodSelectorMatches:过滤掉和 pod 指定的 label 不匹配的节点
  • NoDiskConflict:已经 mount 的 volume 和 pod 指定的 volume 不冲突,除非它们都是只读

如果在 predicate 过程中没有合适的节点,pod 会一直在 pending 状态(pending:等待),不断重试调度,直到有节点满足条件。经过这个步骤,如果有多个节点满足条件,就继续 priorities 过程:按照优先级大小对节点排序。

优先级由一系列键值对组成,键是该优先级项的名称,值是它的权重(该项的重要性)。这些优先级选项包括:

  • LeastRequestedPriority:通过计算 CPU 和 Memory 的使用率来决定权重,使用率越低权重越高。换句话说,这个优先级指标倾向于资源使用比例更低的节点

  • BalancedResourceAllocation:节点上 CPU 和 Memory 使用率越接近,权重越高。这个应该和上面的一起使用,不应该单独使用

  • ImageLocalityPriority:倾向于已经有要使用镜像的节点,镜像总大小值越大,权重越高

通过算法对所有的优先级项目和权重进行计算,得出最终的结果

pod 与 node 的亲和性

pod.spec.nodeAffinity

  • preferredDuringSchedulingIgnoredDuringExecution(优先执行计划):软策略

  • requiredDuringSchedulingIgnoredDuringExecution(要求执行计划):硬策略
    (preferred:首选,较喜欢 required:需要,必须)

键值运算关系

  • In:label 的值在某个列表中
  • NotIn:label 的值不在某个列表中
  • Gt:label 的值大于某个值
  • Lt:label 的值小于某个值
  • Exists:某个 label 存在
  • DoesNotExist:某个 label 不存在

在这里插入图片描述

在这里插入图片描述

#软硬策略(先满足硬策略再满足软策略)
apiVersion: v1
kind: Pod
metadata:name: affinity2labels:app: node-affinity-pod
spec:containers:- name: with-node-affinityimage: nginxaffinity:# 可以编写多个亲和性策略nodeAffinity:        #node亲和性# 硬亲和性限制requiredDuringSchedulingIgnoredDuringExecution:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostname # 标签键名operator: NotIn      #键值运算关系 ,NotIn:label的值不在某个列表中。 表示不是node02节点就可运行values:- k8s-node02 # 标签键值preferredDuringSchedulingIgnoredDuringExecution:- weight: 1   #权重,权重越大越亲和(多个软策略的情况)preference: matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- k8s-node03  # 期望是node03

pod 与 pod 的亲和性

pod.spec.affinity.podAffinity 亲和性 podAntiAffinity 反亲和性

  • preferredDuringSchedulingIgnoredDuringExecution:软策略
  • requiredDuringSchedulingIgnoredDuringExecution:硬策略

要有选择中的 Pod —— 才可以说是 Pod 间 —— 也就是要有 labelSelector(若没有设置此字段,表示没有选中的 Pod)

topology 就是拓扑的意思,这里指的是一个拓扑域,是指一个范围的概念,比如一个 Node、一个机柜、一个机房或者是一个地区(如杭州、上海)等,实际上对应的还是 Node 上的标签。

topologyKey 可以理解为 Node 的 label,比如默认所有节点都会有 kubernetes.io/hostname 这 label,相应的值为节点名称,如 master01 节点的 label 为 kubernetes.io/hostname=master01,这种情况每个节点对应的值都不同。

pod亲和性调度需要各个相关的 pod 对象运行于"同一位置", 而反亲和性调度则要求他们不能运行于"同一位置",这里指定“同一位置” 是通过 topologyKey 来定义的。

在这里插入图片描述

在我这个集群中,找到我期望的pod启动节点:pod亲和性策略:标签: app=node-affinity-pod

反亲和性 podAntiAffinity

在这里插入图片描述

Taint 和 Toleration(污点和容忍)

所谓污点就是故意给某个节点服务器上设置个污点参数,那么你就能让生成 pod 的时候使用相应的参数去避开有污点参数的 node 服务器。而容忍呢,就是当资源不够用的时候,即使这个 node 服务器上有污点,那么只要 pod 的 yaml 配置文件中写了容忍参数,最终 pod 还是会容忍的生成在该污点服务器上。默认 master 节点是 NoSchedule(不会调度任何新的 Pod)。

污点(Taint)是应用在节点机器 node 上之上的,从这个名字就可以看出来,是为了排斥 pod 所存在的。

容忍度(Toleration)是应用于 Pod 上的,允许(但并不要求)Pod 调度到带有与之匹配的污点的节点上。

Taint(污点)和 Toleration(容忍)可以作用于 node 和 pod 上,其目的是优化 pod 在集群间的调度,这跟节点亲和性类似,只不过它们作用的方式相反,具有 taint 的 node 和 pod 是互斥关系,而具有节点亲和性关系的 node 和 pod 是相吸的。另外还有可以给 node 节点设置 label,通过给 pod 设置 nodeSelector 将 pod 调度到具有匹配标签的节点上。

Taint 和 toleration 相互配合,可以用来避免 pod 被分配到不合适的节点上。每个节点上都可以应用一个或多个 taint ,这表示对于那些不能容忍这些 taint 的 pod,是不会被该节点接受的。如果将 toleration 应用于 pod 上,则表示这些 pod 可以(但不要求)被调度到具有相应 taint 的节点上。

基本操作

查看某个节点的 Taint 信息

kubectl describe node nodename
[root@k8s-master01 ~]# kubectl describe node k8s-node01 
......
Taints:             <none>   # 关注这个地方即可 ---没有设置过污点的节点属性中的参数是这样的Taints:     <none>
......

为 node 设置 taint

使用 kubectl taint 命令可以给某个 Node 节点设置污点,Node 被设置上污点之后就和 Pod 之间存在了一种相斥的关系,可以让 Node 拒绝 Pod 的调度执行,甚至将 Node 已经存在的 Pod 驱逐出去。

每个污点有一个 key 和 value 作为污点的标签,其中 value 可以为空,effect 描述污点的作用。当前 taint effect 支持如下三个选项:

# NoSchedule:表示k8s将不会将Pod调度到具有该污点的Node上# PreferNoSchedule:表示k8s将尽量避免将Pod调度到具有该污点的Node上# NoExecute:表示k8s将不会将Pod调度到具有该污点的Node上,同时会将Node上已经存在的Pod驱逐出去,赶到其它节点上

这也是为什么生成的pod不会分配到master的原因(因为天生就打了这个污点NoSchedule)

接下来我们给节点node1增加一个污点,它的键名是key1,键值是value1,效果是NoSchedule。 这表示只有拥有和这个污点相匹配的容忍度的 Pod 才能够被分配到node1这个节点。

为 node1 设置 taint:

kubectl taint nodes k8s-node1 key1=value1:NoSchedule

删除上面的 taint:

# 去除污点,最后一个"-"代表删除
kubectl taint nodes k8s-node1 key1:NoSchedule-

为 pod 设置 toleration

只要在 pod 的 spec 中设置 tolerations 字段即可,可以存在多个 key,如下所示:

tolerations:
- key: "key1"operator: "Equal"value: "value1"effect: "NoSchedule"
- key: "key1"operator: "Equal"value: "value1"effect: "NoExecute"
- key: "node.alpha.kubernetes.io/unreachable"operator: "Exists"effect: "NoExecute"tolerationSeconds: 6000
  • value 的值可以为 NoSchedulePreferNoScheduleNoExecute
  • tolerationSeconds 是当 pod 需要被驱逐时,可以继续在 node 上运行的时间。

多个污点匹配原则

可以给一个节点添加多个污点,也可以给一个 Pod 添加多个容忍度设置。

k8s 处理多个污点和容忍度的过程就像一个过滤器:从一个节点的所有污点开始遍历, 过滤掉那些 Pod 中存在与之相匹配的容忍度的污点。余下未被过滤的污点的 effect 值决定了 Pod 是否会被分配到该节点。

例如,假设您给一个节点添加了如下污点:

kubectl taint nodes node1 key1=value1:NoSchedule
kubectl taint nodes node1 key1=value1:NoExecute
kubectl taint nodes node1 key2=value2:NoSchedule

假定有一个 Pod,它有两个容忍度:

tolerations:
- key: "key1"operator: "Equal"value: "value1"effect: "NoSchedule"
- key: "key1"operator: "Equal"value: "value1"effect: "NoExecute"

上述 Pod 不会被分配到 node1 节点,因为其没有容忍度和第三个污点相匹配。

但是如果在给节点添加上述污点之前,该 Pod 已经在上述节点运行, 那么它还可以继续运行在该节点上,因为第三个污点是三个污点中唯一不能被这个 Pod 容忍的。

总结:

通过污点和容忍度,可以灵活地让 Pod 避开某些节点或者将 Pod 从某些节点驱逐。

如果您想将某些节点专门分配给特定的一组用户使用,您可以给这些节点添加一个污点(即, kubectl taint nodes nodename dedicated=groupName:NoSchedule), 然后给这组用户的 Pod 添加一个相对应的 toleration。

拥有上述容忍度的 Pod 就能够被分配到上述专用节点,同时也能够被分配到集群中的其它节点。

在部分节点配备了特殊硬件(比如 GPU)的集群中, 我们希望不需要这类硬件的 Pod 不要被分配到这些特殊节点,以便为后继需要这类硬件的 Pod 保留资源。

要达到这个目的,可以先给配备了特殊硬件的节点添加 taint (例如 kubectl taint nodes nodename special=true:NoSchedulekubectl taint nodes nodename special=true:PreferNoSchedule), 然后给使用了这类特殊硬件的 Pod 添加一个相匹配的 toleration。

指定调度节点

亲和性和污点,容忍都比较含蓄。

指定调度节点是绝对指定目标,我就要这个 node

Pod.spec.nodeName 将 Pod 直接调度到指定的 Node 节点上,会跳过 Scheduler 的调度策略,该匹配规则是强制匹配

apiVersion: extensions/v1beta1
kind: Deployment
metadata:name: myweb
spec:replicas: 7template:metadata:labels:app: nginxspec:nodeName: k8s-node01 #指定全在node01containers:- name: mywebimage: nginxports:- containerPort: 80

Pod.spec.nodeSelector:通过 k8s 的 label-selector 机制选择节点,由调度器调度策略匹配 label,而后调度 Pod 到目标节点,该匹配规则属于强制约束

首先在 master 节点给需要调度的目标 node 打上 label,并在创建 pod 的 yaml 文件中指定 label 来使得 pod 创建的时候调度到指定标签的 node 节点。

# 首先给指定的 node 节点加上标签
kubectl label nodes  kube-node01 disk=ssd
kubectl get nodes kube-node01 --show-labels |grep disk# 编写 yaml 文件引入标签
[root@kube-master scheduler]# vim nodeLabels-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: test-busybox
spec:replicas: 1selector:matchLabels:app: busyboxtemplate:metadata:labels:app: busyboxspec:containers:- name: busyboximage: busyboximagePullPolicy: IfNotPresentnodeSelector:                  # 定义 nodeSelector 参数disk: ssd                    # 引入标签

指定在某台节点启动的命令: nodename 、nodeSelector(需要再node上指定labels)

Pod 相关配置完整图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/775787.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[DS]Polar靶场web(一)

静以养心&#xff0c;宽以养气。 跟着Dream ZHO大神学专升安的一天 swp 直接dirb扫出.index.php.swp的目录 function jiuzhe($xdmtql){return preg_match(/sys.*nb/is,$xdmtql);//如果包含以 "sys" 开始&#xff0c;后跟任意字符直到 "nb" 的字符串&…

JavaScript中的继承方式详解

Question JavaScript实现继承的方式&#xff1f; 包含原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承、寄生组合式继承和ES6 类继承 JavaScript实现继承的方式 在JavaScript中&#xff0c;实现继承的方式多种多样&#xff0c;每种方式都有其优势和适用场景。以下…

macOS Sonoma 14.4.1 (23E224) 正式版 Boot ISO 原版可引导镜像下载

macOS Sonoma 14.4.1 (23E224) 正式版 Boot ISO 原版可引导镜像下载 2024 年 3 月 26 日凌晨&#xff0c;macOS Sonoma 14.4.1 更新修复了一个可能导致连接到外部显示器的 USB 集线器无法被识别的问题。它还解决了可能导致 Java 应用程序意外退出的问题&#xff0c;并修复了可…

Spring 事务传播行为

实现原理 : Aop (TransactionInterceptor) 实现 使用spring声明式事务注意事项 同一个bean中的方法调用必须重新声明一个bean调用、否则后续方法调用的事务默认使用第一个第二个不生效 package com.cloud.person.service.impl;import com.cloud.person.dao.S1Mapper; import…

STM32常用的开发工具有哪些

大家好&#xff0c;今天给大家介绍STM32常用的开发工具有哪些&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 STM32常用的开发工具主要包括以下几类&#xff1a; 集成开发环境&…

java数据结构与算法刷题-----LeetCode744. 寻找比目标字母大的最小字母

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 二分查找 二分查找 解题思路&#xff1a;时间复杂度O( l o g 2 …

说说webpack proxy工作原理?为什么能解决跨域?

文章目录 一、是什么二、工作原理三、跨域参考文献 一、是什么 webpack proxy&#xff0c;即webpack提供的代理服务 基本行为就是接收客户端发送的请求后转发给其他服务器 其目的是为了便于开发者在开发模式下解决跨域问题&#xff08;浏览器安全策略限制&#xff09; 想要…

电路仿真软件大比拼:哪款更适合你?

以下是关于市面上常见的四款电路仿真软件的整体介绍&#xff1a; 1. Multisim&#xff08;美国&#xff0c;美国国家仪器&#xff08;NI&#xff09;有限公司&#xff09; 特点与优势&#xff1a; 直观的图形界面&#xff1a;提供用户友好的界面&#xff0c;便于快速搭建和修…

Openstack创建和操作实例,实现与外部网络通信

一、熟悉OpenStack图形界面操作 1、了解Horizon项目 Horizon项目 各OpenStack服务的图形界面都是由Horizon提供的。Horizon提供基于Web的模块化用户界面。Horizon为云管理员提供一个整体的视图。Horizon为终端用户提供一个自主服务的门户。Horizon由云管理员进行管理与控制&a…

语音陪玩交友软件系统程序-app小程序H5三端源码交付,支持二开!

电竞行业的发展带动其周边产业的发展&#xff0c;绘制着游戏人物图画的抱枕、鼠标垫、海报销量极大&#xff0c;电竞游戏直播、游戏教程短视频也备受人们喜爱&#xff0c;自然&#xff0c;像游戏陪练、代练行业也随之生长起来&#xff0c;本文就来讲讲&#xff0c;从软件开发角…

【字节二面】SpringBoot可以同时处理多少请求

目录 一、示例代码二、那么springboot可以处理多少请求&#xff1f;三、maxConnections、maxThreads、acceptCount的关系 一、示例代码 RestController Slf4j public class RequestController {GetMapping("/test")public String test(HttpServletRequest request) …

腾讯放大招了!AniPortrait开源上线!音频驱动逼真人像动画合成!人人都是歌手!

文章链接&#xff1a;https://arxiv.org/pdf/2403.17694 github链接&#xff1a;https://github.com/Zejun-Yang/AniPortrait 本文提出了AniPortrait&#xff0c;一个新颖的框架&#xff0c;用于生成由音频和参考肖像驱动的高质量动画。方法分为两个阶段。首先&#xff0c;从音…

linux i2c-tools使用总结

1,安装iic-tools sudo apt install i2c-tools -y 2,查看有几条iic总线 [root@sino-platform:/root]# ls /dev/i2c- i2c-0 i2c-1 i2c-2 i2c-3 3,查看i2c命令 [root@sino-platform:/root]# i2c i2cdetect i2cdump i2cget i2cset 4,iic-help命令 [root@sino-platform…

【vue3学习笔记(二)】(第141-143节)初识setup;ref函数_处理基本类型;ref函数_处理对象类型

尚硅谷Vue2.0Vue3.0全套教程丨vuejs从入门到精通 本篇内容对应课程第141-143节 课程 P141节 《初识setup》笔记 1、setup是所有组合式API“表演的舞台”&#xff0c;组件中所用到的所有数据、方法、监视数据、生命周期钩子等都需要配置在setup中。 2、setup的两种返回值&…

Go语言介绍以及如何在Go语言中操作MySQL数据库

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

「Nginx」Nginx配置详解

「Nginx」Nginx配置详解 参考文章1、正向代理和方向代理2、指定域名允许跨域 参考文章 1、Nginx反向代理 2、nginx配置详解 3、Nginx服务器之负载均衡策略&#xff08;6种&#xff09; 1、正向代理和方向代理 2、指定域名允许跨域 map $http_origin $allow_cors {default 1;…

uniApp使用XR-Frame创建3D场景(6)播放模型动画

上篇文章讲述了如何将XR-Frame作为子组件集成到uniApp中使用 这篇我们讲解播放模型动画 先看源码 <xr-scene render-system"alpha:true" bind:ready"handleReady"> <xr-node visible"{{sec6}}"><xr-light type"ambient&qu…

【Qt学习】了解Qt文件系统 + 利用QFile类实现记事本功能

文章目录 1. 前言 - 关于Qt文件1.1 QIODevice 介绍1.2 QFile 介绍1.2 打开文件的方式 2. 实例 - 记事本功能2.1 功能实现2.2 getOpenFileName() 与 getSaveFileName() 的区别2.3 效果演示 3. 资源文件 1. 前言 - 关于Qt文件 文件操作 是应⽤程序必不可少的部分&#xff0c;Qt作…

android 消息提醒

1.创建 MyBackgroundService.java 继承 Service public class MyBackgroundService extends Service {Overridepublic void onCreate() {super.onCreate();Log.i("业务服务", "开起业务服务");//调用服务后在页面手机上创建一个通知消息。if (android.os…

日本EPSON 爱普生HUD汽车抬头显示系统芯片

目前HUD产品在新车上的配装率逐年上升&#xff0c;预计在2025年将达到30%。那么在介绍爱普生HUD整合方案之前&#xff0c;让我们先了解一下什么叫HUD。 HUD&#xff08;Head Up Display&#xff09;中文叫抬头显示系统&#xff0c;又被叫做平行显示系统。早被应用在飞机辅助…