最简单的方法: podName节点选择,直接选择一个节点,但是一般不推荐,如果直接指定了,那么就会优先于其他选择方法。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: myapp
image: nginx
nodeName: server3 ##直接选择server3的节点
但是这个方法也有一些限制:比如节点不存在,或者是这个节点资源满了,都会使pod调度失败。
使用标签进行调度
[kubeadm@server1 ~]$ kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
server1 Ready master 14d v1.17.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=server1,kubernetes.io/os=linux,node-role.kubernetes.io/master=
server3 Ready <none> 14d v1.17.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=server3,kubernetes.io/os=linux
server4 Ready <none> 14d v1.17.3 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=server4,kubernetes.io/os=linux
首先查看每个节点的标签,发现 在server3上有了一个ssd
的标签,我们可以直接使用这个标签进行调度。
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: myapp
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd ##pod创建时根据这个标签来匹配节点。
亲和与反亲和
节点亲和
这个规则和上面两条规则相比是软性要求,所以在调度器无法满足要求时仍然可以调度这个pod
节点亲和分为必须满足和倾向满足。
apiVersion: v1
kind: Pod
metadata:
name: node-affinity
spec:
containers:
- name: nginx
image: nginx
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: ##这个是硬性要求
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In ##这个参数In代表的就是要从下面的标签进行调度
values:
- ssd ##调度到标签为ssd的节点
[kubeadm@server1 ~]$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
node-affinity 1/1 Running 0 2m28s 10.244.2.52 server3 <none> <none>
如果pod创建完成后现在将调度的标签删除掉,这个pod不会进行节点转移。在之后重新创建才会调度到硬性要求的节点
apiVersion: v1
kind: Pod
metadata:
name: node-affinity
spec:
containers:
- name: nginx
image: nginx
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:##硬性要求
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname ##用户名
operator: NotIn ##不能等于
values:
- server1
preferredDuringSchedulingIgnoredDuringExecution:##软性要求
- weight: 1 软性要求的权重
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
这样创建出来的pod必然不能在server1上,而软性要求可以添加多个,然后看哪个更亲和一些,那么就会部署到哪个节点之上。
pod亲和性
亲和性在pod之间,而不在节点之间,首先创建一个pod
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
再创建一个需要和上面pod放在一个节点上的pod,这个pod我们不做过多的指定,给他一个要求,让他自己去寻找更亲和的pod上的节点。
apiVersion: v1
kind: Pod
metadata:
name: mysql
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql
env:
- name: "MYSQL_ROOT_PASSWORD"
value: "passyt"
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app ##这里让我们选择标签是nginx的pod
operator: In
values:
- nginx
topologyKey: "kubernetes.io/hostname"
这样两个pod就会在一个节点上,有了亲和还有反亲和,其中最大的区别就是podAffinity这个参数,podAffinity
是亲和,podAntiAffinity
是反亲和,设置了这个参数,两个就是排斥的。
污点和容忍
污点代表一个东西不好的地方,容忍是说即使有污点如果没有别的选择我也可以将就一下。
创建污点使用
[kubeadm@server1 test]$ kubectl taint nodes server3 key=value:NoSchedule##不能被调度,除了这个还有两个策略
node/server3 tainted
查询污点使用
[kubeadm@server1 test]$ kubectl describe nodes server3 |grep Taints
Taints: key=value:NoSchedule
创建一个pod来进行测试
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
由于server3上打了一个污点,不进行调度,所以只有1和4上面创建pod。
[kubeadm@server1 test]$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
web-server-86c57db685-8lc4w 1/1 Running 0 32s 10.244.3.57 server4 <none> <none>
web-server-86c57db685-mtq9n 1/1 Running 0 32s 10.244.3.56 server4 <none> <none>
web-server-86c57db685-n89kq 1/1 Running 0 32s 10.244.0.70 server1 <none> <none>
重新设置一个污点
首先直接先使用上面文件创建pod,这时pod是平均调度的,
之后设置一个污点
[kubeadm@server1 test]$ kubectl taint node server3 key=v1:NoExecute ##会踢出原有pod
node/server3 tainted
这个时候被踢出的pod会转移
在pod中设置容忍标签,结果可能会不太一样。
在容器中
tolerations:
- key: "key" ##key value 设置的东西要一一对应
operator: "Equal"
value: "v1"
effect: "NoExecute"
这样可以容忍就能实现正常调度。
暂时隔离cordon,drain和delete创建新的pod不会被调度到该节点,区别在于暴力程度不一样。
cordon
cordon停止调度,使用后不会被调度到该节点,但是原有pod不受影响。
[kubeadm@server1 test]$ kubectl cordon server3
node/server3 cordoned
[kubeadm@server1 test]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
server1 Ready master 15d v1.17.3
server3 Ready,SchedulingDisabled <none> 15d v1.17.3
server4 Ready <none> 15d v1.17.3
[kubeadm@server1 test]$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfs-client-provisioner-6bc469c54d-wqrr8 1/1 Running 3 42h 10.244.3.60 server4 <none> <none>
web-server-86c57db685-cnxg9 1/1 Running 0 10s 10.244.2.56 server3 <none> <none>
web-server-86c57db685-czv7f 1/1 Running 0 10s 10.244.0.77 server1 <none> <none>
web-server-86c57db685-kv22c 1/1 Running 0 10s 10.244.3.66 server4 <none> <none>
上面是已经完成调度的,server3上虽然已经不参加调度,但是已经运行的pod并不受到影响,这个时候我们对集群进行扩容。
[kubeadm@server1 test]$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfs-client-provisioner-6bc469c54d-wqrr8 1/1 Running 3 42h 10.244.3.60 server4 <none> <none>
web-server-86c57db685-cnxg9 1/1 Running 0 105s 10.244.2.56 server3 <none> <none>
web-server-86c57db685-czv7f 1/1 Running 0 105s 10.244.0.77 server1 <none> <none>
web-server-86c57db685-f7jgc 1/1 Running 0 3s 10.244.3.67 server4 <none> <none>
web-server-86c57db685-kv22c 1/1 Running 0 105s 10.244.3.66 server4 <none> <none>
web-server-86c57db685-lrrpl 1/1 Running 0 3s 10.244.3.68 server4 <none> <none>
web-server-86c57db685-wd7mq 1/1 Running 0 3s 10.244.0.78 server1 <none> <none>
这时可以发现,其调度只在1和4上。
去除这个调度选项直接使用命令去除。
[kubeadm@server1 test]$ kubectl uncordon server3
node/server3 uncordoned
drain
使用drain会首先将节点上的pod踢出,之后在其他节点重新进行创建。
[kubeadm@server1 test]$ kubectl drain server3
node/server3 cordoned
evicting pod "web-server-86c57db685-cnxg9"
pod/web-server-86c57db685-cnxg9 evicted
node/server3 evicted
[kubeadm@server1 test]$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfs-client-provisioner-6bc469c54d-wqrr8 1/1 Running 3 42h 10.244.3.60 server4 <none> <none>
web-server-86c57db685-c6pmf 1/1 Running 0 19s 10.244.3.69 server4 <none> <none>
web-server-86c57db685-czv7f 1/1 Running 0 13m 10.244.0.77 server1 <none> <none>
web-server-86c57db685-f7jgc 1/1 Running 0 12m 10.244.3.67 server4 <none> <none>
web-server-86c57db685-kv22c 1/1 Running 0 13m 10.244.3.66 server4 <none> <none>
web-server-86c57db685-lrrpl 1/1 Running 0 12m 10.244.3.68 server4 <none> <none>
web-server-86c57db685-wd7mq 1/1 Running 0 12m 10.244.0.78 server1 <none> <none>
将这个节点恢复过来同样使用命令
[kubeadm@server1 test]$ kubectl uncordon server3
delete
使用delete是最暴力的,过程是:首先将节点上的所有pod踢出,之后在控制节点直接将其删除,脱离节点的控制,如果要恢复那么就要进入节点重新启动kubelet服务。
[kubeadm@server1 test]$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nfs-client-provisioner-6bc469c54d-4w9rl 1/1 Running 0 12s 10.244.2.61 server3 <none> <none>
web-server-86c57db685-6fkkj 1/1 Running 0 12s 10.244.2.59 server3 <none> <none>
web-server-86c57db685-czv7f 1/1 Running 0 24m 10.244.0.77 server1 <none> <none>
web-server-86c57db685-f25rt 1/1 Running 0 12s 10.244.2.58 server3 <none> <none>
web-server-86c57db685-k46tf 1/1 Running 0 12s 10.244.2.57 server3 <none> <none>
web-server-86c57db685-vtwwd 1/1 Running 0 12s 10.244.2.60 server3 <none> <none>
web-server-86c57db685-wd7mq 1/1 Running 0 22m 10.244.0.78 server1 <none> <none>
本来在4上的pod全部转移到了3上
恢复节点,进入对应的node中,启动服务
[root@server4 ~]# systemctl restart kubelet.service
但是这个节点重新启动后并不会重新进行调度。