Отладка uWSGI в кубернетес - PullRequest
1 голос
/ 25 февраля 2020

У меня есть пара kubernetes стручков, одна для nginx и одна для Python Flask + uWSGI. Я локально проверил свою настройку в docker-compose, и она работала нормально, однако после развертывания в kubernetes как-то кажется, что между ними нет связи. В результате я получаю 502 Gateway Error при попытке добраться до моего местоположения.

Поэтому мой вопрос не в том, что не так с моей настройкой, а в том, какие инструменты я могу использовать для отладки этого сценария. Есть ли тест-клиент для uwsgi? Могу ли я использовать ncat? Кажется, я не получаю никакого полезного вывода журнала от nginx, и я не знаю, есть ли у uwsgi даже журнал.

Как я могу отладить это?

Для справки, вот мое nginx местоположение:

location / {
        # Trick to avoid nginx aborting at startup (set server in variable)
        set $upstream_server ${APP_SERVER};

        include            uwsgi_params;
        uwsgi_pass         $upstream_server;
        uwsgi_read_timeout 300;
        uwsgi_intercept_errors on;
}

Вот мое wsgi.ini:

[uwsgi]
module = my_app.app
callable = app
master = true
processes = 5
socket = 0.0.0.0:5000
die-on-term = true

uid = www-data
gid = www-data

Вот kubernetes deploy.yaml для nginx :

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    service: nginx
  name: nginx
spec:
  replicas: 1
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      service: nginx
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        service: nginx
    spec:
      imagePullSecrets:
      - name: docker-reg
      containers:
      - name: nginx
        image: <custom image url>
        imagePullPolicy: Always
        env:
          - name: APP_SERVER
            valueFrom:
              secretKeyRef:
                name: my-environment-config
                key: APP_SERVER
          - name: FK_SERVER_NAME
            valueFrom:
              secretKeyRef:
                name: my-environment-config
                key: SERVER_NAME
        ports:
        - containerPort: 80
        - containerPort: 10443
        - containerPort: 10090
        resources:
          requests:
            cpu: 1m
            memory: 200Mi
        volumeMounts:
        - mountPath: /etc/letsencrypt
          name: my-storage
          subPath: nginx
        - mountPath: /dev/shm
          name: dshm
      restartPolicy: Always
      volumes:
      - name: my-storage
        persistentVolumeClaim:
          claimName: my-storage-claim-nginx
      - name: dshm
        emptyDir:
          medium: Memory

Вот kubernetes service.yaml для nginx:

apiVersion: v1
kind: Service
metadata:
  labels:
    service: nginx
  name: nginx
spec:
  type: LoadBalancer
  ports:
  - name: "nginx-port-80"
    port: 80
    targetPort: 80
    protocol: TCP
  - name: "nginx-port-443"
    port: 443
    targetPort: 10443
    protocol: TCP
  - name: "nginx-port-10090"
    port: 10090
    targetPort: 10090
    protocol: TCP
  selector:
    service: nginx

Вот kubernetes deploy.yaml для python flask:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    service: my-app
  name: my-app
spec:
  replicas: 1
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      service: my-app
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        service: my-app
    spec:
      imagePullSecrets:
      - name: docker-reg
      containers:
      - name: my-app
        image: <custom image url>
        imagePullPolicy: Always
        ports:
        - containerPort: 5000
        resources:
          requests:
            cpu: 1m
            memory: 100Mi
        volumeMounts:
        - name: merchbot-storage
          mountPath: /app/data
          subPath: my-app
        - name: dshm
          mountPath: /dev/shm
        - name: local-config
          mountPath: /app/secrets/local_config.json
          subPath: merchbot-local-config-test.json
      restartPolicy: Always
      volumes:
      - name: merchbot-storage
        persistentVolumeClaim:
          claimName: my-storage-claim-app
      - name: dshm
        emptyDir:
          medium: Memory
      - name: local-config
        secret:
          secretName: my-app-local-config

Вот сервис kubernetes service.yaml для nginx:

apiVersion: v1
kind: Service
metadata:
  labels:
    service: my-app
  name: my-app
spec:
  ports:
  - name: "my-app-port-5000"
    port: 5000
    targetPort: 5000
  selector:
    service: my-app

1 Ответ

3 голосов
/ 25 февраля 2020

Отладка в kubernetes не сильно отличается от отладки снаружи, есть только некоторые концепции, которые необходимо наложить на мир kubernetes.

Pod в kubernetes - это то, что вы концептуально видите как хост в мире виртуальных машин. Каждый контейнер, работающий в модуле Pod, будет видеть сервисы друг друга на локальном хосте. Оттуда к любому модулю будет подключено сетевое соединение (даже если конечная точка является локальным узлом). Поэтому начните тестирование со службами на локальном хосте и пройдите через IP-адрес модуля, IP-адрес службы, имя службы.

Некоторая сложность связана с наличием инструментов отладки в контейнерах. Как правило, контейнеры построены тонкими и не имеют всего доступного. Поэтому вам нужно либо установить инструменты во время работы контейнера (если вы можете), либо создать специальный «отладочный» контейнер, который вы можете развернуть по требованию в той же среде. Вы всегда можете вернуться к тестированию с узлов кластера, которые также имеют доступ.

Если у вас есть python, вы можете провести тестирование с uswgi_curl

pip install uwsgi-tools
uwsgi_curl hostname:port /path

В противном случае nc / curl будет достаточно, до точки.

Pod to localhost

Первый шаг - убедиться, что сам контейнер отвечает. В этом случае вам, вероятно, будет доступен python / pip для использования uwsgi_curl

kubectl exec -ti my-app-XXXX-XXXX sh
nc -v localhost 5000
uwsgi_curl localhost:5000 /path

Pod to Pod / Service

Далее включите сеть kubernetes. Начните с IP-адресов и заканчивайте sh именами.

Менее вероятно, что здесь будет python или даже nc, но я думаю, что здесь важно проверить переменные среды:

kubectl exec -ti nginx-XXXX-XXXX sh
nc -v my-app-pod-IP 5000
nc -v my-app-service-IP 5000
nc -v my-app-service-name 5000

echo $APP_SERVER
echo $FK_SERVER_NAME
nc -v $APP_SERVER 5000
# or 
uwsgi_curl $APP_SERVER:5000 /path

Отладка Pod для Pod / Service

Если вам нужно использовать модуль отладки, попробуйте и имитируйте c модуль, который вы тестируете, как можно больше. Здорово иметь общий c модуль отладки / развертывания для быстрого тестирования чего угодно, но если это не выявит проблему, вам может потребоваться настроить развертывание так, чтобы оно имитировало c модуль, который вы тестируете более внимательно.

В этом случае переменные окружения играют роль в настройке соединения, поэтому их следует эмулировать для модуля отладки.

Узел к Pod / Сервису

Пакеты / Сервисы будут доступны с узлов кластера (если вы не используете ограничительные сетевые политики), поэтому обычно быстрая проверка состоит в том, чтобы проверить, что Контроллеры / Сервисы работают оттуда:

nc -v <pod_ip> <container_port>
nc -v <service_ip> <service_port>
nc -v <service__dns> <service_port>

В этом случае:

nc -v <my_app_pod_ip> 5000
nc -v <my_app_service_ip> 5000
nc -v my-app.svc.<namespace>.cluster.local 5000
...