无法使用 Java SDK 在 Google Cloud 运行 上使用 API 创建服务
Failing to create services on Google Cloud Run with API using Java SDK
我创建了一个 Cloud 运行 客户端,但是无法找到一种方法来列出在 GKE(对于 Anthos)上使用 Cloud 运行 部署的服务。
- 创建客户端:
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleCredentials credential = GoogleCredentials.getApplicationDefault();
credential.createScoped("https://www.googleapis.com/auth/cloud-platform");
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credential);
CloudRun.Builder builder = new CloudRun.Builder(httpTransport, jsonFactory, requestInitializer);
return builder.setApplicationName(applicationName)
.setRootUrl(cloudRunRootUrl)
.build();
} catch (IOException e) {
e.printStackTrace();
}
- 尝试列出服务:
services = cloudRun.namespaces().services()
.list("namespaces/default")
.execute()
.getItems();
我的 "hello" 服务部署在默认命名空间下的 GKE 集群上。上面的代码不起作用,因为客户端总是将 "default" 视为 project_id 并抱怨权限问题。如果我输入 project_id 而不是 "default",权限错误就消失了,但是找不到任何服务。
我尝试了另一个确实具有 Google 完全托管云 运行 服务的项目,相同的代码 returns 结果(使用 .list("namespaces/"))。
如何访问GKE上的服务?
我的下一个问题是,如何以编程方式在 GKE 上创建云 运行 服务?
编辑 - 用于创建服务
由于我不知道如何与 GKE 上的 Cloud 运行 交互,我退后一步尝试完全托管的。以下创建服务的代码失败,错误消息没有提供太多有用的见解,如何让它工作?
Service deployedService = null;
// Map<String,String> annotations = new HashMap<>();
// annotations.put("client.knative.dev/user-image","gcr.io/cloudrun/hello");
ServiceSpec spec = new ServiceSpec();
List<Container> containers = new ArrayList<>();
containers.add(new Container().setImage("gcr.io/cloudrun/hello"));
spec.setTemplate(new RevisionTemplate().setMetadata(new ObjectMeta().setName("hello-fully-managed-v0.1.0"))
.setSpec(new RevisionSpec().setContainerConcurrency(20)
.setContainers(containers)
.setTimeoutSeconds(100)
)
);
helloService.setApiVersion("serving.knative.dev/v1")
.setMetadata(new ObjectMeta().setName("hello-fully-managed")
.setNamespace("data-infrastructure-test-env")
// .setAnnotations(annotations)
)
.setSpec(spec)
.setKind("Service");
try {
deployedService = cloudRun.namespaces().services()
.create("namespaces/data-infrastructure-test-env",helloService)
.execute();
} catch (IOException e) {
e.printStackTrace();
response.add(e.toString());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
我收到的错误消息:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "The request has errors",
"reason" : "badRequest"
} ],
"message" : "The request has errors",
"status" : "INVALID_ARGUMENT"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:150)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
而 base_url 是:https://europe-west1-run.googleapis.com
你的问题很详细(而且是关于 Java 的,我不是专家)而且里面的问题实际上太多了(最好在这里只问 1 个问题)。但是,我会尝试回答您提出的一些问题:
首先,Cloud 运行(托管和在 GKE 上)都实现了 Knative Serving API。我已经在 https://ahmet.im/blog/cloud-run-is-a-knative/ 上对此进行了解释。事实上,GKE 上的 Cloud 运行 只是安装到您的集群的开源 Knative 组件。
And my next question would be, how to programmatically create Cloud Run services on GKE?
使用云 运行 API 客户端库(例如 new CloudRun
,您将 非常困难(如果可能的话)上面),因为这些是为 *.googleapis.com
个端点设计的。
"Cloud Run on GKE" 的 Knative API 部分实际上只是您的 Kubernetes (GKE) 主节点 API 端点(它运行在一个 IP 地址上,具有非 TLS 证书受根 CA 信任,但您可以在 GKE GetCluster API 调用中找到 CA 证书以验证证书。)TLS 是为什么很难使用 API 客户端库的部分原因。
Knative APIs 只是 Kubernetes 对象。所以你最好的选择是以下之一:
- 参见 Kubernetes java 客户端 (https://github.com/kubernetes-client/java) 实际上允许动态对象。 (Go 实现)并尝试使用它来创建 Knative CRD。
- 使用
kubectl apply
.
- 向 Knative Serving 开源存储库寻求帮助(他们应该提供客户端库,也许他们已经在那里我不确定)
要使用 API 客户端库对 Cloud 运行(托管) 进行编程,您需要显式覆盖 API 端点到地区,例如us-central1-run.googleapis.com
。 (这记录在每个 API 调用的 REST API 参考文档中。)
我写了一篇博客 post 详细介绍了如何 create/update 使用 Knative Serving [=75] 在云端 运行 (管理)服务 [=75] =] 这里:https://ahmet.im/blog/gcloud-run-deploy/
如果您想查看 gcloud run deploy
是如何工作的,以及它调用了哪些 API,您可以通过 --log-http
选项来观察 request/response 流量。
至于你得到的错误,似乎错误消息没有帮助,但它可能来自任何地方(因为你试图在 GCP 客户端库中模仿 Knative API)。我建议深入阅读我的博客 posts 和示例代码。
更新: 我们的工程团队正在研究这个问题,目前似乎存在一个没有将 "details" 字段添加到错误中的错误。正在处理中。
对于您的情况,我们从请求中看到以下错误:
field: "spec.template.spec"
description: "Missing template spec."
表示您没有正确填写我在博客 post 和示例代码中显示的规范字段。
field: "metadata.name"
description: "The revision name must be prefixed by the name of the enclosing Service or Configuration with a trailing -"
确保您指定的名称符合 API 文档中指定的模式。尝试在 UI 或 gcloud CLI 中手动创建该名称。
field: "api_version"
description: "Unsupported API version \'serving.knative.dev/v1\'. Expected \'serving.knative.dev/v1alpha1\'"
不要使用v1alpha1 API,直接使用v1。
我们将尝试获取错误消息的详细信息,但您似乎需要更详细地研究我在博客 post 中链接的示例代码:
https://github.com/GoogleCloudPlatform/cloud-run-button/blob/a52c7fbaae33a3e06c112206c7227a0ef9649647/cmd/cloudshell_open/deploy.go#L26-L112
Java SDK 是根据云 运行(完全托管)API 是 public 的事实自动生成的。它不支持 Cloud 运行 for Anthos。
(gcloud.run.deploy) 修订名称必须以封闭服务或配置的名称为前缀,并带有尾随 -revision name
修订名称名称应为 65 个字符,然后问题将在自动化管道中解决,GCP 修订后缀应较少修订名称是(服务名称 + 修订后缀)的组合将由 GCP 自动创建。
我创建了一个 Cloud 运行 客户端,但是无法找到一种方法来列出在 GKE(对于 Anthos)上使用 Cloud 运行 部署的服务。
- 创建客户端:
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleCredentials credential = GoogleCredentials.getApplicationDefault();
credential.createScoped("https://www.googleapis.com/auth/cloud-platform");
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credential);
CloudRun.Builder builder = new CloudRun.Builder(httpTransport, jsonFactory, requestInitializer);
return builder.setApplicationName(applicationName)
.setRootUrl(cloudRunRootUrl)
.build();
} catch (IOException e) {
e.printStackTrace();
}
- 尝试列出服务:
services = cloudRun.namespaces().services()
.list("namespaces/default")
.execute()
.getItems();
我的 "hello" 服务部署在默认命名空间下的 GKE 集群上。上面的代码不起作用,因为客户端总是将 "default" 视为 project_id 并抱怨权限问题。如果我输入 project_id 而不是 "default",权限错误就消失了,但是找不到任何服务。
我尝试了另一个确实具有 Google 完全托管云 运行 服务的项目,相同的代码 returns 结果(使用 .list("namespaces/"))。
如何访问GKE上的服务?
我的下一个问题是,如何以编程方式在 GKE 上创建云 运行 服务?
编辑 - 用于创建服务 由于我不知道如何与 GKE 上的 Cloud 运行 交互,我退后一步尝试完全托管的。以下创建服务的代码失败,错误消息没有提供太多有用的见解,如何让它工作?
Service deployedService = null;
// Map<String,String> annotations = new HashMap<>();
// annotations.put("client.knative.dev/user-image","gcr.io/cloudrun/hello");
ServiceSpec spec = new ServiceSpec();
List<Container> containers = new ArrayList<>();
containers.add(new Container().setImage("gcr.io/cloudrun/hello"));
spec.setTemplate(new RevisionTemplate().setMetadata(new ObjectMeta().setName("hello-fully-managed-v0.1.0"))
.setSpec(new RevisionSpec().setContainerConcurrency(20)
.setContainers(containers)
.setTimeoutSeconds(100)
)
);
helloService.setApiVersion("serving.knative.dev/v1")
.setMetadata(new ObjectMeta().setName("hello-fully-managed")
.setNamespace("data-infrastructure-test-env")
// .setAnnotations(annotations)
)
.setSpec(spec)
.setKind("Service");
try {
deployedService = cloudRun.namespaces().services()
.create("namespaces/data-infrastructure-test-env",helloService)
.execute();
} catch (IOException e) {
e.printStackTrace();
response.add(e.toString());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
我收到的错误消息:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "The request has errors",
"reason" : "badRequest"
} ],
"message" : "The request has errors",
"status" : "INVALID_ARGUMENT"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:150)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
而 base_url 是:https://europe-west1-run.googleapis.com
你的问题很详细(而且是关于 Java 的,我不是专家)而且里面的问题实际上太多了(最好在这里只问 1 个问题)。但是,我会尝试回答您提出的一些问题:
首先,Cloud 运行(托管和在 GKE 上)都实现了 Knative Serving API。我已经在 https://ahmet.im/blog/cloud-run-is-a-knative/ 上对此进行了解释。事实上,GKE 上的 Cloud 运行 只是安装到您的集群的开源 Knative 组件。
And my next question would be, how to programmatically create Cloud Run services on GKE?
使用云 运行 API 客户端库(例如 new CloudRun
,您将 非常困难(如果可能的话)上面),因为这些是为 *.googleapis.com
个端点设计的。
"Cloud Run on GKE" 的 Knative API 部分实际上只是您的 Kubernetes (GKE) 主节点 API 端点(它运行在一个 IP 地址上,具有非 TLS 证书受根 CA 信任,但您可以在 GKE GetCluster API 调用中找到 CA 证书以验证证书。)TLS 是为什么很难使用 API 客户端库的部分原因。
Knative APIs 只是 Kubernetes 对象。所以你最好的选择是以下之一:
- 参见 Kubernetes java 客户端 (https://github.com/kubernetes-client/java) 实际上允许动态对象。 (Go 实现)并尝试使用它来创建 Knative CRD。
- 使用
kubectl apply
. - 向 Knative Serving 开源存储库寻求帮助(他们应该提供客户端库,也许他们已经在那里我不确定)
要使用 API 客户端库对 Cloud 运行(托管) 进行编程,您需要显式覆盖 API 端点到地区,例如us-central1-run.googleapis.com
。 (这记录在每个 API 调用的 REST API 参考文档中。)
我写了一篇博客 post 详细介绍了如何 create/update 使用 Knative Serving [=75] 在云端 运行 (管理)服务 [=75] =] 这里:https://ahmet.im/blog/gcloud-run-deploy/
如果您想查看 gcloud run deploy
是如何工作的,以及它调用了哪些 API,您可以通过 --log-http
选项来观察 request/response 流量。
至于你得到的错误,似乎错误消息没有帮助,但它可能来自任何地方(因为你试图在 GCP 客户端库中模仿 Knative API)。我建议深入阅读我的博客 posts 和示例代码。
更新: 我们的工程团队正在研究这个问题,目前似乎存在一个没有将 "details" 字段添加到错误中的错误。正在处理中。
对于您的情况,我们从请求中看到以下错误:
field: "spec.template.spec"
description: "Missing template spec."
表示您没有正确填写我在博客 post 和示例代码中显示的规范字段。
field: "metadata.name"
description: "The revision name must be prefixed by the name of the enclosing Service or Configuration with a trailing -"
确保您指定的名称符合 API 文档中指定的模式。尝试在 UI 或 gcloud CLI 中手动创建该名称。
field: "api_version"
description: "Unsupported API version \'serving.knative.dev/v1\'. Expected \'serving.knative.dev/v1alpha1\'"
不要使用v1alpha1 API,直接使用v1。
我们将尝试获取错误消息的详细信息,但您似乎需要更详细地研究我在博客 post 中链接的示例代码: https://github.com/GoogleCloudPlatform/cloud-run-button/blob/a52c7fbaae33a3e06c112206c7227a0ef9649647/cmd/cloudshell_open/deploy.go#L26-L112
Java SDK 是根据云 运行(完全托管)API 是 public 的事实自动生成的。它不支持 Cloud 运行 for Anthos。
(gcloud.run.deploy) 修订名称必须以封闭服务或配置的名称为前缀,并带有尾随 -revision name
修订名称名称应为 65 个字符,然后问题将在自动化管道中解决,GCP 修订后缀应较少修订名称是(服务名称 + 修订后缀)的组合将由 GCP 自动创建。