Чрезвычайная задержка в Django API, работающем на EKS - PullRequest
0 голосов
/ 29 мая 2019

Я развернул контейнер API Django Rest на Amazon EKS (Kubernetes), но простой HttpResponse занял около 4-8 секунд.

    def home(request):
    return HttpResponse("Homepage")

Вот мой стек:

  • EKS с 3 рабочими узлами, каждый из которых работает на t2.medium (2 CPU, 4 ГБ ОЗУ)
  • Приложение ELB: L7балансировщик нагрузки, направляющий запросы к 2 различным службам
    • echoserver: для проверки простого времени отклика
    • DjangoAPI
  • Контейнеры:

    • DjangoAPI
    • Redis - кеш
    • эхо-заголовки: простой эхо-сервер (gcr.io/google_containers/echoserver:1.4)
    NAME                               READY     STATUS    RESTARTS   AGE
    pod/djangoapi-65799dd6dc-gkpfp     1/1       Running   0          1h
    pod/echoheaders-5cff747d7d-n4jnt   1/1       Running   0          1h
    pod/redis-7d9fbf54cd-lpffv         1/1       Running   0          1h
    
    NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
    service/djangoapi-svc   NodePort    10.100.41.163    <none>        8000:30327/TCP   11d
    service/echoheaders     NodePort    10.100.94.85     <none>        80:30317/TCP     12d
    service/kubernetes      ClusterIP   10.100.0.1       <none>        443/TCP          35d
    service/redis           ClusterIP   10.100.210.207   <none>        6379/TCP         35d
    
    NAME                          DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/djangoapi     1         1         1            1           11d
    deployment.apps/echoheaders   1         1         1            1           12d
    deployment.apps/redis         1         1         1            1           35d
    

Когда тот же образ DjangoAPI был развернут в моей локальной настройке (minikube), среднее время ответа составляет около ~ 200 мс.

Dockerfile для Django:

FROM python:3.7

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN pip install --upgrade pip

RUN mkdir /app
WORKDIR /app
COPY . /app/
RUN pip install -r requirements.txt

Развертывание Django& Service yaml:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    app: djangoapi
    type: web
  name: djangoapi
  namespace: "default"
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: djangoapi
        type: web
    spec:
      containers:
      - name: djangoapi
        image: wbivan/app:speed
        imagePullPolicy: Always
        args:
        - gunicorn
        - api.wsgi
        - --bind
        - 0.0.0.0:8000
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
        envFrom:
        - configMapRef:
            name: djangoapi-config
        ports:
        - containerPort: 8000
      imagePullSecrets:
        - name: regcred
      restartPolicy: Always

---
apiVersion: v1
kind: Service
metadata:
  name: djangoapi-svc
  namespace: "default"
  labels:
    app: djangoapi
spec:
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 8000
  selector:
    app: djangoapi
    type: web
  type: NodePort  

Вещи, которые я пробовал

  1. Настройка размера экземпляра EC2 с t2.small на t2.medium
  2. Добавление дополнительных реплик DjangoAPI наРазвертывание Kubernetes (от 1 до 3)
  3. Установка и удаление ограничений ресурсов для каждого развертывания.
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
    

но при использовании вышеуказанных методов не было большой разницы

Тогда я подозреваю, что проблема была в эластичном балансировщике нагрузки.Именно поэтому я развернул эхо-сервер (используя изображение gcr.io/google_containers/echoserver:1.4).Но большинство запросов занимало только ~ 50 мс .

# This took ~50ms
  - host: echo.mydomain.com
    http:
      paths:
      - path: /*
        backend:
          serviceName: echoheaders
          servicePort: 80

# This took ~ 8000ms!!!
  - host: django.mydomain.com
    http:
      paths:
      - path: /*
        backend:
          serviceName: djangoapi-svc
          servicePort: 8000
Так что, очевидно, проблема была в сервисе django.Чтобы убедиться в этом, я сравнил одно и то же развертывание на EKS и моей локальной машине (minikube).Я пытался изолировать свой тест только на самой службе, используя kubectl port-forward deployment/djangoapi 7000:8000
  • Служба Django на Minikube : ~ 200ms
  • Служба Django на EKS : 4000-8000 мс

Наблюдения

  1. Я заметил, что время отклика в моем развертывании EKS сильно варьируется.Большая часть ответа заняла 4-8 секунд, но иногда это занимало бы только 150 мс.

  2. При использовании мониторов EC2 все 3 узла работали с загрузкой ЦП 2,5%, пики - 8%,

  3. До того, как этот проект был докеризован и развернут с использованием Kubernetes, код django был размещен на одном экземпляре t2.meduim, работающем в Ubuntu с Nginx.Среднее время отклика составило ~ 300 мс .Так что я уверен, что сам Django API не должен вызывать замедления.

Я понимаю, что несправедливо сравнивать локальное развертывание, так как сеть проще, а доступные ресурсы могут быть разными (2 CPU 2,3 ГГц i5 Mac, 2 ГБ оперативной памяти), но это поразительная разница,

У кого-нибудь есть подобный опыт и какие-либо предложения по дальнейшей отладке ситуации?

...