Kubernetes Ingress 可将集群内部的 Service 通过 HTTP/HTTPS 的方式暴露供外部访问,并通过路径匹配规则定义服务的路由。但是 Ingress 对 TCP/UDP 的服务却支持的不那么好。如果我们服务中有使用 Websocket 或 Socket, 需要暴露给外部访问,在 Kubernetes 中该如何配置呢?

大致有两种方式[见参考文档1]:

  1. 使用 NodePort, 使用节点 IP 与 NodePort 暴露的端口访问
  2. 使用 ClusterIp + Ingress + ConfigMap

使用 NodePort 将端口直接暴露,需要节点有外网 IP,且该方式可能绕过现有的 TLS, 存在安全性的问题。

ClusterIp 只能在集群内部访问,由 Ingress 进行代理对外暴露,但对于 TCP/UDP, Ingress 不支持直接代理, 需要借助 ConfigMap 进行映射。

NodePort 的方式比较简单, 本文介绍 ClusterIp + Ingress + ConfigMap 的方式。

创建 ClusterIp 服务

假设有一个 Websocket/Socket 服务,暴露端口 8828, 针对该服务定义 ClusterIp 配置如下(不声明 type, 默认即为 ClusterIp),

apiVersion: v1
kind: Service
metadata:
name: my-websocket-svc
namespace: develop
spec:
ports:
- name: socket
port: 8828
targetPort: 8828
protocol: TCP
selector:
app: my-websocket

创建 ClusterIp,

[root@kmaster k8s-deploy]# kubectl apply -f my-websocket-svc.yaml

创建 ConfigMap

在 ingress-nginx-controller 所在的 namespace 下创建 ConfigMap(如果已经有 ConfigMap 了, 则可在已有 ConfigMap 的 data 部分添加下面配置中的 data 条目)

apiVersion: v1
kind: ConfigMap
metadata:
name: tcp-services
namespace: ingress-nginx
data:
8828: "develop/my-websocket-svc:8828"

data 部分的格式为: <namespace/service name>:<service port>:[PROXY]:[PROXY][PROXY]:[PROXY] 部分为可选。 上述配置表示将宿主机的 8828 端口 映射到 develop namespace 下 my-websocket-svc 服务的 8828 端口上。

创建 ConfigMap,

[root@kmaster k8s-deploy]# kubectl apply -f tcp-service-configmap.yaml

配置 ingress-nginx-controller

修改 ingress-nginx-controller 的配置,

[root@kmaster ~]# kubectl edit deploy ingress-nginx-controller -n ingress-nginx

.spec.template.spec.containers[].args[] 部分添加 --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services (或针对 UDP, --udp-services-configmap=$(POD_NAMESPACE)/udp-services), 如下图所示

.spec.template.spec.containers[].ports[] 部分添加 port 映射,如图

经验证,不加该部分 port 映射配置也没问题

保存,应用配置更新,nginx-ingress-controller 将会自动重启 Pod,使配置生效。

验证

在 nginx-ingress-controller Pod 所在节点上执行如下命令查看是否监听了 TCP 端口,

如上,8828 端口已被 nginx-ingress 监听。

对于 Websocket 应用, 可使用 wscat 进行调试

C:\Users\Administrator>wscat -c ws://域名:8828
Connected (press CTRL+C to quit)
>

wscat 安装: npm install -g wscat

其它

  1. 注意 ConfigMap 的 namesapce 与 nginx-ingress-controller 一致,否则将 --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services 中的 $(POD_NAMESPACE) 改为 ConfigMap 具体的 namesapce
  2. 如果将 nginx-ingress-controller 绑定了节点,则重启可能导致失败(因为端口分配冲突),可先删除(kubectl delete deploy ingress-nginx-controller -n ingress-nginx),再新建(kubectl apply -f nginx-ingress.yaml),该操作会影响服务可用性,生产环境需慎重
  3. 如果配置后未生效,可通过查看 nginx-ingress-controller Pod 的日志定位原因 kubectl logs ingress-nginx-controller-58fdbbc68d-wqtlr -n ingress-nginx

参考文档:

  1. https://www.ibm.com/support/knowledgecenter/en/SSSHTQ/omnibus/helms/all_helms/wip/reference/hlm_expose_probe.html
  2. https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/exposing-tcp-udp-services.md

[转载请注明出处]

作者:雨歌

欢迎关注作者公众号:半路雨歌,查看更多技术干货文章

在 Kubernetes Ingress 中支持 Websocket/Socket 服务的更多相关文章

  1. ASP.NET Core 中的 WebSocket 支持(转自MSDN)

    本文介绍 ASP.NET Core 中 WebSocket 的入门方法. WebSocket (RFC 6455) 是一个协议,支持通过 TCP 连接建立持久的双向信道. 它用于从快速实时通信中获益的 ...

  2. 如何在 Knative 中部署 WebSocket 和 gRPC 服务?

    作者 | 冬岛  阿里云容器平台工程师 导读:虽然说 Knative 默认就支持 WebSocket 和 gRPC,但在使用中会发现,有时想要把自己的 WebSocket 或 gRPC 部署到 Kna ...

  3. 把H2数据库从jar包部署到Kubernetes,并解决Ingress不支持TCP的问题

    1 前言 欢迎访问南瓜慢说 www.pkslow.com获取更多精彩文章! H2 Database是一个优秀的数据库,又小又方便,支持内存和文件形式,经常会在测试.POC(proof of conce ...

  4. AutoCAD.net支持后台线程-Socket服务端

    最近因为公司项目的需求,CAD作为服务端在服务器中常驻运行,等待客户端远程发送执行任务的指令,最终确认用Socket-tcp通讯,CAD需要实时监听客户端发送的消息,这时就需要开启线程执行Socket ...

  5. node.js中ws模块创建服务端和客户端,网页WebSocket客户端

    首先下载websocket模块,命令行输入 npm install ws 1.node.js中ws模块创建服务端 // 加载node上websocket模块 ws; var ws = require( ...

  6. Socket.IO介绍:支持WebSocket、用于WEB端的即时通讯的框架

    一.基本介绍 WebSocket是HTML5的一种新通信协议,它实现了浏览器与服务器之间的双向通讯.而Socket.IO是一个完全由JavaScript实现.基于Node.js.支持WebSocket ...

  7. 在python中编写socket服务端模块(二):使用poll或epoll

    在linux上编写socket服务端程序一般可以用select.poll.epoll三种方式,本文主要介绍使用poll和epoll编写socket服务端模块. 使用poll方式的服务器端程序代码: i ...

  8. 在Ngnix中配置支持Websocket

    使用SignalR实现Websocket实时数据传输时,前后端各自实现编码后,无法将Websocket调试通过.沮丧之时,负责配置网络代理的同事说,网络访问这块使用了Ngnix代理设置,可能是造成We ...

  9. Kubernetes中使用ClusterDNS进行服务发现

    在k8s集群中,服务是运行在Pod中的,Pod的发现和副本间负载均衡是我们面临的问题.我们使用Service解决了负载均衡的问题,但是集群环境中,service经常伴随着ip的变动而变动,得益于kub ...

随机推荐

  1. Tomcat配置Gizp 客户端使用okHttp3

    找到tomcat 在 server.xml 新增如下配置 <Connector connectionTimeout="20000" port="8088" ...

  2. C#使用RabbitMq队列(Sample,Work,Fanout,Direct等模式的简单使用)

    1:RabbitMQ是个啥?(专业术语参考自网络) RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件). RabbitMQ服务器是用Erlang语言编写的, ...

  3. 使用leveldb

    C++引入leveldb 编译安装: git clone --recurse-submodules https://github.com/google/leveldb.git cd leveldb m ...

  4. 请求https接口时报错:Caused by SSLError(SSLError(1, u'[SSL: CERTIFICATE_VERIFY_FAILED] certificat,安装certifi

    如何解决SSL 根证书验错误: 一种解决方法是:verify=False 在session.request 里面: session.post(post_url,data=post_data,heade ...

  5. spring boot:用itextpdf处理pdf表格文件(spring boot 2.3.2)

    一,什么是itextpdf? 1,itextpdf的用途 itextpdf是用来生成PDF文档的一个java类库, 通过iText可以生成PDF文档, 还可以把XML/Html文件转化为PDF文件 2 ...

  6. doment ready事件和load事件的区别及实现

    从2017年9月至今工作中大部分使用react,前端渲染的一些基础性知识记忆不是很深刻了.面试**公司的时候,碰到"document ready和load的区别,以及document rea ...

  7. python中实现格式化输入(史上最简单、最高效的实现方法,不借助任何模块)

    今天我在写python作业时突然想到格式化输入一段文字,譬如只需读取输入的前几个字符就行,而不幸的是,python中的输入并没有c中的read().getchar()函数,于是我网上搜了一下,网上的解 ...

  8. linux中root目录下下指定磁盘空间扩容

    1 查看当前磁盘情况 fdisk -l /dev/sda1 2048 6143 2048 83 Linux /dev/sda2 * 6144 1054719 524288 83 Linux /dev/ ...

  9. 我天天curd,怎么才能成长?

    起因 "天天在那curd,也没啥技术含量" "你就是一个curd boy" "你就是一个curder啊" "你不写代码,你只是代码 ...

  10. Redis的一些问题

    date: 2020-10-15 10:58:00 updated: 2020-10-19 18:00:00 Redis的一些问题 Remote Dictionary Server 底层C写的 类似于 ...