nginx配置websocket_在 Kubernetes Ingress 中支持 Websocket/Socket 服务

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), 如下图所示

03e7009e1f53e8b3d6dfc4f7a4814d68.png

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

44f33512d4f90c4f2326c39ad01389ee.png

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

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

验证

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

f33fa7f0e5d8d6e2126fd0e0f5eacb6d.png

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

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

C:UsersAdministrator>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

[转载请注明出处] 作者:雨歌 欢迎关注作者公众号:半路雨歌,查看更多技术干货文章

http://weixin.qq.com/r/fDufh-7E-qOBrbrk925u (二维码自动识别)

### 如何在 Nginx配置 WebSocket 支持 #### 配置最佳实践 对于希望利用 WebSocket 提供更高效的数据交换机制的应用来说,在 Nginx 中正确配置 WebSocket 是至关重要的。通过适当调整 Nginx 设置,可以确保 WebSocket 连接被正确识别并转发至目标应用服务器。 为了使 Nginx 正确处理 WebSocket 请求,需特别注意 HTTP 头部 `Connection` 和 `Upgrade` 的设置[^4]。这两个字段告知中间件(如 Nginx)以及最终的服务端程序当前请求意图从标准 HTTP/HTTPS 切换到 WebSocket 协议。 #### 配置示例 下面提供了一个典型的 Nginx 配置片段用于启用对 WebSocket支持: ```nginx server { listen 80; server_name example.com; location /ws/ { proxy_pass http://backend_server; # 后端实际运行WebSocket服务的位置 # 下面两个指令是为了让Nginx能够理解这是一个WebSocket连接 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # 可选:保持长链接不因超时断开 proxy_read_timeout 86400s; } } ``` 此配置中 `/ws/` 表示 WebSocket 接口路径前缀;`proxy_pass` 指令指向后端 WebSocket 服务地址;而 `proxy_http_version`, `proxy_set_header Upgrade` 和 `proxy_set_header Connection` 确保了 WebSocket 握手过程得以顺利成。 另外,当涉及到 Kubernetes 或其他容器编排平台上的部署时,可以通过为 Ingress 添加特定注解来简化 WebSocket 流量管理。例如,使用 NGINX Ingress Controller 时可通过如下方式指定哪些服务应被视为 WebSocket 类型: ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: websocket-ingress annotations: nginx.org/websocket-services: "my-websocket-service" spec: rules: - host: example.com http: paths: - pathType: Prefix path: "/ws/" backend: service: name: my-backend-service port: number: 8080 ``` 上述 YAML 文件展示了如何标记名为 `my-websocket-service` 的服务作为 WebSocket 服务,并将其流量路由至对应的后端服务上[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值