一、Pod资源清单详细解读

apiVersion: v1 #版本号,例如 v1
kind: Pod #资源类型,如 Pod
metadata: #元数据
name: string # Pod 名字
namespace: string # Pod 所属的命名空间
labels: #自定义标签
name: string #自定义标签名字
annotations: #自定义注释列表
name: string
spec: # Pod 中容器的详细定义
containers: # Pod 中容器列表
name: string #容器名称
image: string #容器的镜像名称
imagePullPolicy: [Always | Never | IfNotPresent] #获取镜像的策略 Alawys 表示下载镜像 IfnotPresent 表示优先使用本地镜像,否则下载镜像,Nerver 表示仅使用本地镜像
command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令
args: [string] #容器的启动命令参数列表
workingDir: string #容器的工作目录
volumeMounts: #挂载到容器内部的存储卷配置
name: string #引用 pod 定义的共享存储卷的名称,需用 volumes[]部分定义的的卷名
mountPath: string #存储卷在容器内 mount 的绝对路径,应少于 512 字符
readOnly: boolean #是否为只读模式
ports: #需要暴露的端口库号
- name: string #端口号名称
containerPort: int #容器需要监听的端口号
hostPort: int #容器所在主机需要监听的端口号,默认与 Container 相同
protocol: string #端口协议,支持 TCP 和 UDP,默认 TCP
env: #容器运行前需设置的环境变量列表
- name: string #环境变量名称
value: string #环境变量的值
resources: #资源限制和请求的设置
limits: #资源限制的设置
cpu: string #cpu 的限制,单位为 core 数
memory: string #内存限制,单位可以为 Mib/Gib
requests: #资源请求的设置
cpu: string #cpu 请求,容器启动的初始可用数量
memory: string #内存请求,容器启动的初始可用内存
livenessProbe: #对 Pod 内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有 exec、httpGet 和tcpSocket,对一个容器只需设置其中一种方法即可
exec: #对 Pod 容器内检查方式设置为 exec 方式
command: [string] #exec 方式需要制定的命令或脚本
httpGet: #对 Pod 内个容器健康检查方法设置为 HttpGet,需要制定 Path、port
path: string
port: number
host: string
scheme: string
HttpHeaders:
- name: string
value: string
tcpSocket: #对 Pod 内个容器健康检查方式设置为 tcpSocket 方式
port: number
initialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒
timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认 1 秒
periodSeconds: 0 #对容器监控检查的定期探测时间设置,单位秒,默认 10 秒一次
successThreshold: 0
failureThreshold: 0
securityContext:
privileged:false
restartPolicy: [Always | Never | OnFailure]#Pod 的重启策略,Always 表示一旦不管以何种方式终止运行,kubelet 都将重启,OnFailure 表示只有 Pod 以非 0 退出码退出才重启,Nerver 表示不再重启该 Pod
nodeSelector: obeject #设置 NodeSelector 表示将该 Pod 调度到包含这个 label 的 node上,以 key:value 的格式指定
imagePullSecrets: #Pull 镜像时使用的 secret 名称,以 key:secretkey 格式指定
- name: string
hostNetwork:false #是否使用主机网络模式,默认为 false,如果设置为 true,表示使用宿主机网络
volumes: #在该 pod 上定义共享存储卷列表
- name: string #共享存储卷名称 (volumes 类型有很多种)
emptyDir: {} #类型为 emtyDir 的存储卷,与 Pod 同生命周期的一个临时目录。为空值
hostPath: string #类型为 hostPath 的存储卷,表示挂载 Pod 所在宿主机的目录
path: string #Pod 所在宿主机的目录,将被用于同期中 mount 的目录
secret: #类型为 secret 的存储卷,挂载集群与定义的 secre 对象到容器内部
scretname: string
items:
- key: string
path: string
configMap: #类型为 configMap 的存储卷,挂载预定义的 configMap 对象到容器内部
name: string
items:
- key: string
path: string

二、node节点选择器

    我们在创建 pod 资源的时候,pod 会根据 schduler 进行调度,那么默认会调度到随机的一个工作节点,如果我们想要 pod 调度到指定节点或者调度到一些具有相同特点的 node 节点,怎么办呢?
可以使用 pod 中的 nodeName 或者 nodeSelector 字段指定要调度到的 node 节点 .

2.1 nodeName: 指定pod节点运行在哪个具体node上

[root@master node]# cat pod-node.yaml
apiVersion: v1
kind: Pod
metadata:
name: demo-pod
namespace: default
labels:
app: myapp
env: dev
spec:
nodeName: monitor
containers:
- name: tomcat-pod-java
ports:
- containerPort: 8080
image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent
- name: busybox
image: busybox:latest
command:
- "/bin/sh"
- "-c"
- "sleep 3600" [root@master node]# kubectl apply -f pod-node.yaml
# 如果demo-pod已经存在可以删除或者改变metadata.name名称
[root@master node]# kubectl delete pods -n default demo-pod
pod "demo-pod" deleted # 查看创建的容器
[root@master node]# kubectl get pods -n default
NAME READY STATUS RESTARTS AGE
demo-pod 2/2 Running 0 14s # 可以看到demo-pod所在的node为monitor
[root@master node]# kubectl get pods -n default -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-pod 2/2 Running 0 2m9s 10.244.75.202 monitor <none> <none>

2.2 nodeSelector

指定pod调度到具有哪些标签的node节点上

# 给 node3 节点打标签,打个具有 disk=ceph 的标签
# 查看node3节点详细信息
[root@master node]# kubectl describe nodes node3 # 给node3打上disk=ceph标签
[root@master node]# kubectl label nodes node3 disk=ceph
node/node3 labeled #定义 pod 的时候指定要调度到具有 disk=ceph 标签的node上
[root@master node]# cat pod-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: demo-pod-1
namespace: default
labels:
app: myapp
env: dev
spec:
nodeSelector:
disk: ceph # 如果monitor和node3节点都有disk=ceph,k8s会根据服务器情况在其中一台服务器上生成
containers:
- name: tomcat-pod-java
ports:
- containerPort: 8080
image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent [root@master node]# kubectl get pods -n default -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-pod-1 1/1 Running 0 18s 10.244.135.10 node3 <none> <none>

三、Pod节点选择器

[root@master node]# kubectl explain pods.spec.affinity
KIND: Pod
VERSION: v1 RESOURCE: affinity <Object> DESCRIPTION:
If specified, the pod's scheduling constraints Affinity is a group of affinity scheduling rules. FIELDS:
nodeAffinity <Object>
Describes node affinity scheduling rules for the pod. podAffinity <Object>
Describes pod affinity scheduling rules (e.g. co-locate this pod in the
same node, zone, etc. as some other pod(s)). podAntiAffinity <Object>
Describes pod anti-affinity scheduling rules (e.g. avoid putting this pod
in the same node, zone, etc. as some other pod(s)).

3.1 Pod亲和性--node节点亲和性(pod选择机器)

[root@master node]# kubectl explain pods.spec
[root@master node]# kubectl explain pods.spec.affinity
[root@master node]# kubectl explain pods.spec.affinity.
[root@master node]# kubectl explain pods.spec.affinity.nodeAffinity
KIND: Pod
VERSION: v1
RESOURCE: nodeAffinity <Object>
DESCRIPTION:
Describes node affinity scheduling rules for the pod.
Node affinity is a group of node affinity scheduling rules. FIELDS:
preferredDuringSchedulingIgnoredDuringExecution <[]Object>
requiredDuringSchedulingIgnoredDuringExecution <Object> prefered 表示有节点尽量满足这个位置定义的亲和性,这不是一个必须的条件,软亲和性
require 表示必须有节点满足这个位置定义的亲和性,这是个硬性条件,硬亲和性
[root@master node]# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution
FIELDS:
nodeSelectorTerms <[]Object> -required- [root@master node]# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms
FIELDS:
matchExpressions <[]Object>
matchFields <[]Object> matchExpressions:匹配表达式的
matchFields: 匹配字段的 [root@master node]# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions
FIELDS:
key <string> -required-
operator <string> -required-
values <[]string> key:检查 label
operator:做等值选则还是不等值选则
values:给定值

硬亲和性测试:
apiVersion: v1
kind: Pod
metadata:
name: pod-node-affinity-demo
namespace: default
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: zone
operator: In
values:
- foo
- bar # 我们检查当前节点中有任意一个节点拥有 zone 标签的值是 foo 或者 bar,就可以把 pod 调度到这个 node 节点的 foo 或者 bar 标签上的节点上

master上查看结果:kubectl -f pod-nodeaffinity-demo.yaml
[root@master node]# kubectl get pods -o wide -n default
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-pod 2/2 Running 32 3d11h 10.244.75.202 monitor <none> <none>
demo-pod-1 1/1 Running 0 3d10h 10.244.135.10 node3 <none> <none>
nginx-7f466444dc-ndp5t 1/1 Running 0 4d 10.244.75.198 monitor <none> <none>
nginx-7f466444dc-qbxfn 1/1 Running 0 4d 10.244.135.3 node3 <none> <none>
nginx-test-75c685fdb7-92w5b 1/1 Running 0 3d20h 10.244.135.6 node3 <none> <none>
nginx-test-75c685fdb7-9mkzf 1/1 Running 0 3d20h 10.244.75.199 monitor <none> <none>
pod-node-affinity-demo 0/1 Pending 0 77s <none> <none> <none> <none>
pod-run 0/1 ImagePullBackOff 0 3d18h 10.244.135.8 node3 <none> <none>
pod-test 1/1 Running 0 3d18h 10.244.75.200 monitor <none> <none>
tomcat-test 1/1 Running 0 3d18h 10.244.135.7 node3 <none> <none>
# status 的状态是 pending,上面说明没有完成调度,因为没有一个拥有 zone 的标签的值是 foo 或 者 bar,而且使用的是硬亲和性,必须满足条件才能完成调度,没有分配节点与IP
# 给一个节点打上标签foo,然后查看
[root@master node]# kubectl label nodes node3 zone=foo
node/node3 labeled
[root@master node]# kubectl get pods -o wide -n default
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-pod 2/2 Running 32 3d11h 10.244.75.202 monitor <none> <none>
demo-pod-1 1/1 Running 0 3d10h 10.244.135.10 node3 <none> <none>
nginx-7f466444dc-ndp5t 1/1 Running 0 4d 10.244.75.198 monitor <none> <none>
nginx-7f466444dc-qbxfn 1/1 Running 0 4d 10.244.135.3 node3 <none> <none>
nginx-test-75c685fdb7-92w5b 1/1 Running 0 3d20h 10.244.135.6 node3 <none> <none>
nginx-test-75c685fdb7-9mkzf 1/1 Running 0 3d20h 10.244.75.199 monitor <none> <none>
pod-node-affinity-demo 1/1 Running 0 6m35s 10.244.135.11 node3 <none> <none>
pod-run 0/1 ImagePullBackOff 0 3d18h 10.244.135.8 node3 <none> <none>
pod-test 1/1 Running 0 3d18h 10.244.75.200 monitor <none> <none>
tomcat-test 1/1 Running 0 3d18h 10.244.135.7 node3 <none> <none>

软亲和性测试:

apiVersion: v1
kind: Pod
metadata:
name: pod-node-affinity-demo-2
namespace: default
labels:
app: myapp
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- preference:
matchExpressions:
- key: zone1
operator: In
values:
- foo1
- bar1
weight: 60 [root@master node]# kubectl apply -f pod-nodeaffinity-demo-2.yaml
pod/pod-node-affinity-demo-2 created
[root@master node]# kubectl get pods -o wide -n default
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-pod 2/2 Running 32 3d11h 10.244.75.202 monitor <none> <none>
demo-pod-1 1/1 Running 0 3d10h 10.244.135.10 node3 <none> <none>
nginx-7f466444dc-ndp5t 1/1 Running 0 4d 10.244.75.198 monitor <none> <none>
nginx-7f466444dc-qbxfn 1/1 Running 0 4d 10.244.135.3 node3 <none> <none>
nginx-test-75c685fdb7-92w5b 1/1 Running 0 3d20h 10.244.135.6 node3 <none> <none>
nginx-test-75c685fdb7-9mkzf 1/1 Running 0 3d20h 10.244.75.199 monitor <none> <none>
pod-node-affinity-demo 1/1 Running 0 11m 10.244.135.11 node3 <none> <none>
pod-node-affinity-demo-2 1/1 Running 0 8s 10.244.135.12 node3 <none> <none>
pod-run 0/1 ImagePullBackOff 0 3d18h 10.244.135.8 node3 <none> <none>
pod-test 1/1 Running 0 3d18h 10.244.75.200 monitor <none> <none>
tomcat-test 1/1 Running 0 3d18h 10.244.135.7 node3 <none> <none>

# 上面说明软亲和性是可以运行这个 pod 的,尽管没有运行这个 pod 的节点定义的 zone1 标签

# Node 节点亲和性针对的是 pod 和 node 的关系,Pod 调度到 node 节点的时候匹配的条件


3.2 Pod节点亲和性

pod 自身的亲和性调度有两种表示形式
podaffinity:pod 和 pod 更倾向腻在一起,把相近的 pod 结合到相近的位置,例如功能相似,如有调用关系,如同一区域,同一机架,这样的话 pod 和 pod 之间更好通信,比方说有两个机房,这两个机房部署的集群有 1000 台
主机,那么我们希望把 nginx 和 tomcat 都部署同一个地方的 node 节点上,可以提高通信效率; podunaffinity 反亲和性:pod 和 pod 更倾向不腻在一起,如果部署两套程序,没多大关系,那么这两套程序更倾向于反亲和性,这样相互之间不会有影响。 第一个 pod 随机选则一个节点,做为评判后续的 pod 能否到达这个 pod 所在的节点上的运行方式,这就称为 pod 亲和性;
我们怎么判定哪些节点是相同位置的,哪些节点是不同位置的;
我们在定义 pod 亲和性时需要有一个前提,哪些 pod 在同一个位置,哪些 pod 不在同一个位置,这个位置是怎么定义的,标准是什么?
以节点名称为标准,这个节点名称相同的表示是同一个位置,节点名称不相同的表示不是一个位置。

[root@master node]# kubectl explain pods.spec.affinity.podAffinity
FIELDS:
preferredDuringSchedulingIgnoredDuringExecution <[]Object> 软亲和性
requiredDuringSchedulingIgnoredDuringExecution <[]Object> 硬亲和性 [root@master node]# kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution
FIELDS:
labelSelector <Object>
namespaces <[]string>
topologyKey <string> -required-
topologyKey:位置拓扑的键,这个是必须字段

怎么判断是不是同一个位置:
rack=rack1
row=row1
使用 rack 的键是同一个位置
使用 row 的键是同一个位置 labelSelector:
我们要判断 pod 跟别的 pod 亲和,跟哪个 pod 亲和,需要靠 labelSelector,通过 labelSelector选则一组能作为亲和对象的 pod 资源

namespace:
labelSelector 需要选则一组资源,那么这组资源是在哪个名称空间中呢,通过 namespace 指定,如果不指定 namespaces,那么就是当前创建 pod 的名称空间
[root@master node]# kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.labelSelector
FIELDS:
matchExpressions <[]Object>
matchLabels <map[string]string>

# 查看所有k8s的node节点标签
[root@master node]# kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
master Ready control-plane,master 13d v1.20.7 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=master,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node-role.kubernetes.io/master=
monitor Ready <none> 13d v1.20.7 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=monitor,kubernetes.io/os=linux
node3 Ready <none> 13d v1.20.7 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disk=ceph,kubernetes.io/arch=amd64,kubernetes.io/hostname=node3,kubernetes.io/os=linux,zone=foo

# 查看单个节点标签

[root@master node]# kubectl get nodes node3 --show-labels
   NAME STATUS ROLES AGE VERSION LABELS
   node3 Ready <none> 13d v1.20.7 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disk=ceph,kubernetes.io/arch=amd64,kubernetes.io/hostname=node3,kubernetes.io/os=linux,zone=foo

# 查看某个标签下有多少节点

[root@master node]# kubectl get pods -l app1=myapp1
NAME READY STATUS RESTARTS AGE
pod-first 1/1 Running 0 11m


# 定义2个pod,第一个 pod 做为基准,第二个 pod 跟着它走
[root@master node]# cat pod-required-affinity-demo-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
app2: myapp
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
---
apiVersion: v1
kind: Pod
metadata:
name: pod-second
labels:
app: backend
tier: db
spec:
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 3600"]
affinity:
podAffinity: # 亲和性
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- {key: app, operator: In, values: ["myapp"]}
topologyKey: kubernetes.io/hostname # 基于主机名做为位置,pod-first调度到哪个点,pod-second也跟着调度到哪个点 # 上面表示创建的 pod 必须与拥有 app=myapp 标签的 pod 在一个节点上
# --- 表示链接第二个pod,2个yaml互不影响,但相关的写在一起可以更清晰

[root@master node]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES

pod-first 1/1 Running 0 105s 10.244.75.204 monitor <none> <none>
pod-second 1/1 Running 0 105s 10.244.75.203 monitor <none> <none>

3.3 Pod反亲和性

# 先删除上面亲和性的2个pod
[root@master node]# kubectl delete -f pod-required-affinity-demo-1.yaml
pod "pod-first" deleted
pod "pod-second" deleted # 软亲和性:尽可能不在一起
[root@master node]# kubectl explain pods.spec.affinity.podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution
FIELDS:
podAffinityTerm <Object> -required-
weight <integer> -required-
# 定义两个 pod,第一个 pod 做为基准,第二个 pod 跟它调度节点相反 
[root@master node]# cat pod-required-anti-affinity-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
app1: myapp1
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
---
apiVersion: v1
kind: Pod
metadata:
name: pod-second
labels:
app: backend
tier: db
spec:
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 3600"]
affinity:
podAntiAffinity: # 反亲和性
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- {key: app1, operator: In, values: ["myapp1"]}
topologyKey: kubernetes.io/hostname

[root@master node]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES

pod-first 1/1 Running 0 10s 10.244.75.205 monitor <none> <none>
pod-second 1/1 Running 0 10s 10.244.135.13 node3 <none> <none>

# 如果有问题,就查看下标签下是否有重复命名 kubectl get pods -l app1=myapp1

位置拓扑键topologykey
# 添加标签,如果已经有标签需要在命令末尾加上--overwrite
[root@master node]# kubectl label nodes monitor zone=foo
node/monitor labeled
[root@master node]# kubectl label nodes node3 zone=foo --overwrite
node/node3 not labeled # 现在2个节点都有zone=foo标签
[root@master node]# cat myapp.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
app3: myapp3
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1 [root@master node]# cat backend.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-second
labels:
app: backend
tier: db
spec:
containers:
- name: busybox
image: busybox:latest
imagePullPolicy: IfNotPresent
command: ["sh","-c","sleep 3600"]
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- {key: app3, operator: In, values: ["myapp3"]}
topologyKey: zone [root@master node]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-first 1/1 Running 0 2m28s 10.244.135.14 node3 <none> <none>
pod-second 0/1 Pending 0 12s <none> <none> <none> <none>

第二个节点现是 pending,因为两个节点是同一个位置,现在没有不是同一个位置的了,而且我们 要求反亲和性,所以就会处于 pending 状态,
如果在反亲和性这个位置把 required 改成 preferred,那么也会运行。

podaffinity:pod 节点亲和性,pod 倾向于哪个 pod

nodeaffinity:node 节点亲和性,pod 倾向于哪个 node

四、污点、容忍度

给了节点选则的主动权,我们给节点打一个污点,不容忍的 pod 就运行不上来,污点就是定义在节点上的键值属性数据,可以定决定拒绝那些 pod;
taints 是键值数据,用在节点上,定义污点;
tolerations 是键值数据,用在 pod 上,定义容忍度,能容忍哪些污点

pod 亲和性是 pod 属性;但是污点是节点的属性,污点定义在 nodeSelector 上
# 默认情况只有master节点有污点,工作节点是没有的
[root@master node]# kubectl get nodes master -o yaml | grep taints
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master [root@master node]# kubectl explain nodes.spec.taints
FIELDS:
effect <string> -required-
Required. The effect of the taint on pods that do not tolerate the taint.
Valid effects are NoSchedule, PreferNoSchedule and NoExecute. key <string> -required-
timeAdded <string> NoSchedule:
仅影响 pod 调度过程,当 pod 能容忍这个节点污点,就可以调度到当前节点,后来这个节点的污点改了,加了一个新的污点,使得之前调度的 pod 不能容忍了,那这个 pod 会怎么处理,对现存的 pod 对象不产生影响 NoExecute:
既影响调度过程,又影响现存的 pod 对象,如果现存的 pod 不能容忍节点后来加的污点,这个 pod就会被驱逐 PreferNoSchedule:
最好不,也可以,是 NoSchedule 的柔性版本
在 pod 对象定义容忍度的时候支持两种操作:
1.等值密钥:key 和 value 上完全匹配
2.存在性判断:key 和 effect 必须同时匹配,value 可以是空
在 pod 上定义的容忍度可能不止一个,在节点上定义的污点可能多个,需要琢个检查容忍度和污点能否匹配,每一个污点都能被容忍,才能完成调度,如果不能容忍怎么办,那就需要看 pod 的容忍度了
kubectl taint --help
kubectl taint nodes foo dedicated=special-user:NoSchedule 打上污点
kubectl taint nodes foo dedicated:NoSchedule- 删除污点

示例:

# 打上污点
[root@master node]# kubectl taint node node3 node-type=production:NoSchedule
node/node3 tainted
[root@master taint]# kubectl apply -f pod-taint.yaml
pod/taint-pod created
[root@master taint]# kubectl get pods -o wide -n default
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
taint-pod 1/1 Running 0 3m29s 10.244.75.206 monitor <none> <none> # taint-pod 认为node3节点有污点,不能容忍所以不会在node3上建立 # 将monitor打上污点并设置为NoExecute会发现,monitor上原来存在的pod都变为了Pending状态了
[root@master taint]# kubectl taint node monitor node-type=dev:NoExecute
node/monitor tainted
[root@master taint]# kubectl get pods -o wide -n default
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-7f466444dc-hrx7w 0/1 Pending 0 2m59s <none> <none> <none> <none>
nginx-7f466444dc-qbxfn 1/1 Running 0 4d4h 10.244.135.3 node3 <none> <none>
nginx-test-75c685fdb7-92w5b 1/1 Running 0 4d 10.244.135.6 node3 <none> <none>
nginx-test-75c685fdb7-mlnjg 0/1 Pending 0 2m59s <none> <none> <none> <none>

示例:
apiVersion: v1
kind: Pod
metadata:
name: myapp-deploy
namespace: default
labels:
app: myapp
release: canary
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
ports:
- name: http
containerPort: 80
tolerations:
- key: "node-type"
operator: "Equal" # 相当于符号 =
value: "production"
effect: "NoSchedule"
# effect: "NoExecute" #如果是这个查看的时候会发现Ponding状态
# tolerationSeconds: 3600 # NoExecute可以存在,NoSchedule就不能使用这个 [root@master taint]# kubectl apply -f pod-demo-1.yaml
pod/myapp-deploy created
[root@master taint]# kubectl get pods -n default -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-deploy 1/1 Running 0 5m59s 10.244.135.15 node3 <none> <none>

# 修改容忍度
tolerations:
- key: "node-type"
  operator: "Exists"
  value: ""
effect: ""

[root@master taint]# kubectl get pods -n default -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myapp-deploy 1/1 Running 0 6s 10.244.75.207 monitor <none> <none>

# 删除污点

[root@master taint]# kubectl taint nodes monitor node-type:NoExecute-
node/monitor untainted
[root@master taint]# kubectl taint nodes node3 node-type-
node/node3 untainted

五、Pod常见的状态和重启策略

5.1 常见的pod状态

Pod 的 status 定义在 PodStatus 对象中,其中有一个 phase 字段。它简单描述了 Pod 在其生命周期的阶段。熟悉 Pod 的各种状态对我们理解如何设置 Pod 的调度策略、重启策略是很有必要的。
下面是 phase 可能的值,也就是 pod 常见的状态:
挂起(Pending):我们在请求创建 pod 时,条件不满足,调度没有完成,没有任何一个节点能满足调度条件,已经创建了 pod 但是没有适合它运行的节点叫做挂起,调度没有完成,
处于 pending的状态会持续一段时间:包括调度 Pod 的时间和通过网络下载镜像的时间。
运行中(Running):Pod 已经绑定到了一个节点上,Pod 中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态。
成功(Succeeded):Pod 中的所有容器都被成功终止,并且不会再重启。
失败(Failed):Pod 中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。
未知(Unknown):未知状态,所谓 pod 是什么状态是 apiserver 和运行在 pod 节点的 kubelet 进行通信获取状态信息的,如果节点之上的 kubelet 本身出故障,
那么 apiserver 就连不上kubelet,得不到信息了,就会看 Unknown 扩展:还有其他状态,如下:
Evicted 状态:出现这种情况,多见于系统内存或硬盘资源不足,可 df-h 查看 docker 存储所在目录的资源使用情况,如果百分比大于 85%,就要及时清理下资源,尤其是一些大文件、docker 镜像。
CrashLoopBackOff:容器曾经启动了,但可能又异常退出了
Error 状态:Pod 启动过程中发生了错误

5.2 Pod重启策略

Pod 的重启策略(RestartPolicy)应用于 Pod 内的所有容器,并且仅在 Pod 所处的 Node 上由kubelet 进行判断和重启操作。当某个容器异常退出或者健康检查失败时,kubelet 将根据 RestartPolicy 的设置来进行相应的操作。

Pod 的重启策略包括 Always、OnFailure 和 Never,默认值为 Always。
Always:当容器失败时,由 kubelet 自动重启该容器。
OnFailure:当容器终止运行且退出码不为 0 时,由 kubelet 自动重启该容器。
Never:不论容器运行状态如何,kubelet 都不会重启该容器。
apiVersion: v1
kind: Pod
metadata:
name: demo-pod
namespace: default
labels:
app: myapp
spec:
restartPolicy: Always # 默认一般也是Always
containers:
- name: tomcat-pod-java
ports:
- containerPort: 8080
image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent

六. Pod生命周期

6.1 Init container容器

Pod 里面可以有一个或者多个容器,部署应用的容器可以称为主容器,在创建 Pod 时候,Pod 中可以有一个或多个先于主容器启动的 Init 容器,这个 init 容器就可以成为初始化容器,初始化容
器一旦执行完,它从启动开始到初始化代码执行完就退出了,它不会一直存在,所以在主容器启动之前执行初始化,初始化容器可以有多个,多个初始化容器是要串行执行的,先执行初始化容器
1,在执行初始化容器 2 等,等初始化容器执行完初始化就退出了,然后再执行主容器,主容器一退出,pod 就结束了,主容器退出的时间点就是 pod 的结束点,它俩时间轴是一致的; Init 容器就是做初始化工作的容器。可以有一个或多个,如果多个按照定义的顺序依次执行,只有所有的初始化容器执行完后,主容器才启动。由于一个 Pod 里的存储卷是共享的,所以 Init
Container 里产生的数据可以被主容器使用到,Init Container 可以在多种 K8S 资源里被使用到,如 Deployment、DaemonSet, StatefulSet、Job 等,但都是在 Pod 启动时,
在主容器启动前执行,做初始化工作。 Init 容器与普通的容器区别是:
1、Init 容器不支持 Readiness,因为它们必须在 Pod 就绪之前运行完成
2、每个 Init 容器必须运行成功,下一个才能够运行
3、如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止,然而,如果 Pod 对应的 restartPolicy 值为 Never,它不会重新启动。 初始化容器的官方地址:
https://kubernetes.io/docs/concepts/workloads/pods/init-containers/#init-containersin-use

查看启动容器的信息
kubectl logs myapp-pod # 日志信息
kubectl describe pods myapp-pod

6.2 主容器

6.2.1 容器钩子:

    初始化容器启动之后,开始启动主容器,在主容器启动之前有一个 post start hook(容器启动后钩子)和 pre stop hook(容器结束前钩子),无论启动后还是结束前所做的事我们可以把它放两个钩子,
这个钩子就表示用户可以用它来钩住一些命令,来执行它,做开场前的预设,结束前的清理,如 awk 有 begin,end,和这个效果类似; postStart:该钩子在容器被创建后立刻触发,通知容器它已经被创建。如果该钩子对应的 hook handler 执行失败,则该容器会被杀死,并根据该容器的重启策略决定是否要重启该容器,这个钩子不需要传递任何参数。 preStop:该钩子在容器被删除前触发,其所对应的 hook handler 必须在删除该容器的请求发送给 Docker daemon 之前完成。在该钩子对应的 hook handler 完成后不论执行的结果如何,
Docker daemon 会发送一个 SGTERN 信号量给 Docker daemon 来删除该容器,这个钩子不需要传递任何参数。 在 k8s 中支持两类对 pod 的检测,第一类叫做 livenessprobe(pod 存活性探测): 存活探针主要作用是,用指定的方式检测 pod 中的容器应用是否正常运行,如果检测失败,则认为容器不健康,
那么 Kubelet 将根据 Pod 中设置的 restartPolicy 来判断 Pod 是否要进行重启操作,如果容器配置中没有配置 livenessProbe,Kubelet 将认为存活探针探测一直为成功状态。
第二类是状态检 readinessprobe(pod 就绪性探测):用于判断容器中应用是否启动完成,当探测成功后才使 Pod 对外提供网络访问,设置容器 Ready 状态为 true,如果探测失败,则设置容器的Ready 状态为 false。
NAME                                       READY   STATUS    RESTARTS   AGE
pod-second                                 0/1     Running   0          153m
# Ready 容器中的应用没有启动,Running容器创建成功并启动

6.3 创建pod需要经过哪些阶段?

1.当用户创建 pod 时,这个请求给 apiserver,apiserver 把创建请求的状态保存在 etcd 中;
2.接下来 apiserver 会请求 scheduler 来完成调度,如果调度成功,会把调度的结果(如调度到哪个节点上了,运行在哪个节点上了,把它更新到 etcd 的 pod 资源状态中)保存在 etcd 中,
3.一旦存到 etcd 中并且完成更新以后,如调度到 node1上,那么 node1节点上的kubelet 通过 apiserver 当中的状态变化知道有一些任务被执行了,所以此时此 kubelet 会拿到用户创建时所提交的清单,
这个清单会在当前节点上运行或者启动这个 pod,
4.如果创建成功或者失败会有一个当前状态,当前这个状态会发给 apiserver,apiserver 在存到 etcd 中;
5.在这个过程中,etcd 和 apiserver 一直在打交道,不停的交互,scheduler 也参与其中,负责调度 pod 到合适的 node 节点上,这个就是 pod 的创建过程 pod 在整个生命周期中有非常多的用户行为:
1、初始化容器完成初始化
2、主容器启动后可以做启动后钩子
3、主容器结束前可以做结束前钩子
4、在主容器运行中可以做一些健康检测,如 liveness probe,readness probe

Pod进阶篇:污点-容忍度-亲和性-Affinity-调度(5)的更多相关文章

  1. Kubernetes使用节点污点和pod容忍度阻止节点调度到特定节点

    Kubernetes允许你去影响pod被调度到哪个节点.起初,只能通过在pod规范里指定节点选择器来实现,后面其他的机制逐渐加入来扩容这项功能,本章将包括这些内容. 现在要介绍的高级调度的两个特性是节 ...

  2. k8s核心资源之namespace与pod污点容忍度生命周期进阶篇(四)

    目录 1.命名空间namespace 1.1 什么是命名空间? 1.2 namespace应用场景 1.3 namespacs常用指令 1.4 namespace资源限额 2.标签 2.1 什么是标签 ...

  3. pod(九):污点taint 与容忍度tolerations

    目录 一.系统环境 二.前言 三.污点taint 3.1 污点taint概览 3.2 给节点添加污点taint 四.容忍度tolerations 4.1 容忍度tolerations概览 4.2 设置 ...

  4. 容器编排系统K8s之节点污点和pod容忍度

    前文我们了解了k8s上的kube-scheduler的工作方式,以及pod调度策略的定义:回顾请参考:https://www.cnblogs.com/qiuhom-1874/p/14243312.ht ...

  5. Kubernetes 调度 - 污点和容忍度详解

    当我们使用节点亲和力(Pod 的一个属性)时,它会将Pod吸引到一组节点(作为偏好或硬性要求).污点的行为完全相反,它们允许一个节点排斥一组 Pod. 在 Kubernetes 中,您可以标记(污染) ...

  6. idea 插件的使用 进阶篇

    CSDN 2016博客之星评选结果公布    [系列直播]零基础学习微信小程序!      "我的2016"主题征文活动   博客的神秘功能 idea 插件的使用 进阶篇(个人收集 ...

  7. 进阶篇,第二章:MC与Forge的Event系统

    <基于1.8 Forge的Minecraft mod制作经验分享> 这一章其实才应该是第一章,矿物生成里面用到了Event的一些内容.如果你对之前矿物生成那一章的将算法插入ORE_GEN_ ...

  8. Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十五)阶段总结

    作者:13 GitHub:https://github.com/ZHENFENG13 版权声明:本文为原创文章,未经允许不得转载. 一 每个阶段在结尾时都会有一个阶段总结,在<SSM整合基础篇& ...

  9. C# 30分钟完成百度人脸识别——进阶篇(文末附源码)

    距离上次入门篇时隔两个月才出这进阶篇,小编惭愧,对不住关注我的卡哇伊的小伙伴们,为此小编用这篇博来谢罪. 前面的准备工作我就不说了,注册百度账号api,创建web网站项目,引入动态链接库引入. 不了解 ...

  10. idea 插件的使用 进阶篇(个人收集使用中的)

    idea 插件的使用 进阶篇(个人收集使用中的) 恭喜你,如果你已经看到这篇文章,证明在idear使用上已经初有小成!那么就要向着大神进发了! 下边就是大神之路! 插件的设置 在 IntelliJ I ...

随机推荐

  1. axios中设置了response:blol后,如何处理json对象

    axios中文件下载 上传文件后台校验,若失败则下载文件 let loading = this.$common.loading("正在上传"); let form = new Fo ...

  2. 嵌入式C语言设计学习

    由C语言到嵌入式C语言设计 1.C语言的特性 C语言,最为基本的高级编程语言,已经有许多其他的延伸.而在嵌入式设计中,主要的拓展内容就是相关的硬件设备的驱动.这部分的设计为其提供了更加灵活的应用环境. ...

  3. KingbaseES变更表结构表重写问题

    在实际项目使用数据库的过程中修改字段类型这类需求比较常见. 一.修改表字段类型需要知道: 1.修改表结构可能会导致表进行重写(表OID发生变化). 2.修改表结构带有索引或者字段类型长度或者精度操作时 ...

  4. PicGo图床配置github仓库上传typora图片

    (前提是已注册github并新建一个仓库作为你上传图片的位置) 首先在PicGo官网下载软件:https://picgo.github.io/PicGo-Doc/zh/ 打开typora,找到偏好设置 ...

  5. SpringSecurity认证和授权流程详解

    什么是SpringSecurity Spring Security是一个Java框架,用于保护应用程序的安全性.它提供了一套全面的安全解决方案,包括身份验证.授权.防止攻击等功能.Spring Sec ...

  6. #dp,高精度#洛谷 4295 [SCOI2003]严格N元树

    题目 求有多少棵严格 \(n\) 叉树深度为 \(k\) 分析 考虑往下放子孙挺难维护的,考虑在上面换新的根. 设 \(dp[i]\) 表示深度不超过 \(i\) 的方案数,那么 \(dp[i]=dp ...

  7. OpenHarmony社区运营报告(2023年12月)

      • 截至2023年12月22日,OpenAtom OpenHarmony(简称"OpenHarmony")社区累计超过6700名贡献者,产生26.9万多个PR,2.4万多个St ...

  8. 手工安装部署openGauss3.0一主一备(非om工具安装)

    手工安装部署 openGauss3.0 一主一备(非 om 工具安装) 本文出处:https://www.modb.pro/db/425385 一.操作系统配置(centos7.6) 1.关闭防火墙 ...

  9. HarmonyOS 设备管理开发:USB 服务开发指导

      基本概念 USB服务是应用访问底层的一种设备抽象概念.开发者根据提供的USB API,可以获取设备列表.控制设备访问权限.以及与连接的设备进行数据传输.控制命令传输等. 运作机制 USB服务系统包 ...

  10. 3.1版本【HarmonyOS 第一课】正式上线!参与学习赢官方好礼>>

      [课程介绍] <HarmonyOS第一课>是跟随版本迭代不断推出的系列化课程,本期课程基于HarmonyOS 3.1版本的新技术和特性,每个课程单元里面都包含视频.Codelab.文章 ...