软件测试testopsDocker容器

Testops之路7.Kubernetes之控制器

2019-08-01  本文已影响20人  KalvinDai

控制器

正式开始之前,先来回顾一下上节课的内容。

再来用上帝视角看一下今天要讲的2个主角Deployment和ReplicaSet之间的关系是什么?


image

ReplicationController(rc)

Replication Controller简称RC,RC是Kubernetes系统中的核心概念之一,简单来说,RC可以保证在任意时间运行Pod的副本数量,能够保证Pod总是可用的。如果实际Pod数量比指定的多那就结束掉多余的,如果实际数量比指定的少就新启动一些Pod,当Pod失败、被删除或者挂掉后,RC都会去自动创建新的Pod来保证副本数量,所以即使只有一个Pod,我们也应该使用RC来管理我们的Pod。

image

解释上面这个图:

  1. PodA是直接通过pod方式创建的。
  2. PodB是通过rc、rs或者deploy创建的。
  3. 当node1出现问题时,因为PodB有控制器保障数量,会自动找合适的节点进行调度,而PodA并不会。
image

如上图所示,ReplicationController主要包含三个部分:

image

如上图所示,我们来看一下当一个pod被删除时,ReplicationController的工作过程。当kubia-53thy被删除后,ReplicationController发现数量不匹配(期望3个),立刻在创建一个新的pod出来。

ReplicaSet(rs)

Replication Set简称RS,随着Kubernetes的高速发展,官方已经推荐我们使用RS和Deployment来代替RC了,实际上RS和RC的功能基本一致,目前唯一的一个区别就是RC只支持基于等式的selector(env=dev或environment!=qa),但RS还支持基于集合的selector(version in (v1.0, v2.0)。

代用户创建指定数量的pod副本数量,确保pod副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能

ReplicaSet主要三个组件组成:

帮助用户管理无状态的pod资源,精确反应用户定义的目标数量,但是RelicaSet不是直接使用的控制器,而是使用Deployment。(大家想想这是什么原因)

apiVersion: apps/v1  #api版本定义
kind: ReplicaSet  #定义资源类型为ReplicaSet
metadata:  #元数据定义
    name: myapp
    namespace: default
spec:  #ReplicaSet的规格定义
    replicas: 2  #定义副本数量为2个
    selector:    #标签选择器,定义匹配pod的标签
        matchLabels:
            app: myapp
            release: canary
    template:  #pod的模板定义
        metadata:  #pod的元数据定义
            name: myapp-pod   #自定义pod的名称 
            labels:   #定义pod的标签,需要和上面定义的标签一致,也可以多出其他标签
                app: myapp
                release: canary
                environment: qa
        spec:  #pod的规格定义
            containers:  #容器定义
            - name: myapp-container  #容器名称
              image: ikubernetes/myapp:v1  #容器镜像
              ports:  #暴露端口
              - name: http
                containerPort: 80

Deployment(deploy)

工作在ReplicaSet之上,用于管理无状态应用,目前来说最好的控制器。支持滚动更新和回滚功能,还提供声明式配置。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  generation: 14
  labels:
    app: fbs-cc-v2
    mode: new-production
    role: default
    tier: backend
  name: fbs-cc-v2
  namespace: new-production
spec:
  progressDeadlineSeconds: 600
  replicas: 8 #是可以选字段,指定期望的pod数量,默认是1。
  revisionHistoryLimit: 10
  selector: #是可选字段,用来指定 label selector ,圈定Deployment管理的pod范围。
    matchLabels:
      app: fbs-cc-v2
      mode: new-production
      role: default
      tier: backend
  strategy: #指定新的Pod替换旧的Pod的策略。 .spec.strategy.type 可以是"Recreate"或者是 "RollingUpdate"。"RollingUpdate"是默认值。
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template: #是 pod template. 它跟 Pod有一模一样的schema,除了它是嵌套的并且不需要apiVersion 和 kind字段。
    ……

strategy(更新策略):

例如,该值设置成30%,启动rolling update后新的ReplicatSet将会立即扩容,新老Pod的总数不能超过期望的Pod数量的130%。旧的Pod被杀掉后,新的ReplicaSet将继续扩容,旧的ReplicaSet会进一步缩容,确保在升级的所有时刻所有的Pod数量和不会超过期望Pod数量的130%。

例如,该值设置成30%,启动rolling update后旧的ReplicatSet将会立即缩容到期望的Pod数量的70%。新的Pod ready后,随着新的ReplicaSet的扩容,旧的ReplicaSet会进一步缩容确保在升级的所有时刻可以用的Pod数量至少是期望Pod数量的70%。

image
[root@master1 ~]# kubectl get deploy fbs-cc-v2 -n new-production
NAME        DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
fbs-cc-v2      8        8         8            8      29d
  1. DESIRED:用户期望的 Pod 副本个数(spec.replicas 的值);
  2. CURRENT:当前处于 Running 状态的 Pod 的个数;
  3. UP-TO-DATE:当前处于最新版本的 Pod 的个数,所谓最新版本指的是 Pod 的 Spec 部分与 Deployment 里 Pod 模板里定义的完全一致;
  4. AVAILABLE:当前已经可用的 Pod 的个数,即:既是 Running 状态,又是最新版本,并且已经处于 Ready(健康检查正确)状态的 Pod 的个数。

控制循环(调谐)

实际上,k8s的控制器它们都遵循 Kubernetes 项目中的一个通用编排模式,即:控制循环。

比如,现在有一种待编排的对象 X,它有一个对应的控制器。那么,我就可以用一段 Go 语言风格的伪代码,为你描述这个控制循环:

for {
  实际状态 := 获取集群中对象 X 的实际状态(Actual State)
  期望状态 := 获取集群中对象 X 的期望状态(Desired State)
  if 实际状态 == 期望状态{
    什么都不做
  } else {
    执行编排动作,将实际状态调整为期望状态
  }
}
image

实际状态
实际状态往往来自于 Kubernetes 集群本身。

比如,kubelet 通过心跳汇报的容器状态和节点状态,或者监控系统中保存的应用监控数据,或者控制器主动收集的它自己感兴趣的信息,这些都是常见的实际状态的来源。

期望状态
期望状态一般来自于用户提交的 YAML 文件。

比如,Deployment 对象中 Replicas 字段的值。很明显,这些信息往往都保存在 Etcd 中。

接下来,以 Deployment 为例:

  1. Deployment 控制器从 Etcd 中获取到所有携带了“app: nginx”标签的 Pod,然后统计它们的数量,这就是实际状态
  2. Deployment 对象的 Replicas 字段的值就是期望状态
  3. Deployment 控制器将两个状态做比较,然后根据比较结果,确定是创建 Pod,还是删除已有的 Pod。

可以看到,一个 Kubernetes 对象的主要编排逻辑,实际上是在第三步的“对比”阶段完成的。这个操作,通常被叫作调谐(Reconcile)。这个调谐的过程,则被称作“Reconcile Loop”(调谐循环)或者“Sync Loop”(同步循环)。

k8s使用的是一种“用一种对象管理另一种对象”的“艺术”。

其中,这个控制器对象本身,负责定义被管理对象的期望状态。比如,Deployment 里的 replicas=2 这个字段。

而被控制对象的定义,则来自于一个“模板”。比如,Deployment 里的 template 字段。可以看到,Deployment 这个 template 字段里的内容,跟一个标准的 Pod 对象的 API 定义,丝毫不差。而所有被这个 Deployment 管理的 Pod 实例,其实都是根据这个 template 字段的内容创建出来的。像 Deployment 定义的 template 字段,在 Kubernetes 项目中有一个专有的名字,叫作 PodTemplate。

image

如上图所示,类似 Deployment 这样的一个控制器,实际上都是由上半部分的控制器定义(包括期望状态),加上下半部分的被控制对象的模板组成的。

现在,请思考一个问题,假如我把其中一个pod的label改了,会发生什么?

image image

对pod模板内容进行修改,只有在删除pod,rc尝试重新创建pod时才会用新的pod模板。

image

在删除一个rc时,如果不想同步删除pod 要加上--cascade=false,当rc删除后,这些pod会变成没人管的“孤儿”。

实战体验

#查看deploy
kubectl get deploy -n mengtms1
NAME             DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
boss-dahai-com   1         1         1            1           41d
cc-dahai-com     1         1         1            1           41d
libs-dahai-com   1         1         1            1           41d

#查看replicaset
kubectl get rs -n mengtms1
NAME                        DESIRED   CURRENT   READY     AGE
boss-dahai-com-68788f7775   0         0         0         41d
boss-dahai-com-6f5987c966   1         1         1         3d
cc-dahai-com-77f7bf5867     0         0         0         41d
cc-dahai-com-78df67c954     1         1         1         41d
libs-dahai-com-5db64968f7   1         1         1         41d

#查看pod
kubectl get pods --show-labels -n mengtms1
NAME                              READY     STATUS    RESTARTS   AGE       LABELS
boss-dahai-com-6f5987c966-d2zkn   1/1       Running   0          3d        app=boss-dahai-com,pod-template-hash=2915437522,tier=frontend
cc-dahai-com-78df67c954-qr6zq     1/1       Running   0          41d       app=cc-dahai-com,pod-template-hash=3489237510,tier=backend
libs-dahai-com-5db64968f7-nxw26   1/1       Running   0          41d       app=libs-dahai-com,pod-template-hash=1862052493,tier=backend

# 扩容
## 通过scale命令
kubectl scale deployment cc-dahai-com --replicas 3 -n mengtms1
deployment "cc-dahai-com" scaled

## 通过修改yaml文件/修改deploy文件
kubectl edit deployment cc-dahai-com -n mengtms1
……
replicas: 3
……

## 查看pod数变化
kubectl get deploy -n mengtms1
NAME             DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
boss-dahai-com   1         1         1            1           41d
cc-dahai-com     3         3         3            3           41d
libs-dahai-com   1         1         1            1           41d

## 滚动升级/蓝绿部署
kubectl scale deployment cc-dahai-com --replicas 10 -n mengtms1
kubectl edit deployment cc-dahai-com -n mengtms1
NAME             DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
boss-dahai-com   1         1         1            1           41d
cc-dahai-com     10        10        10           10          41d
libs-dahai-com   1         1         1            1           41d

### fbs-cc:master-20190704174559
### fbs-cc:master-20190704103840

## 观察滚动升级过程
kubectl rollout status deployment cc-dahai-com -n mengtms1
Waiting for rollout to finish: 2 out of 10 new replicas have been updated...

# 金丝雀环境/灰度发布/ABTest
## 将deploy设置为pause
kubectl set image deploy cc-dahai-com cc-dahai-com=image.docker.dahai.com/apps/fbs-cc:master-20190704174559 -n mengtms1 && kubectl rollout pause deploy cc-dahai-com -n mengtms1

## 观察滚动升级过程,发现不再持续更新
kubectl rollout status deployment cc-dahai-com -n mengtms1
Waiting for rollout to finish: 0 out of 10 new replicas have been updated...

## 查看pod
kubectl get pods -l app=cc-dahai-com -n mengtms1 -w

## 确保更新的pod没问题了,继续更新,恢复滚动升级过程
kubectl rollout resume deploy cc-dahai-com -n mengtms1

# 回滚
## 查看版本
kubectl rollout history deploy cc-dahai-com -n mengtms1
deployments "cc-dahai-com"
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>
6         <none>
7         <none>

## 查看对应版本的信息
kubectl rollout history deploy cc-dahai-com -n mengtms1 --revision=2
deployments "cc-dahai-com" with revision #2
Pod Template:
  Labels:   app=cc-dahai-com
    pod-template-hash=3489237510
    tier=backend
  Containers:
   cc-dahai-com:
    Image:  image.docker.xxxxx/apps/cc-dahai-com:latest
    Port:   <none>
    Limits:
      cpu:  400m
      memory:   1Gi
    Requests:
      cpu:  20m
      memory:   100Mi
    Liveness:   http-get http://:9001/ping delay=0s timeout=1s period=10s #success=1 #failure=3
    Readiness:  http-get http://:9001/ping delay=0s timeout=1s period=10s #success=1 #failure=3
    Environment:
      NAMESPACE:     (v1:metadata.namespace)
      CLUSTER:  dev
      OCEAN_ENV:    Test
      ENV_TYPE:
      BASE_MODE:    super
      OCEAN_MODE:   mengtms1
      SERVER_USER_ENV:  mengtms1
      OCEAN_APP:    cc-dahai-com
      SYSTEM_NAME:  cc.xxxxx
    Mounts:
      /libs.xxxxx from libs-vol (rw)
  Volumes:
   libs-vol:
    Type:   PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:  mengtms1-libs-pvc
    ReadOnly:   false

## 回到上个版本
kubectl rollout undo deploy cc-dahai-com -n mengtms1

## 回到特定版本
kubectl rollout undo deploy cc-dahai-com -n mengtms1 --to-revision=1

DaemonSet

image

DaemonSet:用于确保集群中的每一个节点只运行特定的pod副本,通常用于实现系统级后台任务。

Job

只要完成就立即退出,不需要重启或重建。

Cronjob

周期性任务控制,不需要持续后台运行,

StatefulSet

管理有状态应用

上一篇下一篇

猜你喜欢

热点阅读