云原生架构进阶实战
上QQ阅读APP看书,第一时间看更新

2.4 部署

Kubernetes中的部署是指如何控制一组Pod的运行状态使其满足生产需要。部署分为无状态部署和有状态部署。无论哪种部署,其内部都有副本集控制功能。首先了解ReplicaSet是如何控制副本数量的。

2.4.1 ReplicaSet

ReplicaSet的目的是维护一组状态稳定的Pod副本,从而保证指定数量的相同Pod的可用性。它主要通过以下声明来控制副本数量:

之前曾有ReplicationController,后来逐渐被ReplicaSet替代。

ReplicaSet声明文件中,需要Pod模板以进行复制,同时也需要标签选择器.spec.selector.matchLabels以选择当前Pod的副本。在nfs-provisioner的模板声明文件中有标签为app:nfs-provisioner的选择器,部分代码如下:

请注意,.spec.template.metadata.labels必须和.spec.selector.matchLabels匹配,否则无法创建ReplicaSet。

在Pod运行过程中,也可以通过kubectl scale命令手动调整副本数量:

也可以自动调整ReplicaSet的副本数量,下面的命令是对foo这个ReplicaSet Controller设置自动调整规则——最多5个副本,而且在CPU使用率达到80%的时候需要增加副本。

在Kubernetes中,自动分配副本数量的算法如下:

例如当前副本数量是2,CPU度量值为200MHz,期望度量值为100MHz,则应当的副本数量为200/100=2。如果当前CPU度量值为300MHz,而期望度量值为200MHz,则应当的副本数量为300/200=1.5,进位取整后为2。所以不需要调整副本数量。

除了通过命令来控制Pod副本数量,还可以通过声明文件来控制,其类型为HorizontalPodAutoscaler。以下声明和命令的效果是一致的。

请注意,自动调整Pod副本数量的依据是度量值。在上面的例子中是通过CPU的averageUtilization来进行判断的,也可以根据Value、AverageValue、requests-per-second、packets-per-second等度量值来进行判断。

Kubernetes从1.8版本开始使用额外的工具Metrics Server(https://github.com/kubernetes-incubator/metrics-server)收集度量指标,因此需要单独安装Metrics Server。安装完成后,若出现无法收集指标的故障,则需要修改metrics-server-depolyment.yaml文件,添加args参数,然后重新应用该文件。修改部分代码如下:

2.4.2 部署

部署(Deployment)是一个拥有ReplicaSet并通过声明来控制Pod滚动、更新的对象。虽然ReplicaSet可以独立使用,但是它主要被用作协调Pod创建、删除和更新的机制。使用部署时,用户不必担心副本集,因为部署通过ReplicaSet进行管理,所以,本书建议使用部署而不是ReplicaSet。

下面是一个部署的声明文件,部署了3个nginx的Pod副本:

这个例子与ReplicaSet的示例是一样的,这是因为部署通过ReplicaSet来控制副本数量。但是如何更新副本数量,则是部署的职责,其通过StrategyType、RollingUpdateStrategy等属性来控制如何更新Pod副本。

.spec.strategy.type的可选值有重建(Recreate)和滚动更新(RollingUpdate)。Recreate是指重建所有Pod,其过程为先终止Pod所有的副本,然后重新创建指定数量的Pod副本。而RollingUpdate则采取一定的控制策略来逐步更新Pod副本。

.spec.strategy.rollingUpdate.maxUnavailable是一个可选字段,是指更新过程中最大不可用的Pod数量。该值可以是绝对数值,也可以是百分比。其默认值为25%。例如,如果该值为25%,则原有部署中的ReplicaSet立刻将副本数量缩减为75%,然后准备新的Pod副本,再继续控制25%的不可用的比例,逐步缩减原有Pod副本,直至所有Pod更新完成。

.spec.strategy.rollingUpdate.maxSurge也是一个可选字段。它指定了Pod副本的最大副本数量。例如取默认值为25%,则在更新部署时可创建的Pod副本数量是期望副本数量的125%。

.spec.minReadySeconds是一个可选字段,默认为0。它指明新创建的Pod在没有任何容器崩溃的情况下到内部应用所需的时间。例如作者所在学校部署Apereo CAS时,在Pod创建完成并running状态下,CAS启动正常还需要约1min,则需设置.spec.minReadySeconds=60。

下面是影响升级过程的几个重要参数:

(1)新的ReplicaSet创建maxSurge所指定数量的Pod副本,此时新旧Pod副本数量为期望副本数量和maxSurge个副本数量之和。

(2)在创建新的Pod副本时,马上从旧的ReplicaSet中删除maxUnavailable个Pod。这时可用Pod副本数量为期望副本数量减去maxUnavailable。

(3)当新创建的Pod副本有一个可用时,马上从旧的ReplicaSet中删除一个Pod,如此反复直至所有旧的Pod被新的Pod替换。

这就要求maxUnavailable和maxSurge不能同时为0。

如果在版本升级过程中又触发了更新的版本升级,则Kubernetes会暂停之前版本的替换过程,用最新的版本替换之前刚刚升级的版本,然后再用最新的版本替换还未升级的版本。

部署可以回滚到以前的版本,也支持扩展和自动扩展。

2.4.3 有状态部署

有状态部署(StatefulSets)是用于管理有状态应用程序工作负载的一种部署方法。区别于无状态部署(Deployment),StatefulSets可以对Pod副本进行排序并保证每个Pod的唯一性。在无状态部署中,删除一个Pod,新建一个Pod,对于所有Pod来讲都是一致的。但是在StatefulSets中,每个Pod都有唯一的持久标识符,即使在重建后也会继续保留该标识符。

有状态部署适合以下场景:

● 需要独特的网络标识符。

● 需要独立持久的存储。

● 需要有序的部署和扩展。

● 需要有序的升级。

下面演示创建一个nginx的StatefulSet部署。主要内容有:

● 名称为nginx的无头服务。

● 名称为web的StatefulSet。

以上声明文件与无状态部署(Deployment)一致,只是系统在创建后的Pod标识符是唯一且有序数的。

通过kubebctl get pods命令查看,可以看到每个Pod的名称为web-<序数>,而不是web-<随机字符串>。这样,每个Pod也都有自己独立易记且固定的主机名称,例如web-0,其FQDN为web-0.nginx.default.svc.cluster.local。

每个Pod的存储卷也是特定的,不能混用。而且删除Pod时,为了保留该状态,持久卷不会自动删除。

在StatefulSet中Pod的部署过程与无状态部署完全不同。在无状态部署中,Pod副本并发创建,而在有状态部署中,Pod是依次顺序创建。在上例中,web-0、web-1和web-2是依次创建,而且web-1是在web-0创建完成并且正常运行后再创建。如果要删除部署,则顺序恰好相反,最晚创建的容器被最早删除。

2.4.4 DaemonSet

一个DaemonSet确保每个节点上只运行一个副本。若有节点添加到集群中,将在新增的节点上运行唯一一个Pod,若节点删除,则从该节点上终止Pod。

DaemonSet适合以下场景:

● 每个节点上运行集群存储后台驻留程序,例如glusterd、ceph。

● 每个节点上运行日志守护程序,例如fluentd、logstash。

● 每个节点上运行Prometheus node exporter、sisdig、collectd等代理。

DaemonSet的示例在此不再详述,在讲解日志和监控时会详细描述DaemonSet。