Kubernetes零停机时间部署无法正常工作-暂时无法提供503服务

时间:2019-03-29 05:57:46

标签: kubernetes

我正在尝试使用Kubernetes实现零停机时间部署。但是每次我使用新映像进行部署升级时,都会看到2-3秒的停机时间。我正在使用Hello-World这样的应用程序进行测试,但仍然无法实现。我正在使用Helm图表部署应用程序。

在关注在线博客和资源之后,我在Deployment.yaml文件中使用了“准备情况探针和滚动更新”策略。但是,这没有给我成功。 我创建了一个/health端点,该端点仅返回200状态代码作为准备就绪探针的检查。我希望在Kubernetes中使用就绪探针和RollingUpdate策略之后,当我升级容器的映像时,我将能够实现服务的零停机时间。对我的服务的请求通过Amazon ELB进行。

Deployment.yaml文件如下:

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: wine-deployment
  labels:
    app: wine-store
    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
    release: {{ .Release.Name }}
    heritage: {{ .Release.Service }}
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  selector:
    matchLabels:
      app: wine-store
  replicas: 2
  template:
    metadata:
      labels:
        app: wine-store
    spec:
      containers:
        - name: {{ .Chart.Name }}
          resources:
            limits:
              cpu: 250m
            requests:
              cpu: 200m
          image: "my-private-image-repository-with-tag-and-version-goes-here-which-i-have-hidden-here"
          imagePullPolicy: Always
          env:
          - name: GET_HOSTS_FROM
            value: dns
          ports:
          - containerPort: 8089
            name: testing-port
          readinessProbe:
            httpGet:
              path: /health
              port: 8089
            initialDelaySeconds: 3
            periodSeconds: 3 

Service.yaml文件:

apiVersion: v1
kind: Service
metadata:
  name: wine-service
  labels:
    app: wine-store
spec:
  ports:
    - port: 80
      targetPort: 8089
      protocol: TCP
  selector:
    app: wine-store

Ingress.yaml文件:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: wine-ingress
  annotations:
     kubernetes.io/ingress.class: public-nginx
spec:
  rules:
    - host: my-service-my-internal-domain.com
      http:
        paths:
          - path: /
            backend:
              serviceName: wine-service
              servicePort: 80

当我使用helm upgrade命令升级映像时,我希望停机时间为零。同时,在进行升级时,我使用curl命令持续打我的服务。此curl命令在2-3秒内给我503-service Temporarily un-available错误,然后服务再次启动。我希望这种停机时间不会发生。

3 个答案:

答案 0 :(得分:0)

您描述的问题表明准备就绪探针存在问题。重要的是要了解活跃性和准备情况探针之间的差异。首先,您应该同时实现和配置两者!

活动性探针将检查容器是否已启动且仍处于活动状态。如果不是这种情况,kubernetes最终将重新启动容器。

准备情况探测还会依次检查依赖关系,例如数据库连接或您的容器要完成其工作所依赖的其他服务。作为开发人员,您需要在这里花更多的时间在实施上,而不仅仅是活动性探针。您必须公开一个端点,该端点在查询时还要检查提到的依赖项。

您当前的配置使用运行状况探针,通常由活动性探针使用。它可能不会检查您的服务是否真的准备好吸引流量。

Kubernetes依赖于准备情况探针。在滚动更新过程中,它将使旧容器保持运行状态,直到新服务声明已准备好接受流量为止。因此,准备情况探针必须正确实施。

答案 1 :(得分:0)

进行蓝绿色部署,因为即使Pod已启动,kube-proxy仍可能需要一些时间才能将请求转发到新的POD IP。
因此,在所有Pod都更新服务selector至新的POD标签之后,设置新的部署。 跟随:https://kubernetes.io/blog/2018/04/30/zero-downtime-deployment-kubernetes-jenkins/

答案 2 :(得分:0)

此问题是由使用iptables的Service VIP引起的。您没有做错任何事情-这是当前Kubernetes的局限性。

当新Pod上的就绪探针通过并且旧Pod终止时,kube-proxy将重写该服务的iptables。但是,在旧的Pod终止之后,但在iptables更新之前,请求可以触发该服务,从而导致503。

在这种情况下可能无关紧要,但是在您的应用程序中实现优雅终止是个好主意。拦截TERM信号,并等待您的应用程序完成对它已经收到的所有请求的处理,而不是立即退出。

或者,更多的副本,较低的maxUnavailable和较高的maxSurge都将减少请求到达终止容器的可能性。

有关更多信息: https://kubernetes.io/docs/concepts/services-networking/service/#proxy-mode-iptables https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods

另一个答案错误地建议您需要一个活力探针。虽然有一个活跃的探针是一个好主意,但它不会影响您遇到的问题。没有定义活动探针,默认状态为成功。

在滚动部署的情况下,活动性探针将是无关紧要的-一旦新Pod上的就绪性探针通过旧Pod,就将发送TERM信号,并更新iptables。现在,旧的Pod即将终止,任何活动性探针都不再重要,因为它的唯一功能是在活动性探针失败时使Pod重新启动。

在新吊舱上再次进行任何活动探测均无关紧要。首次启动Pod时,默认情况下将其视为活动状态。仅在活动性探针的initialDelaySeconds之后,才开始检查它,如果失败,则将终止该容器。

https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#container-probes