问题
在Kuberetes应用中,一般都是通过Ingress来暴露HTTP/HTTPS的服务。但是在实际应用中,还是有不少应用是TCP长连接的,这个是否也是可以通过Ingress来暴露呢?大家知道Kubernetes社区默认带了一个Nginx的Ingress的,而它本身又是支持TCP做反向代理的。所以也就能支持TCP方式的Ingress的。
具体可以参考:
https://kubernetes.github.io/ingress-nginx/user-guide/exposing-tcp-udp-services/
原理
Ingress Controller在启动时会去watch两个configmap(一个tcp,一个 udp),里面记录了后面需要反向代理的TCP的服务以及暴露的端口。如果里面的key-value发生变换,Ingress controller会去更改Nginx的配置,增加对应的TCP的listen的server以及对应的后端的upstream。
实践
配置Nginx的Ingress-controller的deployment/daemonSet
- 增加Ingress controller需要watch的configmap
- '--tcp-services-configmap=$(POD_NAMESPACE)/tcp-services'
- '--udp-services-configmap=$(POD_NAMESPACE)/udp-services'
- 创建对应的configmap,暂时不需要配置服务。
TCP configmap
apiVersion: v1
kind: ConfigMap
metadata:
name: tcp-services
namespace: vic-uat
UDP configmap
apiVersion: v1
kind: ConfigMap
metadata:
name: udp-services
namespace: vic-uat
创建一个TCP服务(Redis)
模拟redis部署在k8s里,需要对外访问,如何创建这个deployment, service这个就不啰嗦了。
- 给TCP的服务配置"Ingress" TCP服务不像HTTP,不能使用Kubernetes的Ingress对象来配置,而是使用修改对应的Configmap来增加一个"Ingress"
kubectl edit configmap/tcp-services -n
- 然后增加data部分:
格式为:
<Nginx port>: <namespace/service name>:<service port>:[PROXY]:[PROXY]
data:
'6379': 'vic-uat/iot-redis:6379'
例子中将vic-uat/redis这个服务暴露到6379端口
修改Ingress Controller的Service
因为TCP部分是需要通过端口来区分服务的,所以每个服务都需要增加一个独立端口,所以需要给Ingress Controller增加新的端口来映射后端的TCP服务
- name: redis
nodePort: 31774
port: 6379
protocol: TCP
targetPort: 6379
注意:在阿里云的Kubernetes服务创建的集群,可以不用指定nodeport,对应的cloud provider会自动到对应的SLB上创建端口映射如:
ingress里添加域名
spec:
ingressClassName: nginx
rules:
- host: testredis.com
http:
paths:
- backend:
service:
name: iot-redis
port:
number: 6379
path: /
这样就完成了一个TCP的“Ingress”的创建了。
访问TCP服务
直接访问域名的6379端口就可以。如果没有域名可以直接访问SLB也可以。