部署 (Deploy, deployments) 表示用户对 Kubernetes 集群的一次更新操作。部署是一个比 RS 应用模式更广的 API 对象,可以是创建一个新的服务,更新一个新的服务,也可以是滚动升级一个服务。滚动升级一个服务,实际是创建一个新的 RS,然后逐渐将新 RS 中副本数增加到理想状态,将旧 RS 中的副本数减小到 0 的复合操作;这样一个复合操作用一个 RS 是不太好描述的,所以用一个更通用的 Deployment 来描述。以 Kubernetes 的发展方向,未来对所有长期伺服型的的业务的管理,都会通过 Deployment 来管理。
Deployment 为 Pod 和 RS (下一代 RC) 提供了一个声明式定义(declarative)方法,用来替代以前的 ReplicationController 来方便的管理应用。典型的应用场景包括:
- 定义 Deployment 来创建 Pod 和 ReplicaSet
- 滚动升级和回滚应用
- 扩容和缩容
- 暂停和继续 Deployment
您只需要在 Deployment 中描述您想要的目标状态是什么,Deployment Controller 就会帮您将 Pod 和 ReplicaSet 的实际状态改变到您的目标状态。您可以定义一个全新的 Deployment 来创建 ReplicaSet 或者删除已有的 Deployment 并创建一个新的来替换。
:::warning 不该手动管理由 Deployment 创建的 ReplicaSet,否则您就篡越了 Deployment Controller 的职责! :::
典型的用例如下:
- 使用 Deployment 来创建 ReplicaSet。ReplicaSet 在后台创建 pod。检查启动状态,看它是成功还是失败。
- 然后,通过更新 Deployment 的 PodTemplateSpec 字段来声明 Pod 的新状态。这会创建一个新的 ReplicaSet,Deployment 会按照控制的速率将 pod 从旧的 ReplicaSet 移动到新的 ReplicaSet 中。
- 如果当前状态不稳定,回滚到之前的 Deployment revision。每次回滚都会更新 Deployment 的 revision。
- 扩容 Deployment 以满足更高的负载。
- 暂停 Deployment 来应用 PodTemplateSpec 的多个修复,然后恢复上线。
- 根据 Deployment 的状态判断上线是否 hang 住了。
- 清除旧的不必要的 ReplicaSet。
yaml 示例
比如一个简单的 nginx 应用可以定义为
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Deployment 的常用操作
扩容:
kubectl scale deployment nginx-deployment --replicas 10
如果集群支持 horizontal pod autoscaling 的话,还可以为 Deployment 设置自动扩展:
kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
更新镜像也比较简单:
kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
回滚:
kubectl rollout undo deployment/nginx-deployment
创建 Deployment
下面是一个 Deployment 示例,它创建了一个 ReplicaSet 来启动 3 个 nginx pod。
下载示例文件并执行命令:
$ kubectl create -f https://kubernetes.io/docs/user-guide/nginx-deployment.yaml --record
deployment "nginx-deployment" created
将 kubectl 的 --record
的 flag 设置为 true
可以在 annotation 中记录当前命令创建或者升级了该资源。这在未来会很有用,例如,查看在每个 Deployment revision 中执行了哪些命令。
然后执行 get
将获得如下结果:
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 0 0 0 1s
输出结果表明我们希望的 repalica 数是 3(根据 deployment 中的.spec.replicas
配置)当前 replica 数( .status.replicas
)是 0, 最新的 replica 数(.status.updatedReplicas
)是 0,可用的 replica 数(.status.availableReplicas
)是 0。
过几秒后再执行 get
命令,将获得如下输出:
$ kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
nginx-deployment 3 3 3 3 18s
我们可以看到 Deployment 已经创建了 3 个 replica,所有的 replica 都已经是最新的了(包含最新的 pod template),可用的(根据 Deployment 中的.spec.minReadySeconds
声明,处于已就绪状态的 pod 的最少个数)。执行kubectl get rs
和kubectl get pods
会显示 Replica Set(RS)和 Pod 已创建。
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-2035384211 3 3 0 18s
您可能会注意到 ReplicaSet 的名字总是<Deployment的名字>-<pod template的hash值>
。
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-deployment-2035384211-7ci7o 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
nginx-deployment-2035384211-kzszj 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
nginx-deployment-2035384211-qqcnn 1/1 Running 0 18s app=nginx,pod-template-hash=2035384211
刚创建的 Replica Set 将保证总是有 3 个 nginx 的 pod 存在。
注意: 您必须在 Deployment 中的 selector 指定正确的 pod template label(在该示例中是 app = nginx
),不要跟其他的 controller 的 selector 中指定的 pod template label 搞混了(包括 Deployment、Replica Set、Replication Controller 等)。Kubernetes 本身并不会阻止您任意指定 pod template label ,但是如果您真的这么做了,这些 controller 之间会相互打架,并可能导致不正确的行为。