【问题标题】:GKE Autopilot Ingress returns 502 error for 5-15 minutes after deployingGKE Autopilot Ingress 部署后 5-15 分钟返回 502 错误
【发布时间】:2021-03-26 02:37:33
【问题描述】:

我使用 GKE 在运行最新版本 Kubernetes (1.18.15-gke.1501) 的 GKE Autopilot 集群上设置了一个(非常)简单的部署,并附加了一个链接到一个简单的 @987654325 的入口(外部 HTTP(s) 负载平衡器) @服务。

每当我使用新映像更新部署时,我都会遇到大约 5-15 分钟的停机时间,此时负载平衡器会返回 502 错误。似乎控制平面创建了新的、更新的 pod,允许通过服务级别的健康检查(不是负载均衡器,它还没有创建 NEG),然后同时杀死旧的 pod是时候设置新的 NEG 了。然后它直到一段时间后才会删除旧的 NEG。

pod 上的日志显示运行状况检查正在进行,但 GKE 仪表板显示 Ingress 状态的结果不一致。入口将显示正常,但服务将显示 502。

我尝试过的事情

  • 将 pod 数量从 1 个增加到 3 个。这对某些部署有所帮助,但在其他所有部署中增加了负载均衡器正确解析所需的时间。
  • 尝试将 maxSurge 设置为 1,将 maxUnavailable 设置为 0。这根本没有改善停机时间。
  • lifecycle.preStop.exec.command: ["sleep", "60"] 添加到部署中的容器。 This was suggested in the GKE docs here.
  • 多次重新创建入口、服务、部署和集群。
  • 向服务中添加BackendConfig 会增加其消耗速度。
  • 添加在文档中找到的准备门应该可以解决这个问题,但由于某种原因没有?

以上都没有帮助,也没有明显改变事情的持续时间。

我真的很困惑为什么这不起作用。感觉就像我错过了一些明显的真的,但这也是一个如此简单的配置,你会认为它......只是工作?有人知道发生了什么吗?

配置文件

部署配置:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: foundation-deployment
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 1
  selector:
    matchLabels:
      app: foundation-web
  template:
    metadata:
      labels:
        app: foundation-web
    spec:
      readinessGates:
        - conditionType: "cloud.google.com/load-balancer-neg-ready"

      serviceAccountName: foundation-database-account
      containers:
        # Run Cloud SQL proxy so we can safely connect to Postgres on localhost.
        - name: cloud-sql-proxy
          image: gcr.io/cloudsql-docker/gce-proxy:1.17
          resources:
            requests:
              cpu: "250m"
              memory: 100Mi
            limits:
              cpu: "500m"
              memory: 100Mi
          command:
            - "/cloud_sql_proxy"
            - "-instances=nine-foundation:us-central1:foundation-staging=tcp:5432"
          securityContext:
            runAsNonRoot: true
        # Main container config
        - name: foundation-web
          image: gcr.io/project-name/foundation_web:latest
          imagePullPolicy: Always
          lifecycle:
            preStop:
              exec:
                command: ["sleep", "60"]
          env:
           # Env variables
          resources:
            requests:
              memory: "500Mi"
              cpu: "500m"
            limits:
              memory: "1000Mi"
              cpu: "1"
          livenessProbe:
            httpGet:
              path: /healthz
              port: 4000
            initialDelaySeconds: 10
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /healthz
              port: 4000
            initialDelaySeconds: 10
            periodSeconds: 10
          ports:
            - containerPort: 4000

服务配置:

apiVersion: v1
kind: Service
metadata:
  name: foundation-web-service
  annotations:
    cloud.google.com/neg: '{"ingress": true}'
    cloud.google.com/backend-config: '{"ports": {"4000": "foundation-service-config"}}'
spec:
  type: ClusterIP
  selector:
    app: foundation-web
  ports:
    - port: 4000
      targetPort: 4000

后端配置:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: foundation-service-config
spec:
  # sessionAffinity:
  #   affinityType: "GENERATED_COOKIE"
  #   affinityCookieTtlSec: 120
  connectionDraining:
    drainingTimeoutSec: 60

入口配置:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: foundation-web-ingress
  labels:
    name: foundation-web-ingress
spec:
  backend:
    serviceName: foundation-web-service
    servicePort: 4000

【问题讨论】:

  • 你解决过这个问题吗?我无法确定以下答案的头或尾,并且我遇到了完全相同的问题
  • 不,我继续前进。有点难过,GKE 在其他方面都很棒,但这是一次 糟糕 的体验。
  • 同意,这可要了我的命。如果我在下面的可能修复工作有效,我会告诉你。万一它没有……你选择了什么呢??

标签: docker kubernetes google-cloud-platform google-kubernetes-engine gke-networking


【解决方案1】:

我认为这可能与云 sql auth 代理 sidecar 未正确终止有关,导致负载均衡器出现问题。

请注意GCP docs 中的这一点(我已经制作了关键部分斜体

症状

502 错误或拒绝连接。潜在原因 新终点 通常在将它们附加到负载平衡器后变得可访问, 只要他们响应健康检查。你可能会遇到 502 如果流量无法到达端点,则会出现错误或拒绝连接。

502 错误和被拒绝的连接也可能是由容器引起的 那不处理SIGTERM。如果容器没有明确处理 SIGTERM,它立即终止并停止处理请求。这 负载均衡器继续将传入流量发送到终止 容器,导致错误。

容器原生负载均衡器只有一个后端端点。 在滚动更新期间,旧端点在 新端点被编程。

后端 Pod(s) 首次部署到新区域后 容器本机负载均衡器已配置。负载均衡器 当至少有一个区域时,基础设施被编程在一个区域中 区域中的端点。将新端点添加到区域时,加载 平衡器基础架构已编程并导致服务中断。

分辨率

配置容器以处理 SIGTERM 并继续 在整个终止宽限期内响应请求(30 默认为秒)。配置 Pod 以开始未通过健康检查 当他们收到 SIGTERM 时。这会通知负载均衡器停止 在端点解编程过程中向 Pod 发送流量。

默认情况下,代理不能很好地处理 SIGTERM,并且不会在 SIGTERM 上正常退出(请参阅related issue),但是它现在有一个很好的标志来处理这个问题,所以你可以使用类似

- name: cloud-sql-proxy
      image: gcr.io/cloudsql-docker/gce-proxy:1.23.1
      command:
        - "/cloud_sql_proxy"
        - "-instances={{ .Values.postgresConnectionName }}=tcp:5432"
        - "-term_timeout=60s"
      securityContext:
        runAsNonRoot: true
      resources:
        requests:
          memory: "2Gi"
          cpu:    "1"

添加 term_timeout 标志主要为我修复了它,但在部署期间仍然看到偶尔出现 502。一旦设置了 term_timeout,将副本增加到 3 个(我的集群是区域性的,所以我想覆盖所有区域)似乎有所帮助。

【讨论】:

    猜你喜欢
    • 2020-03-04
    • 2017-08-15
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    • 1970-01-01
    • 2020-06-14
    • 2020-04-12
    • 2022-01-11
    相关资源
    最近更新 更多