Replicaset控制器:概念、原理解读Replicaset概述Pod副本。官方推荐不要直接使用ReplicaSet,用Deployments取而代之,Deployments是比ReplicaSet更高级的概念,它会管理ReplicaSet并提供很多其它有用的特性,最重要的是Deployments支持声明式更新,声明式更新的好处是不会丢失历史变更。所以Deployment控制器不直接管理Pod对象,而是由 Deployment 管理ReplicaSet,再由ReplicaSet负责管理Pod对象。Replicaset工作原理:如何管理Pod?起到多退少补的作用,并且还具有自动扩容缩容等机制。Replicaset控制器主要由三个部分组成:1、用户期望的pod副本数:用来定义由这个控制器管控的pod副本有几个2、标签选择器:选定哪些pod是自己管理的,如果通过标签选择器选到的pod副本数量少于我们指定的数量,需要用到下面的组件3、pod资源模板:如果集群中现存的pod数量不够我们定义的副本中期望的数量怎么办,需要新建pod,这就需要pod模板,新建的pod是基于模板来创建的。Replicaset资源清单文件编写技巧#查看定义Replicaset资源需要的字段有哪些?~]# kubectl explain rsKIND: ReplicaSetVERSION: apps/v1DESCRIPTION:ReplicaSet ensures that a specified number of pod replicas are running atany given time.FIELDS:apiVersion <string> #当前资源使用的api版本,跟VERSION: apps/v1保持一致kind <string> #资源类型,跟KIND: ReplicaSet保持一致metadata <Object> #元数据,定义Replicaset名字的spec <Object> #定义容器的status <Object> #状态信息,不能改#查看replicaset的spec字段如何定义?~]# kubectl explain rs.specKIND: ReplicaSetVERSION: apps/v1RESOURCE: spec <Object>DESCRIPTION:Spec defines the specification of the desired behavior of the ReplicaSet.More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-statusReplicaSetSpec is the specification of a ReplicaSet.FIELDS:minReadySeconds <integer>replicas <integer> #定义的pod副本数,根据我们指定的值创建对应数量的podselector <Object> -required- #用于匹配pod的标签选择器template <Object> #定义Pod的模板,基于这个模板定义的所有pod是一样的#查看replicaset的spec.template字段如何定义?#对于template而言,其内部定义的就是pod,pod模板是一个独立的对象~]# kubectl explain rs.spec.templateKIND: ReplicaSetVERSION: apps/v1RESOURCE: template <Object>DESCRIPTION:Template is the object that describes the pod that will be created ifinsufficient replicas are detected。PodTemplateSpec describes the data a pod should have when created from atemplateFIELDS:metadata <Object>spec <Object>.spec.template里的内容是声明Pod对象时要定义的各种属性,所以这部分也叫做PodTemplate(Pod模板)。还有一个值得注意的地方是:在.spec.selector中定义的标签选择器必须能够匹配到spec.template.metadata.labels里定义的Pod标签,否则Kubernetes将不允许创建ReplicaSet。实战1:Replicaset使用案例:部署Guestbook留言板#把frontend.tar.gz上传到node2和node1上,解压docker load -i frontend.tar.gzdocker load -i frontend.tar.gz#编写一个ReplicaSet资源清单[root@master1 ~]# cat replicaset.yaml~]# kubectl apply -f replicaset.yamlcreated~]# kubectl get rsNAME DESIRED CURRENT READY AGEfrontend 3 3 3 53m~]# kubectl get podsNAME READY STATUS RESTARTS AGE1/1 Running 0 36m1/1 Running 0 36m1/1 Running 0 36m#pod的名字是由控制器的名字-随机数组成的#资源清单详细说明apiVersion: apps/v1 #ReplicaSet 这个控制器属于的核心群组kind: ReplicaSet #创建的资源类型metadata:name: frontend #控制器的名字labels:app: guestbooktier: frontendspec:replicas: 3 #管理的pod副本数量selector:matchLabels:tier: frontend #管理带有tier=frontend标签的podtemplate: #定义pod的模板metadata:labels:tier: frontend#pod标签,一定要有,这样上面控制器就能找到它要管理的pod是哪些了spec:containers: #定义pod里运行的容器name: php-redis #定义容器的名字image: yecc/gcr.io-google_samples-gb-frontend:v3ports: #定义端口name: http #定义容器的名字containerPort: 80 #定义容器暴露的端口
实战2:Replicaset管理pod:扩容、缩容、更新
#Replicaset实现pod的动态扩容: 3,现在变成replicaset: 4,修改之后,执行如下命令更新:~]# kubectl apply -f replicaset.yamlconfigured~]# kubectl get rsNAME DESIRED CURRENT READY AGEfrontend 4 4 4 62m~]# kubectl get podsNAME READY STATUS RESTARTS AGE1/1 Running 0 62m1/1 Running 0 62m1/1 Running 0 33s1/1 Running 0 62m#也可以直接编辑控制器实现扩容kubectl edit rs frontend #这个是我们把请求提交给了apiserver,实时修改~]# kubectl edit rs frontend后面的值改成5,保存退出~]# kubectl get rsNAME DESIRED CURRENT READY AGEfrontend 5 5 5 67m~]# kubectl get podsNAME READY STATUS RESTARTS AGE1/1 Running 0 67m1/1 Running 0 67m1/1 Running 0 5m6s1/1 Running 0 67m1/1 Running 0 13s#Replicaset实现pod的动态缩容: 2,修改之后,执行如下命令更新:~]# kubectl apply -f replicaset.yamlconfigured~]# kubectl get rsNAME DESIRED CURRENT READY AGEfrontend 2 2 2 70m~]# kubectl get podsNAME READY STATUS RESTARTS AGE1/1 Running 0 70m1/1 Running 0 70m#Replicaset实现pod的更新~]# kubectl edit rs frontend#修改镜像image: yecc/gcr.io-google_samples-gb-frontend:v3变成- image: ikubernetes/myapp:v2,修改之后保存退出~]# kubectl get rs -o wide~]# kubectl get rs -o wideNAME DESIRED CURRENT READY IMAGESfrontend 2 2 2 ikubernetes/myapp:v2#上面可以看到镜像变成了ikubernetes/myapp:v2,说明滚动升级成功了~]# kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES1/1 Running 0 34s 10.244.209.133 node11/1 Running 0 34s 10.244.187.74 node2~]# curl 10.244.209.133div style="width: 50%; margin-left: 20px"><h2>Guestbook</h2>~]# curl 10.244.209.74div style="width: 50%; margin-left: 20px"><h2>Guestbook</h2>#上面可以看到虽然镜像已经更新了,但是原来的pod使用的还是之前的镜像,新创建的pod才会使用最新的镜像#把myapp-v2.tar.gz上传到node1和node2上,手动解压~]# docker load -i myapp-v2.tar.gz~]# docker load -i myapp-v2.tar.gz#10.244.209.133这个ip对应的pod删除~]# kubectl delete pods frontend-glb2cpod "frontend-glb2c" deleted~]# kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE1/1 Running 0 15s 10.244.187.75 node21/1 Running 0 2m37s 10.244.187.74 node2#重新生成了一个新的pod:frontend-hkhdw~]# curl 10.244.187.75Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>#新生成的pod的镜像已经变成了myapp的,说明更新完成了#如果我们直接修改replicaset.yaml文件,把image: yecc/gcr.io-google_samples-gb-frontend:v3变成- image: ikubernetes/myapp:v2kubectl apply -f replicaset.yaml#发现原来的pod还是用的frontend:v3这个镜像,没有实现自动更新生产环境如果升级,可以删除一个pod,观察一段时间之后没问题再删除另一个pod,但是这样需要人工干预多次;实际生产环境一般采用蓝绿发布,原来有一个rs1,再创建一个rs2(控制器),通过修改service标签,修改service可以匹配到rs2的控制器,这样才是蓝绿发布,这个也需要我们精心的部署规划,我们有一个控制器就是建立在rs之上完成的,叫做DeploymentDeployment控制器:概念、原理解读Deployment概述Deployment是用于部署应用的对象,它是kubernetes中最常用的资源对象,为ReplicaSet和Pod的创建提供了一种声明式的定义方法,在Deployment对象中描述一个期望的状态,Deployment控制器就会按照一定的控制速率把实际状态改成期望状态,通过定义一个Deployment控制器会创建一个新的ReplicaSet控制器,通过ReplicaSet创建pod,删除Deployment控制器,也会删除Deployment控制器下对应的ReplicaSet控制器和pod资源.使用Deployment而不直接创建ReplicaSet是因为Deployment对象拥有许多ReplicaSet没有的特性,例如滚动升级和回滚。apply -f 资源清单yaml文件名字,就可以更改资源Deployment控制器是建立在rs之上的一个控制器,可以管理多个rs,每次更新镜像版本,都会生成一个新的rs,把旧的rs替换掉,多个rs同时存在,但是只有一个rs运行。rs v1控制三个pod,删除一个pod,在rs v2上重新建立一个,依次类推,直到全部都是由rs v2控制,如果rs v2有问题,还可以回滚,Deployment是建构在rs之上的,多个rs组成一个Deployment,但是只有一个rs处于活跃状态.Deployment工作原理:如何管理rs和Pod?Deployment可以使用声明式定义,直接在命令行通过纯命令的方式完成对应资源版本的内容的修改,也就是通过打补丁的方式进行修改;Deployment能提供滚动式自定义自控制的更新;对Deployment来讲,我们在实现更新时还可以实现控制更新节奏和更新逻辑,什么叫做更新节奏和更新逻辑呢?比如说ReplicaSet控制5个pod副本,pod的期望值是5个,但是升级的时候需要额外多几个pod,那么我们控制器可以控制在5个pod副本之外还能再增加几个pod副本;比方说能多一个,但是不能少,那么升级的时候就是先增加一个,再删除一个,增加一个删除一个,始终保持pod副本数是5个;还有一种情况,最多允许多一个,最少允许少一个,也就是最多6个,最少4个,第一次加一个,删除两个,第二次加两个,删除两个,依次类推,可以自己控制更新方式,这种滚动更新的需要加readinessProbe和livenessProbe探测,确保pod中容器里的应用都正常启动了才删除之前的pod;启动第一步,刚更新第一批就暂停了也可以;假如目标是5个,允许一个也不能少,允许最多可以10个,那一次加5个即可;这就是我们可以自己控制节奏来控制更新的方法。通过Deployment对象,你可以轻松的做到以下事情:1、创建ReplicaSet和Pod2、滚动升级(不停止旧服务的状态下升级)和回滚应用(将应用回滚到之前的版本)3、平滑地扩容和缩容4、暂停和继续DeploymentDeployment资源清单文件编写技巧#查看Deployment资源对象由哪几部分组成~]# kubectl explain deploymentKIND: DeploymentVERSION: apps/v1DESCRIPTION:Deployment enables declarative updates for Pods and ReplicaSets.FIELDS:apiVersion <string> #该资源使用的api版本kind <string> #创建的资源是什么?metadata <Object> #元数据,包括资源的名字和名称空间spec <Object> #定义容器的status <Object> #状态,不可以修改#查看Deployment下的spec字段~]# kubectl explain deployment.specKIND: DeploymentVERSION: apps/v1RESOURCE: spec <Object>DESCRIPTION:Specification of the desired behavior of the Deployment.DeploymentSpec is the specification of the desired behavior of theDeployment.FIELDS:minReadySeconds <integer>Kubernetes在等待设置的时间后才进行升级如果没有设置该值,Kubernetes会假设该容器启动起来后就提供服务了如果没有设置该值,在某些极端情况下可能会造成服务服务正常运行paused <boolean> #暂停,当我们更新的时候创建pod先暂停,不是立即更新progressDeadlineSeconds <integer># Deployment controller 等待多少秒才能确定(通过 Deployment status)Deployment进程是卡住的replicas <integer> #副本数revisionHistoryLimit <integer> #保留的历史版本,默认是10selector <Object> -required- #标签选择器,选择它关联的podstrategy <Object> #更新策略template <Object> -required#查看Deployment下的spec.strategy字段~]# kubectl explain deploy.spec.strategyKIND: DeploymentVERSION: apps/v1RESOURCE: 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>type <string>Type of deployment. Can be "Recreate" or "RollingUpdate". Default isRollingUpdate.#支持两种更新,Recreate和RollingUpdate#Recreate是重建式更新,删除一个更新一个#RollingUpdate滚动更新,定义滚动更新方式,也就是pod能多几个,少几个#查看Deployment下的spec.strategy.rollingUpdate字段~]# kubectl explain deploy.spec.strategy.rollingUpdateKIND: DeploymentVERSION: apps/v1RESOURCE: 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>#最多允许几个不可用假设有5个副本,最多一个不可用,就表示最少有4个可用#查看Deployment下的spec.template字段#template为定义Pod的模板,Deployment通过模板创建Pod~]# kubectl explain deploy.spec.templateKIND: DeploymentVERSION: apps/v1RESOURCE: template <Object>DESCRIPTION:Template describes the pods that will be created.PodTemplateSpec describes the data a pod should have when created from a templateFIELDS:metadata <Object> #定义模板的名字spec <Object>deployment.spec.template为Pod定义的模板,和Pod定义不太一样,template中不包含apiVersion和Kind属性,要求必须有metadata。deployment.spec.template.spec为容器的属性信息,其他定义内容和Pod一致。#查看Deployment下的spec.template.spec字段~]# kubectl explain deploy.spec.template.specKIND: DeploymentVERSION: apps/v1RESOURCE: 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-statusPodSpec is a description of a pod.FIELDS:activeDeadlineSeconds <integer>affinity <Object>automountServiceAccountToken <boolean>containers <[]Object> -required-dnsConfig <Object>dnsPolicy <string>enableServiceLinks <boolean>ephemeralContainers <[]Object>hostAliases <[]Object>hostIPC <boolean>hostNetwork <boolean>hostPID <boolean>hostname <string>imagePullSecrets <[]Object>initContainers <[]Object>nodeName <string>nodeSelector <map[string]string>overhead <map[string]string>preemptionPolicy <string>priority <integer>priorityClassName <string>readinessGates <[]Object>restartPolicy <string>runtimeClassName <string>schedulerName <string>securityContext <Object>serviceAccount <string>serviceAccountName <string>setHostnameAsFQDN <boolean>shareProcessNamespace <boolean>subdomain <string>terminationGracePeriodSeconds <integer>tolerations <[]Object>topologySpreadConstraints <[]Objectvolumes <[]Object>实战3:Deployment使用案例:创建一个web站点deployment是一个三级结构,deployment管理replicaset,replicaset管理pod,#把myapp-blue-v1.tar.gz和myapp-blue-v2.tar.gz上传到node1和node2上,手动解压:~]# docker load -i myapp-blue-v1.tar.gz~]# docker load -i myapp-blue-v1.tar.gz~]# docker load -i myapp-blue-v2.tar.gz~]# docker load -i myapp-blue-v2.tar.gz[root@master1 ~]# cat deploy-demo.yaml更新资源清单文件:kubectl apply -f deploy-demo.yaml#kubectl apply:表示声明式的定义,既可以创建资源,也可以动态更新资源查看deploy状态:kubectl get deploy显示如下:NAME READY UP-TO-DATE AVAILABLE AGE2/2 2 2 60s#创建的控制器名字是myapp-v1:列出名称空间中deployment的名称。2.READY:显示deployment有多少副本数。它遵循ready/desired的模式。显示已更新到所需状态的副本数。显示你的可以使用多少个应用程序副本。:显示应用程序已运行的时间。kubectl get rs 显示如下:kubectl get rs显示如下:AME DESIRED CURRENT READY AGE2 2 2 2m35s#创建deploy的时候也会创建一个rs(replicaset),67fd9fc9c8 这个随机数字是我们引用pod的模板template的名字的hash值列出名称空间中ReplicaSet资源2DESIRED:显示应用程序的所需副本数,这些副本数是在创建时定义的。这是所需的状态。显示当前正在运行多少个副本。显示你的用户可以使用多少个应用程序副本。:显示应用程序已运行的时间。请注意,ReplicaSet的名称始终设置为[DEPLOYMENT-NAME]-[RANDOM-STRING]。RANDOM-STRING是随机生成的kubectl get pods显示如下:1/1 Running 0 3s1/1 Running 0 2m21s~]# kubectl get pods -o wide | grep myapp1/1 Running 0 10.244.187.78 node21/1 Running 0 10.244.209.136 node1#请求刚才创建的pod资源~]# curl 10.244.187.78: blue;~]# curl 10.244.209.136: blue;实战4:Deployment管理pod:扩容、缩容、滚动更新、回滚#通过deployment管理应用,实现扩容,把副本数变成3cat deploy-demo.yaml直接修改replicas数量,如下,变成3spec:replicas: 3修改之后保存退出,执行kubectl apply -f deploy-demo.yaml注意:apply不同于create,apply可以执行多次;create执行一次,再执行就会报错复。kubectl get pods显示如下:NAME READY STATUS RESTARTS AGE1/1 Running 0 15m1/1 Running 0 11s1/1 Running 0 17m#上面可以看到pod副本数变成了3个#查看myapp-v1这个控制器的详细信息~]# kubectl describe deploy myapp-v1Name: myapp-v1Namespace: defaultCreationTimestamp: Tue, 30 Mar 2021 12:59:02 +0800Labels: <none>Annotations: deployment.kubernetes.io/revision: 1Selector: app=myapp,version=v1Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailableStrategyType: RollingUpdateMinReadySeconds: 0RollingUpdateStrategy: 25% max unavailable, 25% max surgePod Template:Labels: app=myappversion=v1Containers:myapp:Image: janakiramm/myapp:v1Port: 80/TCPHost Port: 0/TCPEnvironment: <none>Mounts: <none>Volumes: <none>Conditions:Type Status Reason------ ------Progressing True NewReplicaSetAvailableAvailable True MinimumReplicasAvailableOldReplicaSets: <none>NewReplicaSet: myapp-v1-67fd9fc9c8 (3/3 replicas created)Events:Type Reason Age From Message------ ---- ---- -------Normal ScalingReplicaSet 18m deployment-controller Scaled up replica set myapp-v1-67fd9fc9c8 to 2Normal ScalingReplicaSet 51s deployment-controller Scaled up replica set myapp-v1-67fd9fc9c8 to 3#通过deployment管理应用,实现缩容,把副本数变成2cat deploy-demo.yaml直接修改replicas数量,如下,变成2spec:replicas: 2修改之后保存退出,执行~]# kubectl apply -f deploy-demo.yaml~]# kubectl get podsNAME READY STATUS RESTARTS AGE1/1 Running 0 18m1/1 Running 0 20m#通过deployment管理应用,实现滚动更新在一个终端窗口执行如下:~]# kubectl get pods -l app=myapp -wNAME READY STATUS RESTARTS AGE1/1 Running 0 19m1/1 Running 0 22m打开一个新的终端窗口更改镜像版本,按如下操作:vim deploy-demo.yaml: janakiramm/myapp:v1 变成image: janakiramm/myapp:v2kubectl apply -f deploy-demo.yamlget pods -l app=myapp -w的那个窗口,可以看到信息如下:NAME READY STATUS RESTARTS AGE1/1 Running 0 23m1/1 Running 0 26m0/1 Pending 0 0s0/1 Pending 0 0s0/1 ContainerCreating 0 0s0/1 ContainerCreating 0 1s1/1 Running 0 4s1/1 Terminating 0 24m0/1 Pending 0 0s0/1 Pending 0 0s0/1 ContainerCreating 0 0s1/1 Terminating 0 24m0/1 ContainerCreating 0 1s0/1 Terminating 0 24m1/1 Running 0 1s1/1 Terminating 0 26m1/1 Terminating 0 26m0/1 Terminating 0 26m0/1 Terminating 0 26m0/1 Terminating 0 26m0/1 Terminating 0 24m0/1 Terminating 0 24mpending表示正在进行调度,ContainerCreating表示正在创建一个pod,running表示运行一个pod,running起来一个pod之后再Terminating(停掉)一个pod,以此类推,直到所有pod完成滚动升级在另外一个窗口执行kubectl get rs显示如下:0 0 0 27m2 2 2 79s#上面可以看到rs有两个,上面那个是升级之前的,已经被停掉,但是可以随时回滚#查看myapp-v1这个控制器的历史版本~]# kubectl rollout history deployment myapp-v1REVISION CHANGE-CAUSE1 <none>2 <none>#回滚~]# kubectl rollout undo deployment myapp-v1 --to-revision=1rolled back~]# kubectl rollout history deployment myapp-v1REVISION CHANGE-CAUSE2 <none>3 <none>

精彩文章推荐
基于Jenkins+git+harbor+Helm+k8s+Istio构建DevOps流水线
基于k8s+Prometheus+Alertmanager+Grafana构建企业级监控告警系统

点亮,服务器10年不宕机
点击阅读原文 | 了解更多
原文作者:DevOps和k8s全栈技术;如有侵权,请联系管理员删除。