如何在Kubernetes中暴露一个Ingress以供外部访问?

9

我有一个私有网络上的Kubernetes集群(不是AWS或Google Cloud),我创建了一个服务以便访问,但我需要能够从集群外部访问。为此,我在集群中创建了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 吗? - 0x9BD0
服务清单将无法找到Pod,原因是选择器错误。您应该使用与标签匹配的选择器,而不是部署名称。在您的示例中,应该是<code>selector: app: nginx</code>。 - Bal Chua
不是minikube,而是手写的!在“应用程序”中,我曾经有疑虑,但因为在stackoverflow上看到了一个例子而改变了想法,感谢@BalChua的分享! - user2831852
5个回答

3
您可以将Ingress控制器部署为带有主机端口80的守护进程集。此时,控制器的服务将不起作用。您可以将您的域名指向集群中的每个节点。
您可以使用NodePort类型的服务,但这将强制您使用30k附近的某个端口,您将无法使用端口80。
当然,最好的解决方案是使用具有负载均衡器的云提供商。

将其作为守护进程集暴露,并将您的域指向其中一个节点,例如将www.mydomain.com映射到其中一个节点IP,如果映射的节点失败或被取出,这不会导致故障吗? - mslot
你应该指向所有节点,但是除非有一种自动更新域目标的方法,否则这将是一个问题。正如我所说,首选的方法是支付负载均衡器,这个解决方案是为那些不想这样做的人准备的,因此显然不适用于生产部署。 - Lev Kuznetsov
啊,好的,所以您在Ingress前面放了一个类型为负载均衡器的服务 :) - mslot

2
你可以使用一个普通的nginx pod来使其工作,但推荐的方法是安装Kubernetes Ingress Controller,在你的情况下你正在使用nginx,所以你可以安装nginx ingress controller这里有一些关于如何安装它的信息。
如果你想允许外部访问,你还可以将nginx ingress controller公开为LoadBalancer服务。你也可以使用NodePort,但你必须手动将负载均衡器指向Kubernetes节点上的端口。
是的,“Service”上的选择器需要是:
selector: app: nginx

我已经运行了kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml命令来添加Nginx控制器,那么我理解这就是安装控制器的全部步骤,对吗? 接下来我会更改选择器并进行测试! - user2831852
我编辑了yaml文件并在问题中添加了代码!我将Service与app:nginx和LoadBalancer类型放置在Ingress中,我将地址更改为/teste(只是为了确保这将起作用!),但它还没有起作用。我可以通过使用主服务器的IP访问Service端口(32032),但无法通过Ingress设置访问。 kubectl get services nginx的结果: nginx LoadBalancer 10.97.197.167 <pending> 80:32032/TCP 2h 需要配置其他内容吗@Rico? - user2831852
你的服务器在哪里运行? - Rico
服务器位于公司网络上,IP地址为172.16.0.18(主节点),目前只有一个节点(用于测试),操作系统为CentOS 7。这就是关于服务器的信息了吗? - user2831852
服务类型 LoadBalancer 不可用。您需要使用 NodePort - Rico
我已删除所有(Ingress,Service和Deploy),并使用NodePort重新创建它,但它没有起作用。 我运行了命令netstat -tulnp来验证端口,端口80未出现,但服务的32622端口出现了。 应该也有80端口可用吗? 难道这不是为什么CURL总是显示“无法连接到172.16.0.18端口80:连接被拒绝”吗? - user2831852

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

1
如果您在裸机集群上运行,需要告诉nginx-ingress控制器使用hostNetwork:true,在mandatory.yml的template/spec部分中添加。这样,运行ingress控制器的pod将侦听主机节点的端口80和443。

1

https://github.com/alexellis/inlets是实现您想要的最简单的方法。
注意:加密需要wss://,这需要TLS证书。如果您希望完全自动化的加密+使用Inlets作为第4层负载平衡器的能力,则应该使用Inlets Pro,与其他云替代品相比非常便宜。

我还能够使用开源版本的Inlets作为第7层负载平衡器设置oss /非kubernetes-operator版本的Inlets,并进行加密/wss(Web套接字安全)。 (只需进行一些手动配置/不像专业版那样完全自动化)

https://blog.alexellis.io/https-inlets-local-endpoints/ 我成功地将公共互联网HTTPS + nginx入口控制器路由到minikube上,并使用入口对象测试了2个站点。在约3-4小时内完成,没有好的指南来做这件事/对Caddy/Websockets不熟悉,但是对Kubernetes Ingress很熟悉。
基本上:
第1步)在Digital Ocean上创建一个每小时0.007美元或每月5美元的VPS,并具有公共IP
第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
}


第四步.) 在Kubernetes集群上部署一个inlets deployment,使用wss连接到您的VPS,并将inlets deployment指向类型为Cluster IP的ingress controller服务。


基本原理是:
1.) Caddy利用Let's Encrypt免费自动获取每个指向Caddy服务器的网站的HTTPS证书。
2.) 您的inlets deployment使用Websockets与具有公共IP的VPS启动双向VPN隧道。(警告:只有指定了wss,VPN隧道才会被加密,这需要服务器具有TLS证书,它从"LEF"获得)
3.) Caddy现在是公共的L7 LB/反向代理,终止HTTPS,并通过加密的Websockets VPN隧道转发到您的ingress controller。然后是正常的入口。
4.) 流量流向: DNS-(解析IP)-> (HTTPS)VPS/L7反向代理-加密VPN隧道-> Inlets Deployment中的Inlets pod-L7明文在集群网络重定向到-> Ingress Controller Service -> Ingress Controller Pod-L7重定向到-> ingress对象定义的Cluster IP服务/站点。


顺便提一下:我正在撰写一篇长达四部分的博客文章,名为《深入理解Ingress》,第三篇文章将深入介绍如何使用nginx ingress控制器使入口工作。我仍在撰写过程中,但如果您有兴趣,我可以在完成后发布链接。 - neokyle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接