伸缩(Scale Up/Down)是指在线增加或减少 Pod 的副本数。
Deployment nginx-app
初始是两个副本
[root@master ~]# kubectl apply -f nginx.yaml
deployment.apps/nginx-app created
[root@master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-app-7f4fc68488-4szxm 1/1 Running 0 91s 10.244.2.5 node2 <none> <none>
nginx-app-7f4fc68488-zxbg8 1/1 Running 0 91s 10.244.1.4 node1 <none> <none>
node1
和 knode2
上各跑了一个副本。现在修改 nginx.yml,将副本改成 5 个
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-app
spec:
selector:
matchLabels:
app: nginx
# 部署的实例数量改为5
replicas: 5
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.17
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
再次执行 kubectl apply
:
[root@master ~]# kubectl apply -f nginx.yaml
deployment.apps/nginx-app configured
[root@master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-app-7f4fc68488-4szxm 1/1 Running 0 4m19s 10.244.2.5 node2 <none> <none>
nginx-app-7f4fc68488-9zwlc 1/1 Running 0 94s 10.244.2.7 node2 <none> <none>
nginx-app-7f4fc68488-cmdfj 1/1 Running 0 94s 10.244.1.5 node1 <none> <none>
nginx-app-7f4fc68488-tw9nn 1/1 Running 0 94s 10.244.2.6 node2 <none> <none>
nginx-app-7f4fc68488-zxbg8 1/1 Running 0 4m19s 10.244.1.4 node1 <none> <none>
[root@master ~]#
三个新副本被创建并调度到 k8s-node1 和 k8s-node2 上。
出于安全考虑,默认配置下 Kubernetes 不会将 Pod 调度到 Master 节点。如果希望将 k8s-master 也当作 Node 使用,可以执行如下命令:
kubectl taint node k8s-master node-role.kubernetes.io/master-
如果要恢复 Master Only 状态,执行如下命令:
kubectl taint node k8s-master node-role.kubernetes.io/master="":NoSchedule
接下来修改配置文件,将副本数减少为 3 个,重新执行 kubectl apply
:
[root@master ~]# kubectl apply -f nginx.yaml
deployment.apps/nginx-app configured
[root@master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-app-7f4fc68488-4szxm 1/1 Running 0 9m40s 10.244.2.5 node2 <none> <none>
nginx-app-7f4fc68488-9zwlc 1/1 Running 0 6m55s 10.244.2.7 node2 <none> <none>
nginx-app-7f4fc68488-tw9nn 0/1 Terminating 0 6m55s 10.244.2.6 node2 <none> <none>
nginx-app-7f4fc68488-zxbg8 1/1 Running 0 9m40s 10.244.1.4 node1 <none> <none>
[root@master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-app-7f4fc68488-4szxm 1/1 Running 0 9m44s 10.244.2.5 node2 <none> <none>
nginx-app-7f4fc68488-9zwlc 1/1 Running 0 6m59s 10.244.2.7 node2 <none> <none>
nginx-app-7f4fc68488-zxbg8 1/1 Running 0 9m44s 10.244.1.4 node1 <none> <none>
可以看到两个副本被删除,最终保留了 3 个副本
Failover,物理节点故障,容器重构
现在模拟 node2 故障,关闭该节点。等待一段时间,Kubernetes 会检查到 node2 不可用,将 knode2 上的 Pod 标记为 Unknown
状态,并在 node1 上新创建两个 Pod,维持总副本数为 3
[root@master ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
master Ready control-plane,master 4h56m v1.20.0
node1 Ready node 4h48m v1.20.0
node2 NotReady node 4h47m v1.20.0
等待一段时间,Kubernetes 会检查到 k8s-node2 不可用,将 k8s-node2 上的 Pod 标记为 Unknown
状态,并在 k8s-node1 上新创建两个 Pod,维持总副本数为 3。
当 k8s-node2 恢复后,Unknown
的 Pod 会被删除,不过已经运行的 Pod 不会重新调度回 k8s-node2。
删除 nginx-deployment
:
标签
默认配置下,Scheduler 会将 Pod 调度到所有可用的 Node。不过有些情况我们希望将 Pod 部署到指定的 Node,比如将有大量磁盘 I/O 的 Pod 部署到配置了 SSD 的 Node;或者 Pod 需要 GPU,需要运行在配置了 GPU 的节点上。
Kubernetes 是通过 label 来实现这个功能的。
label 是 key-value 对,各种资源都可以设置 label,灵活添加各种自定义属性。比如执行如下命令标注 node1 是配置了 SSD 的节点。
kubectl label node node1 disktype=ssd
然后通过 kubectl get node --show-labels
查看节点的 label。
[root@master ~]# kubectl label node node1 disktype=ssd
node/node1 labeled
[root@master ~]# kubectl get node --show-labels
NAME STATUS ROLES AGE VERSION LABELS
master Ready control-plane,master 24h v1.20.0 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=
node1 Ready node 24h v1.20.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=node1,kubernetes.io/os=linux,node-role.kubernetes.io/node=
node2 Ready node 24h v1.20.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node2,kubernetes.io/os=linux,node-role.kubernetes.io/node=
disktype=ssd
已经成功添加到 node1,除了 disktype
,Node 还有几个 Kubernetes 自己维护的 label。
有了 disktype
这个自定义 label,接下来就可以指定将 Pod 部署到 k8s-node1。编辑 nginx.yml:
root@master ~]# vi nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-app
spec:
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.17
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
nodeSelector:
disktype: ssd #添加标签SSD
在 Pod 模板的 spec
里通过 nodeSelector
指定将此 Pod 部署到具有 label disktype=ssd
的 Node 上。
部署 Deployment 并查看 Pod 的运行节点:
[root@master ~]# kubectl apply -f nginx.yaml
deployment.apps/nginx-app created
[root@master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-app-5856574766-9qlzc 1/1 Running 0 4s 10.244.1.13 node1 <none> <none>
nginx-app-5856574766-gvtrq 1/1 Running 0 4s 10.244.1.14 node1 <none> <none>
nginx-app-5856574766-r7r4x 1/1 Running 0 4s 10.244.1.15 node1 <none> <none>
全部 3个副本都运行在 node1 上,符合我们的预期。
要删除 label disktype
,执行如下命令:
kubectl label node node1 disktype-
-
即删除。
[root@master ~]# kubectl label node node1 disktype-
node/node1 labeled
[root@master ~]# kubectl get node --show-labels
NAME STATUS ROLES AGE VERSION LABELS
master Ready control-plane,master 24h v1.20.0 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=
node1 Ready node 24h v1.20.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node1,kubernetes.io/os=linux,node-role.kubernetes.io/node=
node2 Ready node 24h v1.20.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=node2,kubernetes.io/os=linux,node-role.kubernetes.io/node=
不过此时 Pod 并不会重新部署,依然在 k8s-node1 上运行。
[root@master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-app-5856574766-9qlzc 1/1 Running 0 9m21s 10.244.1.13 node1 <none> <none>
nginx-app-5856574766-gvtrq 1/1 Running 0 9m21s 10.244.1.14 node1 <none> <none>
nginx-app-5856574766-r7r4x 1/1 Running 0 9m21s 10.244.1.15 node1 <none> <none>
除非在 nginx.yml 中删除 nodeSelector
设置,然后通过 kubectl apply
重新部署。
[root@master ~]# vi nginx.yaml
[root@master ~]# kubectl apply -f nginx.yaml
deployment.apps/nginx-app configured
[root@master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-app-5856574766-9qlzc 1/1 Terminating 0 10m 10.244.1.13 node1 <none> <none>
nginx-app-5856574766-gvtrq 1/1 Running 0 10m 10.244.1.14 node1 <none> <none>
nginx-app-5856574766-r7r4x 0/1 Terminating 0 10m 10.244.1.15 node1 <none> <none>
nginx-app-7f4fc68488-9lbth 0/1 ContainerCreating 0 1s <none> node2 <none> <none>
nginx-app-7f4fc68488-m6kfq 1/1 Running 0 4s 10.244.2.23 node1 <none> <none>
nginx-app-7f4fc68488-qxkqh 1/1 Running 0 2s 10.244.2.24 node2 <none> <none>
Kubernetes 会删除之前的 Pod 并调度和运行新的 Pod。