K8S 之 Deployment

摘要

Deployment 介绍

  • Deployment 用于管理运行一个应用负载的一组 Pod,通常适用于不保持状态的负载。

  • Deployment 是最常用的无状态服务控制器,由Deployment、ReplicaSet、Pod组成、支持集群扩容缩容、滚动、更新、自动维护Pod可用性及副本数量等功能,ReplicaSet和Pod由Deployment自动管理,用户无需干预,也就是说,创建一个Deployment后,K8S会自动创建ReplicaSet,并创建指定数量的Pod。

Deployment 管理

Deployment 创建

  • create 创建

1
2
3
4
5
6
7
8
# 创建 deployment
kubectl create deployment nginx --image=nginx
# 多副本,--replicas=3 创建3个副本
kubectl create deployment nginx --image=nginx --replicas=3
# -o 生成 yaml 文件, --dry-run: 不真的执行创建
kubectl create deployment nginx --image=nginx --replicas=3 --dry-run=client -o yaml > deployment.yaml
# 通过 yaml 文件创建
kubectl apply -f deployment.yaml
  • 一个简单的 deployment.yaml 文件说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
apiVersion: apps/v1                  # 指定使用的 API 版本,这里是 apps/v1,适用于 Deployment 资源
kind: Deployment # Kubernetes 资源类型,这里是部署(Deployment)
metadata:
labels:
app: nginx # 标签,用于标识资源,可与 selector 匹配
name: nginx # 资源名称,必须唯一(在同一命名空间下)
spec: # 配置项
replicas: 3 # 副本数,表示希望运行多少个 Pod 实例
selector: # 选择器,指定要管理的 Pod
matchLabels: # 标签选择器
app: nginx # 选择器,指定 Deployment 管理哪些 Pod(标签必须与 template 中匹配)
strategy: # 用新Pod替换现有Pod的部署策略,可省略,默认就是滚动更新
type: RollingUpdate # 滚动更新策略
rollingUpdate: # 滚动更新方式,type: RollingUpdate 时有效
maxSurge: 30% # 最大额外可以存在的副本数,可以为百分比,也可以为整数,默认为 25%
maxUnavailable: 30% # 最大不可用状态的 Pod 的最大值,可以为百分比,也可以为整数,默认为 25%
template: # 模板,定义 Pod 的内容,具体可以参考 Pod 的配置
metadata:
labels:
app: nginx # Pod 的标签,必须与 selector 中的 matchLabels 一致
spec:
containers:
- image: nginx # 容器使用的镜像,这里是官方的 nginx 镜像
name: nginx # 容器的名称

# 需要新了解的配置项就是spec下面几个选项:
# replicas:指定副本数量,其实就是当前rs创建出来的pod的数量,默认为1
# selector:选择器,它的作用是建立pod控制器和pod之间的关联关系,采用的Label Selector机制,在pod模板上定义label,在控制器上定义选择器,就可以表明当前控制器能管理哪些pod了
# template:模板,就是当前控制器创建pod所使用的模板,里面其实就是前一章学过的pod的定义
  • 获取 deployment 的 yaml 文件配置项帮助

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 比如,这里查看用新Pod替换现有Pod的部署策略
$ kubectl explain deployment.spec.strategy
## 输出结果
DESCRIPTION:
The deployment strategy to use to replace existing pods with new ones.
DeploymentStrategy describes how to replace existing pods with new ones.

FIELDS:
rollingUpdate <RollingUpdateDeployment>
Rolling update config params. Present only if DeploymentStrategyType =
RollingUpdate.

type <string>
enum: Recreate, RollingUpdate
Type of deployment. Can be "Recreate" or "RollingUpdate". Default is
RollingUpdate.

Possible enum values:
# 在创建新pod之前,先删除所有现有的pod
- `"Recreate"` Kill all existing pods before creating new ones.
# 使用滚动更新方式用新的 ReplicaSet 替换旧的 ReplicaSet更新,即逐步缩减旧的ReplicaSet并扩大新的ReplicaSet
- `"RollingUpdate"` Replace the old ReplicaSets by new one using rolling update i.e gradually scale down the old ReplicaSets and scale up the new one.

小贴士

  • yaml 文件中,出现了 metadata.labels,spec.selector.matchLabels 以及 template.metadata.labels,三者是什么关系?
  1. metadata.labels(Deployment 的标签)

给 Deployment 本身 打的标签, 和 Pod 没有直接管理关系
常用于资源分组、查找(比如:kubectl get deploy -l app=nginx)

1
2
3
metadata:
labels:
app: nginx # 属于这个 Deployment 的“标签”,只是标识它自己
  1. spec.selector.matchLabels(选择器)

指定 Deployment 要管理哪些 Pod
必须精确匹配 Pod 的标签
决定 Deployment 会不会“接管”某些 Pod

1
2
3
4
spec:
selector:
matchLabels:
app: nginx
  1. template.metadata.labels(模板中的 Pod 标签)

Pod 模板中定义的标签
Deployment 按这个模板创建 Pod
必须与 matchLabels 完全一致,否则会报错

1
2
3
4
template:
metadata:
labels:
app: nginx # Pod 的标签,必须与 selector 匹配!

🔁 关系图示意:

1
2
3
4
5
6
7
Deployment

├─ metadata.labels Deployment 本身的标签(非关键)

├─ spec.selector.matchLabels ─┐

└─ spec.template.metadata.labels 必须匹配 selector,才能让 Pod Deployment 管理

Deployment 扩缩容

1
2
3
4
# 扩容到5个,原先有3个,这里会再创建2个
kubectl scale deployment nginx --replicas=5
# 缩容到3个,原先有5个,这里会删除2个
kubectl scale deployment nginx --replicas=3

查看 Deployment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 查看 Deployment ,默认显示 default 命名空间下的 deployments
kubectl get deployments
kubectl get deploy # 简称

# 查看 pod、deploy、replicaset
$ k get pod,deploy,rs -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-5869d7778c-4sqwf 1/1 Running 0 105s 10.244.126.11 k8s-worker2 <none> <none>
pod/nginx-5869d7778c-kn6pg 1/1 Running 0 105s 10.244.126.12 k8s-worker2 <none> <none>
pod/nginx-5869d7778c-zkwkd 1/1 Running 0 18m 10.244.194.82 k8s-worker1 <none> <none>

NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/nginx 3/3 3 3 18m nginx nginx app=nginx

NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/nginx-5869d7778c 3 3 3 18m nginx nginx app=nginx,pod-template-hash=5869d7778c

# 查看 kube-system 命名空间下的 Deployment
kubectl get deploy -n kube-system
# 查看所有命名空间下的 Deployment
kubectl get deploy -A
# -o wide: 显示 deploy 的详细信息
kubectl get deployments -o wide
# 显示 Deployment 的标签
kubectl get deploy --show-labels
# 按 Deployment 的标签进程查询
kubectl get deploy -l <label_name>=<label_value>
# 持续查看 Deployment 的状态,当 Deployment 状态发生改变时,会实时显示
kubectl get deploy -w

查看 Deployment 详情

  • 当 Deployment 运行错误时,可以通过该命令查看 Deployment 的详情,找到错误原因

1
2
kubectl describe deploy <deploy-name>
kubectl describe deploy <deploy-name> -n <namespace-name>

删除 Deployment

1
2
3
4
5
kubectl delete deploy <deploy-name>
kubectl delete deploy <deploy-name> -n <namespace-name>

# 通过 yaml 文件删除
kubectl delete -f <yaml-file>

查看 Deployment 日志

1
2
kubectl logs deploy/<deploy-name>
kubectl logs deploy/<deploy-name> -n <namespace-name>

滚动升级与回滚 Deployment

  • 升级镜像

1
2
3
# set image: 这里表示要改变的是镜像, --record=true 表示记录此次操作
# kubectl set image deploy <deploy-name> <container-name>=<image-name>:<tag>
kubectl set image deploy nginx nginx=nginx:1.9.1 --record=true
  • 查看历史版本

1
2
3
4
5
6
# 前面的序号表示版本号
$ kubectl rollout history deploy nginx
deployment.apps/nginx
REVISION CHANGE-CAUSE
1 <none>
2 kubectl set image deploy nginx nginx=nginx:1.9.1 --record=true
  • 查看更新状态

1
kubectl rollout status deploy nginx
  • 回滚

1
2
3
4
# 回退到前一个版本
kubectl rollout undo deploy nginx
# 回到指定版本,这里 --to-revision=1 表示回到版本1
kubectl rollout undo deploy nginx --to-revision=1