У меня есть библиотека, размещенная в хранилище Google Cloud. Я использую Jenkins для развертывания своего приложения в GKE.
Я использую библиотеку CloudStorageMaven (V1.0) для отправки проекта в GCS.
Я могу развернуть проект своей библиотеки, но когда я пытаюсь запустить тест для микросервиса на сервере Jenkins, maven не может загрузить мою библиотеку.
Я пытался сделать корзину GCS общедоступной, но это не имело никакого значения.
Дженкинсфайл
#!/usr/bin/env groovy
podTemplate(
label: 'slavepod',
containers: [
containerTemplate (
name: 'maven',
image: 'maven:3.5.2-alpine',
command: 'cat',
ttyEnabled: true,
resourceRequestCpu: '256m',
resourceLimitCpu: '512m',
resourceRequestMemory: '512Mi',
resourceLimitMemory: '1024Mi'
),
containerTemplate (
name: 'docker',
image: 'gcr.io/cloud-builders/docker',
command: 'cat',
ttyEnabled: true,
resourceRequestCpu: '512m',
resourceLimitCpu: '1024m',
resourceRequestMemory: '512Mi',
resourceLimitMemory: '1024Mi'
),
containerTemplate (
name: 'kubectl',
image: 'gcr.io/cloud-builders/kubectl',
command: 'cat',
ttyEnabled: true,
resourceRequestCpu: '512m',
resourceLimitCpu: '1024m',
resourceRequestMemory: '512Mi',
resourceLimitMemory: '1024Mi'
),
containerTemplate (
name: 'gcloud',
image: 'gcr.io/cloud-builders/gcloud',
command: 'cat',
ttyEnabled: true,
resourceRequestCpu: '512m',
resourceLimitCpu: '1024m',
resourceRequestMemory: '512Mi',
resourceLimitMemory: '1024Mi'
)
],
volumes: [
hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),
persistentVolumeClaim(claimName: 'maven-repo', mountPath: '/home/jenkins/.m2')
]
)
{
node('slavepod') {
stage('Clone repository') {
checkout scm
}
stage('Unit Test') {
container('maven') {
echo 'Running Maven tests'
sh("mvn -Dmaven.repo.local=/home/jenkins/.m2/ test")
}
}
} // end of pipeline
У меня есть расширение и репозиторий, настроенные в pom.xml
<build>
....
<extensions>
<extension>
<groupId>com.gkatzioura.maven.cloud</groupId>
<artifactId>google-storage-wagon</artifactId>
<version>1.0</version>
</extension>
</extensions>
</build>
<repositories>
<repository>
<id>ca.performance.common</id>
<url>gs://performance-repository</url>
</repository>
</repositories>
Ошибка, которую я получаю в консоли конвейера Jenkins, выглядит следующим образом:
Downloading from ca.performance.common: gs://url/to/repository/jar-1.0.0.pom
[ERROR] Could not establish connection with google cloud
com.google.cloud.storage.StorageException: Insufficient Permission
at com.google.cloud.storage.spi.v1.HttpStorageRpc.translate (HttpStorageRpc.java:219)
at com.google.cloud.storage.spi.v1.HttpStorageRpc.list (HttpStorageRpc.java:314)
at com.google.cloud.storage.StorageImpl$6.call (StorageImpl.java:272)
at com.google.cloud.storage.StorageImpl$6.call (StorageImpl.java:269)
at com.google.api.gax.retrying.DirectRetryingExecutor.submit (DirectRetryingExecutor.java:89)
at com.google.cloud.RetryHelper.run (RetryHelper.java:74)
at com.google.cloud.RetryHelper.runWithRetries (RetryHelper.java:51)
at com.google.cloud.storage.StorageImpl.listBuckets (StorageImpl.java:268)
at com.google.cloud.storage.StorageImpl.list (StorageImpl.java:257)
at com.gkatzioura.maven.cloud.gcs.GoogleStorageRepository.connect (GoogleStorageRepository.java:55)
at com.gkatzioura.maven.cloud.gcs.GoogleStorageWagon.connect (GoogleStorageWagon.java:135)
at org.eclipse.aether.transport.wagon.WagonTransporter.connectWagon (WagonTransporter.java:342)
at org.eclipse.aether.transport.wagon.WagonTransporter.pollWagon (WagonTransporter.java:382)
at org.eclipse.aether.transport.wagon.WagonTransporter.execute (WagonTransporter.java:431)
at org.eclipse.aether.transport.wagon.WagonTransporter.get (WagonTransporter.java:412)
at org.eclipse.aether.connector.basic.BasicRepositoryConnector$GetTaskRunner.runTask (BasicRepositoryConnector.java:453)
at org.eclipse.aether.connector.basic.BasicRepositoryConnector$TaskRunner.run (BasicRepositoryConnector.java:360)
at org.eclipse.aether.util.concurrency.RunnableErrorForwarder$1.run (RunnableErrorForwarder.java:75)
at org.eclipse.aether.connector.basic.BasicRepositoryConnector$DirectExecutor.execute (BasicRepositoryConnector.java:583)
at org.eclipse.aether.connector.basic.BasicRepositoryConnector.get (BasicRepositoryConnector.java:259)
at org.eclipse.aether.internal.impl.DefaultArtifactResolver.performDownloads (DefaultArtifactResolver.java:498)
at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve (DefaultArtifactResolver.java:399)
at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifacts (DefaultArtifactResolver.java:224)
at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifact (DefaultArtifactResolver.java:201)
at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.loadPom (DefaultArtifactDescriptorReader.java:261)
at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.readArtifactDescriptor (DefaultArtifactDescriptorReader.java:192)
at org.eclipse.aether.internal.impl.DefaultDependencyCollector.resolveCachedArtifactDescriptor (DefaultDependencyCollector.java:539)
at org.eclipse.aether.internal.impl.DefaultDependencyCollector.getArtifactDescriptorResult (DefaultDependencyCollector.java:522)
at org.eclipse.aether.internal.impl.DefaultDependencyCollector.processDependency (DefaultDependencyCollector.java:411)
at org.eclipse.aether.internal.impl.DefaultDependencyCollector.processDependency (DefaultDependencyCollector.java:365)
at org.eclipse.aether.internal.impl.DefaultDependencyCollector.process (DefaultDependencyCollector.java:353)
at org.eclipse.aether.internal.impl.DefaultDependencyCollector.collectDependencies (DefaultDependencyCollector.java:256)
at org.eclipse.aether.internal.impl.DefaultRepositorySystem.collectDependencies (DefaultRepositorySystem.java:282)
at org.apache.maven.project.DefaultProjectDependenciesResolver.resolve (DefaultProjectDependenciesResolver.java:169)
at org.apache.maven.lifecycle.internal.LifecycleDependencyResolver.getDependencies (LifecycleDependencyResolver.java:223)
at org.apache.maven.lifecycle.internal.LifecycleDependencyResolver.resolveProjectDependencies (LifecycleDependencyResolver.java:145)
at org.apache.maven.lifecycle.internal.MojoExecutor.ensureDependenciesAreResolved (MojoExecutor.java:246)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:200)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:154)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:146)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:51)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:309)
at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:194)
at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:107)
at org.apache.maven.cli.MavenCli.execute (MavenCli.java:955)
at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:290)
at org.apache.maven.cli.MavenCli.main (MavenCli.java:194)
at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke (Method.java:498)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:356)
Caused by: com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Insufficient Permission",
"reason" : "insufficientPermissions"
} ],
"message" : "Insufficient Permission"
}
Убедитесь, что вы следуете инструкциям в полное руководство по ссылке CloudStorageMaven, которую вы разместили?
Как указано в официальные документы, вам необходимо предоставить достаточные разрешения определенным пользователям или разрешить общедоступное чтение (allUsers) на уровне корзины, чтобы сделать все объекты в данной корзине доступными для указанных пользователей или allUsers.
Код ошибки из вашей попытки указывает на проблемы с доступом:
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Insufficient Permission",
"reason" : "insufficientPermissions"
} ],
"message" : "Insufficient Permission"
}
Если вы еще не пробовали, вы можете предоставить доступ allUsers на уровне корзины, запустив:
$ gsutil iam ch allUsers:objectViewer gs://[BUCKET_NAME]
Однако, придерживаясь лучших практик, я бы рекомендовал предоставлять детальный доступ на уровне корзины только для учетных записей пользователей или учетных записей служб, которым вы хотите предоставить доступ на чтение/запись к объектам в данной корзине. Вы можете прочитать больше о том, как это сделать здесь.
Если проблема не устранена, проблема «Недостаточно разрешений» связана с кластером GKE. Проверьте, какие права доступа к хранилищу есть у вашего кластера:
В облачной консоли --> щелкните Kubernets Engine.
Нажмите «Имя кластера» ---> Найдите «Хранилище» в разделе «Разрешения».
Если у вас есть только «Только чтение», вам нужно будет воссоздать свой кластер следующим образом:
Спасибо за проверку. Кажется, проблема связана с кластером GKE. Не могли бы вы проверить, какие права доступа к хранилищу есть у вашего кластера? В облачной консоли --> Kubernets Engine --> Нажмите «Имя кластера» ---> Найдите «Хранилище» в разделе «Разрешения». Если у вас есть только «Только чтение», вам нужно будет воссоздать свой кластер следующим образом: 1. Создайте новый кластер, как вы определили ранее. 2. Найдите «Пулы узлов», затем нажмите «Расширенное редактирование». 3. Выберите «чтение и запись». из раскрывающегося списка в теге хранилища 4. Создайте этот кластер для своего проекта Разверните свой проект в новом кластере и повторите попытку.
Ты прав. Я проверил разрешения кластера, а разрешения хранилища были отключены. Я смог заставить его работать. Другой вопрос: «Зачем мне давать разрешение, если моя корзина частная? Работает ли это разрешение так же, как включение API?».
Да, это похоже на включение API, которым вы предоставляете права доступа к облачным службам, таким как GKE, чтобы иметь возможность взаимодействовать с вашей корзиной GCS. Очевидно, вам потребуется точно настроить уровень доступа, который должен быть у каждой части вашего проекта, например, в вашей корзине GCS, которая состоит из низкоуровневых (метаданные объекта) и высокоуровневых (метаданные корзины) ресурсов. Поскольку сегменты GCS имеют уникальный URL-адрес, они доступны через Интернет, поэтому по умолчанию сегменты должны создаваться с наименьшими возможными привилегиями, потому что последнее, что вы хотите, — это открыть ваше хранилище для нежелательного доступа.
Я понимаю. Спасибо за подробный ответ.
Спасибо за ответ. Я предоставил доступ зрителям allUsers на уровне корзины для целей тестирования. Я следовал руководству, которое вы показали. Однако это не работает.