8-还在用Replication Controller吗、不妨考虑Deployment
前言
系统升级(rollout)&回滚(rollback)
Replica Set
介绍Deployment
实操:通过kubectl操作Deployment对象
取得Deployment/Replication Set/Pod基本信息
总结
Q&A
参考链接
8-还在用Replication Controller吗、不妨考虑Deployment
前言
在前一天我们介绍到Replication Controller。如果读者看过 Replication Controller官方文件 ,可以看到官方在文件一开头就表示:
NOTE: A Deployment that configures a ReplicaSet is now the recommended way to set up replication.
正如昨天所提,虽然Replication Controller 看似帮我们解决了Pod Scaling的问题,然而在实际场景上的应用是不够的。
系统升级(rollout)&回滚(rollback)
若是回溯DevOps的历史,可以发现DevOps与Agile敏捷开发 可以说是密不可分,最早DevOps一词也是从Agile社区中被提出,如果读者对于这段历史有兴趣,不妨看看YouTube上的一段影片 The History of DevOps , 会更了解DevOps与Agile之间的关系。而在Agile社区中其中一个精神便是如何正确收集到使用者需求以及快速的回应,频繁的系统升级(Rollout)更是不可避免的。而对于运维人员,如何在频繁更新一个服务时做到每次都能zero downtime(无停机服务迁移)更是一大挑战。幸好,这些Kubernetes都帮我们做好了。
Kubernetes官方提供给我们Deployment 组件,不只能帮我们做到Pod Scaling,对于应用服务的rollout与rollback的支持也非常丰富。今天学习笔记内容如下:
认识 Replication Set
介绍Deployment
实操:通过kubectl操作Deployment对象&常用命令
小提醒: 今天的代码源码都可以在demo-Deployment上找到。
Replica Set
Replica Sets 可以说是进化版的 Replication Controller,与 Replication Controller最大的差异在于,Replica Sets 提供了更弹性的selector
。
以my-replica-sets.yaml为例:
不同于Replication Controller的selector只能用等于的符号表示,Replica Set的selector支持更多复杂的条件过滤。
apiVersion
如果kubectl的版本>= 1.9,则需使用app/v1;如果版本号是在1.9以前的话,则需使用apps/v1beta2
spec.selector.matchLabels
在ReplicaSet的selector里面提供了matchLabels,matchLabels的用法代表着等于(equivalent),代表Pod的labels必须与matchLabels中指定的值相同,才算符合提交。
spec.selector.matchExpressions
而matchExpressions的用法较为弹性,每一个条件主要由三个部分组成:key、operator、value。以my-replica-sets.yaml中叙述为例,我们指定pod的条件为 1) env必须为dev; 2) env不能为prod。而目前operator支持4种条件In、NotIn、Exists、以及DoesNotExits,更多关于matchExpression的使用可以参考官方文件。
ReplicaSet与上一篇提到的Replication Controller的kubectl命令相似,可以参考上一篇 ReplicationController学习笔记。
而在Kubernetes官方文件 中也提到,虽然ReplicaSet提供更弹性的selector,并不推荐开发者直接使用kubectl create等命令创建ReplicaSet对象,而是通过Deployment来创建新的ReplicaSet。
介绍Deployment
Deployment可以帮我们达成以下几件事情:
部署一个应用服务(application)
协助application升级到某个特定版本
服务升级过程中做到无停机服务迁移(zero downtime Deployment)
可以rollback到先前版本
以下,是我们今天会使用到的my-deployment.yaml
apiVersion: apps/v1beta2 # for kubectl versions >= 1.9.0 use apps/v1 kind: Deployment metadata: name: hello-deployment spec: replicas: 3 selector: matchLabels: app: my-deployment template: metadata: labels: app: my-deployment spec: containers: - name: my-pod image: testowner/docker-demo:latest ports: - containerPort: 3000
Deployment yaml文件的写法与ReplicaSet相似,如果kubectl的版本>=1.9,则需使用app/v1;如果版本号是在1.9以前的话,则需使用apps/v1beta2,可以用kubectl version查看目前的版本号:
由于笔者仍使用1.8的版本,所以apiVersion仍需使用 apps/v1beta2。
接着我们可以使用kubectl create命令来新建一个Deployment对象:
$ kubectl create -f ./my-deployment.yaml deployment "hello-deployment" created
用 kubectl get 查看Deployment与pod的状态:
可以发现Deployment已自动帮我们创建pod,且这个pod都带有app=my-deployment的label, 而在同时,Deployment也会自动帮我们创建一个 replication set来管理这些pod:
$ kubectl get rs NAME DESIRED CURRENT READY AGE hello-deployment-6577d8cc46 3 3 3 22m
实操:通过kubectl操作Deployment对象
在开始实操之前,想先分享几个常见的命令:
Deployment相关命令 | 命令功能 |
---|---|
kubectl get deployments | 取得目前Kubernetes中的deployments的详情 |
kubectl get rs | 取得目前Kubernetes中的Replication Set的详情 |
kubectl describe deploy <deployment-name> | 取得特定deployment的详细信息 |
kubectl set image deploy/ <deployment-name> <pod-name>: <image-path>: <version> | 将deployment管理的pod升级到特定image版本 |
kubectl edit deploy <deployment-name> | 编辑特定deployment物件 |
kubectl rollout status deploy <deployment-name> | 查询目前某deployment升级状况 |
kubectl rollout history deploy <deployment-name> | 查询目前某deployment升级的历史记录 |
kubectl rollout undo deploy <deployment-name> | 回滚Pod到先前一个版本 |
kubectl rollout undo deploy <deployment-name> --to-revision=n | 回滚Pod到某个特定版本 |
接下来,将会根据上面几个常用命令,在我们本地的环境中进行实际操作。
取得Deployment/Replication Set/Pod基本信息
相信眼尖的读者已经发现,若是要取得在Kubernetes的对象信息,都是通过kubectl get命令。如果想要看Kubernetes cluster中所有目前已被创建的对象,可以使用 kubectl get all一次取得所有信息。
若是对于命令还不太熟悉,也可以在终端机输入kubectl get,如此便能得到Kubernetes目前所有提供的组件类型以及每个组件类型支持的缩写格式。
$ kubectl get You must specify the type of resource to get. Valid resource types include: * all * certificatesigningrequests (aka 'csr') * clusterrolebindings ... * pods (aka 'po') ...
为了实操如何利用Deployment升级web app,笔者预先将先前demo用的web application v2版本上传到Docker Hub,在v2的版本中,收到request之后会回传Hello World! v2
而在上面,我们使用kubectl create创建好一个Deployment对象之后,我们可以先创建一个Service来测试是否我们创建的web app在正常运行。
$ kubectl expose deploy hello-deployment --type=NodePort --name=my-deployment-service service "my-deployment-service" exposed
创建好之后,我们可以通过minikube server取得目前my-deployment-service的访问地址:
$ minikube service my-deployment-service --url http://192.168.99.100:30390
接着我们可以在本机的浏览器访问 http://192.168.99.100:30390
可以看到webapp正常运行中。接着我们可以通过docker set image来rollout我们的web app:
$ kubectl set image deploy/hello-deployment my-pod=zxcvbnius/docker-demo:v2.0.0 deployment "hello-deployment" image updated
这时我们也可以使用 kubectl rollout status来查询目前升级的状态:
$ kubectl rollout status deploy hello-deployment deployment "hello-deployment" successfully rolled out
可以看到Deployment hello-deployment已成功升级完成。
如果再重新访问一次 http://192.168.99.100:30390,可以看到浏览器的页面变成 Hello World! v2 了!
如果在升级的过程中,查看kubectl get pod,会发现Deployment在升级web app时,并不会把原本的pod直接砍掉,而是会另外生成Pod来取代原本Pod,来达到无痛升级的需求(zero downtime)。也就是说,在我们的Kubernetes cluster中同时间会存在6个pod。
如果不想要同时间存在这么多Pod,我们可以在Deployment的配置文件中指定strategy.rollingUpdate.maxSurge的数量。在今日学习笔记中后半部分,会介绍如何设置maxSurge。
除了通过kubectl set image更新pod的image之外,我们也可以通过kubectl edit来进行更新,输入以下命令:
$ kubectl edit deploy hello-deployment
除了可以看到原先的我们设置的配置项之外,也会发现多了几个不一样的配置项:
strategy
Kubernetes为了让我们可以确保rollout的时候,按照我们所想的方式。所以在Deployment configuration中,有一个strategy的设定值,可以将我们希望的行为放在里面。
strategy.rollingUpdate.maxSurge
maxSurge可以是百分数,也可以是数字。代表在rollout的过程中,最多可以比原先指定的pod数量多出多少。好比原来replicas为3, maxSurge为1,代表在升级的过程中,Deployment顶多会多产生一个pod。
strategy.rollingUpdate.maxUnavailable
代表在升级过程中,可以容忍多少pod无法使用,如果maxSurge的数字非0的话,maxUnavailable的数字也不能为0.
最后,我们可以通过kubectl rollout history来查改Deployment过去rollout的历史记录:
可以看到过去hello-deployment总共经历2次的rollout。一次是我们第一次创建deployment的时候,一次是我们升级成v2版本的时候。而若是kubectl set image命令结尾加上--record, CHANGE-CAUSE可以记录我们每次rollout的命令。例如,我们希望将Pod“升级”到latest版本。
$ kubectl set image deploy/hello-deployment my-pod=zxcvbnius/docker-demo --record deployment "hello-deployment" image updated
可以看到CHANGE-CAUSE多了记录,之后如果我们想要revert到特定版本,也可以根据CHANGE-CAUSE来决定。
如果我们想要把目前版本rollback到上一版,我们可以使用kubectl rollout undo:
$ kubectl rollout undo deployment hello-deployment deployment "hello-deployment" rolled back
如果这时再去检查 kubectl rollout history,会发现多了一个版本:
$ kubectl rollout history deploy hello-deployment deployments "hello-deployment" REVISION CHANGE-CAUSE 1 <none> 3 kubectl set image deploy/hello-deployment my-pod=zxcvbnius/docker-demo --record=true 4 <none>
最后,要介绍的是如何rollback回到特定版本,以回滚到REVISION 3为例,可以使用一下命令:
$ kubectl rollout undo deploy hello-deployment --to-revision=3
在rollback成功之后,若是再次查询kubectl rollout history会发现又多了一个REVISION了。
总结
以上,即是今天学习笔记中想跟大家分享的deployment的部分。虽然今天的学习笔记无法分享deployment的其它用途,但光是rollup与rollback相信读者也可以感受到Deployment的强大。而在明天的学习笔记中,将会分享我们在过去几天中常提及的Kubernetes的组件-Service 。
如果对于A/B test有兴趣的朋友,可以参考官网提供的Canary Deployment ,相信会有不少的收获。
Q&A
依然欢迎大家给予建议与回复, 如果能够一键三连 点个赞给些鼓励也是很开心的 :)