能否不使用GKE标准负载均衡器?小型K8s部署成本优化问询
嘿,我太懂你的纠结了——K8s的声明式配置和Pod调度机制确实让人爱不释手,但GKE自带的负载均衡器对小集群来说成本真的有点吃不消,而且换单实例托管或者Swarm又舍不得K8s的生态。给你几个完全基于K8s原生组件的低成本替代方案,完美适配你的3节点小集群场景:
这是最轻量化的方案,不需要额外组件,直接把应用Service的类型设为NodePort。K8s会在每个节点上开放一个静态端口(默认范围30000-32767),你通过任意节点的IP + 这个端口就能访问应用。
配置示例:
apiVersion: v1 kind: Service metadata: name: app1-service spec: type: NodePort selector: app: app1 ports: - protocol: TCP port: 80 # 集群内部访问的端口 targetPort: 8080 # 容器内应用监听的端口 nodePort: 30080 # 可选,指定固定端口,不填的话K8s会随机分配
⚠️ 注意:如果GKE节点被自动替换(比如节点池升级),节点IP会变,你需要手动更新访问地址。如果想解决这个问题,可以给每个节点绑定一个GCP静态IP——3个节点的静态IP成本远低于一个Cloud LB。
先给应用创建默认的ClusterIP服务(仅集群内部可访问),然后在节点上部署Nginx,通过Nginx反向代理到ClusterIP地址。这种方式比NodePort更灵活,还能实现路由、SSL终止等功能。
步骤:
- 给应用创建ClusterIP服务(默认类型,不用改)
- 用DaemonSet部署Nginx(让每个节点都跑一个Nginx实例),或者用Deployment在单个节点跑(节省资源)
- 用ConfigMap挂载Nginx配置,示例如下:
server { listen 80; server_name app1.yourdomain.com; location / { proxy_pass http://app1-service.default.svc.cluster.local:80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } server_name app2.yourdomain.com; location / { proxy_pass http://app2-service.default.svc.cluster.local:80; } }
优势:只需要给一个节点绑定静态IP就能访问所有应用,还能通过Nginx做流量控制、证书管理,比NodePort更贴近生产级配置。
如果你想用域名区分多个应用,又不想用GKE的Cloud LB,可以自己部署nginx-ingress controller,把它的Service类型设为NodePort,完全绕开GCP的负载均衡服务。
安装示例(用Helm最快):
helm install nginx-ingress ingress-nginx/ingress-nginx --set service.type=NodePort
然后创建Ingress资源来路由流量:
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: app-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: rules: - host: app1.yourdomain.com http: paths: - path: / pathType: Prefix backend: service: name: app1-service port: number: 80 - host: app2.yourdomain.com http: paths: - path: / pathType: Prefix backend: service: name: app2-service port: number: 80
这个方案是我最推荐的——既能享受Ingress的域名路由、SSL、路径重写等高级功能,又不用付GKE LB的额外成本,完全保留K8s的声明式配置和调度能力。
如果你的应用允许直接访问Pod(比如一些分布式服务),可以用Headless Service(设置clusterIP: None),然后通过外部DNS把域名解析到所有Pod的IP。不过这个方案适合不需要负载均衡的场景,或者你自己在客户端实现负载均衡,一般小应用用得不多。
内容的提问来源于stack exchange,提问作者interlude

