K8s Pod 控制器

之前我们共使用两种方式创建 Pod。一种是 kubectl run,另一种为 kubectl create + 配置文件。当我们将以 kubectl create 创建的 Pod 删除之后,Pod 是不会重新被创建的,也就是说此类 Pod 是没有被控制器管理的,删除之后就没有了。而使用 kubectl run 创建的 Pod 是被控制器管理的,删除之后还会重新启动,达到你定义的状态。ReplicationController 是K8s之前的唯一一个控制器,因为其太过庞大,所以目前不怎么使用。从而出现的 ReplicaSet 等控制器成为主流。

ReplicaSet

查看定义

Kubernetes 并不建议我们直接使用 ReplicaSet 控制器。而是建议我们使用 Deployment 控制器。Deployment 通过控制 ReplicaSet 来控制 Pod,是对 ReplicaSet 的进一步封装,拥有更强大的功能。
查看 ReplicaSet 的字段

kubectl explain rs

ReplicaSet 的 spec 中有三个核心的部分组成,分别为副本数(replicas),标签选择器(selector),Pod 模版(template)。template 中 spec 的定义和我们之前定义的 Pod 方式一致,都有什么 containers,nodeName,nodeSelector等等。

kubectl explain rs.spec

创建资源

定义一个 ReplicaSet,标签选择规则为 matchLabels(所有标签都必须满足)。注意,这里创建的 Pod 的标签要和 ReplicaSet标签选择器中的一致,这样才能将创建出来的 Pod 和选择器进行关联。

apiVersion: apps/v1
kind: 
metadata:
  name: myapp
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
     app: myapp
     release: test
  template:
    metadata:
      name: myapp-pod
      labels:
        app: myapp
        release: test
        env: local
    spec:
      containers:
      - name: myapp-container
        image: ikubernetes/myapp:v1
        ports:
        - name: http
          containerPort: 80

创建 Pod

kubectl create -f rs-demo.yaml

查看 ReplicaSet。可以看到期待的两个,当前为两个,处于 READY 装状态的为两个。

kubectl get rs
[[email protected] rexyan]# kubectl get rs 
NAME    DESIRED   CURRENT   READY   AGE
myapp   2         2         2       45s

查看 Pod 列表(注意,Pod 的 name 是以控制器的名称加上随机字符串组成,而不是自己的定义的 myapp-pod)

kubectl get pods 
[[email protected] rexyan]# kubectl get pods 
NAME          READY   STATUS    RESTARTS   AGE
myapp-hl4wg   1/1     Running   0          36s
myapp-xrb9n   1/1     Running   0          36s

查看 Pod 详细信息

kubectl describe pods + pod 名称
[[email protected] rexyan]# kubectl describe pods myapp-hl4wg
Name:               myapp-hl4wg
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               k8s003/172.20.245.193
Start Time:         Sun, 26 May 2019 20:03:39 +0800
Labels:             app=myapp
                    env=local
                    release=test
Annotations:        <none>
Status:             Running
IP:                 10.24.2.2
Controlled By:      ReplicaSet/myapp
Containers:
  myapp-container:
    Container ID:   docker://b3df7d29352b61057535ebe7a48ae27d47105029d17c42298a9938a89c0efd5e
    Image:          ikubernetes/myapp:v1
    Image ID:       docker-pullable://docker.io/ikubernetes/[email protected]:9c3dc30b5219788b2b8a4b065f548b922a34479577befb54b03330999d30d513
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Sun, 26 May 2019 20:03:42 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-wpmp4 (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  default-token-wpmp4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-wpmp4
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  98s   default-scheduler  Successfully assigned default/myapp-hl4wg to k8s003
  Normal  Pulling    97s   kubelet, k8s003    Pulling image "ikubernetes/myapp:v1"
  Normal  Pulled     95s   kubelet, k8s003    Successfully pulled image "ikubernetes/myapp:v1"
  Normal  Created    95s   kubelet, k8s003    Created container myapp-container
  Normal  Started    95s   kubelet, k8s003    Started container myapp-container

查看 pods 的标签

kubectl get pods --show-labels
[[email protected] rexyan]# kubectl get  pods --show-labels
NAME          READY   STATUS    RESTARTS   AGE     LABELS
myapp-hl4wg   1/1     Running   0          2m35s   app=myapp,env=local,release=test
myapp-xrb9n   1/1     Running   0          2m35s   app=myapp,env=local,release=test

修改标签

删除名称为 myapp-hl4wg 的 Pod,会看到一个新的 Pod 会被创建出来,因为我们期待的数量为 2 个。

[[email protected] rexyan]# kubectl get pods --show-labels
NAME          READY   STATUS    RESTARTS   AGE   LABELS
myapp-hl4wg   1/1     Running   0          31m   app=myapp,env=local,release=test
myapp-xrb9n   1/1     Running   0          31m   app=myapp,env=local,release=test

[[email protected] rexyan]# kubectl delete pods myapp-hl4wg
pod "myapp-hl4wg" deleted

[[email protected] rexyan]# kubectl get pods --show-labels
NAME          READY   STATUS    RESTARTS   AGE   LABELS
myapp-d6q5r   1/1     Running   0          4s    app=myapp,env=local,release=test
myapp-xrb9n   1/1     Running   0          32m   app=myapp,env=local,release=test

修改其中一个 Pod 的标签,将其 app=myapp 改为 app=app。会看到会新建一个 Pod 起来,被修改 Pod 现在就不属于任何控制器了。

[[email protected] rexyan]# kubectl label pods myapp-d6q5r app=app --overwrite
pod/myapp-d6q5r labeled

[[email protected] rexyan]# kubectl get pods --show-labels
NAME          READY   STATUS    RESTARTS   AGE     LABELS
myapp-d6q5r   1/1     Running   0          3m36s   app=app,env=local,release=test
myapp-kb94h   1/1     Running   0          3s      app=myapp,env=local,release=test
myapp-xrb9n   1/1     Running   0          35m     app=myapp,env=local,release=test

[[email protected] rexyan]# kubectl get rs -o wide 
NAME    DESIRED   CURRENT   READY   AGE   CONTAINERS        IMAGES                 SELECTOR
myapp   2         2         2       36m   myapp-container   ikubernetes/myapp:v1   app=myapp,release=test

动态扩容

动态修改 ReplicaSet。myapp 为 ReplicaSet 的名称,并且副本为改成 5 个。改完后就会立即生效。

[[email protected] rexyan]# kubectl edit rs myapp
[[email protected] rexyan]# kubectl get pods --show-labels
NAME          READY   STATUS    RESTARTS   AGE     LABELS
myapp-68p22   1/1     Running   0          4s      app=myapp,env=local,release=test
myapp-b9x4x   1/1     Running   0          4s      app=myapp,env=local,release=test
myapp-bphsr   1/1     Running   0          4s      app=myapp,env=local,release=test
myapp-d6q5r   1/1     Running   0          9m34s   app=app,env=local,release=test
myapp-kb94h   1/1     Running   0          6m1s    app=myapp,env=local,release=test
myapp-xrb9n   1/1     Running   0          41m     app=myapp,env=local,release=test

[[email protected] rexyan]# kubectl get rs -o wide 
NAME    DESIRED   CURRENT   READY   AGE   CONTAINERS        IMAGES                 SELECTOR
myapp   5         5         5       41m   myapp-container   ikubernetes/myapp:v1   app=myapp,release=test

或者使用 scale 命令进行修改

[[email protected] rexyan]#  kubectl scale --replicas=2 rs myapp
replicaset.extensions/myapp scaled

[[email protected] rexyan]# kubectl get rs -o wide 
NAME    DESIRED   CURRENT   READY   AGE   CONTAINERS        IMAGES                 SELECTOR
myapp   2         2         2       46m   myapp-container   ikubernetes/myapp:v1   app=myapp,release=test

[[email protected] rexyan]# kubectl get pods --show-labels
NAME          READY   STATUS    RESTARTS   AGE   LABELS
myapp-d6q5r   1/1     Running   0          14m   app=app,env=local,release=test
myapp-kb94h   1/1     Running   0          10m   app=myapp,env=local,release=test
myapp-xrb9n   1/1     Running   0          46m   app=myapp,env=local,release=test

滚动升级

使用 edit 编辑镜像版本之后,Pod 是不会自动更新的,我们需要将 Pod 删除,然后让其自动重新构建,这样构建出来的才是新版镜像版本的 Pod。这里有两种方式,让其服务过度到新镜像版本的服务,第一种为一个一个的删除 Pod,让其重新一个一个的构建。另一种为构建一个新的 ReplicaSet,测试没问题后,在将新的 ReplicaSet 挂载到 Service 上去,并将以前老的 ReplicaSet 在 service 上摘除。Deployment 就是采用的第二种思想,Deployment 可以管理多个 ReplicaSet,但是可用的只有一个,这样也可以进行回滚。

kubectl edit rs myapp 

将其中镜像版本从 v1 改为 v2 ,查看 rs 信息,发现镜像版本已经变成了v2,但是访问结果去还是 v1,这时需要重建 Pod 才能生效。

[[email protected] rexyan]# kubectl get rs -o wide 
NAME    DESIRED   CURRENT   READY   AGE   CONTAINERS        IMAGES                 SELECTOR
myapp   2         2         2       58m   myapp-container   ikubernetes/myapp:v2   app=myapp,release=test

或者选择之前的命令 set image 进行镜像升级。

Deployment

Deployment 是目前用来管理无状态应用的做好的控制器。deployment 简称为 deploy。 deploy.spec.strategy 表示更新策略,deploy.spec.strategy.type 支持两种更新,分别为 Recreate (重新创建) 和 RollingUpdate(滚动更新)默认是 RollingUpdate。当 deploy.spec.strategy.type 是 RollingUpdate 时,还可以配置 deploy.spec.strategy.type.RollingUpdate 字段,这个字段用来控制更新力度,共有两种值,分别为 maxSurge(更新过程中,超出目标副本数的数量,可为数字或者百分比) 和 maxUnavailable (最多有几个不可用)。我们可以控制这里的更新力度来实现不同的发布,例如金丝雀发布,蓝绿发布等。deploy.spec.revisionHistoryLimit 表示滚动更新中最多保存过去几个历史版本,这些历史版本可用于回滚。deployment 通过控制 ReplicaSet 来控制 Pod。

创建资源

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: http
          containerPort: 80

创建 deploy, apply 属于声明式创建,既可以创建,也可以用于更新。

[[email protected] rexyan]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-deploy created

查看 deploy 会发现刚刚的已经创建好了

[[email protected] rexyan]# kubectl get deploy 
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
myapp-deploy   2/2     2 

查看 ReplicaSet 也会看到对应的两个,因为 deployment 是依赖 ReplicaSet 的,基于 ReplicaSet 之上。后面的 67b6dfcd8 模版的 hash值,而不是随机的字符串。

[[email protected] rexyan]# kubectl get rs
NAME                     DESIRED   CURRENT   READY   AGE
myapp-deploy-67b6dfcd8   2         2         2       6m33s

查看 Pod, Pod 的名称是 myapp-deploy-67b6dfcd8-xxxx,格式为 deployment 的名字 + ReplicaSet hash + 随机数。

[[email protected] rexyan]# kubectl get pods 
NAME                           READY   STATUS    RESTARTS   AGE
myapp-deploy-67b6dfcd8-flnxl   1/1     Running   0          11m
myapp-deploy-67b6dfcd8-r6stl   1/1     Running   0          11m

修改副本数

修改 yaml 脚本

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: http
          containerPort: 80                     

之后查看 Pod 的信息,发现名称部分 myapp-deploy-67b6dfcd8 依然没有变化,

[[email protected] rexyan]# kubectl apply -f deploy-demo.yaml 
deployment.apps/myapp-deploy configured
[[email protected] rexyan]# kubectl get pods 
NAME                           READY   STATUS    RESTARTS   AGE
myapp-deploy-67b6dfcd8-flnxl   1/1     Running   0          15m
myapp-deploy-67b6dfcd8-nm9bs   1/1     Running   0          7s
myapp-deploy-67b6dfcd8-r6stl   1/1     Running   0          15m

查看 deploy 的详细信息

[[email protected] rexyan]# kubectl  describe deploy myapp-deploy
Name:                   myapp-deploy
Namespace:              default
CreationTimestamp:      Tue, 28 May 2019 22:22:57 +0800
Labels:                 <none>
Annotations:            deployment.kubernetes.io/revision: 1
                        kubectl.kubernetes.io/last-applied-configuration:
                          {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"myapp-deploy","namespace":"default"},"spec":{"replicas":3...
Selector:               app=myapp,release=canary
Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=myapp
           release=canary
  Containers:
   myapp:
    Image:        ikubernetes/myapp:v1
    Port:         80/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Conditions:
  Type           Status  Reason
  ----           ------  ------
  Progressing    True    NewReplicaSetAvailable
  Available      True    MinimumReplicasAvailable
OldReplicaSets:  <none>
NewReplicaSet:   myapp-deploy-67b6dfcd8 (3/3 replicas created)
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  19m    deployment-controller  Scaled up replica set myapp-deploy-67b6dfcd8 to 2
  Normal  ScalingReplicaSet  4m19s  deployment-controller  Scaled up replica set myapp-deploy-67b6dfcd8 to 3

apply 会自动将每一次版本的变化添加到 Annotations 当中。apply 的 StrategyType(更新方式)RollingUpdate(滚动更新)且最多可用和最多不可用分别为 RollingUpdateStrategy: 25% max unavailable, 25% max surge。

滚动更新

deploy 的 apply 方式更新,Pod 最大可以用和不可用的数量分别是 25%。我们可以使用 -w命令来查看整个更新的过程。

终端1:编辑配置文件,将副本数量调整为5 (当前为3)

[[email protected] rexyan]# vim deploy-demo.yaml 
[[email protected] rexyan]# kubectl apply -f deploy-demo.yaml 

终端2:可以看到有创建了两个 Pod,以此来满足 5 个的数量。

[[email protected] ~]# kubectl get pods -w 
NAME                           READY   STATUS    RESTARTS   AGE
myapp-deploy-67b6dfcd8-wsmxz   0/1     Pending             0          0s
myapp-deploy-67b6dfcd8-wsmxz   0/1     Pending             0          0s
myapp-deploy-67b6dfcd8-fxqvx   0/1     Pending             0          0s
myapp-deploy-67b6dfcd8-fxqvx   0/1     Pending             0          0s
myapp-deploy-67b6dfcd8-wsmxz   0/1     ContainerCreating   0          0s
myapp-deploy-67b6dfcd8-fxqvx   0/1     ContainerCreating   0          0s
myapp-deploy-67b6dfcd8-wsmxz   1/1     Running             0          1s
myapp-deploy-67b6dfcd8-fxqvx   1/1     Running             0          1s

如果此时再次修改配置文件,将镜像从 image: ikubernetes/myapp:v1 升级为 image: ikubernetes/myapp:v2,则现象为, 这个就是整个滚动更新的过程,可以看到 Pod 的整个创建和结束的过程。

myapp-deploy-675558bfc5-g4j5t   0/1     Pending             0          0s
myapp-deploy-675558bfc5-g4j5t   0/1     Pending             0          0s
myapp-deploy-675558bfc5-kkl22   0/1     Pending             0          0s
myapp-deploy-675558bfc5-kkl22   0/1     Pending             0          0s
myapp-deploy-67b6dfcd8-mgh8z    1/1     Terminating         0          2m3s
myapp-deploy-675558bfc5-g4j5t   0/1     ContainerCreating   0          0s
myapp-deploy-675558bfc5-h8c2c   0/1     Pending             0          0s
myapp-deploy-675558bfc5-h8c2c   0/1     Pending             0          0s
myapp-deploy-675558bfc5-kkl22   0/1     ContainerCreating   0          0s
myapp-deploy-675558bfc5-h8c2c   0/1     ContainerCreating   0          0s
myapp-deploy-67b6dfcd8-mgh8z    0/1     Terminating         0          2m3s
myapp-deploy-675558bfc5-g4j5t   1/1     Running             0          2s
myapp-deploy-67b6dfcd8-f5fgw    1/1     Terminating         0          2m5s
myapp-deploy-675558bfc5-4m4nb   0/1     Pending             0          0s
myapp-deploy-675558bfc5-4m4nb   0/1     Pending             0          0s
myapp-deploy-675558bfc5-4m4nb   0/1     ContainerCreating   0          0s
myapp-deploy-675558bfc5-kkl22   1/1     Running             0          2s
myapp-deploy-67b6dfcd8-mzftf    1/1     Terminating         0          2m5s
myapp-deploy-675558bfc5-b2lj5   0/1     Pending             0          0s
myapp-deploy-675558bfc5-b2lj5   0/1     Pending             0          0s
myapp-deploy-675558bfc5-b2lj5   0/1     ContainerCreating   0          0s
myapp-deploy-675558bfc5-h8c2c   1/1     Running             0          3s
myapp-deploy-675558bfc5-b2lj5   1/1     Running             0          1s
myapp-deploy-67b6dfcd8-f5fgw    0/1     Terminating         0          2m6s
myapp-deploy-67b6dfcd8-bktzd    1/1     Terminating         0          2m6s
myapp-deploy-67b6dfcd8-flnxl    1/1     Terminating         0          46m
myapp-deploy-67b6dfcd8-mzftf    0/1     Terminating         0          2m6s
myapp-deploy-675558bfc5-4m4nb   1/1     Running             0          1s
myapp-deploy-67b6dfcd8-flnxl    0/1     Terminating         0          46m
myapp-deploy-67b6dfcd8-bktzd    0/1     Terminating         0          2m7s
myapp-deploy-67b6dfcd8-f5fgw    0/1     Terminating         0          2m10s
myapp-deploy-67b6dfcd8-f5fgw    0/1     Terminating         0          2m10s
myapp-deploy-67b6dfcd8-mgh8z    0/1     Terminating         0          2m10s
myapp-deploy-67b6dfcd8-mgh8z    0/1     Terminating         0          2m10s
myapp-deploy-67b6dfcd8-mzftf    0/1     Terminating         0          2m10s
myapp-deploy-67b6dfcd8-mzftf    0/1     Terminating         0          2m10s
myapp-deploy-67b6dfcd8-flnxl    0/1     Terminating         0          46m
myapp-deploy-67b6dfcd8-flnxl    0/1     Terminating         0          46m
myapp-deploy-67b6dfcd8-bktzd    0/1     Terminating         0          2m20s
myapp-deploy-67b6dfcd8-bktzd    0/1     Terminating         0          2m20s

这时查看 rs 的信息,就会看到有两个 rs。不同点在于镜像的版本一个是v1,期待个数,当前可以个数等全部为0,另一个版本为 v2。v1 的存在是让我们可以回滚。

[[email protected] rexyan]# kubectl  get rs -o wide 
NAME                      DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES                 SELECTOR
myapp-deploy-675558bfc5   5         5         5       2m58s   myapp        ikubernetes/myapp:v2   app=myapp,pod-template-hash=675558bfc5,release=canary
myapp-deploy-67b6dfcd8    0         0         0       49m     myapp        ikubernetes/myapp:v1   app=myapp,pod-template-hash=67b6dfcd8,release=canary

金丝雀发布

修改更新过程中最大更新数(max surge)为 1个, 最大可减少数(max unavailable)为 0 ,这就意味着,在目前已经有的 Pod 的基础上,最多可以存在 6 个Pod,最少那就是 5 个。这时我们要实现当其创建出地 6 个的时候,将其发布暂停(此时有1个新的,5个旧的)那一个新的服务其实就是创建出的金丝雀。确认金丝雀没问题之后,让刚刚暂停住的更新继续执行,完成发布。

1. 修改 yaml 文件

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 5
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v2
        ports:
        - name: http
          containerPort: 80
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
[[email protected] rexyan]# kubectl apply -f deploy-demo.yaml 

2. 查看详细信息, 发现已经修改了。

[[email protected] rexyan]# kubectl describe deploy myapp-deploy
......
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  0 max unavailable, 1 max surge
......

3. 修改镜像版本为 v3,并让其执行更新之后暂停。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 5
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v3
        ports:
        - name: http
          containerPort: 80
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0

执行更新,并且更新后暂定

[[email protected] rexyan]# kubectl apply -f deploy-demo.yaml && kubectl rollout pause deploy myapp-deploy
deployment.apps/myapp-deploy configured
deployment.extensions/myapp-deploy paused

可以看到最后一个 Pod 是新建出来的,并没有继续往下滚动更新执行删除,而是被暂停了。

[[email protected] rexyan]# kubectl get pods 
NAME                            READY   STATUS    RESTARTS   AGE
myapp-deploy-675558bfc5-4m4nb   1/1     Running   0          64m
myapp-deploy-675558bfc5-b2lj5   1/1     Running   0          64m
myapp-deploy-675558bfc5-g4j5t   1/1     Running   0          64m
myapp-deploy-675558bfc5-h8c2c   1/1     Running   0          64m
myapp-deploy-675558bfc5-kkl22   1/1     Running   0          64m
myapp-deploy-7f577979c8-v2ljw   1/1     Running   0          24s

这时可以确认 v3 版本的程序有没有问题(验证金丝雀),如果没有问题之后就可以继续执行更新过程。我们也可以查看更新过程。

[[email protected] rexyan]# kubectl rollout status deploy myapp-deploy 
Waiting for deployment "myapp-deploy" rollout to finish: 1 out of 5 new replicas have been updated...

上面查看状态,显示的意思是,等待部署 myapp-deploy 5 个副本,已经完成了一个。

4. 继续执行更新

[[email protected] rexyan]# kubectl rollout resume deploy myapp-deploy 
deployment.extensions/myapp-deploy resumed

再次查看更新状态,发现提示已经更新完成了。

[[email protected] rexyan]# kubectl rollout status deploy myapp-deploy 
deployment "myapp-deploy" successfully rolled out

查看 Pod,以前的老版本 Pod 都被删除了。

[[email protected] rexyan]# kubectl get pods 
NAME                            READY   STATUS    RESTARTS   AGE
myapp-deploy-7f577979c8-fbsvm   1/1     Running   0          26s
myapp-deploy-7f577979c8-mq26d   1/1     Running   0          30s
myapp-deploy-7f577979c8-r68x5   1/1     Running   0          27s
myapp-deploy-7f577979c8-v2ljw   1/1     Running   0          8m19s
myapp-deploy-7f577979c8-wpktg   1/1     Running   0          28s

查看 rs 的信息,发现 rs 已经有了三个,最新的为 v3 版本的镜像。

[[email protected] rexyan]# kubectl get rs -o wide 
NAME                      DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES                 SELECTOR
myapp-deploy-675558bfc5   0         0         0       72m     myapp        ikubernetes/myapp:v2   app=myapp,pod-template-hash=675558bfc5,release=canary
myapp-deploy-67b6dfcd8    0         0         0       118m    myapp        ikubernetes/myapp:v1   app=myapp,pod-template-hash=67b6dfcd8,release=canary
myapp-deploy-7f577979c8   5         5         5       8m42s   myapp        ikubernetes/myapp:v3   app=myapp,pod-template-hash=7f577979c8,release=canary

至此,就完成了一个金丝雀发布。

回滚操作

查看当前可以回滚的版本

[[email protected] ~]# kubectl rollout history deploy myapp-deploy 
deployment.extensions/myapp-deploy 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>

当前处于最新的第三个版本,我们可以使用 –to-revision 指定回退到的版本,例如回退到第一版本

[[email protected] ~]# kubectl rollout undo deploy myapp-deploy --to-revision=1
deployment.extensions/myapp-deploy rolled back

再次查看 rollout history 会发现第一个版本已经没有了,对应的是第四个版本(其实这里的第四版本就是第一个版本)

[[email protected] ~]# kubectl rollout history deploy myapp-deploy 
deployment.extensions/myapp-deploy 
REVISION  CHANGE-CAUSE
2         <none>
3         <none>
4         <none>

查看 rs的详细信息,也会发现当前版本已经回到了第一版

[[email protected] ~]# kubectl  get rs -o wide 
NAME                      DESIRED   CURRENT   READY   AGE   CONTAINERS   IMAGES                 SELECTOR
myapp-deploy-675558bfc5   0         0         0       22h   myapp        ikubernetes/myapp:v2   app=myapp,pod-template-hash=675558bfc5,release=canary
myapp-deploy-67b6dfcd8    5         5         5       22h   myapp        ikubernetes/myapp:v1   app=myapp,pod-template-hash=67b6dfcd8,release=canary
myapp-deploy-7f577979c8   0         0         0       20h   myapp        ikubernetes/myapp:v3   app=myapp,pod-template-hash=7f577979c8,release=canary
[[email protected] ~]# 
[[email protected] ~]# 

DaemonSet

在集群中的每一个节点或者满足条件的节点之上,有且仅运行一个 Pod 副本。DaemonSet 和 Deployment 一样,所控制的 Pod 也是无状态的,且两者应用一直在后台运行(就算是任务完成 Pod 也不能退出)。简称 ds

创建资源

创建资源,DaemonSet 在每一个 node 上只运行一个副本,所有不能指定 replicas, 其余的定义方式和 deploy 差不多,env 是定义环境变量,这里定义是因为镜像使用所需。

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: myapp-ds
  namespace: default
spec:
  selector:
    matchLabels:
      app: filebeat
      release: stable
  template:
    metadata:
      labels:
        app: filebeat
        release: stable
    spec:
      containers:
      - name: filebeat
        image: ikubernetes/filebeat:5.6.5-alpine
        env:
        - name: REDIS_HOST
          value: redis.default.svc.cluster.local
        - name: REDIS_LOG_LEVEL
          value: info
[[email protected] rexyan]# kubectl create -f ds-demo.yaml 
daemonset.apps/myapp-ds created

创建资源之后就可以看到在两个节点之上分别运行了一个 Pod

[[email protected] rexyan]# kubectl get pods -o wide 
NAME                           READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
myapp-deploy-67b6dfcd8-42x9q   1/1     Running   0          45m   10.244.2.11   k8s003   <none>           <none>
myapp-deploy-67b6dfcd8-9vjwh   1/1     Running   0          44m   10.244.1.17   k8s002   <none>           <none>
myapp-deploy-67b6dfcd8-b45pt   1/1     Running   0          44m   10.244.2.13   k8s003   <none>           <none>
myapp-deploy-67b6dfcd8-c2v69   1/1     Running   0          45m   10.244.1.16   k8s002   <none>           <none>
myapp-deploy-67b6dfcd8-cr5hj   1/1     Running   0          44m   10.244.2.12   k8s003   <none>           <none>
myapp-ds-kf892                 1/1     Running   0          14s   10.244.2.14   k8s003   <none>           <none>
myapp-ds-zb82c                 1/1     Running   0          14s   10.244.1.18   k8s002   <none>           <none>

更新方式

查看 ds 的更新策略可以发现,ds 支持 RollingUpdate(滚动更新) 和 OnDelete(删除后更新) 两种更新,默认为 OnDelete

[[email protected] rexyan]# kubectl explain ds.spec.updateStrategy
KIND:     DaemonSet
VERSION:  extensions/v1beta1

RESOURCE: updateStrategy <Object>

DESCRIPTION:
     An update strategy to replace existing DaemonSet pods with new pods.

FIELDS:
   rollingUpdate    <Object>
     Rolling update config params. Present only if type = "RollingUpdate".

   type    <string>
     Type of daemon set update. Can be "RollingUpdate" or "OnDelete". Default is
     OnDelete.

当 type 是 RollingUpdate 的时候,ds.spec.updateStrategy.rollingUpdate 下只能定义 maxUnavailable 字段。即只能定义最大可减少数(max unavailable)也就是只能删除后才能更新(这也符合 DaemonSet 在 Node 上只能有一个的原则)。

Job

按照用户的定义,完成指定任务,任务正常完成后 Pod 就会正常退出,若任务没有完成 Pod 就退出,则 Pod 会被重新创建。

CronJob

周期性运行

StatefulSet

有状态应用控制器



 上一篇
K8s  Service K8s Service
Service 的分类Service 类型共有四种 ExternalName, ClusterIP(默认,仅用于集群内部), NodePort(对外), LoadBalancer(基于云平台的Service) [[email protected] ~]
2019-05-30
下一篇 
K8s 应用存活和容器启动结束钩子 K8s 应用存活和容器启动结束钩子
Pod 正常里面的 Docker 服务不一定正常。Docker 服务正常,Docker 里面的服务不一定正常。所以如何正确的监测这些状态,成为了应用健康很重要的关键。 livenessProbe, 用来判定容器是否正常。readinessP
2019-05-19
  目录