第 4 章 部署

4.1. 了解 Deployment 和 DeploymentConfig

OpenShift Container Platform 中的 DeploymentDeploymentConfig 是 API 对象,提供两种既相似又不同的方法来细致地管理常见的用户应用程序。由以下独立 API 对象组成:

  • DeploymentConfig 或 Deployment,各自将应用程序特定组件的所需状态描述为 Pod 模板。
  • DeploymentConfig 涉及一个或多个 ReplicationController,其包含 DeploymentConfig 状态的时间点记录,作为 Pod 模板。同样,Deployment 涉及一个或多个 ReplicaSet,即 ReplicationController 的后续。
  • 一个或多个 Pod,代表应用程序某一特定版本的实例。

4.1.1. 部署构建块

Deployment 和 DeploymentConfig 各自通过使用原生 Kubernetes API 对象 ReplicaSet 和 ReplicationController 来启用,作为构建块。

用户不必操控 ReplicationController、ReplicaSet,或者 DeploymentConfig 或 Deployment 拥有的 Pod。部署系统可确保正确传播更改。

提示

如果现有部署策略不适用于您的用例,而且必须在部署的生命周期内执行手动步骤,那么应考虑创建自定义部署策略。

以下部分详细介绍了这些对象。

4.1.1.1. ReplicationController

ReplicationController 确保任何时候都运行指定数量的 Pod 副本。如果 Pod 退出或被删除,ReplicationController 会做出反应,实例化更多 Pod 来达到定义的数量。同样,如果运行中的数量超过所需的数目,它会根据需要删除相应数量的 Pod,使其与定义的数量相符。

ReplicationController 配置包括:

  • 所需的副本数(可在运行时调整)。
  • 创建复制 Pod 时要使用的 Pod 定义。
  • 用于标识受管 Pod 的选择器。

选择器是分配给由 ReplicationController 管理的 Pod 的一组标签。这些标签包含在 ReplicationController 实例化的 Pod 定义中。ReplicationController 使用选择器来决定已在运行的 Pod 实例数量,以便根据需要进行调整。

ReplicationController 不负责根据负载或流量执行自动扩展,也不进行跟踪。相反,这需要由外部自动缩放器调整其副本数。

以下是 ReplicationController 的示例定义:

apiVersion: v1
kind: ReplicationController
metadata:
  name: frontend-1
spec:
  replicas: 1  1
  selector:    2
    name: frontend
  template:    3
    metadata:
      labels:  4
        name: frontend 5
    spec:
      containers:
      - image: openshift/hello-openshift
        name: helloworld
        ports:
        - containerPort: 8080
          protocol: TCP
      restartPolicy: Always
1
要运行的 Pod 副本数。
2
要运行的 Pod 的标签选择器。
3
控制器创建的 Pod 模板。
4
Pod 上的标签应该包括标签选择器中的标签。
5
扩展任何参数后的最大名称长度为 63 个字符。

4.1.1.2. ReplicaSet

与 ReplicationController 类似,ReplicaSet 也是一个原生 Kubernetes API 对象,可以确保在任意给定时间运行指定数量的 Pod 副本。ReplicaSet 和 ReplicationController 之间的区别在于,ReplicaSet 支持基于集合的选择器要求,而 ReplicationController 只支持基于相等的选择器要求。

注意

只有您需要自定义更新编配或根本不需要更新时才可使用 ReplicaSet。否则,请使用 Deployment。ReplicaSet 可以独立使用,但由部署用于编配 Pod 创建、删除和更新。部署自动管理其 ReplicaSet,为 Pod 提供声明性更新,而且不需要手动管理它们创建的 ReplicaSet。

以下是 ReplicaSet 定义示例:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend-1
  labels:
    tier: frontend
spec:
  replicas: 3
  selector: 1
    matchLabels: 2
      tier: frontend
    matchExpressions: 3
      - {key: tier, operator: In, values: [frontend]}
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - image: openshift/hello-openshift
        name: helloworld
        ports:
        - containerPort: 8080
          protocol: TCP
      restartPolicy: Always
1
对一组资源进行的标签查询。matchLabelsmatchExpressions 的结果在逻辑上是组合在一起的。
2
基于相等的选择器,使用与选择器匹配的标签指定资源。
3
基于集合的选择器,用于过滤键。这将选择键等于 tier 并且值等于 frontend 的所有资源。

4.1.2. DeploymentConfig

在 ReplicationController 的基础上,OpenShift Container Platform 在 DeploymentConfig 概念中添加了对软件开发和部署生命周期的支持。在最简单的情形中,DeploymentConfig 会创建一个新的 ReplicationController,并允许它启动 Pod。

但是,从 DeploymentConfig 部署 OpenShift Container Platform 也支持从镜像的现有部署过渡到新部署,还支持定义可在创建 ReplicationController 之前或之后运行的 hook。

DeploymentConfig 部署系统提供以下功能:

  • DeploymentConfig,它是运行应用程序的模板。
  • 为响应事件而触发自动化部署的触发器。
  • 用户可自定义的部署策略,用于从上一版本过渡到新版本。策略在 Pod 内运行,通常称为部署流程。
  • 一组 hook(生命周期 hook),用于在部署生命周期的不同点上执行自定义行为。
  • 应用程序的版本控制,以便在部署失败时支持手动或自动的回滚。
  • 复制的手动扩展和自动扩展。

在创建 DeploymentConfig 时,会创建一个 ReplicationController 来代表 DeploymentConfig 的 Pod 模板。如果 DeploymentConfig 发生变化,则会使用最新的 Pod 模板创建一个新的 ReplicationController,同时运行部署流程来缩减旧 ReplicationController 并扩展新的 ReplicationController。

在创建时,自动从服务负载均衡器和路由器中添加和移除应用程序的实例。只要应用程序支持接收 TERM 信号时安全关机,您可以确保运行的用户连接拥有正常完成的机会。

OpenShift Container Platform DeploymentConfig 对象定义以下详细信息:

  1. ReplicationController 定义的元素。
  2. 自动创建新部署的触发器。
  3. 在部署之间过渡的策略。
  4. 生命周期 hook。

每次触发部署时,不论是手动还是自动,部署器 Pod 会管理部署,包括缩减旧的 ReplicationController、扩展新的 ReplicationController,以及运行 hook。部署 Pod 在完成 Deployment 后无限期保留,以保存其 Deployment 日志。当部署被另一个部署替换时,上一 ReplicationController 会保留下来,以便在需要时轻松回滚。

DeploymentConfig 定义示例

apiVersion: v1
kind: DeploymentConfig
metadata:
  name: frontend
spec:
  replicas: 5
  selector:
    name: frontend
  template: { ... }
  triggers:
  - type: ConfigChange 1
  - imageChangeParams:
      automatic: true
      containerNames:
      - helloworld
      from:
        kind: ImageStreamTag
        name: hello-openshift:latest
    type: ImageChange  2
  strategy:
    type: Rolling      3

1
每当 ReplicationController 模板更改时,ConfigChange 触发器会引发创建新的 Deployment。
2
每当指定镜像流中有新版本的后备镜像可用时,ImageChange 触发器引发创建新的 Deployment。
3
默认的 Rolling 策略会在 Deployment 之间实现无停机过渡。

4.1.3. 部署

Kubernetes 在 OpenShift Container Platform 中提供了一流的原生 API 对象类型,名为 Deployment。Deployment 充当 OpenShift Container Platform 专用 DeploymentConfig 的后代。

与 DeploymentConfig 一样,Deployment 将应用程序特定组件的所需状态描述为 Pod 模板。Deployment 创建 ReplicaSet,后者负责编配 Pod 生命周期。

例如,以下 Deployment 定义创建用于调出一个 hello-openshift Pod 的 ReplicaSet:

Deployment 定义

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-openshift
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-openshift
  template:
    metadata:
      labels:
        app: hello-openshift
    spec:
      containers:
      - name: hello-openshift
        image: openshift/hello-openshift:latest
        ports:
        - containerPort: 80

4.1.4. 比较 Deployment 和 DeploymentConfig

Kubernetes Deployment 和 OpenShift Container Platform 提供的 DeploymentConfig 均在 OpenShift Container Platform 中受到支持;不过,建议您使用 Deployment,除非需要 DeploymentConfig 提供的特定功能或行为。

以下部分详细阐述两种对象之间的区别,以进一步协助您决定使用哪一种类型。

4.1.4.1. 设计

Deployment 和 DeploymentConfig 之间的一大区别在于每种设计都为推出部署过程而选择的 CAP 原理。DeploymentConfig 以一致性为先,而 Deployment 更重视可用性。

对于 DeploymentConfig,如果运行一个部署器 Pod 的节点停机,它不会被替换掉。流程会等待节点重新在线或被手动删除。手动删除节点也会删除对应的 Pod。这意味着您无法删除 Pod 来取消推出部署,因为 kubelet 负责删除相关联的 Pod。

但是,Deployment 推出部署由控制器管理器推进。控制器管理器在 master 上运行高可用性模式,并使用群首选举算法提高可用性与一致性相比的价值。在故障期间,其他 master 有可能同时对同一 Deployment 做出反应,但这个问题会在故障发生后很快进行调节。

4.1.4.2. DeploymentConfig 相关功能

自动回滚

目前,在出现故障时,Deployment 不支持自动回滚到上次成功部署的 ReplicaSet。

触发器

Deployment 有一个隐式 ConfigChange 触发器 (trigger),每次更改部署的 Pod 模板都会自动触发新的推出部署。如果您不想在 Pod 模板更改时进行新的推出部署,请暂停部署:

$ oc rollout pause deployments/<name>
生命周期 hook

Deployment 尚不支持任何生命周期 hook。

自定义策略

Deployment 尚不支持用户指定的自定义部署策略。

4.1.4.3. Deployment 相关功能

滚动

Deployment 的部署过程是由控制器循环推动的,这与使用部署器 Pod 进行每次新推出部署的 DeploymentConfig 相反。这意味着,Deployment 可以拥有尽可能多的活跃 ReplicaSet,最终部署控制器将缩减所有旧 ReplicaSet,并扩展最新的 ReplicaSet。

DeploymentConfig 最多可以运行一个部署器 Pod,否则多个部署器之间会产生冲突,试图扩展它们认为应该是最新的 ReplicationController。因此,任意时间点上只能有两个 ReplicationController 处于活跃状态。最终,这会转化为 Deployment 能够更快地进行推出部署。

按比例扩展

因为 Deployment 控制器是提供 Deployment 所拥有的新旧 ReplicaSet 的大小的唯一来源,所以它能够对正在推出(rollout)的部署进行扩展。额外的副本会根据每个 ReplicaSet 的大小按比例分发。

当一个推出部署(rollout)正在进行时无法扩展 DeploymentConfig,因为 DeploymentConfig 控制器会遇到部署器进程中有关新 ReplicationController 大小的问题。

中途暂停推出部署

Deployment 可以在任何时间暂停,这意味着可以暂停正在进行的推出部署。另一方面,当前还无法暂停部署器 Pod。因此,如果您尝试在推出部署进行期间暂停 DeploymentConfig,则部署器进程不受影响,它会继续运行直到完成为止。