【问题标题】:How to access a pod on an external IP如何访问外部 IP 上的 Pod
【发布时间】:2021-04-07 21:17:01
【问题描述】:

我在控制平面上运行了一个名为 kube-nginx 的 pod,并转发端口。我是 Kubernetes 的大一新生。

[root@k8smaster ~]# kubectl version
Client Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.4", GitCommit:"e87da0bd6e03ec3fea7933c4b5263d151aafd07c", GitTreeState:"clean", BuildDate:"2021-02-18T16:12:00Z", GoVersion:"go1.15.8", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.4", GitCommit:"e87da0bd6e03ec3fea7933c4b5263d151aafd07c", GitTreeState:"clean", BuildDate:"2021-02-18T16:03:00Z", GoVersion:"go1.15.8", Compiler:"gc", Platform:"linux/amd64"}

[root@k8smaster ~]# cat /opt/pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: kube-nginx
spec:
  containers:
  - name: nginx
    image: nginx
[root@k8smaster ~]# kubectl get pod
NAME         READY   STATUS    RESTARTS   AGE
kube-nginx   1/1     Running   0          38m
[root@k8smaster ~]# kubectl port-forward pod/kube-nginx 10086:80
Forwarding from 127.0.0.1:10086 -> 80
Forwarding from [::1]:10086 -> 80

我可以访问localhost上的pod,但是我无法访问extenal IP上的pod。

[root@k8smaster opt]# ip a | awk '/^2: ens33/,/^3: docker/{print $2}' | sed -n '3P'
192.168.80.201/24
[root@k8smaster opt]# nc -vz localhost 10086
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: Connected to ::1:10086.
Ncat: 0 bytes sent, 0 bytes received in 0.01 seconds.

在外部 IP 主机上,我可以 ping k8smaster,但无法访问其中的 pod。

[root@k8snode01 opt]# ping -c 3 192.168.80.201
PING 192.168.80.201 (192.168.80.201) 56(84) bytes of data.
64 bytes from 192.168.80.201: icmp_seq=1 ttl=64 time=0.367 ms
64 bytes from 192.168.80.201: icmp_seq=2 ttl=64 time=0.215 ms
64 bytes from 192.168.80.201: icmp_seq=3 ttl=64 time=0.248 ms

--- 192.168.80.201 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.215/0.276/0.367/0.068 ms

[root@k8snode01 opt]# ip a | awk '/^2: ens33/,/^3: docker/{print $2}' | sed -n '3p'
192.168.80.202/24
[root@k8snode01 opt]# nc -nvz 192.168.80.201 10086
Ncat: Version 7.50 ( https://nmap.org/ncat )
Ncat: No route to host.

路由表如下所示

[root@k8snode01 opt]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.80.2    0.0.0.0         UG    100    0        0 ens33
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
192.168.16.128  192.168.80.201  255.255.255.192 UG    0      0        0 ens33
192.168.80.0    0.0.0.0         255.255.255.0   U     100    0        0 ens33

防火墙设置

[root@k8smaster ~]# iptables-save | egrep -w -- INPUT
:INPUT ACCEPT [78784:15851659]
-A INPUT -j INPUT_direct
:INPUT ACCEPT [0:0]
:INPUT ACCEPT [61299:11943644]
-A INPUT -j INPUT_direct
:INPUT ACCEPT [0:0]
:cali-INPUT - [0:0]
-A INPUT -m comment --comment "cali:Cz_u1IQiXIMmKD4c" -j cali-INPUT
-A INPUT -m conntrack --ctstate NEW -m comment --comment "kubernetes externally-visible service portals" -j KUBE-EXTERNAL-SERVICES
-A INPUT -j KUBE-FIREWALL
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -j INPUT_direct
-A INPUT -j INPUT_ZONES_SOURCE
-A INPUT -j INPUT_ZONES
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A cali-INPUT -p udp -m comment --comment "cali:w7ud0UgQSEi_zKuQ" -m comment --comment "Allow VXLAN packets from whitelisted hosts" -m multiport --dports 4789 -m set --match-set cali40all-vxlan-net src -m addrtype --dst-type LOCAL -j ACCEPT
-A cali-INPUT -p udp -m comment --comment "cali:4cgmbdWsLmozYhJh" -m comment --comment "Drop VXLAN packets from non-whitelisted hosts" -m multiport --dports 4789 -m addrtype --dst-type LOCAL -j DROP
-A cali-INPUT -i cali+ -m comment --comment "cali:t45BUBhpu3Wsmi1_" -g cali-wl-to-host
-A cali-INPUT -m comment --comment "cali:NOmsycyknYZaGOFf" -m mark --mark 0x10000/0x10000 -j ACCEPT
-A cali-INPUT -m comment --comment "cali:Or0B7eoenKO2p8Bf" -j MARK --set-xmark 0x0/0xf0000
-A cali-INPUT -m comment --comment "cali:AmIfvPGG2lYUK6mj" -j cali-from-host-endpoint
-A cali-INPUT -m comment --comment "cali:79fWWn1SpufdO7SE" -m comment --comment "Host endpoint policy accepted packet." -m mark --mark 0x10000/0x10000 -j ACCEPT

[root@k8smaster ~]# firewall-cmd --list-all
trusted (active)
  target: ACCEPT
  icmp-block-inversion: no
  interfaces: ens33
  sources:
  services:
  ports:
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

如何排除故障?

【问题讨论】:

  • @Raman Sailopal 文档使用 kind Deployment 来运行 pod,但我想使用 kind Pod 来运行 pod。 kind Pod 可以将端口暴露给外部 IP 吗?
  • 您好,能否请您详细介绍一下您是如何创建 Kubernetes 集群的?你能告诉我你到底想用$ kubectl port-forward做什么吗?我认为您应该使用Service 而不是port-forward 来公开您的kube-nginx Pod

标签: linux nginx kubernetes


【解决方案1】:

监听所有地址的10086端口,转发到pod中的80

kubectl port-forward --address 0.0.0.0 pod/kube-nginx 10086:80

【讨论】:

  • 我没看到那个输出Forwarding from 127.0.0.1:10086 -> 80 Forwarding from [::1]:10086 -> 80LOL
  • 使用 --address 0.0.0.0 效果很好,这是一种暴露 de pod 的简单方法,没有什么安全但有效!
【解决方案2】:

您可以做的是附加一个服务类型负载平衡,如下所示:

kind: Service
apiVersion: v1
metadata:
  name: kube-nginx
  namespace: <your namespace>
  labels:
    app: kube-nginx
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "your certificate"
    service.beta.kubernetes.io/aws-load-balancer-ssl-negotiation-policy: "ELBSecurityPolicy-TLS-1-2-2017-01"
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "tcp"
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443"
    service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: '*'
    service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: '3600'
spec:
  type: LoadBalancer
  selector:
    app: kube-nginx
  ports:
  - name: http
    port: 80
    targetPort: proxy
  - name: https
    port: 443
    targetPort: http

【讨论】:

    【解决方案3】:

    记住以下声明:

    我是 Kubernetes 的大一新生。

    我认为有一些话题应该解决:

    • 对该问题的一般看法
    • $ kubectl port-forward ...
    • 工作示例

    对该问题的一般看法

    Kubernetes 作为一个平台,有一个特定的对象来完成某些事情/任务。您已经创建了一个名为 kube-nginxPod,它衍生自 Nodes

    要为内部/外部资源公开Pods(如您的kube-nginx),您需要使用Service。您可以通过以下官方文档了解更多信息:

    服务

    一种将在一组 Pod 上运行的应用程序公开为网络服务的抽象方式。 使用 Kubernetes,您无需修改​​应用程序即可使用不熟悉的服务发现机制。 Kubernetes 为 Pod 提供了自己的 IP 地址和一组 Pod 的单个 DNS 名称,并且可以在它们之间进行负载平衡。

    -- Kubernetes.io: Docs: Concepts: Services networking: Service

    您的Pod 定义是正确的,它将生成一个带有nginx 图像的Pod,但Kubernetes 将无法将其暴露给外部源(除了$ kubectl port-forward,我将在稍后解决)清单中缺少某些字段。

    应该使用Services 公开的最小示例:

    apiVersion: v1
    kind: Pod
    metadata:
      name: kube-nginx
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
    

    我也认为您应该使用其他 Kubernetes 对象,例如 Deployment:

    此外,您还没有在清单中添加任何内容来强制将Pod 安排在k8smaster 上。它可以安排在k8snode01。您可以通过以下方式检查您的 Pod 在哪个 Node 上运行:

    • $ kubectl get pods/kube-nginx -o wide
    NAME         READY   STATUS    RESTARTS   AGE   IP         --> NODE <--        NOMINATED NODE   READINESS GATES
    kube-nginx   1/1     Running   0          84m   10.32.2.7  --> raven-6k6m  <--  <none>           <none>
    

    请参阅Node 列。


    $ kubectl port-forward ...

    进入kubectl port-forward pod/kube-nginx 10086:80 命令的主题。这是一个猜测,但我认为其解释是它将永久暴露 kube-nginx Pod 上的端口:10086 在运行此命令的主机上。是的,它将公开您的Pod,但在此设置中仅在 localhost 上,只要命令正在运行,它就会运行。 要公开您的工作负载,您应该使用前面提到的Services 如果您想使用$ kubectl port-forward 公开您的Pod,您应该使用用户@Phillipe 指出的命令:

    • kubectl port-forward --address 0.0.0.0 pod/kube-nginx 10086:80

    --address 0.0.0.0 将允许来自您的LAN 的传入连接(假设没有防火墙丢弃请求)。

    引用 Stackoverflow.com 的另一个答案:

    kubectl port-forward 生成一个特定的Kubernetes API request。这意味着运行它的系统需要访问 API 服务器,并且任何流量都将通过单个 HTTP 连接进行隧道传输。

    这对于调试非常有用(如果一个特定的 pod 正在运行,您可以直接连接到它;在微服务环境中,您可以与您不会公开的后端服务通信),但这不是替代方案设置服务对象。当我使用kubectl port-forward 时,它明显比通过服务连接到 pod 慢,而且我发现命令在几分钟后停止。同样,这些对于调试来说并不是什么大问题,但它们不是我想要的生产系统。

    -- Stackoverflow.com: Answer: How kubectl port-forward works


    工作示例

    假设您的集群配置正确,因为关于集群配置过程的问题中没有任何步骤,您可以使用以下示例将您的 kube-nginx Pod 公开给外部来源。

    apiVersion: v1
    kind: Pod
    metadata:
      name: kube-nginx
      labels: 
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: kube-nginx-service
    spec:
      selector:
        app: nginx # <-- this needs to match .metadata.labels field in Pod
      type: NodePort
      ports:
        - protocol: TCP
          port: 80 # <-- port inside of the cluster 
          targetPort: 80 # <-- port that app is listening on
          nodePort: 30080 # <-- from 30000 to 32767 on the node (can be changed) 
    

    通过此示例,您将生成带有nginx 图像的Pod,并允许每个Node 上的端口:30080 上的连接到达Pod(即$ curl 192.168.0.114:30080)

    LoadBalancer 类型的Service 也可以使用External IP 分配,但由于缺乏有关 Kubernetes 设置的信息,可能很难找到正确的解决方案(本地=metallb ,否则请参阅提供程序文档)。


    我还鼓励您查看以下文档以获取更多参考/最佳实践等:

    【讨论】:

      猜你喜欢
      • 2020-11-10
      • 2019-09-16
      • 2018-02-26
      • 2019-03-11
      • 2022-11-03
      • 1970-01-01
      • 2018-05-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多