简体   繁体   English

Kubernetes Nginx Ingress Connection Refused on External IP Address (Bare Metal)

[英]Kubernetes Nginx Ingress Connection Refused on External IP Address (Bare Metal)

I've setup an ingress resource to route requests to single service.我已经设置了一个入口资源来将请求路由到单个服务。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    #kubernetes.io/ingress.class: nginx
    #ingress.kubernetes.io/rewrite-target: /

spec:
  defaultBackend:
    service:
      name: dashboard
      port:
        number: 80
$ kubectl get ing
NAME              CLASS    HOSTS   ADDRESS         PORTS   AGE
example-ingress   <none>   *       102.16.50.202   80      3m28s

The nginx-controller: nginx 控制器:

$ kubectl get pods -n ingress-nginx
NAME                                        READY   STATUS      RESTARTS      AGE
ingress-nginx-admission-create--1-gl59f     0/1     Completed   0             15h
ingress-nginx-admission-patch--1-9kbz6      0/1     Completed   0             15h
ingress-nginx-controller-54d8b558d4-2ss8f   1/1     Running     1 (13h ago)   15h

$ kubectl get svc -n ingress-nginx
NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.233.48.242   102.16.50.202   80:31690/TCP,443:32666/TCP   15h
ingress-nginx-controller-admission   ClusterIP      10.233.17.68    <none>          443/TCP                      15h

I'm able to reach and get response from the service via the controller's cluster IP:我可以通过控制器的集群 IP 访问服务并获得响应:

$ curl -i 10.233.48.242
HTTP/1.1 200 OK
Date: Tue, 08 Feb 2022 04:50:44 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 2306
Connection: keep-alive
X-Powered-By: Express
Accept-Ranges: bytes
Cache-Control: public, max-age=0
Last-Modified: Tue, 25 Jan 2022 09:35:14 GMT
ETag: W/"902-17e9096e050"
...

But not on its (nginx-controller's) external IP address:但不在其(nginx 控制器的)外部 IP 地址上:

$ curl -i 102.16.50.202
curl: (7) Failed to connect to 102.16.50.202 port 80: Connection refused

$ curl -i http://102.16.50.202
curl: (7) Failed to connect to 102.16.50.202 port 80: Connection refused

$ curl -i http://102.16.50.202/
curl: (7) Failed to connect to 102.16.50.202 port 80: Connection refused

I tried creating a new path (prefix), changed service type to NodePort, disabled the firewall, with no success;我尝试创建一个新路径(前缀),将服务类型更改为 NodePort,禁用防火墙,但没有成功; same issue.同样的问题。

Any observation or input would help a lot.任何观察或输入都会有很大帮助。 Thanks.谢谢。

Edit-1:编辑-1:

The nginx ingress controller is installed ( kubectl apply ) without modifying the default configuration :安装 nginx 入口控制器 ( kubectl apply ) 而不修改默认配置

#file: ingress-controller-deploy.yml
...
apiVersion: v1
kind: Service
metadata:
  annotations:
  labels:
    helm.sh/chart: ingress-nginx-4.0.15
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/version: 1.1.1
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/component: controller
  name: ingress-nginx-controller
  namespace: ingress-nginx
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  ipFamilyPolicy: SingleStack
  ipFamilies:
    - IPv4
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: http
      appProtocol: http
    - name: https
      port: 443
      protocol: TCP
      targetPort: https
      appProtocol: https
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/component: controller

The externalTrafficPolicy:Local seems to be ok if I'm using a load balancer, which in my case is MetalLB .如果我使用的是负载均衡器,则externalTrafficPolicy:Local似乎没问题,在我的例子中是MetalLB

#file: ingress-controller-deploy.yml
apiVersion: apps/v1
kind: Deployment
...
          securityContext:
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            runAsUser: 101
            allowPrivilegeEscalation: true

The securityContext section seems ok too. securityContext部分似乎也不错。

The ingress object is not your issue.入口对象不是您的问题。 You have to concentrate on the ingress-controller setup.您必须专注于入口控制器设置。 Also, which load-balancing mechanism are you using?另外,您使用的是哪种负载平衡机制? If you are on Bare Metal, you need to deploy something like MetalLB, which you probably already have (otherwise the service of type LoadBalancer stays in pending state).如果您在 Bare Metal 上,则需要部署类似 MetalLB 之类的东西,您可能已经拥有它(否则 LoadBalancer 类型的服务将保持挂起状态)。

Good documentation around this topic can be found at https://kubernetes.github.io/ingress-nginx/deploy/baremetal/可以在https://kubernetes.github.io/ingress-nginx/deploy/baremetal/找到有关此主题的良好文档

After reading tons of docs and github issues I came to conclusion than on bare-metal setup without editing ingress controller deploy.yaml (like adding hostNetwork: true ) you can't access exposed ingress IP address by port 80. However, if you specify port which is displayed in service ingress-nginx-controller then you can successfully access exposed service from external network.在阅读了大量文档和 github 问题后,我得出的结论是,在未编辑入口控制器 deploy.yaml 的裸机设置(如添加hostNetwork: true )时,您无法通过端口 80 访问暴露的入口 IP 地址。但是,如果您指定服务ingress-nginx-controller中显示的端口,然后您可以成功地从外部网络访问暴露的服务。

My steps:我的步骤:

  • install ingress controller安装入口控制器

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/baremetal/deploy.yaml

  • launch echo server (yaml files taken from echo server )启动 echo 服务器(取自echo server的 yaml 文件)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: echo-server
  template:
    metadata:
      labels:
        app: echo-server
    spec:
      containers:
        - name: echo-server
          image: jmalloc/echo-server
          ports:
            - name: http-port
              containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: echo-service
spec:
  ports:
    - name: http-port
      port: 80
      targetPort: http-port
      protocol: TCP
  selector:
    app: echo-server
  • install ingress安装入口
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: echo-ingress
    spec:
      rules:
      - host: echo.k8s-test
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: echo-service
                port:
                  number: 80
      ingressClassName: nginx
  • While ingress is aquiring IP address lets check data on ingress-nginx-controller:当 ingress 正在获取 IP 地址时,让我们检查 ingress-nginx-controller 上的数据:
$ kubectl get svc ingress-nginx-controller -n ingress-nginx
NAME                       TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller   NodePort   10.105.96.55   <none>        80:30097/TCP,443:32746/TCP   82m

Note port 30097注意端口 30097

  • Check ingress status检查入口状态
$ kubectl get ing echo-ingress
NAME           CLASS   HOSTS           ADDRESS           PORTS   AGE
echo-ingress   nginx   echo.k8s-test   192.168.122.222   80      81m

192.168.122.222 is IP assigned to NIC on one of worker nodes. 192.168.122.222 是分配给工作节点之一上的 NIC 的 IP。

Now, from outside k8s cluster, we can access现在,从 k8s 集群外部,我们可以访问

$ curl http://192.168.122.222:30097 -H "Host: echo.k8s-test"
Request served by echo-deployment-8586b5977c-pt2pp

HTTP/1.1 GET /

Host: echo.k8s-test
User-Agent: curl/7.47.0
Accept: */*
X-Real-Ip: 10.244.1.1
X-Forwarded-Host: echo.k8s-test
X-Forwarded-Proto: http
X-Forwarded-Scheme: http
X-Scheme: http
X-Request-Id: 188379f183fe0c3e7ddc612b85d0d76d
X-Forwarded-For: 10.244.1.1
X-Forwarded-Port: 80

I was facing exactly the same issue on my bare metal setup.我在裸机设置中遇到了完全相同的问题。 Only difference was that I was using kube-vip instead of MetalLB.唯一不同的是我使用的是kube-vip而不是 MetalLB。 It was finally fixed when I changed the externalTrafficPolicy on ingress-nginx-controller service to Cluster .当我将ingress-nginx-controller服务上的externalTrafficPolicy更改为Cluster时,它终于得到了修复。

I'm unable to reason why, but the closest I could come up with is that the Loadbalancer IP was acquired by node-1 of my bare metal setup, whereas the web frontend was scheduled on node-2我无法解释为什么,但我能想到的最接近的是负载平衡器 IP 是由我的裸机设置的node-1获取的,而 Web 前端被安排在node-2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM