文章目录
背景
公司业务繁多, HTTP、GRPC、TCP多种协议服务并存,Kubernetes流量入口复杂,所以萌生了通过LoadBalancer + Ingress-nginx 的方式完全的结果入口流量,当然在高并发的场景下可以对LoadBalancer 和Ingress-nginx 进行拆分管理。
HTTP以及GRPC在Ingress上的使用就不过多说明了。 主要验证下ingres-nginx对TCP流量的转发,以及简单窥探下实现逻辑。
搞起
首先先准备好内部TCP环境, 这里使用mysql作为测试服务,使用如下命令对服务进行部署。
bash
cat > mysql.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-master
labels:
name: mysql-master
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: mysql-master
name: mysql-master
template:
metadata:
labels:
app: mysql-master
name: mysql-master
spec:
containers:
- name: mysql-master
image: mysql:9
imagePullPolicy: Always
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
---
kind: Service
apiVersion: v1
metadata:
name: mysql
namespace: default
spec:
type: ClusterIP
clusterIP: None
ports:
- name: mysql
port: 3306
selector:
name: mysql-master
---
# 创建ingress tcp转发用到的configmap
apiVersion: v1
kind: ConfigMap
metadata:
name: tcp-services
namespace: ingress-nginx
data:
9000: "default/mysql:3306"
EOF
kubectl apply -f mysql.yaml
ingress对于TCP与UDP的转发通过增加--tcp-services-configmap
和--udp-services-configmap
参数配置,用于指定配置保存的configmap。
configmap 格式如下:
<external port>:<namespace/service name>:<service port/name>:[PROXY]:[PROXY]
- external port:表示ingress对外暴露的端口,需要在ingress service进行添加。 下一步添加。
- <namespace/service name>:service 所在的namespace及名称。
- <service port/name>:service的名称或端口。
- [PROXY]:[PROXY]:TCP 服务中使用代理协议解码 (listen) 和/或编码 (proxy_pass)。第一个PROXY控制代理协议的解码,第二个PROXY控制使用代理协议的编码。(可选)
拓展( PROXY Protocol )
什么是 PROXY Protocol ? 其实很简单,就是为了解决多层NET或TCP转发时 无法获取客户端真实IP的问题,在 TCP 第一行加入了一些信息标识协议、客户端地址、转发地址以及端口等。目前有 v1 和 v2 两个版本。
开源版本支持:
- HTTP 的 PROXY 协议:NGINX Open Source 1.5.12及更高版本
- TCP 客户端 PROXY 协议:NGINX Open Source 1.9.3及更高版本
- 接受 TCP 的 PROXY 协议:NGINX Open Source 1.11.4及更高版本
- PROXY 协议 v2:NGINX Open Source 1.13.11及更高版本
NGINX Open Source 默认不包含HTTP和Stream TCP的 Real-IP 模块;
一般获取客户端真实IP有以下2种方案:
HTTP:
- 使用 X-Forwarded-For(XFF)头
- Proxy Protocol + X-Forwarded-For
TCP:
- Proxy Protocol + nginx日志分析
- 基于网络层信息获取(toa)
然后接着说, 需要对ingress-nginx service 开启相应的端口转发,增加如下配置。
bash
- name: proxied-tcp-9000
port: 9000
targetPort: 9000
protocol: TCP
最后,修改ingress-nginx deployment , 在启动参数中加入如下配置,用来更新nginx 关于TCP/UDP的转发配置。
bash
args:
- /nginx-ingress-controller
- --tcp-services-configmap=ingress-nginx/tcp-services
完结~撒花🎉~~
参考
nginx-ingress 服务架构图
根据配置的信息自动加载后端IP、Port (https://github.com/kubernetes/ingress-nginx/blob/main/rootfs/etc/nginx/lua/tcp_udp_balancer.lua)