Я создал службу Spring Boot для получения сообщений от Sub. Эта служба развернута в кластере Google Kubernetes, для которого настроена идентификация рабочей нагрузки. Я выполнил все шаги, перечисленные в https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity чтобы создать учетную запись службы Kubernetes и учетную запись службы GCP и связать их.
gcloud beta container clusters create ${CLUSTER_NAME} --release-channel regular --workload-pool=${PROJECT_ID}.svc.id.goog --zone ${ZONE} --num-nodes=3 --enable-autoupgrade
gcloud container clusters get-credentials ${CLUSTER_NAME} --zone ${ZONE}
gcloud iam service-accounts create ${GSA_NAME}
kubectl create namespace ${K8S_NAMESPACE}
kubectl create serviceaccount --namespace ${K8S_NAMESPACE} ${KSA_NAME}
gcloud iam service-accounts add-iam-policy-binding --role roles/iam.workloadIdentityUser --member "serviceAccount:${PROJECT_ID}.svc.id.goog[${K8S_NAMESPACE}/${KSA_NAME}]" ${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
gcloud projects add-iam-policy-binding ${PROJECT_ID} --member="serviceAccount:${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" --role="roles/pubsub.admin"
kubectl annotate serviceaccount --namespace ${K8S_NAMESPACE} ${KSA_NAME} iam.gke.io/gcp-service-account=${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
Я создал тему и подписку, и служба Spring Boot настроена для прослушивания подписки.
У меня следующее исключение.
com.google.api.gax.rpc.PermissionDeniedException: com.google.api.gax.rpc.PermissionDeniedException: io.grpc.StatusRuntimeException: PERMISSION_DENIED: User not authorized to perform this action.
at com.google.api.gax.rpc.ApiExceptionFactory.createException(ApiExceptionFactory.java:55) ~[gax-1.56.0.jar!/:1.56.0]
at com.google.cloud.pubsub.v1.StreamingSubscriberConnection$1.onFailure(StreamingSubscriberConnection.java:249) ~[google-cloud-pubsub-1.105.0.jar!/:1.105.0]
at com.google.api.core.ApiFutures$1.onFailure(ApiFutures.java:68) ~[api-common-1.9.0.jar!/:na]
at com.google.common.util.concurrent.Futures$CallbackListener.run(Futures.java:1050) ~[guava-29.0-android.jar!/:na]
at com.google.common.util.concurrent.DirectExecutor.execute(DirectExecutor.java:30) ~[guava-29.0-android.jar!/:na]
at com.google.common.util.concurrent.AbstractFuture.executeListener(AbstractFuture.java:1176) ~[guava-29.0-android.jar!/:na]
at com.google.common.util.concurrent.AbstractFuture.complete(AbstractFuture.java:969) ~[guava-29.0-android.jar!/:na]
at com.google.common.util.concurrent.AbstractFuture.setException(AbstractFuture.java:760) ~[guava-29.0-android.jar!/:na]
at com.google.api.core.AbstractApiFuture$InternalSettableFuture.setException(AbstractApiFuture.java:95) ~[api-common-1.9.0.jar!/:na]
at com.google.api.core.AbstractApiFuture.setException(AbstractApiFuture.java:77) ~[api-common-1.9.0.jar!/:na]
at com.google.api.core.SettableApiFuture.setException(SettableApiFuture.java:52) ~[api-common-1.9.0.jar!/:na]
at com.google.cloud.pubsub.v1.StreamingSubscriberConnection$StreamingPullResponseObserver.onError(StreamingSubscriberConnection.java:184) ~[google-cloud-pubsub-1.105.0.jar!/:1.105.0]
at com.google.api.gax.tracing.TracedResponseObserver.onError(TracedResponseObserver.java:103) ~[gax-1.56.0.jar!/:1.56.0]
at com.google.api.gax.grpc.ExceptionResponseObserver.onErrorImpl(ExceptionResponseObserver.java:84) ~[gax-grpc-1.56.0.jar!/:1.56.0]
at com.google.api.gax.rpc.StateCheckingResponseObserver.onError(StateCheckingResponseObserver.java:86) ~[gax-1.56.0.jar!/:1.56.0]
at com.google.api.gax.grpc.GrpcDirectStreamController$ResponseObserverAdapter.onClose(GrpcDirectStreamController.java:149) ~[gax-grpc-1.56.0.jar!/:1.56.0]
at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:426) ~[grpc-core-1.29.0.jar!/:1.29.0]
at io.grpc.internal.ClientCallImpl.access$500(ClientCallImpl.java:66) ~[grpc-core-1.29.0.jar!/:1.29.0]
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.close(ClientCallImpl.java:689) ~[grpc-core-1.29.0.jar!/:1.29.0]
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.access$900(ClientCallImpl.java:577) ~[grpc-core-1.29.0.jar!/:1.29.0]
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInternal(ClientCallImpl.java:751) ~[grpc-core-1.29.0.jar!/:1.29.0]
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$1StreamClosed.runInContext(ClientCallImpl.java:740) ~[grpc-core-1.29.0.jar!/:1.29.0]
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37) ~[grpc-core-1.29.0.jar!/:1.29.0]
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123) ~[grpc-core-1.29.0.jar!/:1.29.0]
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) ~[na:na]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: com.google.api.gax.rpc.PermissionDeniedException: io.grpc.StatusRuntimeException: PERMISSION_DENIED: User not authorized to perform this action.
at com.google.api.gax.rpc.ApiExceptionFactory.createException(ApiExceptionFactory.java:55) ~[gax-1.56.0.jar!/:1.56.0]
at com.google.api.gax.grpc.GrpcApiExceptionFactory.create(GrpcApiExceptionFactory.java:72) ~[gax-grpc-1.56.0.jar!/:1.56.0]
at com.google.api.gax.grpc.GrpcApiExceptionFactory.create(GrpcApiExceptionFactory.java:60) ~[gax-grpc-1.56.0.jar!/:1.56.0]
at com.google.api.gax.grpc.ExceptionResponseObserver.onErrorImpl(ExceptionResponseObserver.java:82) ~[gax-grpc-1.56.0.jar!/:1.56.0]
... 16 common frames omitted
Caused by: io.grpc.StatusRuntimeException: PERMISSION_DENIED: User not authorized to perform this action.
at io.grpc.Status.asRuntimeException(Status.java:533) ~[grpc-api-1.29.0.jar!/:1.29.0]
... 15 common frames omitted