Невозможно получить частные образы реестра артефактов во вновь созданном кластере GKE

Я не могу загрузить образы реестра артефактов во вновь созданный кластер GKE с Terraform и пользовательской учетной записью службы.

Терраформа, используемая для установки кластера, приведена ниже.

locals {
  service         = "example"
  resource_prefix = format("%s-%s", local.service, var.env)
  location        = format("%s-b", var.gcp_region)
}

resource "google_service_account" "main" {
  account_id   = format("%s-sa", local.resource_prefix)
  display_name = format("%s-sa", local.resource_prefix)
  project      = var.gcp_project
}

resource "google_container_cluster" "main" {
  name                     = local.resource_prefix
  description              = format("Cluster primarily servicing the service %s", local.service)
  location                 = local.location
  remove_default_node_pool = true
  initial_node_count       = 1
}

resource "google_container_node_pool" "main" {
  name       = format("%s-node-pool", local.resource_prefix)
  location   = local.location
  cluster    = google_container_cluster.main.name
  node_count = var.gke_cluster_node_count

  node_config {
    preemptible  = true
    machine_type = var.gke_node_machine_type
    # Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles.
    service_account = google_service_account.main.email
    oauth_scopes = [
      "https://www.googleapis.com/auth/logging.write",
      "https://www.googleapis.com/auth/monitoring",
      "https://www.googleapis.com/auth/cloud-platform",
      "https://www.googleapis.com/auth/devstorage.read_only",
      "https://www.googleapis.com/auth/servicecontrol",
      "https://www.googleapis.com/auth/service.management.readonly",
      "https://www.googleapis.com/auth/trace.append"
    ]
  }

  autoscaling {
    min_node_count = var.gke_cluster_autoscaling_min_node_count
    max_node_count = var.gke_cluster_autoscaling_max_node_count
  }
}

Я запускаю развертывание helm для развертывания приложения и получаю следующую проблему.

default       php-5996c7fbfd-d6xf5                                             0/1     ImagePullBackOff             0          37m
Normal   Pulling    36m (x4 over 37m)      kubelet            Pulling image "europe-docker.pkg.dev/example-999999/eu.gcr.io/example-php-fpm:latest"
  Warning  Failed     36m (x4 over 37m)      kubelet            Failed to pull image "europe-docker.pkg.dev/example-999999/eu.gcr.io/example-php-fpm:latest": rpc error: code = Unknown desc = failed to pull and unpack image "europe-docker.pkg.dev/example-999999/eu.gcr.io/example-php-fpm:latest": failed to resolve reference "europe-docker.pkg.dev/example-999999/eu.gcr.io/example-php-fpm:latest": failed to authorize: failed to fetch oauth token: unexpected status: 403 Forbidden
  Warning  Failed     36m (x4 over 37m)      kubelet            Error: ErrImagePull
  Warning  Failed     35m (x6 over 37m)      kubelet            Error: ImagePullBackOff

Мне кажется, что я что-то упустил из служебной учетной записи. Хотя с помощью облачного ssh я могу сгенерировать токен oauth, но это также не работает с использованием crictl

ОБНОВЛЕНИЕ: проблема решена

Мне удалось решить мою проблему с помощью следующего дополнительного кода terraform.

resource "google_project_iam_member" "artifact_role" {
  role = "roles/artifactregistry.reader"
  member  = "serviceAccount:${google_service_account.main.email}"
  project = var.gcp_project
}

Учетная запись службы не используется автоматически для извлечения образов из реестра. Вы должны создать секрет и указать его в развертывании. См. kubernetes.io/docs/tasks/configure-pod-container/…

Manideep Karthik 07.02.2023 04:34

Может быть, дело в ролях в SA? cloud.google.com/artifact-registry/docs/access-control Вам может понадобиться (roles/artifactregistry.reader) ? Можете ли вы поделиться ролями, привязанными к сервисному аккаунту?

GorginZ 07.02.2023 06:23

@ Джорджия, я думаю, это было все. См. Обновление, которое я разместил в исходном сообщении. Дайте мне знать, что вы думаете.

David 08.02.2023 21:37

@ManideepKarthik По умолчанию используется учетная запись службы узлов, которая будет либо default, либо любой другой пользовательской учетной записью службы, которую вы укажете.

David 08.02.2023 21:38

@Дэвид круто! Приятно слышать, что это решено для вас! Поначалу разрешения могут быть сложными, но добавляя их по мере необходимости, вы будете уверены, что даете минимально необходимые разрешения.

GorginZ 09.02.2023 00:32
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Kubernetes - это портативная, расширяемая платформа с открытым исходным кодом для управления контейнерными рабочими нагрузками и сервисами, которая...
1
5
91
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Как говорит ошибка: неожиданный статус: 403 Запрещено

Возможно, у вас возникла проблема с секретом Deployment imagepull.

Для GKE вы можете использовать сервисный аккаунт JSON.

Ссылочный документ: https://cloud.google.com/container-registry/docs/advanced-authentication#json-key

Terraform создает секрет в GKE, который вы можете использовать для развертывания.

resource "kubernetes_secret" "gcr" {
    type = "kubernetes.io/dockerconfigjson"
    metadata {
        name = "gcr-image-pull"
        namespace = "default"
    }
    data = {
        ".dockerconfigjson" = jsonencode({
            auths = {
                "gcr.io" = {
                    username = "_json_key"
                    password = base64decode(google_service_account_key.myaccount.private_key)
                    email = google_service_account.main.email
                    auth = base64encode("_json_key:${ base64decode(google_service_account_key.myaccount.private_key) }")
                }
            }
        })
    }}

Или используйте kubectl для создания секрета

kubectl create secret docker-registry gcr \
    --docker-server=gcr.io \
    --docker-username=_json_key \
    --docker-password = "$(cat google-service-account-key.json)" \
    --docker-email=<Email address>

Теперь, если у вас есть POD или развертывание, вы можете создать конфигурацию YAML, например

apiVersion: v1
kind: Pod
metadata:
  name: uses-private-registry
spec:
  containers:
  - name: hello-app
    image: <image URI>
  imagePullSecrets:
  - name: secret-that-you-created

Обновлять:

В соответствии с предложением Гийома для GKE/GCP вы можете использовать вариант *идентификатора рабочей нагрузки*, так как наилучшая практика с другим внешним репо может не сработать.

Создайте учетную запись службы IAM в GCP:

gcloud iam service-accounts create gke-workload-indentity \
    --project=<project-id>

Создайте учетную запись службы в кластере K8s:

apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    iam.gke.io/gcp-service-account: [email protected]
  name: gke-sa-workload
  namespace: default

Привязка политики выполняется под командой Gcloud:

gcloud iam service-accounts add-iam-policy-binding gke-workload-indentity@PROJECT_ID.iam.gserviceaccount.com \
    --role roles/iam.workloadIdentityUser \
    --member "serviceAccount:PROJECT_ID.svc.id.goog[default/K8s_SANAME]"

Теперь вы можете создать POD развертывания с изображением в репозитории GCR/astifact, просто обновив ServiceAccount.

spec:
      containers:
      - name: container
        image: IMAGE
        serviceAccountName: gke-sa-workload

Подробнее читайте по адресу: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/

Нет, вы НЕ ДОЛЖНЫ использовать ключ json, это очень плохая практика!!!! Вместо этого используйте идентификатор рабочей нагрузки.

guillaume blaquiere 07.02.2023 11:00

Спасибо, Гийом, что указал на это. я использовал workload identity для аутентификации API Gcloud, никогда не проверял ImagePullSecret для получения изображений из внешнего репо. это будет хорошо работать для GCR/Artifact GCP определенно в приведенном выше сценарии.

Harsh Manvar 07.02.2023 11:17

обновил ответ, еще раз спасибо, Гийом, за исправление.

Harsh Manvar 07.02.2023 11:53
Ответ принят как подходящий

Превращение комментария в ответ, поскольку он решил проблему @David.

Поскольку определяемая пользователем учетная запись службы используется для node_pool, соответствующие роли должны быть привязаны к этой учетной записи службы.

В этом случае: roles/artifactregistry.reader

Настройка разрешений реестра артефактов

Лучшей практикой является предоставление минимально необходимых ролей.

Другие вопросы по теме