【问题标题】:Kubernetes: using container as proxyKubernetes:使用容器作为代理
【发布时间】:2021-10-17 23:54:44
【问题描述】:

我有以下 pod 设置:

apiVersion: v1
kind: Pod
metadata:
  name: proxy-test
  namespace: test
spec:
  containers:
    - name: container-a
      image: <Image>
      imagePullPolicy: Always
      ports:
        - name: http-port
          containerPort: 8083
    - name: container-proxy
      image: <Image>
      ports:
        - name: server
          containerPort: 7487
          protocol: TCP
    - name: container-b
      image: <Image>

我将exec 转换成container-b 并执行以下 curl 请求:

curl --proxy localhost:7487 -X POST http://localhost:8083/

由于某种原因,http://localhost:8083/ 被直接调用,代理被忽略。有人可以解释为什么会发生这种情况吗?

【问题讨论】:

  • 几乎可以肯定,因为在大多数操作系统中,localhost 和它的 127.0.0.1 兄弟在NO_PROXY 中(即使是隐含的);如果您想通过代理联系container-a,则使用其集群内 DNS 名称或 Pod 的 IP 通知 curl 您确实希望网络请求离开该“机器”
  • @mdaniel 感谢您的回复。我认为这是有道理的。还有一个问题,如果您能回答,localhost 的流量是否也通过docker0 处理?
  • 这会令人惊讶,因为 localhost 和 127.0.0.1 有自己的网络接口 lo,用于 127/8 流量

标签: kubernetes networking amazon-eks


【解决方案1】:

环境

我在 kubeadmGCP GKE kubernetes 集群上复制了该场景,看看是否有任何区别 - 不,它们的行为相同,所以我假设 AWS EKS 的行为也应该相同。

我创建了一个包含 3 个容器的 pod:

apiVersion: v1
kind: Pod
metadata:
  name: proxy-pod
spec:
  containers:
  - image: ubuntu # client where connection will go from
    name: ubuntu
    command: ['bash', '-c', 'while true ; do sleep 60; done']
  - name: proxy-container # proxy - that's obvious
    image: ubuntu
    command: ['bash', '-c', 'while true ; do sleep 60; done']
  - name: server # regular nginx server which listens to port 80
    image: nginx

对于这个测试台,我在proxy-container (what is squid and how to install it) 上安装了squid 代理。默认情况下,它侦听端口3128

以及curl 安装在ubuntu - 客户端容器上。 (net-tools 包作为奖励,它有netstat)。

测试

注意!

  • 我使用了127.0.0.1 而不是localhost,因为squid 有一些解决问题,没有找到简单/快速的解决方案。
  • curl-v 标志一起使用以表示详细程度。

我们在 pod 中有 proxy3128nginx 80

# netstat -tulpn

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:3128            0.0.0.0:*               LISTEN      -
tcp6       0      0 :::80                   :::*                    LISTEN      -

curl直接:

# curl 127.0.0.1 -vI

*   Trying 127.0.0.1:80... # connection goes directly to port 80 which is expected
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> HEAD / HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/7.68.0
> Accept: */*

curl 通过代理:

# curl --proxy 127.0.0.1:3128 127.0.0.1:80 -vI

*   Trying 127.0.0.1:3128... # connecting to proxy!
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 3128 (#0) # connected to proxy
> HEAD http://127.0.0.1:80/ HTTP/1.1 # going further to nginx on `80`
> Host: 127.0.0.1
> User-Agent: curl/7.68.0
> Accept: */*

squid日志:

# cat /var/log/squid/access.log

1635161756.048      1 127.0.0.1 TCP_MISS/200 958 GET http://127.0.0.1/ - HIER_DIRECT/127.0.0.1 text/html
1635163617.361      0 127.0.0.1 TCP_MEM_HIT/200 352 HEAD http://127.0.0.1/ - HIER_NONE/- text/html

NO_PROXY

NO_PROXY 环境变量可能已设置,但默认为空。

我手动添加的:

# export NO_PROXY=127.0.0.1

# printenv | grep -i proxy
NO_PROXY=127.0.0.1

现在通过代理的curl 请求将如下所示:

# curl --proxy 127.0.0.1:3128 127.0.0.1 -vI

* Uses proxy env variable NO_PROXY == '127.0.0.1' # curl detects NO_PROXY envvar
*   Trying 127.0.0.1:80... # and ignores the proxy, connection goes directly
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 80 (#0)
> HEAD / HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/7.68.0
> Accept: */*

可以在使用--noproxy 标志执行curl 命令时覆盖NO_PROXY envvar。

--noproxy 无代理列表

不使用代理的主机的逗号分隔列表(如果已指定)。唯一的通配符是单个 * 字符,它匹配所有主机,并有效地禁用 代理。此列表中的每个名称都匹配为一个域 包含主机名或主机名本身。例如,local.com 将匹配 local.com、local.com:80 和 www.local.com,但不匹配 www.notlocal.com。 (在 7.19.4 中添加)。

例子:

# curl --proxy 127.0.0.1:3128 --noproxy "" 127.0.0.1 -vI

*   Trying 127.0.0.1:3128... # connecting to proxy as it was supposed to
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 3128 (#0) # connection to proxy is established
> HEAD http://127.0.0.1/ HTTP/1.1 # connection to nginx on port 80
> Host: 127.0.0.1
> User-Agent: curl/7.68.0
> Accept: */*

这证明代理是有效的!使用本地主机。

另一个选项是问题中使用的proxy 中配置不正确的内容。您可以获取此 pod 并将 squidcurl 安装到两个容器中并自己尝试。

【讨论】:

  • 我会用鱿鱼做一个测试
猜你喜欢
  • 1970-01-01
  • 2018-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-12
  • 2018-09-12
相关资源
最近更新 更多