从远程机器获取 GCP Bigquery 拒绝连接

问题描述

我正在运行来自 google 的示例代码获取简单的选择查询。这在我的本地工作正常,但在我的 k8s 环境中,我收到以下错误

Exception in thread "main" com.google.cloud.bigquery.BigQueryException: Error getting access token for service account: connect timed out
    at com.google.cloud.bigquery.spi.v2.HttpBigQueryRpc.translate(HttpBigQueryRpc.java:115)
    at com.google.cloud.bigquery.spi.v2.HttpBigQueryRpc.create(HttpBigQueryRpc.java:220)
    at com.google.cloud.bigquery.BigQueryImpl$5.call(BigQueryImpl.java:369)
    at com.google.cloud.bigquery.BigQueryImpl$5.call(BigQueryImpl.java:366)
    at com.google.api.gax.retrying.DirectretryingExecutor.submit(DirectretryingExecutor.java:105)
    at com.google.cloud.RetryHelper.run(RetryHelper.java:76)
    at com.google.cloud.RetryHelper.runWithRetries(RetryHelper.java:50)
    at com.google.cloud.bigquery.BigQueryImpl.create(BigQueryImpl.java:365)
    at com.google.cloud.bigquery.BigQueryImpl.create(BigQueryImpl.java:340)
    at com.rakuten.dps.dataplatform.ingest.utility.BQ_test.main(BQ_test.java:67)
Caused by: java.io.IOException: Error getting access token for service account: connect timed out
    at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccesstoken(ServiceAccountCredentials.java:444)
    at com.google.auth.oauth2.OAuth2Credentials.refresh(OAuth2Credentials.java:157)
    at com.google.auth.oauth2.OAuth2Credentials.getRequestMetadata(OAuth2Credentials.java:145)
    at com.google.auth.oauth2.ServiceAccountCredentials.getRequestMetadata(ServiceAccountCredentials.java:603)
    at com.google.auth.http.HttpCredentialsAdapter.initialize(HttpCredentialsAdapter.java:91)
    at com.google.cloud.http.HttpTransportOptions$1.initialize(HttpTransportOptions.java:159)
    at com.google.api.client.http.HttpRequestFactory.buildrequest(HttpRequestFactory.java:88)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.buildHttpRequest(AbstractGoogleClientRequest.java:422)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:541)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:474)
    at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:591)
    at com.google.cloud.bigquery.spi.v2.HttpBigQueryRpc.create(HttpBigQueryRpc.java:218)
    ... 8 more
Caused by: java.net.socketTimeoutException: connect timed out
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.socksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.socket.connect(Socket.java:607)
    at sun.security.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:284)
    at sun.net.NetworkClient.doConnect(NetworkClient.java:175)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:463)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:558)
    at sun.net.www.protocol.https.HttpsClient.<init>(HttpsClient.java:264)
    at sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:367)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(AbstractDelegateHttpsURLConnection.java:191)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1162)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1056)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:177)
    at sun.net.www.protocol.http.HttpURLConnection.getoutputStream0(HttpURLConnection.java:1340)
    at sun.net.www.protocol.http.HttpURLConnection.getoutputStream(HttpURLConnection.java:1315)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getoutputStream(HttpsURLConnectionImpl.java:264)
    at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:113)
    at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:84)
    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1012)
    at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccesstoken(ServiceAccountCredentials.java:441)
    ... 19 more

以下是示例代码

public class BQ_test {
    private static final Logger logger = LoggerFactory.getLogger(BQ_test.class);


    public static void main(String[] args) {

        Job queryJob = null;
        String actualValue = "";

        NetHttpTransport transport = new NetHttpTransport();
        JsonFactory jsonFactory = new JacksonFactory();
        String query = "SELECT * FROM `iconic-parsec-315409.bookmark_BQ.sbm_item_tbl``";

        String projectId = "iconic-parsec-315409";
        File credentialsPath = new File("/tmp/iconic-parsec-315409-823ef1c38a9d.json");
        GoogleCredentials credentials;
        try {
            FileInputStream serviceAccountStream = new FileInputStream(credentialsPath);
            credentials = ServiceAccountCredentials.fromStream(serviceAccountStream);
            if (credentials.createScopedrequired()) {
                Collection<String> bigqueryScopes = BigqueryScopes.all();
                credentials = credentials.createScoped(bigqueryScopes);
            }

            BigQuery bigquery = BigQueryOptions
                    .newBuilder()
                    .setCredentials(credentials)
                    .setProjectId(projectId)
                    .build()
                    .getService();
            QueryJobConfiguration queryConfig =
                    QueryJobConfiguration.newBuilder(query)
                            .setUseLegacysql(false)
                            .setJobTimeoutMs(180000L)
                            .build();
            // Create a job ID so that we can safely retry.
            JobId jobId = JobId.of(UUID.randomUUID().toString());
            queryJob = bigquery.create(JobInfo.newBuilder(queryConfig).setJobId(jobId).build());
            // Wait for the query to complete.
            queryJob = queryJob.waitFor();
        } catch (IOException | InterruptedException e) {
            e.printstacktrace();
        }

        // Check for errors
        if (queryJob == null) {
            throw new RuntimeException("Job no longer exists");
        } else if (queryJob.getStatus().getError() != null) {
            // You can also look at queryJob.getStatus().getExecutionErrors() for all
            // errors,not just the latest one.
            throw new RuntimeException(queryJob.getStatus().getError().toString());
        }
        // Get the results.
        TableResult result = null;
        try {
            result = queryJob.getQueryResults();
            // Print all pages of the results.
           // writeFvLToOrcFile(result,"/Users/susanta.a.adhikary/Downloads/test.orc");
            for (FieldValueList row : result.iterateall()) {
                // String type
                actualValue = row.get("sbm_item_id").getStringValue();
                System.out.println(actualValue);
            }
        } catch (InterruptedException e) {
            e.printstacktrace();
        }

    }
}

我从远程 k8s pod 尝试 curl -I "https://oauth2.googleapis.com/token" 并获取

HTTP/2 404 内容类型:文本/html 日期:格林威治标准时间 2021 年 7 月 4 日星期日 05:54:09 服务器:HTTPServer2 上的脚手架

所以我不认为这是 EGRESS 问题。

GCP 的数据位置是 US-east-1,Pod 本地时区是 UTC,我不确定它是否是 NTP 同步问题。需要建议。相同的代码在我的本地使用相同的 serviceaccount 密钥运行良好。 (顺便提一下,我已经做了一个 kubectl cp 将 serviceaccount.json 移动到 pod 以便稍后测试我会创建一个 configmap 什么的)

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)