如何通过 kubernetes ingress 或者 istio ingressgateway 来暴露 TCP 的服务
点击上方“程序猿技术大咖”,关注并选择“设为星标”
回复“加群”获取入群讨论资格!
在 kubernetes 或 istio 应用中,一般都是通过 kubernetes ingress 或者 istio ingressgateway 来暴露 HTTP/HTTPS 的服务。但是在实际应用中,还是有不少应用是TCP长连接的,这个是否也是可以通过 ingress 来暴露呢?
本文将讲述如何通过 kubernetes ingress 或者 istio ingressgateway 来暴露 TCP 的服务。
1、部署示例服务
-
1. 部署一个 tcp-echo 服务, 用于验证通过 kubernetes ingress 或 istio ingressgateway 来访问 tcp 服务。
执行命令
kubectl apply -f tcp-echo.yaml
部署 tcp-echo 服务:# tcp-echo.yaml apiVersion: v1 kind: Service metadata:name: tcp-echolabels:app: tcp-echoservice: tcp-echo spec:ports:- name: tcpport: 9000- name: tcp-otherport: 9001# Port 9002 is omitted intentionally for testing the pass through filter chain.selector:app: tcp-echo --- apiVersion: apps/v1 kind: Deployment metadata:name: tcp-echo spec:replicas: 1selector:matchLabels:app: tcp-echoversion: v1template:metadata:labels:app: tcp-echoversion: v1spec:containers:- name: tcp-echoimage: docker.io/istio/tcp-echo-server:1.2imagePullPolicy: IfNotPresentargs: [ "9000,9001,9002", "hello" ]ports:- containerPort: 9000- containerPort: 9001
-
2. 部署一个 sleep 服务,作为发送请求的测试客户端。
执行命令
kubectl apply -f sleep.yaml
部署 sleep 服务:# sleep.yaml apiVersion: v1 kind: Service metadata:name: sleeplabels:app: sleepservice: sleep spec:ports:- port: 80name: httpselector:app: sleep --- apiVersion: apps/v1 kind: Deployment metadata:name: sleep spec:replicas: 1selector:matchLabels:app: sleeptemplate:metadata:labels:app: sleepspec:terminationGracePeriodSeconds: 0containers:- name: sleepimage: curlimages/curlcommand: ["/bin/sleep", "3650d"]imagePullPolicy: IfNotPresentvolumeMounts:- mountPath: /etc/sleep/tlsname: secret-volumevolumes:- name: secret-volumesecret:secretName: sleep-secretoptional: true
-
3. 部署成功后,发送一些TCP流量来确认 tcp-echo 服务已启动且正在运行。
# 获取 sleep 的 pod名称 $ kubectl get pods -l app=sleepNAME READY STATUS RESTARTS AGEsleep-557747455f-gwt2j 2/2 Running 4 2d4h # 进入 sleep 容器内,使用 nc 命令向 tcp-echo 服务发送tcp请求 $ kubectl exec -it sleep-557747455f-gwt2j -c sleep sh / $ nc -v tcp-echo 9000 tcp-echo (10.96.141.51:9000) open xcbeyond hello xcbeyond
2、kubernetes ingress tcp
2.1 原理
Kubernetes Ingress Controller 在启动时会去watch两个configmap(一个tcp,一个 udp),里面记录了后面需要反向代理的TCP的服务以及暴露的端口。如果里面的key-value发生变换,Ingress controller 会去更改 Nginx 的配置,增加对应的 TCP 的 listen 的 server 以及对应的后端的 upstream。
2.2 最佳实践
前提条件:
-
已安装 ingress controller。
如果未安装,可以参考执行命令
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.7.0/deploy/static/provider/cloud/deploy.yaml
,完成安装。
-
1. kubernetes ingress controller 中增加需要 watch 的 configmap。
通过命令
kubectl edit -n ingress-nginx deployment ingress-nginx-controller
,在 ingress-nginx-controller 中新增参数 tcp-services-configmap、udp-services-configmap,如下图所示: -
2. 创建对应的 configmap。
暂时不需要配置服务。 对于已经默认创建好了对应的configmap: tcp-services, udp-services,无需再创建。
1)执行命令
kubectl apply -f tcp-services-cm.yaml
,tcp-services-cm.yaml 文件内容如下:# tcp-services-cm.yaml apiVersion: v1 kind: ConfigMap metadata:name: tcp-servicesnamespace: ingress-nginx
2)执行命令
kubectl apply -f udp-services-cm.yaml
,udp-services-cm.yaml 文件内容如下:# udp-services-cm.yaml apiVersion: v1 kind: ConfigMap metadata:name: udp-servicesnamespace: ingress-nginx
-
3. tcp-services configmap 中配置 TCP 服务的端口。
执行命令
kubectl edit -n ingress-nginx cm tcp-services
, 在 data 部分新增暴露的TCP端口,格式为<Nginx port>: <namespace/service name>:<service port>:[PROXY]:[PROXY]
,如下图所示:图例中,是将
default/tcp-echo:9000
服务暴露到 nginx ingress 的 9000 端口。 -
4. Ingress Controller service 对外暴露 TCP 端口。
因为 TCP 服务是需要通过端口来区分服务的,所以每个服务都需要增加一个独立端口,因此,需要给 Ingress Controller 增加新的端口来映射后端的TCP服务。
执行命令
kubectl edit -n ingress-nginx svc ingress-nginx-controller
,如下图所示: -
5. 通过 kubernetes ingress 访问 TCP 服务。
直接通过 Ingress Controller service 暴露的 TCP 端口(nodePort)进行访问即可。
借助命令
nc -v <ip> <port>
完成验证。
3、istio ingressgateway tcp
前提条件:
-
tcp-echo 服务已注入边车。
-
istio 中已部署 isito-ingressgateway 服务。
本示例中,借助 isito-ingressgateway 中默认已开启的 31400 tcp 端口,完成验证。在实际业务功能中,可单独向 isito-ingressgateway 新增多组 tcp 端口(即:在 isito-ingressgateway 的 service 中,新增 tcp 协议端口)。
-
1. 定义 istio gateway。
执行命令
kubectl apply -f tcp-echo-gateway.yaml
创建服务 tcp-echo 的 gateway:# tcp-echo-gateway.yaml apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata:name: tcp-echo-gateway spec:selector:istio: ingressgateway # use istio default controllerservers:- port:number: 31400 # istio-ingressgateway tcp portname: tcpprotocol: TCPhosts:- "*"
-
2. 定义 virtualService。
执行命令
kubectl apply -f tcp-echo-vs.yaml
创建服务 tcp-echo 的 virtualService:apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata:name: tcp-echo-vs spec:hosts:- "*"gateways:- tcp-echo-gatewaytcp:- match:- port: 31400 # istio-ingressgateway tcp portroute:- destination:host: tcp-echo # tcp-echo serviceport:number: 9000
-
3. 通过 istio ingressgateway 访问 TCP 服务。
直接通过 istio-ingressgateway service 暴露的 TCP 端口(nodePort)进行访问即可。
借助命令
nc -v <ip> <port>
完成验证。
参考文章:
-
https://kubernetes.github.io/ingress-nginx/user-guide/exposing-tcp-udp-services
感谢您的阅读,也欢迎您发表关于这篇文章的任何建议,关注我,技术不迷茫!
-
Kubernetes安装篇(三):基于kind快速部署本地多套K8S集群
-
图解 Kubernetes Deployment 故障排查 | 推荐长期收藏
-
全方位解读服务网格(Service Mesh)的背景和概念
-
微服务架构下的核心话题 (三):微服务架构的技术选型
喜欢就点个"在看"呗,留言、转发朋友圈