【问题标题】:How to expose a Ingress for external access in Kubernetes?如何在 Kubernetes 中公开 Ingress 以供外部访问?
【发布时间】:2023-03-14 02:44:01
【问题描述】:

我在私有网络(私有服务器,不是 aws 或谷歌云)上有一个 kubernetes 集群,并且我创建了一个能够访问的服务,但是,我需要能够从集群外部访问,为此我在集群中创建了一个 Ingress 并添加了 ingress-nginx。

这是我多次尝试后使用的 YAML:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: demo-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
  rules:
  - host: k8s.local
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx
          servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: ClusterIP
  selector:
    name: nginx
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  # selector:
    # app: nginx
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: echoserver
        image: nginx
        ports:
        - containerPort: 80

我这样运行 yaml:kubectl create -f file.yaml

在 /etc/hosts 文件中,我将 k8s.local 添加到主服务器的 ip。

在主服务器尝试输入或输出命令时,会出现“连接被拒绝”消息: $ curl http://172.16.0.18:80/ -H 'Host: k8s.local'

我不知道它是否重要,但我在集群中使用 Flannel。

我的想法只是创建一个“hello world”并将其暴露在集群之外!

我是否需要更改配置中的任何内容才能允许此访问?


YAML 文件已编辑:

    apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: demo-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    # nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: k8s.local
    http:
      paths:
      - path: /teste
        backend:
          serviceName: nginx
          servicePort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  type: LoadBalancer # NodePort
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: echoserver
        image: nginx
        ports:
        - containerPort: 80

【问题讨论】:

  • 你在运行 minikube 吗?
  • 由于选择器错误,服务清单将无法找到他的 pod。您应该使用匹配标签而不是部署名称的选择器。在您的示例中,它应该是 selector: app: nginx .
  • 不是minikube,是写的!在“应用程序”上,我很怀疑,我因为在 stackoverflow 中看到的一个例子而改变了,感谢您展示 @BalChua!

标签: kubernetes kubernetes-ingress nginx-ingress


【解决方案1】:

您可以将入口控制器部署为具有主机端口 80 的守护程序集。此时控制器的服务将无关紧要。您可以将您的域指向集群中的每个节点

你可以做一个 NodePort 类型的服务,但这会强制你使用 30k 附近的一些端口,你将无法使用端口 80

当然最好的解决方案是使用带有负载平衡器的云提供商

【讨论】:

  • 将其作为守护程序集公开,并将您的域指向其中一个节点,例如将 www.mydomain.com 映射到其中一个节点 IP,如果一个映射节点失败,这不会中断,还是被取出来了?
  • 你应该指向你的所有节点,但是是的,除非你有办法自动更新域目标,否则这将是一个问题。就像我说的首选方式是为负载均衡器付费,此解决方案适用于那些不想这样做的人,因此显然不是生产部署。
  • 啊,好吧,所以你在入口前面放了一个负载均衡器类型的服务:)
【解决方案2】:

您可以使用普通的 nginx pod 使其工作,但推荐的方法是安装 Kubernetes 入口控制器,在您使用 nginx 的情况下,您可以安装 nginx ingress controller

Here 是一些关于如何安装它的信息。

如果您想允许外部访问,您还可以将 nginx 入口控制器公开为LoadBalancer 服务。您也可以使用 NodePort,但您必须手动将负载均衡器指向 Kubernetes 节点上的端口。

是的,“服务”上的选择器必须是:

选择器: 应用程序:nginx

【讨论】:

  • 我已经运行kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml 命令来添加 nginx 控制器,所以我明白这只是安装控制器,对吧?我将更改选择器并测试!
  • 我编辑了 yaml 文件并在问题中添加了代码!我将服务与 app: nginx 和 LoadBalancer 的类型放在一起,在 Ingress 中我将地址更改为 /teste(只是为了确保这将工作!),但它还没有工作。我可以使用主服务器的 ip 通过服务端口 (32032) 访问,但不能通过 Ingress 设置访问。 kubectl get services nginx 的结果: nginx LoadBalancer 10.97.197.167 <pending> 80:32032/TCP 2h 需要配置其他任何东西@Rico 吗?
  • 你的服务器在哪里运行?
  • 服务器在公司网络上,ip 172.16.0.18(主),只有一个节点(现在,因为它是用于测试)和 SO CentOS 7。这就是你想知道的服务器?
  • 服务类型LoadBalancer 将不起作用。您需要使用NodePort
【解决方案3】:

在这种情况下,NodePort 可以工作。它将在每个节点中打开一个高端口号(每个节点中的相同端口),因此您可以使用这些节点中的任何一个。如果需要,可以放置一个负载均衡器,并将后端池指向您正在运行的那些实例。请勿使用 ClusterIP,仅供内部使用。

【讨论】:

    【解决方案4】:

    如果你运行你的集群裸机,你需要告诉 nginx-ingress 控制器使用 hostNetwork: true,添加到mandatory.yml 的模板/规范部分 这样,运行入口控制器的 pod 将监听主机节点的 80 和 443 端口。

    【讨论】:

      【解决方案5】:

      https://github.com/alexellis/inlets 是做你想做的最简单的方法。
      注意:加密需要 wss:// 这需要 TLS 证书,如果你想要完全自动化的加密 + 使用 Inlets 作为第 4 层 LB 的能力,你应该使用 Inlets Pro,与其他云替代方案相比它非常便宜。

      我还能够设置 oss /non-kubernetes-operator 版本的 Inlets 加密 / wss(网络套接字安全),使用 Inlets 的开源版本作为第 7 层 LB。 (它只是需要一些手动配置/不像专业版那样完全自动化)

      https://blog.alexellis.io/https-inlets-local-endpoints/ 我能够将公共互联网 HTTPS + nginx 入口控制器连接到 minikube + 测试了使用入口对象路由的 2 个站点。在大约 3-4 小时内,没有很好的指导/对 Caddy/Websockets 不熟悉,但是 Kubernetes Ingress 方面的专家。
      基本上:
      步骤 1.) 在 Digital Ocean 上使用公共 IP 创建 0.007 美元/小时或 5 美元/月的 VPS
      第 2 步。)将 mysite1.com、*.mysite1.com、mysite2.com、*.mysite2.com 指向 VPS 的公共 IP。
      步骤 3.) SSH 进入机器并安装 Inlets + Caddy v1.0.3 + Caddyfile 这是我的:

      mysite1.com, *.mysite1.com, mysite2.com, *.mysite2.com
      
      proxy / 127.0.0.1:8080 {
        transparent
      }
      
      proxy /tunnel 127.0.0.1:8080 {
        transparent
        websocket
      }
      
      tls {
          max_certs 10
      }
      


      第 4 步。)在 kubernetes 集群上部署 1 个入口部署,将 wss 用于您的 VPS,并将入口部署指向集群 IP 类型的入口控制器服务。


      发生的基本情况是:
      1.) Caddy 利用 Lets Encrypt Free 为您指向 Caddy 服务器的每个网站自动获取 HTTPS 证书。
      2.) 您的入口部署使用具有公共 IP 的 VPS 使用 websockets 启动双向 VPN 隧道。 (警告 VPN 隧道只有在您指定 wss 时才会被加密,并且这要求服务器具有从“LEF”获取的 TLS 证书)
      3.) Caddy 现在是一个公共的 L7 LB/反向代理,它终止 HTTPS,并通过加密的 websockets VPN 隧道转发到您的入口控制器。然后是正常的入口。
      4.) 流量:DNS -(解析 IP)-> (HTTPS)VPS/L7 ReverseProxy - 加密的 VPNtunnel-> Inlets 部署中的 Inlets pod -L7 集群网络中的明文重定向到 -> Ingress Controller Service -> Ingress Controller Pod -L7 重定向到-> 由入口对象定义的集群 IP 服务/站点。

      【讨论】:

      • 附带说明:我正在撰写一篇关于 Ingress in Depth 的长篇 4 部分系列博客文章,第 3 篇文章将深入介绍如何使入口与 nginx 入口控制器一起工作,我是仍在编写中,但如果您有兴趣,我可以在完成后发布它的链接。
      猜你喜欢
      • 2019-05-12
      • 1970-01-01
      • 2019-07-18
      • 2017-02-13
      • 2020-05-01
      • 2020-03-19
      • 1970-01-01
      • 2021-11-04
      • 1970-01-01
      相关资源
      最近更新 更多