k8s控制器--Replicaset和Deployment

k8s控制器--Replicaset和Deployment

一、Replicaset控制器

2.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对象。

2.2、Replicaset工作原理

Replicaset核心作用在于用户创建指定数量的pod副本,并确保pod副本一直处于满足用户期望的数量, 起到多退少补的作用,并且还具有自动扩容缩容等制。
Replicaset控制器主要由三个部分组成:
1、用户期望的pod副本数:用来定义由这个控制器管控的pod副本有几个
2、标签选择器:选定哪些pod是自己管理的,如果通过标签选择器选到的pod副本数量少于我们指定的数量,需要用到下面的组件
3、pod资源模板:如果集群中现存的pod数量不够我们定义的副本中期望的数量怎么办,需要新建pod,这就需要pod模板,新建的pod是基于模板来创建的。

2.3、Replicaset使用案例

#编写一个ReplicaSet资源清单
[root@k8s-master1 ~]# cat replicaset.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: php-redis
        image: yecc/gcr.io-google_samples-gb-frontend:v3
        imagePullPolicy:  IfNotPresent

[root@k8s-master1 ~]# kubectl apply -f replicaset.yaml 
replicaset.apps/frontend created
[root@k8s-master1 ~]# kubectl get rs
NAME       DESIRED   CURRENT   READY   AGE
frontend   3         3         3       48s
[root@k8s-master1 ~]# kubectl get pods
NAME             READY   STATUS    RESTARTS   AGE
frontend-8p5lq   1/1     Running   0          54s
frontend-9hjr8   1/1     Running   0          54s
frontend-nt6kb   1/1     Running   0          54s

2.4、Replicaset管理pod

2.4.1、实现pod的动态扩缩容

方式一:修改yaml文件的replicas值,重新apply

方式二:使用kubectl edit rs frontend动态修改

# 方式一
[root@k8s-master1 ~]# vim replicaset.yaml
replicas: 4

[root@k8s-master1 ~]# kubectl apply -f replicaset.yaml
replicaset.apps/frontend configured
[root@k8s-master1 ~]# kubectl get pods
NAME             READY   STATUS    RESTARTS   AGE
frontend-8p5lq   1/1     Running   0          22m
frontend-9hjr8   1/1     Running   0          22m
frontend-nt6kb   1/1     Running   0          22m
frontend-vhz2g   1/1     Running   0          5s

# 方式二
[root@k8s-master1 ~]# kubectl edit rs frontend

2.4.2、实现pod的版本更新

修改yaml文件的image或者使用kubectl edit命令修改镜像只会影响新生成的pod,对原先的pod没有影响,只能删除原先的pod才能完成版本更新。

生产环境如果升级,可以删除一个pod,观察一段时间之后没问题再删除另一个pod,但是这样需要人工干预多次;实际生产环境一般采用蓝绿发布,原来有一个rs1,再创建一个rs2(控制器),通过修改service标签,修改service可以匹配到rs2的控制器,这样才是蓝绿发布,这个也需要我们精心的部署规划,我们有一个控制器就是建立在rs之上完成的,叫做Deployment

二、Deployment控制器

Deployment官方文档:https://kubernetes.io/docs/concepts/workloads/controllers/deployment/

2.1、Deployment概述

Deployment是kubernetes中最常用的资源对象,为ReplicaSet和Pod的创建提供了一种声明式的定义方法,在Deployment对象中描述一个期望的状态,Deployment控制器就会按照一定的控制速率把实际状态改成期望状态,通过定义一个Deployment控制器会创建一个新的ReplicaSet控制器,通过ReplicaSet创建pod,删除Deployment控制器,也会删除Deployment控制器下对应的ReplicaSet控制器和pod资源

使用Deployment而不直接创建ReplicaSet是因为Deployment对象拥有许多ReplicaSet没有的特性,例如滚动升级和回滚

声明式定义:指直接修改资源清单yaml文件,然后通过kubectl apply -f 资源清单yaml文件,就可以更改资源

Deployment控制器是建立在rs之上的一个控制器,可以管理多个rs,每次更新镜像版本,都会生成一个新的rs,把旧的rs替换掉,多个rs同时存在,但是只有一个rs运行。

image-20210709222300852

rs v1控制三个pod,删除一个pod,在rs v2上重新建立一个,依次类推,直到全部都是由rs v2控制,如果rs v2有问题,还可以回滚,Deployment是建构在rs之上的,多个rs组成一个Deployment,但是只有一个rs处于活跃状态.

2.2、Deployment工作原理

Deployment可以使用声明式定义,直接在命令行通过纯命令的方式完成对应资源版本的内容的修改,也就是通过打补丁的方式进行修改;Deployment能提供滚动式自定义自控制的更新;对Deployment来讲,我们在实现更新时还可以实现控制更新节奏和更新逻辑。

更新节奏和更新逻辑

​ 比如说Deployment控制5个pod副本,pod的期望值是5个,但是升级的时候需要额外多几个pod,那我们控制器可以控制在5个pod副本之外还能再增加几个pod副本;比方说能多一个,但是不能少,那么升级的时候就是先增加一个,再删除一个,增加一个删除一个,始终保持pod副本数是5个;还有一种情况,最多允许多一个,最少允许少一个,也就是最多6个,最少4个,第一次加一个,删除两个,第二次加两个,删除两个,依次类推,可以自己控制更新方式,这种滚动更新需要加readinessProbe和livenessProbe探测,确保pod中容器里的应用都正常启动了才删除之前的pod。
启动第一步,刚更新第一批就暂停了也可以;假如目标是5个,允许一个也不能少,允许最多可以10个,那一次加5个即可;这就是我们可以自己控制节奏来控制更新的方法。

通过Deployment对象,你可以轻松的做到以下事情:

  1. 创建ReplicaSet和Pod
  2. 滚动升级(不停止旧服务的状态下升级)和回滚应用(将应用回滚到之前的版本)
  3. 平滑地扩容和缩容
  4. 暂停和继续Deployment

2.3、Deployment使用案例

[root@k8s-master1 ~]# cat deploy-demo.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-v1
spec:
  replicas: 2
  selector:
   matchLabels:
    app: myapp
    version: v1
  template:
   metadata:
    labels:
     app: myapp
     version: v1
   spec:
    containers:
    - name: myapp
      image: janakiramm/myapp:v1
      imagePullPolicy: IfNotPresent
      ports:
      - containerPort: 80
      
[root@k8s-master1 ~]# kubectl apply -f deploy-demo.yaml
deployment.apps/myapp-v1 created
[root@k8s-master1 ~]# kubectl get deploy
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
myapp-v1   2/2     2            2           5s
[root@k8s-master1 ~]# kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-67fd9fc9c8   2         2         2       10s
[root@k8s-master1 ~]# kubectl get pods
NAME                        READY   STATUS    RESTARTS   AGE
myapp-v1-67fd9fc9c8-6fw6v   1/1     Running   0          16s
myapp-v1-67fd9fc9c8-pndjj   1/1     Running   0          16s

2.4、Deployment管理pod

2.4.1、实现Pod扩缩容

方式一:修改yaml文件,然后kubectl apply

方式二:使用kubectl edit deploy修改副本数

2.4.2、实现滚动升级及回滚

滚动升级:

  • 方式一:修改yaml文件,然后kubectl apply
  • 方式二:使用kubectl edit deploy修改镜像版本

回滚:

[root@k8s-master1 ~]# kubectl get deploy
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
myapp-v1   2/2     2            2           29m
[root@k8s-master1 ~]# kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-67fd9fc9c8   0         0         0       29m
myapp-v1-75fb478d6c   2         2         2       13s
# 查看myapp-v1这个控制器的历史版本
[root@k8s-master1 ~]# kubectl rollout history deployment myapp-v1
deployment.apps/myapp-v1 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

# 回滚
[root@k8s-master1 ~]# kubectl rollout undo deployment myapp-v1 --to-revision=1
deployment.apps/myapp-v1 rolled back
[root@k8s-master1 ~]# kubectl get rs
NAME                  DESIRED   CURRENT   READY   AGE
myapp-v1-67fd9fc9c8   2         2         2       30m
myapp-v1-75fb478d6c   0         0         0       84s
[root@k8s-master1 ~]# kubectl rollout history deployment myapp-v1
deployment.apps/myapp-v1 
REVISION  CHANGE-CAUSE
2         <none>
3         <none>

2.4.3、自定义滚动更新策略

maxSurgemaxUnavailable用来控制滚动更新的更新策略

# 取值范围
数值:两者不能同时为0。
1. maxUnavailable: [0, 副本数]
2. maxSurge: [0, 副本数]
比例:两者不能同时为0。
1. maxUnavailable: [0%, 100%] 向下取整,比如10个副本,5%的话==0.5个,但计算按照0个;
2. maxSurge: [0%, 100%] 向上取整,比如10个副本,5%的话==0.5个,但计算按照1个;

# 建议配置
1. maxUnavailable == 0
2. maxSurge == 1
这是我们生产环境提供给用户的默认配置。即“一上一下,先上后下”最平滑原则:1个新版本pod ready(结合readiness)后,才销毁旧版本pod。此配置适用场景是平滑更新、保证服务平稳,但也有缺点,就是“太慢”了。

# 总结:
maxUnavailable:和期望的副本数比,不可用副本数最大比例(或最大值),这个值越小,越能保证服务稳定,更新越平滑;
maxSurge:和期望的副本数比,超过期望副本数最大比例(或最大值),这个值调的越大,副本更新速度越快。

自定义策略示例

# 修改更新策略:maxUnavailable=1,maxSurge=1 
[root@k8s-master1 ~]# kubectl patch deployment myapp-v1 -p '{"spec":{"strategy":{"rollingUpdate": {"maxSurge":1,"maxUnavailable":1}}}}' -n blue-green

# 查看myapp-v1这个控制器的详细信息
[root@k8s-master1 ~]# kubectl describe deployment myapp-v1 -n blue-green
RollingUpdateStrategy:  1 max unavailable, 1 max surge

# 这个rollingUpdate更新策略变成了刚才设定的,因为我们设定的pod副本数是3,1和1表示最少不能少于2个pod,最多不能超过4个pod ,这个就是通过控制RollingUpdateStrategy这个字段来设置滚动更新策略的

2.5、Deployment配置模板

apiVersion: apps/v1
kind: Deployment 
metadata:
  name: portal
  namespace: test 
spec:
  replicas: 1
  selector:
    matchLabels:
      project: ms
      app: portal
  template:
    metadata:
      labels:
        project: ms 
        app: portal
    spec:
      containers:
      - name: portal
        image:  xianchao/portal:v1
        imagePullPolicy: Always
        ports:
          - protocol: TCP
            containerPort: 8080 
        resources:  #资源配额
          limits:  #资源限制,最多可用的cpu和内存
            cpu: 1
            memory: 1Gi
          requests: #最少需要多少资源才可以运行Pod
            cpu: 0.5
            memory: 1Gi
        readinessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
        livenessProbe:
          tcpSocket:
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 10
posted @ 2021-07-10 09:28  运维人在路上  阅读(2619)  评论(0编辑  收藏  举报