ReplicaSet控制器
一、ReplicaSet概述
ReplicaSet是kubernetes中的一种副本控制器,简称rs,主要作用是控制由其管理的pod,使pod副本的数量始终维持在预设的个数。它的主要作用就是保证一定数量的Pod能够在集群中正常运行,它会持续监听这些Pod的运行状态,在Pod发生故障时重启pod,pod数量减少时重新运行新的 Pod副本。
官方推荐不要直接使用ReplicaSet,用Deployments取而代之,Deployments是比ReplicaSet更高级的概念,它会管理ReplicaSet并提供很多其它有用的特性,最重要的是Deployments支持声明式更新,声明式更新的好处是不会丢失历史变更。所以Deployment控制器不直接管理Pod对象,而是由 Deployment 管理ReplicaSet,再由ReplicaSet负责管理Pod对象。
ReplicaSet核心作用在于代用户创建指定数量的pod副本,并确保pod副本一直处于满足用户期望的数量, 起到多退少补的作用,并且还具有自动扩容缩容等机制。
ReplicaSet的副本数量,标签选择器和pod模板都可以随时按需进行修改,不过仅改动期望的副本数量会对现存的pod副本产生直接影响。修改标签选择器可能会使现有的pod副本的标签变得不再匹配,此时ReplicaSet控制器要做的不过是不再计入它们而已。另外,在创建完成后,ReplicaSet也不会再关注pod对象中的实际内容,因此pod模板的改动也只会对后来新建的pod副本产生影响。
相比较手动创建和管理pod资源来说,ReplicaSet能够实现以下功能:
1)确保pod资源对象的数量精确反映期望值:ReplicaSet需要确保由其控制运行的pod副本数量精确吻合配置中定义的期望值,否则就会自动补足所缺或终止多余的pod
2)确保pod健康运行:探测到由其管控的pod对象因其所在的工作节点故障而不可用时,自动请求由调度器于其他工作节点创建缺失的pod副本
3)弹性伸缩:业务规模因各种原因时常存在明显波动,在波峰或波谷期间,可以通过ReplicaSet控制器动态调整相关pod资源对象的数量。此外,在必要的时候还可以通过HPA控制器实现pod资源规模的自动伸缩。
二、创建ReplicaSet
类似pod资源,创建ReplicaSet控制器对象时同样使用YAML或JSON格式的清单文件定义其配置,而后使用相关的创建命令来完成资源的创建。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | [root@k8s-master1 ~] # kubectl explain replicaset KIND: ReplicaSet VERSION: apps /v1 DESCRIPTION: ReplicaSet ensures that a specified number of pod replicas are running at any given time . FIELDS: apiVersion <string> APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https: //git .k8s.io /community/contributors/devel/sig-architecture/api-conventions .md #resources kind <string> Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https: //git .k8s.io /community/contributors/devel/sig-architecture/api-conventions .md #types-kinds metadata <Object> If the Labels of a ReplicaSet are empty, they are defaulted to be the same as the Pod(s) that the ReplicaSet manages. Standard object's metadata. More info: https: //git .k8s.io /community/contributors/devel/sig-architecture/api-conventions .md #metadata spec <Object> 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-status status <Object> Status is the most recently observed status of the ReplicaSet. This data may be out of date by some window of time . Populated by the system. Read-only. More info: https: //git .k8s.io /community/contributors/devel/sig-architecture/api-conventions .md #spec-and-status |
ReplicaSet也由kind,apiVersion,metadata,spec和status这5个一级字段组成,其中status为只读字段,因此需要在清单文件中配置前四个字段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | [root@k8s-master1 ~] # kubectl explain replicaset.spec KIND: ReplicaSet VERSION: apps /v1 RESOURCE: 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-status ReplicaSetSpec is the specification of a ReplicaSet. FIELDS: minReadySeconds <integer> Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready) replicas <integer> Replicas is the number of desired replicas. This is a pointer to distinguish between explicit zero and unspecified. Defaults to 1. More info: https: //kubernetes .io /docs/concepts/workloads/controllers/replicationcontroller/ #what-is-a-replicationcontroller selector <Object> -required- Selector is a label query over pods that should match the replica count. Label keys and values that must match in order to be controlled by this replica set . It must match the pod template's labels. More info: https: //kubernetes .io /docs/concepts/overview/working-with-objects/labels/ #label-selectors template <Object> Template is the object that describes the pod that will be created if insufficient replicas are detected. More info: https: //kubernetes .io /docs/concepts/workloads/controllers/replicationcontroller #pod-template |
ReplicaSet的spec字段一般嵌套使用minReadySeconds,replicas,selector和template 这四个字段。
1)minReadySeconds <integer>:新建pod对象,在启动后的多长时间内如果其容器未发生崩溃等异常情况即被视为“就绪”;默认为0秒,表示一旦就绪性探测成功,即被视为可用。
2)replicas <integer>:期望的pod对象副本数
3)selector <Object> -required- :当前控制器匹配pod对象副本的标签选择器,支持matchLabels和matchExpressions两种匹配机制
4)template <Object>:用于补足pod副本数量时使用的pod模板资源
1. 编写一个ReplicaSet资源清单:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | [root@k8s-master1 ~] # mkdir replicaset You have new mail in /var/spool/mail/root [root@k8s-master1 ~] # cd replicaset/ [root@k8s-master1 replicaset] # ll total 0 [root@k8s-master1 replicaset] # kubectl get pods NAME READY STATUS RESTARTS AGE myapp-pod 1 /1 Running 1 23h [root@k8s-master1 replicaset] # vim replicaset-demo.yaml [root@k8s-master1 replicaset] # cat replicaset-demo.yaml apiVersion: apps /v1 kind: ReplicaSet #创建的资源类型 metadata: name: frontend #控制器名字 labels: app: guestbook tier: frontend spec: replicas: 3 #管理pod副本数量 selector: matchLabels: tier: frontend #管理带有tier=frontend标签的pod template: #定义pod模板 metadata: labels: tier: frontend #pod标签,控制器根据这个标签找pod,管理对应的pod spec: containers: #定义pod中运行的容器 - name: php-redis #容器的名字 image: yecc /gcr .io-google_samples-gb-frontend:v3 imagePullPolicy: IfNotPresent |
2. 创建ReplicaSet资源
1 2 3 4 5 6 7 8 9 10 11 | [root@k8s-master1 replicaset] # kubectl apply -f replicaset-demo.yaml replicaset.apps /frontend created You have new mail in /var/spool/mail/root [root@k8s-master1 replicaset] # kubectl get rs -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR frontend 3 3 3 16s php-redis yecc /gcr .io-google_samples-gb-frontend:v3 tier=frontend [root@k8s-master1 replicaset] # kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES frontend-5vghz 1 /1 Running 0 23s 10.244.169.141 k8s-node2 <none> <none> frontend-f62dw 1 /1 Running 0 23s 10.244.36.108 k8s-node1 <none> <none> frontend-z7kng 1 /1 Running 0 23s 10.244.36.107 k8s-node1 <none> <none> |
pod的名字是由控制器的名字-随机数组成的。经由控制器创建与用户自主创建pod对象功能一样,但其自动和解的功能在很大程度上能为用户省去不少管理精力,这也是使得k8s系统上的应用程序变得拥有自愈能力的主要保障。
三、ReplicaSet管控下的pod对象
在实际中存在不少可能导致pod对象数目与期望值不符合的可能性,如pod对象意外删除,pod对象标签的变动,控制器的标签选择器变动,甚至是工作节点故障等。ReplicaSet控制器的和解循环过程能够实时监控到这类异常,并及时启动和解操作。
1. 缺少pod副本
任何原因导致的相关pod对象丢失,都会由ReplicaSet控制器自动补足。例如,手动删除上面列出的一个pod对象。
1 2 | [root@k8s-master1 replicaset] # kubectl delete pods frontend-f62dw pod "frontend-f62dw" deleted |
再次罗列相关pod对象信息,可以看到删除了pod:frontend-f62dw,但是又新建了一个pod对象副本frontend-sfzjr
1 2 3 4 5 | [root@k8s-master1 replicaset] # kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES frontend-5vghz 1 /1 Running 0 14m 10.244.169.141 k8s-node2 <none> <none> frontend-sfzjr 1 /1 Running 0 7s 10.244.36.109 k8s-node1 <none> <none> frontend-z7kng 1 /1 Running 0 14m 10.244.36.107 k8s-node1 <none> <none> |
另外,强行修改隶属于控制器frontend的某个pod资源的标签,会导致它不再被控制器作为副本技术,这也将触发控制器的pod对象副本缺失补足机制。例如,将frontend-z7kng标签tier的值置空:
1 2 | [root@k8s-master1 replicaset] # kubectl label pods frontend-z7kng tier= --overwrite pod /frontend-z7kng labeled |
查看pod对象信息,发现正在创建新的对象副本
1 2 3 4 5 6 7 8 9 10 11 12 | [root@k8s-master1 replicaset] # kubectl get pods -w NAME READY STATUS RESTARTS AGE frontend-5vghz 1 /1 Running 0 24m frontend-sfzjr 1 /1 Running 0 10m frontend-z7kng 1 /1 Running 0 24m frontend-z7kng 1 /1 Running 0 26m frontend-z7kng 1 /1 Running 0 26m frontend-4852w 0 /1 Pending 0 0s frontend-4852w 0 /1 Pending 0 0s frontend-4852w 0 /1 ContainerCreating 0 0s frontend-4852w 0 /1 ContainerCreating 0 1s frontend-4852w 1 /1 Running 0 2s |
列出frontend控制器下相关的pod对象信息,发现pod对象frontend-z7kng已经消失,重新创建了frontend-4852w对象副本:
1 2 3 4 5 | [root@k8s-master1 replicaset] # kubectl get pods -l tier=frontend NAME READY STATUS RESTARTS AGE frontend-4852w 1 /1 Running 0 4m12s frontend-5vghz 1 /1 Running 0 30m frontend-sfzjr 1 /1 Running 0 16m |
由此可见,修改了pod资源的标签即可将其从控制器的管控下移出,如果,修改后的标签又能被其他控制器资源的标签选择器选中,那么此时它又隶属于另外一个控制器的副本。如果修改器标签后的pod对象不再隶属于任何控制器,那么它将成为自主式pod,即误删或者所在节点故障都会造成其永久性消失。
1 2 3 4 5 6 7 | [root@k8s-master1 replicaset] # kubectl delete pods frontend-z7kng pod "frontend-z7kng" deleted [root@k8s-master1 replicaset] # kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES frontend-4852w 1 /1 Running 0 10m 10.244.36.110 k8s-node1 <none> <none> frontend-5vghz 1 /1 Running 0 37m 10.244.169.141 k8s-node2 <none> <none> frontend-sfzjr 1 /1 Running 0 23m 10.244.36.109 k8s-node1 <none> <none> |
2. 多出pod副本
一旦被标签选择器匹配到的pod资源数量因任何原因超出期望值,多余的部分都将被控制器自动删除。例如,创建一个标签为tier=frontend的pod对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | [root@k8s-master1 pod] # vim pod-test.yaml [root@k8s-master1 pod] # cat pod-test.yaml apiVersion: v1 kind: Pod metadata: name: pod- test labels: tier: frontend spec: containers: - name: nginx- test ports: - containerPort: 80 image: nginx:latest imagePullPolicy: IfNotPresent [root@k8s-master1 pod] # kubectl apply -f pod-test.yaml pod /pod-test created |
再次罗列出相关的pod对象,可以看到frontend控制器启动了删除了多余的pod操作,pod-test正处于终止的过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | [root@k8s-master1 replicaset] # kubectl get pods -w NAME READY STATUS RESTARTS AGE frontend-4852w 1 /1 Running 0 17m frontend-5vghz 1 /1 Running 0 43m frontend-sfzjr 1 /1 Running 0 29m pod- test 0 /1 Pending 0 0s pod- test 0 /1 Pending 0 0s pod- test 0 /1 Pending 0 0s pod- test 0 /1 Terminating 0 0s pod- test 0 /1 Terminating 0 0s pod- test 0 /1 Terminating 0 1s pod- test 0 /1 Terminating 0 3s pod- test 0 /1 Terminating 0 7s pod- test 0 /1 Terminating 0 7s |
这就意味着,任何自主式的或本隶属于其他控制器的pod资源其标签变动的结果一旦匹配到了其他的副本数足额的控制器,就会导致这类pod资源被删除。
3. 查看pod资源变动的相关事件
使用“kubectl describe replicasets”命令可打印出控制器的详细状态,从中可以看出控制器frontend执行了pod资源的创建和删除操作,为的就是确保其数量的准确性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | [root@k8s-master1 replicaset] # kubectl describe replicasets Name: frontend Namespace: default Selector: tier=frontend Labels: app=guestbook tier=frontend Annotations: <none> Replicas: 3 current / 3 desired Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed Pod Template: Labels: tier=frontend Containers: php-redis: Image: yecc /gcr .io-google_samples-gb-frontend:v3 Port: <none> Host Port: <none> Environment: <none> Mounts: <none> Volumes: <none> Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfulCreate 49m replicaset-controller Created pod: frontend-z7kng Normal SuccessfulCreate 49m replicaset-controller Created pod: frontend-5vghz Normal SuccessfulCreate 49m replicaset-controller Created pod: frontend-f62dw Normal SuccessfulCreate 35m replicaset-controller Created pod: frontend-sfzjr Normal SuccessfulCreate 23m replicaset-controller Created pod: frontend-4852w Normal SuccessfulDelete 5m40s replicaset-controller Deleted pod: pod- test |
事实上,ReplicaSet控制器能对pod对象数目的异常及时作出响应,是因为它向API Server注册监听(watch)了相关资源及其列表的变动信息,于是API Server会在变动发生时立即通知给相关的监听客户端。
四、更新ReplicaSet控制器
ReplicaSet控制器的核心组成部分是标签选择器、副本数量和pod模板,但要更新操作一般是围绕replicas和template两个字段值进行的,毕竟改变标签选择器的需求几乎不存在。改动pod模板的定义对已经创建完成的活动对象无效,但在用户逐个手动关闭其旧版本的pod资源后就能以新代旧,实现控制器下应用版本的滚动升级。另外,修改副本的数量也就意味着应用规模的扩展或收缩。
1. 更改pod模板:升级应用
ReplicaSet控制器的pod模板可随时按需修改,但它仅影响这之后由其新建的pod对象,对已有的副本不会产生作用。大多数情况下,用户需要改变的通常是模板中的容器镜像文件及其相关的配置以实现应用的版本升级。如:修改镜像image: yecc/gcr.io-google_samples-gb-frontend:v3变成- image: ikubernetes/myapp:v1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | [root@k8s-master1 replicaset] # vim replicaset-demo.yaml You have new mail in /var/spool/mail/root [root@k8s-master1 replicaset] # cat replicaset-demo.yaml apiVersion: apps /v1 kind: ReplicaSet metadata: name: frontend labels: app: guestbook tier: frontend spec: replicas: 3 selector: matchLabels: tier: frontend template: metadata: labels: tier: frontend spec: containers: - name: myapp image: ikubernetes /myapp :v1 imagePullPolicy: IfNotPresent [root@k8s-master1 replicaset] # kubectl apply -f replicaset-demo.yaml replicaset.apps /frontend configured You have new mail in /var/spool/mail/root [root@k8s-master1 replicaset] # kubectl get rs -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR frontend 3 3 3 22h myapp ikubernetes /myapp :v1 tier=frontend [root@k8s-master1 replicaset] # kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES frontend-4852w 1 /1 Running 1 22h 10.244.36.112 k8s-node1 <none> <none> frontend-5vghz 1 /1 Running 1 22h 10.244.169.142 k8s-node2 <none> <none> frontend-sfzjr 1 /1 Running 1 22h 10.244.36.113 k8s-node1 <none> <none> |
上面可以看到镜像变成了ikubernetes/myapp:v1,说明滚动升级成功了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | [root@k8s-master1 replicaset] # kubectl describe pod frontend-4852w Name: frontend-4852w Namespace: default Priority: 0 Node: k8s-node1 /10 .0.0.132 Start Time: Mon, 05 Sep 2022 23:46:56 +0800 Labels: tier=frontend Annotations: cni.projectcalico.org /podIP : 10.244.36.112 /32 cni.projectcalico.org /podIPs : 10.244.36.112 /32 Status: Running IP: 10.244.36.112 IPs: IP: 10.244.36.112 Controlled By: ReplicaSet /frontend Containers: php-redis: Container ID: docker: //a2f3b94bf3c08d0226b9f0e40e7ca6eac0e71f733292b372853d9122f002147f Image: yecc /gcr .io-google_samples-gb-frontend:v3 Image ID: docker: //sha256 :c038466384ab3c5c743186b1b85d14d4e523c91d0f328482764c5d448689fc9b Port: <none> Host Port: <none> State: Running Started: Tue, 06 Sep 2022 21:43:33 +0800 Last State: Terminated Reason: Completed Exit Code: 0 Started: Mon, 05 Sep 2022 23:46:57 +0800 Finished: Tue, 06 Sep 2022 00:17:40 +0800 Ready: True Restart Count: 1 Environment: <none> Mounts: /var/run/secrets/kubernetes .io /serviceaccount from default-token-5n29f (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: default-token-5n29f: Type: Secret (a volume populated by a Secret) SecretName: default-token-5n29f Optional: false 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 22h default-scheduler Successfully assigned default /frontend-4852w to k8s-node1 Normal Pulled 22h kubelet Container image "yecc/gcr.io-google_samples-gb-frontend:v3" already present on machine Normal Created 22h kubelet Created container php-redis Normal Started 22h kubelet Started container php-redis Normal SandboxChanged 15m (x3 over 16m) kubelet Pod sandbox changed, it will be killed and re-created. Normal Pulled 14m kubelet Container image "yecc/gcr.io-google_samples-gb-frontend:v3" already present on machine Normal Created 14m kubelet Created container php-redis Normal Started 14m kubelet Started container php-redis |
上面可以看到虽然镜像已经更新了,但是原来的pod使用的还是之前的镜像,对已有的pod资源对象无效,新创建的pod才会使用最新的镜像。
删除frontend-4852w 这个pod,会重新生成一个新的pod:frontend-xvmmw
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | [root@k8s-master1 replicaset] # kubectl delete pods frontend-4852w pod "frontend-4852w" deleted [root@k8s-master1 ~] # kubectl get pods -w NAME READY STATUS RESTARTS AGE frontend-4852w 1 /1 Running 1 22h frontend-5vghz 1 /1 Running 1 22h frontend-sfzjr 1 /1 Running 1 22h frontend-4852w 1 /1 Terminating 1 22h frontend-xvmmw 0 /1 Pending 0 0s frontend-xvmmw 0 /1 Pending 0 0s frontend-xvmmw 0 /1 ContainerCreating 0 0s frontend-4852w 1 /1 Terminating 1 22h frontend-4852w 0 /1 Terminating 1 22h frontend-xvmmw 0 /1 ContainerCreating 0 2s frontend-xvmmw 1 /1 Running 0 3s frontend-4852w 0 /1 Terminating 1 22h frontend-4852w 0 /1 Terminating 1 22h [root@k8s-master1 replicaset] # kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES frontend-5vghz 1 /1 Running 1 22h 10.244.169.142 k8s-node2 <none> <none> frontend-sfzjr 1 /1 Running 1 22h 10.244.36.113 k8s-node1 <none> <none> frontend-xvmmw 1 /1 Running 0 88s 10.244.36.114 k8s-node1 <none> <none> |
查看新pod:frontend-xvmmw 的信息,使用的是新镜像ikubernetes/myapp:v1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | [root@k8s-master1 replicaset] # kubectl describe pod frontend-xvmmw Name: frontend-xvmmw Namespace: default Priority: 0 Node: k8s-node1 /10 .0.0.132 Start Time: Tue, 06 Sep 2022 22:01:23 +0800 Labels: tier=frontend Annotations: cni.projectcalico.org /podIP : 10.244.36.114 /32 cni.projectcalico.org /podIPs : 10.244.36.114 /32 Status: Running IP: 10.244.36.114 IPs: IP: 10.244.36.114 Controlled By: ReplicaSet /frontend Containers: myapp: Container ID: docker: //89404a0af64081d3e2e50bfa07e6f24240f1c339519d2ba1c3f1c5b405eb439a Image: ikubernetes /myapp :v1 Image ID: docker: //sha256 :d4a5e0eaa84f28550cb9dd1bde4bfe63a93e3cf88886aa5dad52c9a75dd0e6a9 Port: <none> Host Port: <none> State: Running Started: Tue, 06 Sep 2022 22:01:25 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes .io /serviceaccount from default-token-5n29f (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: default-token-5n29f: Type: Secret (a volume populated by a Secret) SecretName: default-token-5n29f Optional: false 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 2m37s default-scheduler Successfully assigned default /frontend-xvmmw to k8s-node1 Normal Pulled 2m35s kubelet Container image "ikubernetes/myapp:v1" already present on machine Normal Created 2m35s kubelet Created container myapp Normal Started 2m35s kubelet Started container myapp |
生产环境如果升级,可以删除一个pod,观察一段时间之后没问题再删除另一个pod,但是这样需要人工干预多次;实际生产环境一般采用蓝绿发布,原来有一个rs1,再创建一个rs2(控制器),通过修改service标签,修改service可以匹配到rs2的控制器,这样才是蓝绿发布。
2. 扩容和缩容
改动ReplicaSet控制器对象配置中期望的pod副本数量(replicas字段)会由控制器实时作出响应,从而实现应用规模的水平伸缩。kubectl还提供了一个专用的子命令scale用于实现应用规模的伸缩,它支持从资源清单文件中获取新的目标副本数量,也可以直接在命令行通过--replicas选项进行读取。例如:将frontend控制器的pod副本数量提升到4个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [root@k8s-master1 replicaset] # kubectl get rs -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR frontend 3 3 3 22h myapp ikubernetes /myapp :v1 tier=frontend [root@k8s-master1 replicaset] # kubectl scale replicasets frontend --replicas=4 replicaset.apps /frontend scaled You have new mail in /var/spool/mail/root [root@k8s-master1 replicaset] # kubectl get rs -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR frontend 4 4 3 22h myapp ikubernetes /myapp :v1 tier=frontend [root@k8s-master1 replicaset] # kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES frontend-5vghz 1 /1 Running 1 22h 10.244.169.142 k8s-node2 <none> <none> frontend-c5m4f 1 /1 Running 0 6s 10.244.36.115 k8s-node1 <none> <none> frontend-sfzjr 1 /1 Running 1 22h 10.244.36.113 k8s-node1 <none> <none> frontend-xvmmw 1 /1 Running 0 12m 10.244.36.114 k8s-node1 <none> <none> |
从frontend资源状态可以看出,将其pod副本数量扩展到4个的操作已完成。收缩规模的方式与扩展相同,只需要明确指定目标副本数量即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | [root@k8s-master1 replicaset] # kubectl scale replicasets frontend --replicas=2 replicaset.apps /frontend scaled You have new mail in /var/spool/mail/root [root@k8s-master1 replicaset] # kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES frontend-5vghz 1 /1 Running 1 22h 10.244.169.142 k8s-node2 <none> <none> frontend-c5m4f 0 /1 Terminating 0 2m39s <none> k8s-node1 <none> <none> frontend-sfzjr 1 /1 Running 1 22h 10.244.36.113 k8s-node1 <none> <none> frontend-xvmmw 0 /1 Terminating 0 14m 10.244.36.114 k8s-node1 <none> <none> [root@k8s-master1 replicaset] # kubectl get rs -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR frontend 2 2 2 22h myapp ikubernetes /myapp :v1 tier=frontend [root@k8s-master1 replicaset] # kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES frontend-5vghz 1 /1 Running 1 22h 10.244.169.142 k8s-node2 <none> <none> frontend-sfzjr 1 /1 Running 1 22h 10.244.36.113 k8s-node1 <none> <none> |
另外,kubectl scale命令还支持在现有pod副本数量符合指定的值时才执行扩展操作,这仅需要为命令使用--current-replicas选项即可。例如:下面的命令表示如果frontend控制器目前的pod副本数量为2,就将其扩展到5个。
1 2 3 4 5 6 7 8 9 10 11 12 13 | [root@k8s-master1 replicaset] # kubectl scale replicasets frontend --current-replicas=2 --replicas=5 replicaset.apps /frontend scaled You have new mail in /var/spool/mail/root [root@k8s-master1 replicaset] # kubectl get rs -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR frontend 5 5 2 22h myapp ikubernetes /myapp :v1 tier=frontend [root@k8s-master1 replicaset] # kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES frontend-5vghz 1 /1 Running 1 22h 10.244.169.142 k8s-node2 <none> <none> frontend-f8bz8 1 /1 Running 0 7s 10.244.36.116 k8s-node1 <none> <none> frontend-pkqkw 1 /1 Running 0 7s 10.244.36.118 k8s-node1 <none> <none> frontend-sfzjr 1 /1 Running 1 22h 10.244.36.113 k8s-node1 <none> <none> frontend-wdrzh 1 /1 Running 0 7s 10.244.36.117 k8s-node1 <none> <none> |
注:当控制器现存pod副本数量不满足命令给出的数量时,扩展操作将不会执行,并返回错误提示
1 2 | [root@k8s-master1 replicaset] # kubectl scale replicasets frontend --current-replicas=4 --replicas=2 error: Expected replicas to be 4, was 5 |
动态扩缩容的另一种方法:直接修改资源清单文件。例如:当前frontend控制器有5个pod副本数量,太多,想要减少到2个,立即生效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | [root@k8s-master1 replicaset] # kubectl get rs -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR frontend 5 5 5 23h myapp ikubernetes /myapp :v1 tier=frontend [root@k8s-master1 replicaset] # kubectl edit replicasets frontend replicaset.apps /frontend edited [root@k8s-master1 replicaset] # kubectl get rs -o wide NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR frontend 2 2 2 23h myapp ikubernetes /myapp :v1 tier=frontend [root@k8s-master1 replicaset] # kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES frontend-5vghz 1 /1 Running 1 23h 10.244.169.142 k8s-node2 <none> <none> frontend-sfzjr 1 /1 Running 1 22h 10.244.36.113 k8s-node1 <none> <none> |
五、删除ReplicaSet控制器资源
使用kubectl delete命令删除ReplicaSet对象时默认会一并删除其管控的各pod对象。有时,考虑到这些pod资源未必由其创建,或者即便由其创建却也并非其自身的组成部分,因此,可以为命令使用“--cascade=false”选项 或者“--cascade=orphan”选项,取消级联,删除相关pod对象。如,删除rs控制器frontend:
1 2 3 4 5 6 7 8 9 10 11 | [root@k8s-master1 replicaset] # kubectl delete replicasets frontend --cascade=false warning: --cascade= false is deprecated (boolean value) and can be replaced with --cascade=orphan. replicaset.apps "frontend" deleted [root@k8s-master1 replicaset] # kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES frontend-5vghz 1 /1 Running 1 23h 10.244.169.142 k8s-node2 <none> <none> frontend-sfzjr 1 /1 Running 1 22h 10.244.36.113 k8s-node1 <none> <none> [root@k8s-master1 replicaset] # kubectl get rs -o wide No resources found in default namespace. |
删除操作完成后,此前由frontend控制器管控的pod对象仍然处于活动状态,但它们变成了自主式pod资源,用户需要自行组织和维护它们。
尽管ReplicaSet控制器功能强大,但是在实践中,RS需要手动执行更新操作。因此,很少会去单独使用RS,,它主要被Deployment这个更加高层的资源对象使用,Deployment控制器能够自动实现更完善的滚动更新和回滚。除非用户需要自定义升级功能或根本不需要升级Pod,在一般情况下,推荐使用Deployment而不直接使用ReplicaSet。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏