如何在EKS中通过单个LB暴露多TCP服务与HTTPS(支持IP限制)
Amazon EKS 单NLB多端口暴露方案指南与问题解答
1. 能否在EKS中用单个NLB同时暴露HTTPS与多TCP端口?
可以。AWS NLB原生支持在同一负载均衡器上配置多个监听端口(涵盖TCP、TLS协议),结合AWS Load Balancer Controller或NGINX Ingress的stream模块均可实现。同时可通过注解给NLB绑定弹性IP,获得静态IP地址,满足客户端白名单配置需求。
2. 两种方案哪种更适配此场景?
方案1:单/多LoadBalancer Service + AWS LB控制器
- 优势:流量从NLB直接转发到后端服务,减少NGINX中转的性能损耗;转发规则由AWS LB控制器管理,架构更轻量化;适合对延迟敏感的TCP服务。
- 劣势:无法通过域名映射区分TCP服务(TCP基于端口转发,NLB不解析域名);IP白名单配置依赖NLB监听规则或后端Security Group,灵活性有限。
方案2:NGINX Ingress Controller stream模块转发TCP流量
- 优势:可通过NGINX的stream配置实现TCP流量的域名映射(需结合SNI,建议TCP服务启用TLS);IP白名单可在NGINX层面精细控制;所有流量统一由NGINX管理,配置更集中。
- 劣势:多了一层NGINX转发,存在轻微性能损耗;需要维护额外的ConfigMap配置,复杂度稍高。
适配建议:如果需要给TCP服务配置域名映射,或者需要灵活的IP白名单规则,选方案2;如果追求极致性能、简化架构,且TCP服务仅通过端口访问,选方案1。
3. 两种方案是否均支持按服务配置IP白名单?
- 方案1:支持。两种实现方式:
- 给对应Service添加
service.beta.kubernetes.io/aws-load-balancer-source-ranges注解,配置该端口的源IP白名单; - 在后端服务的Pod Security Group中配置入站规则,限制仅特定IP可访问服务端口。
- 给对应Service添加
- 方案2:支持。在NGINX的
stream-snippet中给每个TCP服务添加allow/deny规则,实现精细的IP访问控制。
4. TCP服务能否实现域名映射(如redis.mydomain.com),还是仅HTTPS支持?
- 纯明文TCP协议不携带域名信息,方案1(直接NLB转发)无法实现域名映射,只能通过端口区分服务。
- 方案2(NGINX stream模块)可以实现:
- 如果TCP服务启用了TLS,可利用SNI(Server Name Indication),NGINX通过解析客户端请求中的SNI域名,将流量转发到对应服务;
- 明文TCP无法直接识别域名,实用性较低,不建议采用。
示例配置
方案1:多Service共享同一NLB示例
1. NGINX Ingress Service(绑定NLB与弹性IP)
apiVersion: v1 kind: Service metadata: name: nginx-ingress-nlb annotations: # 指定为NLB service.beta.kubernetes.io/aws-load-balancer-type: "external" service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip" # 绑定弹性IP,多个EIP用逗号分隔 service.beta.kubernetes.io/aws-load-balancer-eip-allocations: "eip-xxxxxx,eip-yyyyyy" # 允许其他Service共享此NLB service.beta.kubernetes.io/aws-load-balancer-shared: "true" spec: type: LoadBalancer ports: - name: http port: 80 targetPort: 80 protocol: TCP - name: https port: 443 targetPort: 443 protocol: TCP selector: app: nginx-ingress-controller
2. Redis Service(共享NLB并配置IP白名单)
apiVersion: v1 kind: Service metadata: name: redis-nlb-service annotations: service.beta.kubernetes.io/aws-load-balancer-type: "external" service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip" # 指定共享的NLB名称(从NGINX Service的NLB详情中获取) service.beta.kubernetes.io/aws-load-balancer-name: "nginx-ingress-nlb-xxxxxx" # 配置Redis的IP白名单 service.beta.kubernetes.io/aws-load-balancer-source-ranges: "192.168.1.0/24" spec: type: LoadBalancer ports: - name: redis port: 6379 targetPort: 6379 protocol: TCP selector: app: redis
方案2:NGINX Ingress Stream模块示例
1. 启用NGINX Stream模块(修改Ingress Controller Deployment)
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-ingress-controller namespace: kube-system spec: template: spec: containers: - name: nginx-ingress-controller args: - /nginx-ingress-controller - --enable-stream - --configmap=$(POD_NAMESPACE)/nginx-configuration - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - --ingress-class=nginx # 其他默认参数...
2. 配置TCP服务映射ConfigMap
apiVersion: v1 kind: ConfigMap metadata: name: tcp-services namespace: kube-system data: # 格式:外部端口: 命名空间/服务名称:服务端口 6379: "default/redis-service:6379" 27017: "default/mongo-service:27017" 3306: "default/mysql-service:3306"
3. 更新NGINX Ingress Service(添加TCP端口)
apiVersion: v1 kind: Service metadata: name: nginx-ingress-nlb namespace: kube-system annotations: service.beta.kubernetes.io/aws-load-balancer-type: "external" service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip" service.beta.kubernetes.io/aws-load-balancer-eip-allocations: "eip-xxxxxx,eip-yyyyyy" spec: type: LoadBalancer ports: - name: http port: 80 targetPort: 80 protocol: TCP - name: https port: 443 targetPort: 443 protocol: TCP - name: redis port: 6379 targetPort: 6379 protocol: TCP - name: mongo port: 27017 targetPort: 27017 protocol: TCP - name: mysql port: 3306 targetPort: 3306 protocol: TCP selector: app: nginx-ingress-controller
4. 配置TCP服务IP白名单
apiVersion: v1 kind: ConfigMap metadata: name: nginx-configuration namespace: kube-system data: stream-snippet: | # Redis IP白名单配置 server { listen 6379; allow 192.168.1.0/24; deny all; proxy_pass redis-service.default.svc.cluster.local:6379; } # MongoDB IP白名单配置 server { listen 27017; allow 10.0.0.0/8; deny all; proxy_pass mongo-service.default.svc.cluster.local:27017; }
5. TCP服务域名映射(基于SNI,需启用TLS)
apiVersion: v1 kind: ConfigMap metadata: name: nginx-configuration namespace: kube-system data: stream-snippet: | # 根据SNI域名映射到对应服务 map $ssl_preread_server_name $target_service { redis.mydomain.com redis-service.default.svc.cluster.local:6379; mongo.mydomain.com mongo-service.default.svc.cluster.local:27017; } # TLS监听端口,处理带SNI的TCP请求 server { listen 6443 ssl; # 引用你的TLS证书(需提前在K8s中创建Secret) ssl_certificate /etc/nginx/secrets/tls-secret/tls.crt; ssl_certificate_key /etc/nginx/secrets/tls-secret/tls.key; # 启用SNI预读取 ssl_preread on; proxy_pass $target_service; }
内容的提问来源于stack exchange,提问作者kingfateh khan
相关产品推荐
相关产品推荐

