K8s中控制器的用法
所有的控制器集合都是在kube-controller-manager中完成的。master节点基础插件有kube-schedulerr、kube-apiserver、kube-contoller-manager这三个的。控制器都遵循 Kubernetes 项目中的一个通用编排模式,即:控制循环(control loop)。比如,现在有一种待编排的对象 X,它有一个对应的控制器。
目录
所有的控制器集合都是在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的关系如下所示:
会发现多了一个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的数量。
- 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。可通过以下查看:
水平扩展/收缩
增加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 <none> 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。
我们describe一下我们的deployment,看一下events
一共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。
这时的关系图可以更新为如下:
有时候我们多次更新配置后会生成多个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
回滚到我们之前的1.8版本:
通过上面命令我们已经回滚到1.8版本。
若要回滚到指定版本的命令为:
先查看版本号,选择要更新的版本:
root@master01:/opt/k8s/controller# kubectl rollout history deployment nginx-deployment
deployment.apps/nginx-deployment
REVISION CHANGE-CAUSE
2 <none>
3 <none>
可以通过下面更改revision的值来选择版本回滚。
kubectl rollout history deployment/nginx-deployment --revision=2
StatefulSet:
更多推荐
所有评论(0)