文章目录
一、Deployment概述
Deployment在Pod和ReplicaSet之上,提供了一个声明式定义(declarative)方法,用来替代以前的ReplicationController来方便的管理应用。你只需要在Deployment对象中描述一个期望的状态,Deployment控制器就会按照一定的控制速率把实际状态改成期望状态。
扩展:声明式定义是指直接修改资源清单yaml文件,然后通过kubectl apply -f 资源清单yaml文件,就可以更改资源。
无状态服务:无状态服务不会在本地存储持久化数据.多个服务实例对于同一个用户请求的响应结果是完全一致的.这种多服务实例之间是没有依赖关系,比如web应用,在k8s控制器中动态启停无状态服务的pod并不会对其它的pod产生影响。
有状态服务:有状态服务需要在本地存储持久化数据,典型的是分布式数据库的应用,分布式节点实例之间有依赖的拓扑关系.比如,主从关系. 如果K8S停止分布式集群中任 一实例pod,就可能会导致数据丢失或者集群的crash。
通过定义一个Deployment控制器会创建一个新的ReplicaSet控制器,然后再通过ReplicaSet创建pod。一般来说,删除Deployment控制器,同时会删除Deployment控制器下对应的ReplicaSet控制器和pod资源。
注意:
1、Deployment是用来管理无状态应用的。
2、官方建议使用Deployment来管理pod,而不是使用ReplicaSet管理pod。主要原因是 Deployment对象拥有许多ReplicaSet没有的特性,例如滚动升级和回滚。
Deployment控制器是建立在rs之上的一个控制器,可以管理多个ReplicaSet,每次更新镜像版本,都会生成一个新的ReplicaSet,把旧的ReplicaSet替换掉,多个ReplicaSet同时存在,但是只有一个ReplicaSet运行。如下图所示:
典型的应用场景包括:
1、定义Deployment来创建Pod和ReplicaSet,使用Deployment来创建ReplicaSet。ReplicaSet在后台创建pod。检查启动状态,看它是成功还是失败。然后,通过更新Deployment的Pod.Template.Spec字段来声明Pod的新状态。这会创建一个新的ReplicaSet,Deployment会按照控制的速率将pod从旧的ReplicaSet移动到新d的ReplicaSet中。
2、如果当前状态不稳定,回滚到之前的Deployment revision。每次回滚都会更新Deployment的revision。
3、扩容Deployment以满足更高的负载。
4、暂停Deployment来应用PodTemplateSpec的多个修复,然后恢复上线。
5、根据Deployment的状态判断上线是否hang住了。
6、清除旧的不必要的ReplicaSet。
相关术语
Pod:每个Pod是一个或一组紧密相关的容器,每个Pod就像是一个独立的逻辑机器,拥有自己的IP、主机名、进程等,运行一个独立的应用程序,是K8S调度的基本单位。
ReplicationController:简称RC,旨在创建和管理一个Pod的多个副本(replicas)。当Pod副本数少于指定数目,RC就会启动运行新的Pod副本;多于指定数目,RC就会杀死多余的Pod副本。
ReplicaSet:是新一代的RC,其相比于RC,Pod选择器的表达能力更强,其选择器可匹配缺少某个标签或特定标签名的Pod。
二、Deployment工作原理
2.1、升级方式
k8s部署无状态应用后,若需要更新应用时,可以通过使用ReplicationController或ReplicaSet实现升级,主要有两种方式:
1、直接删除所有现有的pod,然后创建新的pod
2、先创建新的pod,再删除旧pod。这里面也有两种方式,一种是先等所有新pod都运行成功后,应用切换到新pod访问,一次性删除所有旧pod;另一种是滚动升级方式逐步新建pod代替旧pod。
2.2、更新策略
在Deployment中,可以通过spec.strategy指定Pod更新的策略,目前支持:Recreate(重建)和RollingUpdate(滚动更新),默认是RollingUpdate。
Recreate:设置spec.strategy.type=Recreate,更新方式为:Deployment在更新Pod时,会先杀掉所有正在运行的Pod,然后创建新的Pod。 简单的说就是重建式更新,删一个建一个。
RollingUpdate:设置spec.strategy.type=RollingUpdate,更新方式为:Deployment会以滚动的方式来渐变性的更新Pod,即Pod新版本的递增,旧版本的递减的一个过程。 简单的说就是滚动更新,定义更新期间pod最多有几个。
如下图所示:
2.3、滚动更新
“滚动”,给人的是一种“圆”的印象,持续,不中断的意思,类似于“持续交付”的理念。RollingUpdate策略指一次仅更新一个Pod,并且逐个更新,而不是一次性将所有的服务都关闭,避免业务中断。
如下图所示:
1、初始创建Deployment,系统创建了一个ReplicaSet,并按照用户的需求创建了3个Pod副本。
2、当更新Deployment时,系统创建一个新的ReplicaSet,并将其副本数量扩展到1,然后将旧的ReplicaSet缩减为2。
3、系统继续按照相同的更新策略对新旧两个ReplicaSet进行逐个调整。
4、最后,新的ReplicaSet运行了3个新版本的Pod副本,旧的ReplicaSet副本数量则缩减为0。
rollingUpdate有两种策略
maxSurge 指定超出副本数有几个,两种方式:第一种直接给定数量,第二种根据百分比,百分比表示原本是5个,最多可以超出20%,那就允许多一个,最多可以超过40%,那就允许多两个
maxUnavailable 最多有几个不可用,假设有5个副本,最多一个不可用,就表示最少有4个可用
如下图所示:
三、Deployment资源清单文件编写技巧
3.1、查看Deployment资源对象组成部分
[root@k8s-client-17 pkgs]# kubectl explain deployment
KIND: Deployment
VERSION: apps/v1
DESCRIPTION:
Deployment enables declarative updates for Pods and ReplicaSets.
FIELDS:
apiVersion <string> #该资源使用的api版本
kind <string> #创建的资源是什么
metadata <Object> #元数据,包括资源的名字和名称空间
spec <Object> #定义容器属性
status <Object> #状态,不可以修改
3.2、查看Deployment下的spec字段
[root@k8s-client-17 pkgs]# kubectl explain deployment.spec
KIND: Deployment
VERSION: apps/v1
RESOURCE: spec <Object>
DESCRIPTION:
Specification of the desired behavior of the Deployment.
DeploymentSpec is the specification of the desired behavior of the
Deployment.
FIELDS:
minReadySeconds <integer> #k8s在等待设置的时间后才进行升级,如果没有设置该值,k8s会假设该容器启动起来后就提供服务了
paused <boolean> #暂停,当我们更新的时候创建pod先暂停,不是立即更新
progressDeadlineSeconds <integer>#k8s在升级过程中有可能由于各种原因升级卡住(这个时候还没有明确的升级失败),比如在拉取被墙的镜像,权限不够等错误。那么这个时候就需要有个deadline ,在 deadline之内如果还卡着,那么就上报这个情况,这个时候这个Deployment 状态就被标记为 False,并且注明原因。但是它并不会阻止 Deployment 继续进行卡住后面的操作。完全由用户进行控制。 replicas <integer> #副本数
revisionHistoryLimit <integer> #保留的历史版本,默认是10
selector <Object> -required- #必须字段,标签选择器,选择它关联的pod
strategy <Object> #更新策略
template <Object> -required- #必须字段,定义的pod模板
3.3、查看Deployment下的spec.strategy字段
[root@k8s-client-17 pkgs]# kubectl explain deploy.spec.strategy
KIND: Deployment
VERSION: apps/v1
RESOURCE: strategy <Object>
DESCRIPTION:
The deployment strategy to use to replace existing pods with new ones.
DeploymentStrategy describes how to replace existing pods with new ones.
FIELDS:
rollingUpdate <Object>
Rolling update config params. Present only if DeploymentStrategyType =
RollingUpdate.
type <string>
Type of deployment. Can be "Recreate" or "RollingUpdate". Default is
RollingUpdate.
支持两种更新,Recreate和RollingUpdate
1、Recreate是重建式更新,删除一个更新一个。
2、RollingUpdate滚动更新,定义滚动更新方式,也就是pod能多几个,少几个。
3.4、查看Deployment下的spec.strategy.rollingUpdate字段
[root@k8s-client-17 pkgs]# kubectl explain deploy.spec.strategy.rollingUpdate
KIND: Deployment
VERSION: apps/v1
RESOURCE: rollingUpdate <Object>
DESCRIPTION:
Rolling update config params. Present only if DeploymentStrategyType =
RollingUpdate.
Spec to control the desired behavior of rolling update.
FIELDS:
maxSurge <string> #更新的过程当中最多允许超出的指定的目标副本数有几个;它有两种取值方式,第一种直接给定数量,第二种根据百分比,百分比表示原本是5个,如果最多可以超出20%,那就允许多一个,如果最多可以超过40%,那就允许多两个
maxUnavailable <string> #最多允许几个不可用
3.5、查看Deployment下的spec.template字段
[root@k8s-client-17 pkgs]# kubectl explain deploy.spec.template
KIND: Deployment
VERSION: apps/v1
RESOURCE: template <Object>
DESCRIPTION:
Template describes the pods that will be created.
PodTemplateSpec describes the data a pod should have when created from a
template
FIELDS:
metadata <Object> #为Pod定义的模板,和Pod定义不太一样,template中不包含apiVersion和Kind属性,要求必须有metadata
spec <Object> #容器的属性信息,其他定义内容和Pod一致
3.6、查看Deployment下的spec.template.spec字段
[root@k8s-client-17 pkgs]# kubectl explain deploy.spec.template.spec
KIND: Deployment
VERSION: apps/v1
RESOURCE: spec <Object>
DESCRIPTION:
Specification of the desired behavior of the pod. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
PodSpec is a description of a pod.
FIELDS:
activeDeadlineSeconds <integer> #activeDeadlineSeconds表示Pod可以运行的最长时间,达到设置的该值后,Pod会自动停止。
affinity <Object> #定义亲和性,跟直接创建pod时候定义亲和性类似
automountServiceAccountToken <boolean> #身份认证相关的
containers <[]Object> -required- #必须字段,对象列表,定义容器属性
dnsConfig <Object> #设置Pod的DNS
dnsConfig:
nameservers:
- 192.xxx.xxx.6
searches:
- xianchao.svc.cluster.local
- my.dns.search.xianchao
dnsPolicy <string> #dnsPolicy决定Pod内预设的DNS配置策略
None 无任何策略:使用自定义的策略
Default 默认:使用宿主机的dns配置,/etc/resolv.conf
ClusterFirst 集群DNS优先,与 Default 相反,会预先使用 kube-dns (或 CoreDNS ) 的信息当预设置参数写入到该 Pod 内的DNS配置。
ClusterFirstWithHostNet 集群 DNS 优先,并伴随着使用宿主机网络:同时使用 hostNetwork 与 kube-dns 作为 Pod 预设 DNS 配置。
enableServiceLinks <boolean>
ephemeralContainers <[]Object> #定义临时容器
临时容器与其他容器的不同之处在于,它们缺少对资源或执行的保证,并且永远不会自动重启,因此不适用于构建应用程序。临时容器使用与常规容器相同的 ContainerSpec 段进行描述,但许多字段是不相容且不允许的。
临时容器没有端口配置,因此像 ports,livenessProbe,readinessProbe 这样的字段是不允许的。
Pod资源分配是不可变的,因此 resources 配置是不允许的。
临时容器用途:当由于容器崩溃或容器镜像不包含调试应用程序而导致 kubectl exec 无用时,临时容器对于交互式故障排查很有用。
hostAliases <[]Object> #在pod中增加域名解析的
hostAliases:
– ip: "10.1.2.2"
hostnames:
– "mc.local"
– "rabbitmq.local"
– ip: "10.1.2.3"
hostnames:
– "redis.local"
– "mq.local"
hostIPC <boolean> #使用主机IPC
hostNetwork <boolean> #是否使用宿主机的网络
hostPID <boolean> #可以设置容器里是否可以看到宿主机上的进程。True可以
hostname <string>
imagePullSecrets <[]Object>
initContainers <[]Object> #定义初始化容器
nodeName <string> #定义pod调度到具体哪个节点上
nodeSelector <map[string]string> #定义节点选择器
overhead <map[string]string> #overhead是1.16引入的字段,在没有引入Overhead 之前,只要一个节点的资源可用量大于等于 Pod 的requests 时,这个Pod就可以被调度到这个节点上。引入Overhead之后,只有节点的资源可用量大于等于Overhead加上 requests 的和时才能被调度上来。
preemptionPolicy <string>
priority <integer>
priorityClassName <string>
readinessGates <[]Object>
restartPolicy <string> #Pod重启策略
runtimeClassName <string>
schedulerName <string>
securityContext <Object> #是否开启特权模式
serviceAccount <string>
serviceAccountName <string>
setHostnameAsFQDN <boolean>
shareProcessNamespace <boolean>
subdomain <string>
terminationGracePeriodSeconds <integer> #在真正删除容器之前,K8S会先发终止信号(kill -15 {pid})给容器,默认30s
tolerations <[]Object> #定义容忍度
topologySpreadConstraints <[]Object>
volumes <[]Object> #挂载存储卷
四、Deployment基本命令
如下所示:
#创建deployment
1、基于模板创建
kubectl create -f nginx-deployment.yaml
#删除deployment
1、基于模板删除
kubectl delete -f nginx-deployment.yaml
2、基于名称删除
kubectl delete deployment nginx-deployment
#更新deployment
1、基于模板更新
kubectl apply -f nginx-deployment.yaml
2、基于名称更新
kubectl edit deploy/nginx-deployment
#查看deployment
1、基于模板查看
kubectl get deploy nginx-deployment -o yaml
2、基于名称查看
kubectl describe deployments nginx-deployment
3、查看列表
kubectl get deploy
五、Deployment使用案例
下面是 Deployment 示例。其中创建了一个 ReplicaSet,负责启动三个nginx Pods
vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
deployment是一个三级结构,deployment管理replicaset,replicaset管理pod,通过运行以下命令创建Deployment
[root@k8s-client-17 yaml]# kubectl create -f nginx-deployment.yaml
Deployment信息
[root@k8s-client-17 yaml]# kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 110s
字段解释:
1.NAME :列出名称空间中deployment的名称。
2.READY:显示deployment有多少副本数。它遵循ready/desired的模式。
3.UP-TO-DATE: 显示已更新到所需状态的副本数。
4.AVAILABLE: 显示可以使用多少个应用程序副本数量。
5.AGE :显示应用程序已运行的时间。
ReplicaSet信息
[root@k8s-client-17 yaml]# kubectl get replicasets
NAME DESIRED CURRENT READY AGE
nginx-deployment-66b6c48dd5 3 3 3 2m3s
字段解释:
1.NAME: 列出名称空间中ReplicaSet资源
2.DESIRED:显示应用程序的所需副本数,这些副本数是在创建时定义的。这是所需的状态。
3.CURRENT: 显示当前正在运行多少个副本。
4.READY: 显示用户可以使用多少个应用程序副本数量。
5.AGE :显示应用程序已运行的时间。
说明:ReplicaSet的命名和Deployment是相关的,ReplicaSet命名是以Deployment名为前缀,在Deployment名字基础上又加了一串随机数。
Pods信息
[root@k8s-client-17 yaml]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-66b6c48dd5-2z7l2 1/1 Running 0 2m6s
nginx-deployment-66b6c48dd5-7g7mh 1/1 Running 0 2m6s
nginx-deployment-66b6c48dd5-s24tp 1/1 Running 0 2m6s
说明:pod名称以Deployment中的ReplicaSet名称为前缀,在此基础上又加了随机字符串。
六、Deployment管理pod
6.1、扩容
通过deployment管理应用,实现扩容,把副本数变成4
[root@k8s-client-17 yaml]# cat nginx-deployment.yaml
直接修改replicas数量,如下,变成4
spec:
replicas: 4
修改之后保存退出,执行
[root@k8s-client-17 yaml]# kubectl apply -f nginx-deployment.yaml
注意:apply不同于create,apply可以执行多次;create只能执行一次,再执行就会报错。
上面可以看到pod副本数变成了4个,查看nginx-deployment这个控制器的详细信息,如下图所示:
6.2、缩容
通过deployment管理应用,实现缩容,把副本数变成2
[root@k8s-client-17 yaml]# cat nginx-deployment.yaml
直接修改replicas数量,如下,变成2
spec:
replicas: 2
修改之后保存退出,执行
[root@k8s-client-17 yaml]# kubectl apply -f nginx-deployment.yaml
注意:apply不同于create,apply可以执行多次;create只能执行一次,再执行就会报错。
上面可以看到pod副本数变成了2个,查看nginx-deployment这个控制器的详细信息,如下图所示:
6.3、滚动更新
通过deployment管理应用,实现滚动更新,把nginx镜像版本由1.14.2修改为1.16.1。
#将image: nginx:1.14.2修改为image: nginx:1.16.1
[root@k8s-client-17 yaml]# cat nginx-deployment.yaml
image: nginx:1.16.1
修改之后保存退出,执行
[root@k8s-client-17 yaml]# kubectl apply -f nginx-deployment.yaml
pending表示正在进行调度,ContainerCreating表示正在创建一个pod,running表示运行一个pod,running起来一个pod之后再Terminating(停掉)一个pod,以此类推,直到所有pod完成滚动升级。简单的说停止一台,升级一台。
如下图可以看到rs有两个,下面那个是升级之前的,已经被停掉,但是可以随时回滚。
6.4、回滚
查看现在有几个版本
[root@k8s-client-17 yaml]# kubectl rollout history deployment nginx-deployment
如下图所示:
#默认回滚上一版,可以通过 --to-revision指定版本
[root@k8s-client-17 yaml]# kubectl rollout undo deployment nginx-deployment
或
[root@k8s-client-17 yaml]# kubectl rollout undo deployment nginx-deployment --to-revision=1
如下图所示:
七、Deployment资源清单详解
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 4
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.16.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
livenessProbe: #存活性探测,用于判断容器是否存活,即Pod是否为running状态,如果LivenessProbe探针探测到容器不健康,则kubelet将kill掉容器,并根据容器的重启策略是否重启。如果一个容器不包含LivenessProbe探针,则Kubelet认为容器的LivenessProbe探针的返回值永远成功。
tcpSocket:
port: 80 #检测80端口是否存在
initialDelaySeconds: 60 #Pod启动60s执行第一次检查
periodSeconds: 10 #第一次检查后每隔10s检查一次
readinessProbe: #就绪性探测,有时候应用程序可能暂时无法接受请求,比如Pod已经Running了,但是容器内应用程序尚未启动成功,在这种情况下,如果没有ReadinessProbe,则Kubernetes认为它可以处理请求了,然而此时,我们知道程序还没启动成功是不能接收用户请求的,所以不希望kubernetes把请求调度给它,则使用ReadinessProbe探针。
tcpSocket:
port: 80
initialDelaySeconds: 60
periodSeconds: 10
ReadinessProbe和livenessProbe可以使用相同探测方式,只是对Pod的处置方式不同,ReadinessProbe是将Pod IP:Port从对应的EndPoint列表中删除,而livenessProbe则Kill容器并根据Pod的重启策略来决定作出对应的措施。ReadinessProbe探针探测容器是否已准备就绪,如果未准备就绪则kubernetes不会将流量转发给此Pod。
八、kubernetes项目部署
8.1、重新部署
重新部署
定义:先停止旧服务,然后启动新服务,这是最简单的一种部署方式
缺点:在整个过程中会出现一段时间的服务不可用。
8.2、蓝绿部署
蓝绿部署
定义:蓝绿部署就是不停止旧版本,直接部署新版本然后进行测试,测试验证OK后,将流量全部切换到新版本,同时将旧版本也升级到新版本(或者可以将旧版本直接停掉)
优点: 无需停机,风险较小
缺点: 切换是全量的,如果版本2有问题,则对用户体验有直接影响, 需要双倍机器资源。
8.3、金丝雀部署(灰度部署)
金丝雀部署(灰度部署)
定义 : 灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式。
AB Test就是一种灰度发布方式,让部分用户继续使用A版本,一部分用户开始用B版本,如果用户对新版本没有什么意见反馈,那么逐步扩大范围,把所有用户都迁移到新版本上面来(A/B Test主要是用来测试应用功能表现,例如可用性、受欢迎程度、可见性等)。
灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度,而我们平常所说的金丝雀部署就是灰度发布的一种方式。
部署过程:
准备好部署各个阶段的工件
从负载均衡列表中移除掉“金丝雀”服务器。
升级“金丝雀”应用(排掉原有流量并进行部署)。
对应用进行自动化测试。
将“金丝雀”服务器重新添加到负载均衡列表中(连通性和健康检查)。
如果“金丝雀”在线使用测试成功,升级剩余的其他服务器。(否则就回滚)
优点: 用户体验影响小,灰度发布过程出现问题只影响部分用户。
实例一:
vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 4
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
livenessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe:
tcpSocket:
port: 80
initialDelaySeconds: 60
periodSeconds: 10
过set image发布新的镜像,也可以通过yaml文件发布,nginx是containers 的名称
kubectl set image deploy nginx-deployment nginx=nginx:1.16.1
kubectl rollout pause deploy nginx-deployment
查看更新情况(新增加一个资源,但是没执行。是因为pause暂停命令,所以就只发布一个,这样形成了金丝雀发布,这个金丝雀就是让真实用户验证的)
金丝雀没问题,可以发布后续的更新了
kubectl get pods -w
kubectl rollout resume deploy nginx-deployment
如下图所示:
最终全部更新完之后,pod副本数还是4,rs控制器也变成了新的控制器,旧的rs控制器不适用,便于后期回滚操作。
8.4、滚动更新
滚动更新
定义:一般是取出一个或者多个服务器停止服务,更新版本后重新将其投入使用。周而复始,直到集群中所有的实例都更新成新版本。
这种部署方式相对于蓝绿部署,更加节约资源——它不需要运行两个集群、两倍的实例数。我们可以部分部署,例如每次只取出集群的25%进行升级。
总结:整理不易,如果对你有帮助,可否点赞关注一下?
更多详细内容请参考:企业级K8s集群运维实战