Прокси-сервер внутри модуля kubernetes не перехватывает трафик HTTP - PullRequest
1 голос
/ 30 марта 2020

Я жажду, чтобы в модуле работало 2 приложения, каждое из которых имеет свой собственный контейнер. Приложение A - это простое приложение с начальной загрузкой, которое отправляет HTTP-запросы другому приложению, которое развернуто в Kubernetes. Назначение приложения B (прокси) - перехватить этот HTTP-запрос и добавить токен авторизации в его заголовок. Приложение B - это mitmdump со скриптом python. Проблема, с которой я сталкиваюсь, заключается в том, что при развертывании в Kubernetes прокси-сервер, похоже, вообще не перехватывает трафик c (я пытался воспроизвести эту проблему на своем локальном компьютере и не обнаружил никаких проблем, поэтому я угадайте, что проблема лежит где-то в сети внутри стручка). Может кто-нибудь взглянуть на него и подсказать, как его решить?

enter image description here

Вот файл развертывания и обслуживания.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: proxy-deployment
  namespace: myown
  labels:
    app: application-a
spec:
  replicas: 1
  selector:
    matchLabels:
      app: application-a
  template:
    metadata:
      labels:
        app: application-a
    spec:
      containers:
      - name: application-a
        image: registry.gitlab.com/application-a
        resources:
          requests:
            memory: "230Mi"
            cpu: "100m"
          limits:
            memory: "460Mi"
            cpu: "200m"
        imagePullPolicy: Always
        ports:
        - containerPort: 8090
        env:
        - name: "HTTP_PROXY"
          value: "http://localhost:1030"
      - name:
        image: registry.gitlab.com/application-b-proxy
        resources:
          requests:
            memory: "230Mi"
            cpu: "100m"
          limits:
            memory: "460Mi"
            cpu: "200m"
        imagePullPolicy: Always
        ports:
        - containerPort: 1080
---
kind: Service
apiVersion: v1
metadata:
  name: proxy-svc
  namespace: myown
spec:
  ports:
  - nodePort: 31000
    port: 8090
    protocol: TCP
    targetPort: 8090
  selector:
    app: application-a
  sessionAffinity: None
  type: NodePort

А вот как я создаю docker образ mitmproxy / mitmdump

FROM mitmproxy/mitmproxy:latest

ADD get_token.py .
WORKDIR ~/mit_docker
COPY get_token.py .
EXPOSE 1080:1080
ENTRYPOINT ["mitmdump","--listen-port", "1030", "-s","get_token.py"]

РЕДАКТИРОВАТЬ

Я создал два фиктивных docker изображения, чтобы иметь этот сценарий воссоздается локально.

APPLICATION A - приложение с пружинной загрузкой с заданием создавать запрос HTTP GET каждую 1 минуту для указанного, но не относящегося к делу адреса, адрес должен быть доступен. Ответ должен быть 302 НАЙДЕН. Каждый раз, когда делается HTTP-запрос, в журналах приложения появляется сообщение.

APPLICATION B - прокси-приложение, которое должно проксировать контейнер docker с приложением A. Каждый запрос заносится в журнал.

  1. Убедитесь, что ваш прокси-сервер конфигурации docker настроен на прослушивание http://localhost: 8080 - , вы можете проверить, как сделайте это здесь

  2. Откройте терминал и выполните эту команду:

 docker run -p 8080:8080 -ti registry.gitlab.com/dyrekcja117/proxyexample:application-b-proxy
Откройте другой терминал и выполните эту команду:
    docker run --network="host" registry.gitlab.com/dyrekcja117/proxyexample:application-a
Go в оболочку с контейнером приложения A на 3-м терминале:
    docker exec -ti <name of docker container> sh

и попытайтесь свернуться на любой адрес, который вы хотите.

И проблема, с которой я сталкиваюсь, заключается в том, что когда я делаю curl изнутри контейнера с приложением A, он перехватывается моим прокси и это можно увидеть в журналах. Но всякий раз, когда само приложение A делает один и тот же запрос, оно не перехватывается. То же самое происходит с Кубернетесом

1 Ответ

1 голос
/ 07 апреля 2020

Давайте сначала обернем факты, которые мы обнаружим в нашей дискуссии по устранению неполадок, в комментариях:

  • Вам необходимо, чтобы APP-A получил HTTP-запрос, и PROXY должен добавить токен перед полетом PROXY. отправка запроса в ваше хранилище данных.
  • Каждый контейнер в модуле разделяет пространство имен сети, включая IP-адрес и сетевые порты. Контейнеры внутри контейнера могут связываться друг с другом, используя localhost, источник здесь .
  • Вы смогли войти в контейнер application-a и отправить curl запрос к контейнеру application-b-proxy через порт 1030, подтверждающий вышеприведенное утверждение.
  • Проблема в том, что ваш прокси не перехватывает запрос, как ожидалось.
  • Вы упоминаете, что в вас было в состоянии заставить его работать на локальном хосте, но на локальном хосте прокси обладает большей мощностью, чем внутри контейнера.
  • Поскольку у меня нет доступа ни к вашему app-a коду, ни к mitmproxy token.py я дам общий пример того, как перенаправить трафик c с container-a на container-b
  • . Чтобы заставить его работать, я буду использовать NGINX Proxy Pass : это просто передает запрос на container-b.

Воспроизведение:

  • Я буду использовать сервер nginx как container-a.

  • Я построю это с этим Dockerfile:

FROM nginx:1.17.3
RUN rm /etc/nginx/conf.d/default.conf
COPY frontend.conf /etc/nginx/conf.d
  • Я добавлю это файл конфигурации frontend.conf:
server {
    listen 80;

    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

Заказываемый трафик c должен быть отправлен на container-b, который прослушивает port 8080 внутри того же модуля.

  • Я создам этот образ как nginxproxy в моем локальном репо:
$ docker build -t nginxproxy .

$ docker images 
REPOSITORY        TAG       IMAGE ID        CREATED          SIZE
nginxproxy    latest    7c203a72c650    4 minutes ago    126MB
  • Теперь развертывание full.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: proxy-deployment
  labels:
    app: application-a
spec:
  replicas: 1
  selector:
    matchLabels:
      app: application-a
  template:
    metadata:
      labels:
        app: application-a
    spec:
      containers:
      - name: container-a
        image: nginxproxy:latest
        ports:
        - containerPort: 80
        imagePullPolicy: Never
      - name: container-b
        image: echo8080:latest
        ports:
        - containerPort: 8080
        imagePullPolicy: Never
---
apiVersion: v1
kind: Service
metadata:
  name: proxy-svc
spec:
  ports:
  - nodePort: 31000
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: application-a
  sessionAffinity: None
  type: NodePort    

ПРИМЕЧАНИЕ: Я установил imagePullPolicy как Never, потому что я использую локальный docker кэш изображений.

Я перечислю изменения, которые я сделал, чтобы помочь вам связать это в вашей текущей среде:

  • container-a выполняет работу вашего application-a, и я служу nginx на port 80, где вы используете port 8090
  • container-b получает запрос, как ваш application-b-proxy. Изображение, которое я использую, основано на mendhak/http-https-echo, обычно оно слушает port 80, я сделал собственное изображение, просто меняющееся на port 8080, и назвал его echo8080.

  • Сначала я создал модуль nginx и показал его в одиночку, чтобы показать вам, что он работает (так как он пуст по содержанию, он вернет bad gateway, но вы можете видеть, что вывод получен из nginx:

$ kubectl apply -f nginx.yaml 
pod/nginx created
service/nginx-svc created

$ kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
nginx                              1/1     Running   0          64s
$ kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
nginx-svc    NodePort    10.103.178.109   <none>        80:31491/TCP   66s

$ curl http://192.168.39.51:31491
<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.17.3</center>
</body>
</html>
  • Я удалил модуль nginx и создал модуль echo-app и показал его, чтобы показать вам ответ, который он дает, когда его прямо свернули снаружи:
$ kubectl apply -f echo.yaml 
pod/echo created
service/echo-svc created

$ kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
echo                               1/1     Running   0          118s
$ kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
echo-svc     NodePort    10.102.168.235   <none>        8080:32116/TCP   2m

$ curl http://192.168.39.51:32116
{
  "path": "/",
  "headers": {
    "host": "192.168.39.51:32116",
    "user-agent": "curl/7.52.1",
  },
  "method": "GET",
  "hostname": "192.168.39.51",
  "ip": "::ffff:172.17.0.1",
  "protocol": "http",
  "os": {
    "hostname": "echo"
  },
  • Теперь я буду применять full.yaml:
$ kubectl apply -f full.yaml 
deployment.apps/proxy-deployment created
service/proxy-svc created
$ kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
proxy-deployment-9fc4ff64b-qbljn   2/2     Running   0          1s

$ k get service
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
proxy-svc    NodePort    10.103.238.103   <none>        80:31000/TCP   31s
  • Теперь Доказательство концепции, из-за пределов кластера, я пришлю curl для моего узла IP 192.168.39.51 в порту 31000, который отправляет запрос на port 80 на модуле (обрабатывается nginx):
$ curl http://192.168.39.51:31000
{
  "path": "/",
  "headers": {
    "host": "127.0.0.1:8080",
    "user-agent": "curl/7.52.1",
  },
  "method": "GET",
  "hostname": "127.0.0.1",
  "ip": "::ffff:127.0.0.1",
  "protocol": "http",
  "os": {
    "hostname": "proxy-deployment-9fc4ff64b-qbljn"
  },
  • As Вы можете видеть, что в ответе есть все параметры модуля, указывающие, что он был отправлен с 127.0.0.1 вместо общедоступного c IP, показывая, что NGINX передает запрос на container-b.

Соображения:

Надеюсь помочь вам с этим примером.

...