Kubernetes 零停机部署不起作用 - 提供 503 服务暂时不可用

moh*_*aib 4 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 
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

当我使用helm upgrade命令升级映像时,我希望停机时间为零。同时,在升级过程中,我不断使用 curl 命令访问我的服务。这个 curl 命令给了我503-service Temporarily un-available2-3 秒的错误,然后服务再次启动。我希望这种停机时间不会发生。

Ham*_*ish 6

此问题是由 Service VIP 使用 iptables 引起的。你没有做错任何事——这是当前 Kubernetes 的一个限制。

当新 Pod 上的就绪探测通过时,旧 Pod 终止,kube-proxy 重写服务的 iptables。但是,在旧 pod 终止之后但在 iptables 更新之前,请求可能会命中服务,从而导致 503。

一个简单的解决方法是使用preStop生命周期钩子延迟终止:

lifecycle:
  preStop:
    exec:
      command: ["/bin/bash", "-c", "sleep 10"]
Run Code Online (Sandbox Code Playgroud)

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

或者,更多的副本,低maxUnavailable和高maxSurge都会降低请求命中终止 pod 的可能性。

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

另一个答案错误地表明您需要进行活性探测。虽然进行活性探测是个好主意,但它不会影响您遇到的问题。没有定义活性探针,默认状态是成功。

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

新 Pod 上的任何活性探测都是无关紧要的。当 pod 首次启动时,默认情况下它被认为是活动的。只有在initialDelaySeconds活性探针结束后才会开始检查,如果失败,pod 将被终止。

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


Ran*_*ndy 1

您描述的问题表明就绪探针存在问题。了解活性探针和就绪探针之间的差异非常重要。首先,您应该实现并配置两者!

\n\n

存活探针用于检查容器是否已启动且存活。如果不是\xe2\x80\x99t这种情况,kubernetes最终将重新启动容器。

\n\n

就绪探针还会检查容器所依赖的数据库连接或其他服务等依赖关系,以完成它\xe2\x80\x99 的工作。作为开发人员,您必须在实施上投入更多的时间,而不仅仅是活性探针。您必须公开一个端点,该端点在查询时也会检查提到的依赖关系。

\n\n

您当前的配置使用通常由活性探测器使用的运行状况端点。它可能不会检查您的服务是否真的准备好接受流量。

\n\n

Kubernetes 依赖于就绪探针。在滚动更新期间,它将保持旧容器的启动和运行,直到新服务声明它已准备好接收流量。因此,必须正确实施就绪探测。

\n