Гибридное облако без ключей: Workload Identity Federation

Иллюзия гибридной облачной платформы: почему ваш on-prem и облако до сих пор живут порознь

Как мы наконец научили нагрузки нашего датацентра общаться с Google Cloud — без единого ключа сервисного аккаунта.

Примечание
Артефакты Kubernetes и Terraform доступны в репозитории GitHub — ссылка приведена в конце статьи.

Последние несколько месяцев я занимался тем, что должно было быть давно решённой задачей: дать приложениям, работающим в наших on-premises-кластерах Kubernetes, доступ к сервисам Google Cloud. Вместо готового решения я обнаружил повсеместную культуру обходных путей, построенных на антипаттернах безопасности — и на удивление элегантное решение, лежавшее на виду.

Если всё сделано правильно, гибридное облако выглядит примерно так:

Схема идеальной гибридной облачной архитектуры

Зачем нужен гибридный облачный подход

Причин внедрить гибридное облако в организации немало. Вот лишь некоторые из них:

  • Передача «тяжёлых» вычислений в BigQuery. Аналитические приложения остаются on-prem по соображениям суверенитета данных, а массивные датасеты передаются в BigQuery. Это даёт вычислительную мощь мирового уровня без необходимости покупать и обслуживать хотя бы один дополнительный сервер в собственной стойке.

  • Единая сеть с Cloud Interconnect. Используя Cloud Interconnect или Cloud VPN, собственный датацентр буквально становится расширением VPC в GCP. Это позволяет приложениям для выставления счетов обращаться к облачным пользовательским сервисам с низкой задержкой и без выхода в публичный интернет.

  • Экономичное масштабирование через Cloud Storage. Можно навсегда забыть о переполнении дисков on-prem: Cloud Storage в роли бэкенда для локальных приложений позволяет хранить неограниченные объёмы логов, резервных копий и исторических данных, платя только за реально используемый объём.

  • Синхронизация по событиям с Pub/Sub. Когда on-prem происходит какое-либо событие (например, формируется новый счёт), можно отправить сообщение через Cloud Pub/Sub. Облачные сервисы реагируют мгновенно, поддерживая синхронизацию двух платформ без громоздкого ручного опроса.

Экономика гибридного подхода: GPU изменили всё

Прежде чем переходить к технической стороне вопроса, стоит поговорить о том, почему гибридные облака важны сейчас как никогда.

Ваша компания, как и большинство крупных предприятий, сделала серьёзные инвестиции в собственные датацентры. Серверы куплены. Стойки заполнены. Сетевая инфраструктура оплачена. Предельные затраты на запуск ещё одной нагрузки практически равны нулю — капитал уже вложен.

Потом накрыла волна AI.

Внезапно каждой команде нужны GPU. Не один-два — десятки A100 для обучения, целые парки inference-эндпоинтов, векторные базы данных, которые должны располагаться рядом с моделями. И здесь возникает проблема: GPU в дефиците. Время ожидания on-prem-оборудования с GPU измеряется месяцами. Облачные провайдеры, в свою очередь, предоставляют его за минуты.

Поэтому архитектура, которая действительно имеет экономический смысл, выглядит вот так:

Схема гибридной архитектуры с распределением нагрузки между датацентром и облаком

On-prem-датацентр берёт на себя основную вычислительную нагрузку — веб-серверы, бизнес-логику, базы данных, пакетную обработку. Это стандартные вычисления. Мы за них уже заплатили.

Облако занимается дефицитными ресурсами — GPU-ускоренным инференсом, обучением моделей, AI/ML-эндпоинтами. Мы платим за каждый запрос, масштабируемся по требованию и не ждём полгода железа.

Именно такая гибридная платформа имеет финансовый смысл. Облако — не конечная цель миграции, а расширение для возможностей, которые сложно реализовать on-prem.

Конечно, дело не ограничивается GPU. Настоящая гибридная облачная платформа — это когда приложения просто могут общаться друг с другом: надёжно и безопасно. Возможно, вы используете BigQuery и хотите потреблять его данные.

Но вот в чём загвоздка: on-prem-нагрузки должны аутентифицироваться в облачных сервисах. Каждый вызов API из датацентра к эндпоинту Vertex AI, каждый запрос к GPU-сервису инференса, каждая запись артефактов модели в Cloud Storage — всё это требует учётных данных.

И именно здесь мы возвращаемся к ключевой проблеме.

Ключевая проблема (и это каламбур)

Сценарий, разворачивающийся в тысячах предприятий ежедневно:

Команда разработчиков хочет, чтобы их on-prem-приложение писало в Google Cloud Storage. «Очевидное» решение? Сгенерировать ключ сервисного аккаунта GCP, закодировать его в base64, запихнуть в Kubernetes Secret и смонтировать в поде.

apiVersion: v1
kind: Secret
metadata:
  name: gcp-credentials
type: Opaque
data:
  key.json: eyJ0eXBlIjoic2VydmljZV9hY2NvdW50IiwicHJvamVjdF9pZCI6…

Это «работает». Но при этом:

  • Ключ никогда не истекает — он действителен до тех пор, пока кто-нибудь не вспомнит о его ротации (не вспомнит) или пока он не окажется скомпрометирован (а это случится).

  • Его легко похитить — любой, у кого есть доступ на чтение в этот неймспейс, может выполнить kubectl get secret -o yaml и уйти с постоянным доступом к GCP.

  • Отсутствует привязка к конкретной нагрузке в аудите — GCP видит «service-account-xyz обратился к этому бакету», а не «под frontend-abc-123 в неймспейсе production».

  • Это кошмар в масштабе — 50 команд × 3 окружения × 4 проекта GCP = 600 ключей, которые нужно отслеживать, ротировать и молиться, что ни один из них не попал в git.

Службы безопасности прекрасно это понимают. Поэтому многие организации сделали единственно разумное: полностью запретили генерацию ключей сервисных аккаунтов.

Случайный воздушный зазор

Вот где становится интересно. Запретив генерацию ключей, вы не решили проблему гибридной облачной платформы — вы просто переложили её на чужие плечи. Как правило, эти плечи принадлежат платформенной команде, уставившейся в задачу Jira с текстом «нет доступа к GCP из on-prem, P1, блокирует релиз».

В результате ваша «гибридная облачная платформа» вовсе не является гибридной. Это две разрозненные системы:

Диаграмма двух изолированных систем: on-prem и облако без связи

Команды начинают городить промежуточные сервисы, API-шлюзы для проксирования запросов или — будем честными — изобретательно доставать ключи в обход запрета. Это не платформа. Это скотч и изолента.

Технология существовала всё это время

А что если я скажу вам, что каждый кластер Kubernetes уже выдаёт криптографически подписанные токены идентификации каждому поду? И что в Google Cloud есть сервис, специально созданный для того, чтобы доверять этим токенам?

Это Workload Identity Federation (федерация рабочих удостоверений) — и в связке с OIDC (OpenID Connect) именно она является тем недостающим звеном, которое делает гибридные платформы по-настоящему рабочими.

Как работает идентификация в Kubernetes

Каждый под с ServiceAccount (сервисным аккаунтом) автоматически получает JWT-токен, смонтированный по пути /run/secrets/kubernetes.io/serviceaccount/token. Это не просто непрозрачный набор байт — это криптографически подписанное удостоверение личности:

{
  "iss": "https://kubernetes.default.svc.cluster.local",
  "sub": "system:serviceaccount:production:backend-api",
  "aud": ["https://iam.googleapis.com/..."],
  "kubernetes.io": {
    "namespace": "production",
    "serviceaccount": {
      "name": "backend-api"
    }
  },
"exp": 1735689600
}

Ключевой момент: этот токен может верифицировать любой, у кого есть публичные ключи вашего кластера (JWKS — JSON Web Key Set). Кластер публикует их по стандартному эндпоинту:

kubectl get --raw /openid/v1/jwks

Google Cloud Security Token Service (STS) умеет валидировать эти токены. Никакого обмена ключами. Никаких хранимых секретов. Только криптографическое доказательство идентификации.

Строим мост: Workload Identity Federation

Вот архитектура, которую можно реализовать:

Архитектура Workload Identity Federation между on-prem-кластером и Google Cloud

Сторона GCP: пул идентификации и OIDC-провайдер

Workload Identity Pool (пул рабочих удостоверений) — это граница доверия, декларация вида «я принимаю идентификации из внешних источников». OIDC-провайдер задаёт, как именно валидировать эти идентификации.

resource "google_iam_workload_identity_pool" "pool" {
  workload_identity_pool_id = "hybrid-platform-pool"
  project                   = "my-project"
}

resource "google_iam_workload_identity_pool_provider" "k8s_provider" {
  project                            = "my-project"
  workload_identity_pool_id          = google_iam_workload_identity_pool.pool.workload_identity_pool_id
  workload_identity_pool_provider_id = "on-prem-cluster"

  attribute_mapping = {
    "google.subject"      = "assertion.sub"
    "attribute.namespace" = "assertion['kubernetes.io']['namespace']"
  }

  attribute_condition = "attribute.namespace in [\"production\", \"staging\"]"

  oidc {
    issuer_uri = "https://kubernetes.default.svc.cluster.local"
    jwks_json  = file("jwks.json")  # Публичные ключи вашего кластера
  }
}

Два момента, заслуживающих внимания:

  1. attribute_mapping — извлекает claims (утверждения) из Kubernetes JWT и делает их доступными как атрибуты GCP. Мы вытаскиваем неймспейс, чтобы использовать его для управления доступом.

  2. attribute_condition — именно здесь живёт политика безопасности. Подробнее об этом ниже.

Common Expression Language: тонкое управление доступом

Поле attribute_condition использует CEL (Common Expression Language — язык общих выражений), и он на удивление мощный. Вот эта одна строка политики заменяет то, что потребовало бы десятков IAM-привязок:

attribute.namespace in ["production", "staging"]

С этим условием под в неймспейсе kube-system вообще не сможет аутентифицироваться в GCP — обмен токенов будет отклонён ещё до того, как IAM будет опрошен.

Можно усложнить:

// Только неймспейс production и только конкретные сервисные аккаунты
attribute.namespace == "production" &&
  attribute.service_account in ["payment-processor", "order-service"]

// Разрешить staging, но только в рабочее время (да, серьёзно)
attribute.namespace == "staging" &&
  request.time.getHours("America/New_York") >= 9 &&
  request.time.getHours("America/New_York") < 17

Это глубокая эшелонированная защита (defense in depth). Даже если кто-то создаст мошеннический ServiceAccount, даже если у него есть доступ к kubectl — он не сможет аутентифицироваться в GCP, пока не пройдёт условие CEL. Граница безопасности обеспечивается инфраструктурой Google, а не надеждой на то, что разработчики соблюдают политику.

Сторона Kubernetes: автоматическое внедрение учётных данных

Рабочая федерация идентификации — это лишь половина дела. Разработчики не должны разбираться в OIDC, STS или файлах конфигурации учётных данных. Они должны просто задеплоить приложение — и оно должно работать.

Здесь в игру вступает Kyverno. Единственный ClusterPolicy (кластерная политика) автоматически внедряет всё, что нужно поду:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: workload-identity-federation
spec:
  rules:
    - name: inject-gcp-credentials
      match:
        any:
          - resources:
              kinds:
                - Deployment
              selector:
                matchLabels:
                  workload-identity-federation: "enabled"
      mutate:
        patchStrategicMerge:
          spec:
            template:
              spec:
                volumes:
                  - name: workload-identity-credential-configuration
                    configMap:
                      name: workload-identity-federation-config
                containers:
                  - (name): "*"
                    volumeMounts:
                      - name: workload-identity-credential-configuration
                        mountPath: /etc/workload-identity
                        readOnly: true
                    env:
                      - name: GOOGLE_APPLICATION_CREDENTIALS
                        value: "/etc/workload-identity/credential-configuration.json"

С точки зрения разработчика, вот и всё, что нужно для интеграции:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    workload-identity-federation: "enabled"  # Это всё. Буквально.
spec:
  # ... обычная спецификация деплоя

Файл конфигурации учётных данных (создаваемый Terraform в виде ConfigMap) сообщает клиентским библиотекам Google, как обменивать токены:

{
  "type": "external_account",
  "audience": "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID",
  "subject_token_type": "urn:ietf:params:oauth:token-type:jwt",
  "token_url": "https://sts.googleapis.com/v1/token",
  "credential_source": {
    "file": "/run/secrets/kubernetes.io/serviceaccount/token"
  }
}

Этот формат понимают все SDK и клиентские библиотеки Google Cloud. Python, Go, Java, Node — всё работает без дополнительных настроек.

IAM: выдача реальных прав доступа

Федеративным идентификациям нужны права доступа к ресурсам. Мы привязываем IAM-роли к атрибутам пула идентификации:

resource "google_project_iam_member" "secret_access" {
  for_each = toset(["production", "staging"])
  project  = "my-project"
  role     = "roles/secretmanager.secretAccessor"
  member   = "principalSet://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${POOL_ID}/attribute.namespace/${each.value}"
}

Это даёт доступ к Secret Manager всем подам, аутентифицированным из неймспейсов production или staging. Синтаксис principalSet позволяет делать выборку по атрибутам. Можно также ограничить доступ конкретными сервисными аккаунтами:

member = "principal://iam.googleapis.com/.../subject/system:serviceaccount:production:payment-processor"

Проверяем работу: листинг секретов из on-prem

Убедимся в работоспособности с помощью простого Python-скрипта, который выводит список секретов из Secret Manager. Скрипт выполняется внутри пода в вашем on-premises-кластере:

# list_secrets.py - выполняется on-prem, обращается к GCP Secret Manager
from google.cloud import secretmanager

def list_secrets(project_id: str):
    """
    Вывести список всех секретов в проекте GCP.

    Учётные данные явно не передаются. Библиотека google-cloud-secret-manager
    автоматически:
    1. Читает переменную GOOGLE_APPLICATION_CREDENTIALS (установленную Kyverno)
    2. Загружает JSON-конфигурацию учётных данных
    3. Читает токен K8s ServiceAccount из /run/secrets/...
    4. Обменивает его на токен доступа GCP через STS
    5. Использует этот токен для вызова API Secret Manager
    """
    client = secretmanager.SecretManagerServiceClient()
    parent = f"projects/{project_id}"

    print(f"Secrets in {project_id}:")
    print("-" * 40)

    for secret in client.list_secrets(request={"parent": parent}):
        # Извлекаем только имя секрета из полного пути ресурса
        secret_name = secret.name.split("/")[-1]
        print(f"  - {secret_name}")

    print("-" * 40)
    print("Authentication: Workload Identity Federation")
    print("Credentials: None stored, token exchanged at runtime")

if __name__ == "__main__":
    list_secrets("my-project-id")

Запускаем внутри помеченного пода:

$ kubectl exec -it my-app-xyz -- python list_secrets.py

Secrets in my-project-id:
----------------------------------------
  - database-password
  - api-key-stripe
  - oauth-client-secret
  - ml-model-api-key
----------------------------------------
Authentication: Workload Identity Federation
Credentials: None stored, token exchanged at runtime

Никакого ключа сервисного аккаунта. Никакого смонтированного секрета. Просто токен Kubernetes ServiceAccount, обмениваемый на учётные данные GCP во время выполнения. Тот же подход работает для любого сервиса GCP: Secret Manager, Cloud Storage, BigQuery, Pub/Sub и, конечно, Vertex AI.

Возвращаемся к GPU: гибридная AI-платформа

Вспомним архитектуру из начала статьи — on-prem-приложения вызывают облачные GPU-сервисы. Посмотрим, как это реально работает с Workload Identity Federation.

Рассмотрим типичный сценарий: on-prem-сервис обработки заказов должен вызвать эндпоинт Vertex AI для обнаружения мошенничества. Модель работает на GPU в Google Cloud (потому что там можно получить A100 за минуты, а не месяцы). Логика приложения остаётся on-prem (потому что за эти вычислительные мощности мы уже заплатили).

При правильно настроенных IAM-привязках в Google Cloud любой под из разрешённых неймспейсов сможет вызвать Vertex AI. Вот код приложения:

# fraud_detector.py - выполняется on-prem, вызывает облачные GPU
from google.cloud import aiplatform

def check_fraud(transaction: dict) -> float:
    """
    Вызов эндпоинта Vertex AI для обнаружения мошенничества.

    Модель работает на A100 GPU в Google Cloud.
    Этот код выполняется on-prem в нашем датацентре.

    Аутентификация происходит автоматически:
    1. Kyverno внедрил GOOGLE_APPLICATION_CREDENTIALS
    2. SDK aiplatform читает конфигурацию учётных данных
    3. Токен K8s SA обменивается на токен GCP через STS
    4. Запрос аутентифицируется в Vertex AI
    """
    endpoint = aiplatform.Endpoint(
        endpoint_name="projects/my-project/locations/us-central1/endpoints/fraud-model"
    )
    prediction = endpoint.predict(instances=[transaction])
    return prediction.predictions[0]["fraud_score"]


def generate_embeddings(texts: list[str]) -> list[list[float]]:
    """
    Генерация текстовых эмбеддингов с использованием облачной модели.

    Модели эмбеддингов требовательны к GPU. Запускать их on-prem
    означало бы выделять под них специальное железо. В облаке платим за запрос.
    """
    from vertexai.language_models import TextEmbeddingModel

    model = TextEmbeddingModel.from_pretrained("text-embedding-004")
    embeddings = model.get_embeddings(texts)
    return [e.values for e in embeddings]

Разработчику не нужно думать об аутентификации вообще. Он просто добавляет лейбл к своему деплою:

metadata:
  labels:
    workload-identity-federation: "enabled"

И его on-prem-под может теперь обращаться к:

  • Vertex AI endpoints — для ML-инференса на облачных GPU

  • Cloud Storage — для артефактов моделей и обучающих данных

  • BigQuery — для хранилищ фич и аналитики

  • Pub/Sub — для потоковой передачи событий между окружениями

  • Secret Manager — для API-ключей и конфигурации

Вот так и должна работать гибридная платформа. Датацентр занимается высокообъёмными, экономически оптимизированными вычислениями. Облако предоставляет дефицитные GPU-ресурсы по требованию. А слой аутентификации невидим для разработчиков.

Масштабирование GPU-моста

Условия CEL становятся особенно мощными в этом контексте. Возможно, вы захотите, чтобы только ML-связанные неймспейсы имели доступ к Vertex AI:

attribute.namespace in ["ml-inference", "ml-training", "data-science"] &&
  attribute.service_account.startsWith("ml-")

Или настроить разные уровни доступа:

# Неймспейс ml-inference получает доступ только для предсказаний
resource "google_project_iam_member" "ml_inference" {
  project = "my-project"
  role    = "roles/aiplatform.user"
  member  = "principalSet://iam.googleapis.com/.../attribute.namespace/ml-inference"
}

# Неймспейс data-science получает полный доступ к Vertex AI (для экспериментов)
resource "google_project_iam_member" "data_science" {
  project = "my-project"
  role    = "roles/aiplatform.admin"
  member  = "principalSet://iam.googleapis.com/.../attribute.namespace/data-science"
}

Командам on-prem-разработчиков не нужно знать о GCP IAM и думать о нём. Они деплоят в нужный неймспейс, добавляют лейбл — платформа делает всё остальное.

Почему это важно: свойства безопасности

Сравним два подхода:

Сравнительная таблица безопасности ключей сервисных аккаунтов и Workload Identity Federation

Особого внимания заслуживает короткое время жизни токенов. Даже в худшем сценарии, когда токен каким-то образом был похищен, — он истечёт. Kubernetes ServiceAccount токены имеют настраиваемое время жизни, а токены доступа GCP, выданные STS, действительны один час. Сравните это с ключом сервисного аккаунта, который остаётся действительным до тех пор, пока кто-нибудь не вспомнит о его ротации — нередко годами.

Полная картина: инфраструктура как код

Всё решение кодифицировано в Terraform, управляющем как GCP, так и ресурсами Kubernetes:

workload-identity-federation/
├── providers.tf      # Провайдеры Google + Kubernetes
├── locals.tf         # Конфигурация (неймспейсы, ID проекта и т.д.)
├── gcp.tf            # Пул идентификации, провайдер, IAM-привязки
└── kubernetes.tf     # ConfigMap с конфигурацией учётных данных

Один terraform apply:

  1. Создаёт Workload Identity Pool в GCP

  2. Настраивает OIDC-провайдер с JWKS вашего кластера

  3. Устанавливает IAM-привязки для разрешённых неймспейсов

  4. Создаёт ConfigMap в каждом неймспейсе с конфигурацией учётных данных

В связке с политикой Kyverno получается полностью автоматизированный конвейер:

Новый неймспейс добавлен в список разрешённых
        │
        ▼
Terraform создаёт ConfigMap в этом неймспейсе
        │
        ▼
Разработчик деплоит с лейблом
        │
        ▼
Kyverno автоматически внедряет учётные данные
        │
        ▼
Под аутентифицируется в GCP через OIDC
        │
        ▼
Приложение обращается к сервисам GCP

Никаких тикетов. Никаких запросов ключей. Никаких секретов для управления.

Делаем это реальным: доказательство концепции

Чтобы подтвердить работоспособность, я развернул демонстрацию с использованием vcluster — виртуального кластера Kubernetes, работающего внутри другого кластера Kubernetes. Это доказывает, что решение работает для любого кластера, а не только для GKE:

# vcluster.yaml
experimental:
  docker:
    nodes:
      - name: worker-1
      - name: worker-2
deploy:
  cni:
    flannel:
      enabled: true
controlPlane:
  distro:
    k8s:
      version: "v1.35.0"

Внутри vCluster — простой тестовый деплой:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gcp-test
  labels:
    workload-identity-federation: "enabled"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: gcp-test
  template:
    metadata:
      labels:
        app: gcp-test
    spec:
      containers:
        - name: test
          image: google/cloud-sdk:slim
          command: ["sleep", "infinity"]

Заходим в под и проверяем:

$ kubectl exec -it gcp-test-xxx -- bash

# Внутри пода:
$ gcloud auth login --cred-file=$GOOGLE_APPLICATION_CREDENTIALS
Authenticated with external account credentials for: [principal://iam.googleapis.com/...]

$ gcloud secrets list --project=my-project
NAME                 CREATED
database-password    2024-01-15T10:30:00Z
api-key              2024-01-14T09:15:00Z

Никаких ключей. Никаких смонтированных секретов. Просто федерация идентификации выполняет свою работу.

Сложные моменты (и как мы их решили)

Получение JWKS для изолированных кластеров

Если OIDC-эндпоинт вашего кластера недоступен публично (большинство on-prem-кластеров именно таковы), нужно вручную экспортировать JWKS и загрузить в GCP:

kubectl get --raw /openid/v1/jwks > jwks.json

Этот файл нужно обновлять при ротации ключей подписи кластера. В нашей реализации есть периодическое задание, которое проверяет изменения ключей и обновляет конфигурацию Terraform.

Соответствие URL эмитента

Утверждение iss в Kubernetes-токене должно точно совпадать с URL эмитента, настроенным в OIDC-провайдере. Для кластеров с внутренним DNS:

issuer_uri = "https://kubernetes.default.svc.cluster.local"

Этот URL не обязан быть достижим из GCP — валидационные ключи предоставляет файл JWKS. Но он должен совпадать с тем, что записано в токене.

Диагностика сбоев обмена токенов

При сбоях аутентификации сообщения об ошибках могут быть загадочными. Типичные причины проблем:

Таблица типичных ошибок обмена токенов и способов их устранения

Заключение: гибридное облако, сделанное правильно

После внедрения этого решения наши on-prem-нагрузки аутентифицируются в Google Cloud точно так же, как нагрузки GKE, — без единого долгоживущего учётного данного. Служба безопасности довольна (нет ключей для аудита), разработчики довольны (просто добавь лейбл), платформенная команда довольна (никаких тикетов по управлению учётными данными).

Вот как должна выглядеть гибридная платформа: не две разрозненные системы с хрупким мостом из секретов между ними, а единая плоскость идентификации, охватывающая оба окружения.

Экономическая реальность очевидна: мы не собираемся переносить всё в облако (датацентр у нас уже есть), и мы не можем ждать месяцами on-prem GPU (бизнесу нужны AI-возможности прямо сейчас). Гибридная модель — это не компромисс, а оптимальная архитектура. Используйте облако для того, чего у вас нет. Используйте on-prem для того, за что уже заплачено.

Но эта архитектура работает только тогда, когда два окружения могут безопасно общаться друг с другом. Ключи сервисных аккаунтов были старым ответом — хрупким, небезопасным и всё чаще запрещаемым политиками безопасности. Workload Identity Federation — новый ответ: криптографическая идентификация, краткоживущие учётные данные, тонкое управление доступом и нулевое управление ключами.

Все технологии не новы. OIDC присутствует в Kubernetes с версии 1.20. Workload Identity Federation в GCP существует уже несколько лет. Kyverno и Terraform — зрелые инструменты. Не хватало лишь связать их вместе в комплексное решение, которое разработчики могут внедрить с минимальными усилиями.

Если ваша организация запретила ключи сервисных аккаунтов (или должна это сделать) — это правильный путь вперёд. Если вы строите AI-приложения, которым нужны облачные GPU, или аналитические приложения, работающие on-prem и требующие доступа к данным в бакетах GCS, при этом желая сохранить основные вычислительные мощности on-prem — именно так их и нужно соединять. Ваши on-prem и облачные кластеры наконец могут стать тем, чем всегда должны были быть: расширениями друг друга.

Полная реализация доступна как Terraform-модуль с политиками Kyverno. Репозиторий GitHub: github.com/shkatara/hybrid-platform-gcp-workload-identity-federation

© 2026 meganuke