Deployment
-
什么是Deployment
用户可以通过再Deployment中描述所期望的集群状态,将现在的集群状态再一个可控的速度下逐步更新成所期望的集群状态。与Replication Controller基本一样,deployment的主要职责同样时保证Pod的数量和健康。
与Replication Controller相比,除了继承Replication Controller的全部功能之外,deployment还有以下新的特性。- 事件和状态查看:可以查看deployment升级的详细进度和状态。
- 回滚:当升级pod镜像或相关参数的时候发现问题,可以使用回滚操作回退到上一个稳定的版本或者指定的版本。
- 版本记录:每次对deployment的操作都能保存下来,以备后续可能的回滚操作。
- 暂停和启动:每次升级,都能够随时暂停和启动。
- 多种升级方案:主要包括重建,即删除所有已存在的pod,重新创建新的pod;滚动升级,即采用逐步替换的策略,同时滚动升级时支持更多的附加参数。
-
Deployment与ReplicaSet
讲到ReplicaSet对象,不得不提到Replication Controller。在旧版本的Kubermetes中,只有
Replication Controller对象,它的主要作用是确保Pod以用户指定的副本数运行,即如果有容器异常退出,Replication Controller会自动创建新的Pod来替代,因异常情况而多出来的容器也会自动回收。可以说,通过Replication Controller,Kubernetes实现了集群的高可用性。
在Kubernetes 1.15后续版本中,建议使用ReplicaSet来取代Replication Controller. ReplicaSet跟Replication Controller没有本质的不同,只是名字不一样,并且ReplicaSet支持集合式的选择器,而Replication Controller只支持等式选择器。
虽然ReplicaSet也可以独立使用,但是Kubernetes并不建议用户直接操作ReplicaSet对象。而是通过更高层次的对象Deployment来自动管理ReplicaSet,这样就无须担心与其他机制不兼容的问题,比如ReplicaSet不支持滚动更新,但Deployment支持,并且Deployment还支持版本记录、回滚、暂停升级等高级特性。这意味着用户几乎不会有机会直接管理ReplicaSet。 -
运行Deployment
执行如下命令,结果如下:[root@master01 ~]# kubectl create deployment nginx-deployment --image=nginx:latest --replicas=3 deployment.apps/nginx-deployment created
在上面的命令中,nginx-deployment是指要创建额deployment的名称,–image选项用来指定容器所使用的镜像,replicas选项用来指定pod的副本数为3,即当前集群中任何时候都要保证有3个nginx副本在运行。
[root@master01 ~]# kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 4m10s
在上面的输出结果中,READY表示有多个个副本已就绪,UP-TO-DATE表示当前已处于新版本的pod副本数,主要用于在滚动升级的过程中,表示当前已经有多少个副本已经成功升级。AVAILABLE表示当前集群中存活的pod的数量。AGE表示当前deployment的年龄,即从创建到现在的时间差。
[root@master01 ~]# kubectl describe deployment Name: nginx-deployment Namespace: default //表示当前deployment所属的命名空间为default,即默认的命名空间 CreationTimestamp: Mon, 14 Jul 2025 09:20:12 +0800 Labels: app=nginx-deployment Annotations: deployment.kubernetes.io/revision: 1 Selector: app=nginx-deployment Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 25% max unavailable, 25% max surge Pod Template: Labels: app=nginx-deployment Containers: nginx: Image: nginx:latest Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> Conditions: Type Status Reason ---- ------ ------ Available True MinimumReplicasAvailable Progressing True NewReplicaSetAvailable OldReplicaSets: <none> NewReplicaSet: nginx-deployment-7fd6754bf7 (3/3 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 8m12s deployment-controller Scaled up replica set nginx-deployment-7fd6754bf7 to 3
前面已经介绍过ReplicaSet是一个非常重要的概念,而且用户几乎不会直接操作它,而是通过deployment间接管理。
使用get replicaset命令来查看replicaset的信息,如下所示:[root@master01 ~]# kubectl get replicaset NAME DESIRED CURRENT READY AGE nginx-deployment-7fd6754bf7 3 3 3 12m
使用describe replicaset命令来查看详细信息,如下所示:
[root@master01 ~]# kubectl describe replicaset nginx-deployment-7fd6754bf7 Name: nginx-deployment-7fd6754bf7 Namespace: default Selector: app=nginx-deployment,pod-template-hash=7fd6754bf7 Labels: app=nginx-deployment pod-template-hash=7fd6754bf7 Annotations: deployment.kubernetes.io/desired-replicas: 3 deployment.kubernetes.io/max-replicas: 4 deployment.kubernetes.io/revision: 1 Controlled By: Deployment/nginx-deployment Replicas: 3 current / 3 desired Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed Pod Template: Labels: app=nginx-deployment pod-template-hash=7fd6754bf7 Containers: nginx: Image: nginx:latest Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfulCreate 14m replicaset-controller Created pod: nginx-deployment-7fd6754bf7-srdf5 Normal SuccessfulCreate 14m replicaset-controller Created pod: nginx-deployment-7fd6754bf7-pf6fm Normal SuccessfulCreate 14m replicaset-controller Created pod: nginx-deployment-7fd6754bf7-p8g9r
接下来,继续探讨deployment创建的pod。执行get pod命令,获取当前集群中pod的信息,如下所示:
[root@master01 ~]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-deployment-7fd6754bf7-p8g9r 1/1 Running 0 23m 10.244.1.9 node01 <none> <none> nginx-deployment-7fd6754bf7-pf6fm 1/1 Running 0 23m 10.244.0.5 master01 <none> <none> nginx-deployment-7fd6754bf7-srdf5 1/1 Running 0 23m 10.244.1.10 node01 <none> <none>
pod的命名规则也是deployment的名称以及ReplicaSet的名称作为前缀的。由此可见,在同一个节点上,可以同时运行一个pod的多个副本。
前面已经介绍过,k8s中的各种非要我有最终是由pod中的容器提供的。因此,了解pod以及容器是我们的最终目标。[root@master01 ~]# kubectl describe pod nginx-deployment-7fd6754bf7-pf6fm Name: nginx-deployment-7fd6754bf7-pf6fm Namespace: default Priority: 0 Node: master01/192.168.16.2 Start Time: Mon, 14 Jul 2025 09:20:12 +0800 Labels: app=nginx-deployment pod-template-hash=7fd6754bf7 Annotations: <none> Status: Running IP: 10.244.0.5 IPs: IP: 10.244.0.5 Controlled By: ReplicaSet/nginx-deployment-7fd6754bf7 Containers: nginx: Container ID: docker://5a13837b3a35cfc7f91d02d767a30f3ddac950611733526c37f877f50b9260a0 Image: nginx:latest Image ID: docker-pullable://nginx@sha256:93230cd54060f497430c7a120e2347894846a81b6a5dd2110f7362c5423b4abc Port: <none> Host Port: <none> State: Running Started: Mon, 14 Jul 2025 09:21:16 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-nfzfg (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: kube-api-access-nfzfg: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true QoS Class: BestEffort Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 30m default-scheduler Successfully assigned default/nginx-deployment-7fd6754bf7-pf6fm to master01 Normal Pulling 30m kubelet Pulling image "nginx:latest" Normal Pulled 28m kubelet Successfully pulled image "nginx:latest" in 1m2.206924502s Normal Created 28m kubelet Created container nginx Normal Started 28m kubelet Started container nginx
该命令的输出信息非常多,我们只需要关注其中的重要部分即可。Node表示当前的pod所处的节点。IP是k8s为当前pod副本分配的ip地址,用户可以通过该ip地址与pod通讯。containers表示当前pod中的容器的列表,在本例中,只有一个用户容器,其容器id为5a13837b3a35cfc7f91d02d767a30f3ddac950611733526c37f877f50b9260a0。Events为当前pod副本的日志信息,便于用户调试。接着,我们登录192.168.16.2这个节点,使用命令docker ps即可查看当前节点的容器列表:
[root@master01 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5a13837b3a35 nginx "/docker-entrypoint.…" 26 minutes ago Up 26 minutes k8s_nginx_nginx-deployment-7fd6754bf7-pf6fm_default_a7e65b93-c1bd-4796-98a4-813a63c653ac_0 dd04eea5055d registry.aliyuncs.com/google_containers/pause:3.6 "/pause" 27 minutes ago Up 27 minutes k8s_POD_nginx-deployment-7fd6754bf7-pf6fm_default_a7e65b93-c1bd-4796-98a4-813a63c653ac_0 30e38408f7c6 a4ca41631cc7 "/coredns -conf /etc…" 16 hours ago Up 16 hours k8s_coredns_coredns-6d8c4cb4d-5q29k_kube-system_2272e5e0-5c76-45ab-89d6-206d71461f51_0 63f8a14822b7 a4ca41631cc7 "/coredns -conf /etc…" 16 hours ago Up 16 hours k8s_coredns_coredns-6d8c4cb4d-mgrlk_kube-system_bae9caaf-111d-4035-b539-881d3482acf1_0 fc02bd29cd67 registry.aliyuncs.com/google_containers/pause:3.6 "/pause" 16 hours ago Up 16 hours k8s_POD_coredns-6d8c4cb4d-5q29k_kube-system_2272e5e0-5c76-45ab-89d6-206d71461f51_0 8454fcc3934e registry.aliyuncs.com/google_containers/pause:3.6 "/pause" 16 hours ago Up 16 hours k8s_POD_coredns-6d8c4cb4d-mgrlk_kube-system_bae9caaf-111d-4035-b539-881d3482acf1_0 3c1abe8c1733 60e169ce803f "/opt/bin/flanneld -…" 16 hours ago Up 16 hours k8s_kube-flannel_kube-flannel-ds-kfl7q_kube-flannel_b18bd94f-f1c2-4073-aab7-29a2aa05a31f_0 d474c4a7ab7b registry.aliyuncs.com/google_containers/pause:3.6 "/pause" 16 hours ago Up 16 hours k8s_POD_kube-flannel-ds-kfl7q_kube-flannel_b18bd94f-f1c2-4073-aab7-29a2aa05a31f_0
该节点上有2个容器由nginx-deployment创建的。每个pod中都存在一个名称为pause的根容器,这个根容器是k8s系统的一部分。
接下来,我们在节点上验证刚刚k8s创建的服务是否可用:
[root@master01 ~]# curl http://10.244.0.5 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
总结:首先,用户通过kubectl create命令创建一个deployment。接下来,deployment会自动根据用户指定的选项,主要是image,replicas等创建replicaset,最后由replicaset创建pod副本和容器。
-
使用配置文件
在使用kubectl命令创建资源时,需要提供较多的选项来限制资源的各种属性。为了便于迁移复用,一般通过配置文件来限制资源的各种属性。配置文件官方推荐的是yaml,当然也可以使用json。yaml是json的超集,任何有效的json文件都是一个有效的yaml文件。
yaml文件具有以下语法规范:- 区分英文字母大小写
- 使用缩进表示层级关系
- 缩进时不允许使用制表符,只允许使用空格
- 缩进的空格数码不重要,只要相同层级的元素左侧对齐即可
- #表示注释,从这个字符一直到行尾,都会被解析器忽略
yaml有两种比较重要的数据结构,分别为Map和List,用户只要掌握这两种数据结构就可以了。
apiVersion: v1 kind: Pod 等同于 { "apiVersion": "v1" "kind": "Pod" } ------------------------------------------------------ args - sleep - "1000" 等同于 { "args":["sleep","1000"] } ------------------------------------------------------- args - name: "xxxx1" age: 15 - name: "xxxx2" age: 16 等同于 { "args":[{"name":"xxxx1",age:'15'},{"name":"xxxx2",age:'16'}] }
apiVersion: apps/v1 kind: Deployment metadata: name: xxx # 修改为项目的名字 namespace: xxx# 修改为项目的组 labels: app: xxx # 修改为项目的名字 spec: replicas: 1 # 根据业务量调整pod的数量 selector: matchLabels: app: xxx # 修改为项目的名字 revisionHistoryLimit: 10 strategy: rollingUpdate: maxSurge: 20% maxUnavailable: 0 type: RollingUpdate template: metadata: labels: app: xxx # 修改成项目的名字 spec: restartPolicy: Always imagePullSecrets: - name: pulluser containers: - image: <IMAGE>:<IMAGE_TAG> name: lightai-rpa-server # 修改为项目的名字 imagePullPolicy: IfNotPresent ports: - containerPort: 9990 # 这个端口必须和Dockerfile暴露的一个样 readinessProbe: httpGet: path: /deploy/ready port: 9990 initialDelaySeconds: 10 periodSeconds: 10 livenessProbe: httpGet: path: /deploy/live port: 9990 initialDelaySeconds: 15 periodSeconds: 10 lifecycle: preStop: exec: command: ['/bin/sh', '-c', 'sleep 20'] volumeMounts: - name: host-time mountPath: /etc/localtime readOnly: true resources: limits: cpu: 2 # CPU限制为2个 memory: 4Gi # 内存限制4Gi requests: cpu: 100m # CPU要求1个 memory: 512Mi # 内存要求1Gi
注意:用户需要正确区分metadata和spec,前者表示deployment本身固有的属性,后者表示deployment内容的各项属性。
-
扩容和缩容
扩容和缩容是指在线增加或者减少pod的副本数量。- 更改资源配置文件,然后执行kubectl apply命令更新deployment
- 执行命令:kubectl scale deployment nginx-deployment --replicas=2
注意:缩容,之前创建的容器还是存在的。只有deployment被删除,相关容器才会删除。如果将副本缩容为0,这种情况下deployment不会被删除,只是可用副本数变成0.
-
故障转移
k8s支持故障转移,以保证集群中的各项服务的可用性。在k8s中,node节点可动态增加到k8s集群中,前提是这个节点已经正确安装、配置和启动kubelet和kube-proxy等关键进程。在默认情况下,k8s会向master节点注册自己。一旦node节点被纳入集群管理范围,k8s会定时向master节点会报自身情况,以及之前有哪些pod在运行等,这样master节点可以获知每个node节点的资源使用情况,并实现高效均衡的资源调度策略。如果node节点没有按时上报信息,就会被master节点判断为失联,node节点状态就会被标记为NotReady,随后master节点就会触发工作负载转移流程。 -
通过标签控制Pod的位置
在默认情况下,k8s会将pod调度到所有可用的node节点上,以达到负载均衡的目的。但是,在某些情况下,用户可能需要将一些特定功能的pod部署到指定的node节点上。例如,某些运行数据库的pod需要运行在内存大的node节点上,而某些执行存储功能的pod需要运行在磁盘I/O快的Node节点上。
在k8s中,可以通过标签功能来标记各种资源,不只是节点,其他的资源(例如deployment、replicaset等)也可以通过标签来标记。-
通过kubectl label node命令来设置节点的标签
kubectl label node 192.168.1.122 mem=large
-
通过资源配置文件的nodeSelector属性来对节点进行选择
-
-
删除Deployment
对于已经不再使用的deployment,用户可将其从系统中删除。kubectl delete deployment nginx-deployment
当deployment被删除之后,由该deployment创建的所有replicaset和pod都会被自动删除。
-
DaemonSet
deployment创建的pod副本会分布在各个节点上,每个节点都可能运行好几个副本。而 DaemonSet不同,通过它创建的pod只会运行在同一个节点上,并且最多只会有一个副本。
DaemonSet通常会用来创建一些系统性的pod,例如提供日志管理、存储或域名服务等。
Job
对于deployment,replicaset以及replication controller等类型的控制器而言,它们希望pod保持预期的数量,持久地运行下去,除非用户明确删除,否则这些对象一直存在,它们针对的是持久性任务,如web服务等。对于非持久性任务,任务完成后,pod需要结束运行,不需要继续保持在系统中,这个时候就要用到Job。
具体各位读者,参考下面这篇博客:https://blog.csdn.net/cuichongxin/article/details/120141577