目录
K8s 控制器 Replicaset
一、Replicaset 控制器:概念、原理解读
1.1 Replicaset 概述
1.2 Replicaset 工作原理:如何管理 Pod ?
二、Replicaset 资源清单文件编写技巧
三、Replicaset 使用案例:部署 Guestbook 留言板
四、Replicaset 管理 pod:扩容、缩容、更新
4.1 Replicaset 实现 pod 的动态扩容
4.2 Replicaset 实现 pod 的动态缩容
4.3 Replicaset 实现 pod 的更新
4.4 总结
K8s 控制器 Replicaset
K8s 常见的控制器:replicaset、deployment、statefulset、daemonset、job、cronjobe等。
前面我们学习了Pod,那我们在定义pod资源时,可以直接创建一个kind:Pod类型的自主式pod,但是这存在一个问题,假如pod被删除了,那这个pod就不能自我恢复,就会彻底被删除,线上这种情况非常危险,所以今天就给大家讲解下pod的控制器,所谓控制器就是能够管理pod,监测pod运行状况,当pod发生故障,可以自动恢复pod。也就是说能够代我们去管理pod中间层,并帮助我们确保每一个pod资源始终处于我们所定义或者我们所期望的目标状态,一旦pod资源出现故障,那么控制器会尝试重启pod或者里面的容器,如果一直重启有问题的话那么它可能会基于某种策略来进行重新布派或者重新编排;如果pod副本数量低于用户所定义的目标数量,它也会自动补全;如果多余,也会自动终止pod资源。
一、Replicaset 控制器:概念、原理解读
1.1 Replicaset 概述
ReplicaSet 是kubernetes中的一种副本控制器,简称rs,主要作用是控制由其管理的pod,使pod副本的数量始终维持在预设的个数。它的主要作用就是保证一定数量的Pod能够在集群中正常运行,它会持续监听这些Pod的运行状态,在Pod发生故障时重启pod,pod数量减少时重新运行新的 Pod副本。官方推荐不要直接使用ReplicaSet,用Deployments取而代之,Deployments是比ReplicaSet更高级的概念,它会管理ReplicaSet并提供很多其它有用的特性,最重要的是Deployments支持声明式更新,声明式更新的好处是不会丢失历史变更。所以Deployment控制器不直接管理Pod对象,而是由 Deployment 管理ReplicaSet,再由ReplicaSet负责管理Pod对象。
1.2 Replicaset 工作原理:如何管理 Pod ?
Replicaset 核心作用在于代用户创建指定数量的pod副本,并确保pod副本一直处于满足用户期望的数量, 起到多退少补的作用,并且还具有自动扩容缩容等机制。
Replicaset 控制器主要由三个部分组成:
- 用户期望的 pod 副本数:用来定义由这个控制器管控的pod副本有几个。
- 标签选择器:选定哪些pod是自己管理的,如果通过标签选择器选到的pod副本数量少于我们指定的数量,需要用到下面的组件。
- pod 资源模板:如果集群中现存的pod数量不够我们定义的副本中期望的数量怎么办,需要新建pod,这就需要pod模板,新建的pod是基于模板来创建的。
二、Replicaset 资源清单文件编写技巧
# 查看定义 Replicaset 资源需要的字段有哪些?
[root@k8s-master01 ~]# kubectl explain rs
KIND: ReplicaSet
VERSION: apps/v1
DESCRIPTION:
ReplicaSet ensures that a specified number of pod replicas are running at
any given time.
FIELDS:
# 当前资源使用的api 版本,跟VERSION: apps/v1 保持一致
apiVersion <string>
# 资源类型,跟KIND: ReplicaSet 保持一致
kind <string>
# 元数据,定义Replicaset 名字的
metadata <Object>
# 定义副本数、定义标签选择器、定义Pod 模板
spec <Object>
# 状态信息,不能改
status <Object>
[root@k8s-master01 ~]# kubectl explain rs.metadata
[root@k8s-master01 ~]# kubectl explain rs.metadata.labels
# 查看 replicaset 的 spec 字段如何定义?
[root@k8s-master01 ~]# kubectl explain rs.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>
# 定义的pod 副本数,根据我们指定的值创建对应数量的pod
replicas <integer>
# 用于匹配pod 的标签选择器
selector <Object> -required-
# 定义Pod 的模板,基于这个模板定义的所有pod 是一样的
template <Object>
[root@k8s-master01 ~]# kubectl explain rs.spec.selector
# 查看replicaset 的spec.template 字段如何定义?
# 对于template 而言,其内部定义的就是pod,pod 模板是一个独立的对象
[root@k8s-master01 ~]# kubectl explain rs.spec.template
KIND: ReplicaSet
VERSION: apps/v1
RESOURCE: template <Object>
DESCRIPTION:
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
PodTemplateSpec describes the data a pod should have when created from a
template
FIELDS:
metadata <Object>
Standard object's metadata. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
spec <Object>
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
[root@k8s-master01 ~]# kubectl explain rs.spec.template.spec
[root@k8s-master01 ~]# kubectl explain rs.spec.template.spec.containers
[root@k8s-master01 ~]# kubectl explain rs.spec.template.spec.containers.ports
[root@k8s-master01 ~]# kubectl explain rs.spec.template.spec.containers.startupProbe
[root@k8s-master01 ~]# kubectl explain rs.spec.template.spec.containers.startupProbe.httpGet
通过上面可以看到,ReplicaSet 资源中有两个spec 字段。第一个spec 声明的是ReplicaSet 定义多少个Pod 副本(默认将仅部署1 个Pod)、匹配Pod 标签的选择器、创建pod 的模板。第二个spec 是spec.template.spec:主要用于Pod 里的容器属性等配置。
.spec.template 里的内容是声明Pod 对象时要定义的各种属性,所以这部分也叫做PodTemplate(Pod 模板)。还有一个值得注意的地方是:在 .spec.selector 中定义的标签选择器必须能够匹配到 spec.template.metadata.labels 里定义的Pod 标签,否则Kubernetes 将不允许创建ReplicaSet。
参考官方文档:ReplicaSet | Kubernetes
三、Replicaset 使用案例:部署 Guestbook 留言板
把 frontend.tar.gz 上传到 node2 和 node1 上,解压
[root@k8s-node1 ~]# ctr -n=k8s.io images import frontend.tar.gz
[root@k8s-node1 ~]# ctr -n=k8s.io images import frontend.tar.gz
# 编写一个 ReplicaSet 资源清单
[root@k8s-master01 ~]# vim replicaset.yaml
apiVersion: apps/v1 # ReplicaSet 这个控制器属于的核心群组
kind: ReplicaSet # 创建的资源类型
metadata:
name: frontend # 控制器的名字
namespace: default
labels:
app: guestbook
tire: frontend
spec:
replicas: 3 # 管理的pod 副本数量
selector:
matchLabels:
tire1: frontend1
template: # 定义pod 的模板
metadata:
labels:
tire1: frontend1 # pod 标签,一定要有,这样上面控制器就能找到它要管理的pod 是哪些了
spec:
containers: # 定义pod 里运行的容器
- name: php-redis # 定义容器的名字
image: docker.io/yecc/gcr.io-google_samples-gb-frontend:v3
imagePullPolicy: IfNotPresent
ports: # 定义端口
- containerPort: 80 #定义容器暴露的端口
startupProbe:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 80
path: /
livenessProbe:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 80
path: /
readinessProbe:
periodSeconds: 5
initialDelaySeconds: 20
timeoutSeconds: 10
httpGet:
scheme: HTTP
port: 80
path: /
[root@k8s-master01 ~]# kubectl apply -f replicaset.yaml
[root@k8s-master01 ~]# kubectl get rs
[root@k8s-master01 ~]# kubectl get pods
pod 的名字是由 控制器的名字-随机数 组成的:
我们删除一个 pod,看是否会自动恢复:
[root@k8s-master01 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
frontend-5qxtq 1/1 Running 0 5m47s 10.244.169.180 k8s-node2 <none> <none>
frontend-sqrzl 1/1 Running 0 5m47s 10.244.169.179 k8s-node2 <none> <none>
frontend-tzj55 1/1 Running 0 5m47s 10.244.36.99 k8s-node1 <none> <none>
[root@k8s-master01 ~]# kubectl delete pods frontend-5qxtq
pod "frontend-5qxtq" deleted
[root@k8s-master01 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
frontend-sqrzl 1/1 Running 0 6m43s 10.244.169.179 k8s-node2 <none> <none>
frontend-txzg7 1/1 Running 0 29s 10.244.169.181 k8s-node2 <none> <none>
frontend-tzj55 1/1 Running 0 6m43s 10.244.36.99 k8s-node1 <none> <none>
四、Replicaset 管理 pod:扩容、缩容、更新
4.1 Replicaset 实现 pod 的动态扩容
ReplicaSet 最核心的功能是可以动态扩容和回缩,如果我们觉得两个副本太少了,想要增加,只需要修改配置文件replicaset.yaml 里的replicas 的值即可,原来replicas: 3,现在变成replicaset:4,修改之后,执行如下命令更新:
[root@k8s-master01 ~]# kubectl apply -f replicaset.yaml
replicaset.apps/frontend configured
[root@k8s-master01 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
frontend-lwtzd 1/1 Running 0 42s 10.244.36.100 k8s-node1 <none> <none>
frontend-sqrzl 1/1 Running 0 46m 10.244.169.179 k8s-node2 <none> <none>
frontend-txzg7 1/1 Running 0 40m 10.244.169.181 k8s-node2 <none> <none>
frontend-tzj55 1/1 Running 0 46m 10.244.36.99 k8s-node1 <none> <none>
[root@k8s-master01 ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
frontend 4 4 4 46m
4.2 Replicaset 实现 pod 的动态缩容
如果我们觉得4 个Pod 副本太多了,想要减少,只需要修改配置文件replicaset.yaml 里的
replicas 的值即可,把replicaset:4 变成replicas: 2,修改之后,执行如下命令更新:
[root@k8s-master01 ~]# kubectl apply -f replicaset.yaml
replicaset.apps/frontend configured
[root@k8s-master01 ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
frontend 2 2 2 49m
您在 /var/spool/mail/root 中有新邮件
[root@k8s-master01 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
frontend-sqrzl 1/1 Running 0 49m 10.244.169.179 k8s-node2 <none> <none>
frontend-txzg7 1/1 Running 0 43m 10.244.169.181 k8s-node2 <none> <none>
4.3 Replicaset 实现 pod 的更新
把 myapp-v2.tar.gz 上传到 node1 和 node2 上,手动解压
[root@k8s-node1 ~]# ctr -n=k8s.io images import myapp-v2.tar.gz
unpacking docker.io/ikubernetes/myapp:v2 (sha256:ebc427841ba631350f7b630bce441b21d11dd2e700f529bf7b33e3db7a329240)...done
[root@k8s-node2 ~]# ctr -n=k8s.io images import myapp-v2.tar.gz
unpacking docker.io/ikubernetes/myapp:v2 (sha256:ebc427841ba631350f7b630bce441b21d11dd2e700f529bf7b33e3db7a329240)...done
# 修改镜像 image,变成 docker.io/ikubernetes/myapp:v2
[root@k8s-master01 ~]# vim replicaset.yaml
spec:
containers:
- name: php-redis
image: docker.io/ikubernetes/myapp:v2
imagePullPolicy: IfNotPresent
[root@k8s-master01 ~]# kubectl apply -f replicaset.yaml
replicaset.apps/frontend configured
[root@k8s-master01 ~]# curl 10.244.169.179
<html ng-app="redis">
<head>
<title>Guestbook</title>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
但是上面可以看到,虽然replicaset.yaml 修改了镜像,执行了kubectl apply -f replicaset.yaml,但是 pod 还是用的 frontend:v3 这个镜像,没有实现自动更新
# 需手动把10.244.169.179 这个 ip 对应的 pod 删除
[root@k8s-master01 ~]# kubectl delete pods frontend-sqrzl
pod "frontend-sqrzl" deleted
# 重新生成了一个新的 pod:frontend-bmhz6
[root@k8s-master01 ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
frontend-bmhz6 1/1 Running 0 29s 10.244.36.101 k8s-node1 <none> <none>
frontend-txzg7 1/1 Running 0 53m 10.244.169.181 k8s-node2 <none> <none>
# 新生成的pod 的镜像已经变成了myapp 的,说明更新完成了
[root@k8s-master01 ~]# curl 10.244.36.101
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
参考官方文档:ReplicaSet | Kubernetes
4.4 总结
生产环境如果升级,可以删除一个pod,观察一段时间之后没问题再删除另一个pod,但是这样需要人工干预多次;实际生产环境一般采用蓝绿发布,原来有一个rs(Replicaset)1,再创建一个rs2(控制器),通过修改service 标签,修改service 可以匹配到rs2 的控制器,这样才是蓝绿发布,这个也需要我们精心的部署规划,我们有一个控制器就是建立在rs 之上完成的,叫做 Deployment。这个控制器下一篇讲解!
上一篇文章:【云原生 | Kubernetes 实战】08、零故障升级之 Pod 健康探测——启动、存活、就绪探测_Stars.Sky的博客-CSDN博客