Google Cloud动态防火墙规则:实现所有Kubernetes节点访问指定实例
解决方案:K8s节点动态访问GCP独立实例(基于公网IP)
我之前也碰到过一模一样的场景——K8s节点随集群伸缩频繁变IP,要访问一个固定公网IP的独立实例,不想硬编码节点IP到防火墙里。结合GCP的IAM和防火墙机制,最可靠的方案是用节点池绑定的服务账号来做访问控制,比标签方案更稳定,毕竟服务账号不会随节点伸缩、重建而变化。
下面是具体落地步骤,顺便帮你排查下之前可能踩的坑:
一、先确认K8s节点的服务账号
GKE的节点本质就是Compute Engine实例,每个节点池都会绑定一个服务账号(默认是default节点服务账号,也可能是你自定义的)。先把这个服务账号找出来:
用命令查看节点池的服务账号:
gcloud container node-pools describe YOUR_NODE_POOL_NAME --cluster YOUR_CLUSTER_NAME --zone YOUR_ZONE | grep serviceAccount
或者直接看单个节点的服务账号:
gcloud compute instances describe YOUR_NODE_NAME --zone YOUR_ZONE | grep serviceAccounts
记下这个服务账号的邮箱(比如xxx-compute@developer.gserviceaccount.com)。
二、配置入站防火墙规则(允许节点访问实例)
先给你的独立实例加个专属标签(比如target-public-instance),这样防火墙规则能精准定位到它。然后创建入站规则,允许来自节点服务账号的流量访问实例的指定端口:
gcloud compute firewall-rules create allow-gke-nodes-to-target \ --direction=INGRESS \ --target-tags=target-public-instance \ --source-service-accounts=YOUR_NODE_SERVICE_ACCOUNT_EMAIL \ --allow=tcp:YOUR_TARGET_PORT # 替换成实例提供服务的端口,比如80、8080 --description="Allow GKE nodes (via service account) to access target public instance"
这个规则的核心是用服务账号作为身份标识,不管节点怎么扩容缩容,只要节点用这个服务账号,就能被允许访问,完全不依赖节点IP。
三、验证出站规则(确保节点能发流量出去)
默认GCP VPC的出站规则是允许所有流量的,但如果你的集群配置了严格的出站防火墙,需要补充一条出站规则,允许节点访问实例的公网IP:
gcloud compute firewall-rules create allow-gke-nodes-outbound-to-target \ --direction=EGRESS \ --source-tags=YOUR_GKE_NODE_TAG # 节点的标签,比如默认是gke-集群名-节点池名-node --destination-ranges=TARGET_INSTANCE_PUBLIC_IP/32 \ --allow=tcp:YOUR_TARGET_PORT --description="Allow GKE nodes outbound to target instance public IP"
节点标签可以用这个命令查看:
gcloud compute instances list --zone YOUR_ZONE --format="value(tags.items)"
四、测试访问
找一个K8s节点登录进去,直接curl实例的公网IP+端口验证:
gcloud compute ssh YOUR_NODE_NAME --zone YOUR_ZONE curl TARGET_INSTANCE_PUBLIC_IP:YOUR_TARGET_PORT
为什么之前标签方案没成功?
大概率是这两个细节没做好:
- 标签加错了对象:你可能把标签加到了K8s Pod上,而防火墙规则识别的是Compute Engine节点实例的标签,不是K8s Pod的标签。
- 规则方向搞反:入站规则的目标应该是独立实例的标签,来源是节点的标签,而不是反过来。
用服务账号的方案比标签更靠谱,因为服务账号是节点池的固定属性,不会因为节点重建、伸缩而变化,完美匹配动态访问的需求。
内容的提问来源于stack exchange,提问作者Ulukai




