成对应的Replica Set并完成Pod副本的创建过程。
检查Deployment的状态来看部署动作是否完成(Pod副本的数量是否达到预期的值)。
更新Deployment以创建新的Pod(比如镜像升级)。
如果当前Deployment不稳定,则回滚到一个早先的Deployment版本。
暂停Deployment以便于一次性修改多个PodTemplateSpec的配置项,之后再恢复Deployment,进行新的发布。
扩展Deployment以应对高负载。
查看Deployment的状态,以此作为发布是否成功的指标。
清理不再需要的旧版本ReplicaSets。
 Deployment的定义与Replica Set的定义很类似,除了API声明与Kind类型等有所区别:
apiVersion: extensions/v1beta1 apiVersion: v1
kind: Deployment kind: ReplicaSet
metadata: metadata:
name: nginx-deployment name: nginx-repset
 下面我们通过运行一些例子来一起直观地感受这个新概念。首先创建一个名为tomcat-deployment.yaml的Deployment描述文件,内容如下:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 1
selector:
matchLabels:
tier: frontend
matchExpressions: - {key: tier, operator: In, values: [frontend]} template:
metadata:
labels:
app: app-demo
tier: frontend
spec:
containers: - name: tomcat-demo
image: tomcat
imagePullPolicy: IfNotPresent
ports: - containerPort: 8080
 运行下述命令创建Deploymeny:
# kubectl create -f tomcat-deployment.yaml
deployment "tomcat-deploy" created
 运行下述命令查看Deployment的信息:
# kubectl get deploymentsNAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
tomcat-deploy 1 1 1 1 4m
 对上述输出中涉及的数量解释如下:
DESIRED:Pod副本数量的期望值,即Deployment里定义的Replica。
CURRENT:当前Replica的值,实际上是Deployment所创建的Replica Set里的Replica值,这个值不断增加,直到达到DESIRED为止,表明整个部署过程完成。
UP-TO-DATE:最新版本的Pod副本数量,用于指示在滚动升级的过程中,有多少个Pod副本已经成功升级。
AVAILABLE:当前集群中可用的Pod副本数量,即集群中当前存活的Pod数量。
 运行下述命令查看对应的Replica Set,我们看到它的命名与Deployment的名字有关系:
# kubectl get rs
NAME DESIRED CURRENT AGE
tomcat-deploy-1640611518 1 1 1m
 运行下述命令查看创建的Pod,我们发现Pod的命名以Deployment对应的Replica Set的名字为前缀,这种命名很清晰地表明了一个Replica Set创建了哪些Pod,对于滚动升级这种复杂的过程来说,很容易排查错误:
# kubectl get pods
NAME READY STATUS RESTARTS AGE
tomcat-deploy-1640611518-zhrsc 1/1 Running 0 3m
 运行kubectl describe deployments,可以清楚地看到Deployment控制的Pod的水平扩展过程,详见第2章的说明,这里不再赘述。
 Pod的管理对象,除了RC和Deployment,还包括ReplicaSet、DaemonSet、StatefulSet、Job等,分别用于不同的应用场景中,将在第2章中进行详细介绍。
1.4.7 Horizotal(水平的) Pod Autoscaler(自动伸缩器)
 在前两节提到过,通过手工执行kubectl scale命令,我们可以实现Pod扩容或缩容,如果仅仅到此为止,显然不符合谷歌对Kubernetes的定位目标----自动化、智能化。在谷歌看来,分布式系统要能够根据当前负载的变化情况自动触发水平扩展或缩容的行为,因为这一过程可能是频繁发生的、不可预料的,所以手动控制的方式是不现实的。
 因此,Kubernetes的v1.0版本实现后,这帮大牛们就已经在默默研究Pod智能扩容的特性了,并在Kubernetes v1.1的版本中首先发布这一重量级新特性----Horizotal Pod Autoscaler(Pod横向自动扩容,简称HPA)。随后的v1.2版本中HPA被升级为稳定版本(apiVersion:autoscaling/v1),但同时仍然保留旧版本(apiVersion:extensions/v1beta1)。从v1.6版本开始,对根据应用自定义指标进行自动扩容和缩容的功能进行增强,API版本为autoscaling/v2alpha1,仍在不断演进过程中。
 HPA与之前的RC、Deployment一样,也属于一种Kubernetes资源对象。通过追踪分析RC控制的所有目标Pod的负载变化情况,来确定是否需要针对性地调整目标Pod的副本数,这是HPA的实现原理。当前,HPA可以有以下两种方式作为Pod负载的度量指标。
 CPUUtilizationPercentage是一个算数平均值,即目标Pod所有副本自身的CPU利用率的平均值。一个Pod自身的CPU利用率是该Pod当前CPU的使用量除以它的Pod Request的值,比如我们定义一个Pod的Pod Request为0.4,而当前Pod的CPU使用量为0.2,则它的CPU使用率为50%。如此一来,我们就可以就算出来一个RC控制的所有Pod副本的CPU利用率的算术平均值了。如果某一时刻CPUUtilizationPercentage的值超过80%,则意味着当前的Pod的副本数很可能不足以支撑接下来更多的请求,需要进行动态扩容,而当请求高峰时刻过去后,Podd的CPU利用率又会降下来,此时对应的Pod副本数应该自动减少到一个合理的水平。
 CPUUtilizationPercentage计算过程中使用到的Pod的CPU使用量通常1min内的平均值,目前通过查询Heapster扩展组件来得到这个值,所以需要安装部署Heapster,这样一来便增加了系统的复杂度和实施HPA特性的复杂度,因此,未来的计划是Kubernetes自身实现一个基础性能数据采集模块,从而更好地支持HPA和其他需要用到基础性能数据的功能模块。此外,我们也看到,如果目标Pod没有定义Pod Request的值,则无法使用CPUUtilizationPercentage来实现Pod横向自动扩容的能力。除了使用CPUUtilizationPercentage,Kubernetes从v1.2版本开始尝试支持应用程序自定义的度量指标,目前仍然为实验特性,不建议在生产环境中使用。
 下面是HPA定义的一个具体例子:
apiVersion: autoscaling/v1
kind: HorizotalPodAutoscaler
metadata:
name: php-apache
namesapce: defaultspec:
maxReplicas: 10
minReplicas: 1
scaleTargeRef:
kind: Deployment
name: php-apache
targetCPUUtilizationPercentage: 90
 根据上面的定义,我们可以知道这个HPA控制的目标对象为一个名为php-apache的Deployment里d的Pod副本,当这些Pod副本的CPUUtilizationPercentage的值超过90%时会触发自动扩容行为,扩容或缩容时必须满足的一个约束条件是Pod的副本数要介于1与10之间。
 除了可以通过直接定义yaml文件并且调用kubectl create的命令来创建一个HPA资源对象的方式,我们还能通过下面的简单命令行直接创建等价的HPA对象:
# kubectl autoscale deployment php-apache --cpu-percent=90 --min=1 --max=10
 第二章将会给出一个完整的HPA例子来说明其用法和功能。
1.4.8 StatefulSet
 在Kubernetes系统中,Pod的管理对象RC、Deployment、DaemonSet和Job都是面向无状态的服务。但现实中有很多服务是有状态的,特别是一些复杂的中间件集群,例如MySQL集群、MongoDB集群、Kafka集群、Zookeeper集群等,这些应用集群有以下一些共同点。
每个节点都有固定的身份ID,通过这个ID,集群中的成员可以相互发现并且通信。
集群的规模是比较固定的,集群规模不能随意变动。
集群里的每个节点都是有状态的,通常会持久化数据到永久存储中。
如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损。
 如果用RC/Deployment控制Pod副本数的方式来实现上述有状态的集群,则我们会发现第一点是无法满足的,因为Pod的名字是随机产生的,Pod的IP地址也是在运行期才确定且可能有变动的,我们事先无法为每个Pod确定唯一不变的ID,为了能够在其他节点上恢复某个失败的节点,这种集群中的Pod需要挂接某种共享存储,为了解决这个问题,Kubernetes从v1.4版本开始引入了PetSet这个新的资源对象,并且在v1.5版本时更名为StatefulSet,StatefulSet从本质上来说,可以看作Deployment/RC的一个特殊变种,它有如下一些特性。
StatefulSet里的每个Pod都有稳定、唯一的网络标识,可以用来发现集群内的其他成员。假设StatefulSet的名字叫kafka,那么第一个Pod叫kafak-0,第二个Pod叫kafak-1,以此类推。
StatefulSet控制的Pod副本的启停顺序是受控的,操作第n个Pod时,前n-1个Pod已经时运行且准备好的状态。
StatefulSet里的Pod采用稳定的持久化存储卷,通过PV/PVC来实现,删除Pod时默认不会删除与StatefulSet相关的存储卷(为了保证数据的安全)。
 StatefulSet除了要与PV卷捆绑使用以存储Pod的状态数据,还要与Headless Service配合使用,即在每个StatefulSet的定义中要声明它属于哪个Headless Service。Headless Service与普通Service的关键区别在于,它没有Cluster IP,如果解析Headless Service的DNS域名,则返回的是该Service对应的全部Pod的Endpoint列表。StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod实例创建了一个DNS域名,这个域名的格式为:
$(podname).$(headless service name)