如何配置Cloud Run中的Kubernetes客户端连接GKE集群?
配置Cloud Run中的Kubernetes客户端连接GKE集群
问题背景
本地运行的Java代码可正常在GKE集群创建Job,但部署到Cloud Run后触发UnknownHostException: kubernetes.default.svc: Name or service not known错误。这是因为Cloud Run不属于Kubernetes集群内部环境,无法访问集群内部DNS,也没有挂载集群内的ServiceAccount凭证文件。
解决方案
1. 为Cloud Run绑定具备GKE操作权限的ServiceAccount
- 创建或选择一个Cloud IAM服务账号(ServiceAccount),授予其GKE资源操作权限,比如
roles/container.developer(或更细粒度的权限,如roles/batch.jobsCreator)。 - 部署Cloud Run服务时指定该ServiceAccount:
gcloud run deploy [你的Cloud Run服务名] \ --image southamerica-east1-docker.pkg.dev/kubernetes-hello-world-360615/hello-repo/cloud-run:v1 \ --service-account [服务账号邮箱,如xxx@your-project.iam.gserviceaccount.com]
2. 修改Java代码配置Kubernetes客户端
Cloud Run无法自动获取Kubernetes集群配置,需要手动指定GKE集群的外部API端点,并使用Google Cloud的应用默认凭证进行身份验证:
- 先获取GKE集群的API端点:
gcloud container clusters describe [你的GKE集群名] \ --zone [集群所在区域,如southamerica-east1-a] \ --format="value(endpoint)" - 修改Java代码,配置客户端连接参数:
import com.google.auth.oauth2.GoogleCredentials; import io.fabric8.kubernetes.client.ConfigBuilder; import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.kubernetes.client.KubernetesClientBuilder; import java.io.IOException; import java.util.Collections; import io.fabric8.kubernetes.api.model.batch.Job; import io.fabric8.kubernetes.api.model.batch.JobBuilder; import io.fabric8.kubernetes.api.model.PodList; import io.fabric8.kubernetes.client.KubernetesClientException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Main { private static final Logger logger = LoggerFactory.getLogger(Main.class); public static void main(String[] args) { try { // 获取Google应用默认凭证(由Cloud Run绑定的ServiceAccount提供) GoogleCredentials credentials = GoogleCredentials.getApplicationDefault(); String authToken = credentials.refreshAccessToken().getTokenValue(); // 替换为你的GKE集群API端点 String clusterEndpoint = "https://[你的GKE集群端点]"; ConfigBuilder configBuilder = new ConfigBuilder() .withMasterUrl(clusterEndpoint) .withOauthToken(authToken) .withTrustCerts(true); // GKE的公网端点可信任默认证书 try (KubernetesClient client = new KubernetesClientBuilder().withConfig(configBuilder.build()).build()) { // 原有的Job创建及日志获取逻辑保持不变 final String namespace = "default"; final Job job = new JobBuilder() .withApiVersion("batch/v1") .withNewMetadata() .withName("pi") .withLabels(Collections.singletonMap("label1", "maximum-length-of-63-characters")) .withAnnotations(Collections.singletonMap("annotation1", "some-very-long-annotation")) .endMetadata() .withNewSpec() .withNewTemplate() .withNewSpec() .addNewContainer() .withName("pi") .withImage("perl:5.34.0") .withArgs("perl", "-Mbignum=bpi", "-wle", "print bpi(2000)") .endContainer() .withRestartPolicy("Never") .endSpec() .endTemplate() .endSpec() .build(); logger.info("Creating job pi."); client.batch().v1().jobs().inNamespace(namespace).createOrReplace(job); PodList podList = client.pods().inNamespace(namespace).withLabel("job-name", job.getMetadata().getName()).list(); String joblog = client.batch().v1().jobs().inNamespace(namespace).withName("pi").getLog(); logger.info(joblog); } catch (KubernetesClientException e) { logger.error("Unable to create job", e); } } catch (IOException e) { logger.error("Failed to get Google credentials", e); } } } - 添加Google Auth依赖到Maven/POM文件:
<dependency> <groupId>com.google.auth</groupId> <artifactId>google-auth-library-oauth2-http</artifactId> <version>1.19.0</version> </dependency>
3. 验证网络与权限
- 如果GKE集群使用私有端点,需要配置Cloud Run的VPC连接器,让服务可以访问GKE所在的VPC网络;如果是公网端点,确保集群控制平面允许公网访问(默认GKE公网端点允许所有IP,可按需限制)。
- 确认ServiceAccount权限生效:通过以下命令验证权限绑定:
gcloud projects get-iam-policy [你的项目ID] \ --filter="bindings.members:serviceAccount:[你的服务账号邮箱]" \ --format="value(bindings.role)"
内容的提问来源于stack exchange,提问作者carlos palma
相关产品推荐
相关产品推荐

