我想要一个 LoadBalancer 类型的服务,它指向端口 80 上的 nginx,并指向端口 22 的单独 sshd pod。但是,我无法使用单个选择器根据端口进行路由。
我使用的用例类似于 github.com,它接受端口 80 到 github.com 的流量以及端口 22 到 ssh 的流量。因此,在这种情况下,DNS 将指向一组 k8s 负载均衡器,我假设它们将路由到每个端口的相应 pod。所以如果我做错了,请告诉我。我愿意接受其他解决方案。
我想避免做的是设置一个像 HAProxy 那样按端口路由的单独 pod。
我研究过使用 Ingress,但它仅适用于 HTTP 流量。
Ingress 不会公开任意端口或协议。将 HTTP 和 HTTPS 以外的服务公开到互联网通常使用 Service.Type=NodePort 或 Service.Type=LoadBalancer 类型的服务。
https://kubernetes.io/docs/concepts/services-networking/ingress/
答案1
我想避免做的是设置一个像 HAProxy 那样按端口路由的单独 pod。
您不需要设置这样的单独 Pod。
Kubernetes Ingress 默认不支持 TCP 或 UDP 服务。但是例如,ingress-nginx
控制器提供了一种在不同端口上支持 TCP 或 UDP 的机制。您可以通过修改 ConfigMaps 来公开 TCP 或 UDP 端口。
因此,此 Ingress 控制器使用标志“--tcp-services-configmap”和“--udp-services-configmap”指向现有的配置映射,其中键是要使用的外部端口,值表示要使用以下格式公开的服务:
<namespace/service name>:<service port>:[PROXY]:[PROXY]
查看附加信息这里。
此类 ConfigMap 应该已经可用前部署 Ingress 控制器。
因此,请尝试:
1. 使用以下 TCP 服务配置创建 ConfigMap。
$ cat ingress-nginx-tcp.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: ingress-nginx-tcp
namespace: default
data:
"22": targetnamespace/target-service:22
--tcp-services-configmap
2. 使用配置中的标志将 Ingress 控制器指向此 ConfigMap,如下所示:
$ kubectl get deployment ingress-nginx-controller -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ingress-nginx-controller
namespace: default
spec:
...
template:
...
spec:
containers:
- args:
- /nginx-ingress-controller
- --tcp-services-configmap=$(POD_NAMESPACE)/ingress-nginx-tcp
...
3. 在为 Ingress 定义的服务中公开端口 22,如下所示:
$ kubectl get svc ingress-nginx-controller -o yaml
apiVersion: v1
kind: Service
metadata:
name: ingress-nginx-controller
namespace: default
spec:
ports:
- name: tcp-22
nodePort: 30957
port: 22
protocol: TCP
targetPort: 22
...
type: LoadBalancer
...
您可以定义任意数量的可使用此方法公开的端口。
对于那些使用ingress-nginx helm 图表。大部分配置已经完成,您只需在传输控制协议像这样的部分:
tcp:
2222: "default/example-tcp-svc:22"
其中2222
是暴露端口,22
是服务端口。
答案2
感谢@Ivan M. 为我指明了正确的方向,我只想在这里添加解决方案的代码示例:
首先,令人困惑的是,kubernetes 文档让我误以为不能使用 ingress 来处理非 http 流量。你需要知道的是,你可以使用不同的 ingress 控制器。使用 nginx ingress 控制器,你可以代理任意 tcp 甚至 udp 流量。
第二个障碍是 nginx ingress 有两个单独的存储库。它们是:
我最终使用了 kubernetes/ingress-nginx 控制器。
nginx-values.yaml
controller:
service:
enableHttp: true
tcp:
"22": "other-namespace/service-name:22"
然后我们安装 helm
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm -n nginx -f nginx-values.yaml install ingress-nginx ingress-nginx/ingress-nginx
然后我将 Ingress 安装到 k8s 中。注意ingressClassName
入口文件
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
namespace: nginx
spec:
ingressClassName: nginx
defaultBackend:
service:
name: my-http-service
port:
number: 80
然后你使用 kubectl 命令
kubectl apply -f ingress.yaml
答案3
带着同样的问题来到这里。找到了另一个不需要独立 Ingres 控制器的解决方案。不太明显,但您的服务可以从不同的部署中选择和匹配 pod,只要它们满足选择器即可。并且服务端口将仅针对具有相应端口打开的 pod。
https://www.linkedin.com/pulse/exposing-multiple-portsservices-same-load-balancer-sunil-agarwal