如何通过NGINX Ingress Controller暴露22端口?

7

我有一个带有NGINX Ingress控制器的Kubernetes集群。在集群中,我部署了一个Gitea POD。Web UI和HTTPS访问通过类似于这个的Ingress对象公开:

---
kind: Service
apiVersion: v1
metadata:
  name: gitea-service
  namespace: gitea-repo
spec:
  selector:
    app: gitea
  ports:
  - name: gitea-http
    port: 3000
  - name: gitea-ssh
    port: 22
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
  name: git-tls
  namespace: gitea-repo
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  tls:
  - hosts:
    - git.foo.com
    secretName: tls-gitea
  rules:
  - host: git.foo.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: gitea-service
            port:
              number: 3000

对于HTTPS,这一切都很好。

但是Gitea还通过22端口提供SSH访问。我的问题是,我该如何告诉NGINX Ingress Controller也将22端口路由到我的pod?

据我所知,我应该使用类似以下内容修补我的NGINX控制器部署:

spec:
  template:
    spec:
      containers:
      - name: controller
        # defind cusotm tcp/udp configmap
        args:
        - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-configmap-giteassh

        ports:
         - name: ssh
           containerPort: 22
           protocol: TCP

并提供一个配置映射,指向我的gitea服务:

apiVersion: v1
kind: ConfigMap
metadata:
  name: tcp-configmap-giteassh
  namespace: ingress-nginx
data:
  22: "gitea-repo/gitea-service:22"

现在我的Gitea POD是否还需要额外的Ingress配置?

我想知道这是否是正确的方法。为什么我被迫在NGINX控制器中定义它,而不是像HTTP一样在我的POD命名空间中定义呢?这意味着对于每个暴露TCP端口而非HTTP的POD,我都必须调整我的Ingress NGINX Controller吗?


我已经更新了我的答案,你能否请再尝试一下这个解决方案,并让我知道它是否对你有用? - matt_j
2个回答

7
我决定通过增加更多细节和解释来改进我的答案。
我发现你的博客文章包含了我需要复现此问题的所有信息。
在你的示例中,你需要通过端口22(它是TCP协议)传递TCP流量
NGINX Ingress Controller不支持TCP协议,因此需要进行额外的配置,可以在文档中找到。
您可以按照以下步骤公开TCP服务:
  1. 创建包含指定TCP服务配置的ConfigMap
  2. 在Ingress控制器配置中添加--tcp-services-configmap标志。
  3. 在Ingress定义的Service中公开端口22

广告1. 我们需要创建一个ConfigMap,其中键是要使用的外部端口,值表示要公开的服务(格式为<命名空间/服务名称>:<服务端口>:[代理]:[代理])。
注意:根据NGINX Ingress控制器部署的位置,您可能需要更改Namespace

$ cat ingress-nginx-tcp.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: ingress-nginx-tcp
  namespace: default  
data:
  "22": gitea-repo/gitea-service:22

第二条 在创建了ConfigMap之后,我们可以在Ingress控制器配置中使用--tcp-services-configmap标志指向它。
注意: 此外,如果您想要在端口定义中使用名称(例如22-tcp),并且在Service的targetPort属性中引用此名称,则需要定义端口22(参见:定义Service文档)。

$ kubectl get deployment ingress-nginx-controller -oyaml
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
...

第三步。 然后我们需要在Ingress定义的服务中暴露端口22

$ kubectl get svc -oyaml ingress-nginx-controller
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx-controller
  namespace: default
spec:
  ports:
  - name: 22-tcp
    nodePort: 30957
    port: 22
    protocol: TCP
    targetPort: 22
...
  type: LoadBalancer
...

最后,我们可以通过在命令行上创建一个新的存储库来检查它是否按预期工作:
注意:我们需要拥有一个带有正确SSH密钥的gitea用户与此帐户关联。

$ git add README.md
$ git commit -m "first commit"
[master (root-commit) c6fa042] first commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 README.md
$ git remote add origin git@<PUBLIC_IP>:<USERNAME>/repository.git
$ git push -u origin master
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 211 bytes | 211.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: . Processing 1 references
remote: Processed 1 references in total
To <PUBLIC_IP>:<USERNAME>/repository.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

除此之外,我们可以记录到NGINX Ingress Controller Pod,并检查它是否在端口22上进行监听:

$ kubectl exec -it ingress-nginx-controller-784d4c9d9-jhvnm -- bash
bash-5.1$ netstat -tulpn | grep 22
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -
tcp        0      0 :::22                   :::*                    LISTEN      -

到目前为止,我认为我已经理解了情况。我直接安装了NGINX Ingress控制器。当我尝试应用补丁(如我的问题所述)时,我总是会收到错误消息:“--tcp-services-configmap=ingress-nginx/tcp-configmap: 没有这样的文件或目录”。 - Ralph
根据我所看到的,你的ConfigMap命名为 tcp-configmap-giteassh,而不是 tcp-configmap。请检查在 ingress-nginx 命名空间中是否有此ConfigMap:kubectl get cm -n ingress-nginx - matt_j
是的,我在问题中犯了一个拼写错误。我已更改名称并验证了configmap在ingress-nginx命名空间中存在。但我仍然遇到了错误。 - Ralph
你的 NGINX 控制器部署中的 args: 部分看起来不太好,应该有更多的项目。请查看 此处 中的 ingress-nginx-controller 部署。也许你不小心覆盖了某些内容。 - matt_j
当您打补丁NGINX Ingress控制器时,您可能会从“args”部分中删除所有其他项,并且“--tcp-services-configmap”是唯一的项目 - 这肯定会导致错误。您可以通过描述已打补丁的Pod来确认这一点吗? - matt_j
显示剩余2条评论

0
matt_j 提供的解决方案是正确的。
对于那些已经配置了入口使用代理协议的人,需要在 configMap 中的服务地址后面添加 ":PROXY" 后缀,这样它就变成了:
apiVersion: v1
kind: ConfigMap
metadata:
  name: ingress-nginx-tcp
  namespace: default  
data:
  "22": gitea-repo/gitea-service:22:PROXY

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