kubernetes容器内的代理不会拦截任何HTTP流量

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了kubernetes容器内的代理不会拦截任何HTTP流量相关的知识,希望对你有一定的参考价值。

我渴望在一个pod中运行2个应用程序,每个应用程序都有自己的容器。应用程序A是一个简单的spring-boot应用程序,它向Kubernetes上部署的另一个应用程序发出HTTP请求。应用程序B(代理)的目的是拦截该HTTP请求并将授权令牌添加到其标头。应用程序B是带有python脚本的mitmdump。我遇到的问题是,当我在Kubernetes上进行部署时,该代理似乎根本没有拦截任何流量(我试图在本地计算机上重现此问题,但没有发现任何麻烦,所以我想这个问题位于可以在Pod内进行联网的地方)。有人可以看看它并指导我如何解决吗?

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

这是我构建mitmproxy / mitmdump的docker镜像的方式

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映像,以便在本地重新创建此方案。

  1. 打开终端并运行此命令:

    docker run -p 8080:8080 -ti Registry.gitlab.com/dyrekcja117/proxyexample:application-b-proxy

  2. 打开另一个终端并运行此命令:

    docker run --network =“ host” Registry.gitlab.com/dyrekcja117/proxyexample:application-a

  3. 进入第三终端中带有应用程序A的容器的外壳:

    docker exec -ti sh

    并尝试使卷曲到您想要的任何地址。

答案

让我们首先总结一下我们在故障排除讨论中发现的事实:

  • 您需要APP-A收到HTTP请求,并且在将请求发送到您的数据存储之前,PROXY需要在飞行中添加令牌。
  • Pod中的每个容器都共享网络名称空间,包括IP地址和网络端口。容器pod内部可以使用localhost,源here与彼此通信。
  • 您能够登录到容器application-a,并向端口curl上的容器 application-b-proxy发送1030请求,证明了上述说法。
  • 问题是您的代理未按预期拦截请求。
  • 您提到,您能够使它在localhost上运行,但是在localhost中,代理具有比容器内部更大的功能。
  • 由于我既无法访问您的app-a代码,也无法访问mitmproxy token.py,因此我将给您一个一般示例,说明如何将流量从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;
    

正在命令将流量发送到在同一吊舱内的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,而我正在使用nginxport 80上提供port 8090的服务>
  • container-b正在接收请求,就像您的application-b-proxy。我使用的图像基于mendhak/http-https-echo,通常它在port 80上侦听,我制作了一个自定义图像,只是更改为在port 8080上侦听并将其命名为echo8080

  • 首先,我创建了一个nginx pod并将其单独暴露给您看,以显示它正在运行(由于内容为空,它将返回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
  • 现在概念验证,从集群外部,我将卷曲发送到端口192.168.39.51上的节点IP 31000,该节点正在将请求发送到Pod上的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"
  ,
  • 如您所见,响应具有pod的所有参数,表明它是从127.0.0.1而不是公共IP发送的,表明NGINX正在将请求代理到container-b

注意事项:

  • 创建此示例是为了向您展示如何在kubernetes中进行通信。

  • 您将需要检查application-a如何处理请求并对其进行编辑,以将流量发送到您的代理。
  • 这里有一些教程和说明链接,可以帮助您将应用程序移植到kubernetes环境:
  • 希望在这个例子中对您有所帮助。

    以上是关于kubernetes容器内的代理不会拦截任何HTTP流量的主要内容,如果未能解决你的问题,请参考以下文章

    Kubernetes核心概念之Service详解

    kubernetes网络和CNI简介

    在 Kubernetes 上使用 Nginx SSL 代理运行 Meteor 应用程序

    Kubernetes 在现有目录上挂载卷,其中包含容器内的文件

    容器化单页面应用中Nginx反向代理与Kubernetes部署

    DEVOPS架构师 -- 04Kubernetes集群的日志及监控-更新版