Deployment使用

Deployment和rc的对比

        首先RC是Kubernetes的一个核心概念,当我们把应用部署到集群之后,需要保证应用能够持续稳定的运行,RC就是这个保证的关键,主要功能如:

  • 确保Pod数量: 它会确保Kubernetes中有指定数量的Pod在运行,如果少于指定数量的Pod,RC就会创建新的,反之这会删除多余的,保证Pod的副本数量不变。
  • 确保Pod健康: 当Pod不健康,比如运行出错了,总之无法提供正常服务时,RC也会杀死不健康的Pod,重新创建新的。
  • 弹性伸缩: 在业务高峰或者低峰的时候,可以用过RC来动态的调整Pod数量来提供资源的利用率,当然我们也提到过如果使用HPA这种资源对象的话可以做到自动伸缩。
  • 滚动升级: 滚动升级是一种平滑的升级方式,通过逐步替换的策略,保证整体系统的稳定性

        Deployment同样也是Kubernetes系统的一个核心概念,主要职责和RC一样的都是保证Pod的数量和健康,二者大部分功能都是完全一致的,我们可以看成是一个升级版的RC控制器,Deployment具备的新特性

  • RC的全部功能: Deployment具备上面描述的RC的全部功能
  • 事件和状态查看: 可以查看Deployment的升级详细进度和状态
  • 回滚: 当升级Pod的时候如果出现问题,可以使用回滚操作回滚到之前的任一版本
  • 版本记录: 每一次对Deployment的操作,都能够保存下来,这也是保证可以回滚到任一版本的基础
  • 暂停和启动: 对于每一次升级都能够随时暂停和启动

对比: Deployment作为新一代的RC,在功能上更为丰富,同时官方也是推荐使用Deployment来管理Pod,比如一些官方组件kube-dns、kube-proxy也都是使用的Deployment来管理的,所以最好使用Deployment来管理Pod。

Deployment 介绍

        Deployment拥有多个Replica Set,而一个Replica Set拥有一个或多个Pod。一个Deployment控制多个rs主要是为了支持回滚机制,每当Deployment操作时,Kubernetes会重新生成一个Replica Set并保留,以后有需要的话就可以回滚至之前的状态。

实例: 创建一个Deployment,它创建了一个Replica Set来启动3个nginx pod,yaml文件如下:

  • nginx-deployment.yaml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    $ cat > nginx-deployment.yaml <<EOF
    apiVersion: apps/v1beta1
    kind: Deployment
    metadata:
    name: nginx-deploy
    labels:
    k8s-app: nginx-demo
    spec:
    replicas: 3
    template:
    metadata:
    labels:
    app: nginx
    spec:
    containers:
    - name: nginx
    image: nginx:1.7.9
    ports:
    - containerPort: 80
    EOF
  • 执行创建

    1
    2
    $ kubectl create -f nginx-deployment.yaml
    deployment.apps/nginx-deploy created
  • 执行一下命令查看刚刚创建的Deployment

    1
    2
    3
    4
    5
    6
    7
    8
    $ kubectl get deployments
    NAME READY UP-TO-DATE AVAILABLE AGE
    nginx-deploy 0/3 3 0 12s

    # 再次执行上面命令
    $ kubectl get deployments
    NAME READY UP-TO-DATE AVAILABLE AGE
    nginx-deploy 1/3 3 1 35s
  • 可以看到Deployment已经创建了1个Replica Set了,执行下面的命令查看rs和pod

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ kubectl get rs
    NAME DESIRED CURRENT READY AGE
    nginx-deploy-6dd86d77d 3 3 2 70s

    #
    $ kubectl get pod --show-labels
    NAME READY STATUS RESTARTS AGE LABELS
    nginx-deploy-6dd86d77d-9n9vf 1/1 Running 0 99s app=nginx,pod-template-hash=6dd86d77d
    nginx-deploy-6dd86d77d-bhrsk 0/1 ContainerCreating 0 99s app=nginx,pod-template-hash=6dd86d77d
    nginx-deploy-6dd86d77d-jdnrh 1/1 Running 0 99s app=nginx,pod-template-hash=6dd86d77d

上面的Deployment的yaml文件中的replicas:3将会保证我们始终有3个POD在运行。

滚动升级

        修改之前使用的nginx-deployment.yaml文件中的nginx镜像修改为nginx:1.13.3,然后在spec下面添加滚动升级策略:

  • nginx-deploments.yml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    apiVersion: apps/v1beta1
    kind: Deployment
    metadata:
    name: nginx-deploy
    labels:
    k8s-app: nginx-demo
    spec:
    replicas: 3
    minReadySeconds: 5
    strategy:
    type: RollingUpdate
    rollingUpdate:
    maxSurge: 1
    maxUnavailable: 1
    template:
    metadata:
    labels:
    app: nginx
    spec:
    containers:
    - name: nginx
    image: nginx:1.13.3
    ports:
    - containerPort: 80
  • minReadySeconds:

    • 滚动升级时5s后认为该pod就绪
    • 如果没有设置该值,Kubernetes会假设该容器启动起来后就提供服务了
    • 如果没有设置该值,在某些极端情况下可能会造成服务不正常运行
  • rollingUpdate:

    • 于replicas为3,则整个升级,pod个数在2-4个之间
  • maxSurge:

    • 升级过程中最多可以比原先设置多出的POD数量
    • 例如:maxSurage=1,replicas=3,则表示Kubernetes会先启动1一个新的Pod后才删掉一个旧的POD,整个升级过程中最多会有3+1个POD。
  • maxUnavaible:

    • 升级过程中最多有多少个POD处于无法提供服务的状态
    • 当maxSurge不为0时,该值也不能为0
    • 例如:maxUnavaible=1,则表示Kubernetes整个升级过程中最多会有1个POD处于无法服务的状态。
  • 执行创建

    1
    2
    $ kubectl apply -f nginx-deployment.yaml
    deployment.apps/nginx-deploy configured
  • 查看状态

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 使用rollout命令
    $ kubectl rollout status deployment/nginx-deploy
    Waiting for deployment "nginx-deploy" rollout to finish: 2 out of 3 new replicas have been updated...

    # 暂停升级
    $ kubectl rollout pause deployment deployment/nginx-deploy

    # 继续升级
    $ kubectl rollout resume deployment deployment/nginx-deploy

升级结束后,继续查看rs的状态

1
2
3
4
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deploy-6dd86d77d 0 0 0 21m
nginx-deploy-799d666985 3 3 3 10m

根据AGE我们可以看到离我们最近的当前状态是:3,和我们的yaml文件是一致的,证明升级成功了。用describe命令可以查看升级的全部信息:

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
30
31
32
33
34
35
36
37
38
39
40
$ kubectl describe deploy nginx-deploy
Name: nginx-deploy
Namespace: default
CreationTimestamp: Wed, 09 Oct 2019 10:12:56 +0800
Labels: k8s-app=nginx-demo
Annotations: deployment.kubernetes.io/revision: 2
kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"apps/v1beta1","kind":"Deployment","metadata":{"annotations":{},"labels":{"k8s-app":"nginx-demo"},"name":"nginx-deploy","nam...
Selector: app=nginx
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 5
RollingUpdateStrategy: 1 max unavailable, 1 max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.13.3
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: nginx-deploy-799d666985 (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 23m deployment-controller Scaled up replica set nginx-deploy-6dd86d77d to 3
Normal ScalingReplicaSet 12m deployment-controller Scaled up replica set nginx-deploy-799d666985 to 1
Normal ScalingReplicaSet 12m deployment-controller Scaled down replica set nginx-deploy-6dd86d77d to 2
Normal ScalingReplicaSet 12m deployment-controller Scaled up replica set nginx-deploy-799d666985 to 2
Normal ScalingReplicaSet 11m deployment-controller Scaled down replica set nginx-deploy-6dd86d77d to 1
Normal ScalingReplicaSet 11m deployment-controller Scaled up replica set nginx-deploy-799d666985 to 3
Normal ScalingReplicaSet 10m deployment-controller Scaled down replica set nginx-deploy-6dd86d77d to 0

回滚Deployment

        前面已经滚动平滑的升级Deployment,但是如果升级后的POD出了问题该怎么办?我们能够想到的最好最快的方式当然是回退到上一次能够提供正常工作的版本,Deployment就为我们提供了回滚机制。

  • 首先,查看Deployment的升级历史:
    1
    2
    3
    4
    5
    $ kubectl rollout history deployment nginx-deploy
    deployment.extensions/nginx-deploy
    REVISION CHANGE-CAUSE
    1 <none>
    2 <none>

        从上面的结果可以看出在执行Deployment升级的时候最好带上record参数,便于我们查看历史版本信息。kubectl apply --filename=nginx-deployment.yaml --record=true
        默认情况下,所有通过kubectl xxxx –record都会被kubernetes记录到etcd进行持久化,这无疑会占用资源,最重要的是,时间久了,当你kubectl get rs时,会有成百上千的垃圾RS返回,这对于运维来说维护很不便利,
        当我们在上生产时,我们最好通过设置Deployment的.spec.revisionHistoryLimit来限制最大保留的revision number,比如15个版本,回滚的时候一般只会回滚到最近的几个版本就足够了。其实rollout history中记录的revision都和ReplicaSets一一对应。如果手动delete某个ReplicaSet,对应的rollout history就会被删除,也就是还说你无法回滚到这个revison。rollout history和ReplicaSet的对应关系,可以在kubectl describe rs $RSNAME返回的revision字段中得到,这里的revision就对应着rollout history返回的revison。

  • 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
    $ cat nginx-deployment.yaml 
    apiVersion: apps/v1beta1
    kind: Deployment
    metadata:
    name: nginx-deploy
    labels:
    k8s-app: nginx-demo
    spec:
    replicas: 3
    minReadySeconds: 5
    revisionHistoryLimit: 10
    strategy:
    type: RollingUpdate
    rollingUpdate:
    maxSurge: 1
    maxUnavailable: 1
    template:
    metadata:
    labels:
    app: nginx
    spec:
    containers:
    - name: nginx
    image: nginx:1.13.3
    ports:
    - containerPort: 80
  • 可以使用下面的命令查看单个revison的信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $ kubectl rollout history deployment nginx-deploy --revision=2
    deployment.extensions/nginx-deploy with revision #2
    Pod Template:
    Labels: app=nginx
    pod-template-hash=799d666985
    Annotations: kubernetes.io/change-cause: kubectl apply --filename=nginx-deployment.yaml --record=true
    Containers:
    nginx:
    Image: nginx:1.13.3
    Port: 80/TCP
    Host Port: 0/TCP
    Environment: <none>
    Mounts: <none>
    Volumes: <none>
  • 直接回退到当前版本的前一个版本:

    1
    2
    3
    4
    5
    6
    $ kubectl rollout undo deployment nginx-deploy
    deployment.extensions/nginx-deploy rolled back

    # 也可以用revision回退到指定的版本
    $ kubectl rollout undo deployment nginx-deploy --to-revision=1
    deployment.extensions/nginx-deploy rolled back
  • 查看Deployment现在的状态

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    $ kubectl get deployments
    NAME READY UP-TO-DATE AVAILABLE AGE
    nginx-deploy 2/3 3 2 56m

    $ kubectl get rs
    NAME DESIRED CURRENT READY AGE
    nginx-deploy-6dd86d77d 1 1 1 56m
    nginx-deploy-799d666985 3 3 1 46m

    $ kubectl rollout status deployment/nginx-deploy
    Waiting for deployment "nginx-deploy" rollout to finish: 2 of 3 updated replicas are available...
    Waiting for deployment "nginx-deploy" rollout to finish: 2 of 3 updated replicas are available...
    deployment "nginx-deploy" successfully rolled out

    # 完成后查看
    $ kubectl get rs
    NAME DESIRED CURRENT READY AGE
    nginx-deploy-6dd86d77d 0 0 0 57m
    nginx-deploy-799d666985 3 3 3 47m

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
apiVersion: apps/v1  # 指定api版本,此值必须在kubectl api-versions中  
kind: Deployment # 指定创建资源的角色/类型
metadata: # 资源的元数据/属性
name: demo # 资源的名字,在同一个namespace中必须唯一
namespace: default # 部署在哪个namespace中
labels: # 设定资源的标签
app: demo
version: stable
spec: # 资源规范字段
replicas: 1 # 声明副本数目
revisionHistoryLimit: 3 # 保留历史版本
selector: # 选择器
matchLabels: # 匹配标签
app: demo
version: stable
strategy: # 策略
rollingUpdate: # 滚动更新
maxSurge: 3 # 最大额外可以存在的副本数,可以为百分比,也可以为整数
maxUnavailable: 1 # 示在更新过程中能够进入不可用状态的 Pod 的最大值,可以为百分比,也可以为整数
type: RollingUpdate # 滚动更新策略
template: # 模版
metadata: # 资源的元数据/属性
annotations: # 自定义注解列表
sidecar.istio.io/inject: "false" # 自定义注解名字
labels: # 设定资源的标签
app: demo
version: stable
spec: # 资源规范字段
containers:
- name: demo # 容器的名字
image: demo:v1 # 容器使用的镜像地址
imagePullPolicy: IfNotPresent # 每次Pod启动拉取镜像策略,三个选择 Always、Never、IfNotPresent
# Always,每次都检查;Never,每次都不检查(不管本地是否有);IfNotPresent,如果本地有就不检查,如果没有就拉取
resources: # 资源管理
limits: # 最大使用
cpu: 300m # CPU,1核心 = 1000m
memory: 500Mi # 内存,1G = 1000Mi
requests: # 容器运行时,最低资源需求,也就是说最少需要多少资源容器才能正常运行
cpu: 100m
memory: 100Mi
livenessProbe: # pod 内部健康检查的设置
httpGet: # 通过httpget检查健康,返回200-399之间,则认为容器正常
path: /healthCheck # URI地址
port: 8080 # 端口
scheme: HTTP # 协议
# host: 127.0.0.1 # 主机地址
initialDelaySeconds: 30 # 表明第一次检测在容器启动后多长时间后开始
timeoutSeconds: 5 # 检测的超时时间
periodSeconds: 30 # 检查间隔时间
successThreshold: 1 # 成功门槛
failureThreshold: 5 # 失败门槛,连接失败5次,pod杀掉,重启一个新的pod
readinessProbe: # Pod 准备服务健康检查设置
httpGet:
path: /healthCheck
port: 8080
scheme: HTTP
initialDelaySeconds: 30
timeoutSeconds: 5
periodSeconds: 10
successThreshold: 1
failureThreshold: 5
#也可以用这种方法
#exec: 执行命令的方法进行监测,如果其退出码不为0,则认为容器正常
# command:
# - cat
# - /tmp/health
#也可以用这种方法
#tcpSocket: # 通过tcpSocket检查健康
# port: number
ports:
- name: http # 名称
containerPort: 8080 # 容器开发对外的端口
protocol: TCP # 协议
imagePullSecrets: # 镜像仓库拉取密钥
- name: harbor-certification
affinity: # 亲和性调试
nodeAffinity: # 节点亲和力
requiredDuringSchedulingIgnoredDuringExecution: # pod 必须部署到满足条件的节点上
nodeSelectorTerms: # 节点满足任何一个条件就可以
- matchExpressions: # 有多个选项,则只有同时满足这些逻辑选项的节点才能运行 pod
- key: beta.kubernetes.io/arch
operator: In
values:
- amd64

官方参考

坚持原创技术分享,您的支持将鼓励我继续创作!
0%