Django/Google Kubernetes 间歇性 111:连接拒绝上游服务

Posted

技术标签:

【中文标题】Django/Google Kubernetes 间歇性 111:连接拒绝上游服务【英文标题】:Django/Google Kubernetes Intermittent 111: Connection refused to upstream services 【发布时间】:2021-05-27 01:35:30 【问题描述】:

我进行了相当多的搜索,但似乎找不到任何能解决此问题的人。

我的 kubernetes 集群上出现间歇性 111 Connection denied 错误。似乎我的请求中大约 90% 成功,另外 10% 失败。如果您“刷新”页面,则先前失败的请求将成功。我有 2 个不同的 Kubernetes 集群,它们的设置完全相同,都显示了错误。

这看起来与我所经历的非常接近。我确实将我的设置安装到了一个新的集群上,但同样的问题仍然存在: Kubernetes ClusterIP intermittent 502 connection refused

设置

Kubernetes 集群版本:1.18.12-gke.1206 Django 版本:3.1.4 Helm 管理 Kubernetes 图表

集群设置

Kubernetes nginx 入口控制器,为集群提供网络流量: https://kubernetes.github.io/ingress-nginx/deploy/#gce-gke

从那里我有 2 个入口定义了基于引荐来源网址的路由流量。

    舞台入口 产品入口

入口

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: potr-tms-ingress- .Values.environment 
  namespace:  .Values.environment 
  labels:
    app: potr-tms- .Values.environment 
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/from-to-www-redirect: "true"

# this line below doesn't seem to have an effect
#    nginx.ingress.kubernetes.io/service-upstream: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "100M"
    cert-manager.io/cluster-issuer: "letsencrypt- .Values.environment "
spec:
  rules:
    - host:  .Values.ingress_host 
      http:
        paths:
        - path: /
          backend:
            serviceName: potr-tms-service- .Values.environment 
            servicePort: 8000
  tls:
    - hosts:
      -  .Values.ingress_host 
      - www. .Values.ingress_host 
      secretName: potr-tms- .Values.environment -tls

这些入口路由到我为 prod 和 stage 定义的 2 个服务:

服务

apiVersion: v1
kind: Service
metadata:
  name: potr-tms-service- .Values.environment 
  namespace:  .Values.environment 
  labels:
    app: potr-tms- .Values.environment 
spec:
  type: ClusterIP
  ports:
    - name: potr-tms-service- .Values.environment 
      port: 8000
      protocol: TCP
      targetPort: 8000
  selector:
    app: potr-tms- .Values.environment 

这 2 个服务路由到我对 prod 和 stage 的部署:

部署

apiVersion: apps/v1
kind: Deployment
metadata:
  name: potr-tms-deployment- .Values.environment 
  namespace:  .Values.environment 
  labels:
    app: potr-tms- .Values.environment 
spec:
  replicas:  .Values.deployment_replicas 
  selector:
    matchLabels:
      app: potr-tms- .Values.environment 
  strategy:
    type: RollingUpdate
  template:
    metadata:
      annotations:
        rollme:  randAlphaNum 5 | quote 
      labels:
        app: potr-tms- .Values.environment 
    spec:
      containers:
      - command: ["gunicorn", "--bind", ":8000", "config.wsgi"]
#      - command: ["python", "manage.py", "runserver", "0.0.0.0:8000"]
        envFrom:
          - secretRef:
              name: potr-tms-secrets- .Values.environment 
        image: gcr.io/potrtms/potr-tms- .Values.environment :latest
        name: potr-tms- .Values.environment 
        ports:
        - containerPort: 8000
        resources:
          requests:
            cpu: 200m
            memory: 512Mi
      restartPolicy: Always
      serviceAccountName: "potr-tms-service-account- .Values.environment "
status: 

错误 这是我在入口控制器日志中看到的错误:

这似乎很清楚,如果我的部署 pod 失败或显示错误,它们将“不可用”并且服务将无法将它们路由到 pod。为了尝试调试它,我确实增加了我的部署资源和副本数。不过,这个应用的网络流量非常低,大约 10 个用户。

我的尝试

    我尝试使用完全不同的入口控制器https://github.com/kubernetes/ingress-nginx 增加部署资源/副本数(似乎没有效果) 在全新的集群上安装我的整个设置(结果相同) 重启入口控制器/删除并重新安装 这听起来可能是 Gunicorn 问题。为了测试,我尝试使用 python manage.py runserver 启动我的 pod,但问题仍然存在。

更新

增加 pod 数量似乎有所帮助。

部署副本:15 cpu 请求:200m 内存请求:512Mi

有些请求仍然失败。

【问题讨论】:

【参考方案1】:

您找到解决方案了吗?我在 minikube 设置上看到了非常相似的东西。

在我的情况下,我相信我也看到 nginx 控制器在 502 之后重新启动。502 是间歇性的,经常第一次访问失败,然后重新加载工作。

到目前为止我发现的最好的办法是增加 Nginx 超时参数,但我还没有尝试过。仍在尝试搜索所有选项。

【讨论】:

我发现我们在生产中使用的似乎是创可贴,它似乎正在工作。错误仍然会点亮我们的日志,但请求有效,所以我们现在继续。看我的回答。 谢谢克里斯。查看我的访问日志,我可以看到 4 个上游服务器正在被访问。有一个规律的模式。三个拒绝连接,一个连接。一个连接是正确的,我需要将它的名称与其他三个隔离。现在一切都很好。 所以听起来不是服务是问题,而是它试图路由到的 pod。我可能有类似的问题。我将检查我所有的命名/命名空间。我怀疑我的一些请求被路由到一个不存在的 pod。我在同一个入口控制器后面运行 stage 和 prod 环境,这可能会造成混淆。 入口服务本身不是问题。我有第二个服务连接到 4 个 pod,然后入口连接到该服务,所以我可以循环访问所有 4 个 pod。入口只需要转到 4 个中的一个。在我的情况下,带有连接拒绝上游消息的 Nginx 访问日志显示了错误发生时上游服务器的 IP 地址,当我看到该模式时,模式很清楚。 k9s 将 IP 地址与部署相匹配。【参考方案2】:

我无法弄清楚为什么会发生这些连接错误,但我确实找到了一种解决方法,似乎可以为我们的用户解决问题。

在入口配置中添加注释

nginx.ingress.kubernetes.io/proxy-next-upstream-tries: "10"

我将它设置为 10 只是为了确保它重试,因为我相当有信心我们的服务正常工作。您可能会逃脱 2 或 3。

这是我的完整 ingress.yaml

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: potr-tms-ingress- .Values.environment 
  namespace:  .Values.environment 
  labels:
    app: potr-tms- .Values.environment 
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
#    nginx.ingress.kubernetes.io/service-upstream: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "100M"
    nginx.ingress.kubernetes.io/client-body-buffer-size: "100m"
    nginx.ingress.kubernetes.io/proxy-max-temp-file-size: "1024m"
    nginx.ingress.kubernetes.io/proxy-next-upstream-tries: "10"
    cert-manager.io/cluster-issuer: "letsencrypt- .Values.environment "
spec:
  rules:
    - host:  .Values.ingress_host 
      http:
        paths:
        - path: /
          backend:
            serviceName: potr-tms-service- .Values.environment 
            servicePort: 8000
  tls:
    - hosts:
      -  .Values.ingress_host 
      - www. .Values.ingress_host 
      secretName: potr-tms- .Values.environment -tls

【讨论】:

以上是关于Django/Google Kubernetes 间歇性 111:连接拒绝上游服务的主要内容,如果未能解决你的问题,请参考以下文章

Populate() 不是可重入的 Django Google App Engine

Django Google App Engine:502 Bad Gateway,已安装的包无法识别

使用模板变量时,Django google-maps API v3 不适用于 Chrome

Kubernetes——Kubernetes基础+部署Kubernetes集群

Kubernetes——Kubernetes基础+部署Kubernetes集群

Kubernetes - Kubernetes部署Kubernetes Dashbaord