在K8S平台上,我们很少会直接创建一个Pod,在大多数情况下会通过RC,Deployment,DaemonSet,Job等控制器完成一组Pod副本的创建,调度及全生命周期的自动控制任务。
在k8s 1.9以前,在RC等对象被删除后,它们所创建的Pod副本都不会被删除;在k8s 1.9以后,这些Pod副本会被一并删除。
如果不希望这样做,可以通过kubectl命令的“--cascade=false”参数来取消这一默认特性:
kubectl delete replicaset my-reset --cascade=false
NodeSelector:定向调度
在一些情况下,我们需要将pod调度到指定的一些Node上,可以通过Node的标签(Label)和Pod的nodeSelector属性相匹配。
首先通过kubectl label 命令给目标Node打上一些标签:
kubectl label nodes node-name label-key=label-vaule
kubectl label nodes 172.20.103.2 test=jinguanhua
然后,在pod的定义中加上nodeSelector的设置:
kubectl create -f redis.yaml
apiVersion: v1
kind: deploy
metadata:
name: redis-master
labels:
name: redis-master
spec:
replicas: 1
selector:
name: redis-master
template:
metadata:
labels:
name: redis-master
spec:
containers:
- name: master
image: kubeguide/redis-master
ports:
- containerPort: 6379
nodeSelector:
test: jinguanhua
如果我们给多个node都定义了相同的标签,则scheduler会根据调度算法从这组Node中挑选一个可用的Node进行Pod调度。
通过基于Node标签的调度方式,我们可以把集群中具有不同特点的Node都贴上不同的标签,例如“role=test”,“role=backend”,“role=database”等标签,在部署应用时就可以根据应用的需求设置NodeSelector来进行制定Node范围的调度。
PS:如果我们指定了Pod的nodeSelector条件,但是在集群中不存在包含相应标签的Node,则即使在集群中还有其他可供使用的node,这个pod也无法被成功调度。
亲和性调度
亲和性调度功能包括 节点亲和性(NodeAffinity)和 Pod亲和性(PodAffinity)两个维度的设置。
节点亲和性(NodeAffinity)
NodeAffinity是node亲和性的调度策略,是用于替换NodeSelector的全新调度策略。目前有两种节点亲和性表达。
RequiredDuringSchedulingIgnoredDuringExecution:必须满足指定的规则才可以调度pod到node上,相当于硬限制。
PreferredDuringSchedulingIgnoredDuringExecution:强调优先满足指定规则,调度器会尝试调度pod到node上,但并不强求,相当于软限制。多个优先级规则还可以设置权重(weight)值,以定义执行的先后顺序。
IgnoredDuringExecution的意思是:如果一个pod所在的节点在pod运行期间标签发生了变更,不再符合该pod的节点亲和性需求,则系统将忽略node上label的变化,该pod能继续在该节点运行。
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- amd64
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: disk-type
operator: In
values:
- ssd
containers:
- name: with-node-affinity
image: gcr.io/google_containers/pause:2.0
从上面的配置中可以看到In操作符,NodeAffinity语法支持的操作符包括In,NotIn,Exists,DoesNotExist,Gt,Lt。虽然没有节点排斥功能,但是用NotIn和DoesNotExist就可以实现排斥的功能了。
NodeAffinity 规则设置的注意事项如下:
如果同时定义了nodeSelector和nodeAffinity,那么必须两个条件都得到满足,Pod才能最终运行到指定的Node上。
如果nodeAffinity指定了多个nodeSelectorTerms,那么其中一个能够匹配成功即可。
如果在nodeSelectorTerms中有多个matchExpressions,则一个节点必须满足所有matchExpressions才能运行该Pod。
Pod亲和性(PodAffinity)与互斥性(podAntiAffinity)调度策略
Pod间的亲和与互斥从Kubernetes 1.4版本开始引入。这一功能让用户从另一个角度来限制Pod所能运行的节点:根据在节点上正在运行的Pod的标签而不是节点的标签进行判断和调度,要求对节点和Pod两个条件进行匹配。这种规则可以描述为:如果在具有标签X的Node上运行了一个或者多个符合条件Y的Pod,那么Pod应该(如果是互斥的情况,那么就变成拒绝)运行在这个Node上。
这里X指的是一个集群中的节点、区域(zone)和地域(region)等概念,通过Kubernetes内置节点标签中的key来进行声明。这个key的名字为topologyKey,意为表达节点所属的topology范围。
◎ kubernetes.io/hostname
◎ kubernetes.io/arch
◎ kubernetes.io/os
◎ failure-domain.beta.kubernetes.io/zone
◎ failure-domain.beta.kubernetes.io/region
与节点不同的是,Pod是属于某个命名空间的,所以条件Y表达的是一个或者全部命名空间中的一个Label Selector。
[root@iZ2ze7mealklhmaorgtx5jZ pro]# kubectl get no cn-beijing.172.17.13.102 --show-labels
NAME STATUS ROLES AGE VERSION LABELS
cn-beijing.172.17.13.102 Ready <none> 574d v1.16.6-aliyun.1 alibabacloud.com/nodepool-id=np019605d02c37420a9e201a4eba2391c7,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/instance-type=ecs.sn1ne.xlarge,beta.kubernetes.io/os=linux,env=product,failure-domain.beta.kubernetes.io/region=cn-beijing,failure-domain.beta.kubernetes.io/zone=cn-beijing-c,kubernetes.io/arch=amd64,kubernetes.io/hostname=cn-beijing.172.17.13.102,kubernetes.io/os=linux
为了保证业务应用的高可用,有些客户会要求关键应用部署到多个机房,一个机房一旦出问题,其他机房正常工作,从而让应用保持不间断连续运行。类似这样的能力在云上如何实现呢?阿里云有Region(地域)和Zone(可用区)的概念。简单点理解,Region对应城市,例如“华东1”为杭州,“华北2”为北京等。Zone为Region下按照电力和网络设备等相互独立的的可用区,不同的可用区可能在一个物理机房中。同一个地域内的不同可用区之间内网是连通的,网络延迟很小。
和节点亲和相同,Pod亲和与互斥的条件设置也是requiredDuringSchedulingIgnoredDuringExecution和preferredDuringSchedulingIgnoredDuringExecution。
pod的亲和性被定义与PodSpec的affinity字段下的podAffinity子字段中。
pod间的互斥性则被定义于同一层次的podAntiAffinity子字段中。
下面通过实例来说明pod间的亲和性和互斥性策略设置
1.参照目标Pod
首先,创建一个名为pod-flag的Pod,带有标签security=S1和app=nginx,后面的例子将使用pod-flag作为Pod亲和与互斥的目标Pod:
apiVersion: v1
kind: Pod
metadata:
name: pod-flag
labels:
security: "S1"
app: "nginx"
spec:
containers:
- name: nginx
image: nginx
2.Pod的亲和性调度
下面创建第2个Pod来说明Pod的亲和性调度,这里定义的亲和标签是security=S1,对应上面的Pod“pod-flag”,topologyKey的值被设置为“kubernetes.io/hostname”:
apiVersion: v1
kind: Pod
metadata:
name: pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: kubernetes.io/hostname
containers:
- name: with-pod-affinity
image: gcr.io/google_containers/pause:2.0
创建Pod之后,使用kubectl get pods -o wide命令可以看到,这两个Pod在同一个Node上运行。有兴趣的读者还可以测试一下,在创建这个Pod之前,删掉这个节点的kubernetes.io/hostname标签,重复上面的创建步骤,将会发现Pod一直处于Pending状态,这是因为找不到满足条件的Node了。
3.Pod的互斥性调度
创建第3个Pod,我们希望它不与目标Pod运行在同一个Node上:
apiVersion: v1
kind: Pod
metadata:
name: anti-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: failure-domain.beta.kubernetes.io/zone
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- nginx
topologyKey: kubernetes.io/hostname
containers:
- name: anti-affinity
image: gcr.io/google_containers/pause:2.0
这里要求这个新Pod与security=S1的Pod为同一个zone,但是不与app=nginx的Pod为同一个Node。创建Pod之后,同样用kubectl get pods -o wide来查看,会看到新的Pod被调度到了同一Zone内的不同Node上。
与节点亲和性类似,Pod亲和性的操作符也包括In、NotIn、Exists、DoesNotExist、Gt、Lt。
原则上,topologyKey可以使用任何合法的标签Key赋值,但是出于性能和安全方面的考虑,对topologyKey有如下限制。
◎ 在Pod亲和性和RequiredDuringScheduling的Pod互斥性的定义中,不允许使用空的topologyKey。
◎ 如果Admission controller包含了LimitPodHardAntiAffinityTopology,那么针对RequiredDuringScheduling的Pod互斥性定义就被限制为kubernetes.io/hostname,要使用自定义的topologyKey,就要改写或禁用该控制器。
◎ 在PreferredDuringScheduling类型的Pod互斥性定义中,空的topologyKey会被解释为kubernetes.io/hostname、failuredomain.beta.kubernetes.io/zone及failuredomain.beta.kubernetes.io/region的组合。
◎ 如果不是上述情况,就可以采用任意合法的topologyKey了。
PodAffinity规则设置的注意事项如下。
◎ 除了设置Label Selector和topologyKey,用户还可以指定Namespace列表来进行限制,同样,使用Label Selector对Namespace进行选择。Namespace的定义和Label Selector及topologyKey同级。省略Namespace的设置,表示使用定义了affinity/anti-affinity的Pod所在的Namespace。如果Namespace被设置为空值(""),则表示所有Namespace。
◎ 在所有关联requiredDuringSchedulingIgnoredDuringExecution的matchExpressions全都满足之后,系统才能将Pod调度到某个Node上。
来源:oschina
链接:https://my.oschina.net/u/4408441/blog/4947955