Kubernetes通过各种Controller来管理Pod的生命周期 。 为了满足不同业 务 景 , Kubernetes 开发了Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job等多种Controller。我们⾸先学习最常用Deployment。
1.1 Kubectl命令直接创建
第一种是通过kubectl命令直接创建:
kubectl run nginx-deployment --image=nginx:1.7.9 --replicas=2
在最新的 Kubernetes 版本中,kubectl create deployment 命令不再直接支持 --replicas 参数。副本数的指定现在通常是通过 kubectl scale 命令来完成。
kubectl create deployment nginx-deployment --image=nginx:1.7.9
#使用 kubectl scale 命令设置副本数:
kubectl scale deployment nginx-deployment --replicas=2
这样我们就部署了一个具有2个副本的nginx-deployment 。
1.2 YAML配置文件创建
第二种是通过配置文件+kubectl apply(kubectl create也可以)创建:
vi nginx.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: web_server
template:
metadata:
labels:
app: web_server
spec:
containers:
- name: nginx
image: nginx:1.7.9
kubectl apply -f nginx.yml
[root@k8s-master kubernetes]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
busybox 2/2 2 2 32m
nginx-deployment 2/2 2 2 6m7s
1.3 删除deployment
kubectl delete deployment nginx-deployment
执行之后,K8S会自动帮我们删除相关Deployment、ReplicaSet(副本集)以及Pod。
1.4 Deployment配置⽂件简介
既然 用YAML配置文件 署应用 , 现在就很有必要了解⼀下Deployment的配置格式了,其他Controller(比如DaemonSet)非常类似。
vi nginx-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: web_server
template:
metadata:
labels:
app: web_server
spec:
containers:
- name: nginx
image: nginx:1.7.9
这是一个Kubernetes Deployment的YAML文件,用于定义一个NGINX容器的部署。以下是每一行的解释:
-
apiVersion: apps/v1
: 指定使用的 Kubernetes API 版本,这里是 Apps API 的版本。 -
kind: Deployment
: 定义资源对象的类型,这是一个 Deployment 对象,用于在集群中管理 Pod 的部署。 -
metadata
: 定义 Deployment 元数据,包括资源的名称。 -
name: nginx-deployment
: 指定 Deployment 的名称为 “nginx-deployment”。 -
spec
: 定义 Deployment 的规范,包括副本数、选择器和模板。 -
replicas: 2
: 指定要创建的 Pod 副本数为 2,表示要在集群中运行两个相同的 NGINX Pod。 -
selector
: 定义标签选择器,用于选择属于该 Deployment 的 Pod。 -
matchLabels
: 指定 Pod 必须具有哪些标签以匹配该 Deployment 的选择器。 -
app: web_server
: 指定标签 “app” 的值必须为 “web_server”,用于匹配 Pod。 -
template
: 定义要创建的 Pod 的模板。 -
metadata
: 定义 Pod 模板的元数据,包括标签。 -
labels
: 指定 Pod 的标签,这里设置 “app” 标签的值为 “web_server”。 -
spec
: 定义 Pod 的规范,包括容器。 -
containers
: 定义 Pod 中运行的容器的列表。 -
- name: nginx
: 定义容器的名称为 “nginx”。 -
image: nginx:1.7.9
: 指定要使用的 NGINX 镜像及其版本。
因此,这个 YAML 文件描述了一个名为 “nginx-deployment” 的 Deployment,该 Deployment 负责管理两个运行 NGINX 容器的 Pod,并且这些 Pod 必须具有标签 “app: web_server”。容器使用 NGINX 1.7.9 版本的镜像。
1.5伸缩
伸缩是指在线增加或减少Pod的副本数。Deployment nginx-deployment初始是两个副本。
[root@k8s-master kubernetes]# kubectl get deployment nginx-deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 2/2 2 2 21s
现在修改nginx.yml⽂件,将副本改成5个
spec:
replicas: 5
执行kubectl apply -f nginx-deployment.yml
[root@k8s-master kubernetes]# kubectl get deployment nginx-deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 5/5 5 5 114s
1.6 Failover
下⾯我们模拟k8s-node2故障,关闭该节点,编辑yml文件恢复到3个节点。
[root@k8s-node2 ~]# halt -h
[root@k8s-master kubernetes]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready master 57m v1.18.0
k8s-node1 Ready <none> 56m v1.18.0
k8s-node2 NotReady <none> 56m v1.18.
查看pod(可能需要等待一会)
[root@k8s-master kubernetes]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-79c457c54b-js27q 1/1 Terminating 1 17m 10.244.2.10 k8s-node2 <none> <none>
nginx-deployment-79c457c54b-r297k 1/1 Running 0 3m2s 10.244.1.11 k8s-node1 <none> <none>
nginx-deployment-79c457c54b-vvvhr 1/1 Terminating 1 15m 10.244.2.9 k8s-node2 <none> <none>
nginx-deployment-79c457c54b-whsp8 1/1 Running 0 17m 10.244.1.6 k8s-node1 <none> <none>
nginx-deployment-79c457c54b-z5n54 1/1 Running 0 3m2s 10.244.1.12 k8s-node1 <none> <none>
k8s-node2上的Pod最终标记为Terminating状态,并在k8s-node1上新建两个Pod,维持副本总数量为3。
当k8s-node2恢复后,Terminating的Pod会自动被删除,不过已经运行在k8s-node1的Pod是不会重新调度回k8s-node2的。
1.7用label控制Pod位置
默认情况下,K8S的Scheduler会均衡调度Pod到所有可用的Node节点,但是有些时候希望将指定的Pod部署到指定的Node节点。例如,一个I/O密集型的Pod可以尽量部署在配置了SSD的Node节点,又或者一个需要GPU的Pod可以尽量部署在配置了GPU的Node节点上。
不用担心,K8S为我们提供了label来实现这个功能,label是一个key/value对,可以灵活设置各种自定义的属性。比如,我们这里假设我们的k8s-demo示例项目是一个I/O密集型的API,还假设k8s-node1是一个配置了SSD的Node节点:
kubectl label node k8s-node1 disktype=ssd
kubectl get node --show-labels=true
修改yml文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 2
selector:
matchLabels:
app: web_server
template:
metadata:
labels:
app: web_server
spec:
containers:
- name: nginx
image: nginx:1.7.9
nodeSelector:
disktype: ssd
然后,再次apply创建资源:
kubectl apply -f nginx-deployment.yml
验证一下,所有的k8s-demo的Pod全都调度到了k8s-node1上面,符合预期:
[root@k8s-master kubernetes]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-744c4bcdf6-4bzgh 1/1 Running 0 37s 10.244.1.13 k8s-node1 <none> <none>
nginx-deployment-744c4bcdf6-b5t2f 1/1 Running 0 36s 10.244.1.14 k8s-node1 <none> <none>
nginx-deployment-744c4bcdf6-ch65k 1/1 Running 0 35s 10.244.1.15 k8s-node1 <none> <none>