如何为GKE LoadBalancer自动配置域名以替代IP访问?
我完全理解你的痛点——用裸IP访问不仅没法设置Cookie(浏览器对Cookie的domain属性有严格要求,IP不满足),而且GKE的LoadBalancer默认是动态IP,重启服务后IP还会变,必须绑定域名才能稳定访问。之前尝试反向DNS解析没用是因为反向DNS是IP指向域名,而我们需要的是域名指向IP的正向解析,所以得换个思路。
下面是两种可行的自动化方案,结合你的Node.js部署脚本和GKE环境:
方案1:GKE Ingress + Cloud DNS(推荐,支持HTTPS和统一路由)
Ingress是Kubernetes中统一管理外部流量的组件,能帮你实现子域名或路径路由,还能自动配置HTTPS证书。步骤如下:
1. 提前准备Cloud DNS托管区域
确保你已经在GCP Cloud DNS中创建了mysite.com的托管区域,并且域名的NS记录已经指向Cloud DNS的服务器(这一步是域名解析的基础)。
2. 修改部署流程:用ClusterIP Service替代直接LoadBalancer
把原来创建LoadBalancer Service的逻辑改成创建ClusterIP类型的Service(只在集群内部访问),然后通过Ingress暴露外部流量。这样能节省LoadBalancer资源,也方便统一管理路由。
修改后的Service清单示例:
{ "kind": "Service", "apiVersion": "v1", "metadata": { "name": "backend-__ID__" }, "spec": { "selector": { "app": "backend-__ID__" }, "type": "ClusterIP", // 改为ClusterIP "ports": [ { "name": "app1", "protocol": "TCP", "port": 8080, "targetPort": "8080" }, { "name": "app2", "protocol": "TCP", "port": 3010, "targetPort": "3010" } ] } }
3. 创建Ingress资源并绑定域名
编写Ingress清单,配置子域名(比如app-__ID__.mysite.com)或路径路由(比如mysite.com/app-__ID__),并绑定静态公网IP(避免IP变动)。
Ingress清单示例(子域名路由):
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: app-__ID__-ingress annotations: # 绑定提前预留的静态公网IP(需要先在GCP VPC中创建静态IP) kubernetes.io/ingress.global-static-ip-name: "gke-ingress-static-ip" # 可选:自动申请HTTPS证书(GKE Managed Certificates) networking.gke.io/managed-certificates: "app-__ID__-cert" spec: rules: - host: app-__ID__.mysite.com http: paths: - path: / pathType: Prefix backend: service: name: backend-__ID__ port: number: 8080
如果用路径路由(比如mysite.com/appx),只需修改Ingress的host和path:
spec: rules: - host: mysite.com http: paths: - path: /app-__ID__ pathType: Prefix backend: service: name: backend-__ID__ port: number: 8080
4. 自动化配置Cloud DNS记录
在你的Node.js脚本中,当Ingress创建完成后,获取它的公网IP,然后调用Cloud DNS API创建对应的A记录。
示例Node.js代码(用@google-cloud/dns库):
const { DNS } = require('@google-cloud/dns'); const dnsClient = new DNS({ projectId: '你的GCP项目ID' }); const zone = dnsClient.zone('mysite-com'); // 你的Cloud DNS区域名称(不带点) // 你的原有部署逻辑 const projects = get_all_projects_today(); for (const project of projects) { const projectId = project.id; deploy_to_GKE(project); create_clusterip_service_on_GKE(project); // 创建Ingress并获取IP const ingressIp = create_ingress_on_GKE(project, `app-${projectId}.mysite.com`); // 创建Cloud DNS A记录 const record = zone.record('A', { name: `app-${projectId}.mysite.com.`, // 注意末尾必须加英文点 data: ingressIp, ttl: 300, // 5分钟TTL,适合动态更新 }); // 提交DNS记录 await zone.addRecords(record); console.log(`域名 app-${projectId}.mysite.com 已绑定IP ${ingressIp}`); }
5. 可选:配置HTTPS证书
创建Managed Certificate资源,GKE会自动向Let's Encrypt申请免费证书并绑定到Ingress:
apiVersion: networking.gke.io/v1 kind: ManagedCertificate metadata: name: app-__ID__-cert spec: domains: - app-__ID__.mysite.com
方案2:直接给LoadBalancer Service绑定静态IP+Cloud DNS
如果你不想修改Service类型,依然想用LoadBalancer,可以通过绑定静态IP+自动配置DNS来实现:
1. 预留静态公网IP
在GCP VPC中为每个项目预留静态公网IP(或提前批量创建),避免Service重启后IP变动。
2. 修改Service清单绑定静态IP
在Service的metadata.annotations中添加静态IP的绑定:
{ "kind": "Service", "apiVersion": "v1", "metadata": { "name": "backend-__ID__", "annotations": { "service.beta.kubernetes.io/google-load-balancer-ip": "你的静态IP地址" } }, "spec": { // 原有配置不变 } }
3. 自动化配置DNS记录
和方案1类似,在脚本中获取Service的公网IP(这里是你预留的静态IP),然后调用Cloud DNS API创建A记录即可。
关键注意事项
- 权限配置:确保你的部署脚本使用的服务账号拥有
roles/dns.recordSetEditor(DNS记录编辑权限)和roles/container.developer(GKE部署权限)。 - 静态IP类型:GKE Ingress需要使用全局静态IP,而LoadBalancer Service可以用区域静态IP,注意区分。
- DNS生效时间:DNS记录更新后需要等待TTL时间生效,脚本中可以添加验证逻辑(比如用
dns.resolve检查解析结果)。
内容的提问来源于stack exchange,提问作者hamzawi

