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

时间:2022-02-19 04:47:10

1、命名空间namespace

1.1 什么是命名空间?

Kubernetes 支持多个虚拟集群,它们底层依赖于同一个物理集群。 这些虚拟集群被称为命名空间。

命名空间namespace是k8s集群级别的资源,可以给不同的用户、租户、环境或项目创建对应的命名空间,例如,可以为test、devlopment、production环境分别创建各自的命名空间。

1.2 namespace应用场景

命名空间适用于存在很多跨多个团队或项目的用户的场景。对于只有几到几十个用户的集群,根本不需要创建或考虑命名空间。

1、查看名称空间及其资源对象

k8s集群默认提供了几个名称空间用于特定目的,例如,kube-system主要用于运行系统级资源,存放k8s一些组件的。而default则为那些未指定名称空间的资源操作提供一个默认值。

使用kubectl get namespace可以查看namespace资源,使用kubectl describe namespace $NAME可以查看特定的名称空间的详细信息。

2、管理namespace资源

namespace资源属性较少,通常只需要指定名称即可创建,如“kubectl create namespace qa”。namespace资源的名称仅能由字母、数字、下划线、连接线等字符组成。删除namespace资源会级联删除其包含的所有其他资源对象。

1.3 namespacs常用指令

① 创建一个test命名空间
# kubectl create ns test ② 切换命名空间
# kubectl config set-context --current --namespace=kube-system
#切换命名空间后,kubectl get pods 如果不指定-n,查看的就是kube-system命名空间的资源了。
#查看哪些资源属于命名空间级别的

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

1.4 namespace资源限额

namespace是命名空间,里面有很多资源,那么我们可以对命名空间资源做个限制,防止该命名空间部署的资源超过限制。

如何对namespace资源做限额呢?

# vim namespace-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: mem-cpu-quota
namespace: test
spec:
hard:
requests.cpu: "2"
requests.memory: 2Gi
limits.cpu: "4"
limits.memory: 4Gi #创建的ResourceQuota对象将在test名字空间中添加以下限制:
每个容器必须设置内存请求(memory request),内存限额(memory limit),cpu请求(cpu request)和cpu限额(cpu limit)。
所有容器的内存请求总额不得超过2GiB。
所有容器的内存限额总额不得超过4 GiB。
所有容器的CPU请求总额不得超过2 CPU。
所有容器的CPU限额总额不得超过4CPU。 #创建pod时候必须设置资源限额,否则创建失败,如下:
# vim pod-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-test
namespace: test
labels:
app: tomcat-pod-test
spec:
containers:
- name: tomcat-test
ports:
- containerPort: 8080
image: hxu/tomcat-8.5-jre8:v1
imagePullPolicy: IfNotPresent [root@k8s-master1 ~]# kubectl apply -f pod-test.yaml
[root@k8s-master1 kubenetes-han]# kubectl get pod -n test
NAME READY STATUS RESTARTS AGE
pod-test 1/1 Running 0 67s

2、标签

2.1 什么是标签?

标签其实就一对 key/value ,被关联到对象上,比如Pod,标签的使用我们倾向于能够表示对象的特殊特点,就是一眼就看出了这个Pod是干什么的,标签可以用来划分特定的对象(比如版本,服务类型等),标签可以在创建一个对象的时候直接定义,也可以在后期随时修改,每一个对象可以拥有多个标签,但是,key值必须是唯一的。创建标签之后也可以方便我们对资源进行分组管理。如果对pod打标签,之后就可以使用标签来查看、删除指定的pod。

在k8s中,大部分资源都可以打标签。

2.2 如何给pod资源打标签

显示如下,显示如下,说明标签达成功了;

[root@k8s-master1 kubenetes-han]# kubectl get pods pod-test -n test --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod-test 1/1 Running 0 3m55s app=tomcat-pod-test
# 1、对已经存在的pod打标签,release=v1
[root@k8s-master1 kubenetes-han]# kubectl label pods pod-test release=v1 -n test
pod/pod-test labeled
# 2、查看标签是否打成功:
[root@k8s-master1 kubenetes-han]# kubectl get pods pod-test -n test --show-labels
NAME READY STATUS RESTARTS AGE LABELS
pod-test 1/1 Running 0 4m40s app=tomcat-pod-test,release=v1

2.3 查看资源标签

查看默认名称空间下所有pod资源的标签

[root@k8s-master1 kubenetes-han]#  kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
demo-pod 1/1 Running 0 15d app=myapp,env=dev
nginx-test-57f9f5b6d7-8zt7x 1/1 Running 0 38m app=nginx,pod-template-hash=57f9f5b6d7
nginx-test-57f9f5b6d7-fxsw5 1/1 Running 0 8d app=nginx,pod-template-hash=57f9f5b6d7
test-nginx-67b6d886b6-ccrvd 1/1 Running 0 13d k8s-app=test-nginx,pod-template-hash=67b6d886b6
test-nginx-67b6d886b6-qgjdh 1/1 Running 0 13d k8s-app=test-nginx,pod-template-hash=67b6d886b6

用法示例:

# 查看默认名称空间下指定pod具有的所有标签
kubectl get pods pod-first --show-labels
# 列出默认名称空间下标签key是release的pod,不显示标签
kubectl get pods -l release #列出默认名称空间下标签key是release、值是v1的pod,不显示标签
kubectl get pods -l release=v1 #列出默认名称空间下标签key是release的所有pod,并打印对应的标签值
kubectl get pods -L release #查看所有名称空间下的所有pod的标签
kubectl get pods --all-namespaces --show-labels
kubectl get pods -l release=v1 -L release

3、node节点选择器

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

可以使用pod中的nodeName或者nodeSelector字段指定要调度到的node节点

1、nodeName:

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

先来编写一个yaml文件,指定调度节点为k8s-node1节点,我这里只有一个虚拟机所以看不出来效果,如有多个虚拟机可以指定其他的node节点的主机名!

[root@k8s-master1 kubenetes-han]# cat pod-node.yaml
apiVersion: v1
kind: Pod
metadata:
name: demo-pod
namespace: default
labels:
app: myapp
env: dev
spec:
nodeName: k8s-node1 #此处指定调度到哪个节点,写node的主机名
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"
# kubectl apply -f pod-node.yaml
查看pod调度到哪个节点
[root@k8s-master1 kubenetes-han]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-pod 2/2 Running 0 2m 10.244.1.21 k8s-node1 <none> <none>

4、nodeSelector:

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

给node节点打标签,打个具有disk=ceph的标签
# kubectl label nodes k8s-node2 disk=ceph
node/k8s-node2 labeled
# 定义pod的时候指定要调度到具有disk=ceph标签的node上

编辑一个yaml文件

[root@k8s-master1 kubenetes-han]# cat pod-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: demo-pod-1
namespace: default
labels:
app: myapp
env: dev
spec:
nodeSelector: # 加上nodeselector
disk: ceph # 値
containers:
- name: tomcat-pod-java
ports:
- containerPort: 8080
image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent

读取yaml文件并创建pod

[root@k8s-master1 kubenetes-han]# kubectl apply -f pod-1.yaml
pod/demo-pod-1 created
[root@k8s-master1 kubenetes-han]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demo-pod 2/2 Running 68 2d21h 10.244.1.21 k8s-node1 <none> <none>
demo-pod-1 0/1 ContainerCreating 0 3s <none> k8s-node2 # 调度到了node2上 <none> <none>
nginx-test-57f9f5b6d7-8zt7x 1/1 Running 0 2d22h 10.244.1.19 k8s-node1 <none> <none>
nginx-test-57f9f5b6d7-fxsw5 1/1 Running 0 11d 10.244.1.16 k8s-node1 <none> <none>
test-nginx-67b6d886b6-ccrvd 1/1 Running 0 15d 10.244.1.8 k8s-node1 <none> <none>
test-nginx-67b6d886b6-qgjdh 1/1 Running 0 15d 10.244.1.9 k8s-node1 <none> <none>

5、亲和性

5.1 node节点亲和性

node节点亲和性调度:nodeAffinity

# 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>
podAffinity <Object>
podAntiAffinity <Object> # 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表示必须有节点满足这个位置定义的亲和性,这是个硬性条件,硬亲和性
# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution
KIND: Pod
VERSION: v1
RESOURCE: requiredDuringSchedulingIgnoredDuringExecution <Object>
DESCRIPTION:
FIELDS:
nodeSelectorTerms <[]Object> -required-
Required. A list of node selector terms. The terms are ORed. # kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms
KIND: Pod
VERSION: v1
RESOURCE: nodeSelectorTerms <[]Object>
DESCRIPTION:
Required. A list of node selector terms. The terms are ORed.
A null or empty node selector term matches no objects. The requirements of
them are ANDed. The TopologySelectorTerm type implements a subset of the
NodeSelectorTerm.
FIELDS:
matchExpressions <[]Object>
matchFields <[]Object>
matchExpressions:匹配表达式的
matchFields: 匹配字段的
# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchFields
KIND: Pod
VERSION: v1
RESOURCE: matchFields <[]Object>
DESCRIPTION: FIELDS:
key <string> -required-
values <[]string>
# kubectl explain pods.spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms.matchExpressions
KIND: Pod
VERSION: v1
RESOURCE: matchExpressions <[]Object>
DESCRIPTION:
FIELDS:
key <string> -required-
operator <string> -required-
values <[]string>
key:检查label
operator:做等值选则还是不等值选则
values:给定值

5.1.1 硬亲和性

例1:使用requiredDuringSchedulingIgnoredDuringExecution硬亲和性

#把myapp-v1.tar.gz上传到两个node主机中并load -i

在master节点编辑yaml文件

# cat pod-nodeaffinity-demo.yaml
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标签上的节点上

[root@k8s-master1 kubenetes-han]# kubectl apply -f pod-nodeaffinity-demo.yaml
pod/pod-node-affinity-demo created
[root@k8s-master1 kubenetes-han]# kubectl get pods -o wide | grep pod-node
pod-node-affinity-demo 0/1 Pending 0 2s <none>

status的状态是pending,上面说明没有完成调度,因为没有一个拥有zone的标签的值是foo或者bar,而且使用的是硬亲和性,必须满足条件才能完成调度

[root@k8s-master1 kubenetes-han]# kubectl label nodes k8s-node2  zone=foo
node/k8s-node2 labeled
[root@k8s-master1 kubenetes-han]# kubectl get pods -o wide | grep pod-node
pod-node-affinity-demo 1/1 Running 0 78s 10.244.2.3 k8s-node2

5.1.2 软亲和性

例2:使用preferredDuringSchedulingIgnoredDuringExecution软亲和性

# cat pod-nodeaffinity-demo-2.yaml
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@k8s-master1 kubenetes-han]# kubectl apply -f pod-nodeaffinity-demo-2.yaml
pod/pod-node-affinity-demo-2 created
[root@k8s-master1 kubenetes-han]# kubectl get pods -o wide |grep demo-2
pod-node-affinity-demo-2 1/1 Running 0 2s 10.244.2.4 k8s-node2

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

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

5.2 Pod节点亲和性

pod自身的亲和性调度有两种表示形式

podaffinity:pod和pod更倾向腻在一起,把相近的pod结合到相近的位置,如同一区域,同一机架,这样的话pod和pod之间更好通信,比方说有两个机房,这两个机房部署的集群有1000台主机,那么我们希望把nginx和tomcat都部署同一个地方的node节点上,可以提高通信效率;

podunaffinity:pod和pod更倾向不腻在一起,如果部署两套程序,那么这两套程序更倾向于反亲和性,这样相互之间不会有影响。

第一个pod随机选则一个节点,做为评判后续的pod能否到达这个pod所在的节点上的运行方式,这就称为pod亲和性;我们怎么判定哪些节点是相同位置的,哪些节点是不同位置的;我们在定义pod亲和性时需要有一个前提,哪些pod在同一个位置,哪些pod不在同一个位置,这个位置是怎么定义的,标准是什么?以节点名称为标准,这个节点名称相同的表示是同一个位置,节点名称不相同的表示不是一个位置。

帮助:

# kubectl explain pods.spec.affinity.podAffinity
KIND: Pod
VERSION: v1
RESOURCE: podAffinity <Object>
DESCRIPTION:
Describes pod affinity scheduling rules (e.g. co-locate this pod in the
same node, zone, etc. as some other pod(s)).
Pod affinity is a group of inter pod affinity scheduling rules.
FIELDS:
preferredDuringSchedulingIgnoredDuringExecution <[]Object>
requiredDuringSchedulingIgnoredDuringExecution <[]Object> requiredDuringSchedulingIgnoredDuringExecution: 硬亲和性
preferredDuringSchedulingIgnoredDuringExecution:软亲和性 # kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution
KIND: Pod
VERSION: v1
RESOURCE: requiredDuringSchedulingIgnoredDuringExecution <[]Object>
DESCRIPTION:
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的名称空间 # kubectl explain pods.spec.affinity.podAffinity.requiredDuringSchedulingIgnoredDuringExecution.labelSelector
KIND: Pod
VERSION: v1
RESOURCE: labelSelector <Object>
DESCRIPTION:
A label query over a set of resources, in this case pods.
A label selector is a label query over a set of resources. The result of
matchLabels and matchExpressions are ANDed. An empty label selector matches
all objects. A null label selector matches no objects.
FIELDS:
matchExpressions <[]Object>
matchLabels <map[string]string>

5.2.1 pod节点亲和性

例1:

定义两个pod,第一个pod做为基准,第二个pod跟着它走

# cat pod-required-affinity-demo.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
app2: myapp2
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: app2, operator: In, values: ["myapp2"]}
topologyKey: kubernetes.io/hostname #上面表示创建的pod必须与拥有app=myapp标签的pod在一个节点上
# kubectl apply -f pod-required-affinity-demo.yaml
kubectl get pods -o wide 显示如下:
[root@k8s-master1 kubenetes-han]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-first 1/1 Running 0 24s 10.244.2.5 k8s-node2
pod-second 1/1 Running 0 24s 10.244.2.6 k8s-node2

上面说明第一个pod调度到哪,第二个pod也调度到哪,这就是pod节点亲和性

注意:查看node节点的标签可以使用--show-labels查看

kubectl get nodes --show-labels

5.2.2 Pod节点反亲和性

例2:

定义两个pod,第一个pod做为基准,第二个pod跟它调度节点相反

在master节点编辑yaml文件

# 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
# kubectl apply -f pod-required-anti-affinity-demo.yaml
# 显示两个pod不在一个node节点上,这就是pod节点反亲和性
[root@k8s-master1 kubenetes-han]# kubectl get pods -o wide
pod-first 1/1 Running 0 4s 10.244.2.7 k8s-node2
pod-second 1/1 Running 0 4s 10.244.1.22 k8s-node1
# kubectl delete -f pod-required-anti-affinity-demo.yaml

例3:换一个topologykey

[root@k8s-master1 kubenetes-han]# kubectl label nodes k8s-node1  zone=foo
[root@k8s-master1 kubenetes-han]# kubectl label nodes k8s-node2 zone=foo --overwrite
# cat pod-first-required-anti-affinity-demo-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-first
labels:
app3: myapp3
tier: frontend
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1 # cat pod-second-required-anti-affinity-demo-1.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@k8s-master1 kubenetes-han]# kubectl apply -f pod-first-required-anti-affinity-demo-1.yaml
pod/pod-first created
[root@k8s-master1 kubenetes-han]# kubectl apply -f pod-second-required-anti-affinity-demo-1.yaml
pod/pod-second created

[root@k8s-master1 kubenetes-han]# kubectl get pod -o wide显示如下:

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

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

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

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

6、污点、容忍度

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

taints是键值数据,用在节点上,定义污点;

tolerations是键值数据,用在pod上,定义容忍度,能容忍哪些污点

pod亲和性是pod属性;但是污点是节点的属性,污点定义在nodeSelector上

# kubectl describe nodes k8s-master1

Taints: node-role.kubernetes.io/master:NoSchedule

# kubectl explain node.spec.taints
KIND: Node
VERSION: v1
RESOURCE: taints <[]Object>
DESCRIPTION:
If specified, the node's taints.
The node this Taint is attached to has the "effect" on any pod that does
not tolerate the Taint.
FIELDS:
effect <string> -required-
key <string> -required-
timeAdded <string>
value <string>

taints的effect用来定义对pod对象的排斥等级(效果):

NoSchedule:

仅影响pod调度过程,当pod能容忍这个节点污点,就可以调度到当前节点,后来这个节点的污点改了,加了一个新的污点,使得之前调度的pod不能容忍了,那这个pod会怎么处理,对现存的pod对象不产生影响

NoExecute:

既影响调度过程,又影响现存的pod对象,如果现存的pod不能容忍节点后来加的污点,这个pod就会被驱逐

PreferNoSchedule:

最好不,也可以,是NoSchedule的柔性版本

在pod对象定义容忍度的时候支持两种操作:

1.等值密钥:key和value上完全匹配

2.存在性判断:key和effect必须同时匹配,value可以是空

在pod上定义的容忍度可能不止一个,在节点上定义的污点可能多个,需要琢个检查容忍度和污点能否匹配,每一个污点都能被容忍,才能完成调度,如果不能容忍怎么办,那就需要看pod的容忍度了

# kubectl describe nodes k8s-master1

查看master这个节点是否有污点,显示如下:

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

上面可以看到master这个节点的污点是Noschedule

所以我们创建的pod都不会调度到master上,因为我们创建的pod没有容忍度

kubectl describe pods kube-apiserver-k8s-master1 -n kube-system

显示如下

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

可以看到这个pod的容忍度是NoExecute,则可以调度到k8s-master1上

6.1 管理节点污点

[root@k8s-master1]# kubectl taint –help

例1:把k8s-node2当成是生产环境专用的,其他node是测试的,先打个污点

[root@k8s-master1 taint]# kubectl taint node k8s-node2 node-type=production:NoSchedule

node/k8s-node2 tainted

[root@k8s-master1 taint]# cat pod-taint.yaml
apiVersion: v1
kind: Pod
metadata:
name: taint-pod
namespace: default
labels:
tomcat: tomcat-pod
spec:
containers:
- name: taint-pod
ports:
- containerPort: 8080
image: tomcat:8.5-jre8-alpine
imagePullPolicy: IfNotPresent

查看一下pod呗调度到哪个节点了

[root@k8s-master1 taint]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE
taint-pod 1/1 Running 0 20s 10.244.1.23 k8s-node1

可以看到都被调度到k8s-node1上了,因为k8s-node2这个节点打了污点,而我们在创建pod的时候没有容忍度,所以k8s-node2上不会有pod调度上去的

例2:给k8s-node1也打上污点

[root@k8s-master1 taint]# kubectl taint node k8s-node1  node-type=dev:NoExecute
node/k8s-node1 tainted
[root@k8s-master1 taint]# kubectl get pods -o wide

如下图,可以看到node1已经存在的pod节点都被撵走了

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

[root@k8s-master1 taint]# cat pod-demo-1.yaml
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: "NoExecute"
tolerationSeconds: 3600

myapp-deploy 1/1 Pending 0 11s k8s-node2

还是显示pending,因为我们使用的是equal(等值匹配),所以key和value,effect必须和node节点定义的污点完全匹配才可以,把上面配置effect: "NoExecute"变成

effect: "NoSchedule"成;

tolerationSeconds: 3600这行去掉

先delete掉上面创建的pod后在修改,修改后重新应用。

上面就可以调度到k8s-node2上了,因为在pod中定义的容忍度能容忍node节点上的污点

例3:再次修改

修改如下部分:

tolerations:
- key: "node-type"
operator: "Exists"
value: ""
effect: "NoSchedule"

只要对应的键是存在的,exists,其值被自动定义成通配符

# kubectl delete -f pod-demo-1.yaml

# kubectl apply -f pod-demo-1.yaml

# kubectl get pods

发现还是调度到k8s-node2上

myapp-deploy 1/1 running 0 11s k8s-node2

最后删除污点:

[root@k8s-master1 taint]#kubectl taint nodes k8s-node1 node-type:NoExecute-

node/k8s-node1 untainted

[root@k8s-master1 taint]# kubectl taint nodes k8s-node2 node-type:NoSchedule-

node/k8s-node2 untainted

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

7.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 启动过程中发生了错误

7.2 pod重启策略

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

Pod的重启策略包括 Always、OnFailure和Never,默认值为Always。

Always:当容器失败时,由kubelet自动重启该容器。

OnFailure:当容器终止运行且退出码不为0时,由kubelet自动重启该容器。

Never:不论容器运行状态如何,kubelet都不会重启该容器。

[root@k8s-master1 ~]# vim pod.yaml

apiVersion: v1

kind: Pod

metadata:

name: demo-pod

namespace: default

labels:

app: myapp

spec:

restartPolicy: Always

containers:

  • name: tomcat-pod-java

    ports:
    • containerPort: 8080

      image: tomcat:8.5-jre8-alpine

      imagePullPolicy: IfNotPresent

8、Pod生命周期

概念图

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

8.1 Init容器

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-containers-in-use

访问官方文档

在本机也编辑一个yaml

[root@k8s-master1 init-pod]# cat init-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['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-mydb
image: busybox:1.28
command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]

更新yaml文件,此文件一直处于初始化阶段

[root@k8s-master1 init-pod]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 3m17s

可以通过kubectl describe pod myapp-pod查看一下pod相关信息

有两个容器需要先进行初始化后才能继续,

kubectl logs myapp-pod -c init-myservice # Inspect the first init container

kubectl logs myapp-pod -c init-mydb # Inspect the second init container

yaml文件中定义的需要解析db的服务,因为我们还没有创建所以一直卡在这,按着官网文档先进行创建一个

\---
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
\---
apiVersion: v1
kind: Service
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377

8.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。

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

当用户创建pod时,这个请求给apiserver,apiserver把创建请求的状态保存在etcd中;

接下来apiserver会请求scheduler来完成调度,如果调度成功,会把调度的结果(如调度到哪个节点上了,运行在哪个节点上了,把它更新到etcd的pod资源状态中)保存在etcd中,一旦存到etcd中并且完成更新以后,如调度到k8s-master1上,那么k8s-master1节点上的kubelet通过apiserver当中的状态变化知道有一些任务被执行了,所以此时此kubelet会拿到用户创建时所提交的清单,这个清单会在当前节点上运行或者启动这个pod,如果创建成功或者失败会有一个当前状态,当前这个状态会发给apiserver,apiserver在存到etcd中;在这个过程中,etcd和apiserver一直在打交道,不停的交互,scheduler也参与其中,负责调度pod到合适的node节点上,这个就是pod的创建过程

pod在整个生命周期中有非常多的用户行为:

1、初始化容器完成初始化

2、主容器启动后可以做启动后钩子

3、主容器结束前可以做结束前钩子

4、在主容器运行中可以做一些健康检测,如liveness probe,readness probe

k8s核心资源之namespace与pod污点容忍度生命周期进阶篇(四)的更多相关文章

  1. k8s核心资源之Pod概念&amp&semi;入门使用讲解(三)

    目录 1. k8s核心资源之Pod 1.1 什么是Pod? 1.2 Pod如何管理多个容器? 1.3 Pod网络 1.4 Pod存储 1.5 Pod工作方式 1.5.1 自主式Pod 1.5.2 控制 ...

  2. K8S&lpar;02&rpar;管理核心资源的三种基本方法

    系列文章说明 本系列文章,可以基本算是 老男孩2019年王硕的K8S周末班课程 笔记,根据视频来看本笔记最好,否则有些地方会看不明白 需要视频可以联系我 管理k8s核心资源的三种基本方法: 目录 系列 ...

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

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

  4. K8s容器资源限制

    在K8s中定义Pod中运行容器有两个维度的限制: 1. 资源需求:即运行Pod的节点必须满足运行Pod的最基本需求才能运行Pod. 如: Pod运行至少需要2G内存,1核CPU    2. 资源限额: ...

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

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

  6. kubernetes(k8s)Pod污点与容忍

    污点(taints)与容忍(tolerations) 对于nodeAffinity无论是硬策略还是软策略方式,都是调度 pod 到预期节点上,而Taints恰好与之相反,如果一个节点标记为 Taint ...

  7. 从零开始入门 K8s&vert; 阿里技术专家详解 K8s 核心概念

    作者| 阿里巴巴资深技术专家.CNCF 9个 TCO 之一 李响 一.什么是 Kubernetes Kubernetes,从官方网站上可以看到,它是一个工业级的容器编排平台.Kubernetes 这个 ...

  8. k8s控制器资源(五)

    Pod pod在之前说过,pod是kubernetes集群中是最小的调度单元,pod中可以运行多个容器,而node又可以包含多个pod,关系如下图: 在对pod的用法进行说明之前,有必要先对docke ...

  9. k8s的Pod状态和生命周期管理

    Pod状态和生命周期管理   一.什么是Pod? 二.Pod中如何管理多个容器? 三.使用Pod 四.Pod的持久性和终止 五.Pause容器 六.init容器 七.Pod的生命周期 (1)Pod p ...

随机推荐

  1. Windows平台下和跨平台的相关公共库

    以下主要包含windows下公共库以及跨平台公共库: 1. google base库:google下chromium项目的跨平台公共库: 2. vc_common_src:即HP_SOCKET项目中的 ...

  2. SpringMVC4零配置--web&period;xml

    servlet3.0+规范后,允许servlet,filter,listener不必声明在web.xml中,而是以硬编码的方式存在,实现容器的零配置. ServletContainerInitiali ...

  3. Windows系统上的&period;Net版本和&period;NETFramework的C&num;版本

    前言 注:本文内容摘自*,用于在墙内时当作笔记看. WinForm 需要.Net最低版本 2.0 WPF需要的.Net最低版本 3.0 (Win7及之上版本自带) C#版本 版本 语言规格 日期 ...

  4. 认识Java Core和Heap Dump

    什么是Java Core和Heap Dump Java程序运行时,有时会产生Java Core及Heap Dump文件,它一般发生于Java程序遇到致命问题的情况下. 发生致命问题后,Java进程有时 ...

  5. mysql 导入导出方法。

    1.导出  mysqldump -u username - p databasename >名.sql enter passward: 2.导入:mysql -uroot -proot sour ...

  6. OC第三节——NSArray和NSMutableArray

    1.OC数组和c数组的区别        C语言的数组:            相同类型变量的有序结合. 类型:可以是简答数据类型.构造数据类型                int     a[10 ...

  7. zju3430

    题意:给出多个加密的模式串,和多个待匹配的串,问每个串里出现了多少种模式串.加密方法是把每3bytes加密成按6bits一个对应成4个字符,对应方法题里给了. 分析:除了解密之外,基本是个赤裸裸的AC ...

  8. Science论文&quot&semi;Clustering by fast search and find of density peaks&quot&semi;学习笔记

    "Clustering by fast search and find of density peaks"是今年6月份在<Science>期刊上发表的的一篇论文,论文中 ...

  9. BZOJ2348&colon; &lbrack;Baltic 2011&rsqb;Plagiarism

    2348: [Baltic 2011]Plagiarism Time Limit: 1 Sec  Memory Limit: 256 MBSubmit: 304  Solved: 141[Submit ...

  10. &lbrack;睡前灵感and发散思维&rsqb;由一个简单的数组比较问题而想到的

    前言 据说,一只优秀的程序猿往往会有这样的经历,白天遇到一个绞尽脑汁也无法解决的问题,晚上睡了后,半夜在梦中会灵感涌现,立马起床,打开电脑,一气呵成.第二天如果不看注释,完全不知道自己找到了如此巧妙地 ...