“ Kubernetes的核心,编排简析”
应用进阶,编排简析
01.编排简析
“编排“,应该是Kubernetes项目最核心的功能了,先来看一看”控制器“模型。
Podcast这个API对象,实际上就是对容器的进一步抽象和封装。因为容器镜像虽然很好,但是用来描述应用,还是太简单了。Pod对象,可以看出是容器的升级版,对容器进行了组合,添加了更多的属性和字段。而Kubernetes操作它的逻辑,都是由Controller(控制器)完成的。
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.7.9
ports:
- containerPort: 80
这个Deployment定义了:确保携带了app=nginx标签的Pod个数,永远等于spec.replicas知道的个数,2.
当这个集群中携带app=nginx标签的Pod个数大于2时,旧的Pod会被删除,反之,新的Pod就会被建立。而这一过程,都是由kube-controller-manager组件来控制的。
控制器都是遵循Kubernetes项目的通用编排模式,控制循环(controll loop),可以通过一段伪代码来大致理解下:
for {
实际状态 := 获取集群中对象 X 的实际状态(ActualState)
期望状态 := 获取集群中对象 X 的期望状态(DesiredState)
if 实际状态 == 期望状态{
什么都不做
}else {
执行编排动作,将实际状态调整为期望状态
}
}
实际状态往往来自于Kubernetes本身,而期望状态一般来自于用户提交的YAML文件。
-
Deployment控制器从etcd中获取到所有携带了“app: nginx“标签的Pod,然后统计他们的数量,这就是实际状态。
-
Deployment对象的Replicas字段的值就是期望状态。
-
Deployment控制器将两个状态做比较,然后根据比较结果,确定时创建Pod,还是删除已有的Pod。
第三步的对比过程,通常被叫做调谐(Reconcile),这个调谐的过程,则被称作“Reconcile Loop“(调谐循环)或者”Sync Loop“(同步循环)。调谐的最终结果往往都是对被控制对象的某种读写操作。比如增加Pod,删除已有的Pod,或者更新Pod的某个字段,这也是Kubernetes”面向API对象编程“的直观体现,也就是用一种对象来管理另一种对象。
02.控制器模式
控制对象本身,负责定义被管理对象的期望状态,比如Replicas=2字段,而被控制对象的定义,则来自于一个“模板“,比如template字段,它有一个专有名字,PodTemplate(Pod模板)
类似Deployment这样的一个控制器,都是由上半部分的控制器定义(包括期望状态)和下半部分的被控制对象的模板组成的。
Kubernetes项目通过一个称为“控制器模式“(controller pattern)的设计方法,来统一的实现对各种不同的对象或者资源进行的编排操作。
03.Deployment的完整实现
Deployment实现了Kubernetes项目中的一个非常重要的功能:Pod的“水平扩展/收缩”(horizontalscaling out/in)功能。
如果更新了Deployment的Pod模板,那么Deployment就需要遵循一种叫做“滚动更新”(rolling update)的方式,来升级现有的容器。而这个功能的实现,依赖的是Kubernetes项目中的一个非常重要的概念ReplicaSet(API对象)。
ReplicaSet的结构,简单的YAML:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-set
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
一个ReplicaSet对象,就是由副本数目的定义和一个Pod模板组成,就是Deployment的一个子集。同时,Deployment控制器实际操纵的,正是ReplicaSet对象,而不是Pod对象。
普通的Deployment的YAML文件配置如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
-containerPort: 80
ReplicaSet负责通过“控制器模式”,保证系统中Pod的个数永远等于指定的个数。同时Deployment通过“控制器模式”,来操作ReplicaSet的个数和属性,进而实现“水平扩展/收缩”和“滚动更新”这两个编排动作。
下面一起来创建这个nginx-deployment:
$ kubectl create -f nginx-deployment.yaml
检查deployment的状态
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 0 0 0 1s
DESIRED:用户期望的Pod副本个数(spec.replicas的值)
CURRENT:当前处于running状态的Pod的个数
UP-TO-DATE:当前处于最新版本的Pod个数,最新版本是指Pod的Sepc部分与Deployment里Pod模板里定义的一致
AVAILABLE:当前已经可用的Pod个数,即:既是Running状态,又是最新版本,并且已经处于ready(健康检查正确)状态的Pod个数。
实时查看Deployment的状态变化:
$ kubectl rollout statusdeployment/nginx-deployment
Waiting for rollout to finish: 2 out of 3new replicas have been updated…
deployment.apps/nginx-deploymentsuccessfully rolled out
查看Deployment所控制的ReplicaSet信息:
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-3167673210 3 3 3 20s
用户提交了一个Department对象之后,Department Controller立即会创建一个Pod副本为3的ReplicaSet。
触发水平扩展:
$ kubectl scale deployment nginx-deployment–replicas=4
deployment.apps/nginx-deployment scaled
此时,如果修改Deployment的Pod模板,“滚动更新”就会被触发:
$ kubectl edit deployment/nginx-deployment
…
spec:
containers:
- name: nginx
image: nginx:1.9.1 # 1.7.9 -> 1.9.1
ports:
- containerPort: 80
…
deployment.extensions/nginx-deploymentedited
查看滚动更新流程
$ kubectl describe deployment nginx-deployment
…
Events:
Type Reason Age From Message
…
Normal ScalingReplicaSet 24s deployment-controller Scaled upreplica set nginx-deployment-1764197365 to 1
Normal ScalingReplicaSet 22s deployment-controller Scaled downreplica set nginx-deployment-3167673210 to 2
Normal ScalingReplicaSet 22s deployment-controller Scaled upreplica set nginx-deployment-1764197365 to 2
Normal ScalingReplicaSet 19s deployment-controller Scaled downreplica set nginx-deployment-3167673210 to 1
Normal ScalingReplicaSet 19s deployment-controller Scaled upreplica set nginx-deployment-1764197365 to 3
Normal ScalingReplicaSet 14s deployment-controller Scaled down replica setnginx-deployment-3167673210 to 0
Department Controller会创建一个新的ReplicaSet,然后新旧两个ReplicaSet会交替新建、删除各自的Pod。
更新过程完成后,查看状态
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-1764197365 3 3 3 6s
nginx-deployment-3167673210 0 0 0 30s
Deployment实际上是一个两层控制器。首先,它通过ReplicaSet的个数来描述应用的版本;然后,它再通过ReplicaSet的属性,来保证Pod的副本数量。