Kubernetes 学习笔记 4 工作负载 Deployments
https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/
工作负载是在 Kubernetes 上运行的应用程序。
无论你的负载是单一组件还是由多个一同工作的组件构成,在 Kubernetes 中你 可以在一组 Pods 中运行它。 在 Kubernetes 中,Pod 代表的是集群上处于运行状态的一组 容器。
Kubernetes Pods 有确定的生命周期。 例如,当某 Pod 在你的集群中运行时,Pod 运行所在的 节点 出现致命错误时, 所有该节点上的 Pods 都会失败。Kubernetes 将这类失败视为最终状态: 即使该节点后来恢复正常运行,你也需要创建新的 Pod 来恢复应用。
不过,为了让用户的日子略微好过一些,你并不需要直接管理每个 Pod。 相反,你可以使用 负载资源 来替你管理一组 Pods。 这些资源配置 控制器 来确保合适类型的、处于运行状态的 Pod 个数是正确的,与你所指定的状态相一致。
Kubernetes 提供若干种内置的工作负载资源:
- Deployment 和 ReplicaSet (替换原来的资源 ReplicationController)。
Deployment很适合用来管理你的集群上的无状态应用,Deployment中的所有Pod都是相互等价的,并且在需要的时候被换掉。 - StatefulSet 让你能够运行一个或者多个以某种方式跟踪应用状态的 Pods。 例如,如果你的负载会将数据作持久存储,你可以运行一个
StatefulSet,将每个Pod与某个PersistentVolume对应起来。你在StatefulSet中各个Pod内运行的代码可以将数据复制到同一StatefulSet中的其它Pod中以提高整体的服务可靠性。
- DaemonSet 定义提供节点本地支撑设施的
Pods。这些 Pods 可能对于你的集群的运维是 非常重要的,例如作为网络链接的辅助工具或者作为网络 插件 的一部分等等。每次你向集群中添加一个新节点时,如果该节点与某DaemonSet的规约匹配,则控制面会为该DaemonSet调度一个Pod到该新节点上运行。 - Job 和 CronJob。 定义一些一直运行到结束并停止的任务。
Job用来表达的是一次性的任务,而CronJob会根据其时间规划反复运行。
在庞大的 Kubernetes 生态系统中,你还可以找到一些提供额外操作的第三方 工作负载资源。通过使用 定制资源定义(CRD), 你可以添加第三方工作负载资源,以完成原本不是 Kubernetes 核心功能的工作。 例如,如果你希望运行一组 Pods,但要求所有 Pods 都可用时才执行操作 (比如针对某种高吞吐量的分布式任务),你可以实现一个能够满足这一需求 的扩展,并将其安装到集群中运行。
Deployments
一个 Deployment 为 Pods 和 ReplicaSets 提供声明式的更新能力。
你负责描述 Deployment 中的 目标状态,而 Deployment 控制器(Controller) 以受控速率更改实际状态, 使其变为期望状态。你可以定义 Deployment 以创建新的 ReplicaSet,或删除现有 Deployment, 并通过新的 Deployment 收养其资源。
用例
以下是 Deployments 的典型用例:
- 创建 Deployment 以将 ReplicaSet 上线。 ReplicaSet 在后台创建 Pods。 检查 ReplicaSet 的上线状态,查看其是否成功。
- 通过更新 Deployment 的 PodTemplateSpec,声明 Pod 的新状态 。 新的 ReplicaSet 会被创建,Deployment 以受控速率将 Pod 从旧 ReplicaSet 迁移到新 ReplicaSet。 每个新的 ReplicaSet 都会更新 Deployment 的修订版本。
- 如果 Deployment 的当前状态不稳定,回滚到较早的 Deployment 版本。 每次回滚都会更新 Deployment 的修订版本。
- 扩大 Deployment 规模以承担更多负载。
- 暂停 Deployment 以应用对 PodTemplateSpec 所作的多项修改, 然后恢复其执行以启动新的上线版本。
- 使用 Deployment 状态 来判定上线过程是否出现停滞。
- 清理较旧的不再需要的 ReplicaSet
创建 Deployment
下面是 Deployment 示例。其中创建了一个 ReplicaSet,负责启动三个 nginx Pods:
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.14.2 ports: - containerPort: 80
在该例中:
- 创建名为
nginx-deployment(由.metadata.name字段标明)的 Deployment。 - 该 Deployment 创建三个(由
replicas字段标明)Pod 副本。
-
selector字段定义 Deployment 如何查找要管理的 Pods。 在这里,你选择在 Pod 模板中定义的标签(app: nginx)。 不过,更复杂的选择规则是也可能的,只要 Pod 模板本身满足所给规则即可。说明:spec.selector.matchLabels字段是{key,value}键值对映射。 在matchLabels映射中的每个{key,value}映射等效于matchExpressions中的一个元素, 即其key字段是 “key”,operator为 “In”,values数组仅包含 “value”。 在matchLabels和matchExpressions中给出的所有条件都必须满足才能匹配。
template字段包含以下子字段:- Pod 被使用
labels字段打上app: nginx标签。 - Pod 模板规约(即
.template.spec字段)指示 Pods 运行一个nginx容器, 该容器运行版本为 1.14.2 的nginxDocker Hub镜像。 - 创建一个容器并使用
name字段将其命名为nginx。
- Pod 被使用
1 通过运行以下命令创建 Deployment :
kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
2 运行 kubectl get deployments 检查 Deployment 是否已创建。如果仍在创建 Deployment, 则输出类似于:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 3 0 0 0 1s
3 要查看 Deployment 上线状态,运行 kubectl rollout status deployment/nginx-deployment
deployment "nginx-deployment" successfully rolled out
4 几秒钟后再次运行 kubectl get deployments。输出类似于:
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx-deployment 3 3 3 3 18s
5 要查看 Deployment 创建的 ReplicaSet(rs),运行 kubectl get rs。 输出类似于:
NAME DESIRED CURRENT READY AGE nginx-deployment-75675f5897 3 3 3 18s
6 要查看每个 Pod 自动生成的标签,运行 kubectl get pods --show-labels。返回以下输出:
NAME READY STATUS RESTARTS AGE LABELS nginx-deployment-75675f5897-7ci7o 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453 nginx-deployment-75675f5897-kzszj 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453 nginx-deployment-75675f5897-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=3123191453
说明: 你必须在 Deployment 中指定适当的选择算符和 Pod 模板标签(在本例中为
app: nginx)。 标签或者选择算符不要与其他控制器(包括其他 Deployment 和 StatefulSet)重叠。 Kubernetes 不会阻止你这样做,但是如果多个控制器具有重叠的选择算符,它们可能会发生冲突 执行难以预料的操作
Pod-template-hash 标签
Deployment 控制器将 pod-template-hash 标签添加到 Deployment 所创建或收留的 每个 ReplicaSet
此标签可确保 Deployment 的子 ReplicaSets 不重叠。 标签是通过对 ReplicaSet 的 PodTemplate 进行哈希处理。 所生成的哈希值被添加到 ReplicaSet 选择算符、Pod 模板标签,并存在于在 ReplicaSet 可能拥有的任何现有 Pod 中。
更新 Deployment
说明: 仅当 Deployment Pod 模板(即
.spec.template)发生改变时,例如模板的标签或容器镜像被更新, 才会触发 Deployment 上线。 其他更新(如对 Deployment 执行扩缩容的操作)不会触发上线动作。
按照以下步骤更新 Deployment:
1 先来更新 nginx Pod 以使用 nginx:1.16.1 镜像,而不是 nginx:1.14.2 镜像。
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record
或者,可以 edit Deployment 并将 .spec.template.spec.containers[0].image 从 nginx:1.14.2 更改至 nginx:1.16.1。
kubectl edit deployment.v1.apps/nginx-deployment
2 要查看上线状态,运行:
kubectl rollout status deployment/nginx-deployment
获取关于已更新的 Deployment 的更多信息:
在上线成功后,可以通过运行 kubectl get deployments 来查看 Deployment
运行 kubectl get rs 以查看 Deployment 通过创建新的 ReplicaSet 并将其扩容到 3 个副本并将旧 ReplicaSet 缩容到 0 个副本完成了 Pod 的更新操作:
现在运行 kubectl get pods 应仅显示新的 Pods:
Deployment 可确保在更新时仅关闭一定数量的 Pod。默认情况下,它确保至少所需 Pods 75% 处于运行状态(最大不可用比例为 25%)。
Deployment 还确保仅所创建 Pod 数量只可能比期望 Pods 数高一点点。 默认情况下,它可确保启动的 Pod 个数比期望个数最多多出 25%(最大峰值 25%)。
例如,如果仔细查看上述 Deployment ,将看到它首先创建了一个新的 Pod,然后删除了一些旧的 Pods, 并创建了新的 Pods。它不会杀死老 Pods,直到有足够的数量新的 Pods 已经出现。 在足够数量的旧 Pods 被杀死前并没有创建新 Pods。它确保至少 2 个 Pod 可用,同时 最多总共 4 个 Pod 可用。
获取 Deployment 的更多信息
kubectl describe deployments
翻转(多 Deployment 动态更新)
Deployment 控制器每次注意到新的 Deployment 时,都会创建一个 ReplicaSet 以启动所需的 Pods。 如果更新了 Deployment,则控制标签匹配 .spec.selector 但模板不匹配 .spec.template 的 Pods 的现有 ReplicaSet 被缩容。最终,新的 ReplicaSet 缩放为 .spec.replicas 个副本, 所有旧 ReplicaSets 缩放为 0 个副本。
当 Deployment 正在上线时被更新,Deployment 会针对更新创建一个新的 ReplicaSet 并开始对其扩容,之前正在被扩容的 ReplicaSet 会被翻转,添加到旧 ReplicaSets 列表 并开始缩容。
例如,假定你在创建一个 Deployment 以生成 nginx:1.14.2 的 5 个副本,但接下来 更新 Deployment 以创建 5 个 nginx:1.16.1 的副本,而此时只有 3 个nginx:1.14.2 副本已创建。在这种情况下,Deployment 会立即开始杀死 3 个 nginx:1.14.2 Pods, 并开始创建 nginx:1.16.1 Pods。它不会等待 nginx:1.14.2 的 5 个副本都创建完成 后才开始执行变更动作。
回滚 Deployment
有时,你可能想要回滚 Deployment;例如,当 Deployment 不稳定时(例如进入反复崩溃状态)。 默认情况下,Deployment 的所有上线记录都保留在系统中,以便可以随时回滚 (你可以通过修改修订历史记录限制来更改这一约束)。
说明: Deployment 被触发上线时,系统就会创建 Deployment 的新的修订版本。 这意味着仅当 Deployment 的 Pod 模板(
.spec.template)发生更改时,才会创建新修订版本 -- 例如,模板的标签或容器镜像发生变化。 其他更新,如 Deployment 的扩缩容操作不会创建 Deployment 修订版本。 这是为了方便同时执行手动缩放或自动缩放。 换言之,当你回滚到较早的修订版本时,只有 Deployment 的 Pod 模板部分会被回滚。
检查 Deployment 上线历史
1 检查 Deployment 修订历史
kubectl rollout history deployment.v1.apps/nginx
2 要查看修订历史的详细信息,运行:
kubectl rollout history deployment.v1.apps/nginx --revision=1
回滚到之前的修订版本
1 假定现在你已决定撤消当前上线并回滚到以前的修订版本:
kubectl rollout undo deployment.v1.apps/nginx-deployment
或者
kubectl rollout undo deployment.v1.apps/nginx-deployment --to-revision=2
2 检查回滚是否成功以及 Deployment 是否正在运行,运行:
kubectl get deployment nginx-deployment
缩放 Deployment
kubectl scale deployment.v1.apps/nginx-deployment --replicas=10
比例缩放
RollingUpdate 的 Deployment 支持同时运行应用程序的多个版本。 当自动缩放器缩放处于上线进程(仍在进行中或暂停)中的 RollingUpdate Deployment 时, Deployment 控制器会平衡现有的活跃状态的 ReplicaSets(含 Pods 的 ReplicaSets)中的额外副本, 以降低风险。这称为 比例缩放(Proportional Scaling)
例如,你正在运行一个 10 个副本的 Deployment,其 maxSurge=3,maxUnavailable=2。
确保 Deployment 的这 10 个副本都在运行。
更新 Deployment 使用新镜像,碰巧该镜像无法从集群内部解析。
暂停、恢复 Deployment
Deployment 状态
Deployment 的生命周期中会有许多状态。上线新的 ReplicaSet 期间可能处于 Progressing(进行中),可能是 Complete(已完成),也可能是 Failed(失败)以至于无法继续进行。
失败的 Deployment
你的 Deployment 可能会在尝试部署其最新的 ReplicaSet 受挫,一直处于未完成状态。 造成此情况一些可能因素如下:
- 配额(Quota)不足
- 就绪探测(Readiness Probe)失败
- 镜像拉取错误
- 权限不足
- 限制范围(Limit Ranges)问题
- 应用程序运行时的配置错误
浙公网安备 33010602011771号