K8s中控制器的用法

目录

1.Deployment:

水平扩展/收缩

 滚动更新:

回滚

StatefulSet:


所有的控制器集合都是在kube-controller-manager中完成的。master节点基础插件有kube-schedulerr、kube-apiserver、kube-contoller-manager这三个的。

控制器都遵循 Kubernetes 项目中的一个通用编排模式,即:控制循环(control loop)。

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


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

以 Deployment 为例,我和你简单描述一下它对控制器模型的实现:

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

1.Deployment:

Deployment实现了一个重要的功能:对pod的水平收缩/扩展(horizontal scaling out/in)。

Deployment和pod的关系如下所示:

K8s中控制器的用法_第1张图片

 会发现多了一个ReplicaSet,这是什么呢?

ReplicaSet属于deployment的一个子集,deployment并不会直接创建pod,而是要通过操控ReplicaSet去创建pod。ReplicatSet在后面的水平伸缩和滚动更新中都有很大的作用。

ReplicaSet 负责通过“控制器模式”,保证系统中 Pod 的个数永远等于指定的个数(比如,3 个)。这也正是 Deployment 只允许容器的 restartPolicy=Always 的主要原因:只有在容器能保证自己始终是 Running 状态的前提下,ReplicaSet 调整 Pod 的个数才有意义。

对于deployment比较重要的两个编排方式--水平扩展/收缩,

编写deployment文件,并运行

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec: 
      containers:
      - name: nginx
        image: nginx:1.8
        ports:
        - containerPort: 80
        volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: nginx-vol
      volumes:
      - name: nginx-vol
        hostPath:
          path: "/var/data"

 查看一下,我们可以看到多了一个replicaset用来控制pod的数量。

K8s中控制器的用法_第2张图片

  • DESIRED:用户期望的 Pod 副本个数(spec.replicas 的值);
  • CURRENT:当前处于 Running 状态的 Pod 的个数;
  • READY:当前运行正常的pod的个数;
  • UP-TO-DATE:当前处于最新版本的 Pod 的个数,所谓最新版本指的是 Pod 的 Spec 部分与 Deployment 里 Pod 模板里定义的完全一致;
  • AVAILABLE:当前已经可用的 Pod 的个数,即:既是 Running 状态,又是最新版本,并且已经处于 Ready(健康检查正确)状态的 Pod 的个数。

我们可以通过以下查看deployment的状态:

root@master01:/opt/k8s/controller# kubectl rollout status deployment nginx-deployment 
deployment "nginx-deployment" successfully rolled out

 对于每一个API对象都有一个ownerReference,由deployment创建的pod的owner就是replicaset,当然replicaset的owner就为deployment。可通过以下查看:

 K8s中控制器的用法_第3张图片

水平扩展/收缩

增加pod的数量我们可以直接去yaml文件中修改一下,并apply。我们也可以直接更改,这里我直接修改的。非常的easy!

这是扩展,收缩的话就将replicas值调的小一些就好。

root@master01:/opt/k8s/controller# kubectl scale deployment nginx-deployment --replicas=3
deployment.apps/nginx-deployment scaled


root@master01:/opt/k8s/controller# kubectl get all
NAME                                    READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-68b8f9dbf9-2plt4   1/1     Running   0          42m
pod/nginx-deployment-68b8f9dbf9-7z95f   1/1     Running   0          42m
pod/nginx-deployment-68b8f9dbf9-mk65h   1/1     Running   0          9s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.0.0.1             443/TCP   4d20h

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-deployment   3/3     3            3           42m

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-deployment-68b8f9dbf9   3         3         3       42m

 滚动更新:

我们可以直接用kubectl edit去修改存在ectd中的配置文件,kubectl edit 并不神秘,它不过是把 API 对象的内容下载到了本地文件,让你修改完成后再提交上去。

我们直接将我们nginx:1.8升级为nginx1.9.1。

K8s中控制器的用法_第4张图片

 我们describe一下我们的deployment,看一下events

K8s中控制器的用法_第5张图片

  一共8条事件,前2条事件为我们前面测试的收缩和扩展,后面的6条为滚动更新的事件信息。

可以看到,首先,当你修改了 Deployment 里的 Pod 定义之后,Deployment Controller 会使用这个修改后的 Pod 模板,创建一个新的 ReplicaSet(hash=85b59d9477),这个新的 ReplicaSet 的初始 Pod 副本数是:0。

然后,在 Age=51 s 的位置,Deployment Controller 开始将这个新的 ReplicaSet 所控制的 Pod 副本数从 0 个变成 1 个,即:“水平扩展”出一个副本。

紧接着,在 Age=49 s 的位置,Deployment Controller 又将旧的 ReplicaSet(hash=68b8f9dbf9)所控制的旧 Pod 副本数减少一个,即:“水平收缩”成两个副本。

如此交替进行,新 ReplicaSet 管理的 Pod 副本数,从 0 个变成 1 个,再变成 2 个,最后变成 3 个。而旧的 ReplicaSet 管理的 Pod 副本数则从 3 个变成 2 个,再变成 1 个,最后变成 0 个。这样,就完成了这一组 Pod 的版本升级过程。

像这样,将一个集群中正在运行的多个 Pod 版本,交替地逐一升级的过程,就是“滚动更新”。

 我们再来查看一下我们的replicaset。发现68b8的已经更新为了85b5。

 这个旧的rs可以让我们进行回滚,所以不要删除咯。

到这我们也看出滚动更新的好处,当我们的更新第一个pod时,若出现错误,就不会再向下更新了,技术人员就可以介入调整了。而剩下的2个旧容器也可以正常运行,提供服务。

而滚动更新时一次性创建的pod和删除的pod也是可以控制的,如下:


apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
...
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1

 maxSurge为一次性能创建多少个pod,maxUnavailable为一次性能删除多少个容器,我们上面的例子也是可以清楚的看到,每次创建和删除容器的数量都为 1 。这两个配置还可以用前面我们介绍的百分比形式来表示,比如:maxUnavailable=50%,指的是我们最多可以一次删除“50%*DESIRED 数量”个 Pod。

这时的关系图可以更新为如下:

K8s中控制器的用法_第6张图片

有时候我们多次更新配置后会生成多个replicaset,这就显得有点多余了,所以我们可以先暂停更新,等配置都更新完再开启,进而只得到一个replicaset

暂停命令


$ kubectl rollout pause deployment/nginx-deployment
deployment.extensions/nginx-deployment paused

然后你就可以开心的进行各种kubectl edit和kubectl set image等配置了。 

恢复命令


$ kubectl rollout resume deployment/nginx-deployment
deployment.extensions/nginx-deployment resumed

尽管我们已经控制replicaset数量了但是随着技术的更新还是会有很多的replicaset的,所以在Deployment 对象有一个字段,叫作 spec.revisionHistoryLimit,就是 Kubernetes 为 Deployment 保留的“历史版本”个数。所以,如果把它设置为 0,你就再也不能做回滚操作了。直接辞职跑路

回滚

可通过以下命令回滚:

kubectl rollout undo deployment/nginx-deployment

或者

kubectl rollout undo deployment/nginx-deployment --version=

 我们先查看一下我们nginx镜像:

镜像为nginx:1.9.1 

K8s中控制器的用法_第7张图片

回滚到我们之前的1.8版本:

 通过上面命令我们已经回滚到1.8版本。

 若要回滚到指定版本的命令为:

先查看版本号,选择要更新的版本:
root@master01:/opt/k8s/controller# kubectl rollout history deployment nginx-deployment 
deployment.apps/nginx-deployment 
REVISION  CHANGE-CAUSE
2         
3         

可以通过下面更改revision的值来选择版本回滚。
kubectl rollout history deployment/nginx-deployment --revision=2

StatefulSet:

你可能感兴趣的:(kubernetes,linux,运维)