Я не могу загрузить образы реестра артефактов во вновь созданный кластер 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
}
Может быть, дело в ролях в SA? cloud.google.com/artifact-registry/docs/access-control Вам может понадобиться (roles/artifactregistry.reader)
? Можете ли вы поделиться ролями, привязанными к сервисному аккаунту?
@ Джорджия, я думаю, это было все. См. Обновление, которое я разместил в исходном сообщении. Дайте мне знать, что вы думаете.
@ManideepKarthik По умолчанию используется учетная запись службы узлов, которая будет либо default
, либо любой другой пользовательской учетной записью службы, которую вы укажете.
@Дэвид круто! Приятно слышать, что это решено для вас! Поначалу разрешения могут быть сложными, но добавляя их по мере необходимости, вы будете уверены, что даете минимально необходимые разрешения.
Как говорит ошибка: неожиданный статус: 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, это очень плохая практика!!!! Вместо этого используйте идентификатор рабочей нагрузки.
Спасибо, Гийом, что указал на это. я использовал workload identity
для аутентификации API Gcloud, никогда не проверял ImagePullSecret
для получения изображений из внешнего репо. это будет хорошо работать для GCR/Artifact
GCP определенно в приведенном выше сценарии.
обновил ответ, еще раз спасибо, Гийом, за исправление.
Превращение комментария в ответ, поскольку он решил проблему @David.
Поскольку определяемая пользователем учетная запись службы используется для node_pool, соответствующие роли должны быть привязаны к этой учетной записи службы.
В этом случае: roles/artifactregistry.reader
Настройка разрешений реестра артефактов
Лучшей практикой является предоставление минимально необходимых ролей.
Учетная запись службы не используется автоматически для извлечения образов из реестра. Вы должны создать секрет и указать его в развертывании. См. kubernetes.io/docs/tasks/configure-pod-container/…