Deployment 为什么在滚动更新部署或缩小复制集时会出现停机

Deployment 为什么在滚动更新部署或缩小复制集时会出现停机,deployment,kubernetes,replicaset,Deployment,Kubernetes,Replicaset,由于kubernetes的官方文件 Rolling updates allow Deployments' update to take place with zero downtime by incrementally updating Pods instances with new ones 我尝试使用rollingupdate策略执行零停机更新,这是kube集群中更新应用程序的推荐方法。 官方参考: 但在执行时,我对这个定义有点困惑:应用程序的宕机仍然会发生。下面是我的集群信息,如下图所

由于kubernetes的官方文件

Rolling updates allow Deployments' update to take place with zero downtime by incrementally updating Pods instances with new ones
我尝试使用
rollingupdate
策略执行零停机更新,这是kube集群中更新应用程序的推荐方法。 官方参考:

但在执行时,我对这个定义有点困惑:应用程序的宕机仍然会发生。下面是我的集群信息,如下图所示:

liguuudeiMac:~ liguuu$ kubectl get all
NAME                                     READY   STATUS    RESTARTS   AGE
pod/ubuntu-b7d6cb9c6-6bkxz               1/1     Running   0          3h16m
pod/webapp-deployment-6dcf7b88c7-4kpgc   1/1     Running   0          3m52s
pod/webapp-deployment-6dcf7b88c7-4vsch   1/1     Running   0          3m52s
pod/webapp-deployment-6dcf7b88c7-7xzsk   1/1     Running   0          3m52s
pod/webapp-deployment-6dcf7b88c7-jj8vx   1/1     Running   0          3m52s
pod/webapp-deployment-6dcf7b88c7-qz2xq   1/1     Running   0          3m52s
pod/webapp-deployment-6dcf7b88c7-s7rtt   1/1     Running   0          3m52s
pod/webapp-deployment-6dcf7b88c7-s88tb   1/1     Running   0          3m52s
pod/webapp-deployment-6dcf7b88c7-snmw5   1/1     Running   0          3m52s
pod/webapp-deployment-6dcf7b88c7-v287f   1/1     Running   0          3m52s
pod/webapp-deployment-6dcf7b88c7-vd4kb   1/1     Running   0          3m52s
NAME                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/kubernetes          ClusterIP   10.96.0.1       <none>        443/TCP          3h16m
service/tc-webapp-service   NodePort    10.104.32.134   <none>        1234:31234/TCP   3m52s
NAME                                READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ubuntu              1/1     1            1           3h16m
deployment.apps/webapp-deployment   10/10   10           10          3m52s
NAME                                           DESIRED   CURRENT   READY   AGE
replicaset.apps/ubuntu-b7d6cb9c6               1         1         1       3h16m
replicaset.apps/webapp-deployment-6dcf7b88c7   10        10        10      3m52s
ubuntu应用程序的输出(一切正常):

然后我尝试将tomcat图像的标记从
8-jdk8
更改为
8-jdk11
。请注意,
deployment.apps/webapp deployment
的滚动更新策略已正确配置,maxSurge
0
和maxUnavailable
9
(如果这两个属性为默认值,则结果相同)

然后,ubuntu应用程序的输出:

HTTP/1.1 200 
2019-08-30 07:47:43
curl: (56) Recv failure: Connection reset by peer
2019-08-30 07:47:43
HTTP/1.1 200 
2019-08-30 07:47:44
如上所示,一些http请求失败,这无疑是对kube集群中的应用程序执行滚动更新时应用程序的中断。 但是,我也可以在
缩小
中重放上述情况(中断),命令如下所示(从10到2):

在执行了上述测试之后,我想知道所谓的
零停机时间
实际上是否意味着什么。尽管模拟http请求的方式有点棘手,但对于一些设计为能够在一秒钟内处理成千上万个请求的应用程序来说,这种情况是很正常的

环境:

部署和服务配置:

# Service
apiVersion: v1
kind: Service
metadata:
  name: tc-webapp-service
spec:
  type: NodePort
  selector:
    appName: tc-webapp
  ports:
  - name: tc-svc
    protocol: TCP
    port: 1234
    targetPort: 8080
    nodePort: 31234
---
# Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp-deployment
spec:
  replicas: 10
  selector:
    matchLabels:
      appName: tc-webapp
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 9
  # Pod Templates
  template:
    metadata:
      labels:
        appName: tc-webapp
    spec:
      containers:          
      - name: tc-part
        image: tomcat:8-jdk8
        ports:
        - containerPort: 8080
        livenessProbe:
          tcpSocket:
            port: 8080            
          initialDelaySeconds: 10
          periodSeconds: 10
        readinessProbe:
          httpGet:
            scheme: HTTP
            port: 8080
            path: /
          initialDelaySeconds: 5
          periodSeconds: 1 

要部署一个真正能够以零停机时间进行更新的应用程序,该应用程序应该满足一些要求。仅举几个例子:

  • 应用程序应该能够正常关闭
  • 应用程序应该正确地实现就绪性和活动性探测

例如,如果接收到关机信号,则它不应以200响应新的就绪探测,但在处理所有旧请求之前,它仍会以200响应活动性。

在滚动更新期间,会创建新的播客,当它们准备就绪时,流量会转移到新播客,而旧播客则会终止。如果您提交了一个由旧pod处理的请求,并且在pod完成请求之前,该请求的流量被转移到新pod,并且旧pod被终止,则该请求将收到连接重置错误。我不知道你看到的是不是这样。从技术上讲,那里没有停机时间,系统从不停止接受请求。我同意你的观点,兄弟,但我仍然认为这是kube的错误,因为在Pod的整个生命周期中确认Pod的状态应该是kube的职责。例如,如上所述(缩小rs),一旦Pod计划终止,应立即通知服务,并且不应将流量转发到终止Pod。然而,我相信一定有类似于
最佳实践的东西
,所以如果您能展示一些更正确的探针配置,支持上面所示的零停机滚动部署更新(tomcat webapp),我将非常感激,,,谢谢:)问题是服务会立即被注意到,但它不能正确处理信号。在正确开发应用程序方面,还有很多工作要做,而不是配置探测器。作为基础,我可以推荐我的项目。它不支持100%的零停机停机,但它阻碍了这一点。我将在几周内相应地更新它。
...
    spec:
      containers:          
      - name: tc-part
        image: tomcat:8-jdk8 -> tomcat:8-jdk11
...
HTTP/1.1 200 
2019-08-30 07:47:43
curl: (56) Recv failure: Connection reset by peer
2019-08-30 07:47:43
HTTP/1.1 200 
2019-08-30 07:47:44
kubectl scale deployment.apps/tc-webapp-service --replicas=2
liguuudeiMac:cacheee liguuu$ minikube version
minikube version: v1.3.1
commit: ca60a424ce69a4d79f502650199ca2b52f29e631
liguuudeiMac:cacheee liguuu$ kubectl version
Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.3", GitCommit:"5e53fd6bc17c0dec8434817e69b04a25d8ae0ff0", GitTreeState:"clean", BuildDate:"2019-06-06T01:44:30Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.2", GitCommit:"f6278300bebbb750328ac16ee6dd3aa7d3549568", GitTreeState:"clean", BuildDate:"2019-08-05T09:15:22Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"linux/amd64"}
# Service
apiVersion: v1
kind: Service
metadata:
  name: tc-webapp-service
spec:
  type: NodePort
  selector:
    appName: tc-webapp
  ports:
  - name: tc-svc
    protocol: TCP
    port: 1234
    targetPort: 8080
    nodePort: 31234
---
# Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp-deployment
spec:
  replicas: 10
  selector:
    matchLabels:
      appName: tc-webapp
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 0
      maxUnavailable: 9
  # Pod Templates
  template:
    metadata:
      labels:
        appName: tc-webapp
    spec:
      containers:          
      - name: tc-part
        image: tomcat:8-jdk8
        ports:
        - containerPort: 8080
        livenessProbe:
          tcpSocket:
            port: 8080            
          initialDelaySeconds: 10
          periodSeconds: 10
        readinessProbe:
          httpGet:
            scheme: HTTP
            port: 8080
            path: /
          initialDelaySeconds: 5
          periodSeconds: 1